Revenue Interactions

A slice of protocol fees is distributed to wallets that have FAF staked. This page shows how to read a wallet's claimable USDC balance and submit the on-chain claim.

Two things to know before you call these helpers:

  • Revenue is FAF-scoped, not pool-scoped. The tokenVault and revenueTokenAccount are shared across every mainnet pool, so any pool config can be the anchor — Crypto.1 is used in the examples.

  • Wallets without an FAF stake account (or with zero eligible amount) will see revenueAmount == 0. claimRevenue will short-circuit and skip the transaction in that case.

Requires flash-sdk >= 2.52.1.

Setup

Revenue claims use the same PerpetualsClient setup as the other SDK examples. If you've already configured a client on the Flash SDK landing page, reuse it — just import POOL_CONFIGS[0] (or any pool) as the anchor.

For a standalone script:

import dotenv from 'dotenv'
import {
    BN_ZERO,
    nativeToUiDecimals,
    PerpetualsClient,
    PoolConfig,
    USD_DECIMALS,
} from 'flash-sdk'
import { AnchorProvider, BN } from '@coral-xyz/anchor'
import {
    AddressLookupTableAccount,
    ComputeBudgetProgram,
    PublicKey,
    Signer,
    TransactionInstruction,
} from '@solana/web3.js'

dotenv.config()

// Crypto.1 is the canonical anchor — switch to `devnet.1` for devnet testing.
export const POOL_CONFIG = PoolConfig.fromIdsByName('Crypto.1', 'mainnet-beta')

// Revenue is paid in USDC. Override only if a future pool changes this.
const REVENUE_TOKEN_SYMBOL = 'USDC'

// Generous CU budget — matches the flash-main-ui claim flow.
const CU_CLAIM_REVENUE = 200_000

const RPC_URL = process.env.RPC_URL
if (!RPC_URL) throw new Error('RPC_URL is not set')

const provider = AnchorProvider.local(RPC_URL, {
    commitment: 'processed',
    preflightCommitment: 'processed',
    skipPreflight: true,
})

export const flashClient = new PerpetualsClient(
    provider,
    POOL_CONFIG.programId,
    POOL_CONFIG.perpComposibilityProgramId,
    POOL_CONFIG.fbNftRewardProgramId,
    POOL_CONFIG.rewardDistributionProgram.programId,
    { prioritizationFee: 0 },
)

Get claimable revenue

Read-only quote of how much USDC a wallet can currently claim. No transaction is sent. Defaults to the connected wallet when no argument is passed.

Returns a native BN amount in 6-decimal USDC. Use nativeToUiDecimals(amount, USD_DECIMALS) for a human-readable value.

Claim revenue

Submits the claim and sweeps the wallet's eligible USDC balance to its USDC ATA. Auto-creates the receiving ATA if it doesn't exist.

Common gotchas

  • revenueAmount == 0 — the wallet has no FAF staked, or the stake hasn't accrued any revenue yet. Stake FAF first via depositFafStake (see the FAF token docs).

  • claimRevenue throws on a fresh wallet — usually because no token_stake PDA exists. The pre-flight read prevents this; don't remove it.

  • Wrong pool config? — any mainnet pool resolves to the same tokenVault. Crypto.1 is just the canonical anchor. For devnet, switch to devnet.1 and the devnet cluster URL.

  • USDC ATA missing?createUserATA: true on the collectRevenue call handles this. Set it to false only if you've already created the ATA out-of-band.

Last updated

Was this helpful?