diff --git a/.changeset/cold-eggs-film.md b/.changeset/cold-eggs-film.md new file mode 100644 index 00000000..5ebd45f4 --- /dev/null +++ b/.changeset/cold-eggs-film.md @@ -0,0 +1,6 @@ +--- +'@blocto/sdk': patch +--- + +fix story tesnet url, fix multiple chain setting, update polygon url + diff --git a/.changeset/pre.json b/.changeset/pre.json index 2208367f..cd19cf99 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -2,18 +2,19 @@ "mode": "exit", "tag": "beta", "initialVersions": { - "@blocto/aptos-wallet-adapter-plugin": "0.2.10", + "@blocto/aptos-wallet-adapter-plugin": "0.2.11-beta.0", "@blocto/connectkit-connector": "0.2.3", - "@blocto/rainbowkit-connector": "2.0.2", - "@blocto/wagmi-connector": "2.0.4", - "@blocto/web3-react-connector": "1.0.8", + "@blocto/rainbowkit-connector": "2.0.3-beta.0", + "@blocto/wagmi-connector": "2.0.5-beta.0", + "@blocto/web3-react-connector": "1.0.9-beta.0", "@blocto/web3modal-connector": "0.1.4", - "@blocto/sdk": "0.10.3", + "@blocto/sdk": "0.10.4-beta.1", "@blocto/dappauth": "2.2.2", "eslint-config-custom": "0.0.0", "tsconfig": "0.0.0" }, "changesets": [ - "nasty-cats-greet" + "nasty-cats-greet", + "yellow-rockets-judge" ] } diff --git a/.changeset/yellow-rockets-judge.md b/.changeset/yellow-rockets-judge.md new file mode 100644 index 00000000..dde02575 --- /dev/null +++ b/.changeset/yellow-rockets-judge.md @@ -0,0 +1,5 @@ +--- +'@blocto/sdk': patch +--- + +fix multiple chain setting diff --git a/packages/blocto-sdk/CHANGELOG.md b/packages/blocto-sdk/CHANGELOG.md index 73165fd6..3923f866 100644 --- a/packages/blocto-sdk/CHANGELOG.md +++ b/packages/blocto-sdk/CHANGELOG.md @@ -1,5 +1,11 @@ # @blocto/sdk +## 0.10.4-beta.1 + +### Patch Changes + +- 2e2164e: fix multiple chain setting + ## 0.10.4-beta.0 ### Patch Changes diff --git a/packages/blocto-sdk/jest.config.cjs b/packages/blocto-sdk/jest.config.cjs index 0513f8c4..8811ab71 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/', '\\.d\\.ts$'], automock: false, resetMocks: false, }; diff --git a/packages/blocto-sdk/package.json b/packages/blocto-sdk/package.json index 4b5d601a..568fda8c 100644 --- a/packages/blocto-sdk/package.json +++ b/packages/blocto-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@blocto/sdk", - "version": "0.10.4-beta.0", + "version": "0.10.4-beta.1", "repository": "git@github.com:portto/blocto-sdk.git", "author": "Chiaki.C", "license": "MIT", 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/constants.ts b/packages/blocto-sdk/src/constants.ts index 5cf414e9..b9880cfb 100644 --- a/packages/blocto-sdk/src/constants.ts +++ b/packages/blocto-sdk/src/constants.ts @@ -26,7 +26,7 @@ export const ETH_RPC_LIST: Mapping = { 97: 'https://data-seed-prebsc-1-s1.binance.org:8545', // Polygon Mainnet - 137: 'https://rpc-mainnet.maticvigil.com/', + 137: 'https://polygon-rpc.com/', // Polygon Amoy Testnet 80002: 'https://rpc-amoy.polygon.technology/', @@ -77,7 +77,7 @@ export const ETH_RPC_LIST: Mapping = { 686868: 'https://testnet-rpc.merlinchain.io', // Story Testnet - 1513: 'https://testnet.storyrpc.io/', + 1513: 'https://testnet.storyrpc.io', }; export const ETH_ENV_WALLET_SERVER_MAPPING: Mapping = { diff --git a/packages/blocto-sdk/src/providers/ethereum.ts b/packages/blocto-sdk/src/providers/ethereum.ts index 3f95e2c2..76edcb38 100644 --- a/packages/blocto-sdk/src/providers/ethereum.ts +++ b/packages/blocto-sdk/src/providers/ethereum.ts @@ -180,7 +180,6 @@ export default class EthereumProvider chainId: `${number}`; rpcUrls: string[]; }): Promise { - await this.#getBloctoProperties(); const supportNetworkList = await getEvmSupport().catch((e) => { throw ethErrors.provider.custom({ code: 1001, @@ -1041,7 +1040,23 @@ export default class EthereumProvider listener(ethErrors.provider.disconnected()) ); } - + /** + * @internal This method is internal 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 {