Skip to main content
The finalize_and_extract function performs final validation and produces the raw transaction bytes ready to broadcast to the Zcash network.

Prerequisites

Before finalization, ensure:
  • βœ… All transparent inputs are signed
  • βœ… All Orchard proofs are generated
const info = t2z.inspect_pczt(pczt.to_hex());

if (!info.all_inputs_signed) {
  throw new Error('Not all inputs signed');
}
if (!info.has_orchard_proofs) {
  throw new Error('Orchard proofs not generated');
}

Function Signature

  • TypeScript
  • Go
  • Kotlin
// Get raw bytes
function finalize_and_extract(pczt: WasmPczt): Uint8Array

// Get hex string (convenient for broadcasting)
function finalize_and_extract_hex(pczt: WasmPczt): string

Basic Usage

  • TypeScript
  • Go
  • Kotlin
// Get transaction as hex (most common)
const txHex = t2z.finalize_and_extract_hex(pczt);
console.log('Transaction ready:', txHex.length / 2, 'bytes');

// Or get raw bytes
const txBytes = t2z.finalize_and_extract(pczt);

What Happens During Finalization

1

Spend Finalizer

Assembles final script signatures from partial signatures.
2

Validation

Verifies all required data is present and valid.
3

Transaction Extractor

Converts the PCZT into a raw Zcash transaction.
4

Serialization

Produces the final byte representation.

Broadcasting the Transaction

After extraction, broadcast the transaction to the Zcash network:

Using zcash-cli

zcash-cli sendrawtransaction "0500000..."

Using lightwalletd

// gRPC to lightwalletd
const response = await lightwalletClient.sendTransaction({
  data: hexToBytes(txHex)
});
console.log('Txid:', response.txid);

Using a Block Explorer

Many block explorers provide a β€œBroadcast” or β€œPush TX” feature where you can paste the raw transaction hex.

Using JSON-RPC

const response = await fetch('https://zcash-rpc.example.com', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    jsonrpc: '2.0',
    method: 'sendrawtransaction',
    params: [txHex],
    id: 1
  })
});

Complete Example

import * as t2z from '@d4mr/t2z-wasm';

async function buildAndBroadcast() {
  // 1. Create PCZT
  let pczt = t2z.propose_transaction(inputs, payments, changeAddr, network, expiry);
  
  // 2. Sign all inputs
  for (let i = 0; i < inputs.length; i++) {
    const sighash = t2z.get_sighash(pczt, i);
    const sig = await sign(sighash, keys[i]);
    pczt = t2z.append_signature(pczt, i, pubkeys[i], sig);
  }
  
  // 3. Generate proofs
  pczt = t2z.prove_transaction(pczt);
  
  // 4. Finalize
  const txHex = t2z.finalize_and_extract_hex(pczt);
  
  // 5. Broadcast
  const txid = await broadcast(txHex);
  console.log('Transaction broadcast:', txid);
  
  return txid;
}

Transaction Structure

The extracted transaction follows the v5 transaction format:
FieldDescription
HeaderVersion, version group ID
TransparentInputs with signatures, outputs
Sapling(empty in t2z transactions)
OrchardActions with proofs, binding signature
ExpiryBlock height expiry
Typical sizes:
  • 1 input β†’ 1 Orchard output: ~2.5 KB
  • 1 input β†’ 2 Orchard outputs: ~5 KB

Common Errors

Not all transparent inputs have been signed. Use inspect_pczt to check which inputs need signing.
const info = t2z.inspect_pczt(pczt.to_hex());
info.transparent_inputs.forEach((input, i) => {
  if (!input.is_signed) {
    console.log(`Input ${i} needs signature`);
  }
});
Orchard proofs haven’t been generated. Call prove_transaction first.
The PCZT couldn’t be finalized. This usually means something is inconsistent β€” try rebuilding from scratch.

After Broadcasting

After a successful broadcast:
  1. Get the txid β€” Most broadcast methods return the transaction ID
  2. Wait for confirmation β€” Monitor for inclusion in a block
  3. Verify in explorer β€” Check the transaction on a block explorer
The recipient can view incoming shielded funds using their full viewing key (not spending key). For Orchard, viewing keys are encoded as uview1... (mainnet) or uviewtest1... (testnet).

πŸŽ‰ Congratulations!

You’ve completed the full t2z transaction flow:
  1. βœ… Proposed the transaction
  2. βœ… Verified (optional)
  3. βœ… Signed all inputs
  4. βœ… Generated proofs
  5. βœ… Finalized and broadcast

Try the Demo

See this entire flow in action with the interactive demo.