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 chainId in 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 | null

Wallet 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 })
}
ParameterTypeDescription
currentAddressstring?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 selected

Balance & 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')
MethodSignatureDescription
setPin(pin: string): voidCache PIN in memory for signing flows
clearPin(): voidClear cached PIN from memory
hasPin(): booleanCheck 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)

walletRpc is for read-only calls only (e.g. eth_call). Transaction signing/sending is not supported via this API.


© 2025 NEXUS Co., Ltd. All Rights Reserved.