Overview
V18 uses per-operation hooks objects (not a single genericTransactionCallbacks). Each factory’s deps.hooks or options.hooks slot accepts a named interface specific to that operation, with named per-phase / per-step hook keys. Hooks observe the operation as it moves through validation, fetching, ZK proving, transaction submission, MPC callback waiting, and completion.
The two transaction-level building blocks every hooks interface uses:
onSkipped, not onPreSend / onPostSend. This is the V18 way to observe “the step was a no-op because the on-chain state was already correct.”
Usage — Registration
V18 registration uses a singlehooks option (RegistrationHooks) with named per-step slots and top-level phase hooks. Each skippable step slot takes { onPreSend, onPostSend, onSkipped }.
Step slot names:
initUserAccount, registerX25519PublicKey, registerAnonymousUsage. Each fires onSkipped when the on-chain state already satisfies the step, onPreSend before the transaction is submitted, and onPostSend after it confirms.Usage — Stealth Pool Note creation
Creating a Stealth Pool Note involves up to three transactions. Each has its own callbacks slot inside theoptions argument:
Usage — Single-transaction operations
Deposits, withdrawals, conversions, and most other operations take anoptions.hooks field whose shape is operation-specific. There is no single global TransactionCallbacks { pre, post } shape — each operation defines its own hooks interface with named per-phase slots:
- Deposit (
ATAIntoETADirectDepositHooks) — top-level:onValidationStart/Complete,onMintFetchStart/Complete,onAccountFetchStart/Complete,onArciumSetupStart/Complete,onInstructionBuildStart/Complete,onComplete,onError. Per-step:queueComputation: MpcTransactionStepHooks— slots:onPreSend,onPostSend,onMonitorStarted,onProgress,onFinalized,onRentReclaimSubmitted,onRentReclaimError. - Withdrawal (
WithdrawalHooks) — analogous shape with the same MpcTransactionStepHooks slot. - Conversion (
ConvertToSharedHooks) — per-mint hooks plusonComplete/onError.
Usage — Burn lifecycle hooks (BurnHooks)
Burns are relayer-managed: ZK proof generation, relayer submission, polling, and the on-chain callback all happen behind a single burn() call. The burner factory exposes per-stage lifecycle hooks on the deps.hooks slot. The hooks are named per-event (not generic onPhase*):
onError’s phase is one of: "keyDerivation", "batchAssembly", "zkProofGeneration", "batchSubmission", "batchPolling".