Multi-Token Agent
An agent that handles payments in multiple tokens — ETH, WVRN, and USDC — with proper approval management.
Full Code
import { ethers } from 'ethers'
import { WeavrnClient } from '@weavrn/sdk'
const PRIVATE_KEY = process.env.PRIVATE_KEY!
// Token addresses on Base Sepolia
const TOKENS = {
WVRN: '0x1c17b46bd9b37024e86EA5fe05e1dE835aE1Ce0E',
USDC: '0x...', // your USDC address
}
async function main() {
const provider = new ethers.JsonRpcProvider('https://sepolia.base.org')
const signer = new ethers.Wallet(PRIVATE_KEY, provider)
const client = new WeavrnClient({ signer, chainId: 84532 })
if (!(await client.isRegistered())) {
await client.register('MultiTokenAgent', 'https://example.com/agent.json')
}
// Approve all tokens upfront with large allowances
await approveTokens(client)
// Now pay in any token
const recipient = '0xRecipient...'
// ETH — no approval needed
await client.pay(recipient, ethers.parseEther('0.001'), {
memo: 'eth payment',
})
// WVRN (18 decimals)
await client.payERC20(recipient, TOKENS.WVRN, ethers.parseEther('100'), {
memo: 'wvrn payment',
decimals: 18,
})
// USDC (6 decimals)
await client.payERC20(recipient, TOKENS.USDC, ethers.parseUnits('25', 6), {
memo: 'usdc payment',
decimals: 6,
})
}
async function approveTokens(client: WeavrnClient) {
const MAX_ALLOWANCE = ethers.MaxUint256
// Approve router for payments
for (const [name, address] of Object.entries(TOKENS)) {
console.log(`Approving ${name} for PaymentRouter...`)
await client.approveRouter(address, MAX_ALLOWANCE)
}
// Approve escrow for escrow-based payments
for (const [name, address] of Object.entries(TOKENS)) {
console.log(`Approving ${name} for EscrowRouter...`)
await client.approveEscrow(address, MAX_ALLOWANCE)
}
// Wait for approvals to propagate
await new Promise(r => setTimeout(r, 3000))
}
main().catch(console.error)Token Decimals
Different tokens use different decimal places. Always match the decimals parameter to the token:
| Token | Decimals | 1 unit in smallest unit |
|---|---|---|
| ETH | 18 | ethers.parseEther('1') |
| WVRN | 18 | ethers.parseEther('1') |
| USDC | 6 | ethers.parseUnits('1', 6) |
The decimals option in payERC20 only affects how the returned amount and fee strings are formatted — the on-chain transfer uses the raw bigint amount you provide.
Approval Strategy
Two approaches:
Max Approval (Simpler)
Approve ethers.MaxUint256 once per token per contract. Fewer transactions, but grants unlimited spending.
await client.approveRouter(token, ethers.MaxUint256)Exact Approval (Safer)
Approve the exact amount needed before each transaction. More gas, but limits exposure.
await client.approveRouter(token, ethers.parseEther('100'))
await client.payERC20(recipient, token, ethers.parseEther('100'))Important
approveRouterandapproveEscroware separate approvals to different contracts- If you use both payment and escrow features with the same token, approve both
- Wait 2-3 seconds after approval before the next transaction
Last updated on