Volume-based token reward system for traders on the Pump platform.
The token incentives system rewards traders based on their SOL trading volume. Rewards are distributed daily from a configurable token supply pool. The system tracks volume across both the Pump bonding curve program and the PumpAMM program.
flowchart TD
Pool["Daily Token Pool"]
Pool --> A["Trader A volume → proportional share"]
Pool --> B["Trader B volume → proportional share"]
Pool --> C["Trader C volume → proportional share"]
- A global daily token pool is configured (e.g., 1M tokens/day)
- Each trader's SOL volume is tracked via a
UserVolumeAccumulator - Rewards are proportional:
(userVolume / totalVolume) × dailyTokenPool - Unclaimed rewards accumulate across days
Before a user can earn incentives, they need a volume accumulator account:
import { PUMP_SDK, OnlinePumpSdk } from "@nirholas/pump-sdk";
const connection = new Connection("https://api.devnet.solana.com", "confirmed");
const sdk = new OnlinePumpSdk(connection);
// Initialize (one-time setup)
const ix = await PUMP_SDK.initUserVolumeAccumulator({
payer: wallet.publicKey,
user: wallet.publicKey,
});// Unclaimed rewards from pump program only
const pumpRewards = await sdk.getTotalUnclaimedTokens(user);
// Combined rewards from both programs
const totalRewards = await sdk.getTotalUnclaimedTokensBothPrograms(user);
// Current day's accrued rewards
const todayRewards = await sdk.getCurrentDayTokensBothPrograms(user);
console.log("Total unclaimed:", totalRewards.toString());
console.log("Today's rewards:", todayRewards.toString());// Claim from both programs
const instructions = await sdk.claimTokenIncentivesBothPrograms(user, payer);
const tx = new Transaction().add(...instructions);
await sendAndConfirmTransaction(connection, tx, [wallet]);If volume data is stale, sync it:
// Sync across both programs
const ixs = await sdk.syncUserVolumeAccumulatorBothPrograms(user);To reclaim rent:
const ix = await PUMP_SDK.closeUserVolumeAccumulator(user);For offline reward calculations without network calls:
import {
totalUnclaimedTokens,
currentDayTokens,
} from "@nirholas/pump-sdk";
// Calculate unclaimed tokens from raw accumulator data
const unclaimed = totalUnclaimedTokens(
globalVolumeAccumulator,
userVolumeAccumulator,
Math.floor(Date.now() / 1000), // optional timestamp
);
// Calculate current day's earnings
const today = currentDayTokens(
globalVolumeAccumulator,
userVolumeAccumulator,
);Tracks the total trading volume and token supply allocation per day.
interface GlobalVolumeAccumulator {
startTime: BN; // Program start timestamp
endTime: BN; // Program end timestamp
secondsInADay: BN; // Day duration for bucket calculation
mint: PublicKey; // Reward token mint
totalTokenSupply: BN[]; // Token supply per day bucket
solVolumes: BN[]; // Total SOL volume per day bucket
}Tracks an individual user's trading volume and claim state.
interface UserVolumeAccumulator {
user: PublicKey;
needsClaim: boolean; // Whether a claim is pending
totalUnclaimedTokens: BN; // Accumulated unclaimed rewards
totalClaimedTokens: BN; // Total claimed to date
currentSolVolume: BN; // Volume in current day bucket
lastUpdateTimestamp: BN; // Last sync timestamp
}Combined stats from both programs (returned by fetchUserVolumeAccumulatorTotalStats).
interface UserVolumeAccumulatorTotalStats {
totalUnclaimedTokens: BN;
totalClaimedTokens: BN;
currentSolVolume: BN;
}These are restricted to program administrators:
// Configure incentives for pump program
const ix = await sdk.adminUpdateTokenIncentives(
startTime, // BN - program start
endTime, // BN - program end
dayNumber, // number - which day to configure
tokenSupplyPerDay, // BN - tokens allocated for that day
secondsInADay?, // BN - optional, defaults to 86400
mint?, // PublicKey - reward token
tokenProgram?, // PublicKey - Token program ID
);
// Configure for both programs at once
const ixs = await sdk.adminUpdateTokenIncentivesBothPrograms(
startTime, endTime, dayNumber, tokenSupplyPerDay,
secondsInADay?, mint?, tokenProgram?,
);