# Types reference

> Field-by-field shapes for the SDK's public parameter, result, and data types, and the error catalog.

Field-by-field shapes for the public types the [PoolSession](pool-session) methods consume and return. Source of truth: `v2-monorepo/packages/sdk/src/types/`.

Amount fields across the SDK (`amount` on transfer/withdraw params, `value` on deposit params, `feeAmount`) are **0x-prefixed hex strings** (`Hex`), not `bigint`, so convert with `` `0x${wei.toString(16)}` `` before calling. Relayer-quote money fields (`feeAmount`, `txCost`, `gasPrice`) come back as decimal strings; wrap those in `BigInt(...)` before formatting.

## Notes and status

```ts
type PendingNote = {
  noteAddressHash: Hash;
  commitment: Hash;
  value: Hex;
  tokenId: Address;
  label: Label;
  status: NoteStatus;
  ownerAddress: Address;     // zero address for out-of-band recipient notes
  noteSecret: Secret;
  isOwned: boolean;
  depositSecret?: Secret;    // only on the note that originated its lineage
};

type Note = PendingNote & {
  createdAtBlock: Hex;       // on-chain block.timestamp at insertion, despite the name
  spentAtBlock: Hex | null;
  txHash: Hash;
};

enum NoteStatus { INACTIVE, PENDING, ACTIVE, SPENT, EXITED, REJECTED }   // runtime export
```

## Spend parameters

All spend params share `PrepareTransactBase`:

```ts
type PrepareTransactBase = {
  inputCommitments: Hash[];     // all inputs must be ACTIVE
  amount: Hex;
  tokenId: Address;
  relayAddress?: Address;
  feeAmount?: Hex;
  processorAddress?: Address;   // default: owner address in prepareTransfer (self-submit works,
                                // sender visible); zero address in prepareWithdraw and
                                // prepareColdStartTransfer (self-submit reverts unless set)
  nativeGas?: Hex;              // default "0x0"
  feeRecipient?: Address;
};

type TransferParams = PrepareTransactBase & (
  | { recipientDiscoveryData: RecipientDiscoveryData }
  | { recipientNoteAddressHashByLabel: Map<Label, Hash> }   // blind path, keyed by input label
  | { recipientNoteAddressHash: Hash[] }                    // deprecated positional blind path
);

type ColdStartTransferParams = PrepareTransactBase & { recipientEvmAddress: Address };
type WithdrawParams = PrepareTransactBase & { recipientAddress: Address };
type RageQuitParams = { commitment: Hash };                 // must not be EXITED
type DepositParams = { tokenId: Address; value: Hex };
```

`RecipientDiscoveryData` is a three-variant union:

```ts
type RecipientDiscoveryData =
  | { evmAddress: Address; noteSecretsMap?: Map<Hash, Secret>; allowOutOfBandFallback?: boolean }
  | { publicViewingKey: PublicKey; noteSecretsMap: Map<Hash, Secret>; hint?: Hex }
  | { publicViewingKey: PublicKey; noteAddressHashes: Hash[]; hint?: Hex };  // payment requests
```

On the second variant the caller guarantees every map key equals `Poseidon(recipientEvmAddress, noteSecret)`; a malformed map produces notes nobody can spend.

## Spend results

```ts
type PrepareTransferResult = { executeOptions: ExecuteTransferParams; relayOptions: RelayTransferParams[] };

type ExecuteTransferParams = {
  to: Address; callData: Hex;
  spentNotes: Note[]; changePendingNotes: PendingNote[]; recipientPendingNotes: PendingNote[];
  recipient: ResolvedTransferRecipient; recipientEvmAddress?: Address;
};

type RelayTransferParams = PrepareTransactBase & {
  recipient: ResolvedTransferRecipient; recipientEvmAddress?: Address;
  selectedQuote: { relayerInfo: RelayerInfo; quote: TransferRelayerQuote };
};

type TransferResult = { txReceipt: TxReceipt; recipientNotes?: Note[] };  // notes present when the
                                                                          // variant carries secrets

type PrepareWithdrawResult = {
  changePendingNotes: PendingNote[]; callData: Hex; to: Address; spentNotes: Note[];
  relayerOptions: ExecuteWithdrawRelayerParams[];
};

type PrepareRageQuitResult = {
  commitment: Hash; value: Hex;            // always the full note value
  tokenId: Address; nullifierHash: Hash;
  recipientAddress: Address;               // the note's ownerAddress, circuit-enforced
  callData: Hex; to: Address;
};

type PrepareDepositResult = {
  pendingNote: PendingNote;                // self-deposits only
  callData: Hex; to: Address;              // to = Entrypoint
  msgValue: Hex;
  approvalTx: { to: Address; data: Hex; value: Hex } | null;
};

type TxReceipt = { status: boolean; blockNumber: Hex; txHash: Hex; logs: TxLog[] };
```

## Payment requests

```ts
type PaymentRequest = {          // the public, shareable subset; carries no secrets
  paymentId: Hex;
  noteAddressHashes: Hash[];
  amount: Hex;                   // informational, not enforced on-chain
  tokenId: Address;
  tag: Hex;                      // Poseidon([paymentId])
  paymentPubKey: PublicKey;
};

type GeneratePaymentRequestParams = { amount: Hex; tokenId: Address; slots?: number };  // default 5
type FulfillPaymentRequestParams = {
  paymentRequest: PaymentRequest;
  inputCommitments: Hash[];      // length must not exceed noteAddressHashes.length
  relayAddress?: Address; feeAmount?: Hex; processorAddress?: Address;
};
```

The recipient-local record behind a request additionally holds `noteSecretsMap`, `recipientAddress`, `status`, `fulfilledByCommitments`, and a `paymentPrivKey`; everything except the private key is persisted through the payment-request storage adapter (storing it would put a recoverable secret at rest), and the key is re-derived from the [viewing key](/concepts/keys) and `paymentId` on load. None of it is ever shared.

## Keystore

```ts
type RegisterKeystoreOptions = { includeViewingKey?: boolean };   // default true
type RegisterKeystoreResult = {
  alreadyRegistered: boolean;
  keystoreCalldata: PreparedTransaction | null;
  viewingKeyCalldata: PreparedTransaction | null;
  nullifyingKeyHash: Hash; authDigest: Hash;
};
type RotateRevocableKeyConfig = Omit<DeriveFromSignatureConfig, "revocableKeyIndex">;
type DeriveFromSignatureConfig = {
  signature: Hex;                // 65-byte ECDSA signature of the derivation payload
  signerAddress: Address;
  revocableKeyIndex: Hex;        // "0x0" for fresh accounts
  addressHash: Hex;              // keccak256(signerAddress) from the EIP-712 payload
};
type RotateRevocableKeyOutcome = {
  receipt: TxReceipt;
  oldAuthorizerDigest: Hash; newAuthorizerDigest: Hash;
  newRevocableKeyIndex: Hex;     // persist this; future sessions must be built with it
};
```

## Config and environment

```ts
type ProtocolKeys = {
  privateNullifyingKey: Secret; privateRevocableKey: Secret;
  revocableKeyIndex: Hex;
  viewingPrivateKey: Secret; viewingPublicKey: PublicKey;
};
type DeploymentAddresses = {
  poolAddress: Address; entrypointAddress: Address;
  keystoreAddress: Address; aspRegistryAddress: Address;
};
type RelayerInfo = {
  url: string; name: string; chainId: number; chainType: string;
  status: "active" | "inactive"; address: Address; processorAddress: Address;
};
type AccountExport = {
  notes: Note[]; syncCursor: Hex;
  owner?: Address; chainId?: number;       // mismatch on import throws AccountExportMismatch
  paymentRequests?: SerializedPaymentRequestRecord[];
};
type DiscoverNotesParams = { fromBlock?: Hex; contacts?: Contact[] };
```

`DEPLOYMENTS` (runtime export) currently contains only Sepolia (`11155111`).

## Batch withdraw

```ts
type BatchWithdrawSessionParams = { tokenId: Address; recipientAddress: Address };   // whole active balance
type SelfSubmitBatchParams = BatchWithdrawSessionParams & { relayContractAddress: Address };
type PrepareBatchWithdrawResult = BatchPrepareResult & { relayerInfo: RelayerInfo; quote: BatchWithdrawalRelayerQuote };

// Dependency-light, also on @privacy-pools-v2/sdk/batch-fee:
const MAX_BATCH = 10;
type ComputeBatchItemFeeArgs = { relayCost: bigint; feeBps: bigint; flatFee: bigint; amountOut: bigint; maxRelayFee: bigint /* 0 = no cap */ };
```

## Swaps and reshield

```ts
type PrepareSwapQuoteParams = {
  relayerInfo: RelayerInfo;
  amount: Hex; tokenId: Address; outputToken: Address;
  recipientAddress: Address; fallbackAddress?: Address; dustRecipient?: Address;
  extraGas?: boolean; slippage?: number; toChainId?: number; denyExchanges?: string[];
};
type PreparedSwapQuote = {
  selectedQuote: PrepareSwapRelayerQuotes; swapCalldata: Hex;
  minOutputAmount: Hex; destinationMinOutputAmount: Hex;
  feeAmount: string; netAmount: Hex; estimatedOutput: string;
  swapInputToken: Address; swapTarget: Address; approvalAddress: Address;
  dustRecipient: Address; dustAmount: Hex; toChainId: number;
};
type ExecuteWithdrawAndSwapRelayerParams = {
  inputCommitments: Hash[]; amount: Hex; tokenId: Address;
  recipientAddress: Address; fallbackAddress?: Address; outputToken: Address;
  minOutputAmount: Hex; swapCalldata: Hex; selectedQuote: PrepareSwapRelayerQuotes;
  toChainId?: number; dustRecipient?: Address; extraGas?: boolean;
  swapTarget?: Address; approvalAddress?: Address;
};

type EstimateReshieldParams = { relayerInfo: RelayerInfo; amount: Hex; tokenId: Address; outputToken: Address; dustRecipient?: Address; slippage?: number };
type ReshieldEstimate = { feeAmount: string; netSwapAmount: string; estimatedOutput: string; estimatedMinOutput: string; noteValue: Hex; vettingFee: string; totalDepositCost: string; swapInputToken: Address };
type PrepareReshieldQuoteParams = EstimateReshieldParams & { depositResult: PrepareDepositResult; totalDepositCost: string };
type PreparedReshieldQuote = { selectedQuote; swapCalldata: Hex; feeAmount: string; netAmount: Hex; swapTarget: Address; approvalAddress: Address; dustRecipient: Address; dustAmount: Hex; swapInputToken: Address; depositNote: PendingNote };
type ReshieldParams = { inputCommitments: Hash[]; amount: Hex; tokenId: Address; outputToken: Address; swapCalldata: Hex; selectedQuote; dustRecipient?: Address; swapTarget?: Address; approvalAddress?: Address; depositNote?: PendingNote };

// Cross-chain adds toChainId (+ fallbackAddress, denyExchanges) and, on the quote, an optional
// dustRescue: { recipientIdentifier: StealthRecipientIdentifier } for the destination dust deposit.

type SwapAndDepositParams = { fromChainId: number; inputToken: Address; depositToken: Address; depositAmount: Hex; fallbackAddress?: Address; inputAmount?: Hex };
type PrepareSwapAndDepositResult = {
  pendingNote: PendingNote; inputToken: Address; estimatedInputAmount: Hex;
  approvalAddress: Address; approvalTxs: PreparedTransaction[]; approvalTx: PreparedTransaction | null;
  transactionData: Hex; transactionTo: Address; fromChainId: number;
  depositCallData: Hex; depositTarget: Address; depositMsgValue?: Hex; msgValue: Hex; estimatedDuration: number;
};
```

## Yield

```ts
type YieldDeployment = {
  ppRouter: Address; nativeMode?: boolean; zap?: Address;
  ppUSDC: Address; ppUSDCDecimals: number;            // the share token (18 decimals)
  underlying: Address; underlyingDecimals: number; underlyingSymbol: string; apyLabel?: string;
};
type YieldSessions = { chainId: number; deployment: YieldDeployment; deposit: IPoolSessionYieldDeposit; withdraw: IPoolSessionYieldWithdraw; token: IPPYieldTokenInteractor; router: IPPRouterInteractor };

type YieldDepositParams = { fundingSource?: "wallet" | "executor"; value: Hex /* shares */; maxUnderlyingIn?: bigint };
type BudgetSizedYieldDeposit = { shares: bigint; underlyingNeeded: bigint; maxUnderlyingIn: bigint; headroom: bigint };
type PreparedYieldDeposit = { pendingNote: PendingNote; approvalTxs: PreparedTransaction[]; approvalTx: PreparedTransaction | null; depositTx: PreparedTransaction; sharesValue: bigint; underlyingNeeded: bigint; maxUnderlyingIn: bigint };

type YieldWithdrawParams = { inputCommitments: Hash[]; amount: Hex; amountOut: Hex; recipient: Address; feeRecipient?: Address; feeAmount?: Hex; nativeGas?: bigint; slippageBps?: bigint };
type PreparedYieldWithdraw = { withdrawTx: PreparedTransaction; changePendingNotes: PendingNote[]; spentNotes: Note[]; recipientShares: bigint; quotedUnderlyingOut: bigint; minUnderlyingOut: bigint };
type YieldWithdrawRelayParams = { inputCommitments: Hash[]; amount: Hex; amountOut: Hex; recipient: Address; signedFeeCommitment: WithdrawalFeeCommitment; extraGas?: boolean; slippageBps?: bigint };
type PreparedYieldWithdrawRelay = { relayParams: WithdrawalRelayParams; changePendingNotes: PendingNote[]; spentNotes: Note[]; recipientShares: bigint; quotedUnderlyingOut: bigint; minUnderlyingOut: bigint };

// Sizing constants (runtime exports)
const DEPOSIT_RATE_HEADROOM_PPM = 1n;
const CROSS_CHAIN_DEPOSIT_RATE_HEADROOM_PPM = 500n;
const WITHDRAW_SLIPPAGE_BPS = 100n;
const ZAP_SUPPLY_BUFFER_UNITS = 2n;
```

Yield amounts are `bigint` in the public API (the batch-fee precedent), except where the base sessions already speak `Hex` (`value`, `amount`, `amountOut`).

## Errors

The public entrypoint exports exactly seven error classes as runtime values, so `instanceof` works only for these: `InvalidBuilderConfig`, `UnsupportedChainId`, `InvalidAddNoteParams`, `InvalidMarkNoteSpentParams`, `InvalidMarkNoteExitedParams`, `NoteCommitmentNotMined`, and `PoolSessionNoteManagerBaseError`. Every other error class (including `RecipientViewingKeyUnregistered`, `FeeCommitmentExpired`, `RelayerRejected`, `WitnessPreparationFailed`, and the transact/deposit/ragequit/keystore families) reaches the package as a type only. All classes set a distinct `name`, so branch on `error.name` for anything outside the seven.

Most-likely-to-hit errors:

-   `InvalidBuilderConfig`: config validation failure.
-   `WitnessPreparationFailed`: witness construction failed; a "Leaf not found in tree" message on a spend or ragequit usually means the owner never registered on the keystore.
-   `TransactNoteNotActive` / `InsufficientTransactValue`: bad input selection.
-   `NoteNotFoundError`: the local [NoteManager](/sdk/note-manager) doesn't have the commitment.
-   `InvalidStatusTransitionError`: illegal note status transition.
-   `ProofGenerationFailed`: circuit error.
-   `RelayerRejected`: relayer returned 4xx (often wraps an on-chain revert).
-   `RecipientViewingKeyUnregistered`: recipient hasn't registered and `allowOutOfBandFallback` wasn't set.
-   `FeeCommitmentExpired`: quote expired before submit.
-   `CircuitArtifactLoadFailed`: couldn't fetch the wasm/zkey/vkey.

Per-method error conditions are listed on [PoolSession](pool-session).
