How it works
Gift card credits live on Starknet. When a recipient redeems to Solana, USDC is bridged via Circle’s CCTP V2 (Cross-Chain Transfer Protocol):
1. Starknet: USDC burned via TokenMessenger.depositForBurn
2. Circle: attestation signers verify the burn (~5 sec fast mode)
3. Solana: USDC minted to recipient's wallet via receiveMessage
Total time: ~24 seconds end-to-end (burn + attestation + Solana confirmation).
Fast vs Standard mode
Each Gift carries a cctpFast flag that controls Solana redeem speed:
| Mode | Attestation time | Fee | Best for |
|---|
cctpFast: true (default) | ~5 seconds | ~$0.01 per redeem | Real-time claims, good UX |
cctpFast: false | 4-8 hours | Free | Batch distributions where speed doesn’t matter |
Fast mode pays a small fee to Circle’s attestation service for priority. Standard mode waits for Starknet’s ZK proof to post to Ethereum L1.
Single-create (POST /v1/gifts) does not accept cctpFast in the request today. The gift is always created with cctpFast: true (the schema default). To set cctpFast: false, use the bulk endpoint (POST /v1/gifts/bulk) which accepts the flag, or the dashboard’s bulk-airdrop flow.
Supported chains
| Destination | Status | Time |
|---|
| Starknet | Live | Instant (direct ERC20 transfer) |
| Solana | Live | ~24 sec (CCTP V2) |
| Base | Coming soon | — |
| Arbitrum | Coming soon | — |
| Ethereum | Coming soon | — |
Redeem flow for Solana
// 1. Redeem — returns 202 with redeemId
const res = await fetch("https://api.chipipay.com/v1/gifts/claim/CODE/redeem", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
walletAddress: "FZQq6KCS...", // Solana wallet pubkey
chain: "solana",
}),
});
const { redeemId, status } = await res.json();
// status = "BRIDGING"
// 2. Poll until SUCCESS
while (true) {
const statusRes = await fetch(
`https://api.chipipay.com/v1/gifts/claim/CODE/status/${redeemId}`
);
const data = await statusRes.json();
if (data.status === "SUCCESS") {
console.log("USDC received on Solana:", data.receiveChainTxHash);
break;
}
if (data.status === "FAILED") {
console.error("Bridge failed. Burn tx:", data.cctpBurnTxHash);
break;
}
await new Promise(r => setTimeout(r, 5000)); // poll every 5 sec
}
Status flow
PENDING → BRIDGING → ATTESTED → SUCCESS
↘ FAILED (if bridge times out or Solana tx fails)
| Status | Meaning |
|---|
PENDING | Redeem record created, not yet sent |
BRIDGING | CCTP burn submitted on Starknet, waiting for Circle attestation |
ATTESTED | Circle attestation ready, Solana receive pending |
SUCCESS | USDC delivered to recipient’s wallet |
FAILED | Something went wrong — check cctpBurnTxHash for the Starknet burn tx |
Technical details
- CCTP V2 contracts: TokenMessenger on Starknet (
0x07d421...), MessageTransmitter on Solana (CCTPV2Sm4...)
- Domain IDs: Starknet = 25, Solana = 5
- Mint recipient: must be the Solana USDC Associated Token Account (ATA), not the wallet pubkey
- Circle attestation API:
https://iris-api.circle.com/v2/messages/25?transactionHash={txHash}
- Server relay: Chipi’s server submits the
receiveMessage transaction on Solana and pays the SOL gas fee
The recipient doesn’t need SOL for gas — Chipi’s relay pays for the Solana transaction.