diff --git a/.changeset/bright-apes-add-chains.md b/.changeset/bright-apes-add-chains.md new file mode 100644 index 00000000..21695269 --- /dev/null +++ b/.changeset/bright-apes-add-chains.md @@ -0,0 +1,7 @@ +--- +"@mimicprotocol/lib-ts": patch +"@mimicprotocol/cli": patch +"@mimicprotocol/test-ts": patch +--- + +Add Polygon, Avalanche, and BNB chain support diff --git a/packages/lib-ts/src/chains/Avalanche.ts b/packages/lib-ts/src/chains/Avalanche.ts new file mode 100644 index 00000000..580f70f1 --- /dev/null +++ b/packages/lib-ts/src/chains/Avalanche.ts @@ -0,0 +1,15 @@ +import { ERC20Token } from '../tokens' +import { ChainId } from '../types' + +/* eslint-disable no-secrets/no-secrets */ + +export namespace Avalanche { + export const CHAIN_ID = ChainId.AVALANCHE + export const AVAX = ERC20Token.native(CHAIN_ID) + export const USDC = ERC20Token.fromString('0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E', CHAIN_ID, 6, 'USDC') + export const USDT = ERC20Token.fromString('0x9702230A8Ea53601f5cd2dc00fDbc13d4dF4A8c7', CHAIN_ID, 6, 'USDt') + export const DAI = ERC20Token.fromString('0xd586E7F844cEa2F87f50152665BCbc2C279D8d70', CHAIN_ID, 18, 'DAI.e') + export const WBTC = ERC20Token.fromString('0x50b7545627a5162F82A992c33b87aDc75187B218', CHAIN_ID, 8, 'WBTC.e') + export const WETH = ERC20Token.fromString('0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB', CHAIN_ID, 18, 'WETH.e') + export const WAVAX = ERC20Token.fromString('0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7', CHAIN_ID, 18, 'WAVAX') +} diff --git a/packages/lib-ts/src/chains/BNB.ts b/packages/lib-ts/src/chains/BNB.ts new file mode 100644 index 00000000..0fb6cdcc --- /dev/null +++ b/packages/lib-ts/src/chains/BNB.ts @@ -0,0 +1,15 @@ +import { ERC20Token } from '../tokens' +import { ChainId } from '../types' + +/* eslint-disable no-secrets/no-secrets */ + +export namespace BNB { + export const CHAIN_ID = ChainId.BNB + export const BNB = ERC20Token.native(CHAIN_ID) + export const USDC = ERC20Token.fromString('0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d', CHAIN_ID, 18, 'USDC') + export const USDT = ERC20Token.fromString('0x55d398326f99059fF775485246999027B3197955', CHAIN_ID, 18, 'USDT') + export const DAI = ERC20Token.fromString('0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3', CHAIN_ID, 18, 'DAI') + export const WBTC = ERC20Token.fromString('0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3ead9c', CHAIN_ID, 18, 'BTCB') + export const WETH = ERC20Token.fromString('0x2170Ed0880ac9A755fd29B2688956BD959F933F8', CHAIN_ID, 18, 'ETH') + export const WBNB = ERC20Token.fromString('0xBB4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c', CHAIN_ID, 18, 'WBNB') +} diff --git a/packages/lib-ts/src/chains/Polygon.ts b/packages/lib-ts/src/chains/Polygon.ts new file mode 100644 index 00000000..9dea49f6 --- /dev/null +++ b/packages/lib-ts/src/chains/Polygon.ts @@ -0,0 +1,15 @@ +import { ERC20Token } from '../tokens' +import { ChainId } from '../types' + +/* eslint-disable no-secrets/no-secrets */ + +export namespace Polygon { + export const CHAIN_ID = ChainId.POLYGON + export const POL = ERC20Token.native(CHAIN_ID) + export const USDC = ERC20Token.fromString('0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', CHAIN_ID, 6, 'USDC') + export const USDT = ERC20Token.fromString('0xc2132D05D31c914a87C6611C10748AEb04B58e8F', CHAIN_ID, 6, 'USDT0') + export const DAI = ERC20Token.fromString('0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063', CHAIN_ID, 18, 'DAI') + export const WBTC = ERC20Token.fromString('0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6', CHAIN_ID, 8, 'WBTC') + export const WETH = ERC20Token.fromString('0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', CHAIN_ID, 18, 'WETH') + export const WPOL = ERC20Token.fromString('0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', CHAIN_ID, 18, 'WPOL') +} diff --git a/packages/lib-ts/src/chains/index.ts b/packages/lib-ts/src/chains/index.ts index 40e28fed..1a88f1f9 100644 --- a/packages/lib-ts/src/chains/index.ts +++ b/packages/lib-ts/src/chains/index.ts @@ -1,7 +1,10 @@ export * from './Arbitrum' +export * from './Avalanche' export * from './Base' export * from './BaseSepolia' +export * from './BNB' export * from './Ethereum' export * from './Gnosis' export * from './Optimism' +export * from './Polygon' export * from './Sonic' diff --git a/packages/lib-ts/src/tokens/ERC20Token.ts b/packages/lib-ts/src/tokens/ERC20Token.ts index bac39466..d6f85d69 100644 --- a/packages/lib-ts/src/tokens/ERC20Token.ts +++ b/packages/lib-ts/src/tokens/ERC20Token.ts @@ -29,8 +29,14 @@ export class ERC20Token extends BlockchainToken { case ChainId.ARBITRUM: case ChainId.OPTIMISM: return ERC20Token.fromString(EVM_NATIVE_ADDRESS, chainId, 18, 'ETH') + case ChainId.BNB: + return ERC20Token.fromString(EVM_NATIVE_ADDRESS, chainId, 18, 'BNB') case ChainId.GNOSIS: return ERC20Token.fromString(EVM_NATIVE_ADDRESS, chainId, 18, 'xDAI') + case ChainId.POLYGON: + return ERC20Token.fromString('0x0000000000000000000000000000000000001010', chainId, 18, 'POL') + case ChainId.AVALANCHE: + return ERC20Token.fromString(EVM_NATIVE_ADDRESS, chainId, 18, 'AVAX') case ChainId.SONIC: return ERC20Token.fromString(EVM_NATIVE_ADDRESS, chainId, 18, 'SONIC') default: diff --git a/packages/lib-ts/src/tokens/Tokens.ts b/packages/lib-ts/src/tokens/Tokens.ts index 2e6dc3e8..ba136818 100644 --- a/packages/lib-ts/src/tokens/Tokens.ts +++ b/packages/lib-ts/src/tokens/Tokens.ts @@ -1,4 +1,4 @@ -import { Arbitrum, Base, BaseSepolia, Ethereum, Gnosis, Optimism, Sonic } from '../chains' +import { Arbitrum, Avalanche, Base, BaseSepolia, BNB, Ethereum, Gnosis, Optimism, Polygon, Sonic } from '../chains' import { TokenProvider } from './TokenProvider' @@ -23,6 +23,12 @@ export class Tokens { private readonly wbtc: TokenProvider = new TokenProvider('WBTC') private readonly weth: TokenProvider = new TokenProvider('WETH') private readonly eth: TokenProvider = new TokenProvider('ETH') + private readonly avax: TokenProvider = new TokenProvider('AVAX') + private readonly wavax: TokenProvider = new TokenProvider('WAVAX') + private readonly pol: TokenProvider = new TokenProvider('POL') + private readonly wpol: TokenProvider = new TokenProvider('WPOL') + private readonly bnb: TokenProvider = new TokenProvider('BNB') + private readonly wbnb: TokenProvider = new TokenProvider('WBNB') private readonly xdai: TokenProvider = new TokenProvider('xDAI') private readonly sonic: TokenProvider = new TokenProvider('SONIC') private readonly wxdai: TokenProvider = new TokenProvider('WXDAI') @@ -45,6 +51,15 @@ export class Tokens { this.weth.register(Arbitrum.CHAIN_ID, Arbitrum.WETH) this.eth.register(Arbitrum.CHAIN_ID, Arbitrum.ETH) + // Avalanche + this.usdc.register(Avalanche.CHAIN_ID, Avalanche.USDC) + this.usdt.register(Avalanche.CHAIN_ID, Avalanche.USDT) + this.dai.register(Avalanche.CHAIN_ID, Avalanche.DAI) + this.wbtc.register(Avalanche.CHAIN_ID, Avalanche.WBTC) + this.weth.register(Avalanche.CHAIN_ID, Avalanche.WETH) + this.avax.register(Avalanche.CHAIN_ID, Avalanche.AVAX) + this.wavax.register(Avalanche.CHAIN_ID, Avalanche.WAVAX) + // Base this.usdc.register(Base.CHAIN_ID, Base.USDC) this.usdt.register(Base.CHAIN_ID, Base.USDT) @@ -53,6 +68,15 @@ export class Tokens { this.weth.register(Base.CHAIN_ID, Base.WETH) this.eth.register(Base.CHAIN_ID, Base.ETH) + // BNB + this.usdc.register(BNB.CHAIN_ID, BNB.USDC) + this.usdt.register(BNB.CHAIN_ID, BNB.USDT) + this.dai.register(BNB.CHAIN_ID, BNB.DAI) + this.wbtc.register(BNB.CHAIN_ID, BNB.WBTC) + this.weth.register(BNB.CHAIN_ID, BNB.WETH) + this.bnb.register(BNB.CHAIN_ID, BNB.BNB) + this.wbnb.register(BNB.CHAIN_ID, BNB.WBNB) + // Optimism this.usdc.register(Optimism.CHAIN_ID, Optimism.USDC) this.usdt.register(Optimism.CHAIN_ID, Optimism.USDT) @@ -69,6 +93,15 @@ export class Tokens { this.xdai.register(Gnosis.CHAIN_ID, Gnosis.xDAI) this.wxdai.register(Gnosis.CHAIN_ID, Gnosis.WXDAI) + // Polygon + this.usdc.register(Polygon.CHAIN_ID, Polygon.USDC) + this.usdt.register(Polygon.CHAIN_ID, Polygon.USDT) + this.dai.register(Polygon.CHAIN_ID, Polygon.DAI) + this.wbtc.register(Polygon.CHAIN_ID, Polygon.WBTC) + this.weth.register(Polygon.CHAIN_ID, Polygon.WETH) + this.pol.register(Polygon.CHAIN_ID, Polygon.POL) + this.wpol.register(Polygon.CHAIN_ID, Polygon.WPOL) + // Sonic this.usdc.register(Sonic.CHAIN_ID, Sonic.USDC) this.usdt.register(Sonic.CHAIN_ID, Sonic.USDT) @@ -111,6 +144,30 @@ export class Tokens { return Tokens.getInstance().eth } + static get AVAX(): TokenProvider { + return Tokens.getInstance().avax + } + + static get WAVAX(): TokenProvider { + return Tokens.getInstance().wavax + } + + static get POL(): TokenProvider { + return Tokens.getInstance().pol + } + + static get WPOL(): TokenProvider { + return Tokens.getInstance().wpol + } + + static get BNB(): TokenProvider { + return Tokens.getInstance().bnb + } + + static get WBNB(): TokenProvider { + return Tokens.getInstance().wbnb + } + static get XDAI(): TokenProvider { return Tokens.getInstance().xdai } diff --git a/packages/lib-ts/src/types/ChainId.ts b/packages/lib-ts/src/types/ChainId.ts index 44849683..9208dca6 100644 --- a/packages/lib-ts/src/types/ChainId.ts +++ b/packages/lib-ts/src/types/ChainId.ts @@ -5,10 +5,13 @@ export enum ChainId { ETHEREUM = 1, OPTIMISM = 10, - ARBITRUM = 42161, + BNB = 56, + GNOSIS = 100, + POLYGON = 137, + SONIC = 146, BASE = 8453, + ARBITRUM = 42161, + AVALANCHE = 43114, BASE_SEPOLIA = 84532, - GNOSIS = 100, SOLANA_MAINNET = 507424, - SONIC = 146, } diff --git a/packages/lib-ts/tests/helpers.ts b/packages/lib-ts/tests/helpers.ts index cc68f5ac..b393f2e5 100644 --- a/packages/lib-ts/tests/helpers.ts +++ b/packages/lib-ts/tests/helpers.ts @@ -22,6 +22,9 @@ export const CHAIN_IDS: ChainId[] = [ ChainId.ARBITRUM, ChainId.OPTIMISM, ChainId.GNOSIS, + ChainId.BNB, + ChainId.POLYGON, + ChainId.AVALANCHE, ChainId.SONIC, ] diff --git a/packages/lib-ts/tests/tokens/ERC20Token.spec.ts b/packages/lib-ts/tests/tokens/ERC20Token.spec.ts index 4dd337d0..c73521e2 100644 --- a/packages/lib-ts/tests/tokens/ERC20Token.spec.ts +++ b/packages/lib-ts/tests/tokens/ERC20Token.spec.ts @@ -136,6 +136,19 @@ describe('ERC20Token', () => { }) }) + describe('when the chain id is bnb', () => { + const chainId = ChainId.BNB + + it('returns the expected token', () => { + const token = ERC20Token.native(chainId) + + expect(token.address.toHexString()).toBe(EVM_NATIVE_ADDRESS) + expect(token.chainId).toBe(chainId) + expect(token.symbol).toBe('BNB') + expect(token.decimals).toBe(18) + }) + }) + describe('when the chain id is gnosis', () => { const chainId = ChainId.GNOSIS @@ -149,6 +162,32 @@ describe('ERC20Token', () => { }) }) + describe('when the chain id is polygon', () => { + const chainId = ChainId.POLYGON + + it('returns the expected token', () => { + const token = ERC20Token.native(chainId) + + expect(token.address.toHexString()).toBe('0x0000000000000000000000000000000000001010') + expect(token.chainId).toBe(chainId) + expect(token.symbol).toBe('POL') + expect(token.decimals).toBe(18) + }) + }) + + describe('when the chain id is avalanche', () => { + const chainId = ChainId.AVALANCHE + + it('returns the expected token', () => { + const token = ERC20Token.native(chainId) + + expect(token.address.toHexString()).toBe(EVM_NATIVE_ADDRESS) + expect(token.chainId).toBe(chainId) + expect(token.symbol).toBe('AVAX') + expect(token.decimals).toBe(18) + }) + }) + describe('when the chain id is sonic', () => { const chainId = ChainId.SONIC