Fees

Fees

Every pool generates partner fees — a creator-configurable cut of trading fees that accrues to the pool config's partner account. The Pirate API exposes all four fee operations through one unified route: claim from DBC (pre-migration), claim from DAMM v2 (post-migration), withdraw surplus quote tokens left over from migration, and atomically split a single claim across 2–10 recipients in one transaction. A kind discriminator selects the variant.

Lifecycle

Fees lifecycle — DBC vs DAMM v2, split, surplus
  • DBC vs DAMM v2: the SDK under the hood is different (@meteora-ag/dynamic-bonding-curve-sdk vs @meteora-ag/cp-amm-sdk). Use kind: "dbc" until the pool migrates, then switch to kind: "damm_v2".
  • Surplus is a one-shot: it only exists immediately after migration if not all reserves were converted to LP.
  • Split is a convenience wrapper — it builds a single VersionedTransaction that claims fees and disburses them via N SPL transfers in the same instruction set.

Endpoints

MethodPathPurposeScope (signed)
GET/v2/pools/{address}/fee-metricsRead partner balances — partner_quote_fee, partner_base_fee, surplus
POST/v2/pools/{address}/fee-claims with kind: "dbc"Claim partner fees on a still-bonding poolfees:claim
POST/v2/pools/{address}/fee-claims with kind: "damm_v2"Claim partner fees on a migrated poolfees:claim
POST/v2/pools/{address}/fee-claims with kind: "surplus"Withdraw post-migration surplus quote tokensfees:claim
POST/v2/pools/{address}/fee-claims with kind: "split"Atomic claim + N-way disbursementfees:claim

The fee-claim endpoint accepts mode: "unsigned" | "signed". mode=unsigned (default) is always allowed; mode=signed requires the fees:claim scope on your API key and lets the platform Privy wallet sign and broadcast on your behalf. See Transaction Modes for the request/response shape of each mode.

Reading current balances

curl https://api.piratecrew.fun/v2/pools/$POOL_ADDRESS/fee-metrics \
  -H "Authorization: Bearer $PIRATE_API_KEY"
{
  "data": {
    "pool_address": "POOL…",
    "partner_quote_fee": "184523000",
    "partner_base_fee":  "0",
    "surplus":           "0",
    "migrated": false
  },
  "meta": { "request_id": "req_…" }
}

Amounts are decimal strings of raw token units (lamports / token-decimals). Convert with the GOLD or base-token decimals before displaying.

Single-recipient claim (DBC)

curl -X POST https://api.piratecrew.fun/v2/pools/$POOL_ADDRESS/fee-claims \
  -H "Authorization: Bearer $PIRATE_API_KEY" \
  -H "Idempotency-Key: 41e2c9a1-…" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "dbc",
    "payer": "YOUR_WALLET_PUBKEY",
    "mode": "unsigned"
  }'
{
  "data": {
    "mode": "unsigned",
    "transaction": "AQABAo...",
    "pool_address": "POOL…",
    "estimated_quote": "184523000"
  },
  "meta": { "request_id": "req_…" }
}

Sign locally and submit via POST /v2/transactions. After the pool migrates, switch to kind: "damm_v2" — request and response shapes are identical.

Server-signed claim

If the partner account is a Privy-managed wallet, just flip the mode:

curl -X POST https://api.piratecrew.fun/v2/pools/$POOL_ADDRESS/fee-claims \
  -H "Authorization: Bearer $PIRATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "damm_v2",
    "payer": "PLATFORM_WALLET_PUBKEY",
    "mode": "signed"
  }'
{
  "data": { "mode": "signed", "signature": "5kJ2…" },
  "meta": { "request_id": "req_…" }
}

The signature is already confirmed at confirmed commitment when it lands in your response. Without the fees:claim scope on the API key, the request returns 403 forbidden.

Atomic N-way split

kind: "split" takes 2–10 recipients with bps (basis-point) weights that must sum to exactly 10000. The server builds a single VersionedTransaction that:

  1. Claims the partner fee.
  2. Distributes the claim across the recipient ATAs in one go.
curl -X POST https://api.piratecrew.fun/v2/pools/$POOL_ADDRESS/fee-claims \
  -H "Authorization: Bearer $PIRATE_API_KEY" \
  -H "Idempotency-Key: 5f3e2c8a-…" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "split",
    "payer": "YOUR_WALLET_PUBKEY",
    "splits": [
      { "recipient": "CREATOR_PUBKEY", "bps": 5000 },
      { "recipient": "KOL_PUBKEY",     "bps": 3000 },
      { "recipient": "TREASURY_PUBKEY","bps": 2000 }
    ],
    "mode": "unsigned"
  }'
{
  "data": {
    "mode": "unsigned",
    "transaction": "AQABAo...",
    "pool_address": "POOL…",
    "estimated_quote": "184523000",
    "splits": [
      { "recipient": "CREATOR_PUBKEY",  "bps": 5000, "estimated_amount": "92261500" },
      { "recipient": "KOL_PUBKEY",      "bps": 3000, "estimated_amount": "55356900" },
      { "recipient": "TREASURY_PUBKEY", "bps": 2000, "estimated_amount": "36904600" }
    ]
  },
  "meta": { "request_id": "req_…" }
}

Constraints to watch

  • bps sum must equal 10000. The endpoint rejects with 400 bad_request otherwise.
  • Splits length must be 2–10. Single-recipient claims should use kind: "dbc" (or kind: "damm_v2").
  • Recipient ATAs must already exist for the quote mint (GOLD). The transaction does not include create-ATA instructions — it would otherwise blow past compute-unit and account limits. Pre-create them client-side (or via a separate tx) before calling split.
  • Same scope as the single-recipient claim — fees:claim for mode=signed.

Withdrawing surplus

After migration, any quote tokens left in the DBC vault that did not get LP'd are claimable as "surplus" — one shot per pool:

curl -X POST https://api.piratecrew.fun/v2/pools/$POOL_ADDRESS/fee-claims \
  -H "Authorization: Bearer $PIRATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "surplus",
    "payer": "YOUR_WALLET_PUBKEY",
    "mode": "unsigned"
  }'

Returns the same envelope as the claim endpoints. Once executed, surplus reads 0 on GET /v2/pools/{address}/fee-metrics.

Reference