Docs/Integrate your program/Add from wallet
Add from wallet
Create a signed redemption to burn wallet tokens and credit matching points to the customer’s brand account.
When a customer chooses Add from wallet, your backend creates a signed redemption for their verified wallet. The customer completes checkout to burn the selected tokens. After finalized completion, your backend credits the matching points to their brand account.
Inputs#
| Field | Type | Required | Meaning |
|---|---|---|---|
issuer | address | external signing | Brand wallet that signs the redemption. Omit together with the issuer signature for enabled API signing. |
loyaltyId | bytes32 | yes | Brand-scoped program ID. |
amount | uint256 string | yes | Tokenized loyalty amount to burn and reconcile offchain. Must be greater than zero. |
expiresAt | uint256 string | yes | The exact bucket to burn. Use 0 for non-expiring balances. |
deadline | uint256 string | yes | Last Unix timestamp when the redemption can be submitted. Use 0 for no execution deadline. |
nonce | bytes32 | yes | Unique per issuer. Replays are rejected. |
chainId | uint256 string | yes | Expected chain ID. Loyfin uses Base 8453. |
verifyingContract | address | yes | The Loyfin factory that will execute the action. |
operationHash | bytes32 | optional | Brand reference hash for correlating this action with an internal database row. Defaults to zero bytes when omitted. |
data | hex bytes | optional | Brand-defined fulfillment data. Defaults to 0x. Max 2048 bytes. |
Request#
{
"redemption": {
"issuer": "0x1111111111111111111111111111111111111111",
"loyaltyId": "0x4242424242424242424242424242424242424242424242424242424242424242",
"amount": "250",
"expiresAt": "0",
"deadline": "1790965800",
"nonce": "0x7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b",
"chainId": "8453",
"verifyingContract": "0x3333333333333333333333333333333333333333",
"operationHash": "0x9999999999999999999999999999999999999999999999999999999999999999",
"data": "0x"
},
"signature": "0xababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab",
"from": "0x2222222222222222222222222222222222222222"
}// Run on your backend. Sign the redemption as shown in Signing.
// verifiedWallet must be proved and linked to the account receiving points.
const response = await fetch("https://api.loyfin.com/redemptions", {
method: "POST",
headers: {
"content-type": "application/json",
"x-loyfin-api-key": process.env.LOYFIN_API_KEY
},
body: JSON.stringify({
redemption,
signature,
from: verifiedWallet
})
});
if (!response.ok) {
throw new Error(await response.text());
}
const { redemption: session, duplicate } = await response.json();Fulfillment#
Loyfin burns the signed tokenized amount from the customer's selected bucket. The issuer publishes the signed redemption, then the customer authorizes and submits it through Checkout while paying the action fee and gas. Your backend credits the matching points only after finalized completion.
Common errors#
- Customer has insufficient balance in the selected expiry bucket.
- The bucket is expired.
- The action deadline has passed.
- The signature, nonce, chain, or verifying contract does not match.
Brand database flow#
Treat redemption as a pending brand operation until it is confirmed.
Add from wallet usually starts inside the brand app: the customer is logged in, connects a wallet, proves ownership with a brand-scoped wallet signature, chooses tokenized value to add back, and the app calls your brand API. Your backend verifies the wallet/account mapping, creates an internal redemption row, signs the redemption, and creates a private Loyfin checkout for the customer. The brand database remains the system of record for customer balance, support, and account state.
- Use operationHash to connect the signed redemption, indexed Loyfin activity, and your internal redemption row.
- A pasted address is not enough for Add from wallet. The customer should prove wallet ownership before the brand credits an offchain account.
- After
POST /redemptionsreturns successfully, keep the brand operation pending until the burn is confirmed. - After finalized completion, credit the matching points, update the account record, and show the customer the completed conversion.
- Use verified completion webhooks by default. Polling or direct chain reads are reconciliation fallbacks and must check finality. A brand may submit an authorized transaction itself as an alternative; that submitting wallet then pays the action fee and gas. The API does not submit transactions.
Receipt processing#
Credit points exactly once for each finalized burn.
Loyfin indexes burns in redemptions. Query by the verified wallet and your token address. Check that each transaction succeeded in a canonical finalized block before crediting points, and process each receipt only once. See Receipts and webhooks for finality and reversal handling.
curl "https://api.loyfin.com/redemptions?from=0x2222222222222222222222222222222222222222&token=0x4444444444444444444444444444444444444444&chainId=8453&limit=100"- Store a unique receipt key such as
chainId + txHash + logIndex, the block hash, and youroperationHash. Reconcile reversal and re-inclusion events against the existing receipt state. - Verify the receipt belongs to the brand's expected issuer/token before crediting points.
- Sum only unprocessed rows for the wallet mapped to the logged-in brand account, then mark them processed in the same brand-side transaction that credits the loyalty value.
State machine#
Offchain credit should wait for the tokenized value to be burned.
Requested
The logged-in customer starts Add from wallet in the brand app.
Authorized
Your backend verifies wallet ownership, customer identity, token bucket, and internal account constraints.
Awaiting authorization
Create the checkout and keep the account credit pending while the customer authorizes and submits it.
Credited
After finalized completion, credit the points and record the processed receipt in the same database transaction.