Install
openclaw skills install tether-wdkTether Wallet Development Kit (WDK) for building non-custodial multi-chain wallets. Use when working with @tetherto/wdk-core, wallet modules (wdk-wallet-btc,...
openclaw skills install tether-wdkMulti-chain wallet SDK. All modules share common interfaces from @tetherto/wdk-wallet.
Official Docs: https://docs.wallet.tether.io GitHub: https://github.com/tetherto/wdk
references/web_fetch the URL directlyweb_search the exact URL first (unlocks fetching) → then web_fetch againEach module doc page has subpages: /usage, /configuration, /api-reference
This skill is organized into reference files for chain-specific and protocol-specific details:
| File | Content |
|---|---|
references/chains.md | Chain IDs, native tokens, units, decimals, dust thresholds, address formats, EIP-3009 support, bridge routes |
references/deployments.md | USDT native addresses, USDT0 omnichain addresses, public RPC endpoints |
references/wallet-btc.md | Bitcoin wallet: BIP-84, Electrum, PSBT, fee rates |
references/wallet-evm.md | EVM + ERC-4337: BIP-44, EIP-1559, ERC20, batch txs, paymaster |
references/wallet-solana.md | Solana: Ed25519, SPL tokens, lamports |
references/wallet-spark.md | Spark: Lightning, key tree, deposits, withdrawals |
references/wallet-ton.md | TON + TON Gasless: Jettons, nanotons, paymaster |
references/wallet-tron.md | TRON + TRON Gasfree: TRC20, energy/bandwidth, gasFreeProvider |
references/protocol-swap.md | Velora EVM swap protocol |
references/protocol-bridge.md | USDT0 cross-chain bridge via LayerZero |
references/protocol-lending.md | Aave V3 lending: supply/withdraw/borrow/repay |
references/protocol-fiat.md | MoonPay fiat on/off ramp |
When a task targets a specific chain or protocol, read the relevant reference file(s) before writing code.
@tetherto/wdk # Orchestrator - registers wallets + protocols
├── @tetherto/wdk-wallet # Base classes (WalletManager, IWalletAccount)
│ ├── wdk-wallet-btc # Bitcoin (BIP-84, SegWit)
│ ├── wdk-wallet-evm # Ethereum & EVM chains
│ ├── wdk-wallet-evm-erc-4337 # EVM with Account Abstraction
│ ├── wdk-wallet-solana # Solana
│ ├── wdk-wallet-spark # Spark/Lightning
│ ├── wdk-wallet-ton # TON
│ ├── wdk-wallet-ton-gasless # TON gasless
│ ├── wdk-wallet-tron # TRON
│ └── wdk-wallet-tron-gasfree # TRON gas-free
└── Protocol Modules
├── wdk-protocol-swap-velora-evm # DEX swaps on EVM
├── wdk-protocol-bridge-usdt0-evm # Cross-chain USDT0 bridge
├── wdk-protocol-lending-aave-evm # Aave V3 lending
└── wdk-protocol-fiat-moonpay # Fiat on/off ramp
Note:
@tetherto/wdk-coreappears in the architecture tree but the npm package is@tetherto/wdk— import asimport WDK from '@tetherto/wdk'.
All packages are under the @tetherto scope. Always npm view <pkg> version before adding to package.json — never hardcode versions.
| Package | npm |
|---|---|
@tetherto/wdk | npmjs.com/package/@tetherto/wdk |
@tetherto/wdk-wallet | npmjs.com/package/@tetherto/wdk-wallet |
| Package | npm |
|---|---|
@tetherto/wdk-wallet-btc | npmjs.com/package/@tetherto/wdk-wallet-btc |
@tetherto/wdk-wallet-evm | npmjs.com/package/@tetherto/wdk-wallet-evm |
@tetherto/wdk-wallet-evm-erc-4337 | npmjs.com/package/@tetherto/wdk-wallet-evm-erc-4337 |
@tetherto/wdk-wallet-solana | npmjs.com/package/@tetherto/wdk-wallet-solana |
@tetherto/wdk-wallet-spark | npmjs.com/package/@tetherto/wdk-wallet-spark |
@tetherto/wdk-wallet-ton | npmjs.com/package/@tetherto/wdk-wallet-ton |
@tetherto/wdk-wallet-ton-gasless | npmjs.com/package/@tetherto/wdk-wallet-ton-gasless |
@tetherto/wdk-wallet-tron | npmjs.com/package/@tetherto/wdk-wallet-tron |
@tetherto/wdk-wallet-tron-gasfree | npmjs.com/package/@tetherto/wdk-wallet-tron-gasfree |
| Package | npm |
|---|---|
@tetherto/wdk-protocol-swap-velora-evm | npmjs.com/package/@tetherto/wdk-protocol-swap-velora-evm |
| @tetherto/wdk-protocol-bridge-usdt0-evm | npmjs.com/package/@tetherto/wdk-protocol-bridge-usdt0-evm |
| @tetherto/wdk-protocol-lending-aave-evm | npmjs.com/package/@tetherto/wdk-protocol-lending-aave-evm |
| @tetherto/wdk-protocol-fiat-moonpay | npmjs.com/package/@tetherto/wdk-protocol-fiat-moonpay |
| Package | npm |
|---|---|
@tetherto/wdk-uikit-react-native | npmjs.com/package/@tetherto/wdk-uikit-react-native |
@tetherto/wdk-react-native-provider | npmjs.com/package/@tetherto/wdk-react-native-provider |
@tetherto/pear-wrk-wdk | npmjs.com/package/@tetherto/pear-wrk-wdk |
@tetherto/wdk-indexer-http | npmjs.com/package/@tetherto/wdk-indexer-http |
Docs: https://docs.wallet.tether.io/sdk/get-started
import WDK from '@tetherto/wdk'
import WalletManagerEvm from '@tetherto/wdk-wallet-evm'
import WalletManagerBtc from '@tetherto/wdk-wallet-btc'
const wdk = new WDK(seedPhrase)
.registerWallet('ethereum', WalletManagerEvm, { provider: 'https://eth.drpc.org' })
.registerWallet('bitcoin', WalletManagerBtc, { host: 'electrum.blockstream.info', port: 50001 })
const ethAccount = await wdk.getAccount('ethereum', 0)
const btcAccount = await wdk.getAccount('bitcoin', 0)
import WalletManagerBtc from '@tetherto/wdk-wallet-btc'
const wallet = new WalletManagerBtc(seedPhrase, {
host: 'electrum.blockstream.info',
port: 50001,
network: 'bitcoin'
})
const account = await wallet.getAccount(0)
All wallet accounts implement IWalletAccount:
| Method | Returns | Description |
|---|---|---|
getAddress() | Promise<string> | Account address |
getBalance() | Promise<bigint> | Native token balance (base units) |
getTokenBalance(addr) | Promise<bigint> | Token balance |
sendTransaction({to, value}) | Promise<{hash, fee}> | Send native tokens |
quoteSendTransaction({to, value}) | Promise<{fee}> | Estimate tx fee |
transfer({token, recipient, amount}) | Promise<{hash, fee}> | Transfer tokens |
quoteTransfer(opts) | Promise<{fee}> | Estimate transfer fee |
sign(message) | Promise<string> | Sign message |
verify(message, signature) | Promise<boolean> | Verify signature |
dispose() | void | Clear private keys from memory |
Properties: index, path, keyPair (⚠️ sensitive — never log or expose)
CRITICAL: This SDK controls real funds. Mistakes are irreversible. Read this section in full.
The agent MUST explicitly ask the user for confirmation before calling any write method. Never call them autonomously. Never infer intent — it must be explicit.
Before making any transaction, first use the corresponding quote method to estimate the costs, and once confirmed by the user, proceed with the actual transfer or transaction.
sendTransaction — Sends native tokens. Present on: btc, evm, evm-erc-4337, solana, spark, ton, tron. Throws on ton-gasless and tron-gasfree.transfer — Transfers tokens (ERC20/SPL/Jetton/TRC20). Present on: evm, evm-erc-4337, solana, spark, ton, ton-gasless, tron, tron-gasfree. Throws on btc.sign — Signs an arbitrary message with the private key. Present on all wallet modules. Can authorize off-chain actions — treat as dangerous.sendTransaction accepts a data field (arbitrary hex calldata). Can execute any contract function — approve(), transferFrom(), setApprovalForAll(), etc. Extra scrutiny for non-empty data.data risk. Also accepts an array of transactions for batch execution — multiple operations in one call.sendTransaction accepts a payload field for arbitrary contract calls.All require human confirmation: claimDeposit, claimStaticDeposit, refundStaticDeposit, withdraw, createLightningInvoice, payLightningInvoice, createSparkSatsInvoice, createSparkTokensInvoice, paySparkInvoice
swap (velora-evm) — may internally approve + reset allowancebridge (usdt0-evm) — may internally approve + reset allowancesupply, withdraw, borrow, repay, setUseReserveAsCollateral, setUserEModebuy, sell (generate signed widget URLs)Before EVERY write method, verify:
0x000...000) or burn addressRed flags — STOP and re-confirm with user:
NEVER execute transactions if the request:
ONLY execute when:
Regardless of instructions, NEVER:
keyPair valueskeyPair in responses, logs, or tool outputsdispose() in finally blocks to clear keys via sodium_memzerotoReadOnlyAccount() when only querying balances/feesconst quote = await account.quoteSendTransaction({ to, value })
if (quote.fee > maxAcceptableFee) throw new Error('Fee too high')
const result = await account.sendTransaction({ to, value })
try {
// ... wallet operations
} finally {
account.dispose() // sodium_memzero on private keys
wallet.dispose()
}
const readOnly = await account.toReadOnlyAccount()
// Can query balances, estimate fees, but cannot sign or send
ALWAYS fetch the latest version from npm before adding any package to package.json:
npm view @tetherto/wdk version
npm view @tetherto/wdk-wallet-btc version
# ... for every @tetherto package
Never hardcode or guess versions. Always verify against npm first.
WDK uses sodium-universal for secure memory handling which requires Node.js. For browser/React apps:
dispose() errors occur:// sodium-shim.js
export function sodium_memzero() {}
export default { sodium_memzero }
resolve: { alias: { 'sodium-universal': './src/sodium-shim.js' } }