pump-trader 1.1.1 → 1.1.3

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/dist/index.d.ts CHANGED
@@ -33,6 +33,8 @@ interface BondingCurveState {
33
33
  realSolReserves: bigint;
34
34
  tokenTotalSupply: bigint;
35
35
  complete: boolean;
36
+ isMayhemMode?: boolean;
37
+ isCashbackCoin?: boolean;
36
38
  }
37
39
  interface BondingInfo {
38
40
  bonding: PublicKey;
@@ -101,6 +103,7 @@ export declare class PumpTrader {
101
103
  getTradeMode(tokenAddr: string): Promise<"bonding" | "amm">;
102
104
  loadGlobal(): Promise<GlobalState>;
103
105
  getBondingPda(mint: PublicKey): PublicKey;
106
+ deriveBondingCurveV2(mint: PublicKey): PublicKey;
104
107
  loadBonding(mint: PublicKey): Promise<BondingInfo>;
105
108
  calcBuy(solIn: bigint, state: BondingCurveState): bigint;
106
109
  calcSell(tokenIn: bigint, state: BondingCurveState): bigint;
package/dist/index.js CHANGED
@@ -100,6 +100,8 @@ function parsePoolKeys(data) {
100
100
  const coinCreator = new web3_js_1.PublicKey(data.slice(offset, offset + 32));
101
101
  offset += 32;
102
102
  const isMayhemMode = data.readUInt8(offset) === 1;
103
+ offset += 1;
104
+ const isCashbackCoin = offset < data.length ? data.readUInt8(offset) === 1 : false;
103
105
  return {
104
106
  creator,
105
107
  baseMint,
@@ -108,7 +110,8 @@ function parsePoolKeys(data) {
108
110
  poolBaseTokenAccount,
109
111
  poolQuoteTokenAccount,
110
112
  coinCreator,
111
- isMayhemMode
113
+ isMayhemMode,
114
+ isCashbackCoin
112
115
  };
113
116
  }
114
117
  /* ================= PumpTrader 类 ================= */
@@ -176,7 +179,15 @@ class PumpTrader {
176
179
  */
177
180
  async getTradeMode(tokenAddr) {
178
181
  const isAmmMode = await this.isAmmCompleted(tokenAddr);
179
- return isAmmMode ? "amm" : "bonding";
182
+ if (isAmmMode)
183
+ return "amm";
184
+ try {
185
+ await this.getAmmPoolInfo(new web3_js_1.PublicKey(tokenAddr));
186
+ return "amm";
187
+ }
188
+ catch {
189
+ return "bonding";
190
+ }
180
191
  }
181
192
  /* ---------- Global State ---------- */
182
193
  async loadGlobal() {
@@ -213,6 +224,9 @@ class PumpTrader {
213
224
  getBondingPda(mint) {
214
225
  return web3_js_1.PublicKey.findProgramAddressSync([SEEDS.BONDING, mint.toBuffer()], PROGRAM_IDS.PUMP)[0];
215
226
  }
227
+ deriveBondingCurveV2(mint) {
228
+ return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("bonding-curve-v2"), mint.toBuffer()], PROGRAM_IDS.PUMP)[0];
229
+ }
216
230
  async loadBonding(mint) {
217
231
  const bonding = this.getBondingPda(mint);
218
232
  const acc = await this.connection.getAccountInfo(bonding);
@@ -229,6 +243,10 @@ class PumpTrader {
229
243
  state.complete = data[offset] === 1;
230
244
  offset += 1;
231
245
  const creator = new web3_js_1.PublicKey(data.slice(offset, offset + 32));
246
+ offset += 32;
247
+ state.isMayhemMode = offset < data.length ? data[offset] === 1 : false;
248
+ offset += 1;
249
+ state.isCashbackCoin = offset < data.length ? data[offset] === 1 : false;
232
250
  return { bonding, state, creator };
233
251
  }
234
252
  /* ---------- 价格计算 ---------- */
@@ -456,6 +474,7 @@ class PumpTrader {
456
474
  async buy(tokenAddr, totalSolIn, tradeOpt) {
457
475
  const mint = new web3_js_1.PublicKey(tokenAddr);
458
476
  const tokenProgram = await this.detectTokenProgram(tokenAddr);
477
+ const bondingCurveV2 = this.deriveBondingCurveV2(mint);
459
478
  if (!this.globalState)
460
479
  await this.loadGlobal();
461
480
  const { bonding, state, creator } = await this.loadBonding(mint);
@@ -500,7 +519,8 @@ class PumpTrader {
500
519
  { pubkey: globalVolumeAccumulator, isSigner: false, isWritable: false },
501
520
  { pubkey: userVolumeAccumulator, isSigner: false, isWritable: true },
502
521
  { pubkey: feeConfig, isSigner: false, isWritable: false },
503
- { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false }
522
+ { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false },
523
+ { pubkey: bondingCurveV2, isSigner: false, isWritable: false }
504
524
  ],
505
525
  data: Buffer.concat([DISCRIMINATORS.BUY, u64(tokenOut), u64(maxSol)])
506
526
  }));
@@ -530,6 +550,7 @@ class PumpTrader {
530
550
  async sell(tokenAddr, totalTokenIn, tradeOpt) {
531
551
  const mint = new web3_js_1.PublicKey(tokenAddr);
532
552
  const tokenProgram = await this.detectTokenProgram(tokenAddr);
553
+ const bondingCurveV2 = this.deriveBondingCurveV2(mint);
533
554
  if (!this.globalState)
534
555
  await this.loadGlobal();
535
556
  const { bonding, state, creator } = await this.loadBonding(mint);
@@ -545,6 +566,12 @@ class PumpTrader {
545
566
  const userAta = (0, spl_token_1.getAssociatedTokenAddressSync)(mint, this.wallet.publicKey, false, tokenProgram.programId, spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID);
546
567
  const [creatorVault] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("creator-vault"), creator.toBuffer()], PROGRAM_IDS.PUMP);
547
568
  const [feeConfig] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("fee_config"), SEEDS.FEE_CONFIG], PROGRAM_IDS.FEE);
569
+ const [userVolumeAccumulator] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("user_volume_accumulator"), this.wallet.publicKey.toBuffer()], PROGRAM_IDS.PUMP);
570
+ const sellRemainingKeys = [];
571
+ if (state.isCashbackCoin) {
572
+ sellRemainingKeys.push({ pubkey: userVolumeAccumulator, isSigner: false, isWritable: true });
573
+ }
574
+ sellRemainingKeys.push({ pubkey: bondingCurveV2, isSigner: false, isWritable: false });
548
575
  for (let i = 0; i < tokenChunks.length; i++) {
549
576
  try {
550
577
  const tokenIn = tokenChunks[i];
@@ -573,7 +600,8 @@ class PumpTrader {
573
600
  { pubkey: PROGRAM_IDS.EVENT_AUTHORITY, isSigner: false, isWritable: false },
574
601
  { pubkey: PROGRAM_IDS.PUMP, isSigner: false, isWritable: false },
575
602
  { pubkey: feeConfig, isSigner: false, isWritable: false },
576
- { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false }
603
+ { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false },
604
+ ...sellRemainingKeys
577
605
  ],
578
606
  data: Buffer.concat([
579
607
  DISCRIMINATORS.SELL,
@@ -763,6 +791,12 @@ class PumpTrader {
763
791
  const [feeConfig] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("fee_config"), SEEDS.AMM_FEE_CONFIG], PROGRAM_IDS.FEE);
764
792
  const protocolFeeRecipient = globalConfig.protocolFeeRecipients[0];
765
793
  const protocolFeeRecipientTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(SOL_MINT, protocolFeeRecipient, true, spl_token_1.TOKEN_PROGRAM_ID, spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID);
794
+ const remainingKeys = [];
795
+ if (poolKeys.isCashbackCoin) {
796
+ const userVolumeAccumulatorWsolAta = (0, spl_token_1.getAssociatedTokenAddressSync)(SOL_MINT, userVolumeAccumulator, true, spl_token_1.TOKEN_PROGRAM_ID, spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID);
797
+ remainingKeys.push({ pubkey: userVolumeAccumulatorWsolAta, isSigner: false, isWritable: true });
798
+ }
799
+ remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
766
800
  return new web3_js_1.TransactionInstruction({
767
801
  programId: PROGRAM_IDS.PUMP_AMM,
768
802
  keys: [
@@ -789,7 +823,7 @@ class PumpTrader {
789
823
  { pubkey: userVolumeAccumulator, isSigner: false, isWritable: true },
790
824
  { pubkey: feeConfig, isSigner: false, isWritable: false },
791
825
  { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false },
792
- { pubkey: poolV2, isSigner: false, isWritable: false }
826
+ ...remainingKeys
793
827
  ],
794
828
  data: Buffer.concat([
795
829
  DISCRIMINATORS.BUY,
@@ -808,6 +842,13 @@ class PumpTrader {
808
842
  const [feeConfig] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("fee_config"), SEEDS.AMM_FEE_CONFIG], PROGRAM_IDS.FEE);
809
843
  const protocolFeeRecipient = globalConfig.protocolFeeRecipients[0];
810
844
  const protocolFeeRecipientTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(SOL_MINT, protocolFeeRecipient, true, spl_token_1.TOKEN_PROGRAM_ID, spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID);
845
+ const [userVolumeAccumulator] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("user_volume_accumulator"), this.wallet.publicKey.toBuffer()], PROGRAM_IDS.PUMP_AMM);
846
+ const userVolumeAccumulatorWsolAta = (0, spl_token_1.getAssociatedTokenAddressSync)(SOL_MINT, userVolumeAccumulator, true, spl_token_1.TOKEN_PROGRAM_ID, spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID);
847
+ const remainingKeys = [];
848
+ if (poolKeys.isCashbackCoin) {
849
+ remainingKeys.push({ pubkey: userVolumeAccumulatorWsolAta, isSigner: false, isWritable: true }, { pubkey: userVolumeAccumulator, isSigner: false, isWritable: true });
850
+ }
851
+ remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
811
852
  return new web3_js_1.TransactionInstruction({
812
853
  programId: PROGRAM_IDS.PUMP_AMM,
813
854
  keys: [
@@ -832,7 +873,7 @@ class PumpTrader {
832
873
  { pubkey: coinCreatorVaultAuthority, isSigner: false, isWritable: false },
833
874
  { pubkey: feeConfig, isSigner: false, isWritable: false },
834
875
  { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false },
835
- { pubkey: poolV2, isSigner: false, isWritable: false }
876
+ ...remainingKeys
836
877
  ],
837
878
  data: Buffer.concat([
838
879
  DISCRIMINATORS.SELL,
package/index.js CHANGED
@@ -141,6 +141,8 @@ function parsePoolKeys(data) {
141
141
  offset += 32;
142
142
 
143
143
  const isMayhemMode = data.readUInt8(offset) === 1;
144
+ offset += 1;
145
+ const isCashbackCoin = offset < data.length ? data.readUInt8(offset) === 1 : false;
144
146
 
145
147
  return {
146
148
  creator,
@@ -150,7 +152,8 @@ function parsePoolKeys(data) {
150
152
  poolBaseTokenAccount,
151
153
  poolQuoteTokenAccount,
152
154
  coinCreator,
153
- isMayhemMode
155
+ isMayhemMode,
156
+ isCashbackCoin
154
157
  };
155
158
  }
156
159
 
@@ -230,7 +233,13 @@ export class PumpTrader {
230
233
  */
231
234
  async getTradeMode(tokenAddr) {
232
235
  const isAmmMode = await this.isAmmCompleted(tokenAddr);
233
- return isAmmMode ? "amm" : "bonding";
236
+ if (isAmmMode) return "amm";
237
+ try {
238
+ await this.getAmmPoolInfo(new PublicKey(tokenAddr));
239
+ return "amm";
240
+ } catch {
241
+ return "bonding";
242
+ }
234
243
  }
235
244
 
236
245
  /* ---------- Global State ---------- */
@@ -278,6 +287,13 @@ export class PumpTrader {
278
287
  )[0];
279
288
  }
280
289
 
290
+ deriveBondingCurveV2(mint) {
291
+ return PublicKey.findProgramAddressSync(
292
+ [Buffer.from("bonding-curve-v2"), mint.toBuffer()],
293
+ PROGRAM_IDS.PUMP
294
+ )[0];
295
+ }
296
+
281
297
  async loadBonding(mint) {
282
298
  const bonding = this.getBondingPda(mint);
283
299
  const acc = await this.connection.getAccountInfo(bonding);
@@ -296,6 +312,10 @@ export class PumpTrader {
296
312
  offset += 1;
297
313
 
298
314
  const creator = new PublicKey(data.slice(offset, offset + 32));
315
+ offset += 32;
316
+ state.isMayhemMode = offset < data.length ? data[offset] === 1 : false;
317
+ offset += 1;
318
+ state.isCashbackCoin = offset < data.length ? data[offset] === 1 : false;
299
319
 
300
320
  return { bonding, state, creator };
301
321
  }
@@ -611,6 +631,7 @@ export class PumpTrader {
611
631
  async buy(tokenAddr, totalSolIn, tradeOpt) {
612
632
  const mint = new PublicKey(tokenAddr);
613
633
  const tokenProgram = await this.detectTokenProgram(tokenAddr);
634
+ const bondingCurveV2 = this.deriveBondingCurveV2(mint);
614
635
 
615
636
  if (!this.globalState) await this.loadGlobal();
616
637
 
@@ -647,6 +668,17 @@ export class PumpTrader {
647
668
  PROGRAM_IDS.FEE
648
669
  );
649
670
 
671
+ const [userVolumeAccumulator] = PublicKey.findProgramAddressSync(
672
+ [Buffer.from("user_volume_accumulator"), this.wallet.publicKey.toBuffer()],
673
+ PROGRAM_IDS.PUMP
674
+ );
675
+
676
+ const sellRemainingKeys = [];
677
+ if (state.isCashbackCoin) {
678
+ sellRemainingKeys.push({ pubkey: userVolumeAccumulator, isSigner: false, isWritable: true });
679
+ }
680
+ sellRemainingKeys.push({ pubkey: bondingCurveV2, isSigner: false, isWritable: false });
681
+
650
682
  for (let i = 0; i < solChunks.length; i++) {
651
683
  try {
652
684
  const solIn = solChunks[i];
@@ -685,7 +717,8 @@ export class PumpTrader {
685
717
  { pubkey: globalVolumeAccumulator, isSigner: false, isWritable: false },
686
718
  { pubkey: userVolumeAccumulator, isSigner: false, isWritable: true },
687
719
  { pubkey: feeConfig, isSigner: false, isWritable: false },
688
- { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false }
720
+ { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false },
721
+ { pubkey: bondingCurveV2, isSigner: false, isWritable: false }
689
722
  ],
690
723
  data: Buffer.concat([DISCRIMINATORS.BUY, u64(tokenOut), u64(maxSol)])
691
724
  })
@@ -721,6 +754,7 @@ export class PumpTrader {
721
754
  async sell(tokenAddr, totalTokenIn, tradeOpt) {
722
755
  const mint = new PublicKey(tokenAddr);
723
756
  const tokenProgram = await this.detectTokenProgram(tokenAddr);
757
+ const bondingCurveV2 = this.deriveBondingCurveV2(mint);
724
758
 
725
759
  if (!this.globalState) await this.loadGlobal();
726
760
 
@@ -798,7 +832,8 @@ export class PumpTrader {
798
832
  { pubkey: PROGRAM_IDS.EVENT_AUTHORITY, isSigner: false, isWritable: false },
799
833
  { pubkey: PROGRAM_IDS.PUMP, isSigner: false, isWritable: false },
800
834
  { pubkey: feeConfig, isSigner: false, isWritable: false },
801
- { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false }
835
+ { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false },
836
+ ...sellRemainingKeys
802
837
  ],
803
838
  data: Buffer.concat([
804
839
  DISCRIMINATORS.SELL,
@@ -1119,6 +1154,19 @@ export class PumpTrader {
1119
1154
  ASSOCIATED_TOKEN_PROGRAM_ID
1120
1155
  );
1121
1156
 
1157
+ const remainingKeys = [];
1158
+ if (poolKeys.isCashbackCoin) {
1159
+ const userVolumeAccumulatorWsolAta = getAssociatedTokenAddressSync(
1160
+ SOL_MINT,
1161
+ userVolumeAccumulator,
1162
+ true,
1163
+ TOKEN_PROGRAM_ID,
1164
+ ASSOCIATED_TOKEN_PROGRAM_ID
1165
+ );
1166
+ remainingKeys.push({ pubkey: userVolumeAccumulatorWsolAta, isSigner: false, isWritable: true });
1167
+ }
1168
+ remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
1169
+
1122
1170
  return new TransactionInstruction({
1123
1171
  programId: PROGRAM_IDS.PUMP_AMM,
1124
1172
  keys: [
@@ -1145,7 +1193,7 @@ export class PumpTrader {
1145
1193
  { pubkey: userVolumeAccumulator, isSigner: false, isWritable: true },
1146
1194
  { pubkey: feeConfig, isSigner: false, isWritable: false },
1147
1195
  { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false },
1148
- { pubkey: poolV2, isSigner: false, isWritable: false }
1196
+ ...remainingKeys
1149
1197
  ],
1150
1198
  data: Buffer.concat([
1151
1199
  DISCRIMINATORS.BUY,
@@ -1192,6 +1240,28 @@ export class PumpTrader {
1192
1240
  ASSOCIATED_TOKEN_PROGRAM_ID
1193
1241
  );
1194
1242
 
1243
+ const [userVolumeAccumulator] = PublicKey.findProgramAddressSync(
1244
+ [Buffer.from("user_volume_accumulator"), this.wallet.publicKey.toBuffer()],
1245
+ PROGRAM_IDS.PUMP_AMM
1246
+ );
1247
+
1248
+ const userVolumeAccumulatorWsolAta = getAssociatedTokenAddressSync(
1249
+ SOL_MINT,
1250
+ userVolumeAccumulator,
1251
+ true,
1252
+ TOKEN_PROGRAM_ID,
1253
+ ASSOCIATED_TOKEN_PROGRAM_ID
1254
+ );
1255
+
1256
+ const remainingKeys = [];
1257
+ if (poolKeys.isCashbackCoin) {
1258
+ remainingKeys.push(
1259
+ { pubkey: userVolumeAccumulatorWsolAta, isSigner: false, isWritable: true },
1260
+ { pubkey: userVolumeAccumulator, isSigner: false, isWritable: true }
1261
+ );
1262
+ }
1263
+ remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
1264
+
1195
1265
  return new TransactionInstruction({
1196
1266
  programId: PROGRAM_IDS.PUMP_AMM,
1197
1267
  keys: [
@@ -1216,7 +1286,7 @@ export class PumpTrader {
1216
1286
  { pubkey: coinCreatorVaultAuthority, isSigner: false, isWritable: false },
1217
1287
  { pubkey: feeConfig, isSigner: false, isWritable: false },
1218
1288
  { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false },
1219
- { pubkey: poolV2, isSigner: false, isWritable: false }
1289
+ ...remainingKeys
1220
1290
  ],
1221
1291
  data: Buffer.concat([
1222
1292
  DISCRIMINATORS.SELL,
package/index.ts CHANGED
@@ -63,6 +63,8 @@ interface BondingCurveState {
63
63
  realSolReserves: bigint;
64
64
  tokenTotalSupply: bigint;
65
65
  complete: boolean;
66
+ isMayhemMode?: boolean;
67
+ isCashbackCoin?: boolean;
66
68
  }
67
69
 
68
70
  interface BondingInfo {
@@ -239,6 +241,8 @@ function parsePoolKeys(data: Buffer) {
239
241
  offset += 32;
240
242
 
241
243
  const isMayhemMode = data.readUInt8(offset) === 1;
244
+ offset += 1;
245
+ const isCashbackCoin = offset < data.length ? data.readUInt8(offset) === 1 : false;
242
246
 
243
247
  return {
244
248
  creator,
@@ -248,7 +252,8 @@ function parsePoolKeys(data: Buffer) {
248
252
  poolBaseTokenAccount,
249
253
  poolQuoteTokenAccount,
250
254
  coinCreator,
251
- isMayhemMode
255
+ isMayhemMode,
256
+ isCashbackCoin
252
257
  };
253
258
  }
254
259
 
@@ -328,7 +333,13 @@ export class PumpTrader {
328
333
  */
329
334
  async getTradeMode(tokenAddr: string): Promise<"bonding" | "amm"> {
330
335
  const isAmmMode = await this.isAmmCompleted(tokenAddr);
331
- return isAmmMode ? "amm" : "bonding";
336
+ if (isAmmMode) return "amm";
337
+ try {
338
+ await this.getAmmPoolInfo(new PublicKey(tokenAddr));
339
+ return "amm";
340
+ } catch {
341
+ return "bonding";
342
+ }
332
343
  }
333
344
 
334
345
  /* ---------- Global State ---------- */
@@ -376,6 +387,13 @@ export class PumpTrader {
376
387
  )[0];
377
388
  }
378
389
 
390
+ deriveBondingCurveV2(mint: PublicKey): PublicKey {
391
+ return PublicKey.findProgramAddressSync(
392
+ [Buffer.from("bonding-curve-v2"), mint.toBuffer()],
393
+ PROGRAM_IDS.PUMP
394
+ )[0];
395
+ }
396
+
379
397
  async loadBonding(mint: PublicKey): Promise<BondingInfo> {
380
398
  const bonding = this.getBondingPda(mint);
381
399
  const acc = await this.connection.getAccountInfo(bonding);
@@ -394,6 +412,11 @@ export class PumpTrader {
394
412
  offset += 1;
395
413
 
396
414
  const creator = new PublicKey(data.slice(offset, offset + 32));
415
+ offset += 32;
416
+
417
+ state.isMayhemMode = offset < data.length ? data[offset] === 1 : false;
418
+ offset += 1;
419
+ state.isCashbackCoin = offset < data.length ? data[offset] === 1 : false;
397
420
 
398
421
  return { bonding, state, creator };
399
422
  }
@@ -716,6 +739,7 @@ export class PumpTrader {
716
739
  async buy(tokenAddr: string, totalSolIn: bigint, tradeOpt: TradeOptions): Promise<TradeResult> {
717
740
  const mint = new PublicKey(tokenAddr);
718
741
  const tokenProgram = await this.detectTokenProgram(tokenAddr);
742
+ const bondingCurveV2 = this.deriveBondingCurveV2(mint);
719
743
 
720
744
  if (!this.globalState) await this.loadGlobal();
721
745
 
@@ -792,7 +816,8 @@ export class PumpTrader {
792
816
  { pubkey: globalVolumeAccumulator, isSigner: false, isWritable: false },
793
817
  { pubkey: userVolumeAccumulator, isSigner: false, isWritable: true },
794
818
  { pubkey: feeConfig, isSigner: false, isWritable: false },
795
- { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false }
819
+ { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false },
820
+ { pubkey: bondingCurveV2, isSigner: false, isWritable: false }
796
821
  ],
797
822
  data: Buffer.concat([DISCRIMINATORS.BUY, u64(tokenOut), u64(maxSol)])
798
823
  })
@@ -828,6 +853,7 @@ export class PumpTrader {
828
853
  async sell(tokenAddr: string, totalTokenIn: bigint, tradeOpt: TradeOptions): Promise<TradeResult> {
829
854
  const mint = new PublicKey(tokenAddr);
830
855
  const tokenProgram = await this.detectTokenProgram(tokenAddr);
856
+ const bondingCurveV2 = this.deriveBondingCurveV2(mint);
831
857
 
832
858
  if (!this.globalState) await this.loadGlobal();
833
859
 
@@ -871,6 +897,17 @@ export class PumpTrader {
871
897
  PROGRAM_IDS.FEE
872
898
  );
873
899
 
900
+ const [userVolumeAccumulator] = PublicKey.findProgramAddressSync(
901
+ [Buffer.from("user_volume_accumulator"), this.wallet.publicKey.toBuffer()],
902
+ PROGRAM_IDS.PUMP
903
+ );
904
+
905
+ const sellRemainingKeys = [];
906
+ if (state.isCashbackCoin) {
907
+ sellRemainingKeys.push({ pubkey: userVolumeAccumulator, isSigner: false, isWritable: true });
908
+ }
909
+ sellRemainingKeys.push({ pubkey: bondingCurveV2, isSigner: false, isWritable: false });
910
+
874
911
  for (let i = 0; i < tokenChunks.length; i++) {
875
912
  try {
876
913
  const tokenIn = tokenChunks[i];
@@ -905,7 +942,8 @@ export class PumpTrader {
905
942
  { pubkey: PROGRAM_IDS.EVENT_AUTHORITY, isSigner: false, isWritable: false },
906
943
  { pubkey: PROGRAM_IDS.PUMP, isSigner: false, isWritable: false },
907
944
  { pubkey: feeConfig, isSigner: false, isWritable: false },
908
- { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false }
945
+ { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false },
946
+ ...sellRemainingKeys
909
947
  ],
910
948
  data: Buffer.concat([
911
949
  DISCRIMINATORS.SELL,
@@ -1232,6 +1270,19 @@ export class PumpTrader {
1232
1270
  ASSOCIATED_TOKEN_PROGRAM_ID
1233
1271
  );
1234
1272
 
1273
+ const remainingKeys = [];
1274
+ if (poolKeys.isCashbackCoin) {
1275
+ const userVolumeAccumulatorWsolAta = getAssociatedTokenAddressSync(
1276
+ SOL_MINT,
1277
+ userVolumeAccumulator,
1278
+ true,
1279
+ TOKEN_PROGRAM_ID,
1280
+ ASSOCIATED_TOKEN_PROGRAM_ID
1281
+ );
1282
+ remainingKeys.push({ pubkey: userVolumeAccumulatorWsolAta, isSigner: false, isWritable: true });
1283
+ }
1284
+ remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
1285
+
1235
1286
  return new TransactionInstruction({
1236
1287
  programId: PROGRAM_IDS.PUMP_AMM,
1237
1288
  keys: [
@@ -1258,7 +1309,7 @@ export class PumpTrader {
1258
1309
  { pubkey: userVolumeAccumulator, isSigner: false, isWritable: true },
1259
1310
  { pubkey: feeConfig, isSigner: false, isWritable: false },
1260
1311
  { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false },
1261
- { pubkey: poolV2, isSigner: false, isWritable: false }
1312
+ ...remainingKeys
1262
1313
  ],
1263
1314
  data: Buffer.concat([
1264
1315
  DISCRIMINATORS.BUY,
@@ -1312,6 +1363,28 @@ export class PumpTrader {
1312
1363
  ASSOCIATED_TOKEN_PROGRAM_ID
1313
1364
  );
1314
1365
 
1366
+ const [userVolumeAccumulator] = PublicKey.findProgramAddressSync(
1367
+ [Buffer.from("user_volume_accumulator"), this.wallet.publicKey.toBuffer()],
1368
+ PROGRAM_IDS.PUMP_AMM
1369
+ );
1370
+
1371
+ const userVolumeAccumulatorWsolAta = getAssociatedTokenAddressSync(
1372
+ SOL_MINT,
1373
+ userVolumeAccumulator,
1374
+ true,
1375
+ TOKEN_PROGRAM_ID,
1376
+ ASSOCIATED_TOKEN_PROGRAM_ID
1377
+ );
1378
+
1379
+ const remainingKeys = [];
1380
+ if (poolKeys.isCashbackCoin) {
1381
+ remainingKeys.push(
1382
+ { pubkey: userVolumeAccumulatorWsolAta, isSigner: false, isWritable: true },
1383
+ { pubkey: userVolumeAccumulator, isSigner: false, isWritable: true }
1384
+ );
1385
+ }
1386
+ remainingKeys.push({ pubkey: poolV2, isSigner: false, isWritable: false });
1387
+
1315
1388
  return new TransactionInstruction({
1316
1389
  programId: PROGRAM_IDS.PUMP_AMM,
1317
1390
  keys: [
@@ -1336,7 +1409,7 @@ export class PumpTrader {
1336
1409
  { pubkey: coinCreatorVaultAuthority, isSigner: false, isWritable: false },
1337
1410
  { pubkey: feeConfig, isSigner: false, isWritable: false },
1338
1411
  { pubkey: PROGRAM_IDS.FEE, isSigner: false, isWritable: false },
1339
- { pubkey: poolV2, isSigner: false, isWritable: false }
1412
+ ...remainingKeys
1340
1413
  ],
1341
1414
  data: Buffer.concat([
1342
1415
  DISCRIMINATORS.SELL,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pump-trader",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "PumpFun 交易库 - 自动判断 Token Program 和内盘/外盘",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",