@pump-fun/pump-sdk 1.22.1 → 1.23.0-devnet.2

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,17 +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
- import { bondingCurvePda, canonicalPumpPoolPda, creatorVaultPda, getGlobalParamsPda, getMayhemStatePda, getSolVaultPda, getTokenVaultPda, pumpPoolAuthorityPda } from "./pda";
19
+ import {
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";
20
30
  import {
21
31
  BondingCurve,
22
32
  FeeConfig,
23
33
  Global,
24
34
  GlobalVolumeAccumulator,
25
35
  UserVolumeAccumulator,
36
+ Shareholder,
37
+ SharingConfig,
38
+ DistributeCreatorFeesEvent,
39
+ MinimumDistributableFeeEvent,
26
40
  } from "./state";
27
41
  import { getStaticRandomFeeRecipient } from "./bondingCurve";
42
+ import { getFeeRecipient } from "./fees";
28
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";
29
49
 
30
50
  export function getPumpProgram(connection: Connection): Program<Pump> {
31
51
  return new Program(
@@ -38,6 +58,22 @@ export const PUMP_PROGRAM_ID = new PublicKey(
38
58
  "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
39
59
  );
40
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
+
41
77
  export const PUMP_AMM_PROGRAM_ID = new PublicKey(
42
78
  "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA",
43
79
  );
@@ -56,11 +92,24 @@ export const PUMP_TOKEN_MINT = new PublicKey(
56
92
  "pumpCmXqMfrsAkQ5r49WcJnRayYRqmXz6ae8H7H9Dfn",
57
93
  );
58
94
 
95
+ export const MAX_SHAREHOLDERS = 10;
96
+
59
97
  export class PumpSdk {
60
98
  private readonly offlinePumpProgram: Program<Pump>;
99
+ private readonly offlinePumpFeeProgram: Program<PumpFees>;
100
+ private readonly offlinePumpAmmProgram: Program<PumpAmm>;
61
101
 
62
102
  constructor() {
63
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
+ );
64
113
  }
65
114
 
66
115
  decodeGlobal(accountInfo: AccountInfo<Buffer>): Global {
@@ -124,6 +173,13 @@ export class PumpSdk {
124
173
  }
125
174
  }
126
175
 
176
+ decodeSharingConfig(accountInfo: AccountInfo<Buffer>): SharingConfig {
177
+ return this.offlinePumpFeeProgram.coder.accounts.decode<SharingConfig>(
178
+ "sharingConfig",
179
+ accountInfo.data,
180
+ );
181
+ }
182
+
127
183
  /**
128
184
  * @deprecated Use `createInstructionV2` instead.
129
185
  */
@@ -499,15 +555,6 @@ export class PumpSdk {
499
555
  .instruction();
500
556
  }
501
557
 
502
- async syncUserVolumeAccumulatorBothPrograms(
503
- user: PublicKey,
504
- ): Promise<TransactionInstruction[]> {
505
- return [
506
- await this.syncUserVolumeAccumulator(user),
507
- await PUMP_AMM_SDK.syncUserVolumeAccumulator(user),
508
- ];
509
- }
510
-
511
558
  async setCreator({
512
559
  mint,
513
560
  setCreatorAuthority,
@@ -665,16 +712,249 @@ export class PumpSdk {
665
712
  })
666
713
  .instruction();
667
714
  }
668
- }
669
715
 
670
- export const PUMP_SDK = new PumpSdk();
716
+ /**
717
+ * Creates a fee sharing configuration for a token.
718
+ *
719
+ * @param params - Parameters for creating a fee sharing configuration
720
+ * @param params.creator - The creator of the token
721
+ * @param params.mint - The mint address of the token
722
+ * @param params.pool - The pool address of the token (null for ungraduated coins)
723
+ */
724
+ async createFeeSharingConfig({
725
+ creator,
726
+ mint,
727
+ pool,
728
+ }: {
729
+ creator: PublicKey;
730
+ mint: PublicKey;
731
+ pool: PublicKey | null;
732
+ }): Promise<TransactionInstruction> {
733
+ return await this.offlinePumpFeeProgram.methods
734
+ .createFeeSharingConfig()
735
+ .accountsPartial({
736
+ payer: creator,
737
+ mint,
738
+ pool,
739
+ })
740
+ .instruction();
741
+ }
742
+
743
+
744
+ /**
745
+ * Updates the fee shares for a token's creator fee distribution.
746
+ *
747
+ * @param params - Parameters for updating fee shares
748
+ * @param params.authority - The current authority that can modify the fee sharing config
749
+ * @param params.mint - The mint address of the token
750
+ * @param params.curShareholders - Array of current shareholders
751
+ * @param params.newShareholders - Array of new shareholders and their share percentages
752
+ *
753
+ * @requirements for newShareholders:
754
+ * - Must contain at least 1 shareholder (cannot be empty)
755
+ * - Maximum of 10 shareholders allowed
756
+ * - Each shareholder must have a positive share (shareBps > 0)
757
+ * - Total shares must equal exactly 10,000 basis points (100%)
758
+ * - No duplicate addresses allowed
759
+ * - shareBps is in basis points where 1 bps = 0.01% (e.g., 1500 = 15%)
760
+ *
761
+ * @throws {NoShareholdersError} If shareholders array is empty
762
+ * @throws {TooManyShareholdersError} If more than 10 shareholders
763
+ * @throws {ZeroShareError} If any shareholder has zero or negative shares
764
+ * @throws {InvalidShareTotalError} If total shares don't equal 10,000 basis points
765
+ * @throws {DuplicateShareholderError} If duplicate addresses are found
766
+ *
767
+ * @example
768
+ * ```typescript
769
+ * const instruction = await PUMP_SDK.updateFeeShares({
770
+ * authority: authorityPublicKey,
771
+ * mint: mintPublicKey,
772
+ * curShareholders: [wallet1, wallet2, wallet3],
773
+ * newShareholders: [
774
+ * { address: wallet1, shareBps: 5000 }, // 50%
775
+ * { address: wallet2, shareBps: 3000 }, // 30%
776
+ * { address: wallet3, shareBps: 2000 }, // 20%
777
+ * ]
778
+ * });
779
+ * ```
780
+ */
781
+ async updateFeeShares({
782
+ authority,
783
+ mint,
784
+ currentShareholders,
785
+ newShareholders,
786
+ }: {
787
+ authority: PublicKey;
788
+ mint: PublicKey;
789
+ currentShareholders: PublicKey[];
790
+ newShareholders: Shareholder[];
791
+ }): Promise<TransactionInstruction> {
792
+ if (newShareholders.length === 0) {
793
+ throw new NoShareholdersError();
794
+ }
795
+
796
+ if (newShareholders.length > MAX_SHAREHOLDERS) {
797
+ throw new TooManyShareholdersError(newShareholders.length, MAX_SHAREHOLDERS);
798
+ }
799
+
800
+ let totalShares = 0;
801
+ const addresses = new Set<string>();
802
+
803
+ for (const shareholder of newShareholders) {
804
+ if (shareholder.shareBps <= 0) {
805
+ throw new ZeroShareError(shareholder.address.toString());
806
+ }
807
+
808
+ totalShares += shareholder.shareBps;
809
+ addresses.add(shareholder.address.toString());
810
+ }
811
+
812
+ if (totalShares !== 10_000) {
813
+ throw new InvalidShareTotalError(totalShares);
814
+ }
815
+
816
+ if (addresses.size !== newShareholders.length) {
817
+ throw new DuplicateShareholderError();
818
+ }
819
+
820
+ const sharingConfigPda = feeSharingConfigPda(mint);
821
+ const coinCreatorVaultAuthority = coinCreatorVaultAuthorityPda(sharingConfigPda);
671
822
 
672
- export function getFeeRecipient(global: Global, mayhemMode: boolean): PublicKey {
673
- if (mayhemMode) {
674
- const feeRecipients = [global.reservedFeeRecipient, ...global.reservedFeeRecipients];
675
- return feeRecipients[Math.floor(Math.random() * feeRecipients.length)];
676
- } else {
677
- const feeRecipients = [global.feeRecipient, ...global.feeRecipients,];
678
- return feeRecipients[Math.floor(Math.random() * feeRecipients.length)];
823
+ return await this.offlinePumpFeeProgram.methods
824
+ .updateFeeShares(
825
+ newShareholders.map(sh => ({
826
+ address: sh.address,
827
+ shareBps: sh.shareBps,
828
+ }))
829
+ )
830
+ .accountsPartial({
831
+ authority,
832
+ mint,
833
+ coinCreatorVaultAta: coinCreatorVaultAtaPda(coinCreatorVaultAuthority, NATIVE_MINT, TOKEN_PROGRAM_ID),
834
+ })
835
+ .remainingAccounts(
836
+ currentShareholders.map((pubkey) => ({
837
+ pubkey,
838
+ isWritable: true,
839
+ isSigner: false,
840
+ }))
841
+ )
842
+ .instruction();
843
+ }
844
+
845
+ decodeDistributeCreatorFeesEvent(data: Buffer): DistributeCreatorFeesEvent {
846
+ return this.offlinePumpProgram.coder.types.decode<DistributeCreatorFeesEvent>(
847
+ "distributeCreatorFeesEvent",
848
+ data
849
+ );
850
+ }
851
+
852
+ async distributeCreatorFees({
853
+ mint,
854
+ sharingConfig,
855
+ sharingConfigAddress,
856
+ }: {
857
+ mint: PublicKey;
858
+ sharingConfig: SharingConfig;
859
+ sharingConfigAddress: PublicKey;
860
+ }): Promise<TransactionInstruction> {
861
+ return await this.offlinePumpProgram.methods
862
+ .distributeCreatorFees()
863
+ .accountsPartial({
864
+ mint,
865
+ creatorVault: creatorVaultPda(sharingConfigAddress),
866
+ })
867
+ .remainingAccounts(
868
+ sharingConfig.shareholders.map((shareholder) => ({
869
+ pubkey: shareholder.address,
870
+ isWritable: true,
871
+ isSigner: false,
872
+ }))
873
+ )
874
+ .instruction();
875
+ }
876
+
877
+ decodeMinimumDistributableFee(data: Buffer): MinimumDistributableFeeEvent {
878
+ return this.offlinePumpProgram.coder.types.decode<MinimumDistributableFeeEvent>(
879
+ "minimumDistributableFeeEvent",
880
+ data
881
+ );
882
+ }
883
+
884
+ async getMinimumDistributableFee({
885
+ mint,
886
+ sharingConfig,
887
+ sharingConfigAddress,
888
+ }: {
889
+ mint: PublicKey;
890
+ sharingConfig: SharingConfig;
891
+ sharingConfigAddress: PublicKey;
892
+ }): Promise<TransactionInstruction> {
893
+ return await this.offlinePumpProgram.methods
894
+ .getMinimumDistributableFee()
895
+ .accountsPartial({
896
+ mint,
897
+ creatorVault: creatorVaultPda(sharingConfigAddress),
898
+ })
899
+ .remainingAccounts(
900
+ sharingConfig.shareholders.map((shareholder) => ({
901
+ pubkey: shareholder.address,
902
+ isWritable: true,
903
+ isSigner: false,
904
+ }))
905
+ )
906
+ .instruction();
679
907
  }
680
908
  }
909
+
910
+ export const PUMP_SDK = new PumpSdk();
911
+
912
+ /**
913
+ * Checks if a creator has migrated to using a fee sharing configuration.
914
+ *
915
+ * When a creator sets up fee sharing, the creator address in the BondingCurve or Pool
916
+ * is replaced with the fee sharing config PDA address. This function checks if that
917
+ * migration has occurred.
918
+ *
919
+ * @param params - Parameters for checking migration status
920
+ * @param params.mint - The mint address of the token
921
+ * @param params.creator - The creator address to check
922
+ * - For ungraduated coins: use BondingCurve.creator
923
+ * - For graduated coins: use Pool.coinCreator (from AMM pool)
924
+ *
925
+ * @returns true if the creator has migrated to fee sharing config, false otherwise
926
+ *
927
+ * @example
928
+ * ```typescript
929
+ * import { hasCoinCreatorMigratedToSharingConfig } from "@pump-fun/sdk";
930
+ *
931
+ * // For an ungraduated coin
932
+ * const bondingCurve = await program.account.bondingCurve.fetch(bondingCurvePda(mint));
933
+ * const hasMigrated = hasCoinCreatorMigratedToSharingConfig({
934
+ * mint,
935
+ * creator: bondingCurve.creator
936
+ * });
937
+ *
938
+ * // For a graduated coin
939
+ * const pool = await ammProgram.account.pool.fetch(poolAddress);
940
+ * const hasMigrated = hasCoinCreatorMigratedToSharingConfig({
941
+ * mint,
942
+ * creator: pool.coinCreator
943
+ * });
944
+ *
945
+ * if (hasMigrated) {
946
+ * // Creator fees are distributed according to fee sharing config
947
+ * } else {
948
+ * // Creator fees go directly to the creator address
949
+ * }
950
+ * ```
951
+ */
952
+ export function hasCoinCreatorMigratedToSharingConfig({
953
+ mint,
954
+ creator,
955
+ }: {
956
+ mint: PublicKey;
957
+ creator: PublicKey;
958
+ }): boolean {
959
+ return feeSharingConfigPda(mint).equals(creator);
960
+ }
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
+ }