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.
Overview
Section titled “Overview”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
Key Features
Section titled “Key Features”Transparent Address Support
Section titled “Transparent Address Support”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 };}
Custom Address Generation
Section titled “Custom Address Generation”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 };}
Setting Up Zcash Operations
Section titled “Setting Up Zcash Operations”Basic Initialization
Section titled “Basic Initialization”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],});
Address and Key Management
Section titled “Address and Key Management”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, };}
Transaction Operations
Section titled “Transaction Operations”Basic Transfer
Section titled “Basic Transfer”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;}
Transfer with Memo
Section titled “Transfer with Memo”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;}
Manual Transaction Building
Section titled “Manual Transaction Building”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 };}
Fee Management
Section titled “Fee Management”Getting Fee Rates
Section titled “Getting Fee Rates”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;}
Estimating Transaction Fees
Section titled “Estimating Transaction Fees”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 };}
Maximum Sendable Amount
Section titled “Maximum Sendable Amount”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;}
Balance and UTXO Management
Section titled “Balance and UTXO Management”Checking Balances
Section titled “Checking Balances”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;}
Advanced UTXO Operations
Section titled “Advanced UTXO Operations”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 };}
Network Configuration
Section titled “Network Configuration”Mainnet vs Testnet
Section titled “Mainnet vs Testnet”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);
Error Handling and Best Practices
Section titled “Error Handling and Best Practices”Common Error Patterns
Section titled “Common Error Patterns”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; }}
Validation Best Practices
Section titled “Validation Best Practices”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 };}
Integration with Other Chains
Section titled “Integration with Other Chains”Cross-Chain Operations
Section titled “Cross-Chain Operations”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 };}
Limitations and Considerations
Section titled “Limitations and Considerations”Current Limitations
Section titled “Current Limitations”- Transparent Addresses Only: SwapKit does not support Zcash shielded addresses (z-addresses)
- No Sapling/Orchard: Only transparent pool transactions are supported
- Standard UTXO Model: Uses Bitcoin-like UTXO management without privacy features
- Network Fees: Uses Zcash network fee estimation
Performance Considerations
Section titled “Performance Considerations”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 };}
Migration from Previous Versions
Section titled “Migration from Previous Versions”Architecture Updates
Section titled “Architecture Updates”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
API Compatibility
Section titled “API Compatibility”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