From 4a48f545c1c5115476109b1163d3602d91e3b7ef Mon Sep 17 00:00:00 2001 From: Anton Sauchyk <43762166+smypmsa@users.noreply.github.com> Date: Fri, 27 Feb 2026 23:39:52 +0100 Subject: [PATCH] feat(pumpfun): update IDLs and add bonding_curve_v2 + cashback support (#159) Update all 3 pump.fun IDL files (pump_fun, pump_swap, pump_fees) with new cashback rewards and fee-sharing features. Fix IDL parser to handle tuple struct types (OptionBool). Add bonding_curve_v2 remaining account to all buy/sell instructions as required by the pump.fun program upgrade. Key changes: - Fix IDL parser crash on tuple struct fields (string vs dict) - Add bonding_curve_v2 PDA derivation and append as remaining account - Add is_cashback_coin field to TokenInfo and BondingCurve decoding - Propagate is_cashback_enabled from CreateEvent/create_v2 to TokenInfo - Conditionally include user_volume_accumulator for cashback sell txs Co-authored-by: Claude Opus 4.6 --- idl/pump_fees.json | 1977 +++++++++++++++++- idl/pump_fun_idl.json | 1384 +++++++++++- idl/pump_swap_idl.json | 927 +++++++- src/interfaces/core.py | 1 + src/platforms/pumpfun/address_provider.py | 30 + src/platforms/pumpfun/curve_manager.py | 6 +- src/platforms/pumpfun/event_parser.py | 46 +- src/platforms/pumpfun/instruction_builder.py | 29 +- src/utils/idl_parser.py | 22 +- 9 files changed, 4334 insertions(+), 88 deletions(-) diff --git a/idl/pump_fees.json b/idl/pump_fees.json index e368a22..fc21546 100644 --- a/idl/pump_fees.json +++ b/idl/pump_fees.json @@ -7,6 +7,370 @@ "description": "Created with Anchor" }, "instructions": [ + { + "name": "create_fee_sharing_config", + "docs": [ + "Create Fee Sharing Config" + ], + "discriminator": [ + 195, + 78, + 86, + 76, + 111, + 52, + 251, + 213 + ], + "accounts": [ + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program", + "address": "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ" + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "global", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 103, + 108, + 111, + 98, + 97, + 108 + ] + } + ], + "program": { + "kind": "const", + "value": [ + 1, + 86, + 224, + 246, + 147, + 102, + 90, + 207, + 68, + 219, + 21, + 104, + 191, + 23, + 91, + 170, + 81, + 137, + 203, + 151, + 245, + 210, + 255, + 59, + 101, + 93, + 43, + 182, + 253, + 109, + 24, + 176 + ] + } + } + }, + { + "name": "mint" + }, + { + "name": "sharing_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 115, + 104, + 97, + 114, + 105, + 110, + 103, + 45, + 99, + 111, + 110, + 102, + 105, + 103 + ] + }, + { + "kind": "account", + "path": "mint" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "bonding_curve", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 111, + 110, + 100, + 105, + 110, + 103, + 45, + 99, + 117, + 114, + 118, + 101 + ] + }, + { + "kind": "account", + "path": "mint" + } + ], + "program": { + "kind": "const", + "value": [ + 1, + 86, + 224, + 246, + 147, + 102, + 90, + 207, + 68, + 219, + 21, + 104, + 191, + 23, + 91, + 170, + 81, + 137, + 203, + 151, + 245, + 210, + 255, + 59, + 101, + 93, + 43, + 182, + 253, + 109, + 24, + 176 + ] + } + } + }, + { + "name": "pump_program", + "address": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" + }, + { + "name": "pump_event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ], + "program": { + "kind": "const", + "value": [ + 1, + 86, + 224, + 246, + 147, + 102, + 90, + 207, + 68, + 219, + 21, + 104, + 191, + 23, + 91, + 170, + 81, + 137, + 203, + 151, + 245, + 210, + 255, + 59, + 101, + 93, + 43, + 182, + 253, + 109, + 24, + 176 + ] + } + } + }, + { + "name": "pool", + "writable": true, + "optional": true + }, + { + "name": "pump_amm_program", + "optional": true, + "address": "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA" + }, + { + "name": "pump_amm_event_authority", + "optional": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ], + "program": { + "kind": "const", + "value": [ + 12, + 20, + 222, + 252, + 130, + 94, + 198, + 118, + 148, + 37, + 8, + 24, + 187, + 101, + 64, + 101, + 244, + 41, + 141, + 49, + 86, + 213, + 113, + 180, + 212, + 248, + 9, + 12, + 24, + 233, + 168, + 99 + ] + } + } + } + ], + "args": [] + }, { "name": "get_fees", "docs": [ @@ -164,6 +528,453 @@ ], "args": [] }, + { + "name": "reset_fee_sharing_config", + "docs": [ + "Reset Fee Sharing Config, make sure to distribute all the fees before calling this" + ], + "discriminator": [ + 10, + 2, + 182, + 95, + 16, + 127, + 129, + 186 + ], + "accounts": [ + { + "name": "authority", + "signer": true + }, + { + "name": "global", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 103, + 108, + 111, + 98, + 97, + 108 + ] + } + ], + "program": { + "kind": "const", + "value": [ + 1, + 86, + 224, + 246, + 147, + 102, + 90, + 207, + 68, + 219, + 21, + 104, + 191, + 23, + 91, + 170, + 81, + 137, + 203, + 151, + 245, + 210, + 255, + 59, + 101, + 93, + 43, + 182, + 253, + 109, + 24, + 176 + ] + } + } + }, + { + "name": "new_admin" + }, + { + "name": "mint", + "relations": [ + "sharing_config" + ] + }, + { + "name": "sharing_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 115, + 104, + 97, + 114, + 105, + 110, + 103, + 45, + 99, + 111, + 110, + 102, + 105, + 103 + ] + }, + { + "kind": "account", + "path": "mint" + } + ] + } + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program" + } + ], + "args": [] + }, + { + "name": "revoke_fee_sharing_authority", + "docs": [ + "Revoke Fee Sharing Authority" + ], + "discriminator": [ + 18, + 233, + 158, + 39, + 185, + 207, + 58, + 104 + ], + "accounts": [ + { + "name": "authority", + "signer": true + }, + { + "name": "global", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 103, + 108, + 111, + 98, + 97, + 108 + ] + } + ], + "program": { + "kind": "const", + "value": [ + 1, + 86, + 224, + 246, + 147, + 102, + 90, + 207, + 68, + 219, + 21, + 104, + 191, + 23, + 91, + 170, + 81, + 137, + 203, + 151, + 245, + 210, + 255, + 59, + 101, + 93, + 43, + 182, + 253, + 109, + 24, + 176 + ] + } + } + }, + { + "name": "mint", + "relations": [ + "sharing_config" + ] + }, + { + "name": "sharing_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 115, + 104, + 97, + 114, + 105, + 110, + 103, + 45, + 99, + 111, + 110, + 102, + 105, + 103 + ] + }, + { + "kind": "account", + "path": "mint" + } + ] + } + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program" + } + ], + "args": [] + }, + { + "name": "transfer_fee_sharing_authority", + "docs": [ + "Transfer Fee Sharing Authority" + ], + "discriminator": [ + 202, + 10, + 75, + 200, + 164, + 34, + 210, + 96 + ], + "accounts": [ + { + "name": "authority", + "signer": true + }, + { + "name": "global", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 103, + 108, + 111, + 98, + 97, + 108 + ] + } + ], + "program": { + "kind": "const", + "value": [ + 1, + 86, + 224, + 246, + 147, + 102, + 90, + 207, + 68, + 219, + 21, + 104, + 191, + 23, + 91, + 170, + 81, + 137, + 203, + 151, + 245, + 210, + 255, + 59, + 101, + 93, + 43, + 182, + 253, + 109, + 24, + 176 + ] + } + } + }, + { + "name": "mint", + "relations": [ + "sharing_config" + ] + }, + { + "name": "sharing_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 115, + 104, + 97, + 114, + 105, + 110, + 103, + 45, + 99, + 111, + 110, + 102, + 105, + 103 + ] + }, + { + "kind": "account", + "path": "mint" + } + ] + } + }, + { + "name": "new_admin" + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program" + } + ], + "args": [] + }, { "name": "update_admin", "docs": [ @@ -362,6 +1173,525 @@ } ] }, + { + "name": "update_fee_shares", + "docs": [ + "Update Fee Shares, make sure to distribute all the fees before calling this" + ], + "discriminator": [ + 189, + 13, + 136, + 99, + 187, + 164, + 237, + 35 + ], + "accounts": [ + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program", + "address": "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ" + }, + { + "name": "authority", + "signer": true + }, + { + "name": "global", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 103, + 108, + 111, + 98, + 97, + 108 + ] + } + ], + "program": { + "kind": "const", + "value": [ + 1, + 86, + 224, + 246, + 147, + 102, + 90, + 207, + 68, + 219, + 21, + 104, + 191, + 23, + 91, + 170, + 81, + 137, + 203, + 151, + 245, + 210, + 255, + 59, + 101, + 93, + 43, + 182, + 253, + 109, + 24, + 176 + ] + } + } + }, + { + "name": "mint", + "relations": [ + "sharing_config" + ] + }, + { + "name": "sharing_config", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 115, + 104, + 97, + 114, + 105, + 110, + 103, + 45, + 99, + 111, + 110, + 102, + 105, + 103 + ] + }, + { + "kind": "account", + "path": "mint" + } + ] + } + }, + { + "name": "bonding_curve", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 111, + 110, + 100, + 105, + 110, + 103, + 45, + 99, + 117, + 114, + 118, + 101 + ] + }, + { + "kind": "account", + "path": "mint" + } + ], + "program": { + "kind": "const", + "value": [ + 1, + 86, + 224, + 246, + 147, + 102, + 90, + 207, + 68, + 219, + 21, + 104, + 191, + 23, + 91, + 170, + 81, + 137, + 203, + 151, + 245, + 210, + 255, + 59, + 101, + 93, + 43, + 182, + 253, + 109, + 24, + 176 + ] + } + } + }, + { + "name": "pump_creator_vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 99, + 114, + 101, + 97, + 116, + 111, + 114, + 45, + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "sharing_config" + } + ], + "program": { + "kind": "const", + "value": [ + 1, + 86, + 224, + 246, + 147, + 102, + 90, + 207, + 68, + 219, + 21, + 104, + 191, + 23, + 91, + 170, + 81, + 137, + 203, + 151, + 245, + 210, + 255, + 59, + 101, + 93, + 43, + 182, + 253, + 109, + 24, + 176 + ] + } + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "pump_program", + "address": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" + }, + { + "name": "pump_event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ], + "program": { + "kind": "const", + "value": [ + 1, + 86, + 224, + 246, + 147, + 102, + 90, + 207, + 68, + 219, + 21, + 104, + 191, + 23, + 91, + 170, + 81, + 137, + 203, + 151, + 245, + 210, + 255, + 59, + 101, + 93, + 43, + 182, + 253, + 109, + 24, + 176 + ] + } + } + }, + { + "name": "pump_amm_program", + "address": "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA" + }, + { + "name": "amm_event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ], + "program": { + "kind": "const", + "value": [ + 12, + 20, + 222, + 252, + 130, + 94, + 198, + 118, + 148, + 37, + 8, + 24, + 187, + 101, + 64, + 101, + 244, + 41, + 141, + 49, + 86, + 213, + 113, + 180, + 212, + 248, + 9, + 12, + 24, + 233, + 168, + 99 + ] + } + } + }, + { + "name": "wsol_mint", + "address": "So11111111111111111111111111111111111111112" + }, + { + "name": "token_program", + "address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + }, + { + "name": "coin_creator_vault_authority", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 99, + 114, + 101, + 97, + 116, + 111, + 114, + 95, + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "sharing_config" + } + ], + "program": { + "kind": "const", + "value": [ + 12, + 20, + 222, + 252, + 130, + 94, + 198, + 118, + 148, + 37, + 8, + 24, + 187, + 101, + 64, + 101, + 244, + 41, + 141, + 49, + 86, + 213, + 113, + 180, + 212, + 248, + 9, + 12, + 24, + 233, + 168, + 99 + ] + } + } + }, + { + "name": "coin_creator_vault_ata", + "writable": true + } + ], + "args": [ + { + "name": "shareholders", + "type": { + "vec": { + "defined": { + "name": "Shareholder" + } + } + } + } + ] + }, { "name": "upsert_fee_tiers", "docs": [ @@ -467,6 +1797,19 @@ } ], "accounts": [ + { + "name": "BondingCurve", + "discriminator": [ + 23, + 183, + 248, + 55, + 96, + 216, + 172, + 96 + ] + }, { "name": "FeeConfig", "discriminator": [ @@ -479,9 +1822,61 @@ 76, 155 ] + }, + { + "name": "Global", + "discriminator": [ + 167, + 232, + 232, + 177, + 200, + 108, + 114, + 127 + ] + }, + { + "name": "Pool", + "discriminator": [ + 241, + 154, + 109, + 4, + 17, + 177, + 109, + 188 + ] + }, + { + "name": "SharingConfig", + "discriminator": [ + 216, + 74, + 9, + 0, + 56, + 140, + 93, + 75 + ] } ], "events": [ + { + "name": "CreateFeeSharingConfigEvent", + "discriminator": [ + 133, + 105, + 170, + 200, + 184, + 116, + 251, + 88 + ] + }, { "name": "InitializeFeeConfigEvent", "discriminator": [ @@ -495,6 +1890,45 @@ 126 ] }, + { + "name": "ResetFeeSharingConfigEvent", + "discriminator": [ + 203, + 204, + 151, + 226, + 120, + 55, + 214, + 243 + ] + }, + { + "name": "RevokeFeeSharingAuthorityEvent", + "discriminator": [ + 114, + 23, + 101, + 60, + 14, + 190, + 153, + 62 + ] + }, + { + "name": "TransferFeeSharingAuthorityEvent", + "discriminator": [ + 124, + 143, + 198, + 245, + 77, + 184, + 8, + 236 + ] + }, { "name": "UpdateAdminEvent", "discriminator": [ @@ -521,6 +1955,19 @@ 208 ] }, + { + "name": "UpdateFeeSharesEvent", + "discriminator": [ + 21, + 186, + 196, + 184, + 91, + 228, + 225, + 203 + ] + }, { "name": "UpsertFeeTiersEvent", "discriminator": [ @@ -573,16 +2020,182 @@ }, { "code": 6007, - "name": "ZeroMarketCap", - "msg": "Market cap must be greater than 0" + "name": "InvalidSharingConfig", + "msg": "Invalid Sharing Config" }, { "code": 6008, - "name": "ZeroTradeSize", - "msg": "Trade size must be greater than 0" + "name": "InvalidPool", + "msg": "Invalid Pool" + }, + { + "code": 6009, + "name": "SharingConfigAdminRevoked", + "msg": "Sharing config admin has been revoked" + }, + { + "code": 6010, + "name": "NoShareholders", + "msg": "No shareholders provided" + }, + { + "code": 6011, + "name": "TooManyShareholders", + "msg": "format" + }, + { + "code": 6012, + "name": "DuplicateShareholder", + "msg": "Duplicate shareholder address" + }, + { + "code": 6013, + "name": "NotEnoughRemainingAccounts", + "msg": "Not enough remaining accounts" + }, + { + "code": 6014, + "name": "InvalidShareTotal", + "msg": "Invalid share total - must equal 10_000 basis points" + }, + { + "code": 6015, + "name": "ShareCalculationOverflow", + "msg": "Share calculation overflow" + }, + { + "code": 6016, + "name": "NotAuthorized", + "msg": "The given account is not authorized to execute this instruction." + }, + { + "code": 6017, + "name": "ZeroShareNotAllowed", + "msg": "Shareholder cannot have zero share" + }, + { + "code": 6018, + "name": "SharingConfigNotActive", + "msg": "Fee sharing config is not active" + }, + { + "code": 6019, + "name": "AmmAccountsRequiredForGraduatedCoin", + "msg": "AMM accounts are required for graduated coins" + }, + { + "code": 6020, + "name": "ShareholderAccountMismatch", + "msg": "Remaining account key doesn't match shareholder address" } ], "types": [ + { + "name": "BondingCurve", + "type": { + "kind": "struct", + "fields": [ + { + "name": "virtual_token_reserves", + "type": "u64" + }, + { + "name": "virtual_sol_reserves", + "type": "u64" + }, + { + "name": "real_token_reserves", + "type": "u64" + }, + { + "name": "real_sol_reserves", + "type": "u64" + }, + { + "name": "token_total_supply", + "type": "u64" + }, + { + "name": "complete", + "type": "bool" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "is_mayhem_mode", + "type": "bool" + } + ] + } + }, + { + "name": "ConfigStatus", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Paused" + }, + { + "name": "Active" + } + ] + } + }, + { + "name": "CreateFeeSharingConfigEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "timestamp", + "type": "i64" + }, + { + "name": "mint", + "type": "pubkey" + }, + { + "name": "bonding_curve", + "type": "pubkey" + }, + { + "name": "pool", + "type": { + "option": "pubkey" + } + }, + { + "name": "sharing_config", + "type": "pubkey" + }, + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "initial_shareholders", + "type": { + "vec": { + "defined": { + "name": "Shareholder" + } + } + } + }, + { + "name": "status", + "type": { + "defined": { + "name": "ConfigStatus" + } + } + } + ] + } + }, { "name": "FeeConfig", "type": { @@ -669,6 +2282,104 @@ ] } }, + { + "name": "Global", + "type": { + "kind": "struct", + "fields": [ + { + "name": "initialized", + "type": "bool" + }, + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "fee_recipient", + "type": "pubkey" + }, + { + "name": "initial_virtual_token_reserves", + "type": "u64" + }, + { + "name": "initial_virtual_sol_reserves", + "type": "u64" + }, + { + "name": "initial_real_token_reserves", + "type": "u64" + }, + { + "name": "token_total_supply", + "type": "u64" + }, + { + "name": "fee_basis_points", + "type": "u64" + }, + { + "name": "withdraw_authority", + "type": "pubkey" + }, + { + "name": "enable_migrate", + "type": "bool" + }, + { + "name": "pool_migration_fee", + "type": "u64" + }, + { + "name": "creator_fee_basis_points", + "type": "u64" + }, + { + "name": "fee_recipients", + "type": { + "array": [ + "pubkey", + 7 + ] + } + }, + { + "name": "set_creator_authority", + "type": "pubkey" + }, + { + "name": "admin_set_creator_authority", + "type": "pubkey" + }, + { + "name": "create_v2_enabled", + "type": "bool" + }, + { + "name": "whitelist_pda", + "type": "pubkey" + }, + { + "name": "reserved_fee_recipient", + "type": "pubkey" + }, + { + "name": "mayhem_mode_enabled", + "type": "bool" + }, + { + "name": "reserved_fee_recipients", + "type": { + "array": [ + "pubkey", + 7 + ] + } + } + ] + } + }, { "name": "InitializeFeeConfigEvent", "type": { @@ -689,6 +2400,220 @@ ] } }, + { + "name": "Pool", + "type": { + "kind": "struct", + "fields": [ + { + "name": "pool_bump", + "type": "u8" + }, + { + "name": "index", + "type": "u16" + }, + { + "name": "creator", + "type": "pubkey" + }, + { + "name": "base_mint", + "type": "pubkey" + }, + { + "name": "quote_mint", + "type": "pubkey" + }, + { + "name": "lp_mint", + "type": "pubkey" + }, + { + "name": "pool_base_token_account", + "type": "pubkey" + }, + { + "name": "pool_quote_token_account", + "type": "pubkey" + }, + { + "name": "lp_supply", + "type": "u64" + }, + { + "name": "coin_creator", + "type": "pubkey" + }, + { + "name": "is_mayhem_mode", + "type": "bool" + } + ] + } + }, + { + "name": "ResetFeeSharingConfigEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "timestamp", + "type": "i64" + }, + { + "name": "mint", + "type": "pubkey" + }, + { + "name": "sharing_config", + "type": "pubkey" + }, + { + "name": "old_admin", + "type": "pubkey" + }, + { + "name": "old_shareholders", + "type": { + "vec": { + "defined": { + "name": "Shareholder" + } + } + } + }, + { + "name": "new_admin", + "type": "pubkey" + }, + { + "name": "new_shareholders", + "type": { + "vec": { + "defined": { + "name": "Shareholder" + } + } + } + } + ] + } + }, + { + "name": "RevokeFeeSharingAuthorityEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "timestamp", + "type": "i64" + }, + { + "name": "mint", + "type": "pubkey" + }, + { + "name": "sharing_config", + "type": "pubkey" + }, + { + "name": "admin", + "type": "pubkey" + } + ] + } + }, + { + "name": "Shareholder", + "type": { + "kind": "struct", + "fields": [ + { + "name": "address", + "type": "pubkey" + }, + { + "name": "share_bps", + "type": "u16" + } + ] + } + }, + { + "name": "SharingConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "bump", + "type": "u8" + }, + { + "name": "version", + "type": "u8" + }, + { + "name": "status", + "type": { + "defined": { + "name": "ConfigStatus" + } + } + }, + { + "name": "mint", + "type": "pubkey" + }, + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "admin_revoked", + "type": "bool" + }, + { + "name": "shareholders", + "type": { + "vec": { + "defined": { + "name": "Shareholder" + } + } + } + } + ] + } + }, + { + "name": "TransferFeeSharingAuthorityEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "timestamp", + "type": "i64" + }, + { + "name": "mint", + "type": "pubkey" + }, + { + "name": "sharing_config", + "type": "pubkey" + }, + { + "name": "old_admin", + "type": "pubkey" + }, + { + "name": "new_admin", + "type": "pubkey" + } + ] + } + }, { "name": "UpdateAdminEvent", "type": { @@ -747,6 +2672,40 @@ ] } }, + { + "name": "UpdateFeeSharesEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "timestamp", + "type": "i64" + }, + { + "name": "mint", + "type": "pubkey" + }, + { + "name": "sharing_config", + "type": "pubkey" + }, + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "new_shareholders", + "type": { + "vec": { + "defined": { + "name": "Shareholder" + } + } + } + } + ] + } + }, { "name": "UpsertFeeTiersEvent", "type": { @@ -787,6 +2746,16 @@ "name": "FEE_CONFIG_SEED", "type": "bytes", "value": "[102, 101, 101, 95, 99, 111, 110, 102, 105, 103]" + }, + { + "name": "SHARING_CONFIG_SEED", + "type": { + "array": [ + "u8", + 14 + ] + }, + "value": "[115, 104, 97, 114, 105, 110, 103, 45, 99, 111, 110, 102, 105, 103]" } ] } \ No newline at end of file diff --git a/idl/pump_fun_idl.json b/idl/pump_fun_idl.json index 054c19a..7c7f836 100644 --- a/idl/pump_fun_idl.json +++ b/idl/pump_fun_idl.json @@ -792,15 +792,30 @@ { "name": "buy_exact_sol_in", "docs": [ - "Given a budget of spendable SOL, buy at least min_tokens_out", - "Account creation and fees will be deducted from the spendable SOL", + "Given a budget of spendable SOL, buy at least min_tokens_out tokens.", + "Fees are deducted from spendable_sol_in.", "", - "f(sol) = tokens, where tokens >= min_tokens_out and sol > rent + fees", + "# Quote formulas", + "Where:", + "- total_fee_bps = protocol_fee_bps + creator_fee_bps (creator_fee_bps is 0 if no creator)", + "- floor(a/b) = a / b (integer division)", + "- ceil(a/b) = (a + b - 1) / b", "", - "max_slippage = min_tokens_out = 1", + "SOL → tokens quote", + "To calculate tokens_out for a given spendable_sol_in:", + "1. net_sol = floor(spendable_sol_in * 10_000 / (10_000 + total_fee_bps))", + "2. fees = ceil(net_sol * protocol_fee_bps / 10_000) + ceil(net_sol * creator_fee_bps / 10_000) (creator_fee_bps is 0 if no creator)", + "3. if net_sol + fees > spendable_sol_in: net_sol = net_sol - (net_sol + fees - spendable_sol_in)", + "4. tokens_out = floor((net_sol - 1) * virtual_token_reserves / (virtual_sol_reserves + net_sol - 1))", "", - "Make sure the sol budget is enough to cover creation of the following accounts (unless already created):", - "- creator_vault: rent.minimum_balance(SystemAccount::LEN)", + "Reverse quote (tokens → SOL)", + "To calculate spendable_sol_in for a desired number of tokens:", + "1. net_sol = ceil(tokens * virtual_sol_reserves / (virtual_token_reserves - tokens)) + 1", + "2. spendable_sol_in = ceil(net_sol * (10_000 + total_fee_bps) / 10_000)", + "", + "Rent", + "Separately make sure the instruction's payer has enough SOL to cover rent for:", + "- creator_vault: rent.minimum_balance(0)", "- user_volume_accumulator: rent.minimum_balance(UserVolumeAccumulator::LEN)" ], "discriminator": [ @@ -1170,6 +1185,103 @@ } ] }, + { + "name": "claim_cashback", + "discriminator": [ + 37, + 58, + 35, + 126, + 190, + 53, + 228, + 197 + ], + "accounts": [ + { + "name": "user", + "writable": true + }, + { + "name": "user_volume_accumulator", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 117, + 115, + 101, + 114, + 95, + 118, + 111, + 108, + 117, + 109, + 101, + 95, + 97, + 99, + 99, + 117, + 109, + 117, + 108, + 97, + 116, + 111, + 114 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program", + "address": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" + } + ], + "args": [] + }, { "name": "claim_token_incentives", "discriminator": [ @@ -2308,60 +2420,7 @@ }, { "name": "mayhem_token_vault", - "writable": true, - "pda": { - "seeds": [ - { - "kind": "account", - "path": "sol_vault" - }, - { - "kind": "account", - "path": "token_program" - }, - { - "kind": "account", - "path": "mint" - } - ], - "program": { - "kind": "const", - "value": [ - 140, - 151, - 37, - 143, - 78, - 36, - 137, - 241, - 187, - 61, - 16, - 41, - 20, - 142, - 13, - 131, - 11, - 90, - 19, - 153, - 218, - 255, - 16, - 132, - 4, - 142, - 123, - 216, - 219, - 233, - 248, - 89 - ] - } - } + "writable": true }, { "name": "event_authority", @@ -2416,9 +2475,213 @@ { "name": "is_mayhem_mode", "type": "bool" + }, + { + "name": "is_cashback_enabled", + "type": { + "defined": { + "name": "OptionBool" + } + } } ] }, + { + "name": "distribute_creator_fees", + "docs": [ + "Distributes creator fees to shareholders based on their share percentages", + "The creator vault needs to have at least the minimum distributable amount to distribute fees", + "This can be checked with the get_minimum_distributable_fee instruction" + ], + "discriminator": [ + 165, + 114, + 103, + 0, + 121, + 206, + 247, + 81 + ], + "accounts": [ + { + "name": "mint", + "relations": [ + "sharing_config" + ] + }, + { + "name": "bonding_curve", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 111, + 110, + 100, + 105, + 110, + 103, + 45, + 99, + 117, + 114, + 118, + 101 + ] + }, + { + "kind": "account", + "path": "mint" + } + ] + } + }, + { + "name": "sharing_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 115, + 104, + 97, + 114, + 105, + 110, + 103, + 45, + 99, + 111, + 110, + 102, + 105, + 103 + ] + }, + { + "kind": "account", + "path": "mint" + } + ], + "program": { + "kind": "const", + "value": [ + 12, + 53, + 255, + 169, + 5, + 90, + 142, + 86, + 141, + 168, + 247, + 188, + 7, + 86, + 21, + 39, + 76, + 241, + 201, + 44, + 164, + 31, + 64, + 0, + 156, + 81, + 106, + 164, + 20, + 194, + 124, + 112 + ] + } + } + }, + { + "name": "creator_vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 99, + 114, + 101, + 97, + 116, + 111, + 114, + 45, + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "bonding_curve.creator", + "account": "BondingCurve" + } + ] + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program", + "address": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P" + } + ], + "args": [], + "returns": { + "defined": { + "name": "DistributeCreatorFeesEvent" + } + } + }, { "name": "extend_account", "docs": [ @@ -2482,6 +2745,163 @@ ], "args": [] }, + { + "name": "get_minimum_distributable_fee", + "docs": [ + "Permissionless instruction to check the minimum required fees for distribution", + "Returns the minimum required balance from the creator_vault and whether distribution can proceed" + ], + "discriminator": [ + 117, + 225, + 127, + 202, + 134, + 95, + 68, + 35 + ], + "accounts": [ + { + "name": "mint", + "relations": [ + "sharing_config" + ] + }, + { + "name": "bonding_curve", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 111, + 110, + 100, + 105, + 110, + 103, + 45, + 99, + 117, + 114, + 118, + 101 + ] + }, + { + "kind": "account", + "path": "mint" + } + ] + } + }, + { + "name": "sharing_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 115, + 104, + 97, + 114, + 105, + 110, + 103, + 45, + 99, + 111, + 110, + 102, + 105, + 103 + ] + }, + { + "kind": "account", + "path": "mint" + } + ], + "program": { + "kind": "const", + "value": [ + 12, + 53, + 255, + 169, + 5, + 90, + 142, + 86, + 141, + 168, + 247, + 188, + 7, + 86, + 21, + 39, + 76, + 241, + 201, + 44, + 164, + 31, + 64, + 0, + 156, + 81, + 106, + 164, + 20, + 194, + 124, + 112 + ] + } + } + }, + { + "name": "creator_vault", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 99, + 114, + 101, + 97, + 116, + 111, + 114, + 45, + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "bonding_curve.creator", + "account": "BondingCurve" + } + ] + } + } + ], + "args": [], + "returns": { + "defined": { + "name": "MinimumDistributableFeeEvent" + } + } + }, { "name": "init_user_volume_accumulator", "discriminator": [ @@ -3109,10 +3529,164 @@ ], "args": [] }, + { + "name": "migrate_bonding_curve_creator", + "discriminator": [ + 87, + 124, + 52, + 191, + 52, + 38, + 214, + 232 + ], + "accounts": [ + { + "name": "mint", + "relations": [ + "sharing_config" + ] + }, + { + "name": "bonding_curve", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 111, + 110, + 100, + 105, + 110, + 103, + 45, + 99, + 117, + 114, + 118, + 101 + ] + }, + { + "kind": "account", + "path": "mint" + } + ] + } + }, + { + "name": "sharing_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 115, + 104, + 97, + 114, + 105, + 110, + 103, + 45, + 99, + 111, + 110, + 102, + 105, + 103 + ] + }, + { + "kind": "account", + "path": "mint" + } + ], + "program": { + "kind": "const", + "value": [ + 12, + 53, + 255, + 169, + 5, + 90, + 142, + 86, + 141, + 168, + 247, + 188, + 7, + 86, + 21, + 39, + 76, + 241, + 201, + 44, + 164, + 31, + 64, + 0, + 156, + 81, + 106, + 164, + 20, + 194, + 124, + 112 + ] + } + } + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program" + } + ], + "args": [] + }, { "name": "sell", "docs": [ - "Sells tokens into a bonding curve." + "Sells tokens into a bonding curve.", + "For cashback coins, optionally pass user_volume_accumulator as remaining_accounts[0].", + "If provided and valid, creator_fee goes to user_volume_accumulator.", + "Otherwise, falls back to transferring creator_fee to creator_vault." ], "discriminator": [ 51, @@ -3608,6 +4182,226 @@ } ] }, + { + "name": "set_mayhem_virtual_params", + "discriminator": [ + 61, + 169, + 188, + 191, + 153, + 149, + 42, + 97 + ], + "accounts": [ + { + "name": "sol_vault_authority", + "writable": true, + "signer": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 115, + 111, + 108, + 45, + 118, + 97, + 117, + 108, + 116 + ] + } + ], + "program": { + "kind": "const", + "value": [ + 5, + 42, + 229, + 215, + 167, + 218, + 167, + 36, + 166, + 234, + 176, + 167, + 41, + 84, + 145, + 133, + 90, + 212, + 160, + 103, + 22, + 96, + 103, + 76, + 78, + 3, + 69, + 89, + 128, + 61, + 101, + 163 + ] + } + } + }, + { + "name": "mayhem_token_vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "sol_vault_authority" + }, + { + "kind": "account", + "path": "token_program" + }, + { + "kind": "account", + "path": "mint" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "mint" + }, + { + "name": "global", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 103, + 108, + 111, + 98, + 97, + 108 + ] + } + ] + } + }, + { + "name": "bonding_curve", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 98, + 111, + 110, + 100, + 105, + 110, + 103, + 45, + 99, + 117, + 114, + 118, + 101 + ] + }, + { + "kind": "account", + "path": "mint" + } + ] + } + }, + { + "name": "token_program", + "address": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program" + } + ], + "args": [] + }, { "name": "set_metaplex_creator", "docs": [ @@ -4120,6 +4914,86 @@ ], "args": [] }, + { + "name": "toggle_cashback_enabled", + "discriminator": [ + 115, + 103, + 224, + 255, + 189, + 89, + 86, + 195 + ], + "accounts": [ + { + "name": "global", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 103, + 108, + 111, + 98, + 97, + 108 + ] + } + ] + } + }, + { + "name": "authority", + "writable": true, + "signer": true, + "relations": [ + "global" + ] + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program" + } + ], + "args": [ + { + "name": "enabled", + "type": "bool" + } + ] + }, { "name": "toggle_create_v2", "discriminator": [ @@ -4411,6 +5285,19 @@ 255 ] }, + { + "name": "SharingConfig", + "discriminator": [ + 216, + 74, + 9, + 0, + 56, + 140, + 93, + 75 + ] + }, { "name": "UserVolumeAccumulator", "discriminator": [ @@ -4465,6 +5352,19 @@ 222 ] }, + { + "name": "ClaimCashbackEvent", + "discriminator": [ + 226, + 214, + 246, + 33, + 7, + 242, + 147, + 229 + ] + }, { "name": "ClaimTokenIncentivesEvent", "discriminator": [ @@ -4543,6 +5443,19 @@ 118 ] }, + { + "name": "DistributeCreatorFeesEvent", + "discriminator": [ + 165, + 55, + 129, + 112, + 4, + 179, + 202, + 40 + ] + }, { "name": "ExtendAccountEvent", "discriminator": [ @@ -4569,6 +5482,32 @@ 216 ] }, + { + "name": "MigrateBondingCurveCreatorEvent", + "discriminator": [ + 155, + 167, + 104, + 220, + 213, + 108, + 243, + 3 + ] + }, + { + "name": "MinimumDistributableFeeEvent", + "discriminator": [ + 168, + 216, + 132, + 239, + 235, + 182, + 49, + 52 + ] + }, { "name": "ReservedFeeRecipientsEvent", "discriminator": [ @@ -4659,6 +5598,19 @@ 207, 247 ] + }, + { + "name": "UpdateMayhemVirtualParamsEvent", + "discriminator": [ + 117, + 123, + 228, + 182, + 161, + 168, + 220, + 214 + ] } ], "errors": [ @@ -4891,6 +5843,46 @@ { "code": 6048, "name": "MayhemModeDisabled" + }, + { + "code": 6049, + "name": "CreatorMigratedToSharingConfig", + "msg": "creator has been migrated to sharing config, use pump_fees::reset_fee_sharing_config instead" + }, + { + "code": 6050, + "name": "UnableToDistributeCreatorVaultMigratedToSharingConfig", + "msg": "creator_vault has been migrated to sharing config, use pump:distribute_creator_fees instead" + }, + { + "code": 6051, + "name": "SharingConfigNotActive", + "msg": "Sharing config is not active" + }, + { + "code": 6052, + "name": "UnableToDistributeCreatorFeesToExecutableRecipient", + "msg": "The recipient account is executable, so it cannot receive lamports, remove it from the team first" + }, + { + "code": 6053, + "name": "BondingCurveAndSharingConfigCreatorMismatch", + "msg": "Bonding curve creator does not match sharing config" + }, + { + "code": 6054, + "name": "ShareholdersAndRemainingAccountsMismatch", + "msg": "Remaining accounts do not match shareholders, make sure to pass exactly the same pubkeys in the same order" + }, + { + "code": 6055, + "name": "InvalidShareBps", + "msg": "Share bps must be greater than 0" + }, + { + "code": 6056, + "name": "CashbackNotEnabled", + "msg": "Cashback is not enabled" } ], "types": [ @@ -5010,6 +6002,38 @@ { "name": "is_mayhem_mode", "type": "bool" + }, + { + "name": "is_cashback_coin", + "type": "bool" + } + ] + } + }, + { + "name": "ClaimCashbackEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "user", + "type": "pubkey" + }, + { + "name": "amount", + "type": "u64" + }, + { + "name": "timestamp", + "type": "i64" + }, + { + "name": "total_claimed", + "type": "u64" + }, + { + "name": "total_cashback_earned", + "type": "u64" } ] } @@ -5162,6 +6186,20 @@ ] } }, + { + "name": "ConfigStatus", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Paused" + }, + { + "name": "Active" + } + ] + } + }, { "name": "CreateEvent", "type": { @@ -5222,6 +6260,52 @@ { "name": "is_mayhem_mode", "type": "bool" + }, + { + "name": "is_cashback_enabled", + "type": "bool" + } + ] + } + }, + { + "name": "DistributeCreatorFeesEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "timestamp", + "type": "i64" + }, + { + "name": "mint", + "type": "pubkey" + }, + { + "name": "bonding_curve", + "type": "pubkey" + }, + { + "name": "sharing_config", + "type": "pubkey" + }, + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "shareholders", + "type": { + "vec": { + "defined": { + "name": "Shareholder" + } + } + } + }, + { + "name": "distributed", + "type": "u64" } ] } @@ -5428,6 +6512,10 @@ 7 ] } + }, + { + "name": "is_cashback_enabled", + "type": "bool" } ] } @@ -5494,6 +6582,58 @@ ] } }, + { + "name": "MigrateBondingCurveCreatorEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "timestamp", + "type": "i64" + }, + { + "name": "mint", + "type": "pubkey" + }, + { + "name": "bonding_curve", + "type": "pubkey" + }, + { + "name": "sharing_config", + "type": "pubkey" + }, + { + "name": "old_creator", + "type": "pubkey" + }, + { + "name": "new_creator", + "type": "pubkey" + } + ] + } + }, + { + "name": "MinimumDistributableFeeEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "minimum_required", + "type": "u64" + }, + { + "name": "distributable_fees", + "type": "u64" + }, + { + "name": "can_distribute", + "type": "bool" + } + ] + } + }, { "name": "OptionBool", "type": { @@ -5649,6 +6789,68 @@ ] } }, + { + "name": "Shareholder", + "type": { + "kind": "struct", + "fields": [ + { + "name": "address", + "type": "pubkey" + }, + { + "name": "share_bps", + "type": "u16" + } + ] + } + }, + { + "name": "SharingConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "bump", + "type": "u8" + }, + { + "name": "version", + "type": "u8" + }, + { + "name": "status", + "type": { + "defined": { + "name": "ConfigStatus" + } + } + }, + { + "name": "mint", + "type": "pubkey" + }, + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "admin_revoked", + "type": "bool" + }, + { + "name": "shareholders", + "type": { + "vec": { + "defined": { + "name": "Shareholder" + } + } + } + } + ] + } + }, { "name": "SyncUserVolumeAccumulatorEvent", "type": { @@ -5768,6 +6970,18 @@ { "name": "ix_name", "type": "string" + }, + { + "name": "mayhem_mode", + "type": "bool" + }, + { + "name": "cashback_fee_basis_points", + "type": "u64" + }, + { + "name": "cashback", + "type": "u64" } ] } @@ -5796,6 +7010,46 @@ ] } }, + { + "name": "UpdateMayhemVirtualParamsEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "timestamp", + "type": "i64" + }, + { + "name": "mint", + "type": "pubkey" + }, + { + "name": "virtual_token_reserves", + "type": "u64" + }, + { + "name": "virtual_sol_reserves", + "type": "u64" + }, + { + "name": "new_virtual_token_reserves", + "type": "u64" + }, + { + "name": "new_virtual_sol_reserves", + "type": "u64" + }, + { + "name": "real_token_reserves", + "type": "u64" + }, + { + "name": "real_sol_reserves", + "type": "u64" + } + ] + } + }, { "name": "UserVolumeAccumulator", "type": { @@ -5828,6 +7082,14 @@ { "name": "has_total_claimed_tokens", "type": "bool" + }, + { + "name": "cashback_earned", + "type": "u64" + }, + { + "name": "total_cashback_claimed", + "type": "u64" } ] } diff --git a/idl/pump_swap_idl.json b/idl/pump_swap_idl.json index b10031f..47d7b95 100644 --- a/idl/pump_swap_idl.json +++ b/idl/pump_swap_idl.json @@ -290,6 +290,10 @@ }, { "name": "buy", + "docs": [ + "For cashback coins, optionally pass user_volume_accumulator_wsol_ata as remaining_accounts[0].", + "If provided and valid, the ATA will be initialized if needed." + ], "discriminator": [ 102, 6, @@ -716,7 +720,10 @@ "Make sure the payer has enough SOL to cover creation of the following accounts (unless already created):", "- protocol_fee_recipient_token_account: rent.minimum_balance(TokenAccount::LEN)", "- coin_creator_vault_ata: rent.minimum_balance(TokenAccount::LEN)", - "- user_volume_accumulator: rent.minimum_balance(UserVolumeAccumulator::LEN)" + "- user_volume_accumulator: rent.minimum_balance(UserVolumeAccumulator::LEN)", + "", + "For cashback coins, optionally pass user_volume_accumulator_wsol_ata as remaining_accounts[0].", + "If provided and valid, the ATA will be initialized if needed." ], "discriminator": [ 198, @@ -1133,6 +1140,223 @@ } ] }, + { + "name": "claim_cashback", + "discriminator": [ + 37, + 58, + 35, + 126, + 190, + 53, + 228, + 197 + ], + "accounts": [ + { + "name": "user", + "writable": true + }, + { + "name": "user_volume_accumulator", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 117, + 115, + 101, + 114, + 95, + 118, + 111, + 108, + 117, + 109, + 101, + 95, + 97, + 99, + 99, + 117, + 109, + 117, + 108, + 97, + 116, + 111, + 114 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "quote_mint" + }, + { + "name": "quote_token_program" + }, + { + "name": "user_volume_accumulator_wsol_token_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "user_volume_accumulator" + }, + { + "kind": "account", + "path": "quote_token_program" + }, + { + "kind": "account", + "path": "quote_mint" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "user_wsol_token_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "user" + }, + { + "kind": "account", + "path": "quote_token_program" + }, + { + "kind": "account", + "path": "quote_mint" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program", + "address": "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA" + } + ], + "args": [] + }, { "name": "claim_token_incentives", "discriminator": [ @@ -2087,6 +2311,14 @@ { "name": "is_mayhem_mode", "type": "bool" + }, + { + "name": "is_cashback_coin", + "type": { + "defined": { + "name": "OptionBool" + } + } } ] }, @@ -2455,6 +2687,162 @@ ], "args": [] }, + { + "name": "migrate_pool_coin_creator", + "docs": [ + "Migrate Pool Coin Creator to Sharing Config" + ], + "discriminator": [ + 208, + 8, + 159, + 4, + 74, + 175, + 16, + 58 + ], + "accounts": [ + { + "name": "pool", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 112, + 111, + 111, + 108 + ] + }, + { + "kind": "account", + "path": "pool.index", + "account": "Pool" + }, + { + "kind": "account", + "path": "pool.creator", + "account": "Pool" + }, + { + "kind": "account", + "path": "pool.base_mint", + "account": "Pool" + }, + { + "kind": "account", + "path": "pool.quote_mint", + "account": "Pool" + } + ] + } + }, + { + "name": "sharing_config", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 115, + 104, + 97, + 114, + 105, + 110, + 103, + 45, + 99, + 111, + 110, + 102, + 105, + 103 + ] + }, + { + "kind": "account", + "path": "pool.base_mint", + "account": "Pool" + } + ], + "program": { + "kind": "const", + "value": [ + 12, + 53, + 255, + 169, + 5, + 90, + 142, + 86, + 141, + 168, + 247, + 188, + 7, + 86, + 21, + 39, + 76, + 241, + 201, + 44, + 164, + 31, + 64, + 0, + 156, + 81, + 106, + 164, + 20, + 194, + 124, + 112 + ] + } + } + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program" + } + ], + "args": [] + }, { "name": "sell", "discriminator": [ @@ -3222,6 +3610,70 @@ ], "args": [] }, + { + "name": "toggle_cashback_enabled", + "discriminator": [ + 115, + 103, + 224, + 255, + 189, + 89, + 86, + 195 + ], + "accounts": [ + { + "name": "admin", + "signer": true, + "relations": [ + "global_config" + ] + }, + { + "name": "global_config", + "writable": true + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program" + } + ], + "args": [ + { + "name": "enabled", + "type": "bool" + } + ] + }, { "name": "toggle_mayhem_mode", "discriminator": [ @@ -3286,6 +3738,233 @@ } ] }, + { + "name": "transfer_creator_fees_to_pump", + "docs": [ + "Transfer creator fees to pump creator vault", + "If coin creator fees are currently below rent.minimum_balance(TokenAccount::LEN)", + "The transfer will be skipped" + ], + "discriminator": [ + 139, + 52, + 134, + 85, + 228, + 229, + 108, + 241 + ], + "accounts": [ + { + "name": "wsol_mint", + "docs": [ + "Pump Canonical Pool are quoted in wSOL" + ] + }, + { + "name": "token_program" + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + }, + { + "name": "associated_token_program", + "address": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" + }, + { + "name": "coin_creator" + }, + { + "name": "coin_creator_vault_authority", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 99, + 114, + 101, + 97, + 116, + 111, + 114, + 95, + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "coin_creator" + } + ] + } + }, + { + "name": "coin_creator_vault_ata", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "account", + "path": "coin_creator_vault_authority" + }, + { + "kind": "account", + "path": "token_program" + }, + { + "kind": "account", + "path": "wsol_mint" + } + ], + "program": { + "kind": "const", + "value": [ + 140, + 151, + 37, + 143, + 78, + 36, + 137, + 241, + 187, + 61, + 16, + 41, + 20, + 142, + 13, + 131, + 11, + 90, + 19, + 153, + 218, + 255, + 16, + 132, + 4, + 142, + 123, + 216, + 219, + 233, + 248, + 89 + ] + } + } + }, + { + "name": "pump_creator_vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 99, + 114, + 101, + 97, + 116, + 111, + 114, + 45, + 118, + 97, + 117, + 108, + 116 + ] + }, + { + "kind": "account", + "path": "coin_creator" + } + ], + "program": { + "kind": "const", + "value": [ + 1, + 86, + 224, + 246, + 147, + 102, + 90, + 207, + 68, + 219, + 21, + 104, + 191, + 23, + 91, + 170, + 81, + 137, + 203, + 151, + 245, + 210, + 255, + 59, + 101, + 93, + 43, + 182, + 253, + 109, + 24, + 176 + ] + } + } + }, + { + "name": "event_authority", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 95, + 95, + 101, + 118, + 101, + 110, + 116, + 95, + 97, + 117, + 116, + 104, + 111, + 114, + 105, + 116, + 121 + ] + } + ] + } + }, + { + "name": "program" + } + ], + "args": [] + }, { "name": "update_admin", "discriminator": [ @@ -3625,6 +4304,19 @@ 188 ] }, + { + "name": "SharingConfig", + "discriminator": [ + 216, + 74, + 9, + 0, + 56, + 140, + 93, + 75 + ] + }, { "name": "UserVolumeAccumulator", "discriminator": [ @@ -3679,6 +4371,19 @@ 119 ] }, + { + "name": "ClaimCashbackEvent", + "discriminator": [ + 226, + 214, + 246, + 33, + 7, + 242, + 147, + 229 + ] + }, { "name": "ClaimTokenIncentivesEvent", "discriminator": [ @@ -3796,6 +4501,19 @@ 216 ] }, + { + "name": "MigratePoolCoinCreatorEvent", + "discriminator": [ + 170, + 221, + 82, + 199, + 147, + 165, + 247, + 46 + ] + }, { "name": "ReservedFeeRecipientsEvent", "discriminator": [ @@ -4083,6 +4801,41 @@ { "code": 6044, "name": "NotEnoughRemainingAccounts" + }, + { + "code": 6045, + "name": "InvalidSharingConfigBaseMint" + }, + { + "code": 6046, + "name": "InvalidSharingConfigCoinCreator" + }, + { + "code": 6047, + "name": "CoinCreatorMigratedToSharingConfig", + "msg": "coin creator has been migrated to sharing config, use pump_fees::reset_fee_sharing_config instead" + }, + { + "code": 6048, + "name": "CreatorVaultMigratedToSharingConfig", + "msg": "creator_vault has been migrated to sharing config, use pump:distribute_creator_fees instead" + }, + { + "code": 6049, + "name": "CashbackNotEnabled", + "msg": "Cashback is disabled" + }, + { + "code": 6050, + "name": "OnlyPumpPoolsCashback" + }, + { + "code": 6051, + "name": "CashbackNotInDesiredState" + }, + { + "code": 6052, + "name": "CashbackEarnedDoesNotMatchTokenInVault" } ], "types": [ @@ -4190,6 +4943,10 @@ { "name": "is_mayhem_mode", "type": "bool" + }, + { + "name": "is_cashback_coin", + "type": "bool" } ] } @@ -4321,6 +5078,42 @@ { "name": "ix_name", "type": "string" + }, + { + "name": "cashback_fee_basis_points", + "type": "u64" + }, + { + "name": "cashback", + "type": "u64" + } + ] + } + }, + { + "name": "ClaimCashbackEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "user", + "type": "pubkey" + }, + { + "name": "amount", + "type": "u64" + }, + { + "name": "timestamp", + "type": "i64" + }, + { + "name": "total_claimed", + "type": "u64" + }, + { + "name": "total_cashback_earned", + "type": "u64" } ] } @@ -4417,6 +5210,20 @@ ] } }, + { + "name": "ConfigStatus", + "type": { + "kind": "enum", + "variants": [ + { + "name": "Paused" + }, + { + "name": "Active" + } + ] + } + }, { "name": "CreateConfigEvent", "type": { @@ -4835,6 +5642,10 @@ 7 ] } + }, + { + "name": "is_cashback_enabled", + "type": "bool" } ] } @@ -4901,6 +5712,38 @@ ] } }, + { + "name": "MigratePoolCoinCreatorEvent", + "type": { + "kind": "struct", + "fields": [ + { + "name": "timestamp", + "type": "i64" + }, + { + "name": "base_mint", + "type": "pubkey" + }, + { + "name": "pool", + "type": "pubkey" + }, + { + "name": "sharing_config", + "type": "pubkey" + }, + { + "name": "old_coin_creator", + "type": "pubkey" + }, + { + "name": "new_coin_creator", + "type": "pubkey" + } + ] + } + }, { "name": "OptionBool", "type": { @@ -4961,6 +5804,10 @@ { "name": "is_mayhem_mode", "type": "bool" + }, + { + "name": "is_cashback_coin", + "type": "bool" } ] } @@ -5086,6 +5933,14 @@ { "name": "coin_creator_fee", "type": "u64" + }, + { + "name": "cashback_fee_basis_points", + "type": "u64" + }, + { + "name": "cashback", + "type": "u64" } ] } @@ -5146,6 +6001,68 @@ ] } }, + { + "name": "Shareholder", + "type": { + "kind": "struct", + "fields": [ + { + "name": "address", + "type": "pubkey" + }, + { + "name": "share_bps", + "type": "u16" + } + ] + } + }, + { + "name": "SharingConfig", + "type": { + "kind": "struct", + "fields": [ + { + "name": "bump", + "type": "u8" + }, + { + "name": "version", + "type": "u8" + }, + { + "name": "status", + "type": { + "defined": { + "name": "ConfigStatus" + } + } + }, + { + "name": "mint", + "type": "pubkey" + }, + { + "name": "admin", + "type": "pubkey" + }, + { + "name": "admin_revoked", + "type": "bool" + }, + { + "name": "shareholders", + "type": { + "vec": { + "defined": { + "name": "Shareholder" + } + } + } + } + ] + } + }, { "name": "SyncUserVolumeAccumulatorEvent", "type": { @@ -5263,6 +6180,14 @@ { "name": "has_total_claimed_tokens", "type": "bool" + }, + { + "name": "cashback_earned", + "type": "u64" + }, + { + "name": "total_cashback_claimed", + "type": "u64" } ] } diff --git a/src/interfaces/core.py b/src/interfaces/core.py index c7c1b91..aab92a9 100644 --- a/src/interfaces/core.py +++ b/src/interfaces/core.py @@ -47,6 +47,7 @@ class TokenInfo: creator_vault: Pubkey | None = None token_program_id: Pubkey | None = None # Token or Token2022 program is_mayhem_mode: bool = False # pump.fun mayhem mode flag + is_cashback_coin: bool = False # pump.fun cashback coin flag # Metadata creation_timestamp: float | None = None diff --git a/src/platforms/pumpfun/address_provider.py b/src/platforms/pumpfun/address_provider.py index cb412cf..4b9865d 100644 --- a/src/platforms/pumpfun/address_provider.py +++ b/src/platforms/pumpfun/address_provider.py @@ -75,6 +75,22 @@ class PumpFunAddresses: ) return derived_address + @staticmethod + def find_bonding_curve_v2(mint: Pubkey) -> Pubkey: + """Derive the bonding curve v2 PDA for a token mint. + + Args: + mint: Token mint address + + Returns: + Pubkey of the derived bonding curve v2 account + """ + derived_address, _ = Pubkey.find_program_address( + [b"bonding-curve-v2", bytes(mint)], + PumpFunAddresses.PROGRAM, + ) + return derived_address + @staticmethod def find_fee_config() -> Pubkey: """ @@ -256,6 +272,17 @@ class PumpFunAddressProvider(AddressProvider): """ return PumpFunAddresses.find_user_volume_accumulator(user) + def derive_bonding_curve_v2(self, mint: Pubkey) -> Pubkey: + """Derive the bonding curve v2 PDA for a token mint. + + Args: + mint: Token mint address + + Returns: + Bonding curve v2 address + """ + return PumpFunAddresses.find_bonding_curve_v2(mint) + def derive_fee_config(self) -> Pubkey: """Derive the fee config PDA. @@ -326,6 +353,7 @@ class PumpFunAddressProvider(AddressProvider): "user_volume_accumulator": self.derive_user_volume_accumulator(user), "fee_config": self.derive_fee_config(), "fee_program": PumpFunAddresses.FEE_PROGRAM, + "bonding_curve_v2": self.derive_bonding_curve_v2(token_info.mint), } def get_sell_instruction_accounts( @@ -375,4 +403,6 @@ class PumpFunAddressProvider(AddressProvider): "program": PumpFunAddresses.PROGRAM, "fee_config": self.derive_fee_config(), "fee_program": PumpFunAddresses.FEE_PROGRAM, + "bonding_curve_v2": self.derive_bonding_curve_v2(token_info.mint), + "user_volume_accumulator": self.derive_user_volume_accumulator(user), } diff --git a/src/platforms/pumpfun/curve_manager.py b/src/platforms/pumpfun/curve_manager.py index 3fd1ed0..6b107bc 100644 --- a/src/platforms/pumpfun/curve_manager.py +++ b/src/platforms/pumpfun/curve_manager.py @@ -191,6 +191,7 @@ class PumpFunCurveManager(CurveManager): "complete": decoded_curve_state.get("complete", False), "creator": decoded_curve_state.get("creator", ""), "is_mayhem_mode": decoded_curve_state.get("is_mayhem_mode", False), + "is_cashback_coin": decoded_curve_state.get("is_cashback_coin", False), } # Calculate additional metrics @@ -205,10 +206,7 @@ class PumpFunCurveManager(CurveManager): ) curve_data["price_per_token"] = ( - ( - curve_data["virtual_sol_reserves"] - / curve_data["virtual_token_reserves"] - ) + (curve_data["virtual_sol_reserves"] / curve_data["virtual_token_reserves"]) * (10**TOKEN_DECIMALS) / LAMPORTS_PER_SOL ) diff --git a/src/platforms/pumpfun/event_parser.py b/src/platforms/pumpfun/event_parser.py index e1a45ed..a52f0e3 100644 --- a/src/platforms/pumpfun/event_parser.py +++ b/src/platforms/pumpfun/event_parser.py @@ -48,8 +48,8 @@ class PumpFunEventParser(EventParser): )[0] # Support for token2022 (create_v2 instruction) - self._create_v2_instruction_discriminator_bytes = instruction_discriminators.get( - "create_v2" + self._create_v2_instruction_discriminator_bytes = ( + instruction_discriminators.get("create_v2") ) self._create_v2_instruction_discriminator = ( struct.unpack(" Pubkey: """Derive the associated bonding curve (ATA of bonding curve for the token). diff --git a/src/platforms/pumpfun/instruction_builder.py b/src/platforms/pumpfun/instruction_builder.py index 306e2db..31a578c 100644 --- a/src/platforms/pumpfun/instruction_builder.py +++ b/src/platforms/pumpfun/instruction_builder.py @@ -11,7 +11,7 @@ from solders.instruction import AccountMeta, Instruction from solders.pubkey import Pubkey from spl.token.instructions import create_idempotent_associated_token_account -from core.pubkeys import TOKEN_DECIMALS, SystemAddresses +from core.pubkeys import TOKEN_DECIMALS from interfaces.core import AddressProvider, InstructionBuilder, Platform, TokenInfo from utils.idl_parser import IDLParser from utils.logger import get_logger @@ -143,6 +143,12 @@ class PumpFunInstructionBuilder(InstructionBuilder): is_signer=False, is_writable=False, ), + # Remaining account: bonding_curve_v2 (readonly, required for all coins) + AccountMeta( + pubkey=accounts_info["bonding_curve_v2"], + is_signer=False, + is_writable=False, + ), ] # Build instruction data: discriminator + token_amount + max_sol_cost + track_volume @@ -247,6 +253,25 @@ class PumpFunInstructionBuilder(InstructionBuilder): ), ] + # Remaining accounts (after fee_program) for cashback + bonding_curve_v2 + if token_info.is_cashback_coin: + # Cashback sell: user_volume_accumulator (mutable) + bonding_curve_v2 (readonly) + sell_accounts.append( + AccountMeta( + pubkey=accounts_info["user_volume_accumulator"], + is_signer=False, + is_writable=True, + ) + ) + # bonding_curve_v2 is required for ALL coins (cashback and non-cashback) + sell_accounts.append( + AccountMeta( + pubkey=accounts_info["bonding_curve_v2"], + is_signer=False, + is_writable=False, + ) + ) + # Build instruction data: discriminator + token_amount + min_sol_output + track_volume # Encode OptionBool for track_volume: [1, 1] = Some(true) track_volume_bytes = bytes([1, 1]) @@ -293,6 +318,7 @@ class PumpFunInstructionBuilder(InstructionBuilder): accounts_info["program"], accounts_info["fee_config"], accounts_info["fee_program"], + accounts_info["bonding_curve_v2"], ] def get_required_accounts_for_sell( @@ -320,6 +346,7 @@ class PumpFunInstructionBuilder(InstructionBuilder): accounts_info["program"], accounts_info["fee_config"], accounts_info["fee_program"], + accounts_info["bonding_curve_v2"], ] def calculate_token_amount_raw(self, token_amount_decimal: float) -> int: diff --git a/src/utils/idl_parser.py b/src/utils/idl_parser.py index 5961986..fff1878 100644 --- a/src/utils/idl_parser.py +++ b/src/utils/idl_parser.py @@ -412,10 +412,12 @@ class IDLParser: type_def = self.types[type_name]["type"] if type_def["kind"] == "struct": - return sum( - self._calculate_type_min_size(field["type"]) - for field in type_def["fields"] - ) + total = 0 + for field in type_def["fields"]: + # Handle both named fields (dicts) and tuple fields (strings/dicts) + field_type = field["type"] if isinstance(field, dict) else field + total += self._calculate_type_min_size(field_type) + return total if type_def["kind"] == "enum": # The size of an enum is its discriminator plus the size of its LARGEST variant, @@ -495,9 +497,15 @@ class IDLParser: if type_def["kind"] == "struct": struct_data = {} - for field in type_def["fields"]: - value, offset = self._decode_type(data, offset, field["type"]) - struct_data[field["name"]] = value + for i, field in enumerate(type_def["fields"]): + if isinstance(field, dict): + # Named field: {"name": "x", "type": "bool"} + value, offset = self._decode_type(data, offset, field["type"]) + struct_data[field["name"]] = value + else: + # Tuple struct field: just a type string like "bool" + value, offset = self._decode_type(data, offset, field) + struct_data[f"field_{i}"] = value return struct_data, offset if type_def["kind"] == "enum":