-
Notifications
You must be signed in to change notification settings - Fork 2.1k
fix(fees): include Keep staged creator fees #8939
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,17 +3,12 @@ | |
| // Programs (mainnet): Full Launch ETVtC29T7ExxYyWSkpzKPxzrL3SRyrGPRhZe3FwXmFAo | ||
| // Idea Mode 2ww3589FBTgwbCd9sbpBjosiDszsigoqArh5xuc7F2Ve | ||
| // | ||
| // Where Keep's fees come from (verified from the program source): | ||
| // 1. Success platform fee — PLATFORM_FEE_BPS = 500 (5%) of each successful | ||
| // raise, swept to the platform fee receiver in settle_success.rs. | ||
| // 2. Trading-fee harvest — harvest_fees.rs skims the accrued-fee (√k) fraction | ||
| // of the burned Raydium LP; the platform's share (platform_amount) is | ||
| // transferred to the platform fee receiver's USDC ATA, the project's share | ||
| // (project_amount = fee_split_project_bps) to the project owner's USDC ATA. | ||
| // Emitted as FeesHarvested { harvested_usdc, project_amount, platform_amount }. | ||
| // All output is derived from on-chain USDC receipts. Platform receipts are | ||
| // filtered by the Keep programs and destination USDC token account; project | ||
| // receipts include staged raise-fee transfers and FeesHarvested events. | ||
| // | ||
| // Both PLATFORM slices (success 5% + harvest platform_amount) land in the platform | ||
| // fee-receiver USDC ATA, so daily USDC received there = Keep's protocol revenue. | ||
| // All platform slices (staged raise fees + harvest platform_amount) land in the | ||
| // platform fee-receiver USDC ATA, so daily USDC received there = protocol revenue. | ||
|
|
||
| import { Dependencies, FetchOptions, SimpleAdapter } from "../adapters/types"; | ||
| import { CHAIN } from "../helpers/chains"; | ||
|
|
@@ -34,49 +29,100 @@ const KEEP_PROGRAMS = [ | |
| // Anchor's first eight event bytes, base64-encoded. The complete event payload | ||
| // is decoded below; the prefix is only used to select FeesHarvested log lines. | ||
| const FEES_HARVESTED_PREFIX = "Huy2vk3+TAo"; | ||
| const PROJECT_CREATED_PREFIX = "wAqjHbkfQ6g"; | ||
| const BOOTSTRAPPED_PREFIX = "ONeHjsYunZs"; | ||
| const FINALIZED_D7_PREFIX = "JXozXYf7Ulg"; | ||
| const FINALIZED_D30_PREFIX = "2Vt0QavIXBI"; | ||
| const SUCCESS_EXECUTED_PREFIX = "Trx57IcWNIY"; | ||
|
Comment on lines
+32
to
+36
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win Document the event ABI constants and byte offsets. These discriminators and offsets determine the reported fee balances. Add an inline source for the Keep event layout. State the decoded field for each offset and the integer encoding for As per coding guidelines, “Document every hardcoded rate, address, or magic number with a comment and, where possible, a source link.” Also applies to: 65-66, 78-84, 123-124 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
| const IDEA_FUNDING_RELEASED_PREFIX = "PKK4EmjFDVo"; | ||
|
|
||
| const PROGRAM_DEPLOYMENT = "2026-06-14"; | ||
|
|
||
| /** | ||
| * One Dune call: USDC inflows to the platform ATA (protocol revenue) plus the | ||
| * project-owner share decoded from FeesHarvested events (supply-side). | ||
| * One Dune call: USDC inflows to the platform ATA (protocol revenue) plus | ||
| * project-owner staged raise fees and the share decoded from FeesHarvested | ||
| * events (supply-side). | ||
| * | ||
| * Event layout is Anchor discriminator (8 bytes), launchpad (32), project | ||
| * owner (32), harvested_usdc (u64), project_amount (u64), platform_amount | ||
| * (u64), tokens_burned (u64). Borsh integers are little-endian, hence the | ||
| * byte reversal before Dune's numeric conversion. | ||
| * Idea Mode pays the creator 3% at Bootstrap, another 7% at successful | ||
| * settlement, and releases the final 35% through the creator funding stream. | ||
| * These are ordinary SPL transfers, not FeesHarvested events, so the project | ||
| * owner is resolved from ProjectCreated and stream releases are counted from | ||
| * the IdeaFundingReleased event emitted after each actual transfer. | ||
| * | ||
| * Filter the ATA with to_token_account, not to_owner — to_owner is the | ||
| * platform fee-receiver wallet, not this token account. | ||
| * | ||
| * ProjectCreated has to be read from before the current day, so it is bounded | ||
| * by the program deployment date to keep it from scanning Solana history. | ||
| */ | ||
| const getKeepFees = async (options: FetchOptions) => { | ||
| const programs = KEEP_PROGRAMS.map((program) => `'${program}'`).join(", "); | ||
| const rows = await queryDuneSql(options, ` | ||
| WITH platform AS ( | ||
| SELECT COALESCE(SUM(amount), 0) AS amount | ||
| WITH events AS ( | ||
| SELECT DISTINCT i.tx_id, substr(log_message, 15) AS payload | ||
| FROM solana.instruction_calls i | ||
| CROSS JOIN UNNEST(i.log_messages) AS logs(log_message) | ||
| WHERE i.tx_success = TRUE | ||
| AND i.outer_executing_account IN (${programs}) | ||
| AND TIME_RANGE | ||
| AND starts_with(log_message, 'Program data: ') | ||
| ), | ||
| usdc_transfers AS ( | ||
| SELECT tx_id, amount, to_token_account, to_owner | ||
| FROM tokens_solana.transfers | ||
| WHERE to_token_account = '${PLATFORM_FEE_USDC_ATA}' | ||
| AND token_mint_address = '${USDC}' | ||
| WHERE token_mint_address = '${USDC}' | ||
| AND outer_executing_account IN (${programs}) | ||
| AND TIME_RANGE | ||
| ), | ||
| fee_events AS ( | ||
| staged_fee_txs AS ( | ||
| SELECT DISTINCT | ||
| tx_id, | ||
| to_base58(varbinary_substring(from_base64(payload), 9, 32)) AS launchpad | ||
| FROM events | ||
| WHERE starts_with(payload, '${BOOTSTRAPPED_PREFIX}') | ||
| OR starts_with(payload, '${FINALIZED_D7_PREFIX}') | ||
| OR starts_with(payload, '${FINALIZED_D30_PREFIX}') | ||
| OR starts_with(payload, '${SUCCESS_EXECUTED_PREFIX}') | ||
| ), | ||
| project_owners AS ( | ||
| SELECT DISTINCT | ||
| i.tx_id, | ||
| substr(log_message, 15) AS payload | ||
| to_base58(varbinary_substring(from_base64(substr(log_message, 15)), 17, 32)) AS launchpad, | ||
| to_base58(varbinary_substring(from_base64(substr(log_message, 15)), 81, 32)) AS project_owner | ||
| FROM solana.instruction_calls i | ||
| CROSS JOIN UNNEST(i.log_messages) AS logs(log_message) | ||
| WHERE i.tx_success = TRUE | ||
| AND i.outer_executing_account IN (${programs}) | ||
| AND TIME_RANGE | ||
| AND starts_with(log_message, 'Program data: ${FEES_HARVESTED_PREFIX}') | ||
| ), | ||
| project AS ( | ||
| SELECT COALESCE(SUM( | ||
| varbinary_to_uint256(reverse(varbinary_substring(from_base64(payload), 81, 8))) | ||
| ), 0) AS amount | ||
| FROM fee_events | ||
| AND i.block_time >= TIMESTAMP '${PROGRAM_DEPLOYMENT}' | ||
| AND starts_with(log_message, 'Program data: ${PROJECT_CREATED_PREFIX}') | ||
| ) | ||
| SELECT | ||
| (SELECT amount FROM platform) AS platform_amount, | ||
| (SELECT amount FROM project) AS project_amount | ||
| ( | ||
| SELECT COALESCE(SUM(amount), 0) | ||
| FROM usdc_transfers | ||
| WHERE to_token_account = '${PLATFORM_FEE_USDC_ATA}' | ||
| ) AS platform_amount, | ||
| ( | ||
| SELECT COALESCE(SUM(t.amount), 0) | ||
| FROM usdc_transfers t | ||
| JOIN staged_fee_txs s ON s.tx_id = t.tx_id | ||
| JOIN project_owners p | ||
| ON p.launchpad = s.launchpad | ||
| AND p.project_owner = t.to_owner | ||
| ) | ||
| + ( | ||
| SELECT COALESCE(SUM( | ||
| varbinary_to_uint256(reverse(varbinary_substring(from_base64(payload), 73, 8))) | ||
| ), 0) | ||
| FROM events | ||
| WHERE starts_with(payload, '${IDEA_FUNDING_RELEASED_PREFIX}') | ||
| ) | ||
| + ( | ||
| SELECT COALESCE(SUM( | ||
| varbinary_to_uint256(reverse(varbinary_substring(from_base64(payload), 81, 8))) | ||
| ), 0) | ||
| FROM events | ||
| WHERE starts_with(payload, '${FEES_HARVESTED_PREFIX}') | ||
| ) AS project_amount | ||
| `); | ||
|
|
||
| const dailyRevenue = options.createBalances(); | ||
|
|
@@ -110,21 +156,21 @@ const adapter: SimpleAdapter = { | |
| isExpensiveAdapter: true, | ||
| doublecounted: true, // raydium | ||
| methodology: { | ||
| Fees: "All Keep USDC fees: the platform fee-receiver inflows plus the project-owner share of harvested Raydium trading fees. The refundable raise principal and LP liquidity are excluded.", | ||
| Fees: "All Keep USDC fees: platform fee-receiver inflows plus project-owner staged raise-fee transfers and harvested Raydium trading-fee shares. Refundable raise principal and LP liquidity are excluded.", | ||
| Revenue: "The platform portion of Keep fees, received by the platform fee-receiver USDC account. The project-owner share is reported as Supply Side Revenue.", | ||
| SupplySideRevenue: "The project-owner share of harvested Raydium trading fees, decoded from Keep's on-chain FeesHarvested events.", | ||
| SupplySideRevenue: "Project-owner staged raise-fee transfers plus the project share of harvested Raydium trading fees, counted only after the on-chain transfer/event occurs.", | ||
| ProtocolRevenue: "USDC fees received by Keep's platform fee-receiver account.", | ||
| }, | ||
| breakdownMethodology: { | ||
| Fees: { | ||
| [METRIC.PROTOCOL_FEES]: "Platform fee slices received by Keep's platform USDC ATA.", | ||
| [METRIC.CREATOR_FEES]: "Project-owner share emitted in FeesHarvested events.", | ||
| [METRIC.CREATOR_FEES]: "Project-owner staged raise-fee transfers and share emitted in FeesHarvested events.", | ||
| }, | ||
| Revenue: { | ||
| [METRIC.PROTOCOL_FEES]: "Platform fee slices retained by Keep's platform treasury.", | ||
| }, | ||
| SupplySideRevenue: { | ||
| [METRIC.CREATOR_FEES]: "Project-owner share paid from harvested trading fees.", | ||
| [METRIC.CREATOR_FEES]: "Project-owner staged raise-fee transfers and share paid from harvested trading fees.", | ||
| }, | ||
| ProtocolRevenue: { | ||
| [METRIC.PROTOCOL_FEES]: "Platform fee slices received by Keep's platform treasury.", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Correct the data-source description.
harvested_projectdecodesFeesHarvestedevent data at Lines 121-126. It does not derive that amount from a USDC receipt. Describe transfer-derived amounts and event-derived amounts separately.🤖 Prompt for AI Agents