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.

How it works

An ordinary private transfer needs the recipient’s privacy address. A wallet address alone does not supply the MPK and viewing key needed to construct that note. Claimable transfers solve this with a two-step fund → claim flow built around a gift note:
  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 returns an off-chain claim link carrying the gift 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 in a private claim. Wallet-recipient claims require a registered signing key, so an approval-only account cannot claim this way.
  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.
SDK claims require the recipient’s explicit acknowledgment that the sender is unknown before proceeding. 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), using the gift opening and a registered signing key. Wallet-bound funds are self-custodial end to end: only the user’s own authorization plus a valid proof move them. The TEE assists discovery and can never seize or redirect a wallet-bound gift.

Funding modes

The SDK exposes three ways to fund a gift. Pick the one that matches what you know about the recipient.
Anyone who holds a secret gift’s claim link can claim its funds. Only the explicit secret-funding methods (fundSecretBearer in TypeScript and React, giftFundSecretBearer on the other platforms) select this mode, while ordinary gift methods bind to a wallet.Secret claims settle only through the public exit and reveal the token, amount, and destination. The SDK CLI does not expose secret funding.

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 the gift opening, a registered signing key, and public on-chain data, a wallet-bound recipient can build a public exit with no TEE and no relay. This is the ultimate liveness backstop.

Refunds and the deadline

You choose refundAfterBlock when you fund. The deadline opens the sender refund path without expiring the recipient claim. After it passes, either can settle first while the gift remains unspent. The server advertises minimum and maximum refund delays through /info and checks them at funding. The refund proof enforces that the selected deadline has elapsed, so the sender cannot refund early. 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). A secret-bearer gift returns no local record. Its claim link is the funder’s refund credential, so keep the link if you may need to refund.

What observers and the TEE learn

A private claim and a private refund are indistinguishable on chain. The TEE learns the recipient wallet W during discovery. For an ordinary transfer it learns the recipient’s master public key rather than a wallet address, along with the token and amount it already decrypts. 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. A public exit reveals the authorization leaf, which identifies the settling account, along with the token, amount, and destination.

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