SDK & Integration

SDK: Shielded UTXO

Working with shielded notes: keypairs, Utxo objects, the 2-in/2-out transaction builder, signed external amounts, and the ExtData hash that binds recipient, relayer, fee, and encrypted outputs.

Profile A spends and creates notes. A Keypair derives the spend key, a Utxo is a note, and buildTransactionInput assembles a 2-in/2-out join-split witness.

Keypairs

typescript
import { Keypair } from "@shh/sdk";

const kp = await Keypair.generate();   // random privkey
// kp.pubkey === H(privkey)
const sig = await kp.sign(commitment, merklePath);

pubkey = H(privkey); sign(commitment, path) = H(privkey, commitment, path). Keypair.generate(privkey?) lets you reconstruct a known key. init() computes the pubkey (await it before use).

Notes

typescript
import { Utxo } from "@shh/sdk";

const note = new Utxo({ amount: 1_000_000n, keypair: kp });
const commitment = await note.getCommitment(); // H(amount, pubkey, blinding)
const nullifier  = await note.getNullifier();   // H(commitment, index, signature)
amount
Note value (bigint). Constrained to 248 bits in the circuit.
blinding
Per-note randomness; defaults to randomField().
keypair
The owning Keypair.
index
Leaf index once inserted, or null for a not-yet-committed output.

Building a transaction

buildTransactionInput pads inputs and outputs to two each (with distinct dummy keypairs so nullifiers stay unique), computes publicAmount = (extAmount − fee) mod p, and binds the extDataHash:

typescript
import { buildTransactionInput } from "@shh/sdk";

const { input, root, publicAmount, extDataHash,
        inputNullifiers, outputCommitments, extData } =
  await buildTransactionInput({
    inputs:  [noteA],          // spent notes (≤ 2)
    outputs: [noteB, noteC],   // created notes (≤ 2)
    tree,                      // current shielded MerkleTree
    extAmount: 0n,             // 0 = private transfer, >0 deposit, <0 withdraw
    fee: 0n,
    recipient, relayer,
  });

ExtData & amounts

hashExtData(extData)
keccak256(abi.encode(extData)) mod p — matches ShieldedPool._extDataHash. Binds recipient, signed extAmount, relayer, fee, and the two encrypted-output ciphertexts.
toFieldAmount(value)
((value % p) + p) % p — maps a signed amount into the field, matching _calcPublicAmount.

Proving (Node)

typescript
import { generateTransaction } from "@shh/sdk/node";

const result = await generateTransaction({
  inputs, outputs, tree, extAmount, fee, recipient, relayer,
  wasmPath: "build/transaction2x2.wasm",
  zkeyPath: "build/transaction2x2.zkey",
});
// result.proof, result.publicSignals, result.extData …