TORQUEDocs

Creating Incentives

Step-by-step guide to creating any type of incentive

Every incentive follows the same pattern: set up your data sourcegenerate a querypreview resultscreate the incentive. The setup step varies by action type.

Choose Your Action Type

ActionWhat It TracksSetup Required
SwapToken trades on DEXs (Jupiter, Raydium, etc.)None — already indexed
Bonding CurveTrades on launchpads (Raydium Launchlab, Metaplex Genesis)None — already indexed
HoldToken balance at evaluation timeNone — already indexed
Custom EventOff-chain activity (signups, social actions, purchases)Event schema + data ingestion
IDL InstructionOn-chain Solana program interactionsIDL upload
Dune QueryActivity tracked by a saved Dune Analytics queryDune MCP + query registration

Action-Measure Compatibility

Not all measures work with all actions:

Actionvolumecountdurationbalance
Swapyesyes
Bonding Curveyesyes
Holdyesyesyes
Custom Eventvia valueExpressionyes
IDL Instructionvia valueExpressionyes
Dune Queryvia valueExpression or rawQueryyesyesyes

Token Incentives (Zero Setup)

Token incentives reward on-chain token activity using already-indexed data. No setup required.

1

Generate the query

Use generate_incentive_query with the appropriate source:

Swap — track DEX trades:

source: "swap"
tokenMint: "your-token-mint"
direction: "buy"
measure: "volume"

Bonding Curve — track launchpad trades. Each token launched on a launchpad has a unique identifier that locates its bonding curve on-chain: a pool state address on Raydium LaunchLab, or a genesis account address on Metaplex Genesis. Ask the user for the relevant identifier (they can get it from the launchpad UI) — no separate token mint needed; the pool/genesis account already uniquely identifies that token's curve.

For Raydium LaunchLab, ask the user for the pool state address:

source: "bonding_curve"
launchpad: "raydium_launchlab"
poolState: "pool-state-address"
direction: "buy"
measure: "volume"

For Metaplex Genesis, ask the user for the genesis account address:

source: "bonding_curve"
launchpad: "metaplex_genesis"
genesisAccount: "genesis-account-address"
direction: "buy"
measure: "volume"

Hold — track token holders:

source: "hold"
tokenMint: "your-token-mint"
measure: "balance"
minBalance: 1000
2

Preview results

Use preview_incentive_query to validate against real data:

sqlQuery: "<the generated SQL>"
3

Create the incentive

Use create_recurring_incentive with the query and reward configuration:

name: "Weekly Swap Leaderboard"
type: "leaderboard"
emissionType: "TOKENS"
tokenAddress: "your-token-mint"
tokenDecimals: 9
totalFundAmount: 1000
interval: "WEEKLY"
startDate: "2026-01-01T00:00:00Z"
sqlQuery: "<the generated SQL>"
customFormula: "RANK == 1 ? 500 : RANK <= 3 ? 200 : RANK <= 10 ? 50 : 0"

Always call with confirmed: false first to preview the 5% protocol fee (added on top of totalFundAmount — the creator pays totalFundAmount × 1.05) and the 7-day claim window.

For leaderboards, always ask the user how they want rewards distributed and build customFormula from their intent. The fallback N pays each user their raw metric value — rarely intended.

Token Incentive Examples

RecipeSourceMeasureDirectionType
Top Buyers by Volumeswapvolumebuyleaderboard
Hold Rewardsholdbalanceleaderboard or rebate
Bonding Curve Early Buyersbonding_curvevolumebuyleaderboard
Swap Raffleswapcountbuyraffle

Custom Event Incentives

Custom event incentives track off-chain activity — social actions, content creation, purchases, game events.

1

Create the event schema

Use create_custom_event:

eventName: "content_share"
name: "Content Share"
fields: [
  { fieldName: "platform", type: "string" },
  { fieldName: "reach", type: "number" },
  { fieldName: "verified", type: "boolean" }
]
2

Attach to your project

Schemas are project-independent. Use attach_custom_event to make the schema available on the active project:

customEventId: "<the event ID from step 1>"
3

Send event data

Use the ingestion API with your API key (see API Keys):

curl -X POST https://ingest.torque.so/events \
  -H "Content-Type: application/json" \
  -H "x-api-key: your-api-key" \
  -d '{
    "userPubkey": "wallet-address",
    "timestamp": 1234567890000,
    "eventName": "content_share",
    "data": {
      "platform": "twitter",
      "reach": 1500,
      "verified": true
    }
  }'
4

Generate, preview, and create

Generate the query:

source: "custom_event"
customEventId: "<the event ID>"
valueExpression: "SUM(reach)"
filters: ["verified = true"]

Preview with preview_incentive_query, then create with create_recurring_incentive (include customEventId in the creation call).

Events must be ingested at least once before they become query-ready. Use list_custom_events with scope: "project" to check which events are ready.

IDL Instruction Incentives

IDL instruction incentives reward users for interacting with specific instructions in your Solana program.

1

Preview the IDL

Call create_idl with confirmed: false on the IDL file — this parses locally and lists available instructions, fields, and accounts. No auth or active project required in this phase.

filePath: "/path/to/your/idl.json"
confirmed: false
2

Upload the IDL

Call create_idl again with confirmed: true and the instructions you want to track:

filePath: "/path/to/your/idl.json"
confirmed: true
displayName: "My Program"
selectedInstructions: [
  {
    instructionName: "buy_exact_in",
    fields: [
      { fieldName: "amount_in", type: "number" },
      { fieldName: "min_amount_out", type: "number" }
    ],
    accounts: ["payer", "pool"]
  }
]
3

Generate, preview, and create

Generate the query:

source: "idl_instruction"
instructionId: "<the instruction ID from step 2>"
valueExpression: "SUM(amount_in)"

Preview with preview_incentive_query, then create with create_recurring_incentive (include instructionId in the creation call).

Use list_idls to see uploaded IDLs and their tracked instructions. Use create_instruction to add a single instruction to an already-uploaded IDL without re-uploading the whole IDL.

Dune Query Incentives

Dune query incentives reward users based on activity tracked by a saved Dune Analytics query. Use this when the data you want to incentivize is easier to express in Dune SQL than through an IDL or custom event pipeline.

Requires the Dune MCP installed alongside the Torque MCP. The Dune query must be saved (non-temp), return exactly one day of results per run, and be scoped by a single string parameter cast to DATE.

1

Register the Dune event source

Use register_dune_event_source with the column mapping:

duneQueryId: 1234567
queryName: "Daily Active Traders"
fields: [
  { duneColumn: "volume_usd", fieldName: "volume_usd", type: "number" },
  { duneColumn: "trade_count", fieldName: "trade_count", type: "number" }
]
userPubkeyField: "wallet_address"
eventTypeField: "trade_type"
timestampField: "trade_time"
dateParamName: "date"
txHashField: "tx_hash"
usdValueField: "volume_usd"

Call once with confirmed: false to preview, then again with confirmed: true. The tool returns a duneEventQueryId — save it for the generate-preview-create step below.

txHashField and usdValueField are nullable but strongly recommended. If you omit either (e.g. for an aggregated query with no per-row tx hash), you must also pass acknowledgeIncompleteConfig: true on the confirmed: true call — the tool will refuse to proceed otherwise. Incomplete configs make incentive query building significantly harder, so fill these in whenever your Dune query exposes them.

2

Validate via the Dune MCP

Through the Dune MCP: executeQueryById with a recent date for dateParamName, then getExecutionResults. Confirm the execution succeeds and returns rows with the expected columns. If it errors or returns no rows, fix the Dune query (via the Dune MCP) before proceeding.

3

Wait for the first daily ingestion

Torque ingests Dune query results on a daily schedule. generate_incentive_query rejects Dune sources until their column mapping is populated by the first ingestion run — expect up to 24 hours.

4

Generate, preview, and create

Generate the query:

source: "dune_query"
duneEventQueryId: "<the UUID from step 1>"
valueExpression: "SUM(volume_usd)"

Note: pass the Torque-side duneEventQueryId UUID — NOT the numeric Dune duneQueryId.

Preview with preview_incentive_query, then create with create_recurring_incentive.

Daily ingestion means results lag by at most one day. Schedule your incentive intervals (e.g. WEEKLY) to align with this cadence.

Reward Types

Once you have a query, choose how rewards are distributed:

TypeHow It WorksKey Params
LeaderboardRank users by metric, distribute via formulacustomFormula (ask the user!)
RebateReturn a % of each user's metric valuerebatePercentage
RaffleRandom draw from qualifying usersraffleBuckets, raffleWeighting
DirectFixed amounts to specific walletsallocations

See Incentive Types for full details on each type, formulas, and examples.

Creating Incentives - Torque Docs