CommodityReceiptToken representing the stored quantity, and cashes part of its value out to mobile money the same day — instead of waiting for a buyer. This tutorial builds that flow: deposit → receipt token → fiat payout, plus the expiry tracking a warehouse operator needs as receipts approach their storage limit.
What you’ll build
- A deposit endpoint that mints a
CommodityReceiptTokenfor a batch as soon as the warehouse operator confirms intake - An off-ramp endpoint that lets the farmer convert receipt value to mobile money or bank payout via
RampManager - A scheduled job that marks receipts
EXPIREDonce theirexpiryDatepasses
Prerequisites
- Node.js 18+
- A Stellar testnet account and secret key (
S...), funded via the Stellar Friendbot npm install @ankarachain/sdk express node-cron
1
Scaffold the project
src/config.ts
RampManager here is constructed with factory.adapter and a settlementAddress because this tutorial’s off-ramp step needs the on-chain custody half (depositOffRamp) as well as the off-chain quote/session half. Deploy the settlement contract once per platform with factory.deployRampSettlement({ treasury }) — see Fiat Ramp: On-chain settlement.2
Issue a receipt token on deposit
Run this each time the warehouse operator confirms a new batch has arrived. The same call works on EVM by swapping the
TokenFactory config — see Deploy a Token for the EVM variant.src/routes.ts
3
Let the farmer cash out to fiat
The farmer picks how many kilograms’ worth of receipt to convert. Quote, initiate the off-ramp session, then deposit the tokens into the settlement contract for custody:Once your provider confirms the payout (via webhook or by polling
src/routes.ts (continued)
ramp.getStatus()), release the custodied tokens to the treasury:src/routes.ts (continued)
4
Sweep expired batches nightly
Commodity receipts carry a hard
expiryDate — past it, the warehouse can no longer honor the stored quantity. Mark expired batches so your UI and any downstream lender can see the status change immediately:src/jobs/expireBatches.ts
isExpired() and markExpired() are only available on tokens deployed with the "commodity" template — calling them on any other AssetRegistry template throws. See AssetRegistry: Commodity Methods.Going further
- Batch warehouses: if one warehouse holds many rotating lots,
deployCommodityBatchToken()(ERC-1155-style) may fit better than oneCommodityReceiptTokenper batch — see Asset Templates: Multi-Token Variants. - Lending against a receipt instead of an outright off-ramp cash-out: see the Mining Royalty Platform tutorial, which walks through
CollateralVault— the same borrow-against-token pattern applies to warehouse receipts.
Next steps
AssetRegistry
Full reference for
isExpired, markExpired, and every other registry method.RampManager
On-chain settlement,
depositOffRamp, confirmOffRampSettlement, refundOffRamp.Asset Templates
The full
CommodityMetadata schema and lifecycle.CLI Commands
ankara deploy-batch, ankara offramp-initiate, and related commands.