WDK logoWDK documentation
EVMStandard EVMGuides

Send Transactions

Send native tokens on EVM chains with EIP-1559 or legacy gas settings.

This guide explains how to send EVM transactions with EIP-1559 gas parameters, send legacy gas transactions, deploy contracts, sign without broadcasting, estimate fees, cap transaction fees, use dynamic fee rates, and wait for finality.

BigInt Usage: Always use BigInt (the n suffix) for monetary values to avoid precision loss with large numbers.

Send with EIP-1559 Gas Parameters

You can use account.sendTransaction() to send an EIP-1559 transaction. EIP-1559 transactions provide more predictable gas fees and faster inclusion times.

EIP-1559 Transaction
const result = await account.sendTransaction({
  to: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  value: 1000000000000000000n, // 1 ETH in wei
  maxFeePerGas: 30000000000,
  maxPriorityFeePerGas: 2000000000
})
console.log('Transaction hash:', result.hash)
console.log('Transaction fee:', result.fee, 'wei')

Send with Legacy Gas Parameters

You can also use account.sendTransaction() with legacy gas settings for chains that do not support EIP-1559.

Legacy Transaction
const legacyResult = await account.sendTransaction({
  to: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  value: 1000000000000000000n,
  gasPrice: 20000000000n,
  gasLimit: 21000
})
console.log('Transaction hash:', legacyResult.hash)

Deploy a Contract

For contract-creation transactions, omit to or pass to: null and provide the deployment bytecode in data.

Contract Creation
const result = await account.sendTransaction({
  to: null,
  value: 0n,
  data: contractBytecode,
  maxFeePerGas: 30000000000n,
  maxPriorityFeePerGas: 2000000000n
})

console.log('Deployment transaction:', result.hash)

Sign Without Broadcasting

Use account.signTransaction() when you need a signed raw transaction but want to submit it through a separate relay, service, or review flow.

Sign EVM Transaction
const signedTransaction = await account.signTransaction({
  to: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  value: 1000000000000000000n,
  chainId: 1,
  maxFeePerGas: 30000000000n,
  maxPriorityFeePerGas: 2000000000n
})

console.log('Signed transaction:', signedTransaction)

signTransaction() returns the signed transaction payload and does not broadcast it. In 1.0.0-beta.17, do not pass that serialized payload back to sendTransaction(): the send path does not broadcast the supplied bytes and can populate a different transaction. Submit signed raw transactions through a separate relay or provider. Use sendTransaction() with an EvmTransaction object when WDK should populate, sign, broadcast, and return the transaction hash.

Estimate Transaction Fees

Use account.quoteSendTransaction() to get a fee estimate before sending.

Quote Transaction Fee
const quote = await account.quoteSendTransaction({
  to: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  value: 1000000000000000000n
})
console.log('Estimated fee:', quote.fee, 'wei')

Cap Transaction Fees

Set transactionMaxFee when you create the wallet to stop native sendTransaction() calls and provider-backed signTransaction() calls if the estimated fee exceeds your limit. Offline signing without a provider cannot estimate fees, so the fee-cap check does not run there.

Cap Native Transaction Fees
const wallet = new WalletManagerEvm(seedPhrase, {
  provider: 'https://eth.drpc.org',
  transactionMaxFee: 100000000000000n
})

Use Dynamic Fee Rates

Retrieve current fee rates using wallet.getFeeRates() and apply them to your transaction.

Dynamic Fee Rates
const feeRates = await wallet.getFeeRates()
console.log('Normal fee rate:', feeRates.normal, 'wei')
console.log('Fast fee rate:', feeRates.fast, 'wei')

const result = await account.sendTransaction({
  to: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  value: 1000000000000000000n,
  data: '0x',
  gasLimit: 21000,
  maxFeePerGas: feeRates.fast,
  maxPriorityFeePerGas: 2000000000n
})
console.log('Transaction sent:', result.hash)
console.log('Fee paid:', result.fee, 'wei')

Gas Estimation: The maxFeePerGas and maxPriorityFeePerGas fields enable EIP-1559 transactions, ensuring more predictable gas fees and faster inclusion times.

Wait for Finality

Use the hash returned by sendTransaction() with waitForTransaction():

Wait for a Finalized Transaction
const result = await account.sendTransaction({
  to: recipient,
  value: 1000000000000000n
})

const receipt = await account.waitForTransaction(result.hash, {
  target: 'final'
})

if (receipt.finality === 'dropped') {
  console.log('The sender nonce was consumed by another transaction')
} else if (receipt.success === false) {
  console.log('The transaction was included but reverted')
}

The EVM default timeout is 120 seconds and the polling interval is four seconds. A node that does not implement the finalized block tag can report confirmed but cannot advance the receipt to final; use a bounded timeout appropriate for that provider. A finality target indicates settlement level, not execution success, so inspect success.

getTransactionReceipt() remains available for the native ethers receipt but is deprecated in favor of getTransaction().

Next Steps

To transfer ERC-20 tokens instead of native tokens, see Transfer ERC-20 Tokens.

On this page