@paul.lumberwork/bonding-curve-sdk 1.3.0 → 1.5.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/README.md +140 -112
- package/dist/index.d.mts +20 -6
- package/dist/index.d.ts +20 -6
- package/dist/index.js +78 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +78 -31
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Kick.fun SDK
|
|
2
2
|
|
|
3
|
-
Solana program with Linear Bonding Curve for token launches
|
|
3
|
+
Solana program with Linear Bonding Curve for token launches. SDK package: `@paul.lumberwork/bonding-curve-sdk`
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
@@ -12,22 +12,23 @@ Solana program with Linear Bonding Curve for token launches, similar to pump.fun
|
|
|
12
12
|
|
|
13
13
|
| Allocation | Percent | Description |
|
|
14
14
|
|------------|---------|-------------|
|
|
15
|
-
| Bonding Curve |
|
|
15
|
+
| Bonding Curve | 70% | Available for trading |
|
|
16
16
|
| LP Reserve | 20% | Reserved for DEX migration |
|
|
17
|
+
| Treasury | 10% | Platform treasury |
|
|
17
18
|
|
|
18
19
|
## Trading Fees (Hardcoded)
|
|
19
20
|
|
|
20
21
|
| Fee | Percent | Recipient |
|
|
21
22
|
|-----|---------|-----------|
|
|
22
|
-
|
|
|
23
|
-
| Admin Fee | 0.5% | Platform admin |
|
|
23
|
+
| Accumulated Fee | 0.5% | Accumulated in curve (withdrawn by admin) |
|
|
24
|
+
| Admin Fee | 0.5% | Platform admin (immediate) |
|
|
24
25
|
| **Total** | **1%** | |
|
|
25
26
|
|
|
26
27
|
## Bonding Curve Formula
|
|
27
28
|
|
|
28
29
|
```
|
|
29
|
-
Price = K
|
|
30
|
-
Cost = K
|
|
30
|
+
Price = K x sold_supply
|
|
31
|
+
Cost = K x (s2² - s1²) / 2 / K_SCALE
|
|
31
32
|
```
|
|
32
33
|
|
|
33
34
|
Where `K_SCALE = 10^22`
|
|
@@ -41,7 +42,9 @@ Where `K_SCALE = 10^22`
|
|
|
41
42
|
| 2156 | ~69 SOL | pump.fun style |
|
|
42
43
|
| 3125 | ~100 SOL | Large launch |
|
|
43
44
|
|
|
44
|
-
**Formula**: `Target SOL
|
|
45
|
+
**Formula**: `Target SOL = K x 0.032`
|
|
46
|
+
|
|
47
|
+
> **Note:** `total_supply` and `k` are configured by admin in the Launchpad contract. Creators do not set these values.
|
|
45
48
|
|
|
46
49
|
---
|
|
47
50
|
|
|
@@ -50,7 +53,7 @@ Where `K_SCALE = 10^22`
|
|
|
50
53
|
### Installation
|
|
51
54
|
|
|
52
55
|
```bash
|
|
53
|
-
npm install
|
|
56
|
+
npm install @paul.lumberwork/bonding-curve-sdk
|
|
54
57
|
```
|
|
55
58
|
|
|
56
59
|
### Setup
|
|
@@ -59,8 +62,8 @@ npm install github:lumberworks/kickdotfun-contracts-sdk
|
|
|
59
62
|
import * as anchor from "@coral-xyz/anchor";
|
|
60
63
|
import { Program } from "@coral-xyz/anchor";
|
|
61
64
|
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
|
|
62
|
-
import {
|
|
63
|
-
import idl from "
|
|
65
|
+
import { KickFunSDK, formatTokens, formatSol, PROGRAM_ID } from "@paul.lumberwork/bonding-curve-sdk";
|
|
66
|
+
import idl from "@paul.lumberwork/bonding-curve-sdk/idl/kick_fun_program.json";
|
|
64
67
|
|
|
65
68
|
// Setup connection and wallet
|
|
66
69
|
const connection = new Connection("https://api.devnet.solana.com", "confirmed");
|
|
@@ -71,10 +74,10 @@ const provider = new anchor.AnchorProvider(connection, wallet, { commitment: "co
|
|
|
71
74
|
const program = new Program(idl as anchor.Idl, provider);
|
|
72
75
|
|
|
73
76
|
// Create SDK instance
|
|
74
|
-
const sdk = new
|
|
77
|
+
const sdk = new KickFunSDK(program, wallet);
|
|
75
78
|
```
|
|
76
79
|
|
|
77
|
-
### 1. Initialize Launchpad (one-time)
|
|
80
|
+
### 1. Initialize Launchpad (one-time, admin only)
|
|
78
81
|
|
|
79
82
|
```typescript
|
|
80
83
|
const result = await sdk.initializeLaunchpad();
|
|
@@ -83,14 +86,11 @@ const result = await sdk.initializeLaunchpad();
|
|
|
83
86
|
|
|
84
87
|
### 2. Create Token Launch
|
|
85
88
|
|
|
86
|
-
**Default (creator = transaction signer):**
|
|
87
89
|
```typescript
|
|
88
90
|
const { txSignature, addresses, mintKeypair } = await sdk.createTokenLaunch({
|
|
89
91
|
name: "My Token",
|
|
90
92
|
symbol: "MTK",
|
|
91
93
|
uri: "https://example.com/metadata.json",
|
|
92
|
-
totalSupply: 1_000_000_000, // 1B tokens
|
|
93
|
-
k: 60, // ~2 SOL target
|
|
94
94
|
});
|
|
95
95
|
|
|
96
96
|
const mint = mintKeypair.publicKey;
|
|
@@ -100,38 +100,29 @@ console.log("Token Launch PDA:", addresses.tokenLaunch.toString());
|
|
|
100
100
|
|
|
101
101
|
**With Custom Creator Wallet:**
|
|
102
102
|
```typescript
|
|
103
|
-
import { PublicKey } from "@solana/web3.js";
|
|
104
|
-
|
|
105
|
-
const customCreator = new PublicKey("YourCreatorWalletAddress...");
|
|
106
|
-
|
|
107
103
|
const { txSignature, addresses, mintKeypair } = await sdk.createTokenLaunch({
|
|
108
104
|
name: "My Token",
|
|
109
105
|
symbol: "MTK",
|
|
110
106
|
uri: "https://example.com/metadata.json",
|
|
111
|
-
|
|
112
|
-
k: 60,
|
|
113
|
-
creatorWallet: customCreator, // Optional: receives 0.5% trading fees
|
|
107
|
+
creatorWallet: new PublicKey("YourCreatorWalletAddress..."),
|
|
114
108
|
});
|
|
115
109
|
```
|
|
116
110
|
|
|
117
111
|
**Parameters:**
|
|
118
112
|
- `name`: Token name
|
|
119
113
|
- `symbol`: Token symbol
|
|
120
|
-
- `uri`: Metadata URI
|
|
121
|
-
- `
|
|
122
|
-
- `k`: K value for bonding curve
|
|
123
|
-
- `creatorWallet`: (Optional) Custom creator wallet to receive trading fees. Defaults to SDK wallet if not provided.
|
|
114
|
+
- `uri`: Metadata URI (Metaplex standard)
|
|
115
|
+
- `creatorWallet`: (Optional) Custom creator wallet. Defaults to SDK wallet.
|
|
124
116
|
|
|
125
117
|
**Returns:**
|
|
126
118
|
- `txSignature`: Transaction hash
|
|
127
|
-
- `addresses.mint`: Token mint address
|
|
128
119
|
- `addresses.tokenLaunch`: Token launch PDA
|
|
129
120
|
- `addresses.bondingCurve`: Bonding curve PDA
|
|
130
121
|
- `addresses.vault`: SOL vault PDA
|
|
122
|
+
- `addresses.curveTokenAccount`: Token account for curve
|
|
123
|
+
- `addresses.metadata`: Metaplex metadata PDA
|
|
131
124
|
- `mintKeypair`: Keypair of the new token
|
|
132
125
|
|
|
133
|
-
**Note:** The creator wallet will receive 0.5% of all trading fees (buy/sell). Use `creatorWallet` parameter if you want fees to go to a different address than the transaction signer.
|
|
134
|
-
|
|
135
126
|
### 3. Buy Tokens
|
|
136
127
|
|
|
137
128
|
```typescript
|
|
@@ -140,7 +131,6 @@ const result = await sdk.buy(mint, 0.5, { computeUnits: 400_000 });
|
|
|
140
131
|
console.log("Tokens received:", formatTokens(result.tokensTraded));
|
|
141
132
|
console.log("Progress:", result.newProgress.toFixed(2) + "%");
|
|
142
133
|
console.log("Curve complete:", result.isCurveComplete);
|
|
143
|
-
console.log("Tx:", result.txSignature);
|
|
144
134
|
```
|
|
145
135
|
|
|
146
136
|
**Parameters:**
|
|
@@ -148,13 +138,6 @@ console.log("Tx:", result.txSignature);
|
|
|
148
138
|
- `solAmount`: SOL to spend (number, e.g., 0.5 for 0.5 SOL)
|
|
149
139
|
- `options.computeUnits`: Optional compute budget (default: none)
|
|
150
140
|
|
|
151
|
-
**Returns:**
|
|
152
|
-
- `txSignature`: Transaction hash
|
|
153
|
-
- `tokensTraded`: Tokens received (bigint, raw with 6 decimals)
|
|
154
|
-
- `solTraded`: SOL spent (bigint, lamports)
|
|
155
|
-
- `newProgress`: Progress percentage (0-100)
|
|
156
|
-
- `isCurveComplete`: True if 80% sold
|
|
157
|
-
|
|
158
141
|
### 4. Sell Tokens
|
|
159
142
|
|
|
160
143
|
```typescript
|
|
@@ -170,26 +153,52 @@ console.log("Progress:", result.newProgress.toFixed(2) + "%");
|
|
|
170
153
|
- `minSolOut`: Minimum SOL to receive, slippage protection (default: 0)
|
|
171
154
|
- `options.computeUnits`: Optional compute budget
|
|
172
155
|
|
|
173
|
-
### 5. Estimate Buy
|
|
156
|
+
### 5. Estimate Buy (SOL -> Tokens)
|
|
174
157
|
|
|
175
158
|
```typescript
|
|
176
159
|
const estimate = await sdk.estimateBuy(mint, 0.5);
|
|
177
160
|
|
|
178
161
|
console.log("Tokens out:", formatTokens(estimate.tokensOut));
|
|
179
|
-
console.log("
|
|
162
|
+
console.log("SOL in (total):", formatSol(estimate.solIn));
|
|
163
|
+
console.log("SOL after fee:", formatSol(estimate.solAfterFee));
|
|
164
|
+
console.log("Fee:", formatSol(estimate.fee));
|
|
180
165
|
console.log("Price impact:", estimate.priceImpactBps, "bps");
|
|
181
166
|
```
|
|
182
167
|
|
|
183
|
-
### 6. Estimate
|
|
168
|
+
### 6. Estimate Buy by Tokens (Tokens -> SOL needed)
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
const estimate = await sdk.estimateBuyByTokens(mint, 1_000_000); // 1M tokens
|
|
172
|
+
|
|
173
|
+
console.log("SOL needed:", formatSol(estimate.solIn));
|
|
174
|
+
console.log("SOL to curve:", formatSol(estimate.solAfterFee));
|
|
175
|
+
console.log("Fee:", formatSol(estimate.fee));
|
|
176
|
+
console.log("Tokens out:", formatTokens(estimate.tokensOut));
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### 7. Estimate Sell (Tokens -> SOL)
|
|
184
180
|
|
|
185
181
|
```typescript
|
|
186
182
|
const estimate = await sdk.estimateSell(mint, 10_000_000);
|
|
187
183
|
|
|
188
|
-
console.log("SOL
|
|
189
|
-
console.log("
|
|
184
|
+
console.log("SOL before fee:", formatSol(estimate.solBeforeFee));
|
|
185
|
+
console.log("SOL out (net):", formatSol(estimate.solOut));
|
|
186
|
+
console.log("Fee:", formatSol(estimate.fee));
|
|
187
|
+
console.log("Tokens in:", formatTokens(estimate.tokensIn));
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### 8. Estimate Sell by SOL (SOL desired -> Tokens to sell)
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
const estimate = await sdk.estimateSellBySol(mint, 0.5); // want 0.5 SOL
|
|
194
|
+
|
|
195
|
+
console.log("Tokens to sell:", formatTokens(estimate.tokensIn));
|
|
196
|
+
console.log("SOL before fee:", formatSol(estimate.solBeforeFee));
|
|
197
|
+
console.log("SOL out (net):", formatSol(estimate.solOut));
|
|
198
|
+
console.log("Fee:", formatSol(estimate.fee));
|
|
190
199
|
```
|
|
191
200
|
|
|
192
|
-
###
|
|
201
|
+
### 9. Get Progress
|
|
193
202
|
|
|
194
203
|
```typescript
|
|
195
204
|
const progress = await sdk.getProgress(mint);
|
|
@@ -200,19 +209,19 @@ console.log("Current price:", progress.currentPrice.toString(), "lamports/token"
|
|
|
200
209
|
console.log("Complete:", progress.isComplete);
|
|
201
210
|
```
|
|
202
211
|
|
|
203
|
-
###
|
|
212
|
+
### 10. Get Curve State
|
|
204
213
|
|
|
205
214
|
```typescript
|
|
206
215
|
const curve = await sdk.getCurveState(mint);
|
|
207
216
|
|
|
208
217
|
console.log("K:", curve.k.toString());
|
|
209
218
|
console.log("Sold:", formatTokens(curve.soldSupply));
|
|
210
|
-
console.log("
|
|
219
|
+
console.log("For curve:", formatTokens(curve.tokensForCurve));
|
|
211
220
|
console.log("SOL reserves:", formatSol(curve.realSolReserves));
|
|
212
221
|
console.log("Complete:", curve.complete);
|
|
213
222
|
```
|
|
214
223
|
|
|
215
|
-
###
|
|
224
|
+
### 11. Get Token Launch State
|
|
216
225
|
|
|
217
226
|
```typescript
|
|
218
227
|
const launch = await sdk.getTokenLaunchState(mint);
|
|
@@ -223,27 +232,64 @@ console.log("Trading active:", launch.tradingActive);
|
|
|
223
232
|
console.log("Migrated:", launch.migrated);
|
|
224
233
|
```
|
|
225
234
|
|
|
226
|
-
###
|
|
235
|
+
### 12. Admin Withdraw (Admin Only)
|
|
227
236
|
|
|
228
237
|
```typescript
|
|
229
|
-
// Only ADMIN_WALLET can call this
|
|
230
238
|
if (wallet.publicKey.equals(ADMIN_WALLET)) {
|
|
231
239
|
const result = await sdk.adminWithdraw(mint);
|
|
232
240
|
console.log("SOL withdrawn:", formatSol(result.solWithdrawn));
|
|
233
241
|
console.log("LP tokens:", formatTokens(result.tokensWithdrawn));
|
|
242
|
+
console.log("Fees to treasury:", formatSol(result.feesToTreasury));
|
|
243
|
+
console.log("Treasury tokens:", formatTokens(result.treasuryTokens));
|
|
234
244
|
}
|
|
235
245
|
```
|
|
236
246
|
|
|
237
247
|
**Requirements:**
|
|
238
248
|
- Caller must be `ADMIN_WALLET`
|
|
239
|
-
- Curve must be complete (
|
|
249
|
+
- Curve must be complete (70% sold)
|
|
240
250
|
- Token not already migrated
|
|
241
251
|
|
|
242
252
|
---
|
|
243
253
|
|
|
254
|
+
## Estimate Return Types
|
|
255
|
+
|
|
256
|
+
### EstimateBuyResult
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
interface EstimateBuyResult {
|
|
260
|
+
solIn: bigint; // Total SOL user pays (including fee)
|
|
261
|
+
solAfterFee: bigint; // SOL that goes into the curve (after fee)
|
|
262
|
+
tokensOut: bigint; // Tokens user receives
|
|
263
|
+
fee: bigint; // Fee in SOL (lamports)
|
|
264
|
+
pricePerToken: bigint;
|
|
265
|
+
priceImpactBps: number;
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Used by: `estimateBuy()`, `estimateBuyByTokens()`
|
|
270
|
+
|
|
271
|
+
### EstimateSellResult
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
interface EstimateSellResult {
|
|
275
|
+
tokensIn: bigint; // Tokens user sells
|
|
276
|
+
solBeforeFee: bigint; // Gross SOL from curve (before fee)
|
|
277
|
+
solOut: bigint; // Net SOL user receives (after fee)
|
|
278
|
+
fee: bigint; // Fee in SOL (lamports)
|
|
279
|
+
pricePerToken: bigint;
|
|
280
|
+
priceImpactBps: number;
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Used by: `estimateSell()`, `estimateSellBySol()`
|
|
285
|
+
|
|
286
|
+
> **Note:** Fee is always denominated in SOL (lamports).
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
244
290
|
## Event Listeners
|
|
245
291
|
|
|
246
|
-
Subscribe to real-time events from the
|
|
292
|
+
Subscribe to real-time events from the program.
|
|
247
293
|
|
|
248
294
|
### Available Events
|
|
249
295
|
|
|
@@ -258,17 +304,17 @@ Subscribe to real-time events from the Pump.fun program.
|
|
|
258
304
|
### Listen for Token Purchases
|
|
259
305
|
|
|
260
306
|
```typescript
|
|
261
|
-
// Subscribe to buy events
|
|
262
307
|
const listenerId = sdk.onTokensPurchased((event, slot, signature) => {
|
|
263
308
|
console.log("Buy Event:", {
|
|
264
309
|
buyer: event.buyer.toString(),
|
|
265
310
|
mint: event.mint.toString(),
|
|
311
|
+
solAmount: formatSol(event.solAmount),
|
|
312
|
+
solAfterFees: formatSol(event.solAfterFees),
|
|
266
313
|
tokensReceived: formatTokens(event.tokensReceived),
|
|
267
|
-
|
|
314
|
+
curveFee: formatSol(event.curveFee),
|
|
315
|
+
adminFee: formatSol(event.adminFee),
|
|
268
316
|
progress: event.progress + "%",
|
|
269
317
|
complete: event.isCurveComplete,
|
|
270
|
-
slot,
|
|
271
|
-
signature,
|
|
272
318
|
});
|
|
273
319
|
});
|
|
274
320
|
|
|
@@ -283,7 +329,10 @@ const listenerId = sdk.onTokensSold((event, slot, signature) => {
|
|
|
283
329
|
console.log("Sell Event:", {
|
|
284
330
|
seller: event.seller.toString(),
|
|
285
331
|
tokensSold: formatTokens(event.tokensSold),
|
|
286
|
-
|
|
332
|
+
grossSolRefund: formatSol(event.grossSolRefund),
|
|
333
|
+
netSolRefund: formatSol(event.netSolRefund),
|
|
334
|
+
curveFee: formatSol(event.curveFee),
|
|
335
|
+
adminFee: formatSol(event.adminFee),
|
|
287
336
|
progress: event.progress + "%",
|
|
288
337
|
});
|
|
289
338
|
});
|
|
@@ -299,6 +348,9 @@ sdk.onLaunchCreated((event, slot, signature) => {
|
|
|
299
348
|
mint: event.mint.toString(),
|
|
300
349
|
creator: event.creator.toString(),
|
|
301
350
|
totalSupply: formatTokens(event.totalSupply),
|
|
351
|
+
curveAllocation: formatTokens(event.curveAllocation),
|
|
352
|
+
lpAllocation: formatTokens(event.lpAllocation),
|
|
353
|
+
treasuryAllocation: formatTokens(event.treasuryAllocation),
|
|
302
354
|
initialK: event.initialK.toString(),
|
|
303
355
|
});
|
|
304
356
|
});
|
|
@@ -324,54 +376,18 @@ sdk.onAdminWithdraw((event, slot, signature) => {
|
|
|
324
376
|
mint: event.mint.toString(),
|
|
325
377
|
solWithdrawn: formatSol(event.solWithdrawn),
|
|
326
378
|
tokensWithdrawn: formatTokens(event.tokensWithdrawn),
|
|
379
|
+
feesToTreasury: formatSol(event.feesToTreasury),
|
|
380
|
+
treasuryTokens: formatTokens(event.treasuryTokens),
|
|
327
381
|
});
|
|
328
382
|
});
|
|
329
383
|
```
|
|
330
384
|
|
|
331
|
-
### Complete Event Listener Example
|
|
332
|
-
|
|
333
|
-
```typescript
|
|
334
|
-
import { PumpFunSDK, formatTokens, formatSol } from "pump-fun-sdk";
|
|
335
|
-
|
|
336
|
-
async function watchToken(sdk: PumpFunSDK, mint: PublicKey) {
|
|
337
|
-
// Track buys
|
|
338
|
-
const buyListener = sdk.onTokensPurchased((event, slot, sig) => {
|
|
339
|
-
if (event.mint.equals(mint)) {
|
|
340
|
-
console.log(`[Buy] ${formatTokens(event.tokensReceived)} tokens bought`);
|
|
341
|
-
|
|
342
|
-
if (event.isCurveComplete) {
|
|
343
|
-
console.log("🎉 Curve completed!");
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
// Track sells
|
|
349
|
-
const sellListener = sdk.onTokensSold((event, slot, sig) => {
|
|
350
|
-
if (event.mint.equals(mint)) {
|
|
351
|
-
console.log(`[Sell] ${formatTokens(event.tokensSold)} tokens sold`);
|
|
352
|
-
}
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
// Wait for curve completion
|
|
356
|
-
const completeListener = sdk.onCurveComplete((event, slot, sig) => {
|
|
357
|
-
if (event.mint.equals(mint)) {
|
|
358
|
-
console.log(`Curve complete! Total raised: ${formatSol(event.totalSolRaised)} SOL`);
|
|
359
|
-
|
|
360
|
-
// Clean up listeners
|
|
361
|
-
sdk.removeEventListener(buyListener);
|
|
362
|
-
sdk.removeEventListener(sellListener);
|
|
363
|
-
sdk.removeEventListener(completeListener);
|
|
364
|
-
}
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
```
|
|
368
|
-
|
|
369
385
|
---
|
|
370
386
|
|
|
371
387
|
## Utility Functions
|
|
372
388
|
|
|
373
389
|
```typescript
|
|
374
|
-
import { formatTokens, formatSol, parseSol, parseTokens } from "
|
|
390
|
+
import { formatTokens, formatSol, parseSol, parseTokens } from "@paul.lumberwork/bonding-curve-sdk";
|
|
375
391
|
|
|
376
392
|
// Format raw values to readable strings
|
|
377
393
|
formatTokens(1000000000000n); // "1,000,000" (1M tokens)
|
|
@@ -387,12 +403,16 @@ parseTokens(1000000); // 1000000000000n (raw with 6 decimals)
|
|
|
387
403
|
## Constants
|
|
388
404
|
|
|
389
405
|
```typescript
|
|
390
|
-
import { ADMIN_WALLET, K_SCALE, TOKEN_DECIMALS, FEE_BPS } from "
|
|
406
|
+
import { ADMIN_WALLET, K_SCALE, TOKEN_DECIMALS, FEE_BPS, PROGRAM_ID } from "@paul.lumberwork/bonding-curve-sdk";
|
|
391
407
|
|
|
408
|
+
PROGRAM_ID // PublicKey: "6o7oTqg2CfvcMCJTLNEJsef7c875zGpTvcnFctNAjudL"
|
|
392
409
|
ADMIN_WALLET // PublicKey: "7eGpbyRpcM7WpNKQtd6XkteNQWHbWXP7icZjKzNK2aTk"
|
|
393
410
|
K_SCALE // 10^22 (bigint)
|
|
394
411
|
TOKEN_DECIMALS // 6
|
|
395
412
|
FEE_BPS // 100 (1%)
|
|
413
|
+
CURVE_PERCENT // 70
|
|
414
|
+
LP_PERCENT // 20
|
|
415
|
+
TREASURY_PERCENT // 10
|
|
396
416
|
```
|
|
397
417
|
|
|
398
418
|
---
|
|
@@ -414,42 +434,50 @@ FEE_BPS // 100 (1%)
|
|
|
414
434
|
```typescript
|
|
415
435
|
import * as anchor from "@coral-xyz/anchor";
|
|
416
436
|
import { Program } from "@coral-xyz/anchor";
|
|
417
|
-
import {
|
|
418
|
-
import {
|
|
437
|
+
import { Connection, Keypair } from "@solana/web3.js";
|
|
438
|
+
import { KickFunSDK, formatTokens, formatSol, ADMIN_WALLET } from "@paul.lumberwork/bonding-curve-sdk";
|
|
439
|
+
import idl from "@paul.lumberwork/bonding-curve-sdk/idl/kick_fun_program.json";
|
|
419
440
|
|
|
420
441
|
async function main() {
|
|
421
|
-
const
|
|
422
|
-
anchor.
|
|
423
|
-
const
|
|
424
|
-
const
|
|
425
|
-
const sdk = new
|
|
442
|
+
const connection = new Connection("https://api.devnet.solana.com", "confirmed");
|
|
443
|
+
const wallet = new anchor.Wallet(keypair);
|
|
444
|
+
const provider = new anchor.AnchorProvider(connection, wallet, { commitment: "confirmed" });
|
|
445
|
+
const program = new Program(idl as anchor.Idl, provider) as any;
|
|
446
|
+
const sdk = new KickFunSDK(program, wallet);
|
|
426
447
|
|
|
427
|
-
// 1. Initialize launchpad
|
|
448
|
+
// 1. Initialize launchpad (admin only, one-time)
|
|
428
449
|
await sdk.initializeLaunchpad();
|
|
429
450
|
|
|
430
|
-
// 2. Create token
|
|
451
|
+
// 2. Create token (total_supply and k are set by admin)
|
|
431
452
|
const { addresses, mintKeypair } = await sdk.createTokenLaunch({
|
|
432
453
|
name: "Test Token",
|
|
433
454
|
symbol: "TEST",
|
|
434
455
|
uri: "https://example.com/metadata.json",
|
|
435
|
-
totalSupply: 1_000_000_000,
|
|
436
|
-
k: 60,
|
|
437
456
|
});
|
|
438
457
|
const mint = mintKeypair.publicKey;
|
|
439
458
|
|
|
440
|
-
// 3.
|
|
459
|
+
// 3. Estimate before buying
|
|
460
|
+
const buyEstimate = await sdk.estimateBuy(mint, 0.5);
|
|
461
|
+
console.log("Will receive:", formatTokens(buyEstimate.tokensOut), "tokens");
|
|
462
|
+
console.log("Fee:", formatSol(buyEstimate.fee));
|
|
463
|
+
|
|
464
|
+
// 4. Buy tokens
|
|
441
465
|
const buy = await sdk.buy(mint, 0.5, { computeUnits: 400_000 });
|
|
442
466
|
console.log("Bought:", formatTokens(buy.tokensTraded));
|
|
443
467
|
|
|
444
|
-
//
|
|
468
|
+
// 5. Estimate sell by desired SOL
|
|
469
|
+
const sellEstimate = await sdk.estimateSellBySol(mint, 0.3);
|
|
470
|
+
console.log("Need to sell:", formatTokens(sellEstimate.tokensIn), "tokens to get 0.3 SOL");
|
|
471
|
+
|
|
472
|
+
// 6. Sell tokens
|
|
445
473
|
const sell = await sdk.sell(mint, 10_000_000, 0, { computeUnits: 400_000 });
|
|
446
474
|
console.log("Sold for:", formatSol(sell.solTraded), "SOL");
|
|
447
475
|
|
|
448
|
-
//
|
|
476
|
+
// 7. Check progress
|
|
449
477
|
const progress = await sdk.getProgress(mint);
|
|
450
478
|
console.log("Progress:", progress.percent + "%");
|
|
451
479
|
|
|
452
|
-
//
|
|
480
|
+
// 8. Admin withdraw (when curve complete)
|
|
453
481
|
if (progress.isComplete && wallet.publicKey.equals(ADMIN_WALLET)) {
|
|
454
482
|
const withdraw = await sdk.adminWithdraw(mint);
|
|
455
483
|
console.log("Withdrawn:", formatSol(withdraw.solWithdrawn), "SOL");
|
|
@@ -468,7 +496,7 @@ main().catch(console.error);
|
|
|
468
496
|
solana-test-validator --reset
|
|
469
497
|
|
|
470
498
|
# In another terminal
|
|
471
|
-
cd
|
|
499
|
+
cd kick_fun_program
|
|
472
500
|
anchor build && anchor deploy
|
|
473
501
|
|
|
474
502
|
# Run test
|
package/dist/index.d.mts
CHANGED
|
@@ -3279,12 +3279,21 @@ interface TradeResult {
|
|
|
3279
3279
|
newProgress: number;
|
|
3280
3280
|
isCurveComplete: boolean;
|
|
3281
3281
|
}
|
|
3282
|
-
interface
|
|
3282
|
+
interface EstimateBuyResult {
|
|
3283
|
+
solIn: bigint;
|
|
3284
|
+
solAfterFee: bigint;
|
|
3283
3285
|
tokensOut: bigint;
|
|
3284
|
-
|
|
3286
|
+
fee: bigint;
|
|
3287
|
+
pricePerToken: bigint;
|
|
3288
|
+
priceImpactBps: number;
|
|
3289
|
+
}
|
|
3290
|
+
interface EstimateSellResult {
|
|
3291
|
+
tokensIn: bigint;
|
|
3292
|
+
solBeforeFee: bigint;
|
|
3293
|
+
solOut: bigint;
|
|
3294
|
+
fee: bigint;
|
|
3285
3295
|
pricePerToken: bigint;
|
|
3286
3296
|
priceImpactBps: number;
|
|
3287
|
-
feeAmount: bigint;
|
|
3288
3297
|
}
|
|
3289
3298
|
interface LaunchCreatedEvent {
|
|
3290
3299
|
tokenLaunch: PublicKey;
|
|
@@ -3395,8 +3404,10 @@ declare class KickFunSDK {
|
|
|
3395
3404
|
feesToTreasury: bigint;
|
|
3396
3405
|
treasuryTokens: bigint;
|
|
3397
3406
|
}>;
|
|
3398
|
-
estimateBuy(mint: PublicKey, solAmount: number): Promise<
|
|
3399
|
-
|
|
3407
|
+
estimateBuy(mint: PublicKey, solAmount: number): Promise<EstimateBuyResult>;
|
|
3408
|
+
estimateBuyByTokens(mint: PublicKey, tokenAmount: number): Promise<EstimateBuyResult>;
|
|
3409
|
+
estimateSell(mint: PublicKey, tokenAmount: number): Promise<EstimateSellResult>;
|
|
3410
|
+
estimateSellBySol(mint: PublicKey, solAmount: number): Promise<EstimateSellResult>;
|
|
3400
3411
|
getCurveState(mint: PublicKey): Promise<BondingCurveState>;
|
|
3401
3412
|
getTokenLaunchState(mint: PublicKey): Promise<TokenLaunchState>;
|
|
3402
3413
|
getProgress(mint: PublicKey): Promise<{
|
|
@@ -3448,6 +3459,9 @@ declare class KickFunSDK {
|
|
|
3448
3459
|
calculateCost(k: bigint, s1: bigint, s2: bigint): bigint;
|
|
3449
3460
|
/** Calculate tokens received for SOL: s2 = sqrt(s1² + 2×sol×K_SCALE/k) */
|
|
3450
3461
|
calculateTokensForSol(k: bigint, currentSupply: bigint, solIn: bigint): bigint;
|
|
3462
|
+
/** Calculate tokens to sell to receive target SOL: inverse of refund formula
|
|
3463
|
+
* s2 = sqrt(s1² - 2×solOut×K_SCALE/k), return s1 - s2 */
|
|
3464
|
+
calculateTokensForSolSell(k: bigint, currentSupply: bigint, solOut: bigint): bigint;
|
|
3451
3465
|
/** Calculate refund for selling tokens: refund = (k/2) × (s1² - s2²) / K_SCALE */
|
|
3452
3466
|
calculateRefund(k: bigint, s1: bigint, s2: bigint): bigint;
|
|
3453
3467
|
/** Integer square root using Newton's method */
|
|
@@ -3464,4 +3478,4 @@ declare function parseSol(sol: number): bigint;
|
|
|
3464
3478
|
/** Parse tokens to raw */
|
|
3465
3479
|
declare function parseTokens(tokens: number): bigint;
|
|
3466
3480
|
|
|
3467
|
-
export { ADMIN_WALLET, type AdminWithdrawEvent, type BondingCurveState, CURVE_PERCENT, type CurveCompleteEvent, type
|
|
3481
|
+
export { ADMIN_WALLET, type AdminWithdrawEvent, type BondingCurveState, CURVE_PERCENT, type CurveCompleteEvent, type EstimateBuyResult, type EstimateSellResult, type EventCallback, FEE_BPS, K_SCALE, type KickFunEvent, type KickFunProgram, KickFunSDK, LAMPORTS, LP_PERCENT, type LaunchAddresses, type LaunchCreatedEvent, METADATA_PROGRAM_ID, PROGRAM_ID, TOKEN_DECIMALS, TREASURY_PERCENT, type TokenLaunchConfig, type TokenLaunchState, type TokensPurchasedEvent, type TokensSoldEvent, type TradeResult, formatSol, formatTokens, parseSol, parseTokens };
|
package/dist/index.d.ts
CHANGED
|
@@ -3279,12 +3279,21 @@ interface TradeResult {
|
|
|
3279
3279
|
newProgress: number;
|
|
3280
3280
|
isCurveComplete: boolean;
|
|
3281
3281
|
}
|
|
3282
|
-
interface
|
|
3282
|
+
interface EstimateBuyResult {
|
|
3283
|
+
solIn: bigint;
|
|
3284
|
+
solAfterFee: bigint;
|
|
3283
3285
|
tokensOut: bigint;
|
|
3284
|
-
|
|
3286
|
+
fee: bigint;
|
|
3287
|
+
pricePerToken: bigint;
|
|
3288
|
+
priceImpactBps: number;
|
|
3289
|
+
}
|
|
3290
|
+
interface EstimateSellResult {
|
|
3291
|
+
tokensIn: bigint;
|
|
3292
|
+
solBeforeFee: bigint;
|
|
3293
|
+
solOut: bigint;
|
|
3294
|
+
fee: bigint;
|
|
3285
3295
|
pricePerToken: bigint;
|
|
3286
3296
|
priceImpactBps: number;
|
|
3287
|
-
feeAmount: bigint;
|
|
3288
3297
|
}
|
|
3289
3298
|
interface LaunchCreatedEvent {
|
|
3290
3299
|
tokenLaunch: PublicKey;
|
|
@@ -3395,8 +3404,10 @@ declare class KickFunSDK {
|
|
|
3395
3404
|
feesToTreasury: bigint;
|
|
3396
3405
|
treasuryTokens: bigint;
|
|
3397
3406
|
}>;
|
|
3398
|
-
estimateBuy(mint: PublicKey, solAmount: number): Promise<
|
|
3399
|
-
|
|
3407
|
+
estimateBuy(mint: PublicKey, solAmount: number): Promise<EstimateBuyResult>;
|
|
3408
|
+
estimateBuyByTokens(mint: PublicKey, tokenAmount: number): Promise<EstimateBuyResult>;
|
|
3409
|
+
estimateSell(mint: PublicKey, tokenAmount: number): Promise<EstimateSellResult>;
|
|
3410
|
+
estimateSellBySol(mint: PublicKey, solAmount: number): Promise<EstimateSellResult>;
|
|
3400
3411
|
getCurveState(mint: PublicKey): Promise<BondingCurveState>;
|
|
3401
3412
|
getTokenLaunchState(mint: PublicKey): Promise<TokenLaunchState>;
|
|
3402
3413
|
getProgress(mint: PublicKey): Promise<{
|
|
@@ -3448,6 +3459,9 @@ declare class KickFunSDK {
|
|
|
3448
3459
|
calculateCost(k: bigint, s1: bigint, s2: bigint): bigint;
|
|
3449
3460
|
/** Calculate tokens received for SOL: s2 = sqrt(s1² + 2×sol×K_SCALE/k) */
|
|
3450
3461
|
calculateTokensForSol(k: bigint, currentSupply: bigint, solIn: bigint): bigint;
|
|
3462
|
+
/** Calculate tokens to sell to receive target SOL: inverse of refund formula
|
|
3463
|
+
* s2 = sqrt(s1² - 2×solOut×K_SCALE/k), return s1 - s2 */
|
|
3464
|
+
calculateTokensForSolSell(k: bigint, currentSupply: bigint, solOut: bigint): bigint;
|
|
3451
3465
|
/** Calculate refund for selling tokens: refund = (k/2) × (s1² - s2²) / K_SCALE */
|
|
3452
3466
|
calculateRefund(k: bigint, s1: bigint, s2: bigint): bigint;
|
|
3453
3467
|
/** Integer square root using Newton's method */
|
|
@@ -3464,4 +3478,4 @@ declare function parseSol(sol: number): bigint;
|
|
|
3464
3478
|
/** Parse tokens to raw */
|
|
3465
3479
|
declare function parseTokens(tokens: number): bigint;
|
|
3466
3480
|
|
|
3467
|
-
export { ADMIN_WALLET, type AdminWithdrawEvent, type BondingCurveState, CURVE_PERCENT, type CurveCompleteEvent, type
|
|
3481
|
+
export { ADMIN_WALLET, type AdminWithdrawEvent, type BondingCurveState, CURVE_PERCENT, type CurveCompleteEvent, type EstimateBuyResult, type EstimateSellResult, type EventCallback, FEE_BPS, K_SCALE, type KickFunEvent, type KickFunProgram, KickFunSDK, LAMPORTS, LP_PERCENT, type LaunchAddresses, type LaunchCreatedEvent, METADATA_PROGRAM_ID, PROGRAM_ID, TOKEN_DECIMALS, TREASURY_PERCENT, type TokenLaunchConfig, type TokenLaunchState, type TokensPurchasedEvent, type TokensSoldEvent, type TradeResult, formatSol, formatTokens, parseSol, parseTokens };
|