From 3c38e536010790e1a97fac63b9006b1b65a1c10b Mon Sep 17 00:00:00 2001 From: sanyu1225 Date: Fri, 13 Sep 2024 16:10:30 +0800 Subject: [PATCH] feat: add test and comment loadSwitchableNetwork --- packages/blocto-sdk/jest.config.cjs | 2 +- .../blocto-sdk/src/__tests__/ethereum.test.ts | 132 ++++++++ .../src/__tests__/fixtures/getEvmSupport.ts | 312 ++++++++++++++++++ .../blocto-sdk/src/__tests__/index.test.js | 12 +- packages/blocto-sdk/src/providers/ethereum.ts | 18 +- 5 files changed, 471 insertions(+), 5 deletions(-) create mode 100644 packages/blocto-sdk/src/__tests__/ethereum.test.ts create mode 100644 packages/blocto-sdk/src/__tests__/fixtures/getEvmSupport.ts diff --git a/packages/blocto-sdk/jest.config.cjs b/packages/blocto-sdk/jest.config.cjs index 0513f8c4..771a284b 100644 --- a/packages/blocto-sdk/jest.config.cjs +++ b/packages/blocto-sdk/jest.config.cjs @@ -6,7 +6,7 @@ module.exports = { '^.+\\.(ts|tsx)?$': 'ts-jest', '^.+\\.(js|jsx)$': 'babel-jest', }, - transformIgnorePatterns: ['node_modules/(?!variables/.*)'], + testPathIgnorePatterns: ['node_modules/(?!variables/.*)', '/fixtures/'], automock: false, resetMocks: false, }; diff --git a/packages/blocto-sdk/src/__tests__/ethereum.test.ts b/packages/blocto-sdk/src/__tests__/ethereum.test.ts new file mode 100644 index 00000000..5d2e030c --- /dev/null +++ b/packages/blocto-sdk/src/__tests__/ethereum.test.ts @@ -0,0 +1,132 @@ +import EthereumProvider from '../providers/ethereum'; +import { getEvmSupport } from '../lib/getEvmSupport'; +import { getEvmSupportList } from './fixtures/getEvmSupport'; +jest.mock('../lib/getEvmSupport'); + +describe('Testing BloctoSDK ethereum provider initialization and network loading', () => { + beforeEach(() => { + (getEvmSupport as jest.Mock).mockResolvedValue(getEvmSupportList); + }); + + test('should initialize with unloadedNetwork', () => { + const ethereumWithSwitchable = new EthereumProvider({ + defaultChainId: '0xaa36a7', + switchableChains: [ + { + chainId: '0xaa36a7', + rpcUrls: ['https://ethereum-sepolia.blockpi.network/v1/rpc/public'], + }, + { + chainId: '0x61', + rpcUrls: ['https://data-seed-prebsc-1-s1.binance.org:8545'], + }, + ], + }); + + expect(ethereumWithSwitchable['_blocto'].unloadedNetwork).toBeDefined(); + expect( + ethereumWithSwitchable['_blocto']?.unloadedNetwork?.[0].chainId + ).toBe('0xaa36a7'); + expect( + ethereumWithSwitchable['_blocto']?.unloadedNetwork?.[1].chainId + ).toBe('0x61'); + expect(ethereumWithSwitchable['_blocto'].unloadedNetwork?.length).toBe(2); + }); + + test('get support chain list', async () => { + const ethereum = new EthereumProvider({ + chainId: '0xaa36a7', + rpc: 'https://ethereum-sepolia.blockpi.network/v1/rpc/public', + }); + const supportedChains = await ethereum.supportChainList(); + expect(supportedChains).toContainEqual({ + chainId: '11155111', + chainName: 'Sepolia', + }); + }); + + test('should add chain and switch to it', async () => { + const ethereum = new EthereumProvider({ + chainId: '0xaa36a7', + rpc: 'https://ethereum-sepolia.blockpi.network/v1/rpc/public', + }); + await expect( + ethereum.request({ + method: 'wallet_switchEthereumChain', + params: [{ chainId: '0x61' }], + }) + ).rejects.toThrow( + 'Unrecognized chain ID "97". Try adding the chain using wallet_addEthereumChain first.' + ); + + await ethereum.request({ + method: 'wallet_addEthereumChain', + params: [ + { + chainId: '0x61', + rpcUrls: ['https://data-seed-prebsc-1-s1.binance.org:8545'], + }, + ], + }); + await ethereum.request({ + method: 'wallet_switchEthereumChain', + params: [{ chainId: '0x61' }], + }); + expect(ethereum.chainId).toBe('0x61'); + }); + + test('create sdk instance with switchableChains and switch to it', async () => { + const ethereum = new EthereumProvider({ + defaultChainId: '0xaa36a7', + switchableChains: [ + { + chainId: '0xaa36a7', + rpcUrls: ['https://ethereum-sepolia.blockpi.network/v1/rpc/public'], + }, + { + chainId: '0x61', + rpcUrls: ['https://data-seed-prebsc-1-s1.binance.org:8545'], + }, + ], + }); + await ethereum.request({ + method: 'wallet_switchEthereumChain', + params: [{ chainId: '0x61' }], + }); + expect(ethereum.chainId).toBe('0x61'); + }); + test('create sdk instance with switchableChains and call eth_accounts', async () => { + const ethereum = new EthereumProvider({ + defaultChainId: '0xaa36a7', + switchableChains: [ + { + chainId: '0xaa36a7', + rpcUrls: ['https://ethereum-sepolia.blockpi.network/v1/rpc/public'], + }, + { + chainId: '0x61', + rpcUrls: ['https://data-seed-prebsc-1-s1.binance.org:8545'], + }, + ], + }); + // Trigger the loading of switchable networks + await ethereum.request({ + method: 'eth_accounts', + }); + expect(ethereum.chainId).toBe('0xaa36a7'); + // should remove unloadedNetwork after loading + expect(ethereum['_blocto'].unloadedNetwork).toBeUndefined(); + }); + + test('should not call loadSwitchableNetwork if unloadedNetwork is empty', async () => { + const ethereum = new EthereumProvider({ + chainId: '0xaa36a7', + rpc: 'https://ethereum-sepolia.blockpi.network/v1/rpc/public', + }); + const loadSwitchableNetworkSpy = jest.spyOn(ethereum, 'loadSwitchableNetwork'); + + await ethereum.request({ method: 'eth_accounts' }); + + expect(loadSwitchableNetworkSpy).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/blocto-sdk/src/__tests__/fixtures/getEvmSupport.ts b/packages/blocto-sdk/src/__tests__/fixtures/getEvmSupport.ts new file mode 100644 index 00000000..97a6066e --- /dev/null +++ b/packages/blocto-sdk/src/__tests__/fixtures/getEvmSupport.ts @@ -0,0 +1,312 @@ +export const getEvmSupportList = { + '1': { + chain_id: 1, + name: 'ethereum', + display_name: 'Ethereum', + network_type: 'mainnet', + blocto_service_environment: 'prod', + rpc_endpoint_domains: [ + 'mainnet.infura.io', + 'rpc.ankr.com', + 'cloudflare-eth.com', + ], + }, + '5': { + chain_id: 5, + name: 'ethereum', + display_name: 'Goerli', + network_type: 'testnet', + blocto_service_environment: 'dev', + rpc_endpoint_domains: [ + 'goerli.infura.io', + 'goerli.blockpi.network', + 'rpc.ankr.com', + ], + }, + '10': { + chain_id: 10, + name: 'optimism', + display_name: 'Optimism', + network_type: 'mainnet', + blocto_service_environment: 'prod', + rpc_endpoint_domains: [ + 'optimism-mainnet.infura.io', + 'mainnet.optimism.io', + 'opt-mainnet.g.alchemy.com', + 'optimism.blockpi.network', + 'rpc.ankr.com', + ], + }, + '56': { + chain_id: 56, + name: 'bsc', + display_name: 'BNB Smart Chain', + network_type: 'mainnet', + blocto_service_environment: 'prod', + rpc_endpoint_domains: [ + 'bsc-dataseed.binance.org', + 'bsc-dataseed1.binance.org', + 'bsc-dataseed2.binance.org', + 'bsc-dataseed3.binance.org', + 'bsc-dataseed4.binance.org', + 'bsc-dataseed1.defibit.io', + 'bsc-dataseed2.defibit.io', + 'bsc-dataseed3.defibit.io', + 'bsc-dataseed4.defibit.io', + 'bsc-dataseed1.ninicoin.io', + 'bsc-dataseed2.ninicoin.io', + 'bsc-dataseed3.ninicoin.io', + 'bsc-dataseed4.ninicoin.io', + 'rpc.ankr.com', + ], + }, + '97': { + chain_id: 97, + name: 'bsc', + display_name: 'BNB Smart Chain Testnet', + network_type: 'testnet', + blocto_service_environment: 'dev', + rpc_endpoint_domains: [ + 'data-seed-prebsc-1-s1.binance.org', + 'data-seed-prebsc-2-s1.binance.org', + 'data-seed-prebsc-1-s2.binance.org', + 'data-seed-prebsc-2-s2.binance.org', + 'data-seed-prebsc-1-s3.binance.org', + 'data-seed-prebsc-2-s3.binance.org', + 'rpc.ankr.com', + ], + }, + '137': { + chain_id: 137, + name: 'polygon', + display_name: 'Polygon', + network_type: 'mainnet', + blocto_service_environment: 'prod', + rpc_endpoint_domains: [ + 'polygon-mainnet.infura.io', + 'rpc.ankr.com', + 'polygon-rpc.com', + 'rpc-mainnet.maticvigil.com', + ], + }, + '4200': { + chain_id: 4200, + name: 'merlin', + display_name: 'Merlin', + network_type: 'mainnet', + blocto_service_environment: 'prod', + rpc_endpoint_domains: ['rpc.merlinchain.io', 'merlin.blockpi.network'], + }, + '8453': { + chain_id: 8453, + name: 'base', + display_name: 'Base', + network_type: 'mainnet', + blocto_service_environment: 'prod', + rpc_endpoint_domains: [ + 'base-mainnet.infura.io', + 'base-mainnet.g.alchemy.com', + 'mainnet.base.org', + 'rpc.ankr.com', + 'base.blockpi.network', + '1rpc.io', + ], + }, + '42161': { + chain_id: 42161, + name: 'arbitrum', + display_name: 'Arbitrum', + network_type: 'mainnet', + blocto_service_environment: 'prod', + rpc_endpoint_domains: [ + 'arbitrum-mainnet.infura.io', + 'arb1.arbitrum.io', + 'arb-mainnet.g.alchemy.com', + 'arbitrum.blockpi.network', + 'rpc.ankr.com', + ], + }, + '43113': { + chain_id: 43113, + name: 'avalanche', + display_name: 'Avalanche Fuji', + network_type: 'testnet', + blocto_service_environment: 'dev', + rpc_endpoint_domains: [ + 'api.avax-test.network', + 'avalanche-fuji.infura.io', + 'rpc.ankr.com', + 'ava-testnet.public.blastapi.io', + ], + }, + '43114': { + chain_id: 43114, + name: 'avalanche', + display_name: 'Avalanche', + network_type: 'mainnet', + blocto_service_environment: 'prod', + rpc_endpoint_domains: [ + 'api.avax.network', + 'avalanche-mainnet.infura.io', + 'rpc.ankr.com', + 'ava-mainnet.public.blastapi.io', + 'snowtrace.io', + ], + }, + '80002': { + chain_id: 80002, + name: 'polygon_amoy', + display_name: 'Amoy Testnet', + network_type: 'testnet', + blocto_service_environment: 'dev', + rpc_endpoint_domains: ['rpc-amoy.polygon.technology', 'rpc.ankr.com'], + }, + '81457': { + chain_id: 81457, + name: 'blast', + display_name: 'Blast', + network_type: 'mainnet', + blocto_service_environment: 'prod', + rpc_endpoint_domains: [ + 'rpc.blast.io', + 'rpc.ankr.com', + 'blast.din.dev', + 'blastl2-mainnet.public.blastapi.io', + 'blast.blockpi.network', + ], + }, + '84532': { + chain_id: 84532, + name: 'base_sepolia', + display_name: 'Base Sepolia', + network_type: 'testnet', + blocto_service_environment: 'dev', + rpc_endpoint_domains: [ + 'sepolia.base.org', + 'base-sepolia.blockpi.network', + 'base-sepolia.g.alchemy.com', + 'base-sepolia.infura.io', + 'rpc.ankr.com', + '1rpc.io', + ], + }, + '421614': { + chain_id: 421614, + name: 'arbitrum_sepolia', + display_name: 'Arbitrum Sepolia', + network_type: 'testnet', + blocto_service_environment: 'dev', + rpc_endpoint_domains: [ + 'sepolia-rollup.arbitrum.io/rpc', + 'arbitrum-sepolia.infura.io', + 'arb-sepolia.g.alchemy.com', + 'rpc.ankr.com', + ], + }, + '534351': { + chain_id: 534351, + name: 'scroll_sepolia', + display_name: 'Scroll Sepolia', + network_type: 'testnet', + blocto_service_environment: 'dev', + rpc_endpoint_domains: [ + 'sepolia-rpc.scroll.io', + 'scroll-testnet-public.unifra.io', + 'scroll-sepolia.blockpi.network', + 'rpc.ankr.com', + 'scroll-sepolia.chainstacklabs.com', + 'scroll-public.scroll-testnet.quiknode.pro', + ], + }, + '534352': { + chain_id: 534352, + name: 'scroll', + display_name: 'Scroll', + network_type: 'mainnet', + blocto_service_environment: 'prod', + rpc_endpoint_domains: [ + 'rpc.scroll.io', + 'rpc.ankr.com', + 'rpc-scroll.icecreamswap.com', + 'scroll-mainnet.public.blastapi.io', + 'scroll-mainnet-public.unifra.io', + 'scroll.blockpi.network', + '1rpc.io', + 'scroll-mainnet.chainstacklabs.com', + ], + }, + '686868': { + chain_id: 686868, + name: 'merlin_testnet', + display_name: 'Merlin Testnet', + network_type: 'testnet', + blocto_service_environment: 'dev', + rpc_endpoint_domains: ['testnet-rpc.merlinchain.io'], + }, + '1261120': { + chain_id: 1261120, + name: 'zkatana_sepolia', + display_name: 'Astar zKatana', + network_type: 'testnet', + blocto_service_environment: 'dev', + rpc_endpoint_domains: [ + 'rpc.startale.com/zkatana', + 'rpc.zkatana.gelato.digital', + 'astar-zkatana-rpc.dwellir.com', + ], + }, + '7777777': { + chain_id: 7777777, + name: 'zora', + display_name: 'Zora', + network_type: 'mainnet', + blocto_service_environment: 'prod', + rpc_endpoint_domains: ['rpc.zora.energy'], + }, + '11155111': { + chain_id: 11155111, + name: 'ethereum_sepolia', + display_name: 'Sepolia', + network_type: 'testnet', + blocto_service_environment: 'dev', + rpc_endpoint_domains: [ + 'sepolia.infura.io', + 'rpc.sepolia.dev', + 'rpc.sepolia.org', + 'rpc.sepolia.online', + 'www.sepoliarpc.space', + 'rpc-sepolia.rockx.com', + 'rpc.bordel.wtf/sepolia', + ], + }, + '11155420': { + chain_id: 11155420, + name: 'optimism_sepolia', + display_name: 'Optimism Sepolia', + network_type: 'testnet', + blocto_service_environment: 'dev', + rpc_endpoint_domains: [ + 'optimism-sepolia.infura.io', + 'rpc.ankr.com', + 'sepolia.optimism.io', + 'opt-sepolia.g.alchemy.com', + 'optimism-sepolia.blockpi.network', + ], + }, + '168587773': { + chain_id: 168587773, + name: 'blast_sepolia', + display_name: 'Blast Sepolia', + network_type: 'testnet', + blocto_service_environment: 'dev', + rpc_endpoint_domains: ['sepolia.blast.io', 'blast-sepolia.blockpi.network'], + }, + '999999999': { + chain_id: 999999999, + name: 'zora_sepolia', + display_name: 'Zora Sepolia', + network_type: 'testnet', + blocto_service_environment: 'dev', + rpc_endpoint_domains: ['sepolia.rpc.zora.energy'], + }, +}; diff --git a/packages/blocto-sdk/src/__tests__/index.test.js b/packages/blocto-sdk/src/__tests__/index.test.js index 045f12b0..bd16ae9b 100644 --- a/packages/blocto-sdk/src/__tests__/index.test.js +++ b/packages/blocto-sdk/src/__tests__/index.test.js @@ -85,9 +85,15 @@ describe('Testing BloctoSDK ethereum provider', () => { expect(ethereum.rpc).toBe('https://bsc-dataseed.binance.org'); }); test('should setup _blocto', async () => { - await ethereum.loadSwitchableNetwork([ - { chainId: '0x5', rpcUrls: ['https://goerli.infura.io/v3/'] }, - ]); + await ethereum.request({ + method:"eth_addEthereumChain", + params: [ + { + chainId: '0xaa36a7', + rpcUrls: ['https://ethereum-sepolia.blockpi.network/v1/rpc/public'] + } + ] + }); expect(ethereum._blocto.networkType).toBe('mainnet'); }); test('should request chainId work', async () => { diff --git a/packages/blocto-sdk/src/providers/ethereum.ts b/packages/blocto-sdk/src/providers/ethereum.ts index e019fb06..2eadbb45 100644 --- a/packages/blocto-sdk/src/providers/ethereum.ts +++ b/packages/blocto-sdk/src/providers/ethereum.ts @@ -1040,7 +1040,23 @@ export default class EthereumProvider listener(ethErrors.provider.disconnected()) ); } - + /** + * @deprecated This method is deprecated and will be removed in future versions. + * Please use request({method: "wallet_addEthereumChain"}) instead to add new networks. + * + * @example + * // Instead of using loadSwitchableNetwork, use: + * await provider.request({ + * method: 'wallet_addEthereumChain', + * params: [{ + * chainId: '0xaa36a7', + * rpcUrls: ['https://ethereum-sepolia.blockpi.network/v1/rpc/public'], + * }] + * }); + * + * @param networkList - List of networks to add + * @returns Promise + */ async loadSwitchableNetwork( networkList: AddEthereumChainParameter[] ): Promise {