Docs/Build guides/Add from wallet
Add from wallet
Prepare and store a signed redemption that burns tokenized loyalty value so the brand can credit or restore offchain points/value.
Create a redemption when a logged-in customer proves wallet ownership and burns tokenized loyalty value so the brand can credit or restore offchain points/value. A brand can also map this to a discount, product, upgrade, or access pass, but the default integration model is an offramp back to the brand's ledger.
Inputs#
| Field | Type | Required | Meaning |
|---|---|---|---|
issuer | address | yes | Brand wallet that signs the redemption. |
from | address | session | Customer wallet whose tokenized balance is burned. Not part of the issuer-signed terms; add it with the holder signature or collect it on checkout. |
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": "0",
"nonce": "0x7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a",
"chainId": "8453",
"verifyingContract": "0x3333333333333333333333333333333333333333",
"operationHash": "0x9999999999999999999999999999999999999999999999999999999999999999",
"data": "0x"
},
"signature": "0xababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab"
}import { Loyfin, redemptionTypedData } from "@loyfin/server";
const loyfin = new Loyfin({ apiKey: process.env.LOYFIN_API_KEY });
const typedData = redemptionTypedData(redemption);
const signature = await issuerSigner.signTypedData(typedData);
const { redemption: session, duplicate } = await loyfin.redemptions.create({
redemption,
signature
});
// Show session.checkoutUrl when the holder still needs to sign.Fulfillment#
Loyfin burns the signed tokenized amount from the customer's selected bucket. The issuer only needs to publish the signed redemption; Loyfin's official relayer or an independent relayer can submit it. Your brand system should credit, restore, or fulfill the offchain result only after the redemption is completed.
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 stores it through Loyfin or submits it onchain directly. 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. - On confirmation, apply the brand-side result: credit or restore the offchain points/value, update the account record, and show the customer the completed add-from-wallet receipt.
- The helper API is the default path for performance and efficiency. Confirmation can come from account-level webhooks, polling
GET /operationsorGET /redemptions, or direct onchain event reads. Brands can also submit theredeemtransaction themselves instead of relying on the helper API.
Receipt processing#
Credit offchain value exactly once for each completed burn.
Loyfin indexes completed burns in redemptions. For a wallet-linked account, a brand can query completed rows by wallet and token address, then process only receipts that are not already marked completed in the brand database.
curl "https://api.loyfin.com/redemptions?from=0x2222222222222222222222222222222222222222&token=0x4444444444444444444444444444444444444444&chainId=8453&limit=100"- Store a processed key such as
chainId + txHash + logIndex, plusoperationHashwhen available. - Verify the receipt belongs to the brand's expected issuer/token before adding offchain value.
- 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 points.
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.
Created
POST the signed redemption to Loyfin and keep the offchain credit pending in your own system.
Credited
After the redemption is mined, add the offchain points/value and store the receipt key for support.