$ npm install @tetherto/wdk-protocol-bridge-usdt0-evmNote: This package is currently in beta. Please test thoroughly in development environments before using in production.
A simple and secure package that lets EVM wallet accounts bridge USDT0 tokens across different blockchains. This package provides a clean SDK for moving tokens between EVM-compatible chains using the LayerZero protocol and USDT0 bridge system with support for both standard wallets and ERC-4337 smart accounts.
This module can be managed by the @tetherto/wdk package, which provides a unified interface for managing multiple WDK wallet and protocol modules across different blockchains.
This module is part of the WDK (Wallet Development Kit) project, which empowers developers to build secure, non-custodial wallets with unified blockchain access, stateless architecture, and complete user control.
For detailed documentation about the complete WDK ecosystem, visit docs.wallet.tether.io.
To install the @tetherto/wdk-protocol-bridge-usdt0-evm package, follow these instructions:
You can install it using npm:
npm install @tetherto/wdk-protocol-bridge-usdt0-evm
import WDK from '@tetherto/wdk'
import Usdt0ProtocolEvm from '@tetherto/wdk-protocol-bridge-usdt0-evm'
// Create WDK instance with EVM wallet support
const wdk = new WDK(seedPhrase)
.registerWallet('ethereum', WalletManagerEvm, {
provider: 'https://ethereum-rpc.publicnode.com'
})
.registerWallet('arbitrum', WalletManagerEvm, {
provider: 'https://arb1.arbitrum.io/rpc'
})
.registerProtocol('ethereum', 'usdt0', Usdt0ProtocolEvm, {
bridgeMaxFee: 100000000000000 // 0.0001 ETH in wei
})
// Get account with bridge protocol
const account = await wdk.getAccount('ethereum', 0)
const usdt0Bridge = account.getBridgeProtocol('usdt0')
// Perform bridge
const result = await usdt0Bridge.bridge({
targetChain: 'arbitrum',
recipient: 'RECIPIENT_ADDRESS',
token: 'USDT_TOKEN_ADDRESS',
amount: 1000000n // 1 USDT (6 decimals)
})
import Usdt0ProtocolEvm from '@tetherto/wdk-protocol-bridge-usdt0-evm'
import { WalletAccountEvm } from '@tetherto/wdk-wallet-evm'
// Use a BIP-39 seed phrase (replace with your own secure phrase)
const seedPhrase = 'test only example nut use this real life secret phrase must random'
// Create wallet account with provider config
const account = new WalletAccountEvm(seedPhrase, "0'/0/0", {
provider: 'https://ethereum-rpc.publicnode.com'
})
// Create bridge service with configuration
const bridgeProtocol = new Usdt0ProtocolEvm(account, {
bridgeMaxFee: 100000000000000n // Optional: Maximum bridge fee in wei
})
// OR for ERC-4337 smart accounts
import { WalletAccountEvmErc4337 } from '@tetherto/wdk-wallet-evm-erc-4337'
// Create ERC-4337 account
const smartAccount = new WalletAccountEvmErc4337(seedPhrase, "0'/0/0", {
provider: 'https://arb1.arbitrum.io/rpc',
bundlerUrl: 'YOUR_BUNDLER_URL',
paymasterUrl: 'YOUR_PAYMASTER_URL'
})
// Create bridge service for smart account
const smartBridgeProtocol = new Usdt0ProtocolEvm(smartAccount, {
bridgeMaxFee: 100000000000000n
})
// Bridge USDT from Ethereum to Arbitrum
const result = await bridgeProtocol.bridge({
targetChain: 'arbitrum', // Where to send tokens
recipient: 'RECIPIENT_ADDRESS', // Who gets the tokens on target chain
token: 'USDT_TOKEN_ADDRESS', // USDT token address on source chain
amount: 1000000n // Amount to bridge (1 USDT with 6 decimals)
})
console.log('Bridge transaction hash:', result.hash)
console.log('Total fee:', result.fee, 'wei')
console.log('Bridge fee:', result.bridgeFee, 'wei')
// Bridge from Arbitrum to Ethereum
const reverseResult = await bridgeProtocol.bridge({
targetChain: 'ethereum',
recipient: 'RECIPIENT_ADDRESS',
token: 'USDT_TOKEN_ADDRESS',
amount: 5000000n // 5 USDT
})
// Bridge to Polygon
const polygonResult = await bridgeProtocol.bridge({
targetChain: 'polygon',
recipient: 'RECIPIENT_ADDRESS',
token: 'USDT_TOKEN_ADDRESS',
amount: 10000000n // 10 USDT
})
// Get bridge cost estimate before executing
const quote = await bridgeProtocol.quoteBridge({
targetChain: 'arbitrum',
recipient: 'RECIPIENT_ADDRESS',
token: 'USDT_TOKEN_ADDRESS',
amount: 1000000n
})
console.log('Estimated gas fee:', quote.fee, 'wei')
console.log('Estimated bridge fee:', quote.bridgeFee, 'wei')
console.log('Total cost:', Number(quote.fee + quote.bridgeFee) / 1e18, 'ETH')
// Check if bridge is cost-effective
if (quote.fee + quote.bridgeFee > 100000000000000n) { // More than 0.0001 ETH
console.log('Bridge fees too high, consider waiting for lower gas prices')
} else {
// Execute the bridge
const result = await bridgeProtocol.bridge({
targetChain: 'arbitrum',
recipient: 'RECIPIENT_ADDRESS',
token: 'USDT_TOKEN_ADDRESS',
amount: 1000000n
})
}
// Bridge using ERC-4337 smart account with sponsored transactions
const smartAccountResult = await smartBridgeProtocol.bridge({
targetChain: 'ethereum',
recipient: 'RECIPIENT_ADDRESS',
token: 'USDT_TOKEN_ADDRESS',
amount: 1000000n
}, {
paymasterToken: 'USDT', // Use USDT to pay gas fees
bridgeMaxFee: 100000000000000n // Override max fee
})
console.log('Smart account bridge hash:', smartAccountResult.hash)
console.log('Gas fee paid in USDT:', smartAccountResult.fee)
console.log('Bridge service fee:', smartAccountResult.bridgeFee)
// Bridge different USDT0 ecosystem tokens
const tokens = [
{ address: 'USDT_TOKEN_ADDRESS', amount: 1000000n, name: 'USDT' },
{ address: 'XAUT_TOKEN_ADDRESS', amount: 1000000000000000000n, name: 'XAUT' }, // 18 decimals
]
for (const token of tokens) {
try {
// Get quote first
const quote = await bridgeProtocol.quoteBridge({
targetChain: 'arbitrum',
recipient: 'RECIPIENT_ADDRESS',
token: token.address,
amount: token.amount
})
console.log(`Bridge ${token.name} quote:`)
console.log(` Gas fee: ${quote.fee} wei`)
console.log(` Bridge fee: ${quote.bridgeFee} wei`)
// Execute bridge
const result = await bridgeProtocol.bridge({
targetChain: 'arbitrum',
recipient: 'RECIPIENT_ADDRESS',
token: token.address,
amount: token.amount
})
console.log(`${token.name} bridge successful: ${result.hash}`)
} catch (error) {
console.error(`${token.name} bridge failed:`, error.message)
}
}
// Bridge USDT0 from Ethereum to Solana
const solanaResult = await bridgeProtocol.bridge({
targetChain: 'solana',
recipient: 'HyXJcgYpURfDhgzuyRL7zxP4FhLg7LZQMeDrR4MXZcMN', // Solana base58 address
token: 'USDT_TOKEN_ADDRESS',
amount: 1000000n
})
// Bridge USDT0 from Ethereum to TON
const tonResult = await bridgeProtocol.bridge({
targetChain: 'ton',
recipient: 'EQAd31gAUhdO0d0NZsNb_cGl_Maa9PSuNhVLE9z8bBSjX6Gq', // TON address
token: 'USDT_TOKEN_ADDRESS',
amount: 1000000n
})
// Bridge USDT0 from Ethereum to TRON
const tronResult = await bridgeProtocol.bridge({
targetChain: 'tron',
recipient: 'TFG4wBaDQ8sHWWP1ACeSGnoNR6RRzevLPt', // TRON address
token: 'USDT_TOKEN_ADDRESS',
amount: 1000000n
})
// Use a custom OFT contract address (bypasses auto-resolution)
const result = await bridgeProtocol.bridge({
targetChain: 'arbitrum',
recipient: 'RECIPIENT_ADDRESS',
token: 'USDT_TOKEN_ADDRESS',
amount: 1000000n,
oftContractAddress: '0xYourCustomOftContractAddress'
})
// Override the destination endpoint ID
const result2 = await bridgeProtocol.bridge({
targetChain: 'arbitrum',
recipient: 'RECIPIENT_ADDRESS',
token: 'USDT_TOKEN_ADDRESS',
amount: 1000000n,
dstEid: 30110 // Custom LayerZero endpoint ID
})
// Both overrides work with quoteBridge too
const quote = await bridgeProtocol.quoteBridge({
targetChain: 'arbitrum',
recipient: 'RECIPIENT_ADDRESS',
token: 'USDT_TOKEN_ADDRESS',
amount: 1000000n,
oftContractAddress: '0xYourCustomOftContractAddress',
dstEid: 30110
})
// Compare bridge costs across different target chains
const sourceChain = 'ethereum'
const targetChains = ['arbitrum', 'optimism', 'polygon']
const amount = 1000000n
const token = 'USDT_TOKEN_ADDRESS'
const recipient = 'RECIPIENT_ADDRESS'
const quotes = await Promise.allSettled(
targetChains.map(async (chain) => {
const quote = await bridgeProtocol.quoteBridge({
targetChain: chain,
recipient,
token,
amount
})
return { chain, ...quote }
})
)
quotes.forEach((result, index) => {
if (result.status === 'fulfilled') {
const { chain, fee, bridgeFee } = result.value
console.log(`Bridge to ${chain}:`)
console.log(` Total cost: ${Number(fee + bridgeFee) / 1e18} ETH`)
} else {
console.error(`Bridge to ${targetChains[index]} failed:`, result.reason.message)
}
})
| Class | Description | Methods |
|---|---|---|
| Usdt0ProtocolEvm | Main class for bridging USDT0 tokens between EVM chains. Extends BridgeProtocol from @tetherto/wdk-wallet/protocols. | Constructor, Methods |
The main class for bridging USDT0 tokens between EVM-compatible blockchains using the LayerZero protocol.
Extends BridgeProtocol from @tetherto/wdk-wallet/protocols.
new Usdt0ProtocolEvm(account, config)
Parameters:
account (WalletAccountEvm | WalletAccountEvmErc4337 | WalletAccountReadOnlyEvm | WalletAccountReadOnlyEvmErc4337): The wallet account to use for bridge operationsconfig (object, optional): Configuration object
bridgeMaxFee (bigint, optional): Maximum total bridge cost in weiExample:
const bridgeProtocol = new Usdt0ProtocolEvm(account, {
bridgeMaxFee: 100000000000000n // Maximum bridge fee in wei (0.0001 ETH)
})
| Method | Description | Returns |
|---|---|---|
bridge(options, config?) | Bridges tokens between EVM chains | Promise<BridgeResult> |
quoteBridge(options, config?) | Gets the cost of a bridge operation | Promise<Omit<BridgeResult, 'hash'>> |
bridge(options, config?)Bridges tokens between blockchains using the USDT0 protocol.
Parameters:
options (BridgeOptions): Bridge operation options
targetChain (string): Where to send tokens (e.g. 'ethereum', 'arbitrum', 'polygon', 'solana', 'ton', 'tron', etc.)recipient (string): Address that will get the bridged tokens (EVM hex address, Solana base58, TON, or TRON address)token (string): Token address on source chainamount (bigint): Amount to bridge in token base unitsoftContractAddress (string, optional): Custom OFT contract address to use instead of auto-resolving from the source chaindstEid (number, optional): Custom LayerZero destination endpoint ID to override the default for the target chainconfig (Pick<EvmErc4337WalletConfig, 'paymasterToken'> & Pick<BridgeProtocolConfig, 'bridgeMaxFee'>, optional): Override settings for ERC-4337 accounts
paymasterToken ({ address: string }, optional): Paymaster token configurationbridgeMaxFee (bigint, optional): Override maximum bridge feeReturns: Promise<BridgeResult> - Bridge operation result
Example:
const result = await bridgeProtocol.bridge({
targetChain: 'arbitrum',
recipient: 'RECIPIENT_ADDRESS',
token: 'USDT_TOKEN_ADDRESS',
amount: 1000000n // 1 USDT (6 decimals)
})
quoteBridge(options, config?)Gets the cost of a bridge operation without executing it.
Parameters:
options (BridgeOptions): Same as bridge method (including optional oftContractAddress and dstEid overrides)config (Pick<EvmErc4337WalletConfig, 'paymasterToken'>, optional): Override settings for ERC-4337 accountsReturns: Promise<Omit<BridgeResult, 'hash'>> - Bridge cost estimate
Example:
const quote = await bridgeProtocol.quoteBridge({
targetChain: 'arbitrum',
recipient: 'RECIPIENT_ADDRESS',
token: 'USDT_TOKEN_ADDRESS',
amount: 1000000n
})
This package supports bridging from EVM source chains to both EVM and non-EVM destination chains.
EVM Source/Destination Chains (USDT0):
| Chain | Chain ID | EID |
|---|---|---|
| Ethereum | 1 | 30101 |
| Arbitrum | 42161 | 30110 |
| Berachain | 80094 | 30362 |
| Conflux eSpace | 1030 | 30212 |
| Corn | 21000000 | 30331 |
| Flare | 14 | 30295 |
| HyperEVM | 999 | 30367 |
| Ink | 57073 | 30339 |
| Mantle | 5000 | 30181 |
| MegaETH | 4326 | 30398 |
| Monad | 143 | 30390 |
| Morph | 2818 | 30322 |
| Optimism | 10 | 30111 |
| Plasma | 9745 | 30383 |
| Polygon | 137 | 30109 |
| Rootstock | 30 | 30333 |
| Sei | 1329 | 30280 |
| Stable | 988 | 30396 |
| Unichain | 130 | 30320 |
| XLayer | 196 | 30274 |
Legacy Mesh Chains (USDT0):
| Chain | EID |
|---|---|
| Ethereum | 30101 |
| Arbitrum | 30110 |
| Celo | 30125 |
| Solana | 30168 |
| TON | 30343 |
| TRON | 30420 |
Non-EVM Destination Chains:
XAUt0 (Tether Gold) Support:
| Chain | EID |
|---|---|
| Ethereum | 30101 |
| Arbitrum | 30110 |
| Avalanche | 30106 |
| Celo | 30125 |
| HyperEVM | 30367 |
| Ink | 30339 |
| Monad | 30390 |
| Plasma | 30383 |
| Polygon | 30109 |
| Stable | 30396 |
Account Types:
@tetherto/wdk-wallet-evm accounts@tetherto/wdk-wallet-evm-erc-4337 accounts with sponsored transactionsNote: Token support is determined by the contracts deployed on each chain. The protocol checks for oftContract, legacyMeshContract, and xautOftContract to determine available tokens.
bridgeMaxFee limits# Install dependencies
npm install
# Build TypeScript definitions
npm run build:types
# Lint code
npm run lint
# Fix linting issues
npm run lint:fix
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
For support, please open an issue on the GitHub repository.