Quickstart
This page builds a wallet on Ethereum, Base, Bitcoin, Solana, TON, Tron and NEAR from one
seed phrase. Every snippet comes from examples/quickstart in the SDK repository, which
our CI compiles and runs on every change.
1. Imports
Section titled “1. Imports”import { Wallet, type Policies } from '@anywalletkit/kit'import { getRandomSeedPhrase, isValidSeedPhrase } from '@anywalletkit/core'import { WalletManagerEvm } from '@anywalletkit/wallet-evm'import { WalletManagerBtc } from '@anywalletkit/wallet-btc'import { WalletManagerSolana } from '@anywalletkit/wallet-solana'import { WalletManagerTon } from '@anywalletkit/wallet-ton'import { WalletManagerTron } from '@anywalletkit/wallet-tron'import { WalletManagerNear } from '@anywalletkit/wallet-near'2. Chain ids
Section titled “2. Chain ids”The SDK names chains with CAIP-2 ids: one string format for every ecosystem.
// CAIP-2 chain ids: one string names a chain on any ecosystem.export const ETHEREUM = 'eip155:1'export const BASE = 'eip155:8453'export const BITCOIN = 'bip122:000000000019d6689c085ae165831e93'export const SOLANA = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'export const TON = 'ton:-239'export const TRON = 'tron:0x2b6653dc'export const NEAR = 'near:mainnet'3. A seed phrase
Section titled “3. A seed phrase”export function newSeedPhrase(): string { return getRandomSeedPhrase(12) // or 24}
export function checkSeedPhrase(words: string): boolean { return isValidSeedPhrase(words) // BIP-39 wordlist + checksum}4. Create the wallet
Section titled “4. Create the wallet”Wallet is the orchestrator from @anywalletkit/kit. Register one chain package per
chain (or per chain family), each with its own RPC endpoint. Managers are built lazily,
on first use.
export function createWallet(seedPhrase: string, policies?: Policies): Wallet { const wallet = new Wallet(seedPhrase, policies ? { policies } : {})
// One EVM registration per network: each has its own RPC. wallet.registerWallet(ETHEREUM, WalletManagerEvm, { provider: 'https://ethereum-rpc.publicnode.com', chainId: 1 }) wallet.registerWallet(BASE, WalletManagerEvm, { provider: 'https://base-rpc.publicnode.com', chainId: 8453 })
// Other ecosystems register by namespace. wallet.registerWallet('bip122', WalletManagerBtc, { client: { type: 'esplora-http', clientConfig: { url: 'https://mempool.space/api' } }, }) wallet.registerWallet('solana', WalletManagerSolana, { provider: 'https://api.mainnet-beta.solana.com' }) wallet.registerWallet('ton', WalletManagerTon, { tonClient: { url: 'https://toncenter.com/api/v2/jsonRPC' } }) wallet.registerWallet('tron', WalletManagerTron, { provider: 'https://api.trongrid.io' }) wallet.registerWallet('near', WalletManagerNear, { provider: 'https://free.rpc.fastnear.com' })
return wallet}5. Addresses
Section titled “5. Addresses”export async function addresses(wallet: Wallet): Promise<Record<string, string>> { const out: Record<string, string> = {} for (const chain of [ETHEREUM, BASE, BITCOIN, SOLANA, TON, TRON, NEAR]) { const account = await wallet.getAccount(chain) // account #0; getAccount(chain, 1) for the next one out[chain] = await account.getAddress() } return out}Addresses are derived on the device, with no network calls. Every EVM network shares the same address. The default derivation paths are the common ones (MetaMask on EVM, Phantom on Solana and so on), so a user who imports a seed phrase from another wallet usually finds their funds. The paths are listed in Packages.
6. Balances
Section titled “6. Balances”Amounts are always bigint in the chain’s base units (wei, satoshi, lamports, nanotons…).
Format them for display yourself; never do money math with floating point numbers.
export async function ethBalance(wallet: Wallet): Promise<bigint> { const account = await wallet.getAccount(ETHEREUM) return account.getBalance() // wei, as bigint}
export async function usdtBalance(wallet: Wallet): Promise<bigint> { const account = await wallet.getAccount(ETHEREUM) return account.getTokenBalance('0xdAC17F958D2ee523a2206206994597C13D831ec7') // USDT, 6 decimals}7. Send
Section titled “7. Send”Every account has the same transfer call on every chain. Quote the fee first, show it
to the user, then send:
export async function sendUsdt(wallet: Wallet, recipient: string, amount: bigint) { const account = await wallet.getAccount(ETHEREUM) const transfer = { token: '0xdAC17F958D2ee523a2206206994597C13D831ec7', recipient, amount }
const { fee } = await account.quoteTransfer(transfer) // network fee in wei, nothing is signed console.log('fee', fee)
const { hash } = await account.transfer(transfer) // simulate → sign → broadcast const receipt = await account.getTransactionReceipt(hash) // undefined until mined return { hash, receipt }}transfer simulates the transaction before signing it. A transaction that would revert
is refused before anything is signed.
8. Sign a message
Section titled “8. Sign a message”export async function signIn(wallet: Wallet, message: string) { const account = await wallet.getAccount(ETHEREUM) const signature = await account.sign(message) // EIP-191 personal_sign const valid = await account.verify(message, signature) return { signature, valid }}9. Policies
Section titled “9. Policies”Policies run before every signature and broadcast, including those made by protocol modules (swaps, staking…) through the same account. Pass them when you create the wallet:
export const policies: Policies = { // Refuse any Ethereum write whose quoted fee is above 0.005 ETH. maxFee: { [ETHEREUM]: 5_000_000_000_000_000n }, // Never send to these addresses. blocklist: { [ETHEREUM]: ['0x000000000000000000000000000000000000dEaD'] }, // The last word before anything is signed: show your confirmation sheet here. confirm: async (intent) => { console.log(`${intent.method} on ${intent.chain} → ${intent.to ?? 'contract'}`) return true },}const wallet = createWallet(seedPhrase, policies)More in Policies.
10. Clean up
Section titled “10. Clean up”wallet.dispose() overwrites the seed and every derived key in memory with zeros. Call
it when the wallet locks or the user signs out, and build a new Wallet when they
unlock.
wallet.dispose()Try it on a testnet
Section titled “Try it on a testnet”The same code runs on a testnet: register the testnet’s chain id with its RPC and chainId,
and fund the address from a faucet.
wallet.registerWallet('eip155:11155111', WalletManagerEvm, { provider: 'https://sepolia.drpc.org', chainId: 11155111 }) // Sepoliaconst account = await wallet.getAccount('eip155:11155111')await account.getAddress() // the same address as on mainnet: fund it from a Sepolia faucetBase Sepolia, Arbitrum Sepolia, OP Sepolia, Polygon Amoy, BSC and Monad testnets work the same way. The Networks table ships every supported testnet (Solana devnet, Bitcoin testnet4, TON testnet, Tron Nile, NEAR testnet too) switched off, with its RPC list; show a clear “testnet” badge in the UI whenever one is on.