diff --git a/packages/provider/src/provider.ts b/packages/provider/src/provider.ts index 2479c70a8..0287622d8 100644 --- a/packages/provider/src/provider.ts +++ b/packages/provider/src/provider.ts @@ -64,14 +64,9 @@ export class Web3Provider extends providers.Web3Provider implements JsonRpcHandl } async getChainId(): Promise { - // If the dapp is asking for a particular default chain, then we first need to see - // if the wallet supports the network, for that we need to query the wallet networks - // and see if it contains the default chain. If it does, then we can return the default. - if (this._defaultChainId) { - const networks = await this.getNetworks() - if (networks.find((n) => n.chainId === this._defaultChainId)) return this._defaultChainId - throw new Error(`Default chainId ${this._defaultChainId} not supported by wallet`) - } + // If we already have a default chainId, then we can just return it + const defaultChainId = this._defaultChainId + if (defaultChainId) return defaultChainId // If there is no default chain, then we can just return the chainId of the provider return this.send('eth_chainId', []) diff --git a/packages/provider/src/transports/base-wallet-transport.ts b/packages/provider/src/transports/base-wallet-transport.ts index c4c49cedd..cac2939a1 100644 --- a/packages/provider/src/transports/base-wallet-transport.ts +++ b/packages/provider/src/transports/base-wallet-transport.ts @@ -385,9 +385,10 @@ export abstract class BaseWalletTransport implements WalletTransport { let chainId: number | undefined = undefined try { if (networkId) { - chainId = this.walletRequestHandler.setDefaultNetwork(networkId) + const networkIdNumber = ethers.BigNumber.from(networkId).toNumber() + chainId = await this.walletRequestHandler.setDefaultChainId(networkIdNumber) } else { - chainId = this.walletRequestHandler.defaultNetworkId + chainId = this.walletRequestHandler.defaultChainId() } } catch (err) { console.error(err) @@ -422,9 +423,10 @@ export abstract class BaseWalletTransport implements WalletTransport { let chainId: number | undefined = undefined try { if (networkId) { - chainId = this.walletRequestHandler.setDefaultNetwork(networkId) + const networkIdNumber = ethers.BigNumber.from(networkId).toNumber() + chainId = await this.walletRequestHandler.setDefaultChainId(networkIdNumber) } else { - chainId = this.walletRequestHandler.defaultNetworkId + chainId = this.walletRequestHandler.defaultChainId() } } catch (err) { console.error(err) diff --git a/packages/provider/src/transports/wallet-request-handler.ts b/packages/provider/src/transports/wallet-request-handler.ts index 7c97ba5b1..dee357dd1 100644 --- a/packages/provider/src/transports/wallet-request-handler.ts +++ b/packages/provider/src/transports/wallet-request-handler.ts @@ -30,8 +30,7 @@ const SIGNER_READY_TIMEOUT = 10000 export interface WalletSignInOptions { connect?: boolean - networks?: NetworkConfig[] - defaultNetworkId?: string | number + defaultNetworkId?: number } export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, ProviderMessageRequestHandler { @@ -51,19 +50,18 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P onConnectOptionsChange: ((connectOptions: ConnectOptions | undefined) => void) | undefined = undefined - public defaultNetworkId: number - constructor( account: Account | null | undefined, prompter: WalletUserPrompter | null, - networks: NetworkConfig[], - defaultNetworkId?: string | number + networks: NetworkConfig[] ) { this.account = account this.prompter = prompter this.networks = networks + } - this.defaultNetworkId = defaultNetworkId ? this.findNetworkID(defaultNetworkId) : networks[0].chainId + defaultChainId(): number { + return this.prompter?.getDefaultChainId() ?? this.networks[0].chainId } private findNetworkID(network: string | number) { @@ -82,14 +80,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P async signIn(account: Account | null, options: WalletSignInOptions = {}) { this.setAccount(account) - const { connect, networks, defaultNetworkId } = options - - if (networks !== undefined && networks.length > 0) { - const networkId = defaultNetworkId || this.defaultNetworkId - if (networkId) { - this.setDefaultNetwork(networkId) - } - } + const { connect, defaultNetworkId } = options // Optionally, connect the dapp and wallet. In case connectOptions are provided, we will perform // necessary auth request, and then notify the dapp of the 'connect' details. @@ -117,6 +108,10 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P this.notifyClose() } } + + if (defaultNetworkId && this.defaultChainId() !== defaultNetworkId) { + await this.prompter?.promptChangeNetwork(defaultNetworkId) + } } signOut() { @@ -155,7 +150,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P } } - let chainId: number + let chainId: number | string switch (typeof options?.networkId) { case 'string': // First see if it matches the name of a network @@ -171,7 +166,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P chainId = options.networkId break default: - chainId = this.defaultNetworkId + chainId = this.prompter?.getDefaultChainId() ?? 1 break } @@ -280,7 +275,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P if (!account) throw new Error('WalletRequestHandler: wallet account is not configured') // fetch the provider for the specific chain, or undefined will select defaultChain - const provider = this.account?.provider(chainId ?? this.defaultNetworkId) + const provider = this.account?.provider(chainId ?? this.defaultChainId()) if (!provider) throw new Error(`WalletRequestHandler: wallet provider is not configured for chainId ${chainId}`) const jsonRpcProvider = provider instanceof ethers.providers.JsonRpcProvider ? provider : undefined @@ -351,7 +346,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P // if (process.env.TEST_MODE === 'true' && this.prompter === null) { if (this.prompter === null) { // prompter is null, so we'll sign from here - sig = await account.signMessage(prefixedMessage, chainId ?? this.defaultNetworkId) + sig = await account.signMessage(prefixedMessage, chainId ?? this.defaultChainId()) } else { const promptResultForDeployment = request.method === 'sequence_sign' || await this.handleConfirmWalletDeployPrompt(this.prompter, account, chainId) if (promptResultForDeployment) { @@ -392,7 +387,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P if (this.prompter === null) { // prompter is null, so we'll sign from here - sig = await account.signTypedData(typedData.domain, typedData.types, typedData.message, chainId ?? this.defaultNetworkId) + sig = await account.signTypedData(typedData.domain, typedData.types, typedData.message, chainId ?? this.defaultChainId()) } else { const promptResultForDeployment = request.method === 'sequence_signTypedData_v4' || await this.handleConfirmWalletDeployPrompt(this.prompter, account, chainId) if (promptResultForDeployment) { @@ -426,7 +421,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P let txnHash = '' if (this.prompter === null) { // prompter is null, so we'll send from here - const txnResponse = await account.sendTransaction(transactionParams, chainId ?? this.defaultNetworkId) + const txnResponse = await account.sendTransaction(transactionParams, chainId ?? this.defaultChainId()) txnHash = txnResponse.hash } else { // prompt user to provide the response @@ -457,7 +452,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P // // TODO: verify serializing / transporting the SignedTransaction object works as expected, most likely however // we will want to resolveProperties the big number values to hex strings - response.result = await account.signTransactions(transaction, chainId ?? this.defaultNetworkId) + response.result = await account.signTransactions(transaction, chainId ?? this.defaultChainId()) } else { response.result = await this.prompter.promptSignTransaction(transaction, chainId, this.connectOptions) } @@ -546,7 +541,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P const chainId = ethers.BigNumber.from(switchParams.chainId) - this.setDefaultNetwork(chainId.toString()) + this.setDefaultChainId(chainId.toNumber()) response.result = null // success break @@ -639,13 +634,13 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P // set default network of wallet case 'sequence_setDefaultNetwork': { - const [defaultNetworkId] = request.params! + const [defaultChainId] = request.params! - if (!defaultNetworkId) { - throw new Error('invalid request, method argument defaultNetworkId cannot be empty') + if (!defaultChainId) { + throw new Error('invalid request, method argument defaultChainId cannot be empty') } - this.setDefaultNetwork(defaultNetworkId) + this.setDefaultChainId(defaultChainId) response.result = await this.getNetworks(true) break } @@ -704,9 +699,9 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P this.onConnectOptionsChange?.(options) } - setDefaultNetwork(chainId: string | number): number { - this.defaultNetworkId = this.findNetworkID(chainId) - return this.defaultNetworkId + async setDefaultChainId(chainId: number): Promise { + await this.prompter?.promptChangeNetwork(chainId) + return this.defaultChainId() } async getNetworks(jsonRpcResponse?: boolean): Promise { @@ -754,7 +749,7 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P const n = networks || (await this.getNetworks(true)) this.events.emit('networks', n) if (n.length > 0) { - const defaultNetwork = n.find(network => network.chainId === this.defaultNetworkId) + const defaultNetwork = n.find(network => network.chainId === this.defaultChainId()) if (defaultNetwork) { this.events.emit('chainChanged', ethers.utils.hexlify(defaultNetwork.chainId)) } @@ -831,6 +826,8 @@ export class WalletRequestHandler implements ExternalProvider, JsonRpcHandler, P } export interface WalletUserPrompter { + getDefaultChainId(): number + promptConnect(options?: ConnectOptions): Promise promptSignInConnect(options?: ConnectOptions): Promise @@ -838,6 +835,8 @@ export interface WalletUserPrompter { promptSignTransaction(txn: commons.transaction.Transactionish, chainId?: number, options?: ConnectOptions): Promise promptSendTransaction(txn: commons.transaction.Transactionish, chainId?: number, options?: ConnectOptions): Promise promptConfirmWalletDeploy(chainId: number, options?: ConnectOptions): Promise + + promptChangeNetwork(chainId: number): Promise } interface LegacyWalletState {