diff --git a/packages/sdk/package-lock.json b/packages/sdk/package-lock.json index fd9e0f261..6a9063ccf 100644 --- a/packages/sdk/package-lock.json +++ b/packages/sdk/package-lock.json @@ -18,7 +18,7 @@ "debug": "^4.3.4", "ethers": "^6.13.2", "graphql-request": "^6.0.0", - "iexec": "^8.14.0", + "iexec": "^8.16.0", "jszip": "^3.7.1", "kubo-rpc-client": "^4.1.1", "magic-bytes.js": "^1.0.15", @@ -5845,15 +5845,16 @@ ] }, "node_modules/iexec": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/iexec/-/iexec-8.14.0.tgz", - "integrity": "sha512-/MAXfEMgIR0642QjsO/qE+BsfvaCzyUrSaxP9THJUpIdPOkWDctUA/mxucI9/X34+zID05pXmpKFpgFnguck8Q==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/iexec/-/iexec-8.16.0.tgz", + "integrity": "sha512-cIg+hagscVfVjB/0fzGa3Xd3LJYtH9DxwBMqVTGy/l/wM4kfc/oKLYIuICqj9iR/7RjvoOw4o8DpBtzRClu4pg==", "license": "Apache-2.0", "dependencies": { "@ensdomains/ens-contracts": "^1.2.5", "@iexec/poco": "^5.5.0", "@iexec/voucher-contracts": "^1.0.0", "@multiformats/multiaddr": "^12.4.0", + "@types/bn.js": "^5.1.6", "bn.js": "^5.2.1", "buffer": "^6.0.3", "commander": "^13.1.0", diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 7c67c8dca..b81dfd290 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -61,7 +61,7 @@ "debug": "^4.3.4", "ethers": "^6.13.2", "graphql-request": "^6.0.0", - "iexec": "^8.14.0", + "iexec": "^8.16.0", "jszip": "^3.7.1", "kubo-rpc-client": "^4.1.1", "magic-bytes.js": "^1.0.15", diff --git a/packages/sdk/src/config/config.ts b/packages/sdk/src/config/config.ts index e34c1b518..96f5c793a 100644 --- a/packages/sdk/src/config/config.ts +++ b/packages/sdk/src/config/config.ts @@ -1,17 +1,18 @@ export type ChainId = number; export interface ChainConfig { - name: string; - dataprotectorContractAddress: string; - sharingContractAddress: string; - subgraphUrl: string; - ipfsGateway: string; - ipfsNode: string; - smsDebugURL: string; - workerpoolAddress: string; + name?: string; + dataprotectorContractAddress?: string; + sharingContractAddress?: string; + subgraphUrl?: string; + ipfsGateway?: string; + ipfsNode?: string; + smsDebugURL?: string; + workerpoolAddress?: string; + isExperimental?: boolean; } -export const CHAIN_CONFIG: Record = { +const CHAIN_CONFIG: Record = { // Bellecour 134: { name: 'bellecour', @@ -24,6 +25,30 @@ export const CHAIN_CONFIG: Record = { smsDebugURL: 'https://sms-debug.iex.ec', workerpoolAddress: 'prod-v8-bellecour.main.pools.iexec.eth', }, + // Arbitrum Sepolia + 421614: { + name: 'arbitrum-sepolia-testnet', + dataprotectorContractAddress: '0x2296daeDD3090750a80fFB2D0147669984909ED2', + sharingContractAddress: '0x2485Ed90d4566516298B7D01462df8d1A41E13AE', + subgraphUrl: + 'https://thegraph.arbitrum-sepolia-testnet.iex.ec/api/subgraphs/id/5YjRPLtjS6GH6bB4yY55Qg4HzwtRGQ8TaHtGf9UBWWd', + ipfsGateway: 'https://ipfs-gateway.arbitrum-sepolia-testnet.iex.ec', + ipfsNode: 'https://ipfs-upload.arbitrum-sepolia-testnet.iex.ec', + smsDebugURL: 'https://sms.arbitrum-sepolia-testnet.iex.ec', // ⚠️ default SMS is a debug SMS + workerpoolAddress: '0x39c3cdd91a7f1c4ed59108a9da4e79de9a1c1b59', + isExperimental: true, + }, +}; + +export const getChainConfig = ( + chainId: ChainId, + options?: { allowExperimentalNetworks?: boolean } +): ChainConfig => { + const config = CHAIN_CONFIG[chainId] || {}; + if (config?.isExperimental && !options?.allowExperimentalNetworks) { + return {}; + } + return config; }; export const DEFAULT_CHAIN_ID = 134; diff --git a/packages/sdk/src/lib/IExecDataProtectorModule.ts b/packages/sdk/src/lib/IExecDataProtectorModule.ts index df7716c86..80583860d 100644 --- a/packages/sdk/src/lib/IExecDataProtectorModule.ts +++ b/packages/sdk/src/lib/IExecDataProtectorModule.ts @@ -1,7 +1,10 @@ import { AbstractProvider, AbstractSigner, Eip1193Provider } from 'ethers'; import { GraphQLClient } from 'graphql-request'; import { IExec } from 'iexec'; -import { CHAIN_CONFIG, DEFAULT_ARWEAVE_UPLOAD_API } from '../config/config.js'; +import { + getChainConfig, + DEFAULT_ARWEAVE_UPLOAD_API, +} from '../config/config.js'; import { getChainIdFromProvider } from '../utils/getChainId.js'; import { AddressOrENS, @@ -78,7 +81,9 @@ abstract class IExecDataProtectorModule { private async resolveConfig(): Promise { const chainId = await getChainIdFromProvider(this.ethProvider); - const chainDefaultConfig = CHAIN_CONFIG[chainId]; + const chainDefaultConfig = getChainConfig(chainId, { + allowExperimentalNetworks: this.options.allowExperimentalNetworks, + }); const subgraphUrl = this.options?.subgraphUrl || chainDefaultConfig?.subgraphUrl; @@ -122,6 +127,7 @@ abstract class IExecDataProtectorModule { { ipfsGatewayURL: ipfsGateway, ...this.options?.iexecOptions, + allowExperimentalNetworks: this.options.allowExperimentalNetworks, } ); @@ -131,6 +137,7 @@ abstract class IExecDataProtectorModule { ipfsGatewayURL: ipfsGateway, ...this.options?.iexecOptions, smsURL, + allowExperimentalNetworks: this.options.allowExperimentalNetworks, } ); } catch (e: any) { diff --git a/packages/sdk/src/lib/types/commonTypes.ts b/packages/sdk/src/lib/types/commonTypes.ts index 319970a48..473e5797d 100644 --- a/packages/sdk/src/lib/types/commonTypes.ts +++ b/packages/sdk/src/lib/types/commonTypes.ts @@ -70,6 +70,13 @@ export type DataProtectorConfigOptions = { * If not provided, default iexec options will be used. */ iexecOptions?: IExecConfigOptionsExtended; + + /** + * if true allows using a provider connected to an experimental networks (default false) + * + * ⚠️ experimental networks are networks on which the iExec's stack is partially deployed, experimental networks can be subject to instabilities or discontinuity. Access is provided without warranties. + */ + allowExperimentalNetworks?: boolean; }; interface IExecConfigOptionsExtended extends IExecConfigOptions { diff --git a/packages/sdk/src/utils/getWeb3Provider.ts b/packages/sdk/src/utils/getWeb3Provider.ts index c5040ef6d..50427fc4f 100644 --- a/packages/sdk/src/utils/getWeb3Provider.ts +++ b/packages/sdk/src/utils/getWeb3Provider.ts @@ -1,5 +1,14 @@ import { getSignerFromPrivateKey } from 'iexec/utils'; +import { ChainId } from '../config/config.js'; import { Web3SignerProvider } from '../lib/types/index.js'; -export const getWeb3Provider = (privateKey: string): Web3SignerProvider => - getSignerFromPrivateKey('bellecour', privateKey); +export const getWeb3Provider = ( + privateKey: string, + options: { allowExperimentalNetworks?: boolean; host?: ChainId | string } = {} +): Web3SignerProvider => { + const chainHost = options?.host ? `${options.host}` : 'bellecour'; + return getSignerFromPrivateKey(chainHost, privateKey, { + allowExperimentalNetworks: options?.allowExperimentalNetworks, + providers: {}, + }); +}; diff --git a/packages/sdk/tests/e2e/dataProtectorSharing/addAppToAppWhitelist.test.ts b/packages/sdk/tests/e2e/dataProtectorSharing/addAppToAppWhitelist.test.ts index 4ef82c6e8..6be0b0803 100644 --- a/packages/sdk/tests/e2e/dataProtectorSharing/addAppToAppWhitelist.test.ts +++ b/packages/sdk/tests/e2e/dataProtectorSharing/addAppToAppWhitelist.test.ts @@ -1,7 +1,7 @@ import { HDNodeWallet, Wallet } from 'ethers'; import { Address, IExec } from 'iexec'; import { ValidationError } from 'yup'; -import { CHAIN_CONFIG } from '../../../src/config/config.js'; +import { getChainConfig } from '../../../src/config/config.js'; import { IExecDataProtector } from '../../../src/index.js'; import { getTestConfig, @@ -38,7 +38,7 @@ describe('dataProtector.addAppToAddOnlyAppWhitelist()', () => { appWhitelistAddress = createAppWhitelistResponse.addOnlyAppWhitelist; appAddress = await createAppFor( wallet, - CHAIN_CONFIG['134'].sharingContractAddress + getChainConfig(134).sharingContractAddress ); }, timeouts.createAddOnlyAppWhitelist + timeouts.createAppInPocoRegistry); diff --git a/packages/sdk/tests/e2e/dataProtectorSharing/addToCollection.test.ts b/packages/sdk/tests/e2e/dataProtectorSharing/addToCollection.test.ts index 65bdc5de8..d1b88ef76 100644 --- a/packages/sdk/tests/e2e/dataProtectorSharing/addToCollection.test.ts +++ b/packages/sdk/tests/e2e/dataProtectorSharing/addToCollection.test.ts @@ -1,7 +1,7 @@ import { beforeAll, describe, expect, it, jest } from '@jest/globals'; import { type HDNodeWallet, Wallet } from 'ethers'; import { IExec } from 'iexec'; -import { CHAIN_CONFIG } from '../../../src/config/config.js'; +import { getChainConfig } from '../../../src/config/config.js'; import { IExecDataProtector } from '../../../src/index.js'; import { approveProtectedDataForCollectionContract } from '../../../src/lib/dataProtectorSharing/smartContract/approveProtectedDataForCollectionContract.js'; import { getTestConfig, timeouts } from '../../test-utils.js'; @@ -76,7 +76,7 @@ describe('dataProtector.addToCollection()', () => { await approveProtectedDataForCollectionContract({ iexec, protectedData, - sharingContractAddress: CHAIN_CONFIG['134'].sharingContractAddress, + sharingContractAddress: getChainConfig(134).sharingContractAddress, }); // --- WHEN diff --git a/packages/sdk/tests/e2e/dataProtectorSharing/buyProtectedData.test.ts b/packages/sdk/tests/e2e/dataProtectorSharing/buyProtectedData.test.ts index 3ab88150a..752ddd0c2 100644 --- a/packages/sdk/tests/e2e/dataProtectorSharing/buyProtectedData.test.ts +++ b/packages/sdk/tests/e2e/dataProtectorSharing/buyProtectedData.test.ts @@ -1,7 +1,7 @@ import { beforeAll, describe, expect, it } from '@jest/globals'; import { Wallet, type HDNodeWallet } from 'ethers'; import { ValidationError } from 'yup'; -import { CHAIN_CONFIG } from '../../../src/config/config.js'; +import { getChainConfig } from '../../../src/config/config.js'; import { IExecDataProtector } from '../../../src/index.js'; import { approveAccount, @@ -104,7 +104,7 @@ describe('dataProtector.buyProtectedData()', () => { await depositNRlcForAccount(buyer.address, price); await approveAccount( buyer.privateKey, - CHAIN_CONFIG['134'].sharingContractAddress, + getChainConfig(134).sharingContractAddress, price ); diff --git a/packages/sdk/tests/e2e/dataProtectorSharing/rentProtectedData.test.ts b/packages/sdk/tests/e2e/dataProtectorSharing/rentProtectedData.test.ts index 5f11c6ca2..1a5912421 100644 --- a/packages/sdk/tests/e2e/dataProtectorSharing/rentProtectedData.test.ts +++ b/packages/sdk/tests/e2e/dataProtectorSharing/rentProtectedData.test.ts @@ -1,6 +1,6 @@ import { beforeAll, describe, expect, it } from '@jest/globals'; import { HDNodeWallet, Wallet } from 'ethers'; -import { CHAIN_CONFIG } from '../../../src/config/config.js'; +import { getChainConfig } from '../../../src/config/config.js'; import { IExecDataProtector } from '../../../src/index.js'; import { approveAccount, @@ -154,7 +154,7 @@ describe('dataProtector.rentProtectedData()', () => { ); await approveAccount( walletEndUser.privateKey, - CHAIN_CONFIG['134'].sharingContractAddress, + getChainConfig(134).sharingContractAddress, rentingParams.price ); diff --git a/packages/sdk/tests/e2e/dataProtectorSharing/subscribeToCollection.test.ts b/packages/sdk/tests/e2e/dataProtectorSharing/subscribeToCollection.test.ts index bc4bfaee0..db20411f4 100644 --- a/packages/sdk/tests/e2e/dataProtectorSharing/subscribeToCollection.test.ts +++ b/packages/sdk/tests/e2e/dataProtectorSharing/subscribeToCollection.test.ts @@ -1,6 +1,6 @@ import { beforeAll, describe, expect, it } from '@jest/globals'; import { HDNodeWallet, Wallet } from 'ethers'; -import { CHAIN_CONFIG } from '../../../src/config/config.js'; +import { getChainConfig } from '../../../src/config/config.js'; import { IExecDataProtector } from '../../../src/index.js'; import { approveAccount, @@ -107,7 +107,7 @@ describe('dataProtector.subscribeToCollection()', () => { ); await approveAccount( walletEndUser.privateKey, - CHAIN_CONFIG['134'].sharingContractAddress, + getChainConfig(134).sharingContractAddress, subscriptionParams.price ); diff --git a/packages/sdk/tests/test-utils.ts b/packages/sdk/tests/test-utils.ts index 3446dd09a..97e960462 100644 --- a/packages/sdk/tests/test-utils.ts +++ b/packages/sdk/tests/test-utils.ts @@ -109,7 +109,7 @@ export const MAX_EXPECTED_MARKET_API_PURGE_TIME = 5_000; export const MAX_EXPECTED_WEB2_SERVICES_TIME = 80_000; -const SUBGRAPH_CALL_TIMEOUT = 2_000; +const SUBGRAPH_CALL_TIMEOUT = 5_000; const SMART_CONTRACT_CALL_TIMEOUT = 10_000; const ONE_SMART_CONTRACT_WRITE_CALL = diff --git a/packages/sdk/tests/unit/constructor.test.ts b/packages/sdk/tests/unit/constructor.test.ts index 36e3a5cd6..7a070faf3 100644 --- a/packages/sdk/tests/unit/constructor.test.ts +++ b/packages/sdk/tests/unit/constructor.test.ts @@ -2,7 +2,7 @@ // needed to access and assert IExecDataProtector's private properties import { describe, it, expect } from '@jest/globals'; import { Wallet } from 'ethers'; -import { CHAIN_CONFIG } from '../../src/config/config.js'; +import { getChainConfig } from '../../src/config/config.js'; import { IExecDataProtector, getWeb3Provider } from '../../src/index.js'; describe('IExecDataProtector()', () => { @@ -12,7 +12,7 @@ describe('IExecDataProtector()', () => { ); await dataProtector['init'](); const ipfsNode = dataProtector['ipfsNode']; - expect(ipfsNode).toStrictEqual(CHAIN_CONFIG['134'].ipfsNode); + expect(ipfsNode).toStrictEqual(getChainConfig(134).ipfsNode); }); it('should use provided ipfs node url when ipfsNode is provided', async () => { @@ -34,7 +34,7 @@ describe('IExecDataProtector()', () => { ); await dataProtector['init'](); const ipfsGateway = dataProtector['ipfsGateway']; - expect(ipfsGateway).toStrictEqual(CHAIN_CONFIG['134'].ipfsGateway); + expect(ipfsGateway).toStrictEqual(getChainConfig(134).ipfsGateway); }); it('should use default ipfs gateway url when ipfsGateway is provided', async () => { @@ -58,7 +58,7 @@ describe('IExecDataProtector()', () => { const dataprotectorContractAddress = dataProtector['dataprotectorContractAddress']; expect(dataprotectorContractAddress).toStrictEqual( - CHAIN_CONFIG['134'].dataprotectorContractAddress + getChainConfig(134).dataprotectorContractAddress ); }); @@ -84,7 +84,7 @@ describe('IExecDataProtector()', () => { ); await dataProtector['init'](); const graphQLClientUrl = dataProtector['graphQLClient']; - expect(graphQLClientUrl['url']).toBe(CHAIN_CONFIG['134'].subgraphUrl); + expect(graphQLClientUrl['url']).toBe(getChainConfig(134).subgraphUrl); }); it('should use provided subgraph URL when subgraphUrl is provided', async () => { @@ -188,4 +188,43 @@ describe('IExecDataProtector()', () => { }); }); }); + + describe('When instantiating SDK with an experimental network', () => { + const experimentalNetworkSigner = getWeb3Provider( + Wallet.createRandom().privateKey, + { + host: 421614, + allowExperimentalNetworks: true, + } + ); + + describe('Without allowExperimentalNetworks', () => { + it('should throw a configuration error', async () => { + const dataProtector = new IExecDataProtector(experimentalNetworkSigner); + await expect(dataProtector['init']()).rejects.toThrow( + 'Missing required configuration for chainId 421614: subgraphUrl, dataprotectorContractAddress, sharingContractAddress, ipfsGateway, defaultWorkerpool, ipfsNode, smsDebugURL' + ); + }); + }); + + describe('With allowExperimentalNetworks: true', () => { + it('should resolve the configuration', async () => { + const dataProtector = new IExecDataProtector( + experimentalNetworkSigner, + { allowExperimentalNetworks: true } + ); + await expect(dataProtector['init']()).resolves.toBeUndefined(); + expect(dataProtector['arweaveUploadApi']).toBeDefined(); + expect(dataProtector['dataprotectorContractAddress']).toBeDefined(); + expect(dataProtector['defaultWorkerpool']).toBeDefined(); + expect(dataProtector['ethProvider']).toBeDefined(); + expect(dataProtector['graphQLClient']).toBeDefined(); + expect(dataProtector['iexec']).toBeDefined(); + expect(dataProtector['iexecDebug']).toBeDefined(); + expect(dataProtector['ipfsGateway']).toBeDefined(); + expect(dataProtector['ipfsNode']).toBeDefined(); + expect(dataProtector['sharingContractAddress']).toBeDefined(); + }); + }); + }); }); diff --git a/packages/sdk/tests/unit/dataProtectorCore/protectData.test.ts b/packages/sdk/tests/unit/dataProtectorCore/protectData.test.ts index 30b0251bc..7b4067769 100644 --- a/packages/sdk/tests/unit/dataProtectorCore/protectData.test.ts +++ b/packages/sdk/tests/unit/dataProtectorCore/protectData.test.ts @@ -3,7 +3,7 @@ import path from 'path'; import { beforeEach, describe, expect, it, jest } from '@jest/globals'; import { Wallet, HDNodeWallet, Contract } from 'ethers'; import { IExec, utils } from 'iexec'; -import { CHAIN_CONFIG } from '../../../src/config/config.js'; +import { getChainConfig } from '../../../src/config/config.js'; import { type ProtectData } from '../../../src/lib/dataProtectorCore/protectData.js'; import { ValidationError, WorkflowError } from '../../../src/utils/errors.js'; import { getRandomAddress } from '../../test-utils.js'; @@ -36,9 +36,9 @@ jest.unstable_mockModule('../../../src/utils/getEventFromLogs.js', () => ({ })); const protectDataDefaultArgs = { - contractAddress: CHAIN_CONFIG['134'].dataprotectorContractAddress, - ipfsNode: CHAIN_CONFIG['134'].ipfsNode, - ipfsGateway: CHAIN_CONFIG['134'].ipfsGateway, + contractAddress: getChainConfig(134).dataprotectorContractAddress, + ipfsNode: getChainConfig(134).ipfsNode, + ipfsGateway: getChainConfig(134).ipfsGateway, }; describe('protectData()', () => { diff --git a/packages/sdk/tests/unit/dataProtectorSharing/consumeProtectedData.test.ts b/packages/sdk/tests/unit/dataProtectorSharing/consumeProtectedData.test.ts index b9b4119cc..86e208587 100644 --- a/packages/sdk/tests/unit/dataProtectorSharing/consumeProtectedData.test.ts +++ b/packages/sdk/tests/unit/dataProtectorSharing/consumeProtectedData.test.ts @@ -1,8 +1,8 @@ import { describe, expect, it } from '@jest/globals'; import { ValidationError } from 'yup'; +import { getChainConfig } from '../../../src/config/config.js'; import { consumeProtectedData } from '../../../src/lib/dataProtectorSharing/consumeProtectedData.js'; import { getRandomAddress, getRequiredFieldMessage } from '../../test-utils.js'; -import { CHAIN_CONFIG } from '../../../src/config/config.js'; describe('consumeProtectedData', () => { describe('Check validation for input parameters', () => { @@ -14,7 +14,7 @@ describe('consumeProtectedData', () => { consumeProtectedData({ // @ts-expect-error No need for iexec here iexec: {}, - sharingContractAddress: CHAIN_CONFIG['134'].sharingContractAddress, + sharingContractAddress: getChainConfig(134).sharingContractAddress, protectedData: missingProtectedData, app: getRandomAddress(), }) @@ -32,7 +32,7 @@ describe('consumeProtectedData', () => { consumeProtectedData({ // @ts-expect-error No need for iexec here iexec: {}, - sharingContractAddress: CHAIN_CONFIG['134'].sharingContractAddress, + sharingContractAddress: getChainConfig(134).sharingContractAddress, protectedData: invalidProtectedData, app: getRandomAddress(), }) @@ -52,7 +52,7 @@ describe('consumeProtectedData', () => { consumeProtectedData({ // @ts-expect-error No need for iexec here iexec: {}, - sharingContractAddress: CHAIN_CONFIG['134'].sharingContractAddress, + sharingContractAddress: getChainConfig(134).sharingContractAddress, protectedData: getRandomAddress(), app: missingAppAddress, }) @@ -68,7 +68,7 @@ describe('consumeProtectedData', () => { consumeProtectedData({ // @ts-expect-error No need for iexec here iexec: {}, - sharingContractAddress: CHAIN_CONFIG['134'].sharingContractAddress, + sharingContractAddress: getChainConfig(134).sharingContractAddress, protectedData: getRandomAddress(), app: invalidAppAddress, }) @@ -86,7 +86,7 @@ describe('consumeProtectedData', () => { consumeProtectedData({ // @ts-expect-error No need for iexec here iexec: {}, - sharingContractAddress: CHAIN_CONFIG['134'].sharingContractAddress, + sharingContractAddress: getChainConfig(134).sharingContractAddress, protectedData: getRandomAddress(), app: getRandomAddress(), maxPrice: invalidMaxPrice, @@ -105,7 +105,7 @@ describe('consumeProtectedData', () => { consumeProtectedData({ // @ts-expect-error No need for iexec here iexec: {}, - sharingContractAddress: CHAIN_CONFIG['134'].sharingContractAddress, + sharingContractAddress: getChainConfig(134).sharingContractAddress, protectedData: getRandomAddress(), app: getRandomAddress(), // @ts-expect-error Type 'number' is not assignable to type 'string' diff --git a/packages/sdk/tests/unit/getWeb3Provider.test.ts b/packages/sdk/tests/unit/getWeb3Provider.test.ts new file mode 100644 index 000000000..ae0c85dfc --- /dev/null +++ b/packages/sdk/tests/unit/getWeb3Provider.test.ts @@ -0,0 +1,53 @@ +import { describe, it, expect } from '@jest/globals'; +import { Wallet } from 'ethers'; +import { getWeb3Provider } from '../../src/index.js'; + +describe('getWeb3Provider()', () => { + const { privateKey, address } = Wallet.createRandom(); + it('should use the wallet', async () => { + const provider = getWeb3Provider(privateKey); + const providerAddress = await provider.getAddress(); + expect(providerAddress).toBe(address); + }); + + it('should use bellecour by default', async () => { + const provider = getWeb3Provider(privateKey); + const network = await provider.provider.getNetwork(); + expect(network.name).toBe('bellecour'); + }); + + it('should accept RPC URL as host', () => { + expect( + getWeb3Provider(privateKey, { host: 'https://bellecour.iex.ec' }) + ).toBeDefined(); + }); + + it('should accept chainId as host', () => { + expect(getWeb3Provider(privateKey, { host: 134 })).toBeDefined(); + }); + + it('should accept chain name as host', () => { + expect(getWeb3Provider(privateKey, { host: 'bellecour' })).toBeDefined(); + }); + + describe('When instantiating SDK with an experimental network', () => { + describe('Without allowExperimentalNetworks', () => { + it('should throw a configuration error', () => { + expect(() => + getWeb3Provider(privateKey, { host: 'arbitrum-sepolia-testnet' }) + ).toThrow('Invalid provider host name or url'); + }); + }); + + describe('With allowExperimentalNetworks: true', () => { + it('should use the specified network', async () => { + const provider = getWeb3Provider(privateKey, { + host: 'arbitrum-sepolia-testnet', + allowExperimentalNetworks: true, + }); + const network = await provider.provider.getNetwork(); + expect(network.name).toBe('arbitrum-sepolia'); + }); + }); + }); +});