Skip to main content

Claimable Transfers (Gifts)

Send shielded funds to an Ethereum wallet address that has not registered with Privacy Boost yet. The recipient claims by proving ownership of that address; you reclaim the funds if they never do. See Claimable Transfers for the concept and trust model.
Gift methods live on sdk.gifts and route every call through the key vault, so they work in the browser-default iframe vault mode as well as with a local WASM vault. Every method is async, including the ones that do no network work, because an iframe vault answers over postMessage.

Sending a gift

The most common case: you know the recipient’s wallet address but they have not joined Privacy Boost. Use sdk.gifts.fundToWallet. Block heights cross the vault boundary as decimal strings, so pass refundAfterBlock and currentBlock as strings rather than numbers.
If the recipient is already a Privacy Boost user, fund with their privacy address as well (sdk.gifts.fund). The gift still binds to recipientWallet; the privacy address only decides whose viewing key the ciphertext is sealed to, so the recipient’s own discovery finds the gift without needing the claim link:

Funding parameters

The gift binds irrevocably to recipientWallet. A wrong-but-valid address can be claimed by whoever controls it, and only an unclaimed gift is refundable. Show the exact checksummed address and require explicit confirmation before funding.

Funding result

fund and fundToWallet return a GiftResult:

Secret-bearer gifts

sdk.gifts.fundSecretBearer binds the gift to a secret instead of a wallet, so it can be claimed by whoever holds the link, before the recipient owns any wallet at all. It is a bearer instrument: the link is the only credential, for the recipient and for you. No giftRecord comes back and records() never lists the gift, so keep the link as carefully as the funds it unlocks. currentBlock is required here, because the refund delay is validated locally before funding.
A secret-bearer gift is a bearer instrument, selected only by the explicit fundSecretBearer method. See the concept page before considering it.
result.claimLink is a pbgift:v1:... string that carries the encrypted opening the recipient needs. Share it out of band (message, QR code). Treat it like a password: it reveals the gift’s amount and recipient to anyone who reads it, and for a secret-bearer gift it lets anyone who reads it claim.

Claiming a gift

The recipient registers Privacy Boost with the same wallet address, then claims. List the pending gifts addressed to the authenticated wallet. The server is queried and each entry is decrypted with the viewing key:
Claim one by its stable commitment cGift. Each pending entry also carries a positional index, but that shifts as gifts settle, so the commitment is the selector to keep:
Or claim straight from a claim link, without a server lookup first:
acknowledgeUnknownSender must be true to claim. The hidden-sender model cannot reveal who funded a gift, so the recipient explicitly acknowledges accepting funds from an unknown sender. Surface this as a consent prompt.
A successful claim re-mints the gift into a normal shielded note. From then on it behaves like any other note in the recipient’s balance.

Refunding an unclaimed gift

A claim and a refund spend the same nullifier, so only one can ever settle. After the refund deadline passes, reclaim an unclaimed gift. Within the session that funded it, sdk.gifts.records() lists your gifts newest first and sdk.gifts.refundByRecord reclaims one by position:
records() is an in-memory ledger, not a query. The per-gift blind it holds is the refund secret; it is generated locally at funding time and never reaches the server, so there is nothing to fetch it back from. The list is empty after a page reload or a new login, and a gift whose record was not persisted can no longer be reclaimed. Persist result.giftRecord yourself at funding time.
To refund a gift from a stored record, use sdk.gifts.refund with the record’s fields. Every field is a string, including the ones GiftRecord reports as numbers, so convert them rather than spreading the record in:
fundingTreeNumber and giftLeafIndex are filled in once the funding transfer is indexed, so a record captured the instant funding returns may not carry them yet. Refresh it from records() before the session ends, or store the two values once they are known. Decode and decrypt a claim link into a preview without any network call. Useful to show the recipient what they are about to accept:

Types

GiftFundParams, GiftFundToWalletParams, GiftFundSecretBearerParams, GiftClaimByCGiftParams, GiftClaimFromLinkParams, GiftRefundParams, GiftResult, and the three below are exported from @sunnyside-io/privacy-boost.
sdk.gifts is bound to the chain the root SDK was configured for, and sdk.forChain() clients have no gifts. To gift on more than one chain, create a separate root SDK instance per chain.