@coinbarrel/sdk 1.1.0 → 1.2.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 +52 -0
- package/dist/accounts.js +33 -26
- package/dist/constants.js +21 -18
- package/dist/create.js +100 -0
- package/dist/curve.js +57 -51
- package/dist/index.js +126 -23
- package/dist/metadata.js +60 -96
- package/dist/pda.js +36 -24
- package/dist/pool.js +61 -55
- package/dist/rewards.js +97 -0
- package/dist/types.js +2 -2
- package/package.json +2 -3
- package/dist/accounts.d.ts +0 -36
- package/dist/accounts.d.ts.map +0 -1
- package/dist/accounts.js.map +0 -1
- package/dist/constants.d.ts +0 -80
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js.map +0 -1
- package/dist/curve.d.ts +0 -37
- package/dist/curve.d.ts.map +0 -1
- package/dist/curve.js.map +0 -1
- package/dist/index.d.ts +0 -220
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/metadata.d.ts +0 -113
- package/dist/metadata.d.ts.map +0 -1
- package/dist/metadata.js.map +0 -1
- package/dist/pda.d.ts +0 -51
- package/dist/pda.d.ts.map +0 -1
- package/dist/pda.js.map +0 -1
- package/dist/pool.d.ts +0 -32
- package/dist/pool.d.ts.map +0 -1
- package/dist/pool.js.map +0 -1
- package/dist/types.d.ts +0 -162
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
package/README.md
CHANGED
|
@@ -116,6 +116,55 @@ const sellMaxIx = await sdk.pool.buildSwapTokenToSolMaxInstruction({
|
|
|
116
116
|
});
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
+
## Token Creation
|
|
120
|
+
|
|
121
|
+
### Create a New Token
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// Build create token instruction
|
|
125
|
+
const { instructions, mintKeypair } = sdk.buildCreateTokenInstruction({
|
|
126
|
+
payer: wallet.publicKey,
|
|
127
|
+
name: 'My Token',
|
|
128
|
+
symbol: 'MTK',
|
|
129
|
+
uri: 'https://arweave.net/...', // Metadata JSON URI
|
|
130
|
+
creatorFeeRecipient: wallet.publicKey,
|
|
131
|
+
traderRewardsShareBps: 3000, // 30% of fees to holders (optional, default 2500)
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Build and send transaction
|
|
135
|
+
const tx = new Transaction().add(...instructions);
|
|
136
|
+
const signature = await sendAndConfirmTransaction(connection, tx, [wallet, mintKeypair]);
|
|
137
|
+
|
|
138
|
+
console.log(`Token created: ${mintKeypair.publicKey.toBase58()}`);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The token is created with:
|
|
142
|
+
|
|
143
|
+
- **Mint authority**: Revoked immediately after minting 1B tokens
|
|
144
|
+
- **Freeze authority**: Never set (null from creation)
|
|
145
|
+
- **Total supply**: 1,000,000,000 tokens (6 decimals)
|
|
146
|
+
- **Metadata**: Created via Metaplex (update_authority = creator)
|
|
147
|
+
|
|
148
|
+
## Holder Rewards
|
|
149
|
+
|
|
150
|
+
### Claim Rewards from Bonding Curve
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
const instructions = await sdk.buildClaimRewardsCurveInstruction(tokenMint, wallet.publicKey);
|
|
154
|
+
|
|
155
|
+
const tx = new Transaction().add(...instructions);
|
|
156
|
+
const signature = await sendAndConfirmTransaction(connection, tx, [wallet]);
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Claim Rewards from AMM Pool (Post-Graduation)
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
const instructions = await sdk.buildClaimRewardsPoolInstruction(tokenMint, wallet.publicKey);
|
|
163
|
+
|
|
164
|
+
const tx = new Transaction().add(...instructions);
|
|
165
|
+
const signature = await sendAndConfirmTransaction(connection, tx, [wallet]);
|
|
166
|
+
```
|
|
167
|
+
|
|
119
168
|
## Market Info
|
|
120
169
|
|
|
121
170
|
### Get Token Market State
|
|
@@ -245,6 +294,9 @@ import type {
|
|
|
245
294
|
Network,
|
|
246
295
|
TokenMetadata,
|
|
247
296
|
TokenMetadataJson,
|
|
297
|
+
CreateBarrelTokenParams,
|
|
298
|
+
ClaimHolderRewardsParams,
|
|
299
|
+
ClaimHolderRewardsCurveParams,
|
|
248
300
|
} from '@coinbarrel/sdk';
|
|
249
301
|
```
|
|
250
302
|
|
package/dist/accounts.js
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Account Fetching and Parsing
|
|
3
4
|
* Read on-chain account data for bonding curves and pools
|
|
4
5
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.getBondingCurveState = getBondingCurveState;
|
|
8
|
+
exports.getCurveSolBalance = getCurveSolBalance;
|
|
9
|
+
exports.getPoolState = getPoolState;
|
|
10
|
+
exports.getPoolBalances = getPoolBalances;
|
|
11
|
+
exports.getMarketInfo = getMarketInfo;
|
|
12
|
+
exports.getUserTokenBalance = getUserTokenBalance;
|
|
13
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
14
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
15
|
+
const constants_js_1 = require("./constants.js");
|
|
16
|
+
const pda_js_1 = require("./pda.js");
|
|
9
17
|
// ============= Buffer Helpers =============
|
|
10
18
|
function readU16LE(data, offset) {
|
|
11
19
|
return data.readUInt16LE(offset);
|
|
@@ -19,7 +27,7 @@ function readU128LE(data, offset) {
|
|
|
19
27
|
return low + (high << 64n);
|
|
20
28
|
}
|
|
21
29
|
function readPubkey(data, offset) {
|
|
22
|
-
return new PublicKey(data.subarray(offset, offset + 32));
|
|
30
|
+
return new web3_js_1.PublicKey(data.subarray(offset, offset + 32));
|
|
23
31
|
}
|
|
24
32
|
function readBool(data, offset) {
|
|
25
33
|
return data[offset] !== 0;
|
|
@@ -28,14 +36,14 @@ function readBool(data, offset) {
|
|
|
28
36
|
/**
|
|
29
37
|
* Fetch and parse bonding curve state
|
|
30
38
|
*/
|
|
31
|
-
|
|
32
|
-
const bondingCurve = getBondingCurvePda(tokenMint, programId);
|
|
39
|
+
async function getBondingCurveState(connection, tokenMint, programId) {
|
|
40
|
+
const bondingCurve = (0, pda_js_1.getBondingCurvePda)(tokenMint, programId);
|
|
33
41
|
const accountInfo = await connection.getAccountInfo(bondingCurve);
|
|
34
42
|
if (!accountInfo || accountInfo.data.length < 209) {
|
|
35
43
|
return null;
|
|
36
44
|
}
|
|
37
45
|
const data = accountInfo.data;
|
|
38
|
-
const O = BONDING_CURVE_OFFSETS;
|
|
46
|
+
const O = constants_js_1.BONDING_CURVE_OFFSETS;
|
|
39
47
|
return {
|
|
40
48
|
tokenMint: readPubkey(data, O.TOKEN_MINT),
|
|
41
49
|
tokenVault: readPubkey(data, O.TOKEN_VAULT),
|
|
@@ -57,9 +65,9 @@ export async function getBondingCurveState(connection, tokenMint, programId) {
|
|
|
57
65
|
/**
|
|
58
66
|
* Get SOL balance in bonding curve escrow
|
|
59
67
|
*/
|
|
60
|
-
|
|
61
|
-
const bondingCurve = getBondingCurvePda(tokenMint, programId);
|
|
62
|
-
const solEscrow = getSolEscrowPda(bondingCurve, programId);
|
|
68
|
+
async function getCurveSolBalance(connection, tokenMint, programId) {
|
|
69
|
+
const bondingCurve = (0, pda_js_1.getBondingCurvePda)(tokenMint, programId);
|
|
70
|
+
const solEscrow = (0, pda_js_1.getSolEscrowPda)(bondingCurve, programId);
|
|
63
71
|
const balance = await connection.getBalance(solEscrow);
|
|
64
72
|
return BigInt(balance);
|
|
65
73
|
}
|
|
@@ -67,14 +75,14 @@ export async function getCurveSolBalance(connection, tokenMint, programId) {
|
|
|
67
75
|
/**
|
|
68
76
|
* Fetch and parse pool state
|
|
69
77
|
*/
|
|
70
|
-
|
|
71
|
-
const pool = getPoolPda(tokenMint, programId);
|
|
78
|
+
async function getPoolState(connection, tokenMint, programId) {
|
|
79
|
+
const pool = (0, pda_js_1.getPoolPda)(tokenMint, programId);
|
|
72
80
|
const accountInfo = await connection.getAccountInfo(pool);
|
|
73
81
|
if (!accountInfo || accountInfo.data.length < 269) {
|
|
74
82
|
return null;
|
|
75
83
|
}
|
|
76
84
|
const data = accountInfo.data;
|
|
77
|
-
const O = POOL_OFFSETS;
|
|
85
|
+
const O = constants_js_1.POOL_OFFSETS;
|
|
78
86
|
return {
|
|
79
87
|
tokenAMint: readPubkey(data, O.TOKEN_A_MINT),
|
|
80
88
|
tokenBMint: readPubkey(data, O.TOKEN_B_MINT),
|
|
@@ -95,20 +103,20 @@ export async function getPoolState(connection, tokenMint, programId) {
|
|
|
95
103
|
* Get pool vault balances
|
|
96
104
|
* Uses vault addresses stored in Pool state rather than deriving PDAs
|
|
97
105
|
*/
|
|
98
|
-
|
|
106
|
+
async function getPoolBalances(connection, tokenMint, programId) {
|
|
99
107
|
// First fetch pool state to get stored vault addresses
|
|
100
108
|
const state = await getPoolState(connection, tokenMint, programId);
|
|
101
109
|
if (!state) {
|
|
102
110
|
return null;
|
|
103
111
|
}
|
|
104
112
|
// Determine which vault is WSOL and which is the token based on stored mints
|
|
105
|
-
const isTokenANative = state.tokenAMint.equals(NATIVE_MINT);
|
|
113
|
+
const isTokenANative = state.tokenAMint.equals(constants_js_1.NATIVE_MINT);
|
|
106
114
|
const wsolVault = isTokenANative ? state.tokenAVault : state.tokenBVault;
|
|
107
115
|
const tokenVault = isTokenANative ? state.tokenBVault : state.tokenAVault;
|
|
108
116
|
try {
|
|
109
117
|
const [wsolAccount, tokenAccount] = await Promise.all([
|
|
110
|
-
getAccount(connection, wsolVault),
|
|
111
|
-
getAccount(connection, tokenVault),
|
|
118
|
+
(0, spl_token_1.getAccount)(connection, wsolVault),
|
|
119
|
+
(0, spl_token_1.getAccount)(connection, tokenVault),
|
|
112
120
|
]);
|
|
113
121
|
return {
|
|
114
122
|
solBalance: wsolAccount.amount,
|
|
@@ -124,7 +132,7 @@ export async function getPoolBalances(connection, tokenMint, programId) {
|
|
|
124
132
|
* Get comprehensive market info for a token
|
|
125
133
|
* Automatically detects if on bonding curve or AMM pool
|
|
126
134
|
*/
|
|
127
|
-
|
|
135
|
+
async function getMarketInfo(connection, tokenMint, programId) {
|
|
128
136
|
// Try bonding curve first
|
|
129
137
|
const curveState = await getBondingCurveState(connection, tokenMint, programId);
|
|
130
138
|
if (curveState && !curveState.paused) {
|
|
@@ -133,9 +141,9 @@ export async function getMarketInfo(connection, tokenMint, programId) {
|
|
|
133
141
|
// Still on bonding curve
|
|
134
142
|
const solBalance = await getCurveSolBalance(connection, tokenMint, programId);
|
|
135
143
|
// Calculate price from virtual reserves: price = vSol / vToken
|
|
136
|
-
const price = curveState.vToken > 0n ? (curveState.vSol * LAMPORTS_PER_SOL) / curveState.vToken : 0n;
|
|
144
|
+
const price = curveState.vToken > 0n ? (curveState.vSol * constants_js_1.LAMPORTS_PER_SOL) / curveState.vToken : 0n;
|
|
137
145
|
// Market cap = circulating supply * price
|
|
138
|
-
const marketCapSol = curveState.totalSold > 0n ? (curveState.totalSold * price) / LAMPORTS_PER_SOL : 0n;
|
|
146
|
+
const marketCapSol = curveState.totalSold > 0n ? (curveState.totalSold * price) / constants_js_1.LAMPORTS_PER_SOL : 0n;
|
|
139
147
|
return {
|
|
140
148
|
tokenMint,
|
|
141
149
|
phase: 'curve',
|
|
@@ -155,7 +163,7 @@ export async function getMarketInfo(connection, tokenMint, programId) {
|
|
|
155
163
|
if (poolState && poolBalances) {
|
|
156
164
|
// Calculate price from reserves: price = solReserve / tokenReserve
|
|
157
165
|
const price = poolBalances.tokenBalance > 0n
|
|
158
|
-
? (poolBalances.solBalance * LAMPORTS_PER_SOL) / poolBalances.tokenBalance
|
|
166
|
+
? (poolBalances.solBalance * constants_js_1.LAMPORTS_PER_SOL) / poolBalances.tokenBalance
|
|
159
167
|
: 0n;
|
|
160
168
|
// For pool, circulating = total supply - vault balance
|
|
161
169
|
// We'd need to fetch total supply, for now use a placeholder
|
|
@@ -179,14 +187,13 @@ export async function getMarketInfo(connection, tokenMint, programId) {
|
|
|
179
187
|
/**
|
|
180
188
|
* Get user's token balance
|
|
181
189
|
*/
|
|
182
|
-
|
|
190
|
+
async function getUserTokenBalance(connection, tokenMint, user) {
|
|
183
191
|
try {
|
|
184
|
-
const ata = getAssociatedTokenAddressSync(tokenMint, user);
|
|
185
|
-
const account = await getAccount(connection, ata);
|
|
192
|
+
const ata = (0, spl_token_1.getAssociatedTokenAddressSync)(tokenMint, user);
|
|
193
|
+
const account = await (0, spl_token_1.getAccount)(connection, ata);
|
|
186
194
|
return account.amount;
|
|
187
195
|
}
|
|
188
196
|
catch {
|
|
189
197
|
return 0n;
|
|
190
198
|
}
|
|
191
199
|
}
|
|
192
|
-
//# sourceMappingURL=accounts.js.map
|
package/dist/constants.js
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* CoinBarrel SDK Constants
|
|
3
4
|
* Network-specific program IDs and configuration
|
|
4
5
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.TOKEN_DECIMALS_MULTIPLIER = exports.LAMPORTS_PER_SOL = exports.DEFAULT_SLIPPAGE_BPS = exports.DEFAULT_DECIMALS = exports.POOL_OFFSETS = exports.BONDING_CURVE_OFFSETS = exports.DISCRIMINATORS = exports.SEEDS = exports.TOKEN_METADATA_PROGRAM_ID = exports.NATIVE_MINT = exports.ADMIN_FEE_RECIPIENTS = exports.PROGRAM_IDS = void 0;
|
|
8
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
9
|
+
exports.PROGRAM_IDS = {
|
|
10
|
+
devnet: new web3_js_1.PublicKey('AhfARnaxxX61YotZw3mZWLLUFpF8UV6pZmWJBEZCbVC4'),
|
|
11
|
+
mainnet: new web3_js_1.PublicKey('7HxbxHnTUBaUfWjVPbPLs8gqqScmjmBWjRnETBjS9DMj'),
|
|
9
12
|
};
|
|
10
13
|
// Admin fee recipient (CoinBarrel protocol fee wallet)
|
|
11
|
-
|
|
12
|
-
devnet: new PublicKey('4Uw8XhtqVBEXEkjZfWb7agyrhxbSmfDSGWEdxbWonhwu'),
|
|
13
|
-
mainnet: new PublicKey('4Uw8XhtqVBEXEkjZfWb7agyrhxbSmfDSGWEdxbWonhwu'),
|
|
14
|
+
exports.ADMIN_FEE_RECIPIENTS = {
|
|
15
|
+
devnet: new web3_js_1.PublicKey('4Uw8XhtqVBEXEkjZfWb7agyrhxbSmfDSGWEdxbWonhwu'),
|
|
16
|
+
mainnet: new web3_js_1.PublicKey('4Uw8XhtqVBEXEkjZfWb7agyrhxbSmfDSGWEdxbWonhwu'),
|
|
14
17
|
};
|
|
15
18
|
// WSOL mint (same on all networks)
|
|
16
|
-
|
|
19
|
+
exports.NATIVE_MINT = new web3_js_1.PublicKey('So11111111111111111111111111111111111111112');
|
|
17
20
|
// Metaplex Token Metadata Program ID (same on all networks)
|
|
18
|
-
|
|
21
|
+
exports.TOKEN_METADATA_PROGRAM_ID = new web3_js_1.PublicKey('metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s');
|
|
19
22
|
// ============= PDA Seeds =============
|
|
20
|
-
|
|
23
|
+
exports.SEEDS = {
|
|
21
24
|
BONDING: Buffer.from('bonding'),
|
|
22
25
|
BONDING_AUTHORITY: Buffer.from('bonding_authority'),
|
|
23
26
|
BONDING_SOL: Buffer.from('bonding_sol'),
|
|
@@ -30,9 +33,10 @@ export const SEEDS = {
|
|
|
30
33
|
};
|
|
31
34
|
// ============= Instruction Discriminators =============
|
|
32
35
|
// Pre-computed Anchor discriminators (first 8 bytes of sha256("global:<instruction_name>"))
|
|
33
|
-
|
|
36
|
+
exports.DISCRIMINATORS = {
|
|
34
37
|
// Bonding curve
|
|
35
38
|
initialize_barrel_curve: Buffer.from([158, 16, 141, 14, 53, 250, 33, 42]),
|
|
39
|
+
create_barrel_token: Buffer.from([88, 190, 74, 163, 144, 5, 73, 246]),
|
|
36
40
|
buy_on_curve: Buffer.from([6, 20, 84, 191, 116, 79, 21, 147]),
|
|
37
41
|
sell_on_curve: Buffer.from([158, 242, 158, 47, 48, 215, 214, 209]),
|
|
38
42
|
sell_max_on_curve: Buffer.from([42, 184, 90, 220, 13, 36, 18, 77]),
|
|
@@ -56,7 +60,7 @@ export const DISCRIMINATORS = {
|
|
|
56
60
|
};
|
|
57
61
|
// ============= Account Data Offsets =============
|
|
58
62
|
// For parsing on-chain account data
|
|
59
|
-
|
|
63
|
+
exports.BONDING_CURVE_OFFSETS = {
|
|
60
64
|
DISCRIMINATOR: 0,
|
|
61
65
|
TOKEN_MINT: 8,
|
|
62
66
|
TOKEN_VAULT: 8 + 32,
|
|
@@ -74,7 +78,7 @@ export const BONDING_CURVE_OFFSETS = {
|
|
|
74
78
|
TOTAL_SOLD: 8 + 192,
|
|
75
79
|
PAUSED: 8 + 208,
|
|
76
80
|
};
|
|
77
|
-
|
|
81
|
+
exports.POOL_OFFSETS = {
|
|
78
82
|
DISCRIMINATOR: 0,
|
|
79
83
|
TOKEN_A_MINT: 8,
|
|
80
84
|
TOKEN_B_MINT: 8 + 32,
|
|
@@ -91,8 +95,7 @@ export const POOL_OFFSETS = {
|
|
|
91
95
|
CREATOR_FEE_RECIPIENT: 8 + 237,
|
|
92
96
|
};
|
|
93
97
|
// ============= Defaults =============
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
//# sourceMappingURL=constants.js.map
|
|
98
|
+
exports.DEFAULT_DECIMALS = 6;
|
|
99
|
+
exports.DEFAULT_SLIPPAGE_BPS = 100; // 1%
|
|
100
|
+
exports.LAMPORTS_PER_SOL = 1000000000n;
|
|
101
|
+
exports.TOKEN_DECIMALS_MULTIPLIER = 1000000n; // 10^6 for 6 decimals
|
package/dist/create.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Token Creation
|
|
4
|
+
* Create new barrel tokens with atomically revoked mint/freeze authority
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.buildCreateBarrelTokenInstruction = buildCreateBarrelTokenInstruction;
|
|
8
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
9
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
10
|
+
const constants_js_1 = require("./constants.js");
|
|
11
|
+
const pda_js_1 = require("./pda.js");
|
|
12
|
+
const metadata_js_1 = require("./metadata.js");
|
|
13
|
+
// ============= Buffer Helpers =============
|
|
14
|
+
function writeU8(n) {
|
|
15
|
+
const b = Buffer.alloc(1);
|
|
16
|
+
b.writeUInt8(n);
|
|
17
|
+
return b;
|
|
18
|
+
}
|
|
19
|
+
function writeU16LE(n) {
|
|
20
|
+
const b = Buffer.alloc(2);
|
|
21
|
+
b.writeUInt16LE(n);
|
|
22
|
+
return b;
|
|
23
|
+
}
|
|
24
|
+
function writePubkey(pk) {
|
|
25
|
+
return pk.toBuffer();
|
|
26
|
+
}
|
|
27
|
+
function writeString(s) {
|
|
28
|
+
const bytes = Buffer.from(s, 'utf-8');
|
|
29
|
+
const lenBuf = Buffer.alloc(4);
|
|
30
|
+
lenBuf.writeUInt32LE(bytes.length);
|
|
31
|
+
return Buffer.concat([lenBuf, bytes]);
|
|
32
|
+
}
|
|
33
|
+
// ============= Token Vault PDA =============
|
|
34
|
+
function getTokenVaultPda(bondingCurve, programId) {
|
|
35
|
+
const [pda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('token_vault'), bondingCurve.toBuffer()], programId);
|
|
36
|
+
return pda;
|
|
37
|
+
}
|
|
38
|
+
// ============= Instruction Builder =============
|
|
39
|
+
/**
|
|
40
|
+
* Build create_barrel_token instruction
|
|
41
|
+
*
|
|
42
|
+
* Creates a new token with:
|
|
43
|
+
* - Mint authority: revoked immediately after minting 1B tokens
|
|
44
|
+
* - Freeze authority: null from creation
|
|
45
|
+
* - 1B total supply minted to bonding curve vault
|
|
46
|
+
* - Metadata created via Metaplex CPI
|
|
47
|
+
*
|
|
48
|
+
* @param params - Token creation parameters
|
|
49
|
+
* @param programId - CoinBarrel program ID
|
|
50
|
+
* @param network - Network for admin fee recipient
|
|
51
|
+
* @returns Object containing instruction and mint keypair (must sign transaction)
|
|
52
|
+
*/
|
|
53
|
+
function buildCreateBarrelTokenInstruction(params, programId, network) {
|
|
54
|
+
const { payer, name, symbol, uri, decimals = 6, variant = 0, creatorFeeRecipient, traderRewardsShareBps = 2500, // 25% of fees to holders
|
|
55
|
+
} = params;
|
|
56
|
+
// Generate new mint keypair
|
|
57
|
+
const mintKeypair = web3_js_1.Keypair.generate();
|
|
58
|
+
const tokenMint = mintKeypair.publicKey;
|
|
59
|
+
// Derive PDAs
|
|
60
|
+
const bondingCurve = (0, pda_js_1.getBondingCurvePda)(tokenMint, programId);
|
|
61
|
+
const bondingAuthority = (0, pda_js_1.getBondingAuthorityPda)(bondingCurve, programId);
|
|
62
|
+
const tokenVault = getTokenVaultPda(bondingCurve, programId);
|
|
63
|
+
const metadata = (0, metadata_js_1.getMetadataPda)(tokenMint);
|
|
64
|
+
// Admin fee recipient from network config
|
|
65
|
+
const adminFeeRecipient = constants_js_1.ADMIN_FEE_RECIPIENTS[network];
|
|
66
|
+
// Build instruction data
|
|
67
|
+
// Discriminator + decimals(u8) + variant(u8) + admin_fee_recipient(Pubkey) + creator_fee_recipient(Pubkey)
|
|
68
|
+
// + trader_rewards_share_bps(u16) + name(String) + symbol(String) + uri(String)
|
|
69
|
+
const data = Buffer.concat([
|
|
70
|
+
constants_js_1.DISCRIMINATORS.create_barrel_token,
|
|
71
|
+
writeU8(decimals),
|
|
72
|
+
writeU8(variant),
|
|
73
|
+
writePubkey(adminFeeRecipient),
|
|
74
|
+
writePubkey(creatorFeeRecipient),
|
|
75
|
+
writeU16LE(traderRewardsShareBps),
|
|
76
|
+
writeString(name),
|
|
77
|
+
writeString(symbol),
|
|
78
|
+
writeString(uri),
|
|
79
|
+
]);
|
|
80
|
+
const createIx = new web3_js_1.TransactionInstruction({
|
|
81
|
+
programId,
|
|
82
|
+
keys: [
|
|
83
|
+
{ pubkey: tokenMint, isWritable: true, isSigner: true },
|
|
84
|
+
{ pubkey: bondingCurve, isWritable: true, isSigner: false },
|
|
85
|
+
{ pubkey: tokenVault, isWritable: true, isSigner: false },
|
|
86
|
+
{ pubkey: bondingAuthority, isWritable: false, isSigner: false },
|
|
87
|
+
{ pubkey: metadata, isWritable: true, isSigner: false },
|
|
88
|
+
{ pubkey: constants_js_1.TOKEN_METADATA_PROGRAM_ID, isWritable: false, isSigner: false },
|
|
89
|
+
{ pubkey: payer, isWritable: true, isSigner: true },
|
|
90
|
+
{ pubkey: web3_js_1.SystemProgram.programId, isWritable: false, isSigner: false },
|
|
91
|
+
{ pubkey: spl_token_1.TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
|
|
92
|
+
{ pubkey: web3_js_1.SYSVAR_RENT_PUBKEY, isWritable: false, isSigner: false },
|
|
93
|
+
],
|
|
94
|
+
data,
|
|
95
|
+
});
|
|
96
|
+
return {
|
|
97
|
+
instructions: [createIx],
|
|
98
|
+
mintKeypair,
|
|
99
|
+
};
|
|
100
|
+
}
|
package/dist/curve.js
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Bonding Curve Operations
|
|
3
4
|
* Buy and sell tokens on the bonding curve
|
|
4
5
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.getBuyQuote = getBuyQuote;
|
|
8
|
+
exports.getSellQuote = getSellQuote;
|
|
9
|
+
exports.buildBuyOnCurveInstruction = buildBuyOnCurveInstruction;
|
|
10
|
+
exports.buildSellOnCurveInstruction = buildSellOnCurveInstruction;
|
|
11
|
+
exports.buildSellMaxOnCurveInstruction = buildSellMaxOnCurveInstruction;
|
|
12
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
13
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
14
|
+
const constants_js_1 = require("./constants.js");
|
|
15
|
+
const pda_js_1 = require("./pda.js");
|
|
16
|
+
const accounts_js_1 = require("./accounts.js");
|
|
10
17
|
// ============= Buffer Helpers =============
|
|
11
18
|
function writeU64LE(n) {
|
|
12
19
|
const b = Buffer.alloc(8);
|
|
@@ -19,8 +26,8 @@ function writeU64LE(n) {
|
|
|
19
26
|
* Uses amplified constant product formula matching the program:
|
|
20
27
|
* k = vSol_eff * vToken_eff where _eff = base * amp_bps / 10000
|
|
21
28
|
*/
|
|
22
|
-
|
|
23
|
-
const state = await getBondingCurveState(connection, tokenMint, programId);
|
|
29
|
+
async function getBuyQuote(connection, tokenMint, solIn, programId) {
|
|
30
|
+
const state = await (0, accounts_js_1.getBondingCurveState)(connection, tokenMint, programId);
|
|
24
31
|
if (!state || state.paused)
|
|
25
32
|
return null;
|
|
26
33
|
const feeBps = BigInt(state.feeBps);
|
|
@@ -46,8 +53,8 @@ export async function getBuyQuote(connection, tokenMint, solIn, programId) {
|
|
|
46
53
|
const newVSolEff = vSolEff + netCost;
|
|
47
54
|
const newVTokenEff = kDiv;
|
|
48
55
|
// Price impact
|
|
49
|
-
const priceBeforeLamports = vTokenEff > 0n ? (vSolEff * LAMPORTS_PER_SOL) / vTokenEff : 0n;
|
|
50
|
-
const priceAfterLamports = newVTokenEff > 0n ? (newVSolEff * LAMPORTS_PER_SOL) / newVTokenEff : 0n;
|
|
56
|
+
const priceBeforeLamports = vTokenEff > 0n ? (vSolEff * constants_js_1.LAMPORTS_PER_SOL) / vTokenEff : 0n;
|
|
57
|
+
const priceAfterLamports = newVTokenEff > 0n ? (newVSolEff * constants_js_1.LAMPORTS_PER_SOL) / newVTokenEff : 0n;
|
|
51
58
|
const priceImpactBps = priceBeforeLamports > 0n
|
|
52
59
|
? Number(((priceAfterLamports - priceBeforeLamports) * 10000n) / priceBeforeLamports)
|
|
53
60
|
: 0;
|
|
@@ -57,7 +64,7 @@ export async function getBuyQuote(connection, tokenMint, solIn, programId) {
|
|
|
57
64
|
adminFee,
|
|
58
65
|
creatorFee,
|
|
59
66
|
holderRewards,
|
|
60
|
-
pricePerToken: tokensOut > 0n ? (solIn * TOKEN_DECIMALS_MULTIPLIER) / tokensOut : 0n,
|
|
67
|
+
pricePerToken: tokensOut > 0n ? (solIn * constants_js_1.TOKEN_DECIMALS_MULTIPLIER) / tokensOut : 0n,
|
|
61
68
|
priceImpactBps,
|
|
62
69
|
};
|
|
63
70
|
}
|
|
@@ -65,8 +72,8 @@ export async function getBuyQuote(connection, tokenMint, solIn, programId) {
|
|
|
65
72
|
* Calculate sell quote for bonding curve
|
|
66
73
|
* Uses amplified constant product formula matching the program
|
|
67
74
|
*/
|
|
68
|
-
|
|
69
|
-
const state = await getBondingCurveState(connection, tokenMint, programId);
|
|
75
|
+
async function getSellQuote(connection, tokenMint, tokensIn, programId) {
|
|
76
|
+
const state = await (0, accounts_js_1.getBondingCurveState)(connection, tokenMint, programId);
|
|
70
77
|
if (!state || state.paused)
|
|
71
78
|
return null;
|
|
72
79
|
// Amplified constant product formula (matches program)
|
|
@@ -90,8 +97,8 @@ export async function getSellQuote(connection, tokenMint, tokensIn, programId) {
|
|
|
90
97
|
const newVTokenEff = denominator;
|
|
91
98
|
const newVSolEff = kDiv;
|
|
92
99
|
// Price impact
|
|
93
|
-
const priceBeforeLamports = vTokenEff > 0n ? (vSolEff * LAMPORTS_PER_SOL) / vTokenEff : 0n;
|
|
94
|
-
const priceAfterLamports = newVTokenEff > 0n ? (newVSolEff * LAMPORTS_PER_SOL) / newVTokenEff : 0n;
|
|
100
|
+
const priceBeforeLamports = vTokenEff > 0n ? (vSolEff * constants_js_1.LAMPORTS_PER_SOL) / vTokenEff : 0n;
|
|
101
|
+
const priceAfterLamports = newVTokenEff > 0n ? (newVSolEff * constants_js_1.LAMPORTS_PER_SOL) / newVTokenEff : 0n;
|
|
95
102
|
const priceImpactBps = priceBeforeLamports > 0n
|
|
96
103
|
? Number(((priceBeforeLamports - priceAfterLamports) * 10000n) / priceBeforeLamports)
|
|
97
104
|
: 0;
|
|
@@ -101,7 +108,7 @@ export async function getSellQuote(connection, tokenMint, tokensIn, programId) {
|
|
|
101
108
|
adminFee,
|
|
102
109
|
creatorFee,
|
|
103
110
|
holderRewards,
|
|
104
|
-
pricePerToken: tokensIn > 0n ? (solOutNetEff * TOKEN_DECIMALS_MULTIPLIER) / tokensIn : 0n,
|
|
111
|
+
pricePerToken: tokensIn > 0n ? (solOutNetEff * constants_js_1.TOKEN_DECIMALS_MULTIPLIER) / tokensIn : 0n,
|
|
105
112
|
priceImpactBps,
|
|
106
113
|
};
|
|
107
114
|
}
|
|
@@ -112,31 +119,31 @@ export async function getSellQuote(connection, tokenMint, tokensIn, programId) {
|
|
|
112
119
|
* IMPORTANT: Fee recipients are read from on-chain state and cannot be modified.
|
|
113
120
|
* The program enforces that fees go to the correct recipients.
|
|
114
121
|
*/
|
|
115
|
-
|
|
122
|
+
async function buildBuyOnCurveInstruction(connection, params, programId) {
|
|
116
123
|
const { tokenMint, buyer, lamportsIn } = params;
|
|
117
124
|
// Fetch curve state to get fee recipients (enforced on-chain)
|
|
118
|
-
const state = await getBondingCurveState(connection, tokenMint, programId);
|
|
125
|
+
const state = await (0, accounts_js_1.getBondingCurveState)(connection, tokenMint, programId);
|
|
119
126
|
if (!state) {
|
|
120
127
|
throw new Error('Bonding curve not found for this token');
|
|
121
128
|
}
|
|
122
129
|
if (state.paused) {
|
|
123
130
|
throw new Error('Bonding curve is paused');
|
|
124
131
|
}
|
|
125
|
-
const bondingCurve = getBondingCurvePda(tokenMint, programId);
|
|
126
|
-
const bondingAuthority = getBondingAuthorityPda(bondingCurve, programId);
|
|
127
|
-
const solEscrow = getSolEscrowPda(bondingCurve, programId);
|
|
128
|
-
const buyerAta = getAssociatedTokenAddressSync(tokenMint, buyer);
|
|
129
|
-
const holderRewardAccount = getHolderRewardPda(tokenMint, buyer, programId);
|
|
132
|
+
const bondingCurve = (0, pda_js_1.getBondingCurvePda)(tokenMint, programId);
|
|
133
|
+
const bondingAuthority = (0, pda_js_1.getBondingAuthorityPda)(bondingCurve, programId);
|
|
134
|
+
const solEscrow = (0, pda_js_1.getSolEscrowPda)(bondingCurve, programId);
|
|
135
|
+
const buyerAta = (0, spl_token_1.getAssociatedTokenAddressSync)(tokenMint, buyer);
|
|
136
|
+
const holderRewardAccount = (0, pda_js_1.getHolderRewardPda)(tokenMint, buyer, programId);
|
|
130
137
|
const instructions = [];
|
|
131
138
|
// Check if buyer's ATA exists, create if needed
|
|
132
139
|
try {
|
|
133
|
-
await getAccount(connection, buyerAta);
|
|
140
|
+
await (0, spl_token_1.getAccount)(connection, buyerAta);
|
|
134
141
|
}
|
|
135
142
|
catch {
|
|
136
|
-
instructions.push(createAssociatedTokenAccountInstruction(buyer, buyerAta, buyer, tokenMint));
|
|
143
|
+
instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(buyer, buyerAta, buyer, tokenMint));
|
|
137
144
|
}
|
|
138
145
|
// Build buy instruction with fee recipients from on-chain state
|
|
139
|
-
const buyIx = new TransactionInstruction({
|
|
146
|
+
const buyIx = new web3_js_1.TransactionInstruction({
|
|
140
147
|
programId,
|
|
141
148
|
keys: [
|
|
142
149
|
{ pubkey: bondingCurve, isWritable: true, isSigner: false },
|
|
@@ -151,10 +158,10 @@ export async function buildBuyOnCurveInstruction(connection, params, programId)
|
|
|
151
158
|
{ pubkey: state.creatorFeeRecipient, isWritable: true, isSigner: false },
|
|
152
159
|
// Holder reward account - auto-initialized by program
|
|
153
160
|
{ pubkey: holderRewardAccount, isWritable: true, isSigner: false },
|
|
154
|
-
{ pubkey: TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
|
|
155
|
-
{ pubkey: SystemProgram.programId, isWritable: false, isSigner: false },
|
|
161
|
+
{ pubkey: spl_token_1.TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
|
|
162
|
+
{ pubkey: web3_js_1.SystemProgram.programId, isWritable: false, isSigner: false },
|
|
156
163
|
],
|
|
157
|
-
data: Buffer.concat([DISCRIMINATORS.buy_on_curve, writeU64LE(lamportsIn)]),
|
|
164
|
+
data: Buffer.concat([constants_js_1.DISCRIMINATORS.buy_on_curve, writeU64LE(lamportsIn)]),
|
|
158
165
|
});
|
|
159
166
|
instructions.push(buyIx);
|
|
160
167
|
return instructions;
|
|
@@ -165,22 +172,22 @@ export async function buildBuyOnCurveInstruction(connection, params, programId)
|
|
|
165
172
|
* IMPORTANT: Fee recipients are read from on-chain state and cannot be modified.
|
|
166
173
|
* Includes holder reward account in remaining_accounts for auto-payout.
|
|
167
174
|
*/
|
|
168
|
-
|
|
175
|
+
async function buildSellOnCurveInstruction(connection, params, programId) {
|
|
169
176
|
const { tokenMint, seller, tokenAmount } = params;
|
|
170
177
|
// Fetch curve state to get fee recipients (enforced on-chain)
|
|
171
|
-
const state = await getBondingCurveState(connection, tokenMint, programId);
|
|
178
|
+
const state = await (0, accounts_js_1.getBondingCurveState)(connection, tokenMint, programId);
|
|
172
179
|
if (!state) {
|
|
173
180
|
throw new Error('Bonding curve not found for this token');
|
|
174
181
|
}
|
|
175
182
|
if (state.paused) {
|
|
176
183
|
throw new Error('Bonding curve is paused');
|
|
177
184
|
}
|
|
178
|
-
const bondingCurve = getBondingCurvePda(tokenMint, programId);
|
|
179
|
-
const bondingAuthority = getBondingAuthorityPda(bondingCurve, programId);
|
|
180
|
-
const solEscrow = getSolEscrowPda(bondingCurve, programId);
|
|
181
|
-
const sellerAta = getAssociatedTokenAddressSync(tokenMint, seller);
|
|
182
|
-
const holderRewardAccount = getHolderRewardPda(tokenMint, seller, programId);
|
|
183
|
-
const sellIx = new TransactionInstruction({
|
|
185
|
+
const bondingCurve = (0, pda_js_1.getBondingCurvePda)(tokenMint, programId);
|
|
186
|
+
const bondingAuthority = (0, pda_js_1.getBondingAuthorityPda)(bondingCurve, programId);
|
|
187
|
+
const solEscrow = (0, pda_js_1.getSolEscrowPda)(bondingCurve, programId);
|
|
188
|
+
const sellerAta = (0, spl_token_1.getAssociatedTokenAddressSync)(tokenMint, seller);
|
|
189
|
+
const holderRewardAccount = (0, pda_js_1.getHolderRewardPda)(tokenMint, seller, programId);
|
|
190
|
+
const sellIx = new web3_js_1.TransactionInstruction({
|
|
184
191
|
programId,
|
|
185
192
|
keys: [
|
|
186
193
|
{ pubkey: bondingCurve, isWritable: true, isSigner: false },
|
|
@@ -193,12 +200,12 @@ export async function buildSellOnCurveInstruction(connection, params, programId)
|
|
|
193
200
|
// Fee recipients - read from on-chain state, cannot be modified
|
|
194
201
|
{ pubkey: state.adminFeeRecipient, isWritable: true, isSigner: false },
|
|
195
202
|
{ pubkey: state.creatorFeeRecipient, isWritable: true, isSigner: false },
|
|
196
|
-
{ pubkey: TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
|
|
197
|
-
{ pubkey: SystemProgram.programId, isWritable: false, isSigner: false },
|
|
203
|
+
{ pubkey: spl_token_1.TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
|
|
204
|
+
{ pubkey: web3_js_1.SystemProgram.programId, isWritable: false, isSigner: false },
|
|
198
205
|
// Holder reward account in remaining_accounts for auto-payout
|
|
199
206
|
{ pubkey: holderRewardAccount, isWritable: true, isSigner: false },
|
|
200
207
|
],
|
|
201
|
-
data: Buffer.concat([DISCRIMINATORS.sell_on_curve, writeU64LE(tokenAmount)]),
|
|
208
|
+
data: Buffer.concat([constants_js_1.DISCRIMINATORS.sell_on_curve, writeU64LE(tokenAmount)]),
|
|
202
209
|
});
|
|
203
210
|
return [sellIx];
|
|
204
211
|
}
|
|
@@ -206,22 +213,22 @@ export async function buildSellOnCurveInstruction(connection, params, programId)
|
|
|
206
213
|
* Build sell_max_on_curve instruction (sell entire balance)
|
|
207
214
|
* Includes holder reward account in remaining_accounts for auto-payout.
|
|
208
215
|
*/
|
|
209
|
-
|
|
216
|
+
async function buildSellMaxOnCurveInstruction(connection, params, programId) {
|
|
210
217
|
const { tokenMint, seller } = params;
|
|
211
218
|
// Fetch curve state to get fee recipients (enforced on-chain)
|
|
212
|
-
const state = await getBondingCurveState(connection, tokenMint, programId);
|
|
219
|
+
const state = await (0, accounts_js_1.getBondingCurveState)(connection, tokenMint, programId);
|
|
213
220
|
if (!state) {
|
|
214
221
|
throw new Error('Bonding curve not found for this token');
|
|
215
222
|
}
|
|
216
223
|
if (state.paused) {
|
|
217
224
|
throw new Error('Bonding curve is paused');
|
|
218
225
|
}
|
|
219
|
-
const bondingCurve = getBondingCurvePda(tokenMint, programId);
|
|
220
|
-
const bondingAuthority = getBondingAuthorityPda(bondingCurve, programId);
|
|
221
|
-
const solEscrow = getSolEscrowPda(bondingCurve, programId);
|
|
222
|
-
const sellerAta = getAssociatedTokenAddressSync(tokenMint, seller);
|
|
223
|
-
const holderRewardAccount = getHolderRewardPda(tokenMint, seller, programId);
|
|
224
|
-
const sellMaxIx = new TransactionInstruction({
|
|
226
|
+
const bondingCurve = (0, pda_js_1.getBondingCurvePda)(tokenMint, programId);
|
|
227
|
+
const bondingAuthority = (0, pda_js_1.getBondingAuthorityPda)(bondingCurve, programId);
|
|
228
|
+
const solEscrow = (0, pda_js_1.getSolEscrowPda)(bondingCurve, programId);
|
|
229
|
+
const sellerAta = (0, spl_token_1.getAssociatedTokenAddressSync)(tokenMint, seller);
|
|
230
|
+
const holderRewardAccount = (0, pda_js_1.getHolderRewardPda)(tokenMint, seller, programId);
|
|
231
|
+
const sellMaxIx = new web3_js_1.TransactionInstruction({
|
|
225
232
|
programId,
|
|
226
233
|
keys: [
|
|
227
234
|
{ pubkey: bondingCurve, isWritable: true, isSigner: false },
|
|
@@ -234,13 +241,12 @@ export async function buildSellMaxOnCurveInstruction(connection, params, program
|
|
|
234
241
|
// Fee recipients - read from on-chain state, cannot be modified
|
|
235
242
|
{ pubkey: state.adminFeeRecipient, isWritable: true, isSigner: false },
|
|
236
243
|
{ pubkey: state.creatorFeeRecipient, isWritable: true, isSigner: false },
|
|
237
|
-
{ pubkey: TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
|
|
238
|
-
{ pubkey: SystemProgram.programId, isWritable: false, isSigner: false },
|
|
244
|
+
{ pubkey: spl_token_1.TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
|
|
245
|
+
{ pubkey: web3_js_1.SystemProgram.programId, isWritable: false, isSigner: false },
|
|
239
246
|
// Holder reward account in remaining_accounts for auto-payout
|
|
240
247
|
{ pubkey: holderRewardAccount, isWritable: true, isSigner: false },
|
|
241
248
|
],
|
|
242
|
-
data: DISCRIMINATORS.sell_max_on_curve,
|
|
249
|
+
data: constants_js_1.DISCRIMINATORS.sell_max_on_curve,
|
|
243
250
|
});
|
|
244
251
|
return [sellMaxIx];
|
|
245
252
|
}
|
|
246
|
-
//# sourceMappingURL=curve.js.map
|