Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.snagsolutions.io/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Token rewards let a loyalty rule pay an on-chain ERC-20 amount directly into the user’s wallet on rule completion. Examples:
  • A “mint NFT” rule that grants $50 in FLOW.
  • A “10k impressions” rule that grants $10 in ETH.
  • A quest chain that grants $5 in USDC on the final step.
The reward type lives next to Points, Multiplier, and Badge in the loyalty rule form. Picking it surfaces a relayer + token contract picker.

How it works

Token rewards reuse the existing loyalty ledger via a hidden LoyaltyCurrency. When you create a token rule:
  1. The backend resolves (or creates) a hidden LoyaltyCurrency bound to the chosen contract, with decimals: 18 (so fractional amounts like 0.5 work correctly).
  2. It also creates an OnchainToken row with distributionType = transfer and the chosen relayer.
  3. Rule completion writes a normal LoyaltyTransactionEntry against that hidden currency — same code path as points.
  4. The on-chain token sync worker picks up the entries, batches recipients/amounts, and submits a disperseToken call to the Disperse.app contract via the relayer.
  5. The payout transaction hash is written back to each LoyaltyTransactionEntry.distributeNativeTokensTxHash.
Because Option 1 (hidden currency) is in use, leaderboard, history, and balance APIs see token rewards as just another currency — no special-cased reads. The hidden currency itself is filtered out of header dropdowns / customer-facing currency selectors.

Distribution types on OnchainToken

TypeWhat it does
mintExisting flow. Calls batchAdminMint / batchAdminBurn on the hybrid ERC-20 contract from the relayer.
transferNew flow. Encodes a batched disperseToken(token, recipients[], amounts[]) call to the Disperse contract; the relayer’s wallet is the funding source. Used for token rewards.

Decimals — important for fractional amounts

Token rewards depend on the existing LoyaltyCurrency.decimals field. The loyalty system stores raw amounts in the smallest units of the currency; everything user-facing converts via formatLoyaltyAmountForDisplay(rawAmount, decimals) (frontend) or fromDecimalToNumber(decimals, rawAmount) (backend). If you add a custom display path for loyalty amounts, route it through formatLoyaltyAmountForDisplay — otherwise an 18-decimal currency will show as 1000000000000000000 instead of 1. When a user completes a token-reward rule, the success modal includes the line “It may take a few minutes to appear in your wallet.” — payout is asynchronous (driven by the on-chain token sync worker), with a 5-minute upper bound under normal load.

Plan gating

Token rewards require Pro (specifically enableStratusRelayers). The rule will reject at create time and at run time on lower plans with a pricing-plan error.

Configuration

In the rule form:
  1. Pick Tokens in the reward-type toggle.
  2. Pick a Relayer — the dropdown filters to relayers on the chain of any contract you’ve already chosen.
  3. Pick a Token (the contract) — filtered to the relayer’s chain.
  4. Set the amount per completion (0.01 minimum).
The backend creates the hidden LoyaltyCurrency + OnchainToken linkage on first save; subsequent rules pointing at the same (contract, relayer) reuse them.