Cross-chain USDT0 bridging with Tether WDK and LayerZero
npm install @t402/wdk-bridgeCross-chain USDT0 bridging with Tether WDK and LayerZero.
- Multi-Chain Bridging: Bridge USDT0 between Ethereum, Arbitrum, Ink, Berachain, and Unichain
- Auto-Routing: Automatic source chain selection based on balance and fees
- Route Strategies: Choose cheapest, fastest, or preferred chain
- Delivery Tracking: Track bridge status via LayerZero Scan
- Balance Management: Query USDT0 balances across all configured chains
``bash`
npm install @t402/wdk-bridgeor
pnpm add @t402/wdk-bridge
`bash`
npm install @tetherto/wdk @tetherto/wdk-wallet-evm
`typescript
import { WdkBridgeClient } from '@t402/wdk-bridge'
// Create client with WDK accounts for multiple chains
const bridge = new WdkBridgeClient({
accounts: {
ethereum: ethereumWdkAccount,
arbitrum: arbitrumWdkAccount,
},
defaultStrategy: 'cheapest',
})
// Get balances across all chains
const summary = await bridge.getBalances()
console.log(Total USDT0: ${summary.totalUsdt0})
// Auto-bridge from the best source chain
const result = await bridge.autoBridge({
toChain: 'ethereum',
amount: 100_000000n, // 100 USDT0
recipient: '0xRecipientAddress...',
})
// Wait for delivery
const delivery = await result.waitForDelivery()
if (delivery.success) {
console.log(Delivered! Destination tx: ${delivery.dstTxHash})`
}
#### Constructor
`typescript
interface WdkBridgeClientConfig {
accounts: Record
defaultStrategy?: RouteStrategy // 'cheapest' | 'fastest' | 'preferred'
defaultSlippage?: number // Default: 0.5 (0.5%)
}
const bridge = new WdkBridgeClient(config)
`
#### autoBridge(params): Promise
Execute a bridge with automatic source chain selection.
`typescript
interface AutoBridgeParams {
toChain: string // Destination chain
amount: bigint // Amount in USDT0 decimals (6)
recipient: Address // Recipient address on destination
preferredSourceChain?: string // Optional preferred source
slippageTolerance?: number // Slippage tolerance (default: 0.5%)
}
interface WdkBridgeResult {
txHash: Hex // Source transaction hash
messageGuid: string // LayerZero message GUID
amountSent: bigint // Amount sent
amountToReceive: bigint // Expected amount to receive
fromChain: string // Source chain
toChain: string // Destination chain
estimatedTime: number // Estimated delivery time (seconds)
waitForDelivery(options?: WaitOptions): Promise
}
`
#### bridge(params): Promise
Execute a bridge from a specific chain.
`typescript`
await bridge.bridge({
fromChain: 'arbitrum',
toChain: 'ethereum',
amount: 50_000000n,
recipient: '0x...',
})
#### getRoutes(toChain, amount): Promise
Get all available routes to a destination.
`typescript`
interface BridgeRoute {
fromChain: string
toChain: string
nativeFee: bigint // Fee in native token
amountToSend: bigint
minAmountToReceive: bigint
estimatedTime: number // Seconds
available: boolean
unavailableReason?: string
}
#### getBalances(): Promise
Get USDT0 balances across all configured chains.
`typescript
interface BalanceSummary {
balances: ChainBalance[]
totalUsdt0: bigint
chainsWithBalance: string[]
bridgeableChains: string[] // Chains with enough for bridge minimum
}
interface ChainBalance {
chain: string
chainId: number
usdt0Balance: bigint
nativeBalance: bigint
canBridge: boolean
}
`
#### getChainBalance(chain): Promise
Get balance for a specific chain.
#### trackMessage(guid): Promise
Track a LayerZero message by GUID.
#### waitForDelivery(guid, options): Promise
Wait for a message to be delivered.
| Chain | Chain ID | LayerZero EID |
| --------- | -------- | ------------- |
| Ethereum | 1 | 30101 |
| Arbitrum | 42161 | 30110 |
| Ink | 57073 | 30291 |
| Berachain | 80094 | 30362 |
| Unichain | 130 | 30320 |
| Strategy | Description |
| ----------- | ------------------------------------------------------ |
| cheapest | Select route with lowest native fee (default) |fastest
| | Select route with shortest estimated time |preferred
| | Use preferred chain if available, fallback to cheapest |
| Route | Time |
| ------------------------------- | ----------- |
| L1 -> L2 (Ethereum -> Arbitrum) | ~3 minutes |
| L2 -> L1 (Arbitrum -> Ethereum) | ~15 minutes |
| L2 -> L2 (Cross-L2) | ~5 minutes |
`typescript
import {
BRIDGE_CHAINS,
USDT0_ADDRESSES,
CHAIN_IDS,
MIN_BRIDGE_AMOUNT,
DEFAULT_SLIPPAGE,
supportsBridging,
getUsdt0Address,
getChainId,
getEstimatedBridgeTime,
} from '@t402/wdk-bridge'
// Minimum bridge amount (1 USDT0)
console.log(MIN_BRIDGE_AMOUNT) // 1_000000n
// Check if chain supports bridging
supportsBridging('arbitrum') // true
supportsBridging('polygon') // false
// Get USDT0 address
getUsdt0Address('ethereum')
// '0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee'
`
`typescript
const bridge = new WdkBridgeClient({
accounts: {
ethereum: ethAccount,
arbitrum: arbAccount,
ink: inkAccount,
},
})
const summary = await bridge.getBalances()
console.log(Total USDT0: ${summary.totalUsdt0 / 1_000000n} USDT0)Chains with balance: ${summary.chainsWithBalance.join(', ')}
console.log()Bridgeable from: ${summary.bridgeableChains.join(', ')}
console.log()`
`typescript
const routes = await bridge.getRoutes('ethereum', 100_000000n)
for (const route of routes) {
if (route.available) {
console.log(
${route.fromChain} -> ${route.toChain}: +fee=${route.nativeFee}, time=${route.estimatedTime}s
,${route.fromChain}: ${route.unavailableReason}
)
} else {
console.log()`
}
}
`typescript
const result = await bridge.autoBridge({
toChain: 'ethereum',
amount: 50_000000n,
recipient: '0x...',
})
console.log(Bridge initiated: ${result.txHash})Message GUID: ${result.messageGuid}
console.log()Expected delivery: ${result.estimatedTime}s
console.log()
// Track delivery with status updates
const delivery = await result.waitForDelivery({
timeout: 600_000, // 10 minutes
pollInterval: 10_000, // 10 seconds
onStatusChange: (status) => {
console.log(Status: ${status})
},
})
if (delivery.success) {
console.log(Delivered in tx: ${delivery.dstTxHash})Failed: ${delivery.error}
} else {
console.log()`
}
`typescript
const bridge = new WdkBridgeClient({
accounts: { arbitrum: arbAccount },
})
// Set custom RPC URL
bridge.setRpcUrl('arbitrum', 'https://arb1.arbitrum.io/rpc')
`
- @t402/core - Core protocol types and client@t402/wdk
- - Tether WDK integration@t402/wdk-gasless
- - ERC-4337 gasless payments@t402/wdk-multisig
- - Safe multi-sig wallets@t402/evm` - EVM mechanism implementation
-
Apache-2.0