Skip to content

Receive addresses and viewing ​

Issue an address from a wallet ​

ts
import type { AccountRecord, WalletClient } from '@zcashlabs/zcash.js';

export async function receiveAddress(wallet: WalletClient, account: AccountRecord) {
  const issued = await wallet.addresses.next({
    accountId: account.id,
    request: { format: 'unified', transparent: 'omit', sapling: 'omit', ironwood: 'require' },
  });
  return issued.address;
}

This Ironwood-only address matches the endpoint wallet’s default spending policy. Request additional receivers only when your spending policy and network support those pools. Omitting receiver requirements still exposes all supported receivers; the SDK default is unchanged.

next commits address exposure before returning. Display the returned string in your receive UI or QR code. current({ accountId, request }) is a local read returning a string or null; it does not allocate an address. list returns issued records. at({ accountId, index, request }) exposes an exact derivation index and is a write.

Use { format: 'transparent' } for a transparent address. Explicit unified receiver requirements can fail when the account lacks the required viewing components.

Derive without a wallet database ​

ts
import { accountFromViewingKey, addresses, diversifierIndex } from '@zcashlabs/zcash.js';
import type { Network } from '@zcashlabs/zcash.js';

export async function deriveAddress(network: Network, encoded: string) {
  const account = await accountFromViewingKey({
    network, format: 'ufvk', encoded, enabledPools: ['transparent', 'sapling', 'ironwood'],
  });
  try {
    return await addresses.find({
      account,
      start: diversifierIndex(0n),
      maxAttempts: 100,
      request: { format: 'unified' },
    });
  } finally {
    await account.viewing.dispose();
  }
}

Standalone derivation does not record address exposure in a wallet. Prefer wallet address methods for wallet receive flows. addresses.derive tries an exact index; find performs a bounded search. addresses.decode inspects an address, and addresses.selectReceiver chooses a supported receiver for a consensus context.

viewing.toIncoming({ account }) creates a separate incoming-viewing descriptor. Dispose each descriptor's viewing handle independently. viewing.export requires explicit acknowledge: 'discloses-viewing-authority' because a viewing key reveals private account information.

Inspect and select a receiver ​

Use a reviewed proposal's context when available. For standalone selection, derive one from the registered network and intended transaction height:

ts
import { addresses, getConsensusContext } from '@zcashlabs/zcash.js';
import type { Network, Pool } from '@zcashlabs/zcash.js';

export async function receiver(network: Network, targetHeight: number, encoded: string, pool: Pool) {
  const context = getConsensusContext({ network, targetHeight });
  const address = await addresses.decode({ network, address: encoded });
  return addresses.selectReceiver({ address, pool, context });
}

Decoding exposes known receivers and unknown typecodes. A decodable address is not automatically usable for every pool or transaction context.