For the complete documentation index, see llms.txt. This page is also available as Markdown.

Quest

Quest/reward collection β€” users complete criteria and claim a badge + coin payout

Category: Token Types

Summary

Required standards: ["Quests"]

  • Single token only: validTokenIds = [{start: "1", end: "1"}]

  • Quest approval MUST be properly gated β€” typically via an off-chain claim (merkle challenge with claimConfig), but can also use on-chain criteria (mustOwnTokens, dynamicStoreChallenges, evmQueryChallenges, votingChallenges)

  • Coin transfers with overrideFromWithApproverAddress: true + overrideToWithInitiator: true

  • predeterminedBalances: amount 1, no increments, no recurring, no duration

  • Escrow funded upfront via set_mint_escrow_coins (rewardAmount * maxClaims)

  • invariants.noCustomOwnershipTimes: true

  • Permissions: use "locked-approvals" preset (recommended)

  • Default balances: empty balances, all auto-approve flags true

Instructions

Quest Configuration

Mental Model

A quest collection rewards users for completing criteria. Users receive a quest badge (token 1) + coin payout.

The quest approval MUST be properly gated so that only eligible users can claim. Gating options:

  • Off-chain claim (most common): A merkle challenge with claimConfig containing plugins (password, codes, whitelist, etc.). The claim is verified off-chain by BitBadges, and a merkle proof is issued for on-chain redemption.

  • On-chain criteria: mustOwnTokens (require holding specific tokens/badges), dynamicStoreChallenges, evmQueryChallenges, votingChallenges β€” these are checked directly on-chain during the transfer.

  • Both: Combine off-chain claims with on-chain criteria for layered verification.

Choose the gating approach based on the user's request. If they mention passwords, codes, or whitelists, use an off-chain claim. If they mention token ownership or on-chain conditions, use the corresponding on-chain criteria.

Build Steps (call ALL in parallel in one round)

  1. set_standards β†’ ["Quests"]

  2. set_valid_token_ids β†’ [{ "start": "1", "end": "1" }]

  3. set_invariants β†’ { "noCustomOwnershipTimes": true }

  4. set_permissions β†’ { "preset": "locked-approvals" }

  5. set_default_balances β†’ empty balances, all auto-approve true

  6. set_collection_metadata / set_token_metadata β€” descriptive content

  7. add_approval β€” the quest approval (see exact structure below)

  8. set_mint_escrow_coins β€” REQUIRED for coin rewards. Amount = rewardPerClaim Γ— maxClaims.

Quest Approval (add_approval)

Use approvalId "quest-approval". The EXACT approvalCriteria structure:

Gating β€” add ONE OR MORE of these to approvalCriteria based on the user's request:

  • Off-chain claim: "merkleChallenges": [{ "root": "", "expectedProofLength": "0", "maxUsesPerLeaf": "1", "uri": "", "customData": "", "useCreatorAddressAsLeaf": false, "claimConfig": { "approach": "in-site", "label": "...", "plugins": [...] } }]

  • Token ownership: "mustOwnTokens": [{ "collectionId": "...", "amountRange": {"start":"1","end":"18446744073709551615"}, ... }] β€” Use collectionId "0" to self-reference this collection (e.g., require holding token 1 from this quest collection itself).

  • Dynamic store: "dynamicStoreChallenges": [...]

  • EVM query: "evmQueryChallenges": [...]

Off-chain claims are the most common for quests (passwords, codes, whitelists). On-chain criteria can be combined with or used instead of claims.

Escrow Funding (REQUIRED)

Call set_mint_escrow_coins in the SAME round as the other tools. Example for 10 ATOM reward Γ— 50 claims:

Without this, the escrow has no funds and claims will fail.

Common Mistakes

  • DON'T add extra fields to coinTransfers β€” the ONLY fields are: to, overrideFromWithApproverAddress, overrideToWithInitiator, coins. NO startTime, NO other fields.

  • DON'T omit manualBalances: [] in predeterminedBalances β€” SDK crashes without it

  • DON'T omit fields in orderCalculationMethod β€” include ALL boolean fields

  • DON'T forget set_mint_escrow_coins β€” without it, the escrow is empty and rewards can't be paid

  • DON'T set maxUsesPerLeaf to anything other than "1" β€” each user claims once

  • DON'T set allowOverrideTimestamp: true β€” quests require false

  • DON'T set useCreatorAddressAsLeaf: true β€” quests require false

Last updated