Sending transactions¶
The SDK exposes four high-level send methods (sendTransaction, sendToMany, sendToken, sendNft), plus raw broadcast and aggregation for advanced flows.
Send NAV¶
const result = await client.sendTransaction({
address: 'tnv1...',
amount: 100_000_000n, // satoshis
memo: 'Coffee',
subtractFeeFromAmount: false, // default
});
console.log('txid:', result.txId);
console.log('fee:', Number(result.fee) / 1e8, 'NAV');
console.log('ins:', result.inputCount,
'outs:', result.outputCount);
SendTransactionOptions:
interface SendTransactionOptions {
address: string; // bech32m recipient
amount: bigint; // in satoshis
memo?: string; // UTF-8, stored encrypted
subtractFeeFromAmount?: boolean;
tokenId?: string | null; // null for NAV (default)
}
Result:
interface SendTransactionResult {
txId: string; // hex
rawTx: string; // hex
fee: bigint; // sats
inputCount: number;
outputCount: number; // includes change
}
Subtract fee from amount¶
Use when sending "everything in this wallet":
await client.sendTransaction({
address: 'tnv1...',
amount: 50_000_000n,
subtractFeeFromAmount: true,
});
Send to many¶
Pay several recipients in a single confidential NAV transaction. All recipients share one set of (auto- or manually-selected) NAV inputs and a single optional change output — cheaper and more private than N separate sends.
const result = await client.sendToMany({
recipients: [
{ address: 'tnv1...', amount: 100_000_000n, memo: 'invoice 1' },
{ address: 'tnv1...', amount: 50_000_000n },
{ address: 'tnv1...', amount: 25_000_000n, subtractFeeFromAmount: true },
],
});
console.log('txid:', result.txId);
console.log('outs:', result.outputCount); // recipients + change
SendToManyOptions:
interface SendRecipient {
address: string; // bech32m recipient
amount: bigint; // satoshis, must be > 0
memo?: string; // per-output memo
subtractFeeFromAmount?: boolean; // this recipient pays a share of the fee
}
interface SendToManyOptions {
recipients: SendRecipient[]; // one or more, non-empty
selectedUtxos?: string[]; // optional manual NAV UTXO selection (outputHashes)
}
When subtractFeeFromAmount is set on more than one recipient, the fee is split evenly between them (rounding remainder goes to the first such recipient). NAV only — for tokens/NFTs use sendToken / sendNft. Returns the same SendTransactionResult as sendTransaction.
Send token¶
await client.sendToken({
address: 'tnv1...',
amount: 25n,
tokenId: 'abcdef...64-hex...', // collection id
memo: 'Token payment',
});
Accepts the 64-hex collection id or an 80-hex full token id (auto-normalised to the 64-hex prefix).
Send NFT¶
Either pass a full 80-hex token id:
Or pass the collection + nft_id pair:
await client.sendNft({
address: 'tnv1...',
collectionTokenId: '<64-hex>',
nftId: 1n,
memo: 'NFT transfer',
});
Broadcast a pre-built raw tx¶
If you constructed a transaction manually (via createblsctrawtransaction + sign):
Aggregate transactions¶
Combine multiple independently-signed BLSCT transactions into one. Used for intra-chain swaps and coordinated multi-party transactions.
const aggregated = client.aggregateTransactions([
aliceSignedHex,
bobSignedHex,
]);
console.log(aggregated.txId);
await client.broadcastRawTransaction(aggregated.rawTx);
Return shape:
Does not broadcast automatically — call broadcastRawTransaction yourself after inspecting the aggregated tx.
Under the hood calls CTx.aggregateTransactions in navio-blsct.
Coin selection¶
The default selector:
- Partitions unspent outputs by
tokenId. - Picks outputs from the target
tokenIduntil the amount + estimated fee is covered. - Creates a BLSCT output to the destination and a change output back to a sub-address in the change pool (
account = -1). - Balances amount commitments.
Tweakable via raw-transaction RPC flows for fine-grained control.
Fee estimation¶
The SDK asks the backend for a fee rate (via Electrum's blockchain.estimatefee or RPC estimatesmartfee) and applies it to the estimated transaction size. No per-call override today — use the raw-transaction flow if you need explicit fee control.
Error cases¶
| Thrown error | Likely cause |
|---|---|
"insufficient funds" |
Not enough spendable UTXOs of the requested tokenId |
"wallet is locked" |
Call keyManager.unlock(pw) first |
"backend not connected" |
Run await client.initialize() / check backend health |
"invalid address" |
Malformed bech32m or wrong-network HRP |
"audit-only wallet" |
Wallet restored from audit key; no spend key |