Skip to Content
DocsFlowsClaim flow

Claim flow

This guide is written for whoever owns recipient communications. Use it to understand what claim surfaces are available, what the API expects, and how to troubleshoot issues quickly.

What recipients experience

  1. Open a claim surface. You can send them to the hosted Sync page, embed the (coming soon) widget in your product, or trigger the flow yourself via SDK.
  2. Verify eligibility. The UI asks for a wallet address, fetches the Merkle proof, and previews the payout.
  3. Sign once. Claims are subsidized (≈ $0.50 USD) so recipients don’t need SOL. They approve one transaction and get a success receipt.

Behind the scenes

  • Proof lookup. GET /sync/distributions/:id/proof?wallet=<pubkey> returns { amount, index, merkleProof[], tokenMint } along with status flags (claimed, outside vesting window, etc.).
  • Transaction build. POST /sync/v1/distributions/:id/claims assembles the newClaim instruction, Token-2022 wrapper steps (if required), memos, and Lighthouse assertions.
  • Submission + logging. Sync submits the transaction, stores the signature, and records who claimed which allocation for your analytics.

Token-2022 specifics

  • Wrapping/unwrapping is transparent to recipients. They still end up with plain SPL tokens in their ATA even if the source mint uses Token-2022 extensions.
  • Wrapper rent and compute sit inside the subsidized fee. No separate approvals needed.

Error states you’ll see

  • Invalid proof / already claimed. Suggest the recipient refresh; if it persists, re-sync the cohort or reach out with the signature for audit.
  • Vesting not open. The UI shows the unlock timestamp so support can give a concrete answer.
  • Empty vault. Claims pause automatically. Fund or claw back from the dashboard.
  • Missing token account. Sync creates the ATA inside the same transaction; recipients only see a slightly longer signing flow.

SDK example

import { useSyncClaims } from "@fractalshq/sync/react"; import { useTxAuth } from "@fractalshq/auth/react"; const { fetchClaimTx } = useSyncClaims(); const { signAndSend } = useTxAuth(); async function claim(distributionId: string) { const { transaction, expectedAmount } = await fetchClaimTx({ distributionId }); await signAndSend(transaction); console.info(`Claimed ${expectedAmount} tokens`); }

Widget drop-in

<SyncClaimWidget distributionId="dist_23" wallet={wallet} onClaimed={refreshStats} />

Use the (coming soon) widget when you want a no-code surface that still fires events (onClaimed, onError) so your UI stays live.

Last updated on