Prerequisites
@keystoneos/reactand@keystoneos/nodeinstalledKeystoneProviderconfigured withsettlements:writescope- A backend that can submit transactions via your custody provider (Fireblocks, BitGo, etc.)
Why action delegates exist
Institutional platforms do not let end-users sign transactions in the browser. Assets are held in custody wallets managed by Fireblocks, BitGo, or similar infrastructure. When a settlement requires a deposit to escrow, the transaction must route through the custody provider’s API. Action delegates bridge this gap. Instead of the widget interacting with the blockchain directly, it calls your backend, which submits the transaction through your signing infrastructure.The deposit flow
Frontend setup
Configuring the provider with action delegates
PassonDepositRequired (and optionally onApprovalRequired) to the KeystoneProvider. These callbacks fire when the user triggers a deposit from the UI.
Building the deposit button component
TheuseDeposit hook manages the multi-step deposit flow. It returns the current status, deposit info for preview, and the deposit() function to trigger the flow.
Backend implementation
Your backend receives the pre-encoded calldata from the frontend and submits it to your custody provider. The calldata is already ABI-encoded by the KeyStone API - your backend just needs to forward it.Fireblocks
BitGo
Generic signing infrastructure
If you use a different custody provider or your own HSM, the pattern is the same - forward the pre-encoded calldata:Deposit status states
TheuseDeposit hook progresses through these states:
| Status | What is happening | User sees |
|---|---|---|
idle | Nothing in progress | Deposit button |
fetching_info | Calling KeyStone API for calldata | Loading spinner |
approving | ERC-20 approve() submitted to custody | ”Submitting approval…” |
approval_confirmed | Approval mined, proceeding to deposit | Brief transition |
depositing | depositLeg() submitted to custody | ”Submitting deposit…” |
deposit_confirmed | Deposit mined and confirmed by escrow | Success with txHash |
error | Any step failed | Error message + retry button |
Error handling
Common failure scenarios
| Failure | Cause | What happens |
|---|---|---|
| Custody API rejects | Insufficient balance, policy violation, rate limit | onDepositRequired throws, useDeposit sets status: "error" |
| Gas estimation fails | Contract revert (wrong calldata, already deposited) | Custody provider returns error before signing |
| Transaction reverts | On-chain revert (deadline passed, wrong token) | txHash exists but transaction failed |
| Network timeout | RPC or custody API unreachable | onDepositRequired throws with timeout error |
Implementing robust error handling
Security considerations
- The backend deposit endpoint should authenticate the request (verify the session or user identity before submitting a transaction)
- Validate that the
escrowAddressmatches a known KeyStone escrow contract before signing - Implement rate limiting on the deposit endpoint
- Log all deposit submissions with the settlement ID, leg index, and caller identity for audit
Next steps
Real-time Tracking
Track deposit progress and settlement state in real time.
Action Delegates Reference
Full reference for all action delegate callbacks.
useDeposit Reference
Full API reference for the useDeposit hook.
Escrow Deposits Guide
Server-side guide for escrow deposits using the SDK.