@paul.lumberwork/bonding-curve-sdk 1.0.0

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.mjs ADDED
@@ -0,0 +1,544 @@
1
+ import { BN } from '@coral-xyz/anchor';
2
+ import { PublicKey, LAMPORTS_PER_SOL, SystemProgram, Keypair, SYSVAR_RENT_PUBKEY, ComputeBudgetProgram } from '@solana/web3.js';
3
+ import { getAssociatedTokenAddressSync, ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID, getAccount } from '@solana/spl-token';
4
+
5
+ // src/sdk/index.ts
6
+ var PROGRAM_ID = new PublicKey("6o7oTqg2CfvcMCJTLNEJsef7c875zGpTvcnFctNAjudL");
7
+ var ADMIN_WALLET = new PublicKey("7eGpbyRpcM7WpNKQtd6XkteNQWHbWXP7icZjKzNK2aTk");
8
+ var METADATA_PROGRAM_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");
9
+ var K_SCALE = 10000000000000000000000n;
10
+ var LAMPORTS = LAMPORTS_PER_SOL;
11
+ var TOKEN_DECIMALS = 6;
12
+ var FEE_BPS = 100;
13
+ var CURVE_PERCENT = 70;
14
+ var LP_PERCENT = 20;
15
+ var TREASURY_PERCENT = 10;
16
+ var PumpFunSDK = class {
17
+ constructor(program, wallet) {
18
+ this.program = program;
19
+ this.connection = program.provider.connection;
20
+ this.wallet = wallet;
21
+ [this.launchpadPda] = PublicKey.findProgramAddressSync(
22
+ [Buffer.from("launchpad")],
23
+ program.programId
24
+ );
25
+ }
26
+ // ═══════════════════════════════════════════════════════════════════════════
27
+ // PDA Derivation Helpers
28
+ // ═══════════════════════════════════════════════════════════════════════════
29
+ deriveAddresses(mint) {
30
+ const [tokenLaunch] = PublicKey.findProgramAddressSync(
31
+ [Buffer.from("token_launch"), mint.toBuffer()],
32
+ this.program.programId
33
+ );
34
+ const [bondingCurve] = PublicKey.findProgramAddressSync(
35
+ [Buffer.from("bonding_curve"), tokenLaunch.toBuffer()],
36
+ this.program.programId
37
+ );
38
+ const [vault] = PublicKey.findProgramAddressSync(
39
+ [Buffer.from("vault"), tokenLaunch.toBuffer()],
40
+ this.program.programId
41
+ );
42
+ const curveTokenAccount = getAssociatedTokenAddressSync(mint, bondingCurve, true);
43
+ const [metadata] = PublicKey.findProgramAddressSync(
44
+ [Buffer.from("metadata"), METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer()],
45
+ METADATA_PROGRAM_ID
46
+ );
47
+ return { mint, tokenLaunch, bondingCurve, vault, curveTokenAccount, metadata };
48
+ }
49
+ deriveUserPosition(tokenLaunch, user) {
50
+ const [userPosition] = PublicKey.findProgramAddressSync(
51
+ [Buffer.from("user_position"), tokenLaunch.toBuffer(), user.toBuffer()],
52
+ this.program.programId
53
+ );
54
+ return userPosition;
55
+ }
56
+ // ═══════════════════════════════════════════════════════════════════════════
57
+ // Initialize Launchpad (one-time setup)
58
+ // ═══════════════════════════════════════════════════════════════════════════
59
+ async initializeLaunchpad(platformFeeBps = 200) {
60
+ try {
61
+ await this.program.account.launchpad.fetch(this.launchpadPda);
62
+ return "already_initialized";
63
+ } catch {
64
+ const tx = await this.program.methods.initializeLaunchpad(platformFeeBps).accountsPartial({
65
+ authority: this.wallet.publicKey,
66
+ launchpad: this.launchpadPda,
67
+ treasury: this.wallet.publicKey,
68
+ systemProgram: SystemProgram.programId
69
+ }).rpc();
70
+ return tx;
71
+ }
72
+ }
73
+ // ═══════════════════════════════════════════════════════════════════════════
74
+ // Create Token Launch
75
+ // ═══════════════════════════════════════════════════════════════════════════
76
+ async createTokenLaunch(config) {
77
+ const mintKeypair = Keypair.generate();
78
+ const addresses = this.deriveAddresses(mintKeypair.publicKey);
79
+ const creatorWallet = config.creatorWallet || this.wallet.publicKey;
80
+ const totalSupplyRaw = new BN(config.totalSupply).mul(new BN(10 ** TOKEN_DECIMALS));
81
+ const kValue = new BN(config.k);
82
+ const tx = await this.program.methods.createTokenLaunch(config.name, config.symbol, config.uri, totalSupplyRaw, kValue).accountsPartial({
83
+ creator: creatorWallet,
84
+ launchpad: this.launchpadPda,
85
+ mint: mintKeypair.publicKey,
86
+ tokenLaunch: addresses.tokenLaunch,
87
+ bondingCurve: addresses.bondingCurve,
88
+ vault: addresses.vault,
89
+ curveTokenAccount: addresses.curveTokenAccount,
90
+ metadata: addresses.metadata,
91
+ tokenProgram: TOKEN_PROGRAM_ID,
92
+ associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
93
+ metadataProgram: METADATA_PROGRAM_ID,
94
+ systemProgram: SystemProgram.programId,
95
+ rent: SYSVAR_RENT_PUBKEY
96
+ }).signers([mintKeypair]).transaction();
97
+ const { blockhash } = await this.connection.getLatestBlockhash();
98
+ tx.recentBlockhash = blockhash;
99
+ tx.feePayer = this.wallet.publicKey;
100
+ tx.partialSign(mintKeypair);
101
+ const signedTx = await this.wallet.signTransaction(tx);
102
+ const txSignature = await this.connection.sendRawTransaction(signedTx.serialize(), {
103
+ skipPreflight: true
104
+ });
105
+ await this.connection.confirmTransaction({
106
+ signature: txSignature,
107
+ ...await this.connection.getLatestBlockhash()
108
+ });
109
+ return { txSignature, addresses, mintKeypair };
110
+ }
111
+ // ═══════════════════════════════════════════════════════════════════════════
112
+ // Buy Tokens
113
+ // ═══════════════════════════════════════════════════════════════════════════
114
+ async buy(mint, solAmount, options) {
115
+ const addresses = this.deriveAddresses(mint);
116
+ const userTokenAccount = getAssociatedTokenAddressSync(mint, this.wallet.publicKey);
117
+ const userPosition = this.deriveUserPosition(addresses.tokenLaunch, this.wallet.publicKey);
118
+ await this.program.account.bondingCurve.fetch(addresses.bondingCurve);
119
+ let tokensBefore = 0n;
120
+ try {
121
+ const account = await getAccount(this.connection, userTokenAccount);
122
+ tokensBefore = account.amount;
123
+ } catch {
124
+ }
125
+ const solLamports = new BN(Math.floor(solAmount * LAMPORTS_PER_SOL));
126
+ const preInstructions = [];
127
+ if (options?.computeUnits) {
128
+ preInstructions.push(
129
+ ComputeBudgetProgram.setComputeUnitLimit({ units: options.computeUnits })
130
+ );
131
+ }
132
+ const tx = await this.program.methods.buyTokens(solLamports).accountsPartial({
133
+ contributor: this.wallet.publicKey,
134
+ launchpad: this.launchpadPda,
135
+ adminWallet: ADMIN_WALLET,
136
+ tokenLaunch: addresses.tokenLaunch,
137
+ bondingCurve: addresses.bondingCurve,
138
+ mint,
139
+ vault: addresses.vault,
140
+ curveTokenAccount: addresses.curveTokenAccount,
141
+ userTokenAccount,
142
+ userPosition,
143
+ systemProgram: SystemProgram.programId,
144
+ tokenProgram: TOKEN_PROGRAM_ID,
145
+ associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID
146
+ }).preInstructions(preInstructions).rpc();
147
+ const curveAfter = await this.program.account.bondingCurve.fetch(addresses.bondingCurve);
148
+ const tokensAfter = (await getAccount(this.connection, userTokenAccount)).amount;
149
+ const tokensReceived = tokensAfter - tokensBefore;
150
+ const progress = Number(curveAfter.soldSupply.toString()) / Number(curveAfter.tokensForCurve.toString()) * 100;
151
+ return {
152
+ txSignature: tx,
153
+ tokensTraded: tokensReceived,
154
+ solTraded: BigInt(solLamports.toString()),
155
+ newProgress: progress,
156
+ isCurveComplete: curveAfter.complete
157
+ };
158
+ }
159
+ // ═══════════════════════════════════════════════════════════════════════════
160
+ // Sell Tokens
161
+ // ═══════════════════════════════════════════════════════════════════════════
162
+ async sell(mint, tokenAmount, minSolOut = 0, options) {
163
+ const addresses = this.deriveAddresses(mint);
164
+ const userTokenAccount = getAssociatedTokenAddressSync(mint, this.wallet.publicKey);
165
+ const userPosition = this.deriveUserPosition(addresses.tokenLaunch, this.wallet.publicKey);
166
+ await this.program.account.bondingCurve.fetch(addresses.bondingCurve);
167
+ const walletBefore = await this.connection.getBalance(this.wallet.publicKey);
168
+ const tokensRaw = new BN(tokenAmount).mul(new BN(10 ** TOKEN_DECIMALS));
169
+ const minSolLamports = new BN(Math.floor(minSolOut * LAMPORTS_PER_SOL));
170
+ const preInstructions = [];
171
+ if (options?.computeUnits) {
172
+ preInstructions.push(
173
+ ComputeBudgetProgram.setComputeUnitLimit({ units: options.computeUnits })
174
+ );
175
+ }
176
+ const tx = await this.program.methods.sellTokens(tokensRaw, minSolLamports).accountsPartial({
177
+ contributor: this.wallet.publicKey,
178
+ launchpad: this.launchpadPda,
179
+ adminWallet: ADMIN_WALLET,
180
+ tokenLaunch: addresses.tokenLaunch,
181
+ bondingCurve: addresses.bondingCurve,
182
+ mint,
183
+ vault: addresses.vault,
184
+ curveTokenAccount: addresses.curveTokenAccount,
185
+ userTokenAccount,
186
+ userPosition,
187
+ systemProgram: SystemProgram.programId,
188
+ tokenProgram: TOKEN_PROGRAM_ID
189
+ }).preInstructions(preInstructions).rpc();
190
+ const curveAfter = await this.program.account.bondingCurve.fetch(addresses.bondingCurve);
191
+ const walletAfter = await this.connection.getBalance(this.wallet.publicKey);
192
+ const solReceived = BigInt(walletAfter - walletBefore);
193
+ const progress = Number(curveAfter.soldSupply.toString()) / Number(curveAfter.tokensForCurve.toString()) * 100;
194
+ return {
195
+ txSignature: tx,
196
+ tokensTraded: BigInt(tokensRaw.toString()),
197
+ solTraded: solReceived,
198
+ newProgress: progress,
199
+ isCurveComplete: curveAfter.complete
200
+ };
201
+ }
202
+ // ═══════════════════════════════════════════════════════════════════════════
203
+ // Admin Withdraw
204
+ // ═══════════════════════════════════════════════════════════════════════════
205
+ async adminWithdraw(mint) {
206
+ const addresses = this.deriveAddresses(mint);
207
+ const adminTokenAccount = getAssociatedTokenAddressSync(mint, this.wallet.publicKey);
208
+ const launchpad = await this.program.account.launchpad.fetch(this.launchpadPda);
209
+ const treasuryWallet = launchpad.treasury;
210
+ const treasuryTokenAccount = getAssociatedTokenAddressSync(mint, treasuryWallet, true);
211
+ const curve = await this.program.account.bondingCurve.fetch(addresses.bondingCurve);
212
+ const lpSol = BigInt(curve.realSolReserves.toString());
213
+ const lpTokens = BigInt(curve.tokenReservesForLp.toString());
214
+ const accumulatedFees = BigInt(curve.accumulatedFees.toString());
215
+ const treasuryTokensAmount = BigInt(curve.tokenReservesForTreasury.toString());
216
+ const tx = await this.program.methods.adminWithdraw().accountsPartial({
217
+ admin: this.wallet.publicKey,
218
+ launchpad: this.launchpadPda,
219
+ tokenLaunch: addresses.tokenLaunch,
220
+ bondingCurve: addresses.bondingCurve,
221
+ mint,
222
+ vault: addresses.vault,
223
+ curveTokenAccount: addresses.curveTokenAccount,
224
+ adminTokenAccount,
225
+ treasuryWallet,
226
+ treasuryTokenAccount,
227
+ systemProgram: SystemProgram.programId,
228
+ tokenProgram: TOKEN_PROGRAM_ID,
229
+ associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID
230
+ }).rpc();
231
+ return {
232
+ txSignature: tx,
233
+ solWithdrawn: lpSol,
234
+ tokensWithdrawn: lpTokens,
235
+ feesToTreasury: accumulatedFees,
236
+ treasuryTokens: treasuryTokensAmount
237
+ };
238
+ }
239
+ // ═══════════════════════════════════════════════════════════════════════════
240
+ // Estimate Buy (tokens received for SOL)
241
+ // ═══════════════════════════════════════════════════════════════════════════
242
+ async estimateBuy(mint, solAmount) {
243
+ const addresses = this.deriveAddresses(mint);
244
+ const curve = await this.program.account.bondingCurve.fetch(addresses.bondingCurve);
245
+ const k = BigInt(curve.k.toString());
246
+ const soldSupply = BigInt(curve.soldSupply.toString());
247
+ const tokensForCurve = BigInt(curve.tokensForCurve.toString());
248
+ const solLamports = BigInt(Math.floor(solAmount * LAMPORTS_PER_SOL));
249
+ const feeAmount = solLamports / 100n;
250
+ const solAfterFees = solLamports - feeAmount;
251
+ const tokensOut = this.calculateTokensForSol(k, soldSupply, solAfterFees);
252
+ const available = tokensForCurve - soldSupply;
253
+ const actualTokensOut = tokensOut > available ? available : tokensOut;
254
+ const pricePerToken = solAfterFees / (actualTokensOut / BigInt(10 ** TOKEN_DECIMALS));
255
+ const newSoldSupply = soldSupply + actualTokensOut;
256
+ const priceBefore = this.calculatePrice(k, soldSupply);
257
+ const priceAfter = this.calculatePrice(k, newSoldSupply);
258
+ const priceImpactBps = priceBefore > 0n ? Number((priceAfter - priceBefore) * 10000n / priceBefore) : 0;
259
+ return {
260
+ tokensOut: actualTokensOut,
261
+ solCost: solLamports,
262
+ pricePerToken,
263
+ priceImpactBps,
264
+ feeAmount
265
+ };
266
+ }
267
+ // ═══════════════════════════════════════════════════════════════════════════
268
+ // Estimate Sell (SOL received for tokens)
269
+ // ═══════════════════════════════════════════════════════════════════════════
270
+ async estimateSell(mint, tokenAmount) {
271
+ const addresses = this.deriveAddresses(mint);
272
+ const curve = await this.program.account.bondingCurve.fetch(addresses.bondingCurve);
273
+ const k = BigInt(curve.k.toString());
274
+ const soldSupply = BigInt(curve.soldSupply.toString());
275
+ const realSolReserves = BigInt(curve.realSolReserves.toString());
276
+ const tokensRaw = BigInt(tokenAmount) * BigInt(10 ** TOKEN_DECIMALS);
277
+ if (tokensRaw > soldSupply) {
278
+ throw new Error(`Cannot sell ${tokenAmount} tokens. Only ${soldSupply / BigInt(10 ** TOKEN_DECIMALS)} available.`);
279
+ }
280
+ const grossRefund = this.calculateRefund(k, soldSupply, soldSupply - tokensRaw);
281
+ const cappedRefund = grossRefund > realSolReserves ? realSolReserves : grossRefund;
282
+ const feeAmount = cappedRefund / 100n;
283
+ const netSolOut = cappedRefund - feeAmount;
284
+ const pricePerToken = netSolOut / BigInt(tokenAmount);
285
+ const newSoldSupply = soldSupply - tokensRaw;
286
+ const priceBefore = this.calculatePrice(k, soldSupply);
287
+ const priceAfter = this.calculatePrice(k, newSoldSupply);
288
+ const priceImpactBps = priceBefore > 0n ? Number((priceBefore - priceAfter) * 10000n / priceBefore) : 0;
289
+ return {
290
+ tokensOut: tokensRaw,
291
+ // tokens being sold
292
+ solCost: netSolOut,
293
+ // SOL to receive
294
+ pricePerToken,
295
+ priceImpactBps,
296
+ feeAmount
297
+ };
298
+ }
299
+ // ═══════════════════════════════════════════════════════════════════════════
300
+ // Get Curve State
301
+ // ═══════════════════════════════════════════════════════════════════════════
302
+ async getCurveState(mint) {
303
+ const addresses = this.deriveAddresses(mint);
304
+ const curve = await this.program.account.bondingCurve.fetch(addresses.bondingCurve);
305
+ return {
306
+ tokenLaunch: curve.tokenLaunch,
307
+ k: BigInt(curve.k.toString()),
308
+ totalSupply: BigInt(curve.totalSupply.toString()),
309
+ soldSupply: BigInt(curve.soldSupply.toString()),
310
+ realSolReserves: BigInt(curve.realSolReserves.toString()),
311
+ tokenReservesForLp: BigInt(curve.tokenReservesForLp.toString()),
312
+ tokenReservesForTreasury: BigInt(curve.tokenReservesForTreasury.toString()),
313
+ tokensForCurve: BigInt(curve.tokensForCurve.toString()),
314
+ accumulatedFees: BigInt(curve.accumulatedFees.toString()),
315
+ complete: curve.complete,
316
+ bump: curve.bump
317
+ };
318
+ }
319
+ // ═══════════════════════════════════════════════════════════════════════════
320
+ // Get Token Launch State
321
+ // ═══════════════════════════════════════════════════════════════════════════
322
+ async getTokenLaunchState(mint) {
323
+ const addresses = this.deriveAddresses(mint);
324
+ const launch = await this.program.account.tokenLaunch.fetch(addresses.tokenLaunch);
325
+ return {
326
+ creator: launch.creator,
327
+ mint: launch.mint,
328
+ vault: launch.vault,
329
+ bondingCurve: launch.bondingCurve,
330
+ totalSupply: BigInt(launch.totalSupply.toString()),
331
+ curveAllocation: BigInt(launch.curveAllocation.toString()),
332
+ lpAllocation: BigInt(launch.lpAllocation.toString()),
333
+ treasuryAllocation: BigInt(launch.treasuryAllocation.toString()),
334
+ totalSolRaised: BigInt(launch.totalSolRaised.toString()),
335
+ tradingActive: launch.tradingActive,
336
+ migrated: launch.migrated,
337
+ initialK: BigInt(launch.initialK.toString()),
338
+ name: launch.name,
339
+ symbol: launch.symbol
340
+ };
341
+ }
342
+ // ═══════════════════════════════════════════════════════════════════════════
343
+ // Get Progress
344
+ // ═══════════════════════════════════════════════════════════════════════════
345
+ async getProgress(mint) {
346
+ const curve = await this.getCurveState(mint);
347
+ const percent = Number(curve.soldSupply * 100n / curve.tokensForCurve);
348
+ const currentPrice = this.calculatePrice(curve.k, curve.soldSupply);
349
+ return {
350
+ percent,
351
+ soldSupply: curve.soldSupply,
352
+ tokensForCurve: curve.tokensForCurve,
353
+ solRaised: curve.realSolReserves,
354
+ currentPrice,
355
+ isComplete: curve.complete
356
+ };
357
+ }
358
+ // ═══════════════════════════════════════════════════════════════════════════
359
+ // Event Listeners
360
+ // ═══════════════════════════════════════════════════════════════════════════
361
+ /**
362
+ * Listen for LaunchCreated events
363
+ * @param callback Function to call when event is emitted
364
+ * @returns Listener ID for removal
365
+ */
366
+ onLaunchCreated(callback) {
367
+ return this.program.addEventListener("launchCreated", (event, slot, signature) => {
368
+ callback({
369
+ tokenLaunch: event.tokenLaunch,
370
+ mint: event.mint,
371
+ creator: event.creator,
372
+ name: event.name,
373
+ symbol: event.symbol,
374
+ totalSupply: BigInt(event.totalSupply.toString()),
375
+ curveAllocation: BigInt(event.curveAllocation.toString()),
376
+ lpAllocation: BigInt(event.lpAllocation.toString()),
377
+ treasuryAllocation: BigInt(event.treasuryAllocation.toString()),
378
+ initialK: BigInt(event.initialK.toString()),
379
+ initialPrice: BigInt(event.initialPrice.toString()),
380
+ timestamp: BigInt(event.timestamp.toString())
381
+ }, slot, signature);
382
+ });
383
+ }
384
+ /**
385
+ * Listen for TokensPurchased events
386
+ * @param callback Function to call when event is emitted
387
+ * @returns Listener ID for removal
388
+ */
389
+ onTokensPurchased(callback) {
390
+ return this.program.addEventListener("tokensPurchased", (event, slot, signature) => {
391
+ callback({
392
+ tokenLaunch: event.tokenLaunch,
393
+ mint: event.mint,
394
+ buyer: event.buyer,
395
+ solAmount: BigInt(event.solAmount.toString()),
396
+ solAfterFees: BigInt(event.solAfterFees.toString()),
397
+ tokensReceived: BigInt(event.tokensReceived.toString()),
398
+ curveFee: BigInt(event.curveFee.toString()),
399
+ adminFee: BigInt(event.adminFee.toString()),
400
+ priceAfter: BigInt(event.priceAfter.toString()),
401
+ totalSold: BigInt(event.totalSold.toString()),
402
+ progress: event.progress,
403
+ timestamp: BigInt(event.timestamp.toString()),
404
+ isCurveComplete: event.isCurveComplete
405
+ }, slot, signature);
406
+ });
407
+ }
408
+ /**
409
+ * Listen for TokensSold events
410
+ * @param callback Function to call when event is emitted
411
+ * @returns Listener ID for removal
412
+ */
413
+ onTokensSold(callback) {
414
+ return this.program.addEventListener("tokensSold", (event, slot, signature) => {
415
+ callback({
416
+ tokenLaunch: event.tokenLaunch,
417
+ mint: event.mint,
418
+ seller: event.seller,
419
+ tokensSold: BigInt(event.tokensSold.toString()),
420
+ grossSolRefund: BigInt(event.grossSolRefund.toString()),
421
+ netSolRefund: BigInt(event.netSolRefund.toString()),
422
+ curveFee: BigInt(event.curveFee.toString()),
423
+ adminFee: BigInt(event.adminFee.toString()),
424
+ priceAfter: BigInt(event.priceAfter.toString()),
425
+ totalSold: BigInt(event.totalSold.toString()),
426
+ progress: event.progress,
427
+ timestamp: BigInt(event.timestamp.toString())
428
+ }, slot, signature);
429
+ });
430
+ }
431
+ /**
432
+ * Listen for CurveComplete events
433
+ * @param callback Function to call when event is emitted
434
+ * @returns Listener ID for removal
435
+ */
436
+ onCurveComplete(callback) {
437
+ return this.program.addEventListener("curveComplete", (event, slot, signature) => {
438
+ callback({
439
+ tokenLaunch: event.tokenLaunch,
440
+ mint: event.mint,
441
+ totalSolRaised: BigInt(event.totalSolRaised.toString()),
442
+ finalPrice: BigInt(event.finalPrice.toString()),
443
+ timestamp: BigInt(event.timestamp.toString())
444
+ }, slot, signature);
445
+ });
446
+ }
447
+ /**
448
+ * Listen for AdminWithdraw events
449
+ * @param callback Function to call when event is emitted
450
+ * @returns Listener ID for removal
451
+ */
452
+ onAdminWithdraw(callback) {
453
+ return this.program.addEventListener("adminWithdraw", (event, slot, signature) => {
454
+ callback({
455
+ tokenLaunch: event.tokenLaunch,
456
+ mint: event.mint,
457
+ admin: event.admin,
458
+ creator: event.creator,
459
+ treasury: event.treasury,
460
+ solWithdrawn: BigInt(event.solWithdrawn.toString()),
461
+ tokensWithdrawn: BigInt(event.tokensWithdrawn.toString()),
462
+ feesToTreasury: BigInt(event.feesToTreasury.toString()),
463
+ treasuryTokens: BigInt(event.treasuryTokens.toString()),
464
+ timestamp: BigInt(event.timestamp.toString())
465
+ }, slot, signature);
466
+ });
467
+ }
468
+ /**
469
+ * Remove an event listener
470
+ * @param listenerId The ID returned from addEventListener
471
+ */
472
+ async removeEventListener(listenerId) {
473
+ await this.program.removeEventListener(listenerId);
474
+ }
475
+ // ═══════════════════════════════════════════════════════════════════════════
476
+ // Math Helpers (Pure functions, no async)
477
+ // ═══════════════════════════════════════════════════════════════════════════
478
+ /** Calculate price at a given supply: price = k × supply / K_SCALE */
479
+ calculatePrice(k, supply) {
480
+ if (supply === 0n) return 0n;
481
+ return k * supply / K_SCALE;
482
+ }
483
+ /** Calculate cost to buy from s1 to s2: cost = (k/2) × (s2² - s1²) / K_SCALE */
484
+ calculateCost(k, s1, s2) {
485
+ if (s2 <= s1) return 0n;
486
+ const s1Sq = s1 * s1;
487
+ const s2Sq = s2 * s2;
488
+ const diffSq = s2Sq - s1Sq;
489
+ return k * diffSq / 2n / K_SCALE;
490
+ }
491
+ /** Calculate tokens received for SOL: s2 = sqrt(s1² + 2×sol×K_SCALE/k) */
492
+ calculateTokensForSol(k, currentSupply, solIn) {
493
+ if (solIn === 0n || k === 0n) return 0n;
494
+ const s1Sq = currentSupply * currentSupply;
495
+ const addition = 2n * solIn * K_SCALE / k;
496
+ const s2Sq = s1Sq + addition;
497
+ const s2 = this.isqrt(s2Sq);
498
+ return s2 - currentSupply;
499
+ }
500
+ /** Calculate refund for selling tokens: refund = (k/2) × (s1² - s2²) / K_SCALE */
501
+ calculateRefund(k, s1, s2) {
502
+ if (s1 <= s2) return 0n;
503
+ const s1Sq = s1 * s1;
504
+ const s2Sq = s2 * s2;
505
+ const diffSq = s1Sq - s2Sq;
506
+ return k * diffSq / 2n / K_SCALE;
507
+ }
508
+ /** Integer square root using Newton's method */
509
+ isqrt(n) {
510
+ if (n === 0n) return 0n;
511
+ if (n === 1n) return 1n;
512
+ let x = n;
513
+ let y = (x + 1n) / 2n;
514
+ while (y < x) {
515
+ x = y;
516
+ y = (x + n / x) / 2n;
517
+ }
518
+ return x;
519
+ }
520
+ /** Calculate K for a given target SOL and curve supply */
521
+ static calculateK(curveSupply, targetSol) {
522
+ const numerator = 2n * targetSol * K_SCALE;
523
+ const denominator = curveSupply * curveSupply;
524
+ return numerator / denominator;
525
+ }
526
+ };
527
+ function formatTokens(raw) {
528
+ const tokens = Number(raw) / 10 ** TOKEN_DECIMALS;
529
+ return tokens.toLocaleString(void 0, { maximumFractionDigits: 2 });
530
+ }
531
+ function formatSol(lamports) {
532
+ const sol = Number(lamports) / LAMPORTS_PER_SOL;
533
+ return sol.toFixed(4);
534
+ }
535
+ function parseSol(sol) {
536
+ return BigInt(Math.floor(sol * LAMPORTS_PER_SOL));
537
+ }
538
+ function parseTokens(tokens) {
539
+ return BigInt(Math.floor(tokens * 10 ** TOKEN_DECIMALS));
540
+ }
541
+
542
+ export { ADMIN_WALLET, CURVE_PERCENT, FEE_BPS, K_SCALE, LAMPORTS, LP_PERCENT, METADATA_PROGRAM_ID, PROGRAM_ID, PumpFunSDK, TOKEN_DECIMALS, TREASURY_PERCENT, formatSol, formatTokens, parseSol, parseTokens };
543
+ //# sourceMappingURL=index.mjs.map
544
+ //# sourceMappingURL=index.mjs.map