diff --git a/packages/mask/src/plugins/Wallet/services/send.ts b/packages/mask/src/plugins/Wallet/services/send.ts index 30c627ddb7bd..1f79b681d5c0 100644 --- a/packages/mask/src/plugins/Wallet/services/send.ts +++ b/packages/mask/src/plugins/Wallet/services/send.ts @@ -1,11 +1,14 @@ import Web3 from 'web3' import type { HttpProvider } from 'web3-core' +import { isHex, hexToNumber } from 'web3-utils' import type { JsonRpcPayload, JsonRpcResponse } from 'web3-core-helpers' +import { isNil } from 'lodash-unified' import { defer } from '@dimensiondev/kit' import { ChainId, + createWeb3, EthereumMethodType, - getPayloadConfig, + getSignablePayloadConfig, getPayloadId, getRPCConstants, isRiskMethod, @@ -13,7 +16,6 @@ import { import { openPopupWindow, removePopupWindow } from '../../../../background/services/helper' import { nativeAPI } from '../../../../shared/native-rpc' import { WalletRPC } from '../messages' -import { isNil } from 'lodash-unified' enum JSON_RPC_ERROR_CODE { INVALID_REQUEST = -32600, @@ -119,34 +121,34 @@ export async function send( options?: Options, ) { const provider = await createProvider(options?.chainId) - const computedPayload = getPayloadConfig(payload) + switch (payload.method) { case EthereumMethodType.ETH_SEND_TRANSACTION: case EthereumMethodType.MASK_REPLACE_TRANSACTION: + const computedPayload = getSignablePayloadConfig(payload) if (!computedPayload?.from || !computedPayload.to || !options?.chainId) return - const rawTransaction = await WalletRPC.signTransaction(computedPayload.from as string, { - ...computedPayload, - chainId: options.chainId, - }) - if (!rawTransaction) break + const privateKey = await WalletRPC.exportPrivateKey(computedPayload.from as string) + const web3 = createWeb3(provider) + const transactionSigned = await web3.eth.accounts.signTransaction(computedPayload, `0x${privateKey}`) + if (!transactionSigned.rawTransaction) break return provider.send( { ...payload, method: EthereumMethodType.ETH_SEND_RAW_TRANSACTION, - params: [rawTransaction], + params: [transactionSigned.rawTransaction], }, callback, ) case EthereumMethodType.ETH_SIGN_TYPED_DATA: const [address, dataToSign] = payload.params as [string, string] - const signed = await WalletRPC.signTypedData(address, dataToSign) + const dataSigned = await WalletRPC.signTypedData(address, dataToSign) try { callback(null, { jsonrpc: '2.0', id: payload.id as number, - result: signed, + result: dataSigned, }) } catch (error) { callback(getError(error, null, 'Failed to sign message.')) @@ -154,12 +156,12 @@ export async function send( break case EthereumMethodType.PERSONAL_SIGN: const [data, account] = payload.params as [string, string] - const personalSigned = await WalletRPC.signPersonalMessage(data, account) + const messageSigned = await WalletRPC.signPersonalMessage(data, account) try { callback(null, { jsonrpc: '2.0', id: payload.id as number, - result: personalSigned, + result: messageSigned, }) } catch (error) { callback(getError(error, null, 'Failed to sign message.')) @@ -219,7 +221,7 @@ export async function confirmRequest(payload: JsonRpcPayload, options?: Options) return } if (response?.error) { - reject(new Error(`Failed to send transaction: ${response.error}`)) + reject(new Error(`Failed to send transaction: ${response.error?.message ?? response.error}`)) return } WalletRPC.deleteUnconfirmedRequest(payload) diff --git a/packages/web3-shared/evm/utils/contract.ts b/packages/web3-shared/evm/utils/contract.ts index 19d935af9259..46d2c0e53caf 100644 --- a/packages/web3-shared/evm/utils/contract.ts +++ b/packages/web3-shared/evm/utils/contract.ts @@ -57,9 +57,9 @@ export async function encodeContractTransaction( if (!tx.gas) { tx.gas = await transaction.estimateGas({ from: tx.from as string | undefined, - value: tx.value, - data: tx.data as string | undefined, to: tx.to as string | undefined, + data: tx.data as string | undefined, + value: tx.value, }) } diff --git a/packages/web3-shared/evm/utils/payload.ts b/packages/web3-shared/evm/utils/payload.ts index 58c2e282ac65..b4073caa5b22 100644 --- a/packages/web3-shared/evm/utils/payload.ts +++ b/packages/web3-shared/evm/utils/payload.ts @@ -1,6 +1,7 @@ import BigNumber from 'bignumber.js' -import { first } from 'lodash-unified' +import { first, isUndefined, omitBy } from 'lodash-unified' import type { JsonRpcPayload } from 'web3-core-helpers' +import { hexToNumber } from 'web3-utils' import { EthereumMethodType, Transaction } from '../types' export function addGasMargin(value: BigNumber.Value, scale = 3000) { @@ -56,3 +57,25 @@ export function getPayloadConfig(payload: JsonRpcPayload) { return } } + +export function getSignablePayloadConfig(payload: JsonRpcPayload) { + const raw = getPayloadConfig(payload) + if (!raw) return + + const parseHexNumber = (hex: string | number | undefined) => + typeof hex !== 'undefined' ? hexToNumber(hex ?? '0x0') : undefined + + return omitBy( + { + ...raw, + value: parseHexNumber(raw.value as string | undefined), + gas: parseHexNumber(raw.gas), + gasPrice: parseHexNumber(raw.gasPrice as string | undefined), + maxFeePerGas: parseHexNumber(raw.maxFeePerGas as string | undefined), + maxPriorityFeePerGas: parseHexNumber(raw.maxPriorityFeePerGas as string | undefined), + chainId: parseHexNumber(raw.chainId), + nonce: parseHexNumber(raw.nonce), + }, + isUndefined, + ) as Transaction +} diff --git a/packages/web3-shared/evm/utils/provider.ts b/packages/web3-shared/evm/utils/provider.ts index 4ec56364cdc1..2367e25a3568 100644 --- a/packages/web3-shared/evm/utils/provider.ts +++ b/packages/web3-shared/evm/utils/provider.ts @@ -12,6 +12,15 @@ export function createWeb3(provider: Provider) { return web3 } +export function createSignableWeb3(provider: Provider, keys: string[]) { + const web3 = createWeb3(provider) + if (keys.length) { + web3.eth.accounts.wallet.clear() + keys.forEach((k) => k && ['0x', '0x0'].includes(k) && web3.eth.accounts.wallet.add(k)) + } + return web3 +} + export function createWeb3Provider(request: (requestArguments: RequestArguments) => Promise): Web3Provider { const provider: Web3Provider = { on() {