import { AddressLookupTableAccount, Connection, TransactionInstruction } from "@solana/web3.js"; import { bytesToBigIntBE, BN254_FR_MODULUS } from "../poseidon.js"; import type { ShieldParams, ShieldProofCache, ShieldResult } from "./types.js"; /** * Build an unsigned transaction that shields public funds into the privacy pool. * * ## The contract * * This function builds. It does not sign, submit, confirm, or retry — those * belong to whoever holds the key, exactly as with Jupiter's `/swap`. The * returned `transaction` is unsigned; the caller signs it with whatever wallet * they have and broadcasts it themselves. * * ## Why this can be handed to a third party * * Three properties make it safe to build a shield on behalf of a signer you do * not control, and to shield to an owner who is not the signer: * * 1. **Deposits are permissionless.** The program gates its relayer allowlist * to `public_amount <= 0`, so any wallet can sign a deposit. * 2. **No secrets are involved in building.** The proof for a deposit has no * real inputs, and the output commitment binds only the recipient's *public* * keys. * 3. **The note rides on-chain.** `note_ciphers` travels inside the instruction, * so the recipient can find the note by scanning even if the platform that * submitted it never says a word. * * ## What the signer unavoidably pays * * The signer is the fee payer, the funding source, and the payer of two * `NullifierMarker` rents (~0.00192 SOL, permanently burned — the program * hardcodes `payer = relayer` on both). A wallet with zero SOL cannot shield * through this path no matter who submits the transaction. Fee sponsorship is * not achievable here: a second signature costs ~96 bytes against a budget with * ~69 to spare, and would not cover the rent anyway. */ export declare function shield(params: ShieldParams): Promise; /** * Re-assemble a shield with a fresh blockhash and deadline, reusing the proof. * * The Groth16 proof commits to the root, the public amount, `ext_data_hash`, the * mint, the nullifiers and the commitments — none of which is time-dependent. * `deadline` is a positional instruction argument, outside `ext_data_hash` and * therefore outside the proof, so it can be refreshed too. That last part * matters: a shield built at T and signed at T+59min needs a new deadline, not * just a new blockhash. * * Costs one `getLatestBlockhash` and a message compile — no proving, no * Poseidon, no account resolution. * * Does NOT recover from `ROOT_STALE`: a stale root invalidates the proof, so * that case needs a fresh `shield()` call. */ export declare function rebuild(result: ShieldResult, opts?: { connection?: Connection; alt?: AddressLookupTableAccount; blockhash?: { blockhash: string; lastValidBlockHeight: number; }; deadlineSeconds?: number; computeUnitPriceMicroLamports?: number; }): Promise; /** * Rebuild the `transact` instruction from a public proof cache. Shared by the * v0 path above and the v1 path in ./v1.ts so both sign the same instruction. */ export declare function transactInstructionFromCache(cache: ShieldProofCache, deadline: bigint): TransactionInstruction; /** Serialize a proof cache for transport between processes. Contains no secrets. */ export declare function serializeProofCache(cache: ShieldProofCache): string; export declare function deserializeProofCache(json: string): ShieldProofCache; /** Re-exported for callers that want the raw field arithmetic. */ export { bytesToBigIntBE, BN254_FR_MODULUS };