Status lifecycle
How we read purchase, send and buyback status
We track each pack by its memo, through GET /api/pack/status. Status fields are
two-state, "confirmed" or null; there is no pending, failed or refunded value.
| Field | "confirmed" | null |
|---|---|---|
pack.status | Paid; the pack can be opened. Never reverts. | Reserved, payment not seen. Stays null for an abandoned checkout. |
send.status | Card transfer confirmed on chain | Not sent yet. Turbo packs are never stamped: treat webhook_sent: true or transaction_signature: "turbomode" as delivered. |
buyback[].status | Settled: card returned, USDC paid | Quote issued or submitted, not settled |
Refunds show as pack.refunded: true with refund_transaction_signature.
State diagram
What we derive
| Our state | Rule |
|---|---|
| Awaiting payment | pack.status is null |
| Paid, unopened | pack.status confirmed, no send row |
| Delivered | send.status confirmed, or webhook_sent, or turbo |
| Sold back | a buyback row confirmed |
| Refunded | pack.refunded is true |
Timing we rely on
- Payment confirmation:
confirmedcommitment, about 2 seconds on Solana. - Open deadline: 2 hours at Collector Crypt, then auto-refund. Prizes and unclaimed packs can wait days, so a fixed 24-hour auto-open needs to be configurable or switchable off per purchase.
- Delivery: within seconds of open.
- Buyback window: 72 hours at Collector Crypt. Your 7 days is fine.
Status checks
We poll pack/status and getGifted today. A signed webhook for paid, opened, delivered,
refunded and buyback settled would replace most of that polling.