@pump-fun/pump-sdk 1.24.0 → 1.25.0-devnet.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { Pump } from "./idl/pump";
2
2
  export { default as pumpIdl } from "./idl/pump.json";
3
+ export type { PumpFees } from "./idl/pump_fees";
3
4
  export {
4
5
  getBuyTokenAmountFromSolAmount,
5
6
  getBuySolAmountFromTokenAmount,
@@ -10,11 +11,16 @@ export {
10
11
  export * from "./pda";
11
12
  export {
12
13
  getPumpProgram,
14
+ getPumpAmmProgram,
15
+ getPumpFeeProgram,
13
16
  PUMP_PROGRAM_ID,
14
17
  PUMP_AMM_PROGRAM_ID,
18
+ PUMP_FEE_PROGRAM_ID,
19
+ MAYHEM_PROGRAM_ID,
15
20
  BONDING_CURVE_NEW_SIZE,
16
21
  PumpSdk,
17
22
  PUMP_SDK,
23
+ hasCoinCreatorMigratedToSharingConfig,
18
24
  } from "./sdk";
19
25
  export { OnlinePumpSdk } from "./onlineSdk";
20
26
  export {
@@ -24,5 +30,10 @@ export {
24
30
  GlobalVolumeAccumulator,
25
31
  UserVolumeAccumulator,
26
32
  UserVolumeAccumulatorTotalStats,
33
+ Shareholder,
34
+ SharingConfig,
35
+ DistributeCreatorFeesEvent,
36
+ MinimumDistributableFeeEvent,
27
37
  } from "./state";
28
38
  export { totalUnclaimedTokens, currentDayTokens } from "./tokenIncentives";
39
+ export * from "./errors";
package/src/pda.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  import { PublicKey, PublicKeyInitData } from "@solana/web3.js";
2
2
  import { getAssociatedTokenAddressSync, NATIVE_MINT, TOKEN_2022_PROGRAM_ID } from "@solana/spl-token";
3
- import { poolPda, pumpFeePda, pumpPda } from "@pump-fun/pump-swap-sdk";
4
- import { MAYHEM_PROGRAM_ID, PUMP_PROGRAM_ID } from "./sdk";
3
+ import { poolPda, pumpFeePda, pumpPda, pumpAmmPda } from "@pump-fun/pump-swap-sdk";
4
+ import { MAYHEM_PROGRAM_ID, PUMP_PROGRAM_ID, PUMP_AMM_PROGRAM_ID, PUMP_FEE_PROGRAM_ID } from "./sdk";
5
5
  import { Buffer } from "buffer";
6
6
 
7
7
  export const GLOBAL_PDA = pumpPda([Buffer.from("global")]);
8
8
 
9
+ export const AMM_GLOBAL_PDA = pumpAmmPda([Buffer.from("amm_global")]);
10
+
9
11
  export const PUMP_FEE_CONFIG_PDA = pumpFeePda([
10
12
  Buffer.from("fee_config"),
11
13
  PUMP_PROGRAM_ID.toBuffer(),
@@ -15,6 +17,22 @@ export const GLOBAL_VOLUME_ACCUMULATOR_PDA = pumpPda([
15
17
  Buffer.from("global_volume_accumulator"),
16
18
  ]);
17
19
 
20
+ export const AMM_GLOBAL_VOLUME_ACCUMULATOR_PDA = pumpAmmPda([
21
+ Buffer.from("global_volume_accumulator"),
22
+ ]);
23
+
24
+
25
+ export const PUMP_EVENT_AUTHORITY_PDA = getEventAuthorityPda(PUMP_PROGRAM_ID);
26
+ export const PUMP_AMM_EVENT_AUTHORITY_PDA = getEventAuthorityPda(PUMP_AMM_PROGRAM_ID);
27
+ export const PUMP_FEE_EVENT_AUTHORITY_PDA = getEventAuthorityPda(PUMP_FEE_PROGRAM_ID);
28
+
29
+ export function getEventAuthorityPda(programId: PublicKey): PublicKey {
30
+ return PublicKey.findProgramAddressSync(
31
+ [Buffer.from("__event_authority")],
32
+ programId
33
+ )[0];
34
+ }
35
+
18
36
  export function bondingCurvePda(mint: PublicKeyInitData): PublicKey {
19
37
  return pumpPda([
20
38
  Buffer.from("bonding-curve"),
@@ -75,4 +93,18 @@ export const getTokenVaultPda = (mintPubkey: PublicKey): PublicKey => {
75
93
  true,
76
94
  TOKEN_2022_PROGRAM_ID
77
95
  );
78
- };
96
+ };
97
+
98
+ export const feeSharingConfigPda = (mint: PublicKey): PublicKey => {
99
+ return pumpFeePda([
100
+ Buffer.from("sharing-config"),
101
+ mint.toBuffer(),
102
+ ]);
103
+ };
104
+
105
+ export const ammCreatorVaultPda = (creator: PublicKey): PublicKey => {
106
+ return PublicKey.findProgramAddressSync(
107
+ [Buffer.from("creator_vault"), creator.toBuffer()],
108
+ PUMP_AMM_PROGRAM_ID
109
+ )[0];
110
+ };
package/src/sdk.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { AnchorProvider, Program } from "@coral-xyz/anchor";
2
- import { PUMP_AMM_SDK } from "@pump-fun/pump-swap-sdk";
3
2
  import {
4
3
  createAssociatedTokenAccountIdempotentInstruction,
4
+ ASSOCIATED_TOKEN_PROGRAM_ID,
5
5
  getAssociatedTokenAddressSync,
6
+ NATIVE_MINT,
6
7
  TOKEN_2022_PROGRAM_ID,
7
8
  TOKEN_PROGRAM_ID,
8
9
  } from "@solana/spl-token";
@@ -15,26 +16,36 @@ import {
15
16
  import pumpIdl from "./idl/pump.json";
16
17
  import { Pump } from "./idl/pump";
17
18
  import BN from "bn.js";
18
-
19
19
  import {
20
- bondingCurvePda,
21
- canonicalPumpPoolPda,
22
- creatorVaultPda,
23
- getGlobalParamsPda,
24
- getMayhemStatePda,
25
- getSolVaultPda,
26
- getTokenVaultPda,
27
- pumpPoolAuthorityPda,
28
- } from "./pda";
20
+ NoShareholdersError,
21
+ TooManyShareholdersError,
22
+ ZeroShareError,
23
+ ShareCalculationOverflowError,
24
+ InvalidShareTotalError,
25
+ DuplicateShareholderError,
26
+ PoolRequiredForGraduatedError,
27
+ } from "./errors";
28
+
29
+ import { bondingCurvePda, canonicalPumpPoolPda, creatorVaultPda, getGlobalParamsPda, getMayhemStatePda, getSolVaultPda, getTokenVaultPda, pumpPoolAuthorityPda, ammCreatorVaultPda, feeSharingConfigPda } from "./pda";
29
30
  import {
30
31
  BondingCurve,
31
32
  FeeConfig,
32
33
  Global,
33
34
  GlobalVolumeAccumulator,
34
35
  UserVolumeAccumulator,
36
+ Shareholder,
37
+ SharingConfig,
38
+ DistributeCreatorFeesEvent,
39
+ MinimumDistributableFeeEvent,
35
40
  } from "./state";
36
41
  import { getStaticRandomFeeRecipient } from "./bondingCurve";
42
+ import { getFeeRecipient } from "./fees";
37
43
  import { OFFLINE_PUMP_PROGRAM } from "./onlineSdk";
44
+ import PumpAmmIdl from "./idl/pump_amm.json";
45
+ import { PumpAmm } from "./idl/pump_amm";
46
+ import PumpFeesIdl from "./idl/pump_fees.json";
47
+ import { PumpFees } from "./idl/pump_fees";
48
+ import { coinCreatorVaultAtaPda, coinCreatorVaultAuthorityPda, PUMP_AMM_EVENT_AUTHORITY_PDA, pumpAmmPda } from "@pump-fun/pump-swap-sdk";
38
49
 
39
50
  export function getPumpProgram(connection: Connection): Program<Pump> {
40
51
  return new Program(
@@ -47,6 +58,22 @@ export const PUMP_PROGRAM_ID = new PublicKey(
47
58
  "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
48
59
  );
49
60
 
61
+ export function getPumpAmmProgram(connection: Connection): Program<PumpAmm> {
62
+ return new Program(
63
+ PumpAmmIdl as PumpAmm,
64
+ new AnchorProvider(connection, null as any, {}),
65
+ );
66
+ }
67
+
68
+ export function getPumpFeeProgram(
69
+ connection: Connection,
70
+ ): Program<PumpFees> {
71
+ return new Program(
72
+ PumpFeesIdl as PumpFees,
73
+ new AnchorProvider(connection, null as any, {}),
74
+ );
75
+ }
76
+
50
77
  export const PUMP_AMM_PROGRAM_ID = new PublicKey(
51
78
  "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA"
52
79
  );
@@ -65,11 +92,24 @@ export const PUMP_TOKEN_MINT = new PublicKey(
65
92
  "pumpCmXqMfrsAkQ5r49WcJnRayYRqmXz6ae8H7H9Dfn"
66
93
  );
67
94
 
95
+ export const MAX_SHAREHOLDERS = 10;
96
+
68
97
  export class PumpSdk {
69
98
  private readonly offlinePumpProgram: Program<Pump>;
99
+ private readonly offlinePumpFeeProgram: Program<PumpFees>;
100
+ private readonly offlinePumpAmmProgram: Program<PumpAmm>;
70
101
 
71
102
  constructor() {
72
103
  this.offlinePumpProgram = OFFLINE_PUMP_PROGRAM;
104
+ // Create offline programs for fee and AMM
105
+ this.offlinePumpFeeProgram = new Program(
106
+ PumpFeesIdl as PumpFees,
107
+ new AnchorProvider(null as any, null as any, {})
108
+ );
109
+ this.offlinePumpAmmProgram = new Program(
110
+ PumpAmmIdl as PumpAmm,
111
+ new AnchorProvider(null as any, null as any, {})
112
+ );
73
113
  }
74
114
 
75
115
  decodeGlobal(accountInfo: AccountInfo<Buffer>): Global {
@@ -144,6 +184,13 @@ export class PumpSdk {
144
184
  }
145
185
  }
146
186
 
187
+ decodeSharingConfig(accountInfo: AccountInfo<Buffer>): SharingConfig {
188
+ return this.offlinePumpFeeProgram.coder.accounts.decode<SharingConfig>(
189
+ "sharingConfig",
190
+ accountInfo.data,
191
+ );
192
+ }
193
+
147
194
  /**
148
195
  * @deprecated Use `createInstructionV2` instead.
149
196
  */
@@ -552,15 +599,6 @@ export class PumpSdk {
552
599
  .instruction();
553
600
  }
554
601
 
555
- async syncUserVolumeAccumulatorBothPrograms(
556
- user: PublicKey
557
- ): Promise<TransactionInstruction[]> {
558
- return [
559
- await this.syncUserVolumeAccumulator(user),
560
- await PUMP_AMM_SDK.syncUserVolumeAccumulator(user),
561
- ];
562
- }
563
-
564
602
  async setCreator({
565
603
  mint,
566
604
  setCreatorAuthority,
@@ -728,22 +766,249 @@ export class PumpSdk {
728
766
  })
729
767
  .instruction();
730
768
  }
769
+
770
+ /**
771
+ * Creates a fee sharing configuration for a token.
772
+ *
773
+ * @param params - Parameters for creating a fee sharing configuration
774
+ * @param params.creator - The creator of the token
775
+ * @param params.mint - The mint address of the token
776
+ * @param params.pool - The pool address of the token (null for ungraduated coins)
777
+ */
778
+ async createFeeSharingConfig({
779
+ creator,
780
+ mint,
781
+ pool,
782
+ }: {
783
+ creator: PublicKey;
784
+ mint: PublicKey;
785
+ pool: PublicKey | null;
786
+ }): Promise<TransactionInstruction> {
787
+ return await this.offlinePumpFeeProgram.methods
788
+ .createFeeSharingConfig()
789
+ .accountsPartial({
790
+ payer: creator,
791
+ mint,
792
+ pool,
793
+ })
794
+ .instruction();
795
+ }
796
+
797
+
798
+ /**
799
+ * Updates the fee shares for a token's creator fee distribution.
800
+ *
801
+ * @param params - Parameters for updating fee shares
802
+ * @param params.authority - The current authority that can modify the fee sharing config
803
+ * @param params.mint - The mint address of the token
804
+ * @param params.curShareholders - Array of current shareholders
805
+ * @param params.newShareholders - Array of new shareholders and their share percentages
806
+ *
807
+ * @requirements for newShareholders:
808
+ * - Must contain at least 1 shareholder (cannot be empty)
809
+ * - Maximum of 10 shareholders allowed
810
+ * - Each shareholder must have a positive share (shareBps > 0)
811
+ * - Total shares must equal exactly 10,000 basis points (100%)
812
+ * - No duplicate addresses allowed
813
+ * - shareBps is in basis points where 1 bps = 0.01% (e.g., 1500 = 15%)
814
+ *
815
+ * @throws {NoShareholdersError} If shareholders array is empty
816
+ * @throws {TooManyShareholdersError} If more than 10 shareholders
817
+ * @throws {ZeroShareError} If any shareholder has zero or negative shares
818
+ * @throws {InvalidShareTotalError} If total shares don't equal 10,000 basis points
819
+ * @throws {DuplicateShareholderError} If duplicate addresses are found
820
+ *
821
+ * @example
822
+ * ```typescript
823
+ * const instruction = await PUMP_SDK.updateFeeShares({
824
+ * authority: authorityPublicKey,
825
+ * mint: mintPublicKey,
826
+ * curShareholders: [wallet1, wallet2, wallet3],
827
+ * newShareholders: [
828
+ * { address: wallet1, shareBps: 5000 }, // 50%
829
+ * { address: wallet2, shareBps: 3000 }, // 30%
830
+ * { address: wallet3, shareBps: 2000 }, // 20%
831
+ * ]
832
+ * });
833
+ * ```
834
+ */
835
+ async updateFeeShares({
836
+ authority,
837
+ mint,
838
+ currentShareholders,
839
+ newShareholders,
840
+ }: {
841
+ authority: PublicKey;
842
+ mint: PublicKey;
843
+ currentShareholders: PublicKey[];
844
+ newShareholders: Shareholder[];
845
+ }): Promise<TransactionInstruction> {
846
+ if (newShareholders.length === 0) {
847
+ throw new NoShareholdersError();
848
+ }
849
+
850
+ if (newShareholders.length > MAX_SHAREHOLDERS) {
851
+ throw new TooManyShareholdersError(newShareholders.length, MAX_SHAREHOLDERS);
852
+ }
853
+
854
+ let totalShares = 0;
855
+ const addresses = new Set<string>();
856
+
857
+ for (const shareholder of newShareholders) {
858
+ if (shareholder.shareBps <= 0) {
859
+ throw new ZeroShareError(shareholder.address.toString());
860
+ }
861
+
862
+ totalShares += shareholder.shareBps;
863
+ addresses.add(shareholder.address.toString());
864
+ }
865
+
866
+ if (totalShares !== 10_000) {
867
+ throw new InvalidShareTotalError(totalShares);
868
+ }
869
+
870
+ if (addresses.size !== newShareholders.length) {
871
+ throw new DuplicateShareholderError();
872
+ }
873
+
874
+ const sharingConfigPda = feeSharingConfigPda(mint);
875
+ const coinCreatorVaultAuthority = coinCreatorVaultAuthorityPda(sharingConfigPda);
876
+
877
+ return await this.offlinePumpFeeProgram.methods
878
+ .updateFeeShares(
879
+ newShareholders.map(sh => ({
880
+ address: sh.address,
881
+ shareBps: sh.shareBps,
882
+ }))
883
+ )
884
+ .accountsPartial({
885
+ authority,
886
+ mint,
887
+ coinCreatorVaultAta: coinCreatorVaultAtaPda(coinCreatorVaultAuthority, NATIVE_MINT, TOKEN_PROGRAM_ID),
888
+ })
889
+ .remainingAccounts(
890
+ currentShareholders.map((pubkey) => ({
891
+ pubkey,
892
+ isWritable: true,
893
+ isSigner: false,
894
+ }))
895
+ )
896
+ .instruction();
897
+ }
898
+
899
+ decodeDistributeCreatorFeesEvent(data: Buffer): DistributeCreatorFeesEvent {
900
+ return this.offlinePumpProgram.coder.types.decode<DistributeCreatorFeesEvent>(
901
+ "distributeCreatorFeesEvent",
902
+ data
903
+ );
904
+ }
905
+
906
+ async distributeCreatorFees({
907
+ mint,
908
+ sharingConfig,
909
+ sharingConfigAddress,
910
+ }: {
911
+ mint: PublicKey;
912
+ sharingConfig: SharingConfig;
913
+ sharingConfigAddress: PublicKey;
914
+ }): Promise<TransactionInstruction> {
915
+ return await this.offlinePumpProgram.methods
916
+ .distributeCreatorFees()
917
+ .accountsPartial({
918
+ mint,
919
+ creatorVault: creatorVaultPda(sharingConfigAddress),
920
+ })
921
+ .remainingAccounts(
922
+ sharingConfig.shareholders.map((shareholder) => ({
923
+ pubkey: shareholder.address,
924
+ isWritable: true,
925
+ isSigner: false,
926
+ }))
927
+ )
928
+ .instruction();
929
+ }
930
+
931
+ decodeMinimumDistributableFee(data: Buffer): MinimumDistributableFeeEvent {
932
+ return this.offlinePumpProgram.coder.types.decode<MinimumDistributableFeeEvent>(
933
+ "minimumDistributableFeeEvent",
934
+ data
935
+ );
936
+ }
937
+
938
+ async getMinimumDistributableFee({
939
+ mint,
940
+ sharingConfig,
941
+ sharingConfigAddress,
942
+ }: {
943
+ mint: PublicKey;
944
+ sharingConfig: SharingConfig;
945
+ sharingConfigAddress: PublicKey;
946
+ }): Promise<TransactionInstruction> {
947
+ return await this.offlinePumpProgram.methods
948
+ .getMinimumDistributableFee()
949
+ .accountsPartial({
950
+ mint,
951
+ creatorVault: creatorVaultPda(sharingConfigAddress),
952
+ })
953
+ .remainingAccounts(
954
+ sharingConfig.shareholders.map((shareholder) => ({
955
+ pubkey: shareholder.address,
956
+ isWritable: true,
957
+ isSigner: false,
958
+ }))
959
+ )
960
+ .instruction();
961
+ }
731
962
  }
732
963
 
733
964
  export const PUMP_SDK = new PumpSdk();
734
965
 
735
- export function getFeeRecipient(
736
- global: Global,
737
- mayhemMode: boolean
738
- ): PublicKey {
739
- if (mayhemMode) {
740
- const feeRecipients = [
741
- global.reservedFeeRecipient,
742
- ...global.reservedFeeRecipients,
743
- ];
744
- return feeRecipients[Math.floor(Math.random() * feeRecipients.length)];
745
- } else {
746
- const feeRecipients = [global.feeRecipient, ...global.feeRecipients];
747
- return feeRecipients[Math.floor(Math.random() * feeRecipients.length)];
748
- }
966
+ /**
967
+ * Checks if a creator has migrated to using a fee sharing configuration.
968
+ *
969
+ * When a creator sets up fee sharing, the creator address in the BondingCurve or Pool
970
+ * is replaced with the fee sharing config PDA address. This function checks if that
971
+ * migration has occurred.
972
+ *
973
+ * @param params - Parameters for checking migration status
974
+ * @param params.mint - The mint address of the token
975
+ * @param params.creator - The creator address to check
976
+ * - For ungraduated coins: use BondingCurve.creator
977
+ * - For graduated coins: use Pool.coinCreator (from AMM pool)
978
+ *
979
+ * @returns true if the creator has migrated to fee sharing config, false otherwise
980
+ *
981
+ * @example
982
+ * ```typescript
983
+ * import { hasCoinCreatorMigratedToSharingConfig } from "@pump-fun/sdk";
984
+ *
985
+ * // For an ungraduated coin
986
+ * const bondingCurve = await program.account.bondingCurve.fetch(bondingCurvePda(mint));
987
+ * const hasMigrated = hasCoinCreatorMigratedToSharingConfig({
988
+ * mint,
989
+ * creator: bondingCurve.creator
990
+ * });
991
+ *
992
+ * // For a graduated coin
993
+ * const pool = await ammProgram.account.pool.fetch(poolAddress);
994
+ * const hasMigrated = hasCoinCreatorMigratedToSharingConfig({
995
+ * mint,
996
+ * creator: pool.coinCreator
997
+ * });
998
+ *
999
+ * if (hasMigrated) {
1000
+ * // Creator fees are distributed according to fee sharing config
1001
+ * } else {
1002
+ * // Creator fees go directly to the creator address
1003
+ * }
1004
+ * ```
1005
+ */
1006
+ export function hasCoinCreatorMigratedToSharingConfig({
1007
+ mint,
1008
+ creator,
1009
+ }: {
1010
+ mint: PublicKey;
1011
+ creator: PublicKey;
1012
+ }): boolean {
1013
+ return feeSharingConfigPda(mint).equals(creator);
749
1014
  }
package/src/state.ts CHANGED
@@ -77,3 +77,31 @@ export interface Fees {
77
77
  protocolFeeBps: BN;
78
78
  creatorFeeBps: BN;
79
79
  }
80
+
81
+ export interface Shareholder {
82
+ address: PublicKey;
83
+ shareBps: number;
84
+ }
85
+
86
+ export interface SharingConfig {
87
+ version: number;
88
+ mint: PublicKey;
89
+ admin: PublicKey;
90
+ adminRevoked: boolean;
91
+ shareholders: Shareholder[];
92
+ }
93
+
94
+ export interface DistributeCreatorFeesEvent {
95
+ timestamp: BN;
96
+ mint: PublicKey;
97
+ sharingConfig: PublicKey;
98
+ admin: PublicKey;
99
+ shareholders: Shareholder[];
100
+ distributed: BN;
101
+ }
102
+
103
+ export interface MinimumDistributableFeeEvent {
104
+ minimumRequired: BN;
105
+ distributableFees: BN;
106
+ canDistribute: boolean;
107
+ }