Skip to main content

Claimable Transfers

A claimable transfer (a gift) lets you send shielded funds to an Ethereum wallet address that is not yet a registered Privacy Boost account. You need only the recipient’s wallet address and an amount. The recipient later registers Privacy Boost with that same address and claims the funds into a normal shielded note; if they never claim, you reclaim the funds after a deadline you set. Like a normal private transfer, the recipient and amount stay hidden on chain. Unlike a normal transfer, the recipient does not have to exist on Privacy Boost when you send.
Preview feature — pending external audit. Claimable transfers are implemented across the protocol and SDKs but have not completed external security audit. Treat the API as stable-but-unaudited and gate production use on your own review. The feature is enabled per deployment; the server’s /info advertises gift support through its gift refund-delay bounds (giftMinRefundDelayBlocks / giftMaxRefundDelayBlocks).

How it works

The protocol cannot send a spendable note to an address it has never seen — a note is only spendable by a registered account’s keys. Claimable transfers solve this with a two-step fund → claim flow built around a gift note:
SENDER                          ON-CHAIN / NOTE TREE            RECIPIENT
  │ 1. fund a gift note bound to the recipient wallet W
  │    (ordinary private transfer; amount + recipient hidden)
  │ ────────────────────────────▶ gift note appended
  │ 2. share a claim link (optional, off-chain)  ────────────▶ 3. register PB with wallet W
  │                                                            4. discover the pending gift
  │                              claim  ◀───────────────────── 5. claim → receive a normal note

  │ 6. if unclaimed past the refund deadline → refund ──────▶ funds return to sender
  1. Fund. You build a gift note bound to the recipient’s wallet address W and a fresh hiding factor, then fund it through an ordinary shielded transfer. On chain it is indistinguishable from any other transfer — the amount and the recipient are hidden. The SDK records the gift locally so you can always refund it, and (for the wallet-bound modes) returns an off-chain claim link carrying the encrypted opening.
  2. Claim. The recipient registers Privacy Boost with the same wallet W, discovers the pending gift, and claims it. Claiming proves control of W with a zero-knowledge proof and re-mints the gift into a normal shielded note. The amount stays hidden.
  3. Refund. You pick a refund deadline (a block height) at funding time. If the gift is still unclaimed after it, you reclaim the funds. A claim and a refund spend the same nullifier, so exactly one of them can ever settle — the recipient can’t claim a refunded gift, and you can’t refund a claimed one.
If the relay or TEE is unavailable, a recipient can always recover the funds through a permissionless public exit (which reveals the amount, like a forced withdrawal). Funds are self-custodial end to end: only the user’s own keys plus a valid proof move them. The TEE assists discovery and can never seize or redirect a gift.

Funding modes

The SDK exposes three ways to fund a gift. Pick the one that matches what you know about the recipient.
ModeYou provideWhen to use
Wallet + privacy addressrecipient wallet W and their privacy addressThe recipient is already a Privacy Boost user — the ciphertext is sealed to their viewing key for the smoothest discovery.
Wallet onlyrecipient wallet WThe recipient has an EOA but has not joined Privacy Boost. The claim link carries everything they need.
Secret-bearernothing but an amountThe recipient has no wallet at all yet. See the warning below.
Secret-bearer mode is experimental, off by default, and a bearer instrument. It binds the gift to a secret embedded in the claim link instead of a wallet, so anyone who holds the link can claim the funds — if the link leaks, the funds are stealable, exactly like cash or a gift card. It is gated on audit and product sign-off, is not exposed in the CLI, and a secret-bearer gift can only be claimed through the public (amount-revealing) exit. Do not use it in production without your own review. The wallet-bound modes above are the supported default.

Discovering a gift

A recipient finds a pending gift in one of three ways, in increasing order of trustlessness:
  • TEE discovery. Behind a normal authenticated session for wallet W, the server lists the pending gifts addressed to that wallet. This is the default path the SDK’s “list pending gifts” call uses.
  • Claim link. The sender shares a pbgift:v1:... link out of band (message, QR code). The recipient can decode it offline to preview the gift, then claim directly from it — no server lookup required to read it. Treat a claim link like a password: for wallet-bound gifts the recipient still needs their own keys to claim, but the link reveals the amount and recipient to anyone who sees it.
  • Trustless recovery. Using only the claim link’s encrypted opening and public on-chain data, a recipient can rebuild and submit the claim with no TEE and no relay. This is the ultimate liveness backstop.

Refunds and the deadline

You choose refundAfterBlock when you fund. It is bounded by the server (at least a minimum delay, at most a maximum, both advertised from /info) so a genuinely abandoned gift always stays recoverable but a sender cannot claw back immediately. Anti-clawback is enforced on chain — a refund proof requires the deadline block to have genuinely elapsed. To refund, the SDK uses the local gift record it saved at funding time (getGiftRecords() / gift_refund_by_record). Keep these records: they are what makes an unclaimed gift refundable. They travel inside an exported session (see your platform’s session-storage guide), and a chain context can rehydrate them with import_gift_records. If you lose them, you can still refund by supplying the gift’s fields manually (gift_refund).

What observers and the TEE learn

Observer learnsFundingPrivate claimPublic exit
Recipient wallet Whiddenhiddenrevealed (as destination)
Amounthiddenhiddenrevealed
That a settlement happenedas a transferyes (one event)yes
Whether it was a claim or a refundindistinguishable
A private claim and a private refund are indistinguishable on chain. The TEE learns the recipient wallet W during discovery — a deliberate, narrow privacy-scope widening versus a normal transfer — but can never move funds. A reusable funding pattern carries the usual send-to-address correlation caveat: a checksummed-address confirmation prompt and an optional unknown-sender warning on claim blunt it, but funding any address is inherently address-bound.

Using it from the SDK

The full method surface — giftFund, giftFundToWallet, giftClaim, giftClaimFromLink, giftRefundByRecord, getPendingGifts, decodeGiftLink, and the gift fields added to the transfer result — is documented per platform:

TypeScript

CLI

iOS

Android

React Native

WASM