Skip to content

Commit

Permalink
fix metamask sendtransaction (#6540)
Browse files Browse the repository at this point in the history
* add metamask check

* format and update changelog

* fix lint

* add metamask logic to request manager

* add payload batch request and lint

* fix deploy
  • Loading branch information
Alex authored Nov 1, 2023
1 parent f6c7fca commit b05345b
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 6 deletions.
4 changes: 4 additions & 0 deletions packages/web3-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
12 changes: 10 additions & 2 deletions packages/web3-core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,21 @@ import {
SupportedProviders,
Web3APISpec,
Web3BaseProvider,
MetaMaskProvider,
} from 'web3-types';

export const isWeb3Provider = <API extends Web3APISpec>(
provider: SupportedProviders<API>,
): provider is Web3BaseProvider<API> => Web3BaseProvider.isWeb3Provider(provider);

export const isMetaMaskProvider = <API extends Web3APISpec>(
provider: SupportedProviders<API>,
): provider is MetaMaskProvider<API> =>
typeof provider !== 'string' &&
'request' in provider &&
provider.request.constructor.name === 'AsyncFunction' && 'isMetaMask' in provider && provider.isMetaMask;


export const isLegacyRequestProvider = <API extends Web3APISpec>(
provider: SupportedProviders<API>,
): provider is LegacyRequestProvider =>
Expand All @@ -53,14 +62,13 @@ export const isLegacySendAsyncProvider = <API extends Web3APISpec>(

export const isSupportedProvider = <API extends Web3APISpec>(
provider: SupportedProviders<API>,
): provider is SupportedProviders<API> =>
): provider is SupportedProviders<API> =>
provider &&
(isWeb3Provider(provider) ||
isEIP1193Provider(provider) ||
isLegacyRequestProvider(provider) ||
isLegacySendAsyncProvider(provider) ||
isLegacySendProvider(provider));

export const isSupportSubscriptions = <API extends Web3APISpec>(
provider: SupportedProviders<API>,
): boolean => {
Expand Down
36 changes: 33 additions & 3 deletions packages/web3-core/src/web3_request_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
Web3APISpec,
Web3BaseProvider,
Web3BaseProviderConstructor,
JsonRpcRequest
} from 'web3-types';
import { isNullish, isPromise, jsonRpc, isResponseRpcError } from 'web3-utils';
import {
Expand All @@ -50,6 +51,7 @@ import {
isLegacySendAsyncProvider,
isLegacySendProvider,
isWeb3Provider,
isMetaMaskProvider,
} from './utils.js';
import { Web3EventEmitter } from './web3_event_emitter.js';

Expand All @@ -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<string, unknown>
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<{
Expand Down Expand Up @@ -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<ResponseType>).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;

Expand Down
2 changes: 2 additions & 0 deletions packages/web3-eth-contract/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,3 +321,5 @@ Documentation:
- Dependencies updated

## [Unreleased]

- Will populate `data` for transactions in contract for metamask provider instead of `input` (#6534)
1 change: 1 addition & 0 deletions packages/web3-eth-contract/src/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,7 @@ export class Contract<Abi extends ContractAbi>
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,
Expand Down
2 changes: 2 additions & 0 deletions packages/web3-types/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,6 @@ Documentation:
## [Unreleased]

### Added

- Interface `MetaMaskProvider` added and is part of `SupportedProviders` (#6534)
- `gasPrice` was added to `Transaction1559UnsignedAPI` type. (#6539)
20 changes: 19 additions & 1 deletion packages/web3-types/src/web3_base_provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export type ProviderChainId = string;

export type ProviderAccounts = string[];


export type Eip1193EventName =
| 'connect'
| 'disconnect'
Expand All @@ -133,6 +134,22 @@ export interface EIP1193Provider<API extends Web3APISpec> extends SimpleProvider
removeListener(event: 'accountsChanged', listener: (accounts: ProviderAccounts) => void): void;
}

export interface MetaMaskProvider<API extends Web3APISpec> extends SimpleProvider<API> {
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<API extends Web3APISpec = EthExecutionAPI> = Omit<
// eslint-disable-next-line no-use-before-define
Omit<Web3BaseProvider, 'request'>,
Expand Down Expand Up @@ -325,7 +342,8 @@ export type SupportedProviders<API extends Web3APISpec = Web3EthExecutionAPI> =
| LegacyRequestProvider
| LegacySendProvider
| LegacySendAsyncProvider
| SimpleProvider<API>;
| SimpleProvider<API>
| MetaMaskProvider<API>;

export type Web3BaseProviderConstructor = new <API extends Web3APISpec>(
url: string,
Expand Down

0 comments on commit b05345b

Please sign in to comment.