Send ETH and contract transactions with MetaMask using eth_sendTransaction via the EIP-1193 provider, gas estimation, receipt polling, and the connectWith shortcut
Send ETH and contract transactions with MetaMask using eth_sendTransaction via the EIP-1193 provider, gas estimation, receipt polling, and the connectWith shortcut
Send EVM Transactions with MetaMask Connect
When to use
Use this skill when:
Sending ETH transfers via eth_sendTransaction
Calling smart contract functions by encoding data in the transaction
Estimating gas with eth_estimateGas before sending
Polling for transaction confirmation with eth_getTransactionReceipt
Using the connectWith shortcut to connect and send in a single approval
connectWith connects the wallet and sends a transaction in one user interaction:
const { accounts, chainId, result } = await client.connectWith({
method: 'eth_sendTransaction',
// The params function receives the FIRST connected account (a single// Address), not the accounts arrayparams: (account: Address) => [
{
from: account,
to: '0xRecipientAddress'asAddress,
value: ethToHexWei('0.01'),
},
],
chainIds: ['0x1'],
});
// result is the transaction hashconst txHash = result asHex;
console.log('Connected as:', accounts[0]);
console.log('Transaction hash:', txHash);
The params field accepts a function that receives the first connected account ((account: Address) => unknown[]), letting you use the connected address as from without knowing it ahead of time.
Step 8: Handle errors
try {
const txHash = await provider.request({
method: 'eth_sendTransaction',
params: [txParams],
});
} catch (err: any) {
switch (err.code) {
case4001:
// User rejected the transaction — offer retrybreak;
case -32002:
// Request already pending — wait for user action in MetaMaskbreak;
case -32000:
// Execution error (insufficient funds, gas too low, etc.)console.error('Execution error:', err.message);
break;
default:
console.error('Transaction failed:', err);
}
}
Important Notes
value must be hex-encoded wei — '0xde0b6b3a7640000' is 1 ETH. Never pass decimal strings or ETH-denominated numbers directly.
from must match the connected account — MetaMask rejects transactions where from doesn't match the active account.
eth_sendTransaction returns a transaction hash, not a receipt — poll eth_getTransactionReceipt to confirm the transaction was mined.
Receipt status is hex — '0x1' means success, '0x0' means the transaction was mined but reverted.
eth_estimateGas can throw — if the transaction would revert, estimation fails. Wrap it in a try/catch and show the error to the user.
connectWith params can be a function — params: (account) => [{ from: account, ... }] — it receives the first connected account (a single Address, not an array).
Chain IDs are always hex strings in SDK calls — '0x1', '0x89', '0xaa36a7'. The chainId in transaction objects follows the same convention when present.
Error code 4001 means the user deliberately rejected — handle gracefully.
Error code -32002 means a request is pending — do not send another transaction.
0x1 is auto-included in every connect() / connectWith() call.