Skip to content
SwapKit is a powerful suite of tools for building blockchain applications.

Zcash Integration

SwapKit provides comprehensive support for Zcash through the UTXO toolbox with specialized handling for Zcash transparent addresses. This guide covers everything you need to know about working with Zcash in your applications.

The Zcash integration in SwapKit supports:

  • Transparent addresses only (t1… for mainnet, t3… for testnet)
  • Custom address generation with 2-byte prefixes
  • PSBT-based transaction building for compatibility
  • Full UTXO management and fee estimation
  • Memo support via OP_RETURN outputs
  • bitcoinjs-lib + ecpair for cryptographic operations

SwapKit supports Zcash transparent addresses which provide Bitcoin-like functionality on the Zcash network:

import { Chain, getUtxoToolbox } from "@swapkit/sdk";
async function validateZcashAddresses() {
const zcashToolbox = await getUtxoToolbox(Chain.Zcash);
const mainnetValid = zcashToolbox.validateAddress(
"t1XVXWCvpMgBvUaed4XDqWtgQgJSu1Ghz7F"
);
console.log("Mainnet address valid:", mainnetValid);
const testnetValid = zcashToolbox.validateAddress(
"t3Vz22vK5z2LcKEdg16Yv4FFneEL1zg9ojd"
);
console.log("Testnet address valid:", testnetValid);
const shieldedValid = zcashToolbox.validateAddress(
"zs1z7rejlpsa98s2rrrfkwmaxu2xldqmfq5nj2m3hq6s7r8qjq8eqqqq9p4e7x"
);
console.log("Shielded address valid:", shieldedValid);
return { mainnetValid, testnetValid, shieldedValid };
}

Zcash uses 2-byte version prefixes for addresses, which requires custom generation logic:

import { Chain, getUtxoToolbox } from "@swapkit/sdk";
async function generateZcashAddress() {
const zcashToolbox = await getUtxoToolbox(Chain.Zcash, {
phrase:
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
});
const address = await zcashToolbox.getAddress();
console.log("Generated address:", address);
const keys = await zcashToolbox.createKeysForPath({
phrase:
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
derivationPath: "m/44'/133'/0'/0/0",
});
const customAddress = zcashToolbox.getAddressFromKeys(keys);
console.log("Custom path address:", customAddress);
return { address, customAddress };
}
import { Chain, getUtxoToolbox } from "@swapkit/sdk";
const zcashToolbox = await getUtxoToolbox(Chain.Zcash);
const signingToolbox = await getUtxoToolbox(Chain.Zcash, {
phrase: "your twelve word mnemonic phrase here",
index: 0,
});
const customToolbox = await getUtxoToolbox(Chain.Zcash, {
phrase: "your twelve word mnemonic phrase here",
derivationPath: [44, 133, 0, 0, 5],
});
import { Chain, getUtxoToolbox } from "@swapkit/sdk";
async function zcashKeyManagement() {
const zcashToolbox = await getUtxoToolbox(Chain.Zcash, {
phrase:
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
});
const address = await zcashToolbox.getAddress();
const keys = await zcashToolbox.createKeysForPath({
phrase:
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
derivationPath: "m/44'/133'/0'/0/0",
});
const publicKey = keys.publicKey;
const privateKey = keys.privateKey;
const wifKey = keys.toWIF();
const wifFromMnemonic = await zcashToolbox.getPrivateKeyFromMnemonic({
phrase:
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
derivationPath: "m/44'/133'/0'/0/0",
});
return {
address,
publicKey,
privateKey,
wifKey,
wifFromMnemonic,
};
}
import { AssetValue, Chain, FeeOption, getUtxoToolbox } from "@swapkit/sdk";
async function sendZcash() {
const zcashToolbox = await getUtxoToolbox(Chain.Zcash, {
phrase: "your twelve word mnemonic phrase here",
});
const amount = AssetValue.from({
chain: Chain.Zcash,
value: "0.001",
});
const txHash = await zcashToolbox.transfer({
recipient: "t1XVXWCvpMgBvUaed4XDqWtgQgJSu1Ghz7F",
assetValue: amount,
feeOptionKey: FeeOption.Fast,
memo: "Payment for services",
});
console.log("Transaction sent:", txHash);
return txHash;
}

Zcash supports memos via OP_RETURN outputs in transparent transactions:

import { AssetValue, Chain, FeeOption, getUtxoToolbox } from "@swapkit/sdk";
async function sendZcashWithMemo() {
const zcashToolbox = await getUtxoToolbox(Chain.Zcash, {
phrase: "your twelve word mnemonic phrase here",
});
const amount = AssetValue.from({
chain: Chain.Zcash,
value: "0.005",
});
const txHash = await zcashToolbox.transfer({
recipient: "t1XVXWCvpMgBvUaed4XDqWtgQgJSu1Ghz7F",
assetValue: amount,
feeOptionKey: FeeOption.Average,
memo: "Invoice #12345 - Payment for development work",
});
return txHash;
}

For advanced use cases, you can build transactions manually:

import { AssetValue, Chain, getUtxoToolbox } from "@swapkit/sdk";
async function buildZcashTransaction() {
const zcashToolbox = await getUtxoToolbox(Chain.Zcash, {
phrase: "your twelve word mnemonic phrase here",
});
const senderAddress = await zcashToolbox.getAddress();
const feeRates = await zcashToolbox.getFeeRates();
const { psbt, utxos, inputs } = await zcashToolbox.createTransaction({
recipient: "t1XVXWCvpMgBvUaed4XDqWtgQgJSu1Ghz7F",
assetValue: AssetValue.from({ chain: Chain.Zcash, value: "0.002" }),
sender: senderAddress,
feeRate: feeRates.fast,
memo: "Manual transaction",
});
console.log("PSBT created with", inputs.length, "inputs");
console.log("UTXOs used:", utxos.length);
return { psbt, utxos, inputs };
}
import { Chain, getUtxoToolbox } from "@swapkit/sdk";
async function getZcashFees() {
const zcashToolbox = await getUtxoToolbox(Chain.Zcash);
const feeRates = await zcashToolbox.getFeeRates();
console.log("Fee rates (satoshis per byte):");
console.log("Average:", feeRates.average);
console.log("Fast:", feeRates.fast);
console.log("Fastest:", feeRates.fastest);
return feeRates;
}
import { AssetValue, Chain, FeeOption, getUtxoToolbox } from "@swapkit/sdk";
async function estimateZcashFees() {
const zcashToolbox = await getUtxoToolbox(Chain.Zcash);
const senderAddress = "t1XVXWCvpMgBvUaed4XDqWtgQgJSu1Ghz7F";
const amount = AssetValue.from({ chain: Chain.Zcash, value: "0.001" });
const averageFee = await zcashToolbox.estimateTransactionFee({
sender: senderAddress,
recipient: "t1YourRecipientAddressHere",
assetValue: amount,
feeOptionKey: FeeOption.Average,
memo: "Test transaction",
});
const fastFee = await zcashToolbox.estimateTransactionFee({
sender: senderAddress,
recipient: "t1YourRecipientAddressHere",
assetValue: amount,
feeOptionKey: FeeOption.Fast,
});
console.log("Average fee:", averageFee.toString());
console.log("Fast fee:", fastFee.toString());
return { averageFee, fastFee };
}
import { Chain, FeeOption, getUtxoToolbox } from "@swapkit/sdk";
async function getMaxSendable() {
const zcashToolbox = await getUtxoToolbox(Chain.Zcash);
const address = "t1XVXWCvpMgBvUaed4XDqWtgQgJSu1Ghz7F";
const maxAmount = await zcashToolbox.estimateMaxSendableAmount({
from: address,
feeOptionKey: FeeOption.Fast,
recipients: 1,
memo: "Maximum transfer",
});
console.log("Maximum sendable:", maxAmount.toString());
return maxAmount;
}
import { Chain, getUtxoToolbox } from "@swapkit/sdk";
async function getZcashBalance() {
const zcashToolbox = await getUtxoToolbox(Chain.Zcash);
const address = "t1XVXWCvpMgBvUaed4XDqWtgQgJSu1Ghz7F";
const balance = await zcashToolbox.getBalance(address);
console.log("Balance:", balance.toString(), "ZEC");
return balance;
}
import { Chain, getUtxoToolbox } from "@swapkit/sdk";
async function analyzeUtxos() {
const zcashToolbox = await getUtxoToolbox(Chain.Zcash);
const address = "t1XVXWCvpMgBvUaed4XDqWtgQgJSu1Ghz7F";
const { inputs, outputs, fee } = await zcashToolbox.getInputsOutputsFee({
sender: address,
recipient: "t1RecipientAddress",
assetValue: AssetValue.from({ chain: Chain.Zcash, value: "0.001" }),
feeOptionKey: FeeOption.Average,
});
console.log("Selected inputs:", inputs?.length || 0);
console.log("Generated outputs:", outputs?.length || 0);
console.log("Estimated fee:", fee, "satoshis");
return { inputs, outputs, fee };
}

The Zcash toolbox automatically detects network based on SwapKit configuration:

import { Chain, SKConfig, getUtxoToolbox } from "@swapkit/sdk";
SKConfig.set({
envs: { isStagenet: false },
});
const mainnetToolbox = await getUtxoToolbox(Chain.Zcash, {
phrase: "your mnemonic here",
});
const mainnetAddress = await mainnetToolbox.getAddress();
console.log("Mainnet address:", mainnetAddress);
SKConfig.set({
envs: { isStagenet: true },
});
const testnetToolbox = await getUtxoToolbox(Chain.Zcash, {
phrase: "your mnemonic here",
});
const testnetAddress = await testnetToolbox.getAddress();
console.log("Testnet address:", testnetAddress);
import { AssetValue, Chain, SwapKitError, getUtxoToolbox } from "@swapkit/sdk";
async function handleZcashErrors() {
const zcashToolbox = await getUtxoToolbox(Chain.Zcash, {
phrase: "your mnemonic here",
});
try {
const txHash = await zcashToolbox.transfer({
recipient: "t1XVXWCvpMgBvUaed4XDqWtgQgJSu1Ghz7F",
assetValue: AssetValue.from({ chain: Chain.Zcash, value: "1000" }),
});
return txHash;
} catch (error) {
if (error instanceof SwapKitError) {
switch (error.errorKey) {
case "toolbox_utxo_insufficient_balance":
console.error("Insufficient balance for transaction");
break;
case "toolbox_utxo_invalid_address":
console.error("Invalid recipient address");
break;
case "toolbox_utxo_broadcast_failed":
console.error("Failed to broadcast transaction");
break;
default:
console.error("SwapKit error:", error.message);
}
} else {
console.error("Unexpected error:", error);
}
throw error;
}
}
import { Chain, getUtxoToolbox } from "@swapkit/sdk";
async function validateInputs() {
const zcashToolbox = await getUtxoToolbox(Chain.Zcash);
function isValidZcashAddress(address: string): boolean {
const isValid = zcashToolbox.validateAddress(address);
if (!isValid) {
console.warn(`Invalid Zcash address: ${address}`);
return false;
}
const isMainnet = address.startsWith("t1");
const isTestnet = address.startsWith("t3");
if (!(isMainnet || isTestnet)) {
console.warn(`Unsupported address format: ${address}`);
return false;
}
return true;
}
const recipientAddress = "t1XVXWCvpMgBvUaed4XDqWtgQgJSu1Ghz7F";
if (!isValidZcashAddress(recipientAddress)) {
throw new Error("Invalid recipient address");
}
return { valid: true };
}
import { AssetValue, Chain, getUtxoToolbox, getEvmToolbox } from "@swapkit/sdk";
async function crossChainExample() {
const zcashToolbox = await getUtxoToolbox(Chain.Zcash, {
phrase: "your zcash mnemonic here",
});
const btcToolbox = await getUtxoToolbox(Chain.Bitcoin, {
phrase: "your bitcoin mnemonic here",
});
const zcashAddress = await zcashToolbox.getAddress();
const btcAddress = await btcToolbox.getAddress();
const zcashBalance = await zcashToolbox.getBalance(zcashAddress);
const btcBalance = await btcToolbox.getBalance(btcAddress);
console.log("Zcash balance:", zcashBalance.toString());
console.log("Bitcoin balance:", btcBalance.toString());
return { zcashBalance, btcBalance };
}
  1. Transparent Addresses Only: SwapKit does not support Zcash shielded addresses (z-addresses)
  2. No Sapling/Orchard: Only transparent pool transactions are supported
  3. Standard UTXO Model: Uses Bitcoin-like UTXO management without privacy features
  4. Network Fees: Uses Zcash network fee estimation
import { Chain, getUtxoToolbox } from "@swapkit/sdk";
async function optimizePerformance() {
const zcashToolbox = await getUtxoToolbox(Chain.Zcash);
const feeRates = await zcashToolbox.getFeeRates();
const estimation1 = await zcashToolbox.estimateTransactionFee({
sender: "t1Address1",
recipient: "t1Address2",
assetValue: AssetValue.from({ chain: Chain.Zcash, value: "0.001" }),
feeRate: feeRates.fast,
});
return { feeRates, estimation1 };
}

SwapKit has evolved to use modern cryptographic libraries for Zcash operations:

  • Current: Uses bitcoinjs-lib + ecpair for better compatibility and smaller bundles
  • Impact: No breaking changes to public API, improved performance and bundle size

All existing Zcash integration code continues to work without changes:

import { Chain, getUtxoToolbox } from "@swapkit/sdk";
const zcashToolbox = await getUtxoToolbox(Chain.Zcash, {
phrase: "your mnemonic here",
});
const address = await zcashToolbox.getAddress();
const balance = await zcashToolbox.getBalance(address);

The architecture updates are transparent to users and provide:

  • Reduced bundle size
  • Better maintenance and security
  • Improved consistency with other UTXO chains
  • Reliable fee estimation