import { PublicKey, type Connection } from "@solana/web3.js"; import type { TransactionProofBuilder } from "../proofs/types.js"; import { type ClientProvingDeps, type ClientProvingFailure, type ClientProvingNote, type ClientProvingOutputNote, type ClientSpendRecovery, type NoteCipherRecipient, type RecoverableOutputNote } from "./shared.js"; /** * Who receives a private transfer. * * Structurally a `ShieldOwner`: get it from `resolveShieldOwner`, which checks * the recipient's wallet-signed key binding. Both keys must belong to the same * account — a note owned by one account but encrypted to another is money * nobody can find. */ export interface TransferRecipient { /** Owner of the output note. */ veiloPublicKey: bigint; /** Recipient's wallet; the legacy cipher target. */ noteViewingKey: PublicKey; /** Verified X25519 view key. When present, the cipher targets it. */ viewPublicKey?: Uint8Array; } export interface TransferWithClientProofParams { connection: Connection; /** One or two notes of the same mint. Merge down first with `consolidateNotes`. */ notes: ClientProvingNote[]; /** Base units the recipient receives. A transfer has no fee. */ amount: bigint; recipient: TransferRecipient; mintAddress?: PublicKey; /** Account identifier the relayer quotes for. */ userPublicKey: string; /** Who can decrypt the change note from chain data. */ changeCipherRecipient: NoteCipherRecipient; /** Owner key of the change note. Defaults to the first input note's key. */ changeOwnerPrivateKey?: bigint; /** * Tell the relayer the amount and recipient wallet. Default true: the relayer * then does what the relayer-proved transfer does — enforces the minimum, * saves the recipient's note for their wallet, notifies both parties and * counts the volume — after checking the disclosure against the proof. Set * false to keep both hidden; the recipient then finds the note only by * scanning chain data. */ discloseToRelayer?: boolean; /** Awaited before proving; if it throws, nothing is submitted. */ persistRecovery(recovery: ClientSpendRecovery): Promise | void; prover?: TransactionProofBuilder; indexTimeoutMs?: number; } interface TransferResultBase { quoteId: string; /** The recipient's note. The sender cannot spend it; kept for history and support. */ recipientNote: RecoverableOutputNote & { leafIndex?: number; }; /** Null when the notes are spent exactly. */ changeNote: ClientProvingOutputNote | null; recovery: ClientSpendRecovery; } /** Same outcome semantics as `ClientWithdrawResult`. */ export type ClientTransferResult = (TransferResultBase & { status: "landed"; txSignature: string; noteCiphersIncluded: boolean; }) | (TransferResultBase & { status: "unconfirmed"; txSignature: string; }) | (TransferResultBase & { status: "unknown"; error: ClientProvingFailure; }) | (TransferResultBase & { status: "rejected"; error: ClientProvingFailure; }); /** * Send a private transfer with a proof generated on this device. * * The relayer never learns the recipient or the amount: they exist only inside * the output commitments and the note ciphers. It quotes the root and paths, * checks the proof, and pays for the transaction. * * Throws only while nothing has been submitted; see `ClientTransferResult`. */ export declare function transferWithClientProof(params: TransferWithClientProofParams): Promise; /** @internal */ export declare function runTransferWithClientProof(params: TransferWithClientProofParams, deps: ClientProvingDeps): Promise; export {};