WDK logoWDK documentation

Wallet EVM ERC-4337 API Reference

Complete API documentation for @tetherto/wdk-wallet-evm-erc-4337

Table of Contents

ClassDescriptionMethods
WalletManagerEvmErc4337Main class for managing ERC-4337 EVM wallets. Extends WalletManager from @tetherto/wdk-wallet.Constructor, Methods
WalletAccountEvmErc4337Individual ERC-4337 wallet account implementation. Extends WalletAccountReadOnlyEvmErc4337 and implements IWalletAccount.Constructor, Methods, Properties
WalletAccountReadOnlyEvmErc4337Read-only ERC-4337 wallet account. Extends WalletAccountReadOnly from @tetherto/wdk-wallet.Constructor, Methods
ConfigurationErrorError thrown when the wallet configuration is invalid or has missing required fields.-

WalletManagerEvmErc4337

The main class for managing ERC-4337 EVM wallets. Extends WalletManager from @tetherto/wdk-wallet.

Fee Rate Behavior

Internally, getFeeRates() applies these multipliers to the base fee:

  • Normal: base fee × 110%
  • Fast: base fee × 200%

These multipliers are internal (protected static) and cannot be imported or overridden.

Constructor

new WalletManagerEvmErc4337(seed, config)

Parameters:

  • seed (string | Uint8Array): BIP-39 mnemonic seed phrase or seed bytes
  • config (EvmErc4337WalletConfig): Configuration object with common fields and a gas payment mode

Common config fields (required for all modes):

  • chainId (number): The blockchain's ID (e.g., 1 for Ethereum mainnet)
  • provider (string | Eip1193Provider | Array<string | Eip1193Provider>): RPC endpoint URL, EIP-1193 provider instance, or ordered failover list
  • bundlerUrl (string): The URL of the bundler service
  • safeModulesVersion (string): The Safe modules version (e.g., '0.3.0')

Gas payment mode (one of the following):

Fees are paid using an ERC-20 token through a paymaster service.

  • paymasterUrl (string): The URL of the paymaster service
  • paymasterAddress (string): The address of the paymaster smart contract
  • paymasterToken (object): The paymaster token configuration
    • address (string): The address of the ERC-20 token used for fees
  • transferMaxFee (number | bigint, optional): Maximum fee limit in paymaster token units
const wallet = new WalletManagerEvmErc4337(seedPhrase, {
  chainId: 1,
  provider: 'https://rpc.mevblocker.io/fast',
  bundlerUrl: 'https://api.candide.dev/public/v3/ethereum',
  safeModulesVersion: '0.3.0',
  // Paymaster token mode
  paymasterUrl: 'https://api.candide.dev/public/v3/ethereum',
  paymasterAddress: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
  paymasterToken: {
    address: '0xdAC17F958D2ee523a2206206994597C13D831ec7' // USD₮
  },
  transferMaxFee: 100000 // Optional: max fee in token units
})

Methods

MethodDescriptionReturnsThrows
getRandomSeedPhrase(wordCount?)(static) Returns a random BIP-39 seed phrasestring-
isValidSeedPhrase(seedPhrase)(static) Checks if a seed phrase is validboolean-
getAccount(index?)Returns a wallet account at the specified indexPromise\<WalletAccountEvmErc4337\>-
getAccountByPath(path)Returns a wallet account at the specified BIP-44 derivation pathPromise\<WalletAccountEvmErc4337\>-
getFeeRates()Returns current fee rates for transactionsPromise\<{normal: bigint, fast: bigint}\>If no provider
dispose()Disposes all wallet accounts, clearing private keys from memoryvoid-

Properties

PropertyTypeDescription
seedUint8ArrayThe wallet's seed phrase as bytes

getRandomSeedPhrase(wordCount?) (static)

Returns a random BIP-39 seed phrase.

Parameters:

  • wordCount (12 | 24, optional): The number of words in the seed phrase (default: 12)

Returns: string - The seed phrase

Example:

const seedPhrase = WalletManagerEvmErc4337.getRandomSeedPhrase()
console.log('Seed phrase:', seedPhrase) // 12 words

const longSeedPhrase = WalletManagerEvmErc4337.getRandomSeedPhrase(24)
console.log('Long seed phrase:', longSeedPhrase) // 24 words

isValidSeedPhrase(seedPhrase) (static)

Checks if a seed phrase is valid.

Parameters:

  • seedPhrase (string): The seed phrase to validate

Returns: boolean - True if the seed phrase is valid

Example:

const isValid = WalletManagerEvmErc4337.isValidSeedPhrase('abandon abandon abandon ...')
console.log('Valid:', isValid)

getAccount(index)

Returns a wallet account at the specified index using BIP-44 derivation.

Parameters:

  • index (number, optional): The index of the account to get (default: 0)

Returns: Promise\<WalletAccountEvmErc4337\> - The wallet account

Example:

// Get first account (index 0)
const account = await wallet.getAccount(0)

// Get default account
const defaultAccount = await wallet.getAccount()

getAccountByPath(path)

Returns a wallet account at the specified BIP-44 derivation path.

Parameters:

  • path (string): The derivation path (e.g., "0'/0/0")

Returns: Promise\<WalletAccountEvmErc4337\> - The wallet account

Example:

// Full derivation path: m/44'/60'/0'/0/1
const account = await wallet.getAccountByPath("0'/0/1")

getFeeRates()

Returns current fee rates with ERC-4337 specific multipliers.

Returns: Promise\<{normal: bigint, fast: bigint}\> - Fee rates in wei

Throws: Error if no provider is configured

Example:

const feeRates = await wallet.getFeeRates()
console.log('Normal fee rate:', feeRates.normal, 'wei') // base fee × 1.1
console.log('Fast fee rate:', feeRates.fast, 'wei')     // base fee × 2.0

dispose()

Disposes all wallet accounts, clearing private keys from memory.

Example:

// Clean up when done
wallet.dispose()

WalletAccountEvmErc4337

Represents an individual ERC-4337 wallet account. Extends WalletAccountReadOnlyEvmErc4337 and implements IWalletAccount.

Constants

The following constant is used internally for Safe account address derivation:

// Internal: used by predictSafeAddress() for deterministic address generation
const SALT_NONCE = '0x69b348339eea4ed93f9d11931c3b894c8f9d8c7663a053024b11cb7eb4e5a1f6'

Note: This constant is not re-exported from the package entry point. Use predictSafeAddress() instead of referencing it directly.

Constructor

new WalletAccountEvmErc4337(seed, path, config)

Parameters:

  • seed (string | Uint8Array): BIP-39 mnemonic seed phrase or seed bytes
  • path (string): BIP-44 derivation path (e.g., "0'/0/0")
  • config (EvmErc4337WalletConfig): Configuration object (same as WalletManagerEvmErc4337)

Example:

const account = new WalletAccountEvmErc4337(seedPhrase, "0'/0/0", {
  chainId: 1,
  provider: 'https://rpc.mevblocker.io/fast',
  bundlerUrl: 'https://api.candide.dev/public/v3/ethereum',
  safeModulesVersion: '0.3.0',
  paymasterUrl: 'https://api.candide.dev/public/v3/ethereum',
  paymasterAddress: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
  paymasterToken: {
    address: '0xdAC17F958D2ee523a2206206994597C13D831ec7'
  }
})

Methods

MethodDescriptionReturnsThrows
predictSafeAddress(owner, config)(static) Predicts the Safe address for a given ownerstring-
getAddress()Returns the Safe account's addressPromise\<string\>-
sign(message)Signs a message using the account's private keyPromise\<string\>-
verify(message, signature)Verifies a message signaturePromise\<boolean\>-
sendTransaction(tx, config?)Sends a transaction via UserOperationPromise\<{hash: string, fee: bigint}\>If fee exceeds max
quoteSendTransaction(tx, config?)Estimates the fee for a UserOperationPromise\<{fee: bigint}\>-
transfer(options, config?)Transfers ERC20 tokens via UserOperationPromise\<{hash: string, fee: bigint}\>If fee exceeds max
quoteTransfer(options, config?)Estimates the fee for an ERC20 transferPromise\<{fee: bigint}\>-
approve(options)Approves a spender to spend ERC20 tokensPromise\<{hash: string, fee: bigint}\>-
getBalance()Returns the native token balance (in wei)Promise\<bigint\>-
getTokenBalance(tokenAddress)Returns the balance of a specific ERC20 tokenPromise\<bigint\>-
getPaymasterTokenBalance()Returns the paymaster token balancePromise\<bigint\>-
getAllowance(token, spender)Returns current token allowance for a spenderPromise\<bigint\>-
getTransactionReceipt(hash)Returns a transaction receiptPromise\<EvmTransactionReceipt | null\>-
getUserOperationReceipt(hash)Returns a UserOperation receiptPromise\<UserOperationReceipt | null\>-
signTypedData(typedData)Signs EIP-712 typed structured dataPromise\<string\>-
verifyTypedData(typedData, signature)Verifies an EIP-712 typed data signaturePromise\<boolean\>-
getTokenBalances(tokenAddresses)Returns balances for multiple ERC20 tokensPromise\<Map\<string, bigint\>\>-
toReadOnlyAccount()Returns a read-only copy of the accountPromise\<WalletAccountReadOnlyEvmErc4337\>-
dispose()Disposes the wallet account, clearing private keys from memoryvoid-
getAddress()

Returns the Safe smart contract wallet address (not the underlying EOA address).

Returns: Promise\<string\> - The Safe account's address

Example:

const address = await account.getAddress()
console.log('Safe account address:', address) // 0x... (Smart contract address)
sign(message)

Signs a message using the underlying EOA private key.

Parameters:

  • message (string): The message to sign

Returns: Promise\<string\> - The message signature

Example:

const message = 'Hello, ERC-4337!'
const signature = await account.sign(message)
console.log('Signature:', signature)
verify(message, signature)

Verifies a message signature against the underlying EOA address.

Parameters:

  • message (string): The original message
  • signature (string): The signature to verify

Returns: Promise\<boolean\> - True if signature is valid

Example:

const isValid = await account.verify(message, signature)
console.log('Signature valid:', isValid)
sendTransaction(tx, config?)

Sends a transaction via UserOperation through the bundler.

Parameters:

  • tx (EvmErc4337Transaction | EvmErc4337Transaction[]): Transaction object or array for batch transactions
    • to (string): Recipient address
    • value (number | bigint): Amount in wei
    • data (string, optional): Transaction data in hex format
    • callGasLimit, verificationGasLimit, preVerificationGas (number | bigint, optional): Per-call overrides for the UserOperation gas limits
    • maxFeePerGas, maxPriorityFeePerGas (number | bigint, optional): Per-call overrides for the EIP-1559 fee pair; set both together. In a batch, only the first transaction's gas overrides apply (see EvmErc4337Transaction)
  • config (optional): Per-call configuration override. Accepts a partial version of the gas payment mode fields (see Config Override).

Returns: Promise\<{hash: string, fee: bigint}\> - UserOperation hash and fee

Throws: Error if fee exceeds transferMaxFee

Example:

// Single transaction
const result = await account.sendTransaction({
  to: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  value: 1000000000000000000n, // 1 ETH
  data: '0x'
})
console.log('UserOperation hash:', result.hash)
console.log('Fee paid:', result.fee)

// Batch transactions
const batchResult = await account.sendTransaction([
  { to: '0x...', value: 100000000000000000n },
  { to: '0x...', value: 200000000000000000n }
])

// With per-call config override
const customResult = await account.sendTransaction({
  to: '0x...',
  value: 1000000000000000000n
}, {
  paymasterToken: { address: '0xNewToken...' }
})

// With per-call gas overrides (EIP-1559 fee pair set together)
const fastResult = await account.sendTransaction({
  to: '0x...',
  value: 1000000000000000000n,
  maxFeePerGas: 30000000000n,        // 30 gwei
  maxPriorityFeePerGas: 2000000000n  // 2 gwei
})
quoteSendTransaction(tx, config?)

Estimates the fee for a UserOperation without sending it.

Parameters:

  • tx (EvmErc4337Transaction | EvmErc4337Transaction[]): Transaction object or array (same as sendTransaction)
  • config (optional): Per-call configuration override (see Config Override)

Returns: Promise\<{fee: bigint}\> - Fee estimate

Example:

const quote = await account.quoteSendTransaction({
  to: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  value: 1000000000000000000n
})
console.log('Estimated fee:', quote.fee)
transfer(options, config?)

Transfers ERC20 tokens via UserOperation.

Parameters:

  • options (TransferOptions): Transfer options
    • token (string): ERC20 token contract address
    • recipient (string): Recipient address
    • amount (number | bigint): Amount in token base units
  • config (optional): Per-call configuration override (see Config Override)

Returns: Promise\<{hash: string, fee: bigint}\> - UserOperation hash and fee

Throws:

  • Error if fee exceeds transferMaxFee
  • Error if insufficient token balance

Example:

const result = await account.transfer({
  token: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USD₮
  recipient: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  amount: 1000000 // 1 USD₮ (6 decimals)
}, {
  transferMaxFee: 50000 // Override max fee for this call
})
console.log('Transfer hash:', result.hash)
console.log('Transfer fee:', result.fee)
quoteTransfer(options, config?)

Estimates the fee for an ERC20 token transfer.

Parameters:

  • options (TransferOptions): Transfer options (same as transfer)
  • config (optional): Per-call configuration override (see Config Override)

Returns: Promise\<{fee: bigint}\> - Fee estimate

Example:

const quote = await account.quoteTransfer({
  token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
  recipient: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  amount: 1000000
})
console.log('Transfer fee estimate:', quote.fee)
getBalance()

Returns the Safe account's native token balance.

Returns: Promise\<bigint\> - Balance in wei

Example:

const balance = await account.getBalance()
console.log('Native balance:', balance, 'wei')
getTokenBalance(tokenAddress)

Returns the balance of a specific ERC20 token in the Safe account.

Parameters:

  • tokenAddress (string): The ERC20 token contract address

Returns: Promise\<bigint\> - Token balance in base units

Example:

const tokenBalance = await account.getTokenBalance('0xdAC17F958D2ee523a2206206994597C13D831ec7')
console.log('USDT balance:', tokenBalance) // In 6 decimal units
getPaymasterTokenBalance()

Returns the balance of the configured paymaster token used for paying fees.

Returns: Promise\<bigint\> - Paymaster token balance in base units

Example:

const paymasterBalance = await account.getPaymasterTokenBalance()
console.log('Paymaster token balance:', paymasterBalance)

// Check if sufficient for transaction
if (paymasterBalance < 10000n) {
  console.warn('Low paymaster token balance - may not cover fees')
}
approve(options)

Approves a spender to spend ERC20 tokens on behalf of the Safe account.

Parameters:

  • options (ApproveOptions): Approve options
    • token (string): ERC20 token contract address
    • spender (string): The address allowed to spend the tokens
    • amount (number | bigint): Amount to approve in token base units

Returns: Promise\<{hash: string, fee: bigint}\> - Transaction result

Example:

const result = await account.approve({
  token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
  spender: '0xSpenderContract...',
  amount: 1000000n // 1 USD₮
})
console.log('Approval hash:', result.hash)
getAllowance(token, spender)

Returns the current token allowance for the given spender.

Parameters:

  • token (string): ERC20 token contract address
  • spender (string): The spender's address

Returns: Promise\<bigint\> - The current allowance

Example:

const allowance = await account.getAllowance(
  '0xdAC17F958D2ee523a2206206994597C13D831ec7',
  '0xSpenderContract...'
)
console.log('Current allowance:', allowance)
getTransactionReceipt(hash)

Returns a transaction receipt by hash.

Parameters:

  • hash (string): The transaction hash

Returns: Promise\<EvmTransactionReceipt | null\> - Transaction receipt or null if not mined

Example:

const receipt = await account.getTransactionReceipt('0x...')
if (receipt) {
  console.log('Confirmed in block:', receipt.blockNumber)
}
getUserOperationReceipt(hash)

Returns a UserOperation receipt by hash.

Parameters:

  • hash (string): The UserOperation hash

Returns: Promise\<UserOperationReceipt | null\> - UserOperation receipt or null if not processed

Example:

const receipt = await account.getUserOperationReceipt('0x...')
if (receipt) {
  console.log('UserOp receipt:', receipt)
}
signTypedData(typedData)

Signs EIP-712 typed structured data using the underlying EOA private key.

Parameters:

  • typedData (TypedData): The typed data object containing domain, types, primaryType, and message

Returns: Promise\<string\> - The typed data signature

Example:

const typedData = {
  domain: {
    name: 'MyDApp',
    version: '1',
    chainId: 1,
    verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC'
  },
  types: {
    Transfer: [
      { name: 'to', type: 'address' },
      { name: 'amount', type: 'uint256' }
    ]
  },
  primaryType: 'Transfer',
  message: {
    to: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
    amount: 1000000n
  }
}

const signature = await account.signTypedData(typedData)
console.log('Typed data signature:', signature)
verifyTypedData(typedData, signature)

Verifies an EIP-712 typed data signature against the underlying EOA address.

Parameters:

  • typedData (TypedData): The original typed data object
  • signature (string): The signature to verify

Returns: Promise\<boolean\> - True if the signature is valid

Example:

const isValid = await account.verifyTypedData(typedData, signature)
console.log('Typed data signature valid:', isValid)
getTokenBalances(tokenAddresses)

Returns balances for multiple ERC20 tokens in a single call.

Parameters:

  • tokenAddresses (string[]): Array of ERC20 token contract addresses

Returns: Promise\<Map\<string, bigint\>\> - Map of token address to balance in base units

Example:

const balances = await account.getTokenBalances([
  '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
  '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'  // USDC
])
for (const [address, balance] of balances) {
  console.log(`Token ${address}: ${balance}`)
}
toReadOnlyAccount()

Creates a read-only copy of the account with the same Safe address and configuration.

Returns: Promise\<WalletAccountReadOnlyEvmErc4337\> - Read-only account instance

Example:

const readOnlyAccount = await account.toReadOnlyAccount()

// Can check balances but cannot send transactions
const balance = await readOnlyAccount.getBalance()
// readOnlyAccount.sendTransaction() // Would not be available
dispose()

Disposes the wallet account, clearing private keys from memory.

Example:

account.dispose()

Properties

PropertyTypeDescription
indexnumberThe derivation path's index of this account
pathstringThe full BIP-44 derivation path of this account
keyPair{privateKey: Uint8Array | null, publicKey: Uint8Array}The account's key pair (⚠️ Contains sensitive data)

Example:

console.log('Account index:', account.index) // 0, 1, 2, etc.
console.log('Account path:', account.path) // m/44'/60'/0'/0/0

// ⚠️ SENSITIVE: Handle with care
const { privateKey, publicKey } = account.keyPair
console.log('Public key length:', publicKey.length) // 65 bytes
console.log('Private key length:', privateKey?.length) // 32 bytes (null after dispose)

⚠️ Security Note: The keyPair property contains sensitive cryptographic material. Never log, display, or expose the private key.

WalletAccountReadOnlyEvmErc4337

Represents a read-only ERC-4337 wallet account that can query balances and estimate fees but cannot send transactions.

Constants

The following constant is used internally for Safe account address derivation:

// Internal: used by predictSafeAddress() for deterministic address generation
const SALT_NONCE = '0x69b348339eea4ed93f9d11931c3b894c8f9d8c7663a053024b11cb7eb4e5a1f6'

Note: This constant is not re-exported from the package entry point. Use predictSafeAddress() instead of referencing it directly.

Constructor

new WalletAccountReadOnlyEvmErc4337(address, config)

Parameters:

  • address (string): The EOA address (owner address)
  • config (Omit<EvmErc4337WalletConfig, 'transferMaxFee'>): Configuration object without transferMaxFee

Example:

const readOnlyAccount = new WalletAccountReadOnlyEvmErc4337('0x...', {
  chainId: 1,
  provider: 'https://rpc.mevblocker.io/fast',
  bundlerUrl: 'https://api.candide.dev/public/v3/ethereum',
  safeModulesVersion: '0.3.0',
  paymasterUrl: 'https://api.candide.dev/public/v3/ethereum',
  paymasterAddress: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
  paymasterToken: {
    address: '0xdAC17F958D2ee523a2206206994597C13D831ec7'
  }
})

Static Methods

MethodDescriptionReturns
predictSafeAddress(owner, config)Predicts the Safe address for a given owner without instantiating an accountstring

predictSafeAddress(owner, config) (static)

Predicts the address of a Safe account.

Parameters:

  • owner (string): The Safe owner's EOA address
  • config (object): Configuration with:
    • chainId (number): The blockchain ID
    • safeModulesVersion (string): The Safe modules version

Returns: string - The predicted Safe address

Example:

const safeAddress = WalletAccountReadOnlyEvmErc4337.predictSafeAddress(
  '0xOwnerEOA...',
  { chainId: 1, safeModulesVersion: '0.3.0' }
)
console.log('Predicted Safe address:', safeAddress)

// Also available on WalletAccountEvmErc4337 (inherited)
const sameAddress = WalletAccountEvmErc4337.predictSafeAddress(
  '0xOwnerEOA...',
  { chainId: 1, safeModulesVersion: '0.3.0' }
)

Methods

MethodDescriptionReturnsThrows
getAddress()Returns the Safe account's addressPromise\<string\>-
verify(message, signature)Verifies a message signaturePromise\<boolean\>-
getBalance()Returns the native token balance (in wei)Promise\<bigint\>-
getTokenBalance(tokenAddress)Returns the balance of a specific ERC20 tokenPromise\<bigint\>-
getPaymasterTokenBalance()Returns the paymaster token balancePromise\<bigint\>-
getAllowance(token, spender)Returns current token allowance for a spenderPromise\<bigint\>-
quoteSendTransaction(tx, config?)Estimates the fee for a UserOperationPromise\<{fee: bigint}\>If simulation fails
quoteTransfer(options, config?)Estimates the fee for an ERC20 transferPromise\<{fee: bigint}\>If simulation fails
getTransactionReceipt(hash)Returns a transaction receiptPromise\<EvmTransactionReceipt | null\>-
getUserOperationReceipt(hash)Returns a UserOperation receiptPromise\<UserOperationReceipt | null\>-
signTypedData(typedData)Signs EIP-712 typed structured dataPromise\<string\>-
verifyTypedData(typedData, signature)Verifies an EIP-712 typed data signaturePromise\<boolean\>-
getTokenBalances(tokenAddresses)Returns balances for multiple ERC20 tokensPromise\<Map\<string, bigint\>\>-
getAddress()

Returns the Safe smart contract wallet address.

Returns: Promise\<string\> - The Safe account's address

Example:

const address = await readOnlyAccount.getAddress()
console.log('Safe address:', address)
verify(message, signature)

Verifies a message signature against the underlying EOA address.

Parameters:

  • message (string): The original message
  • signature (string): The signature to verify

Returns: Promise\<boolean\> - True if signature is valid

Example:

const isValid = await readOnlyAccount.verify(message, signature)
console.log('Signature valid:', isValid)
getBalance()

Returns the Safe account's native token balance.

Returns: Promise\<bigint\> - Balance in wei

Example:

const balance = await readOnlyAccount.getBalance()
console.log('Balance:', balance, 'wei')
getTokenBalance(tokenAddress)

Returns the balance of a specific ERC20 token.

Parameters:

  • tokenAddress (string): The ERC20 token contract address

Returns: Promise\<bigint\> - Token balance in base units

Example:

const tokenBalance = await readOnlyAccount.getTokenBalance('0xdAC17F958D2ee523a2206206994597C13D831ec7')
console.log('USDT balance:', tokenBalance)
getPaymasterTokenBalance()

Returns the balance of the configured paymaster token.

Returns: Promise\<bigint\> - Paymaster token balance in base units

Example:

const paymasterBalance = await readOnlyAccount.getPaymasterTokenBalance()
console.log('Paymaster token balance:', paymasterBalance)
getAllowance(token, spender)

Returns the current token allowance for the given spender.

Parameters:

  • token (string): ERC20 token contract address
  • spender (string): The spender's address

Returns: Promise\<bigint\> - The current allowance

Example:

const allowance = await readOnlyAccount.getAllowance(
  '0xdAC17F958D2ee523a2206206994597C13D831ec7',
  '0xSpenderContract...'
)
console.log('Allowance:', allowance)
quoteSendTransaction(tx, config?)

Estimates the fee for a UserOperation.

Parameters:

  • tx (EvmErc4337Transaction | EvmErc4337Transaction[]): Transaction object or array
  • config (optional): Per-call configuration override (see Config Override)

Returns: Promise\<{fee: bigint}\> - Fee estimate

Throws: Error if simulation fails

Example:

try {
  const quote = await readOnlyAccount.quoteSendTransaction({
    to: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
    value: 1000000000000000000n
  })
  console.log('Estimated fee:', quote.fee)
} catch (error) {
  if (error.message.includes('not enough funds')) {
    console.error('Insufficient paymaster token balance')
  }
}
quoteTransfer(options, config?)

Estimates the fee for an ERC20 token transfer.

Parameters:

  • options (TransferOptions): Transfer options
  • config (optional): Per-call configuration override (see Config Override)

Returns: Promise\<{fee: bigint}\> - Fee estimate

Example:

const quote = await readOnlyAccount.quoteTransfer({
  token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
  recipient: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  amount: 1000000
})
console.log('Transfer fee estimate:', quote.fee)
getTransactionReceipt(hash)

Returns a transaction receipt by hash.

Parameters:

  • hash (string): The transaction hash

Returns: Promise\<EvmTransactionReceipt | null\> - Transaction receipt or null if not mined

Example:

const receipt = await readOnlyAccount.getTransactionReceipt('0x...')
if (receipt) {
  console.log('Transaction confirmed in block:', receipt.blockNumber)
  console.log('Status:', receipt.status) // 1 = success, 0 = failed
} else {
  console.log('Transaction not yet mined')
}
getUserOperationReceipt(hash)

Returns a UserOperation receipt by hash.

Parameters:

  • hash (string): The UserOperation hash

Returns: Promise\<UserOperationReceipt | null\> - UserOperation receipt or null if not processed

Example:

const receipt = await readOnlyAccount.getUserOperationReceipt('0x...')
if (receipt) {
  console.log('UserOp receipt:', receipt)
}
signTypedData(typedData)

Signs EIP-712 typed structured data using the underlying EOA address.

Parameters:

  • typedData (TypedData): The typed data object containing domain, types, primaryType, and message

Returns: Promise\<string\> - The typed data signature

Example:

const typedData = {
  domain: {
    name: 'MyDApp',
    version: '1',
    chainId: 1,
    verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC'
  },
  types: {
    Transfer: [
      { name: 'to', type: 'address' },
      { name: 'amount', type: 'uint256' }
    ]
  },
  primaryType: 'Transfer',
  message: {
    to: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
    amount: 1000000n
  }
}

const signature = await readOnlyAccount.signTypedData(typedData)
console.log('Typed data signature:', signature)
verifyTypedData(typedData, signature)

Verifies an EIP-712 typed data signature against the underlying EOA address.

Parameters:

  • typedData (TypedData): The original typed data object
  • signature (string): The signature to verify

Returns: Promise\<boolean\> - True if the signature is valid

Example:

const isValid = await readOnlyAccount.verifyTypedData(typedData, signature)
console.log('Typed data signature valid:', isValid)
getTokenBalances(tokenAddresses)

Returns balances for multiple ERC20 tokens in a single call.

Parameters:

  • tokenAddresses (string[]): Array of ERC20 token contract addresses

Returns: Promise\<Map\<string, bigint\>\> - Map of token address to balance in base units

Example:

const balances = await readOnlyAccount.getTokenBalances([
  '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
  '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'  // USDC
])
for (const [address, balance] of balances) {
  console.log(`Token ${address}: ${balance}`)
}

Types

EvmErc4337WalletConfig

The configuration is a union type combining common fields with one of three gas payment modes:

// Common fields (required for all modes)
interface EvmErc4337WalletCommonConfig {
  chainId: number;                          // Blockchain ID
  provider: string | Eip1193Provider | Array<string | Eip1193Provider>; // RPC provider or failover list
  bundlerUrl: string;                       // Bundler service URL
  safeModulesVersion: string;               // Safe modules version (e.g., '0.3.0')
}

// Mode 1: Paymaster Token
interface EvmErc4337WalletPaymasterTokenConfig {
  isSponsored?: false;
  useNativeCoins?: false;
  paymasterUrl: string;                     // Paymaster service URL
  paymasterAddress: string;                 // Paymaster contract address
  paymasterToken: { address: string };      // ERC-20 token for fees
  transferMaxFee?: number | bigint;         // Maximum fee limit
}

// Mode 2: Sponsorship Policy
interface EvmErc4337WalletSponsorshipPolicyConfig {
  isSponsored: true;
  useNativeCoins?: false;
  paymasterUrl: string;                     // Paymaster service URL
  sponsorshipPolicyId?: string;             // Sponsorship policy ID
}

// Mode 3: Native Coins
interface EvmErc4337WalletNativeCoinsConfig {
  isSponsored?: false;
  useNativeCoins: true;
  transferMaxFee?: number | bigint;         // Maximum fee limit
}

// Full config type
type EvmErc4337WalletConfig = EvmErc4337WalletCommonConfig &
  (EvmErc4337WalletPaymasterTokenConfig |
   EvmErc4337WalletSponsorshipPolicyConfig |
   EvmErc4337WalletNativeCoinsConfig);

Config Override

The config parameter on sendTransaction, quoteSendTransaction, transfer, and quoteTransfer allows per-call overrides of gas payment settings:

type ConfigOverride = Partial<
  EvmErc4337WalletPaymasterTokenConfig |
  EvmErc4337WalletSponsorshipPolicyConfig |
  EvmErc4337WalletNativeCoinsConfig
>;

Available override fields:

  • isSponsored (boolean): Switch to sponsorship mode
  • useNativeCoins (boolean): Switch to native coin mode
  • paymasterUrl (string): Override paymaster URL
  • paymasterAddress (string): Override paymaster contract
  • paymasterToken ({address: string}): Override paymaster token
  • sponsorshipPolicyId (string): Set sponsorship policy
  • transferMaxFee (number | bigint): Override maximum fee

EvmErc4337Transaction

The transaction shape accepted by sendTransaction, quoteSendTransaction, and signTransaction. Beyond the call fields (to, value, data), it accepts optional gas overrides that are applied to the resulting UserOperation.

interface EvmErc4337Transaction {
  to: string;                               // Recipient address
  value: number | bigint;                   // Amount of native coin in wei
  data?: string;                            // Call data in hex format (optional)
  callGasLimit?: number | bigint;           // Override the UserOperation call gas limit (optional)
  verificationGasLimit?: number | bigint;   // Override the UserOperation verification gas limit (optional)
  preVerificationGas?: number | bigint;     // Override the UserOperation pre-verification gas (optional)
  maxFeePerGas?: number | bigint;           // Override the UserOperation max fee per gas — EIP-1559 cap (optional)
  maxPriorityFeePerGas?: number | bigint;   // Override the UserOperation max priority fee per gas (optional)
}

The gas-override fields are optional. When omitted, the gas limits fall back to AbstractionKit's estimation and the fee pair (maxFeePerGas / maxPriorityFeePerGas) falls back to the bundler-fetched gas price. Setting either fee field disables the bundler-fetched fee fallback for both, so set them together. In a batched call (tx passed as an array), only the gas overrides on the first transaction are honored — a UserOperation carries a single set of gas fields regardless of how many calls it batches.

TransferOptions

interface TransferOptions {
  token: string;                            // ERC20 token contract address
  recipient: string;                        // Recipient address
  amount: number | bigint;                  // Amount in token base units
}

ApproveOptions

interface ApproveOptions {
  token: string;                            // ERC20 token contract address
  spender: string;                          // Address allowed to spend tokens
  amount: number | bigint;                  // Amount to approve in base units
}

TransactionResult

interface TransactionResult {
  hash: string;                             // UserOperation hash
  fee: bigint;                              // Fee paid
}

TransferResult

interface TransferResult {
  hash: string;                             // UserOperation hash
  fee: bigint;                              // Fee paid
}

TypedData

interface TypedData {
  domain: TypedDataDomain;                  // EIP-712 domain separator
  types: Record<string, TypedDataField[]>;  // Type definitions
  primaryType: string;                      // Primary type name
  message: Record<string, unknown>;         // Structured message data
}

TypedDataDomain

interface TypedDataDomain {
  name?: string;                            // DApp or protocol name
  version?: string;                         // Domain version
  chainId?: number;                         // Blockchain ID
  verifyingContract?: string;               // Contract address
  salt?: string;                            // Optional salt
}

TypedDataField

interface TypedDataField {
  name: string;                             // Field name
  type: string;                             // Solidity type (e.g., 'address', 'uint256')
}

UserOperationReceipt

interface UserOperationReceipt {
  userOpHash: string;                       // UserOperation hash
  sender: string;                           // Sender address
  nonce: bigint;                            // Nonce
  actualGasUsed: bigint;                    // Gas used
  actualGasCost: bigint;                    // Gas cost
  success: boolean;                         // Whether the operation succeeded
  receipt: EvmTransactionReceipt;           // The underlying transaction receipt
}

ConfigurationError

class ConfigurationError extends Error {
  // Thrown when the wallet configuration is invalid
  // e.g., missing required fields for the selected gas payment mode
}

FeeRates

interface FeeRates {
  normal: bigint;                             // Fee rate for normal priority
  fast: bigint;                               // Fee rate for fast priority
}

KeyPair

interface KeyPair {
  publicKey: Uint8Array;                      // The public key
  privateKey: Uint8Array | null;              // The private key (null after dispose)
}

Internal Constants

The following constants are used internally by the SDK and are not importable from the package entry point.

// Used by predictSafeAddress() for deterministic address generation
// Not re-exported from '@tetherto/wdk-wallet-evm-erc-4337'
const SALT_NONCE: string = '0x69b348339eea4ed93f9d11931c3b894c8f9d8c7663a053024b11cb7eb4e5a1f6';

// Fee rate multipliers (protected static on WalletManagerEvm)
// Applied internally by getFeeRates()
const _FEE_RATE_NORMAL_MULTIPLIER: bigint;  // ~110%
const _FEE_RATE_FAST_MULTIPLIER: bigint;    // ~200%

Need Help?

On this page