Wallet
Core SDK — Wallet
This guide covers wallet creation, address/balance APIs, signing, sending, and receipt polling.
Prerequisites
- User should be authenticated (
sdk.signIn()completed). - EVM chain routing requires
chainIdin CAIP-2 format (e.g.eip155:612044).
Address & wallet APIs
const address = await sdk.getAddress() // { address, index } | null
const byIndex = await sdk.getAddress(0) // specific derivation index
const all = await sdk.getAddresses() // [{ address, index }, ...]
const wallet = await sdk.createWallet() // { address }
// Synchronous access (no API call)
const addr = sdk.currentAddress // string | null
const userId = sdk.currentUserId // string | nullWallet selector
Display a wallet selection modal when the user has multiple wallets:
// Show wallet selector (no "selected" indicator)
const wallet = await sdk.selectWallet()
// Show wallet selector with current address highlighted as "selected"
const wallet = await sdk.selectWallet(currentAddress)
if (wallet) {
console.log(wallet.address, wallet.index)
await sdk.signMessage(chainId, message, { index: wallet.index })
}| Parameter | Type | Description |
|---|---|---|
currentAddress | string? | If provided, the matching wallet is highlighted with a "selected" tag in the popup |
selectWallet() emits an addressChanged event when a wallet is selected, which automatically updates sdk.currentAddress, the wagmi provider state, and CROSSxProvider (React).
Automatic selection during sign-in
signInWithCreate() calls selectWallet() automatically when 2+ wallets exist. You don't need to call selectWallet() manually after signInWithCreate():
// Wallet selector modal appears automatically if user has 2+ wallets
const result = await sdk.signInWithCreate()
console.log(result.address) // the wallet user selectedBalance & nonce
const chainId = 'eip155:612044'
const { wei, formatted } = await sdk.getBalance(chainId)
console.log(`Balance: ${formatted}`) // "1.234567 CROSS"
const nonce = await sdk.getNonce(chainId)Sign message
All signing methods display a user confirmation modal.
const chainId = 'eip155:612044'
const { signature } = await sdk.signMessage(chainId, 'Hello, World!')
// With options: customize confirmation modal
const { signature } = await sdk.signMessage(chainId, 'Hello, World!', {
dappName: 'My DApp',
accountName: 'Account 1',
index: 0,
})Sign EIP-712 typed data
// On-chain (domain.chainId required — e.g. Permit)
const { signature } = await sdk.signTypedData(chainId, {
domain: { name: 'MyApp', version: '1', chainId: 612044 },
types: { /* ... */ },
primaryType: 'MyType',
message: { /* ... */ },
}, { dappName: 'My DApp' })
// Off-chain (no domain.chainId — e.g. EIP-712 order signatures)
const { signature } = await sdk.signTypedDataOffchain({
domain: { name: 'MyApp' },
types: { /* ... */ },
primaryType: 'MyType',
message: { /* ... */ },
})Sign transaction (without broadcasting)
const { signedTx, txHash } = await sdk.signTransaction(chainId, {
from: '0xYourAddress...',
to: '0xRecipient...',
value: '0x0',
data: '0x',
}, { dappName: 'My DApp' })Send transaction
const { txHash } = await sdk.sendTransaction(chainId, {
from: '0xYourAddress...',
to: '0xRecipient...',
value: '0xDE0B6B3A7640000', // 1 ETH in wei (hex)
data: '0x',
}, { dappName: 'My DApp' })Send + wait for receipt
const { txHash, receipt } = await sdk.sendTransactionWithWaitForReceipt(
chainId,
{ from: '0xYourAddress...', to: '0x...', value: '0x...', data: '0x' },
{ intervalMs: 2000, timeoutMs: 30000 }
)
console.log(receipt.status) // '0x1' (success) | '0x0' (reverted)For transaction sign/send flows, from must be provided (non-empty).
Manual receipt polling
const receipt = await sdk.waitForTxAndGetReceipt(
'0xTxHash...',
chainId,
{ intervalMs: 1000, timeoutMs: 30000 }
)EIP-1193 Provider
Standard provider for ethers.js, viem, and wagmi integration:
const provider = sdk.getProvider('eip155:612044')
// ethers.js v6
import { BrowserProvider } from 'ethers'
const ethersProvider = new BrowserProvider(provider)
// viem
import { createWalletClient, custom } from 'viem'
const client = createWalletClient({ transport: custom(provider) })Chain info
// Get all supported chains
const chains = await sdk.getChains()
chains.forEach(c => console.log(c.chainId, c.rpcUrl))
// Get specific chain info
const chain = await sdk.getChain('eip155:612044')
console.log(chain.rpcUrl) // 'https://testnet.crosstoken.io:22001'Gas helpers
const chainId = 'eip155:612044'
// Legacy gas price
const gasPrice = await sdk.getGasPrice(chainId) // hex string
// Estimate gas for a transaction
const gasLimit = await sdk.estimateGas(
{ from: '0x...', to: '0x...', value: '0x0' },
chainId,
) // hex string
// EIP-1559 base fee (null on legacy chains)
const baseFee = await sdk.getBaseFeePerGas(chainId)
// EIP-1559 priority fee (tip)
const tip = await sdk.getMaxPriorityFeePerGas(chainId)PIN management
The SDK supports PIN-based security for wallet operations. PIN is a 4-digit code used for transaction signing and wallet migration.
// Set PIN (cached in memory for the session)
sdk.setPin('1234')
// Check if PIN is set
const hasPinSet = sdk.hasPin() // boolean
// Clear cached PIN
sdk.clearPin()
// Change PIN (requires current PIN)
await sdk.changePin('1234', '5678')| Method | Signature | Description |
|---|---|---|
setPin | (pin: string): void | Cache PIN in memory for signing flows |
clearPin | (): void | Clear cached PIN from memory |
hasPin | (): boolean | Check if a PIN is cached |
changePin | (oldPin: string, newPin: string): Promise<void> | Change PIN on the server |
When a PIN is required but not cached, the SDK automatically displays a PIN input modal to the user.
RPC helpers
// Arbitrary RPC method call
const blockNumber = await sdk.walletRpc('eth_blockNumber', [], chainId)
walletRpcis for read-only calls only (e.g.eth_call). Transaction signing/sending is not supported via this API.
Updated 11 days ago