import { TransactionInstruction } from "@solana/web3.js"; /** * Error taxonomy for the shield path. * * `parseOnChainError` already turns program codes into readable sentences. What * it does not give you is a *decision*: can this be retried, and how? That is * what integrators actually need, because the three retry classes have wildly * different costs: * * - `rebuild` — reuse the proof, new blockhash. Milliseconds. * - `reshield` — the proof is stale, prove again. 10–30 seconds. * - `none` — retrying cannot help; something must change first. */ export type ShieldRetryClass = "rebuild" | "reshield" | "none"; export type ShieldErrorCode = "POOL_NOT_FOUND" | "POOL_PAUSED" | "AMOUNT_BELOW_MINIMUM" | "AMOUNT_ABOVE_MAXIMUM" | "TREE_FULL" | "INSUFFICIENT_SOL" | "INSUFFICIENT_TOKEN_BALANCE" | "TOKEN_ACCOUNT_MISSING" | "TOKEN_ACCOUNT_WRONG_MINT" | "TOKEN_ACCOUNT_WRONG_OWNER" | "TOKEN_ACCOUNT_DELEGATED" | "TOKEN_ACCOUNT_FROZEN" | "VAULT_ATA_MISSING" | "ALT_NOT_FOUND" | "ALT_INCOMPLETE" | "TX_TOO_LARGE" | "OWNER_INVARIANT_UNACKNOWLEDGED" | "UNRESOLVED_ACCOUNT" | "BLOCKHASH_EXPIRED" | "DEADLINE_EXPIRED" | "ROOT_STALE" | "NULLIFIER_COLLISION" | "COMPUTE_BUDGET_EXCEEDED" | "PROOF_REJECTED" | "UNKNOWN"; export type ShieldErrorRemedy = { /** Human-readable description of what would fix this. */ description: string; /** Instructions that, once executed, clear the condition. */ instructions: TransactionInstruction[]; }; export declare class ShieldError extends Error { readonly code: ShieldErrorCode; /** Program error code (6000–6060) when this was derived from a chain error. */ readonly programCode?: number; /** Whether and how a retry can succeed. */ readonly retryable: ShieldRetryClass; /** Machine-readable detail: which account, what value, what was expected. */ readonly context?: Record; /** Present when the condition is fixable by executing instructions first. */ readonly remedy?: ShieldErrorRemedy; readonly cause?: unknown; constructor(code: ShieldErrorCode, message: string, opts?: { programCode?: number; retryable?: ShieldRetryClass; context?: Record; remedy?: ShieldErrorRemedy; cause?: unknown; }); } /** Extract a privacy_pool program error code from an arbitrary thrown value. */ export declare function extractProgramCode(error: any): number | null; /** * Map a submission failure onto the taxonomy. * * Two mappings here are not obvious and are worth stating plainly: * * **Nullifier collision means "already landed", not "already spent."** The * marker PDAs are `init`, not `init_if_needed`, so a second submission of the * same shield fails at account resolution. For a deposit the nullifiers derive * from freshly generated random keys, so a genuine collision is impossible — * in practice this only ever means the first attempt succeeded. Telling a user * their funds were "already spent" here would be alarming and wrong. * * **`UnknownRoot` is recoverable but not by `rebuild()`.** The proof commits to * the root, so a stale root needs a fresh proof, not a fresh blockhash. */ export declare function mapShieldError(error: unknown): ShieldError;