From b05345b21d3f5c01d5fdb0462ed7e5fbe19a2331 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 1 Nov 2023 11:25:51 -0400 Subject: [PATCH] fix metamask sendtransaction (#6540) * add metamask check * format and update changelog * fix lint * add metamask logic to request manager * add payload batch request and lint * fix deploy --- packages/web3-core/CHANGELOG.md | 4 +++ packages/web3-core/src/utils.ts | 12 +++++-- .../web3-core/src/web3_request_manager.ts | 36 +++++++++++++++++-- packages/web3-eth-contract/CHANGELOG.md | 2 ++ packages/web3-eth-contract/src/contract.ts | 1 + packages/web3-types/CHANGELOG.md | 2 ++ packages/web3-types/src/web3_base_provider.ts | 20 ++++++++++- 7 files changed, 71 insertions(+), 6 deletions(-) diff --git a/packages/web3-core/CHANGELOG.md b/packages/web3-core/CHANGELOG.md index 2075f77082d..902c754b7f5 100644 --- a/packages/web3-core/CHANGELOG.md +++ b/packages/web3-core/CHANGELOG.md @@ -192,3 +192,7 @@ Documentation: - Fix the issue: "Uncaught TypeError: Class extends value undefined is not a constructor or null #6371". (#6398) ## [Unreleased] + +### Added + +- Added `isMetaMaskProvider` function to check if provider is metamask (#6534) \ No newline at end of file diff --git a/packages/web3-core/src/utils.ts b/packages/web3-core/src/utils.ts index e5b30f0db83..34c5162c488 100644 --- a/packages/web3-core/src/utils.ts +++ b/packages/web3-core/src/utils.ts @@ -23,12 +23,21 @@ import { SupportedProviders, Web3APISpec, Web3BaseProvider, + MetaMaskProvider, } from 'web3-types'; export const isWeb3Provider = ( provider: SupportedProviders, ): provider is Web3BaseProvider => Web3BaseProvider.isWeb3Provider(provider); +export const isMetaMaskProvider = ( + provider: SupportedProviders, +): provider is MetaMaskProvider => + typeof provider !== 'string' && +'request' in provider && +provider.request.constructor.name === 'AsyncFunction' && 'isMetaMask' in provider && provider.isMetaMask; + + export const isLegacyRequestProvider = ( provider: SupportedProviders, ): provider is LegacyRequestProvider => @@ -53,14 +62,13 @@ export const isLegacySendAsyncProvider = ( export const isSupportedProvider = ( provider: SupportedProviders, -): provider is SupportedProviders => +): provider is SupportedProviders => provider && (isWeb3Provider(provider) || isEIP1193Provider(provider) || isLegacyRequestProvider(provider) || isLegacySendAsyncProvider(provider) || isLegacySendProvider(provider)); - export const isSupportSubscriptions = ( provider: SupportedProviders, ): boolean => { diff --git a/packages/web3-core/src/web3_request_manager.ts b/packages/web3-core/src/web3_request_manager.ts index 7a6018ce253..5fe063a7881 100644 --- a/packages/web3-core/src/web3_request_manager.ts +++ b/packages/web3-core/src/web3_request_manager.ts @@ -42,6 +42,7 @@ import { Web3APISpec, Web3BaseProvider, Web3BaseProviderConstructor, + JsonRpcRequest } from 'web3-types'; import { isNullish, isPromise, jsonRpc, isResponseRpcError } from 'web3-utils'; import { @@ -50,6 +51,7 @@ import { isLegacySendAsyncProvider, isLegacySendProvider, isWeb3Provider, + isMetaMaskProvider, } from './utils.js'; import { Web3EventEmitter } from './web3_event_emitter.js'; @@ -66,6 +68,24 @@ const availableProviders: { WebsocketProvider: WSProvider as Web3BaseProviderConstructor, }; + +// if input was provided in params, change to data due to metamask only accepting data +const metamaskPayload = (payload: JsonRpcRequest) => { + + if(Array.isArray(payload.params)) { + const params = payload.params[0] as Record + if (params.input && !params.data) { + + return {...payload, + params: [{...params, + data: params.data ?? params.input}] + } + } +} +return payload; + +} + export class Web3RequestManager< API extends Web3APISpec = EthExecutionAPI, > extends Web3EventEmitter<{ @@ -187,11 +207,21 @@ export class Web3RequestManager< 'Provider not available. Use `.setProvider` or `.provider=` to initialize the provider.', ); } - - const payload = jsonRpc.isBatchRequest(request) + + let payload = jsonRpc.isBatchRequest(request) ? jsonRpc.toBatchPayload(request) : jsonRpc.toPayload(request); - + + if(isMetaMaskProvider(provider)){ // metamask send_transaction accepts data and not input, so we change it + if ((payload as JsonRpcRequest).method === 'eth_sendTransaction'){ + if(!jsonRpc.isBatchRequest(payload)){ + payload = metamaskPayload(payload as JsonRpcRequest) + } else { + payload = payload.map(p => metamaskPayload(p as JsonRpcRequest)) + } + } + } + if (isWeb3Provider(provider)) { let response; diff --git a/packages/web3-eth-contract/CHANGELOG.md b/packages/web3-eth-contract/CHANGELOG.md index 08b2da7c2f7..6a978416e82 100644 --- a/packages/web3-eth-contract/CHANGELOG.md +++ b/packages/web3-eth-contract/CHANGELOG.md @@ -321,3 +321,5 @@ Documentation: - Dependencies updated ## [Unreleased] + +- Will populate `data` for transactions in contract for metamask provider instead of `input` (#6534) diff --git a/packages/web3-eth-contract/src/contract.ts b/packages/web3-eth-contract/src/contract.ts index dcf726b07e5..6290ab20140 100644 --- a/packages/web3-eth-contract/src/contract.ts +++ b/packages/web3-eth-contract/src/contract.ts @@ -1082,6 +1082,7 @@ export class Contract options: { ...options, dataInputFill: this.config.contractDataInputFill }, contractOptions: modifiedContractOptions, }); + const transactionToSend = sendTransaction(this, tx, DEFAULT_RETURN_FORMAT, { // TODO Should make this configurable by the user checkRevertBeforeSending: false, diff --git a/packages/web3-types/CHANGELOG.md b/packages/web3-types/CHANGELOG.md index 97b01da0d31..aa55e8a83f8 100644 --- a/packages/web3-types/CHANGELOG.md +++ b/packages/web3-types/CHANGELOG.md @@ -173,4 +173,6 @@ Documentation: ## [Unreleased] ### Added + +- Interface `MetaMaskProvider` added and is part of `SupportedProviders` (#6534) - `gasPrice` was added to `Transaction1559UnsignedAPI` type. (#6539) diff --git a/packages/web3-types/src/web3_base_provider.ts b/packages/web3-types/src/web3_base_provider.ts index aac2e722bfc..5f840aa7488 100644 --- a/packages/web3-types/src/web3_base_provider.ts +++ b/packages/web3-types/src/web3_base_provider.ts @@ -112,6 +112,7 @@ export type ProviderChainId = string; export type ProviderAccounts = string[]; + export type Eip1193EventName = | 'connect' | 'disconnect' @@ -133,6 +134,22 @@ export interface EIP1193Provider extends SimpleProvider removeListener(event: 'accountsChanged', listener: (accounts: ProviderAccounts) => void): void; } +export interface MetaMaskProvider extends SimpleProvider { + on(event: 'connect', listener: (info: ProviderInfo) => void): void; + on(event: 'disconnect', listener: (error: ProviderRpcError) => void): void; + on(event: 'message', listener: (message: ProviderMessage) => void): void; + on(event: 'chainChanged', listener: (chainId: ProviderChainId) => void): void; + on(event: 'accountsChanged', listener: (accounts: ProviderAccounts) => void): void; + + removeListener(event: 'connect', listener: (info: ProviderInfo) => void): void; + removeListener(event: 'disconnect', listener: (error: ProviderRpcError) => void): void; + removeListener(event: 'message', listener: (message: ProviderMessage) => void): void; + removeListener(event: 'chainChanged', listener: (chainId: ProviderChainId) => void): void; + removeListener(event: 'accountsChanged', listener: (accounts: ProviderAccounts) => void): void; + isMetaMask: boolean; +} + + export type Eip1193Compatible = Omit< // eslint-disable-next-line no-use-before-define Omit, @@ -325,7 +342,8 @@ export type SupportedProviders = | LegacyRequestProvider | LegacySendProvider | LegacySendAsyncProvider - | SimpleProvider; + | SimpleProvider + | MetaMaskProvider; export type Web3BaseProviderConstructor = new ( url: string,