Skip to main content
sendTransaction moves value out of a personal, single-signature wallet. Multisig transfers go through the order lifecycle instead. See Orders.
A wallet on a hardware root sends with prepareHardwareSend (or prepareHardwareTrustLine for XRP trust lines). sendTransaction throws HardwareSignerRequiredError for it. See Hardware Wallets.

Prerequisites

If the account runs in strict authentication, pass walletPassword on every signing call. Without it the SDK throws StrictAuthPasswordRequiredError.
Sending reconstructs a private key, so it needs the full session stack:
runWithUserRef scopes the signing user for the whole callback, keeping concurrent requests isolated. The alternative is passing userRef on each input.

SendTransactionInput

A memo on a chain that supports it is validated before anything else happens: an invalid memo throws InvalidInputError and no transaction is built.Only XRP, Solana and Tron support one. On EVM, Bitcoin and Cardano a memo is neither validated nor rejected. It is silently dropped, so nothing reaches the chain. Check isMemoSupported(chain) before offering the field.

RPC endpoints

Sends and fee quotes talk to a chain node. Defaults ship per network, and SDKConfig.rpcOverrides replaces them:
rpcOverrides is a flat map keyed by ChainIdValue, not a nested { evm: { 1: '…' } } object. EVM chain ids are the string form of the number ('1', not 1).
The shipped defaults are public endpoints: fine for trying things out, not for production throughput. Point rpcOverrides at your own nodes before you go live.
An EVM chain id with no default and no override throws No RPC endpoint configured for EVM chain ID {chainId}. Only the chain ids listed in Supported chains resolve out of the box; add any other through rpcOverrides.
Cardano ships no default RPC and does not need one: Cardano sends and fee quotes source their UTXOs from the Trustodian API rather than from a node.

Address validation

Validate before you send. These helpers check the address’s embedded checksum rather than matching a shape regex, so a single mistyped character is rejected instead of paid to an address nobody controls.
Two rejections are intentional: XRP X-addresses, since the destination tag is carried separately (see below), and Cardano Byron addresses (Ae2..., DdzFF...). Cardano addresses are also checked against the network, so a well-formed testnet address is rejected on mainnet.

Memos and destination tags

Only XRP, Solana and Tron carry a memo. EVM, Bitcoin and Cardano ignore memo entirely.
An empty memo is always valid.
sendTransaction calls validateMemo itself and throws InvalidInputError on failure, but only when isMemoSupported(chain) is true. A memo passed for an EVM or Bitcoin send is silently dropped, not rejected.

Spend authorization

Before a key is rebuilt, every send hands the unsigned transaction to Trustodian and gets back a single-use handle, which travels with the share request. This exists because the share request would otherwise carry a recipient and an amount that the client computed, and those are what the Address Book whitelist and the organization spending limit are enforced against. A caller could simply understate them. By reading the payee and amount out of the transaction that is actually about to be signed, the server enforces its policies against the real spend rather than a claim about it. The SDK does all of this inside sendTransaction; there is no method for you to call and nothing to configure. What you may see is its effect: a send can be refused by an organization policy at this step, before any signature exists. Nothing is reserved, so an abandoned send costs no allowance.

Per-chain behaviour

What each chain needs from you, and what it will refuse.
  • chainId selects both the RPC endpoint and the network; it defaults to 1.
  • Token sends need tokenAddress and decimals; native sends leave tokenAddress empty and set isNativeToken: true.
  • A chain id with no configured RPC throws No RPC endpoint configured for EVM chain ID ….
  • The RPC URL must be https://.
  • A native send will not leave the recipient below rent-exemption, and refuses rather than creating an unusable account.
  • Sending a token to a recipient who has no account for it creates that account in the same transaction, and the sender pays rent for it. Budget for that.
  • Both SPL and Token-2022 tokens are supported; the right one is detected from the mint.
  • Native sends keep about 0.3 TRX back for bandwidth, and refuse when the amount would eat into it: “Insufficient TRX for transaction. Please leave ~0.1 TRX for bandwidth costs.”
  • TRC-20 sends require both tokenAddress and decimals.
  • Sending to an account that is not yet activated costs roughly 1 TRX extra.
  • The recipient is checked against the active network before anything else.
  • Inputs are selected automatically and the fee comes from the current network rate.
  • Change below the dust limit is dropped into the fee rather than creating a dust output.
  • Chain type is BTC on mainnet and BTC_T3 on testnet.
  • For a token transfer, tokenAddress carries the policy id and symbol the asset name; both are required.
  • amount is the token amount. Every output must also carry a minimum of ADA, which the SDK derives. You do not choose it.
  • A token send needs pure-ADA UTXOs to pay from. If all the ADA is locked in UTXOs that also hold tokens, the send is refused and the tokens must be moved first.
  • Sending to yourself is refused up front.
  • For an issued asset, tokenAddress must be "currency.issuer", for example "USD.rIssuer...". A trust line for that pair must already exist; see XRP trust lines.
  • A numeric memo becomes the destination tag; a non-numeric one is dropped.
  • Every account locks 1 XRP as a base reserve plus 0.2 XRP per owned object, and that part of the balance cannot be spent.

Minimum balances and native currencies

These are the per-chain floors and native units the SDK works with, reproduced so you can apply the same thresholds yourself.
The native-asset column is one flat ETH for the whole EVM row. On Polygon, BNB Smart Chain or Avalanche the real native symbol is POL, BNB or AVAX, so label an EVM amount from EstimatedFee.currency, which is resolved per chain id, rather than from this table.

Fee estimation

payload.from is the wallet the quote is priced against. For a token transfer add tokenAddress and decimals. When chainId is omitted it defaults to the SDK’s network: '1' / '11155111' on EVM, sol_mainnet / sol_devnet, and so on. Pass the result back as feeHint on sendTransaction to reuse the quote instead of re-pricing it.
Always use the TransactionEstimatingType members rather than string literals, because an unrecognised value is priced as a plain transfer instead of throwing. The other operation types, the full EstimatedFee shape, and who pays what on each chain are covered in Multisig Fees.

New device or missing device share

If the device share for a wallet is absent or stale, pass walletPassword and the SDK performs a recovery rotation as part of the send. Without it, the failed send throws an error you can test with isDeviceShareRecoveryError(error), then retry after recovering explicitly.
To do the rotation explicitly instead, use ensureWalletReadyForCrypto or ensureWalletDeviceShare. See Keeping a device share current for the recovery pattern and what makes a share stale.

XRP trust lines

An XRP wallet can only hold an issued asset once a trust line to that currency/issuer pair is open. Opening one consumes 0.2 XRP of the account’s available balance as a reserve object.
Both address and issuer are validated before any network call. Opening the line needs roughly 0.2 XRP of available balance for the new reserve object.

Inspecting reserve and existing lines

Both read straight from the XRP ledger, with no Trustodian API call, and both validate the address first.

Errors worth handling

A reconstructed key that fails to derive the wallet’s address does not surface as a thrown KeyMismatchError instance; catch it with isDeviceShareRecoveryError(error) instead. See Keeping a device share current. Use isTrustodianError(error) to narrow before reading these fields. For the full error taxonomy, HTTP status mapping and retry guidance, see Errors.

Next

Preflight

Simulate the send before a signature is collected

Orders

Multisig transfers through the order lifecycle

Wallets

Creating, listing, and reading wallets

Address Book

Whitelisting payees before they can be paid
Last modified on October 27, 2026