chore: sync submodule state (parent ref update)

Made-with: Cursor
This commit is contained in:
defiQUG
2026-03-02 12:14:14 -08:00
parent b6a776e5d7
commit 25c96e210a
316 changed files with 29779 additions and 677 deletions

129
provider/README.md Normal file
View File

@@ -0,0 +1,129 @@
# MetaMask Multi-Chain Provider
Connect **MetaMask** and other Web3 providers to **ChainID 138** (DeFi Oracle Meta Mainnet), **Ethereum Mainnet** (1), and **ALL Mainnet** (651940). Includes chain configs, combined token list, and oracle helpers so tokens and price feeds work across chains.
## Features
- **Multi-chain**: Add and switch between Chain 138, Ethereum Mainnet, and ALL Mainnet in one flow.
- **Token list**: All tokens from all three chains (Chain 138: WETH, WETH10, cUSDT, cUSDC, ETH/USD oracle; Mainnet: WETH, USDT, USDC, DAI, ETH/USD oracle; ALL Mainnet: USDC).
- **Oracles**: Read ETH/USD from Chain 138 oracle and from Chainlink on Mainnet so dApps can display USD values.
## Installation
Use as a local module (no publish required):
```bash
# From your app (e.g. metamask-integration/examples/react-example)
npm install ethers # peer dependency for getEthUsdPrice
```
Import from the provider path:
```javascript
import { addChainsToWallet, switchChain, getEthUsdPrice, getTokensByChain } from '../provider/index.js'
```
Or copy the `provider/` folder into your project and import from `./provider`.
## Quick Start
### 1. Add both chains to MetaMask
```javascript
import { addChainsToWallet } from './provider/index.js'
const ethereum = window.ethereum
if (ethereum) {
const result = await addChainsToWallet(ethereum)
console.log('Added:', result.added, 'Skipped:', result.skipped, 'Errors:', result.errors)
}
```
### 2. Switch chain
```javascript
import { switchChain, ensureChain } from './provider/index.js'
await switchChain(window.ethereum, 138) // DeFi Oracle Meta Mainnet
await switchChain(window.ethereum, 1) // Ethereum Mainnet
// Or ensure current chain (switch if needed, add if missing)
await ensureChain(window.ethereum, 138)
```
### 3. Add a token to the wallet
```javascript
import { addTokenToWallet, getToken, getTokensByChain } from './provider/index.js'
const tokens138 = getTokensByChain(138)
for (const token of tokens138) {
if (token.tags?.includes('oracle')) continue
await addTokenToWallet(window.ethereum, token)
}
// Or a single token by address
const weth = getToken(138, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2')
if (weth) await addTokenToWallet(window.ethereum, weth)
```
### 4. Read oracle price (ETH/USD)
Requires `ethers` v6. Works on both Chain 138 and Mainnet.
```javascript
import { ethers } from 'ethers'
import { getEthUsdPrice } from './provider/index.js'
const provider = new ethers.BrowserProvider(window.ethereum)
const chainId = (await provider.getNetwork()).chainId
const result = await getEthUsdPrice(provider, Number(chainId))
if (result) {
console.log('ETH/USD:', result.price, 'Updated:', result.updatedAt)
}
```
## API
| Export | Description |
|--------|-------------|
| `CHAINS`, `CHAIN_138`, `CHAIN_MAINNET` | Chain params for `wallet_addEthereumChain` |
| `getChainById(chainIdDecimal)`, `getChainByHex(chainIdHex)` | Look up chain config |
| `addChainsToWallet(ethereum, options?)` | Add Chain 138 and/or Mainnet |
| `switchChain(ethereum, chainIdDecimal)` | Switch to chain (adds if missing) |
| `ensureChain(ethereum, chainIdDecimal)` | Switch to chain if not already on it |
| `addTokenToWallet(ethereum, token)` | Add token via `wallet_watchAsset` |
| `TOKEN_LIST`, `getTokensByChain(chainId)`, `getToken(chainId, address)` | Token list for both chains |
| `TOKEN_LIST_URL` | URL/path to host the combined token list JSON |
| `getEthUsdPrice(provider, chainId)` | Read ETH/USD from oracle (needs ethers) |
| `ORACLES_CHAIN_138`, `ORACLES_MAINNET`, `getOracleConfig(chainId)` | Oracle addresses and config |
## Config files
- **Networks**: `docs/04-configuration/metamask/DUAL_CHAIN_NETWORKS.json` — both chain params.
- **Token list**: `docs/04-configuration/metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json` — tokens for Chain 138 and Mainnet.
Host the token list at a public URL and set your apps token list URL to it so MetaMask can fetch the list (or use the inline `TOKEN_LIST` / `getTokensByChain` in your UI).
## Downloads
| Asset | In-repo path | Use |
|-------|--------------|-----|
| **Multi-chain networks** | `docs/04-configuration/metamask/DUAL_CHAIN_NETWORKS.json` | `wallet_addEthereumChain` params for Chain 138, Ethereum Mainnet, and ALL Mainnet. If bundled: `config/DUAL_CHAIN_NETWORKS.json`. |
| **Dual-chain token list** | `docs/04-configuration/metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json` | MetaMask token list URL; Uniswap token list format. If bundled: `config/DUAL_CHAIN_TOKEN_LIST.tokenlist.json`. **Hosted:** `https://explorer.d-bis.org/api/config/token-list` (explorer API). `TOKEN_LIST_URL` in code points to this by default. |
| **Feature parity and recommendations** | `docs/04-configuration/metamask/METAMASK_CHAIN138_FEATURE_PARITY_ANALYSIS.md` | Plugin/snap requirements, gaps, and build/integration options. |
| **Oracle and pricing** | `docs/04-configuration/metamask/ORACLE_PRICE_FEED_SETUP.md`, `WETH_ORACLE_QUICK_REFERENCE.md` | Oracle addresses and Oracle Publisher setup. |
| **Token-aggregation REST API** | `smom-dbis-138/services/token-aggregation/docs/REST_API_REFERENCE.md` | Tokens, pools, prices, volume, OHLCV for Chain 138 and ALL Mainnet (discovery without CMC/CoinGecko). |
| **Optional next steps** | `docs/04-configuration/metamask/METAMASK_CHAIN138_FEATURE_PARITY_ANALYSIS.md` §7, `SNAP_IMPLEMENTATION_ROADMAP.md` | Custom Snap roadmap, CoinGecko submission, Consensys outreach. |
## Oracles
- **Chain 138**: ETH/USD at `0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6` (8 decimals). Keep the Oracle Publisher service running so the feed stays updated.
- **Ethereum Mainnet**: Chainlink ETH/USD at `0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419`.
MetaMask does not read these oracles by default; use `getEthUsdPrice(provider, chainId)` in your dApp to show USD values.
## License
MIT

176
provider/chains.js Normal file
View File

@@ -0,0 +1,176 @@
/**
* Multi-chain network params for MetaMask and Web3 providers.
* 13 chains: 138, 1, 651940, 25, 56, 100, 137, 10, 42161, 8453, 43114, 42220, 1111.
* Use with wallet_addEthereumChain and wallet_switchEthereumChain.
*
* @typedef {Object} ChainParams
* @property {string} chainId
* @property {number} chainIdDecimal
* @property {string} chainName
* @property {{ name: string, symbol: string, decimals: number }} nativeCurrency
* @property {string[]} rpcUrls
* @property {string[]} blockExplorerUrls
* @property {string[]} [iconUrls]
*/
/** @type {ChainParams[]} */
export const CHAINS = [
{
chainId: '0x8a',
chainIdDecimal: 138,
chainName: 'DeFi Oracle Meta Mainnet',
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
rpcUrls: [
'https://rpc-http-pub.d-bis.org',
'https://rpc.d-bis.org',
'https://rpc2.d-bis.org',
'https://rpc.defi-oracle.io',
],
blockExplorerUrls: ['https://explorer.d-bis.org'],
iconUrls: [
'https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png',
],
},
{
chainId: '0x1',
chainIdDecimal: 1,
chainName: 'Ethereum Mainnet',
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
rpcUrls: [
'https://eth.llamarpc.com',
'https://rpc.ankr.com/eth',
'https://ethereum.publicnode.com',
'https://1rpc.io/eth',
],
blockExplorerUrls: ['https://etherscan.io'],
iconUrls: [
'https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png',
],
},
{
chainId: '0x9f2c4',
chainIdDecimal: 651940,
chainName: 'ALL Mainnet',
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
rpcUrls: ['https://mainnet-rpc.alltra.global'],
blockExplorerUrls: ['https://alltra.global'],
iconUrls: [
'https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png',
],
},
{
chainId: '0x19',
chainIdDecimal: 25,
chainName: 'Cronos Mainnet',
nativeCurrency: { name: 'CRO', symbol: 'CRO', decimals: 18 },
rpcUrls: ['https://evm.cronos.org', 'https://cronos-rpc.publicnode.com'],
blockExplorerUrls: ['https://cronos.org/explorer'],
iconUrls: ['https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png'],
},
{
chainId: '0x38',
chainIdDecimal: 56,
chainName: 'BNB Smart Chain',
nativeCurrency: { name: 'BNB', symbol: 'BNB', decimals: 18 },
rpcUrls: ['https://bsc-dataseed.binance.org', 'https://bsc-dataseed1.defibit.io'],
blockExplorerUrls: ['https://bscscan.com'],
iconUrls: ['https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png'],
},
{
chainId: '0x64',
chainIdDecimal: 100,
chainName: 'Gnosis Chain',
nativeCurrency: { name: 'xDAI', symbol: 'xDAI', decimals: 18 },
rpcUrls: ['https://rpc.gnosischain.com', 'https://gnosis-rpc.publicnode.com'],
blockExplorerUrls: ['https://gnosisscan.io'],
iconUrls: ['https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png'],
},
{
chainId: '0x89',
chainIdDecimal: 137,
chainName: 'Polygon',
nativeCurrency: { name: 'MATIC', symbol: 'MATIC', decimals: 18 },
rpcUrls: ['https://polygon-rpc.com', 'https://polygon.llamarpc.com'],
blockExplorerUrls: ['https://polygonscan.com'],
iconUrls: ['https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png'],
},
{
chainId: '0xa',
chainIdDecimal: 10,
chainName: 'Optimism',
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
rpcUrls: ['https://mainnet.optimism.io', 'https://optimism.llamarpc.com'],
blockExplorerUrls: ['https://optimistic.etherscan.io'],
iconUrls: ['https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png'],
},
{
chainId: '0xa4b1',
chainIdDecimal: 42161,
chainName: 'Arbitrum One',
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
rpcUrls: ['https://arb1.arbitrum.io/rpc', 'https://arbitrum.llamarpc.com'],
blockExplorerUrls: ['https://arbiscan.io'],
iconUrls: ['https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png'],
},
{
chainId: '0x2105',
chainIdDecimal: 8453,
chainName: 'Base',
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
rpcUrls: ['https://mainnet.base.org', 'https://base.llamarpc.com'],
blockExplorerUrls: ['https://basescan.org'],
iconUrls: ['https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png'],
},
{
chainId: '0xa86a',
chainIdDecimal: 43114,
chainName: 'Avalanche C-Chain',
nativeCurrency: { name: 'AVAX', symbol: 'AVAX', decimals: 18 },
rpcUrls: ['https://api.avax.network/ext/bc/C/rpc'],
blockExplorerUrls: ['https://snowtrace.io'],
iconUrls: ['https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png'],
},
{
chainId: '0xa4ec',
chainIdDecimal: 42220,
chainName: 'Celo',
nativeCurrency: { name: 'CELO', symbol: 'CELO', decimals: 18 },
rpcUrls: ['https://forno.celo.org'],
blockExplorerUrls: ['https://celoscan.io'],
iconUrls: ['https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png'],
},
{
chainId: '0x457',
chainIdDecimal: 1111,
chainName: 'Wemix',
nativeCurrency: { name: 'WEMIX', symbol: 'WEMIX', decimals: 18 },
rpcUrls: ['https://api.wemix.com'],
blockExplorerUrls: ['https://scan.wemix.com'],
iconUrls: ['https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png'],
},
]
/** Chain 138 only (for wallet_addEthereumChain single chain) */
export const CHAIN_138 = CHAINS[0]
/** Ethereum Mainnet only */
export const CHAIN_MAINNET = CHAINS[1]
/** ALL Mainnet only (651940) */
export const CHAIN_ALL_MAINNET = CHAINS[2]
/**
* @param {number} chainIdDecimal - 138, 1, 651940, 25, 56, 100, 137, 10, 42161, 8453, 43114, 42220, 1111
* @returns {ChainParams | undefined}
*/
export function getChainById(chainIdDecimal) {
return CHAINS.find((c) => c.chainIdDecimal === chainIdDecimal)
}
/**
* @param {string} chainIdHex - e.g. '0x8a', '0x1', '0x9f2c4', '0x19', etc.
* @returns {ChainParams | undefined}
*/
export function getChainByHex(chainIdHex) {
return CHAINS.find((c) => c.chainId === chainIdHex)
}

View File

@@ -0,0 +1,19 @@
{
"name": "MetaMask Multi-Chain Networks (13 chains)",
"version": {"major": 1, "minor": 2, "patch": 0},
"chains": [
{"chainId":"0x8a","chainIdDecimal":138,"chainName":"DeFi Oracle Meta Mainnet","rpcUrls":["https://rpc-http-pub.d-bis.org","https://rpc.d-bis.org","https://rpc2.d-bis.org","https://rpc.defi-oracle.io"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://explorer.d-bis.org"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
{"chainId":"0x1","chainIdDecimal":1,"chainName":"Ethereum Mainnet","rpcUrls":["https://eth.llamarpc.com","https://rpc.ankr.com/eth","https://ethereum.publicnode.com","https://1rpc.io/eth"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://etherscan.io"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
{"chainId":"0x9f2c4","chainIdDecimal":651940,"chainName":"ALL Mainnet","rpcUrls":["https://mainnet-rpc.alltra.global"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://alltra.global"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
{"chainId":"0x19","chainIdDecimal":25,"chainName":"Cronos Mainnet","rpcUrls":["https://evm.cronos.org","https://cronos-rpc.publicnode.com"],"nativeCurrency":{"name":"CRO","symbol":"CRO","decimals":18},"blockExplorerUrls":["https://cronos.org/explorer"],"iconUrls":["https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong"]},
{"chainId":"0x38","chainIdDecimal":56,"chainName":"BNB Smart Chain","rpcUrls":["https://bsc-dataseed.binance.org","https://bsc-dataseed1.defibit.io","https://bsc-dataseed1.ninicoin.io"],"nativeCurrency":{"name":"BNB","symbol":"BNB","decimals":18},"blockExplorerUrls":["https://bscscan.com"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
{"chainId":"0x64","chainIdDecimal":100,"chainName":"Gnosis Chain","rpcUrls":["https://rpc.gnosischain.com","https://gnosis-rpc.publicnode.com","https://1rpc.io/gnosis"],"nativeCurrency":{"name":"xDAI","symbol":"xDAI","decimals":18},"blockExplorerUrls":["https://gnosisscan.io"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
{"chainId":"0x89","chainIdDecimal":137,"chainName":"Polygon","rpcUrls":["https://polygon-rpc.com","https://polygon.llamarpc.com","https://polygon-bor-rpc.publicnode.com"],"nativeCurrency":{"name":"MATIC","symbol":"MATIC","decimals":18},"blockExplorerUrls":["https://polygonscan.com"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
{"chainId":"0xa","chainIdDecimal":10,"chainName":"Optimism","rpcUrls":["https://mainnet.optimism.io","https://optimism.llamarpc.com","https://optimism-rpc.publicnode.com"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://optimistic.etherscan.io"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
{"chainId":"0xa4b1","chainIdDecimal":42161,"chainName":"Arbitrum One","rpcUrls":["https://arb1.arbitrum.io/rpc","https://arbitrum.llamarpc.com","https://arbitrum-one-rpc.publicnode.com"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://arbiscan.io"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
{"chainId":"0x2105","chainIdDecimal":8453,"chainName":"Base","rpcUrls":["https://mainnet.base.org","https://base.llamarpc.com","https://base-rpc.publicnode.com"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://basescan.org"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
{"chainId":"0xa86a","chainIdDecimal":43114,"chainName":"Avalanche C-Chain","rpcUrls":["https://api.avax.network/ext/bc/C/rpc","https://avalanche-c-chain-rpc.publicnode.com","https://1rpc.io/avax/c"],"nativeCurrency":{"name":"AVAX","symbol":"AVAX","decimals":18},"blockExplorerUrls":["https://snowtrace.io"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
{"chainId":"0xa4ec","chainIdDecimal":42220,"chainName":"Celo","rpcUrls":["https://forno.celo.org","https://celo-mainnet-rpc.publicnode.com","https://1rpc.io/celo"],"nativeCurrency":{"name":"CELO","symbol":"CELO","decimals":18},"blockExplorerUrls":["https://celoscan.io"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
{"chainId":"0x457","chainIdDecimal":1111,"chainName":"Wemix","rpcUrls":["https://api.wemix.com","https://wemix-mainnet-rpc.publicnode.com"],"nativeCurrency":{"name":"WEMIX","symbol":"WEMIX","decimals":18},"blockExplorerUrls":["https://scan.wemix.com"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]}
]
}

View File

@@ -0,0 +1,859 @@
{
"name": "Multi-Chain Token List (13 chains, 138 base)",
"version": {
"major": 1,
"minor": 3,
"patch": 0
},
"timestamp": "2026-02-28T00:00:00.000Z",
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
"tokens": [
{
"chainId": 138,
"address": "0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6",
"name": "ETH/USD Price Feed",
"symbol": "ETH-USD",
"decimals": 8,
"logoURI": "https://ipfs.io/ipfs/QmPZuycjyJEe2otREuQ5HirvPJ8X6Yc6MBtwz1VhdD79pY",
"tags": [
"oracle",
"price-feed"
]
},
{
"chainId": 138,
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"name": "Wrapped Ether",
"symbol": "WETH",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
"tags": [
"defi",
"wrapped"
]
},
{
"chainId": 138,
"address": "0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9F",
"name": "Wrapped Ether v10",
"symbol": "WETH10",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/QmanDFPHxnbKd6SSNzzXHf9GbpL9dLXSphxDZSPPYE6ds4",
"tags": [
"defi",
"wrapped"
]
},
{
"chainId": 138,
"address": "0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03",
"name": "Chainlink Token",
"symbol": "LINK",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
"tags": [
"defi",
"oracle",
"ccip"
]
},
{
"chainId": 138,
"address": "0x93E66202A11B1772E55407B32B44e5Cd8eda7f22",
"name": "Compliant Tether USD",
"symbol": "cUSDT",
"decimals": 6,
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
"tags": [
"stablecoin",
"defi",
"compliant"
]
},
{
"chainId": 138,
"address": "0xf22258f57794CC8E06237084b353Ab30fFfa640b",
"name": "Compliant USD Coin",
"symbol": "cUSDC",
"decimals": 6,
"logoURI": "https://ipfs.io/ipfs/QmNPq4D5JXzurmi9jAhogVMzhAQRk1PZ1r9H3qQUV9gjDm",
"tags": [
"stablecoin",
"defi",
"compliant"
]
},
{
"chainId": 1,
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 1,
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 1,
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"name": "Wrapped Ether",
"symbol": "WETH",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
"tags": [
"defi",
"wrapped"
]
},
{
"chainId": 1,
"address": "0x514910771AF9Ca656af840dff83E8264EcF986CA",
"name": "Chainlink Token",
"symbol": "LINK",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
"tags": [
"defi",
"oracle",
"ccip"
]
},
{
"chainId": 1,
"address": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
"name": "Dai Stablecoin",
"symbol": "DAI",
"decimals": 18,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 1,
"address": "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419",
"name": "ETH/USD Price Feed",
"symbol": "ETH-USD",
"decimals": 8,
"logoURI": "https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png",
"tags": [
"oracle",
"price-feed"
]
},
{
"chainId": 651940,
"address": "0xa95EeD79f84E6A0151eaEb9d441F9Ffd50e8e881",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 651940,
"address": "0x015B1897Ed5279930bC2Be46F661894d219292A6",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 25,
"address": "0xc21223249CA28397B4B6541dfFaEcC539BfF0c59",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 25,
"address": "0x66e4286603D22FF153A6547700f37C7Eae42F8E2",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 25,
"address": "0x99B3511A2d315A497C8112C1fdd8D508d4B1E506",
"name": "Wrapped Ether (WETH9)",
"symbol": "WETH",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
"tags": [
"defi",
"wrapped"
]
},
{
"chainId": 25,
"address": "0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6",
"name": "Wrapped Ether v10",
"symbol": "WETH10",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/QmanDFPHxnbKd6SSNzzXHf9GbpL9dLXSphxDZSPPYE6ds4",
"tags": [
"defi",
"wrapped"
]
},
{
"chainId": 25,
"address": "0x8c80A01F461f297Df7F9DA3A4f740D7297C8Ac85",
"name": "Chainlink Token",
"symbol": "LINK",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
"tags": [
"defi",
"oracle",
"ccip"
]
},
{
"chainId": 25,
"address": "0x948690147D2e50ffe50C5d38C14125aD6a9FA036",
"name": "USD W Token",
"symbol": "USDW",
"decimals": 2,
"logoURI": "https://ipfs.io/ipfs/QmNPq4D5JXzurmi9jAhogVMzhAQRk1PZ1r9H3qQUV9gjDm",
"tags": [
"stablecoin",
"iso4217w"
]
},
{
"chainId": 25,
"address": "0x58a8D8F78F1B65c06dAd7542eC46b299629A60dd",
"name": "EUR W Token",
"symbol": "EURW",
"decimals": 2,
"logoURI": "https://ipfs.io/ipfs/QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS",
"tags": [
"stablecoin",
"iso4217w"
]
},
{
"chainId": 25,
"address": "0xFb4B6Cc81211F7d886950158294A44C312abCA29",
"name": "GBP W Token",
"symbol": "GBPW",
"decimals": 2,
"logoURI": "https://ipfs.io/ipfs/QmT2nJ6WyhYBCsYJ6NfS1BPAqiGKkCEuMxiC8ye93Co1hF",
"tags": [
"stablecoin",
"iso4217w"
]
},
{
"chainId": 25,
"address": "0xf9f5D0ACD71C76F9476F10B3F3d3E201F0883C68",
"name": "AUD W Token",
"symbol": "AUDW",
"decimals": 2,
"logoURI": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
"tags": [
"stablecoin",
"iso4217w"
]
},
{
"chainId": 25,
"address": "0xeE17bB0322383fecCA2784fbE2d4CD7d02b1905B",
"name": "JPY W Token",
"symbol": "JPYW",
"decimals": 2,
"logoURI": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
"tags": [
"stablecoin",
"iso4217w"
]
},
{
"chainId": 25,
"address": "0xc9750828124D4c10e7a6f4B655cA8487bD3842EB",
"name": "CHF W Token",
"symbol": "CHFW",
"decimals": 2,
"logoURI": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
"tags": [
"stablecoin",
"iso4217w"
]
},
{
"chainId": 25,
"address": "0x328Cd365Bb35524297E68ED28c6fF2C9557d1363",
"name": "CAD W Token",
"symbol": "CADW",
"decimals": 2,
"logoURI": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
"tags": [
"stablecoin",
"iso4217w"
]
},
{
"chainId": 56,
"address": "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 56,
"address": "0x55d398326f99059fF775485246999027B3197955",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 56,
"address": "0x2170Ed0880ac9A755fd29B2688956BD959F933F8",
"name": "Wrapped Ether",
"symbol": "WETH",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
"tags": [
"defi",
"wrapped"
]
},
{
"chainId": 56,
"address": "0x404460C6A5EdE2D891e8297795264fDe62ADBB75",
"name": "Chainlink Token",
"symbol": "LINK",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
"tags": [
"defi",
"oracle",
"ccip"
]
},
{
"chainId": 56,
"address": "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3",
"name": "Dai Stablecoin",
"symbol": "DAI",
"decimals": 18,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 100,
"address": "0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 100,
"address": "0x4ECaBa5870353805a9F068101A40E0f32ed605C6",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 100,
"address": "0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1",
"name": "Wrapped Ether",
"symbol": "WETH",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
"tags": [
"defi",
"wrapped"
]
},
{
"chainId": 100,
"address": "0xE2e73A1c69ecF83F464EFCE6A5be353a37cA09b2",
"name": "Chainlink Token",
"symbol": "LINK",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
"tags": [
"defi",
"oracle",
"ccip"
]
},
{
"chainId": 100,
"address": "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d",
"name": "Dai Stablecoin",
"symbol": "DAI",
"decimals": 18,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 137,
"address": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c1369",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 137,
"address": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 137,
"address": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619",
"name": "Wrapped Ether",
"symbol": "WETH",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
"tags": [
"defi",
"wrapped"
]
},
{
"chainId": 137,
"address": "0xb0897686c545045aFc77CF20eC7A532E3120E0F1",
"name": "Chainlink Token",
"symbol": "LINK",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
"tags": [
"defi",
"oracle",
"ccip"
]
},
{
"chainId": 137,
"address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063",
"name": "Dai Stablecoin",
"symbol": "DAI",
"decimals": 18,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 10,
"address": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 10,
"address": "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 10,
"address": "0x4200000000000000000000000000000000000006",
"name": "Wrapped Ether",
"symbol": "WETH",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
"tags": [
"defi",
"wrapped"
]
},
{
"chainId": 10,
"address": "0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6",
"name": "Chainlink Token",
"symbol": "LINK",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
"tags": [
"defi",
"oracle",
"ccip"
]
},
{
"chainId": 10,
"address": "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1",
"name": "Dai Stablecoin",
"symbol": "DAI",
"decimals": 18,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 42161,
"address": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 42161,
"address": "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 42161,
"address": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
"name": "Wrapped Ether",
"symbol": "WETH",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
"tags": [
"defi",
"wrapped"
]
},
{
"chainId": 42161,
"address": "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4",
"name": "Chainlink Token",
"symbol": "LINK",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
"tags": [
"defi",
"oracle",
"ccip"
]
},
{
"chainId": 42161,
"address": "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1",
"name": "Dai Stablecoin",
"symbol": "DAI",
"decimals": 18,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 8453,
"address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 8453,
"address": "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 8453,
"address": "0x4200000000000000000000000000000000000006",
"name": "Wrapped Ether",
"symbol": "WETH",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
"tags": [
"defi",
"wrapped"
]
},
{
"chainId": 8453,
"address": "0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196",
"name": "Chainlink Token",
"symbol": "LINK",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
"tags": [
"defi",
"oracle",
"ccip"
]
},
{
"chainId": 8453,
"address": "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
"name": "Dai Stablecoin",
"symbol": "DAI",
"decimals": 18,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 43114,
"address": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 43114,
"address": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 43114,
"address": "0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB",
"name": "Wrapped Ether",
"symbol": "WETH",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
"tags": [
"defi",
"wrapped"
]
},
{
"chainId": 43114,
"address": "0x5947BB275c521040051D82396192181b413227A3",
"name": "Chainlink Token",
"symbol": "LINK",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
"tags": [
"defi",
"oracle",
"ccip"
]
},
{
"chainId": 43114,
"address": "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70",
"name": "Dai Stablecoin",
"symbol": "DAI",
"decimals": 18,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 42220,
"address": "0xcebA9300f2b948710d2653dD7B07f33A8B32118C",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 42220,
"address": "0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 42220,
"address": "0x122013fd7dF1C6F636a5bb8f03108E876548b455",
"name": "Wrapped Ether",
"symbol": "WETH",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
"tags": [
"defi",
"wrapped"
]
},
{
"chainId": 42220,
"address": "0xd07294e6E917e07dfDcee882dd1e2565085C2ae0",
"name": "Chainlink Token",
"symbol": "LINK",
"decimals": 18,
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
"tags": [
"defi",
"oracle",
"ccip"
]
},
{
"chainId": 1111,
"address": "0xE3F5a90F9cb311505cd691a46596599aA1A0AD7D",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6,
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
"tags": [
"stablecoin",
"defi"
]
},
{
"chainId": 1111,
"address": "0xA649325Aa7C5093d12D6F98EB4378deAe68CE23F",
"name": "Tether USD",
"symbol": "USDT",
"decimals": 6,
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
"tags": [
"stablecoin",
"defi"
]
}
],
"tags": {
"defi": {
"name": "DeFi",
"description": "Decentralized Finance tokens"
},
"wrapped": {
"name": "Wrapped",
"description": "Wrapped tokens representing native assets"
},
"oracle": {
"name": "Oracle",
"description": "Oracle price feed contracts"
},
"price-feed": {
"name": "Price Feed",
"description": "Price feed oracle contracts"
},
"stablecoin": {
"name": "Stablecoin",
"description": "Stable value tokens pegged to fiat"
},
"compliant": {
"name": "Compliant",
"description": "Regulatory compliant tokens"
},
"iso4217w": {
"name": "ISO4217W",
"description": "ISO 4217 compliant wrapped fiat tokens"
}
}
}

36
provider/index.js Normal file
View File

@@ -0,0 +1,36 @@
/**
* MetaMask Dual-Chain Provider
* Connect MetaMask and other Web3 providers to ChainID 138 (DeFi Oracle Meta Mainnet)
* and Ethereum Mainnet (1). Includes chain configs, token list, and oracle helpers.
*
* Usage:
* import { addChainsToWallet, switchChain, getEthUsdPrice, getTokensByChain } from './provider'
* await addChainsToWallet(window.ethereum)
* const price = await getEthUsdPrice(provider, 138)
*/
export {
CHAINS,
CHAIN_138,
CHAIN_MAINNET,
CHAIN_ALL_MAINNET,
getChainById,
getChainByHex,
} from './chains.js'
export {
ORACLES_CHAIN_138,
ORACLES_MAINNET,
ORACLE_ABI,
getEthUsdPrice,
getOracleConfig,
} from './oracles.js'
export {
TOKEN_LIST,
TOKEN_LIST_URL,
getTokensByChain,
getToken,
} from './tokens.js'
export { addChainsToWallet, switchChain, addTokenToWallet, ensureChain } from './wallet.js'

65
provider/oracles.js Normal file
View File

@@ -0,0 +1,65 @@
/**
* Oracle addresses and helpers for Chain 138 and Ethereum Mainnet.
* Use these to read price feeds so MetaMask and dApps can display USD values.
*/
/** Chain 138: ETH/USD proxy and aggregator */
export const ORACLES_CHAIN_138 = {
chainId: 138,
ethUsdProxy: '0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6',
aggregator: '0x99b3511a2d315a497c8112c1fdd8d508d4b1e506',
decimals: 8,
rpcUrl: 'https://rpc-http-pub.d-bis.org',
}
/** Ethereum Mainnet: Chainlink ETH/USD */
export const ORACLES_MAINNET = {
chainId: 1,
ethUsdProxy: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419',
decimals: 8,
rpcUrl: 'https://eth.llamarpc.com',
}
/** Minimal ABI for latestRoundData (Chainlink-compatible) */
export const ORACLE_ABI = [
'function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)',
'function decimals() external view returns (uint8)',
]
/**
* Get ETH/USD price from the appropriate oracle for the given chain.
* @param {import('ethers').Provider} provider - ethers v6 JsonRpcProvider or BrowserProvider
* @param {number} chainId - 138 or 1
* @returns {Promise<{ price: number, updatedAt: Date, decimals: number } | null>}
*/
export async function getEthUsdPrice(provider, chainId) {
const oracleConfig = chainId === 138 ? ORACLES_CHAIN_138 : chainId === 1 ? ORACLES_MAINNET : null
if (!oracleConfig) return null
try {
const { ethers } = await import('ethers')
const contract = new ethers.Contract(oracleConfig.ethUsdProxy, ORACLE_ABI, provider)
const [roundId, answer, startedAt, updatedAt] = await contract.latestRoundData()
const decimals = Number(await contract.decimals())
const price = Number(answer) / Math.pow(10, decimals)
return {
price,
updatedAt: new Date(Number(updatedAt) * 1000),
decimals,
roundId: Number(roundId),
}
} catch (err) {
console.error('getEthUsdPrice error:', err)
return null
}
}
/**
* Get oracle config for a chain (for custom contract usage).
* @param {number} chainId - 138 or 1
*/
export function getOracleConfig(chainId) {
if (chainId === 138) return ORACLES_CHAIN_138
if (chainId === 1) return ORACLES_MAINNET
return null
}

19
provider/package.json Normal file
View File

@@ -0,0 +1,19 @@
{
"name": "@proxmox/metamask-dual-chain-provider",
"version": "1.0.0",
"description": "MetaMask provider for ChainID 138 and Ethereum Mainnet",
"type": "module",
"main": "index.js",
"files": ["*.js", "*.d.ts", "config/"],
"keywords": ["metamask", "web3", "chainid-138", "ethereum-mainnet", "oracle", "token-list"],
"license": "MIT",
"peerDependencies": {
"ethers": ">=6.0.0"
},
"peerDependenciesMeta": {
"ethers": { "optional": true }
},
"scripts": {
"test:integration": "node test-integration.mjs"
}
}

View File

@@ -0,0 +1,98 @@
#!/usr/bin/env node
/**
* Provider integration test (Node).
* Tests chain configs, token list, and exports without window.ethereum.
* Run: node test-integration.mjs
*/
const assert = (ok, msg) => {
if (!ok) throw new Error(msg)
}
async function main() {
console.log('Provider integration test (Node)\n')
const { CHAINS, CHAIN_138, CHAIN_MAINNET, CHAIN_ALL_MAINNET, getChainById, getChainByHex } = await import('./chains.js')
const { getTokensByChain, getToken, TOKEN_LIST_URL } = await import('./tokens.js')
const { addChainsToWallet, switchChain, addTokenToWallet, ensureChain } = await import('./wallet.js')
const { ORACLES_CHAIN_138, ORACLES_MAINNET, getOracleConfig } = await import('./oracles.js')
let passed = 0
let failed = 0
// Chains
try {
assert(Array.isArray(CHAINS) && CHAINS.length >= 3, 'CHAINS has at least 3 entries')
assert(CHAIN_138 && CHAIN_138.chainIdDecimal === 138, 'CHAIN_138 has chainIdDecimal 138')
assert(CHAIN_MAINNET && CHAIN_MAINNET.chainIdDecimal === 1, 'CHAIN_MAINNET has chainIdDecimal 1')
assert(CHAIN_ALL_MAINNET && CHAIN_ALL_MAINNET.chainIdDecimal === 651940, 'CHAIN_ALL_MAINNET has chainIdDecimal 651940')
assert(getChainById(138) === CHAIN_138, 'getChainById(138) returns CHAIN_138')
assert(getChainById(1) === CHAIN_MAINNET, 'getChainById(1) returns CHAIN_MAINNET')
assert(getChainByHex('0x8a') === CHAIN_138, 'getChainByHex(0x8a) returns CHAIN_138')
console.log(' ✓ Chains (CHAINS, CHAIN_138, CHAIN_MAINNET, CHAIN_ALL_MAINNET, getChainById, getChainByHex)')
passed++
} catch (e) {
console.log(' ✗ Chains:', e.message)
failed++
}
// Tokens
try {
const t138 = getTokensByChain(138)
const t1 = getTokensByChain(1)
const t651940 = getTokensByChain(651940)
assert(Array.isArray(t138) && t138.length > 0, 'getTokensByChain(138) returns non-empty array')
assert(Array.isArray(t1) && t1.length > 0, 'getTokensByChain(1) returns non-empty array')
assert(Array.isArray(t651940), 'getTokensByChain(651940) returns array')
assert(typeof TOKEN_LIST_URL === 'string' && TOKEN_LIST_URL.length > 0, 'TOKEN_LIST_URL is set')
const weth138 = getToken(138, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2')
assert(weth138 && weth138.symbol, 'getToken(138, WETH9) returns token with symbol')
console.log(' ✓ Tokens (getTokensByChain, getToken, TOKEN_LIST_URL)')
passed++
} catch (e) {
console.log(' ✗ Tokens:', e.message)
failed++
}
// Wallet (exports only; no window.ethereum)
try {
assert(typeof addChainsToWallet === 'function', 'addChainsToWallet is function')
assert(typeof switchChain === 'function', 'switchChain is function')
assert(typeof addTokenToWallet === 'function', 'addTokenToWallet is function')
assert(typeof ensureChain === 'function', 'ensureChain is function')
console.log(' ✓ Wallet exports (addChainsToWallet, switchChain, addTokenToWallet, ensureChain)')
passed++
} catch (e) {
console.log(' ✗ Wallet:', e.message)
failed++
}
// Oracles
try {
assert(ORACLES_CHAIN_138 && ORACLES_CHAIN_138.ethUsdProxy, 'ORACLES_CHAIN_138 has ethUsdProxy')
assert(ORACLES_MAINNET && ORACLES_MAINNET.ethUsdProxy, 'ORACLES_MAINNET has ethUsdProxy')
const cfg138 = getOracleConfig(138)
const cfg1 = getOracleConfig(1)
assert(cfg138 && cfg138.ethUsdProxy, 'getOracleConfig(138) has ethUsdProxy')
assert(cfg1 && cfg1.ethUsdProxy, 'getOracleConfig(1) has ethUsdProxy')
console.log(' ✓ Oracles (ORACLES_CHAIN_138, ORACLES_MAINNET, getOracleConfig)')
passed++
} catch (e) {
console.log(' ✗ Oracles:', e.message)
failed++
}
console.log('')
if (failed === 0) {
console.log(`Result: ${passed} passed, 0 failed`)
process.exit(0)
} else {
console.log(`Result: ${passed} passed, ${failed} failed`)
process.exit(1)
}
}
main().catch((err) => {
console.error(err)
process.exit(1)
})

46
provider/tokens.js Normal file
View File

@@ -0,0 +1,46 @@
/**
* Multi-chain token list (Chain 138 + Ethereum Mainnet + ALL Mainnet).
* Use with wallet_watchAsset and for displaying tokens in dApps.
*/
/** Inline token list for Chain 138, Mainnet, and ALL Mainnet. Matches DUAL_CHAIN_TOKEN_LIST.tokenlist.json */
export const TOKEN_LIST = [
// Chain 138
{ chainId: 138, address: '0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6', name: 'ETH/USD Price Feed', symbol: 'ETH-USD', decimals: 8, tags: ['oracle', 'price-feed'] },
{ chainId: 138, address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', name: 'Wrapped Ether', symbol: 'WETH', decimals: 18, tags: ['defi', 'wrapped'] },
{ chainId: 138, address: '0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f', name: 'Wrapped Ether v10', symbol: 'WETH', decimals: 18, tags: ['defi', 'wrapped'] },
{ chainId: 138, address: '0x93E66202A11B1772E55407B32B44e5Cd8eda7f22', name: 'Compliant Tether USD', symbol: 'cUSDT', decimals: 6, tags: ['stablecoin', 'defi', 'compliant'] },
{ chainId: 138, address: '0xf22258f57794CC8E06237084b353Ab30fFfa640b', name: 'Compliant USD Coin', symbol: 'cUSDC', decimals: 6, tags: ['stablecoin', 'defi', 'compliant'] },
// Ethereum Mainnet
{ chainId: 1, address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', name: 'Wrapped Ether', symbol: 'WETH', decimals: 18, tags: ['defi', 'wrapped'] },
{ chainId: 1, address: '0xdAC17F958D2ee523a2206206994597C13D831ec7', name: 'Tether USD', symbol: 'USDT', decimals: 6, tags: ['stablecoin', 'defi'] },
{ chainId: 1, address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', name: 'USD Coin', symbol: 'USDC', decimals: 6, tags: ['stablecoin', 'defi'] },
{ chainId: 1, address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', name: 'Dai Stablecoin', symbol: 'DAI', decimals: 18, tags: ['stablecoin', 'defi'] },
{ chainId: 1, address: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', name: 'ETH/USD Price Feed', symbol: 'ETH-USD', decimals: 8, tags: ['oracle', 'price-feed'] },
// ALL Mainnet (651940)
{ chainId: 651940, address: '0xa95EeD79f84E6A0151eaEb9d441F9Ffd50e8e881', name: 'USD Coin', symbol: 'USDC', decimals: 6, tags: ['stablecoin', 'defi'] },
]
/**
* @param {number} chainId - 138, 1, or 651940
* @returns {Array<{ chainId: number, address: string, name: string, symbol: string, decimals: number, tags?: string[] }>}
*/
export function getTokensByChain(chainId) {
return TOKEN_LIST.filter((t) => t.chainId === chainId)
}
/**
* @param {number} chainId
* @param {string} address - token contract address (checksummed or lowercase)
* @returns {typeof TOKEN_LIST[0] | undefined}
*/
export function getToken(chainId, address) {
const addr = address.toLowerCase()
return TOKEN_LIST.find((t) => t.chainId === chainId && t.address.toLowerCase() === addr)
}
/**
* URL to the combined token list JSON (hosted by the explorer API).
* Override in your app if you host the list elsewhere.
*/
export const TOKEN_LIST_URL = 'https://explorer.d-bis.org/api/config/token-list'

30
provider/types.d.ts vendored Normal file
View File

@@ -0,0 +1,30 @@
/**
* Types for MetaMask dual-chain provider (Chain 138 + Ethereum Mainnet).
*/
export interface ChainParams {
chainId: string
chainIdDecimal: number
chainName: string
nativeCurrency: { name: string; symbol: string; decimals: number }
rpcUrls: string[]
blockExplorerUrls: string[]
iconUrls?: string[]
}
export interface TokenInfo {
chainId: number
address: string
name: string
symbol: string
decimals: number
logoURI?: string
tags?: string[]
}
export interface OraclePriceResult {
price: number
updatedAt: Date
decimals: number
roundId?: number
}

104
provider/wallet.js Normal file
View File

@@ -0,0 +1,104 @@
/**
* Wallet helpers for MetaMask and EIP-1193 providers.
* Add chains (138 + Mainnet), switch chain, add tokens.
*/
import { CHAINS, getChainByHex, getChainById } from './chains.js'
import { getTokensByChain, getToken } from './tokens.js'
/**
* Add both Chain 138 and Ethereum Mainnet to the wallet (if not already added).
* @param {import('ethers').Eip1193Provider} ethereum - window.ethereum or other EIP-1193 provider
* @param {{ chains?: number[] }} options - optional: { chains: [138, 1] } to add only specific chains
* @returns {Promise<{ added: number[], skipped: number[], errors: { chainId: number, error: Error }[] }>}
*/
export async function addChainsToWallet(ethereum, options = {}) {
const chainIds = options.chains ?? [138, 1]
const toAdd = CHAINS.filter((c) => chainIds.includes(c.chainIdDecimal))
const result = { added: [], skipped: [], errors: [] }
for (const chain of toAdd) {
try {
await ethereum.request({
method: 'wallet_addEthereumChain',
params: [{ ...chain }],
})
result.added.push(chain.chainIdDecimal)
} catch (err) {
if (err.code === 4902) {
result.added.push(chain.chainIdDecimal)
} else if (err.code === -32603 && /already exists/i.test(String(err.message))) {
result.skipped.push(chain.chainIdDecimal)
} else {
result.errors.push({ chainId: chain.chainIdDecimal, error: err })
}
}
}
return result
}
/**
* Switch the wallet to the given chain. If chain is not added, adds it first (wallet_addEthereumChain).
* @param {import('ethers').Eip1193Provider} ethereum - window.ethereum
* @param {number} chainIdDecimal - 138 or 1
* @returns {Promise<void>}
*/
export async function switchChain(ethereum, chainIdDecimal) {
const chain = getChainById(chainIdDecimal)
if (!chain) throw new Error(`Unknown chain: ${chainIdDecimal}`)
try {
await ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: chain.chainId }],
})
} catch (err) {
if (err.code === 4902) {
await ethereum.request({
method: 'wallet_addEthereumChain',
params: [chain],
})
} else {
throw err
}
}
}
/**
* Add a token to the wallet (wallet_watchAsset).
* @param {import('ethers').Eip1193Provider} ethereum - window.ethereum
* @param {{ chainId: number, address: string, symbol: string, decimals: number, name?: string }} token - token info (use getToken(chainId, address) for known tokens)
* @returns {Promise<boolean>} - true if user approved
*/
export async function addTokenToWallet(ethereum, token) {
const result = await ethereum.request({
method: 'wallet_watchAsset',
params: {
type: 'ERC20',
options: {
address: token.address,
symbol: token.symbol,
decimals: token.decimals,
...(token.name && { name: token.name }),
},
},
})
return !!result
}
/**
* Ensure the wallet is on the given chain; if not, switch (and add if needed).
* @param {import('ethers').Eip1193Provider} ethereum - window.ethereum
* @param {number} chainIdDecimal - 138 or 1
* @returns {Promise<boolean>} - true if already on chain or switched successfully
*/
export async function ensureChain(ethereum, chainIdDecimal) {
const hex = await ethereum.request({ method: 'eth_chainId', params: [] })
const current = parseInt(hex, 16)
if (current === chainIdDecimal) return true
await switchChain(ethereum, chainIdDecimal)
return true
}
export { getTokensByChain, getToken }