@coinbarrel/sdk 1.0.1 → 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.
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+ /**
3
+ * Token Metadata Fetching
4
+ * Read Metaplex token metadata for CoinBarrel tokens
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.getMetadataPda = getMetadataPda;
8
+ exports.parseMetaplexMetadata = parseMetaplexMetadata;
9
+ exports.getTokenMetadata = getTokenMetadata;
10
+ exports.getTokenMetadataJson = getTokenMetadataJson;
11
+ exports.batchGetTokenMetadata = batchGetTokenMetadata;
12
+ const web3_js_1 = require("@solana/web3.js");
13
+ const constants_js_1 = require("./constants.js");
14
+ // ============= PDA =============
15
+ /**
16
+ * Derive Metaplex metadata PDA for a token mint
17
+ */
18
+ function getMetadataPda(mint) {
19
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('metadata'), constants_js_1.TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer()], constants_js_1.TOKEN_METADATA_PROGRAM_ID);
20
+ return pda;
21
+ }
22
+ // ============= Parsing =============
23
+ /**
24
+ * Read a length-prefixed string from buffer
25
+ */
26
+ function readLengthPrefixedString(data, offset) {
27
+ const length = data.readUInt32LE(offset);
28
+ const start = offset + 4;
29
+ const end = start + length;
30
+ const value = data
31
+ .subarray(start, end)
32
+ .toString('utf8')
33
+ .replace(/\0/g, '')
34
+ .trim();
35
+ return { value, nextOffset: end };
36
+ }
37
+ /**
38
+ * Parse Metaplex metadata from raw account data
39
+ *
40
+ * Layout:
41
+ * - key: 1 byte
42
+ * - update_authority: 32 bytes
43
+ * - mint: 32 bytes
44
+ * - name: 4 bytes length + string
45
+ * - symbol: 4 bytes length + string
46
+ * - uri: 4 bytes length + string
47
+ */
48
+ function parseMetaplexMetadata(data) {
49
+ try {
50
+ if (!data || data.length < 65)
51
+ return null;
52
+ // Skip: key (1) + update_authority (32) + mint (32) = 65 bytes
53
+ let offset = 1 + 32 + 32;
54
+ // Name
55
+ const name = readLengthPrefixedString(data, offset);
56
+ offset = name.nextOffset;
57
+ // Symbol
58
+ const symbol = readLengthPrefixedString(data, offset);
59
+ offset = symbol.nextOffset;
60
+ // URI
61
+ const uri = readLengthPrefixedString(data, offset);
62
+ return {
63
+ name: name.value,
64
+ symbol: symbol.value,
65
+ uri: uri.value,
66
+ };
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ }
72
+ // ============= Fetching =============
73
+ /**
74
+ * Fetch on-chain token metadata from Metaplex
75
+ *
76
+ * Returns the name, symbol, and URI stored on-chain.
77
+ * Use `getTokenMetadataJson` to also fetch the off-chain JSON.
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const metadata = await getTokenMetadata(connection, tokenMint);
82
+ * if (metadata) {
83
+ * console.log(metadata.name); // "My Token"
84
+ * console.log(metadata.symbol); // "MTK"
85
+ * console.log(metadata.uri); // "https://..."
86
+ * }
87
+ * ```
88
+ */
89
+ async function getTokenMetadata(connection, mint) {
90
+ try {
91
+ const metadataPda = getMetadataPda(mint);
92
+ const accountInfo = await connection.getAccountInfo(metadataPda);
93
+ if (!accountInfo || !accountInfo.data || accountInfo.data.length === 0) {
94
+ return null;
95
+ }
96
+ return parseMetaplexMetadata(accountInfo.data);
97
+ }
98
+ catch {
99
+ return null;
100
+ }
101
+ }
102
+ /**
103
+ * Fetch on-chain Metaplex metadata and then fetch the off-chain JSON pointed to by the URI.
104
+ */
105
+ async function getTokenMetadataJson(connection, mint, options) {
106
+ const meta = await getTokenMetadata(connection, mint);
107
+ if (!meta)
108
+ return null;
109
+ const uri = (meta.uri ?? '').replace(/\0/g, '').trim();
110
+ if (!uri)
111
+ return { ...meta };
112
+ try {
113
+ const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
114
+ const timeoutMs = options?.timeoutMs;
115
+ const timeout = controller && typeof timeoutMs === 'number' && timeoutMs > 0
116
+ ? setTimeout(() => controller.abort(), timeoutMs)
117
+ : null;
118
+ const resp = await fetch(uri, {
119
+ signal: controller?.signal,
120
+ headers: { accept: 'application/json' },
121
+ });
122
+ if (!resp.ok)
123
+ return { ...meta };
124
+ const json = (await resp.json());
125
+ if (timeout)
126
+ clearTimeout(timeout);
127
+ // Best-effort map of common social fields
128
+ const properties = json.properties && typeof json.properties === 'object'
129
+ ? json.properties
130
+ : undefined;
131
+ const extensions = (json.extensions && typeof json.extensions === 'object'
132
+ ? json.extensions
133
+ : undefined) ||
134
+ (properties?.extensions && typeof properties.extensions === 'object'
135
+ ? properties.extensions
136
+ : undefined);
137
+ const twitter = (typeof json.twitter === 'string' && json.twitter) ||
138
+ (typeof extensions?.twitter === 'string' && extensions.twitter) ||
139
+ undefined;
140
+ const telegram = (typeof json.telegram === 'string' && json.telegram) ||
141
+ (typeof extensions?.telegram === 'string' && extensions.telegram) ||
142
+ undefined;
143
+ const website = (typeof json.website === 'string' && json.website) ||
144
+ (typeof extensions?.website === 'string' && extensions.website) ||
145
+ undefined;
146
+ return {
147
+ ...meta,
148
+ ...json,
149
+ // ensure we always surface these normalized keys when available
150
+ twitter,
151
+ telegram,
152
+ website,
153
+ };
154
+ }
155
+ catch {
156
+ return { ...meta };
157
+ }
158
+ }
159
+ /**
160
+ * Batch fetch metadata for multiple tokens
161
+ *
162
+ * More efficient than calling getTokenMetadata individually.
163
+ *
164
+ * @param connection - Solana RPC connection
165
+ * @param mints - Array of token mint addresses
166
+ * @returns Map of mint address string to metadata
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * const mints = [mint1, mint2, mint3];
171
+ * const metadataMap = await batchGetTokenMetadata(connection, mints);
172
+ *
173
+ * for (const [mintStr, metadata] of metadataMap) {
174
+ * console.log(`${mintStr}: ${metadata?.name}`);
175
+ * }
176
+ * ```
177
+ */
178
+ async function batchGetTokenMetadata(connection, mints) {
179
+ const results = new Map();
180
+ if (mints.length === 0) {
181
+ return results;
182
+ }
183
+ // Derive all metadata PDAs
184
+ const pdas = mints.map((mint) => ({
185
+ mint,
186
+ pda: getMetadataPda(mint),
187
+ }));
188
+ // Batch fetch all accounts
189
+ try {
190
+ const accountInfos = await connection.getMultipleAccountsInfo(pdas.map((p) => p.pda));
191
+ // Parse each result
192
+ for (let i = 0; i < pdas.length; i++) {
193
+ const mintStr = pdas[i].mint.toBase58();
194
+ const accountInfo = accountInfos[i];
195
+ if (accountInfo && accountInfo.data && accountInfo.data.length > 0) {
196
+ const metadata = parseMetaplexMetadata(accountInfo.data);
197
+ results.set(mintStr, metadata);
198
+ }
199
+ else {
200
+ results.set(mintStr, null);
201
+ }
202
+ }
203
+ }
204
+ catch {
205
+ // If batch fails, set all to null
206
+ for (const { mint } of pdas) {
207
+ results.set(mint.toBase58(), null);
208
+ }
209
+ }
210
+ return results;
211
+ }
package/dist/pda.js CHANGED
@@ -1,77 +1,90 @@
1
+ "use strict";
1
2
  /**
2
3
  * PDA Derivation Helpers
3
4
  * All Program Derived Addresses for CoinBarrel AMM
4
5
  */
5
- import { PublicKey } from '@solana/web3.js';
6
- import { SEEDS, NATIVE_MINT } from './constants.js';
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.getBondingCurvePda = getBondingCurvePda;
8
+ exports.getBondingAuthorityPda = getBondingAuthorityPda;
9
+ exports.getSolEscrowPda = getSolEscrowPda;
10
+ exports.getPoolPda = getPoolPda;
11
+ exports.getPoolAuthorityPda = getPoolAuthorityPda;
12
+ exports.getVaultPda = getVaultPda;
13
+ exports.getPoolWsolVaultPda = getPoolWsolVaultPda;
14
+ exports.getPoolTokenVaultPda = getPoolTokenVaultPda;
15
+ exports.getLpMintPda = getLpMintPda;
16
+ exports.getLpVaultPda = getLpVaultPda;
17
+ exports.getHolderRewardPda = getHolderRewardPda;
18
+ const web3_js_1 = require("@solana/web3.js");
19
+ const constants_js_1 = require("./constants.js");
7
20
  // ============= Bonding Curve PDAs =============
8
21
  /**
9
22
  * Derive bonding curve PDA for a token mint
10
23
  */
11
- export function getBondingCurvePda(mint, programId) {
12
- const [pda] = PublicKey.findProgramAddressSync([SEEDS.BONDING, mint.toBuffer()], programId);
24
+ function getBondingCurvePda(mint, programId) {
25
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([constants_js_1.SEEDS.BONDING, mint.toBuffer()], programId);
13
26
  return pda;
14
27
  }
15
28
  /**
16
29
  * Derive bonding authority PDA (signs transfers from curve)
17
30
  */
18
- export function getBondingAuthorityPda(bondingCurve, programId) {
19
- const [pda] = PublicKey.findProgramAddressSync([SEEDS.BONDING_AUTHORITY, bondingCurve.toBuffer()], programId);
31
+ function getBondingAuthorityPda(bondingCurve, programId) {
32
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([constants_js_1.SEEDS.BONDING_AUTHORITY, bondingCurve.toBuffer()], programId);
20
33
  return pda;
21
34
  }
22
35
  /**
23
36
  * Derive SOL escrow PDA for bonding curve
24
37
  */
25
- export function getSolEscrowPda(bondingCurve, programId) {
26
- const [pda] = PublicKey.findProgramAddressSync([SEEDS.BONDING_SOL, bondingCurve.toBuffer()], programId);
38
+ function getSolEscrowPda(bondingCurve, programId) {
39
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([constants_js_1.SEEDS.BONDING_SOL, bondingCurve.toBuffer()], programId);
27
40
  return pda;
28
41
  }
29
42
  // ============= AMM Pool PDAs =============
30
43
  /**
31
44
  * Derive pool PDA for a WSOL <-> Token pair
32
45
  */
33
- export function getPoolPda(tokenMint, programId) {
34
- const [pda] = PublicKey.findProgramAddressSync([SEEDS.POOL, NATIVE_MINT.toBuffer(), tokenMint.toBuffer()], programId);
46
+ function getPoolPda(tokenMint, programId) {
47
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([constants_js_1.SEEDS.POOL, constants_js_1.NATIVE_MINT.toBuffer(), tokenMint.toBuffer()], programId);
35
48
  return pda;
36
49
  }
37
50
  /**
38
51
  * Derive pool authority PDA (signs transfers from pool vaults)
39
52
  */
40
- export function getPoolAuthorityPda(pool, programId) {
41
- const [pda] = PublicKey.findProgramAddressSync([SEEDS.AUTHORITY, pool.toBuffer()], programId);
53
+ function getPoolAuthorityPda(pool, programId) {
54
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([constants_js_1.SEEDS.AUTHORITY, pool.toBuffer()], programId);
42
55
  return pda;
43
56
  }
44
57
  /**
45
58
  * Derive vault PDA for a pool + mint
46
59
  */
47
- export function getVaultPda(pool, mint, programId) {
48
- const [pda] = PublicKey.findProgramAddressSync([SEEDS.VAULT, pool.toBuffer(), mint.toBuffer()], programId);
60
+ function getVaultPda(pool, mint, programId) {
61
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([constants_js_1.SEEDS.VAULT, pool.toBuffer(), mint.toBuffer()], programId);
49
62
  return pda;
50
63
  }
51
64
  /**
52
65
  * Derive WSOL vault PDA for a pool
53
66
  */
54
- export function getPoolWsolVaultPda(pool, programId) {
55
- return getVaultPda(pool, NATIVE_MINT, programId);
67
+ function getPoolWsolVaultPda(pool, programId) {
68
+ return getVaultPda(pool, constants_js_1.NATIVE_MINT, programId);
56
69
  }
57
70
  /**
58
71
  * Derive token vault PDA for a pool
59
72
  */
60
- export function getPoolTokenVaultPda(pool, tokenMint, programId) {
73
+ function getPoolTokenVaultPda(pool, tokenMint, programId) {
61
74
  return getVaultPda(pool, tokenMint, programId);
62
75
  }
63
76
  /**
64
77
  * Derive LP mint PDA for a pool
65
78
  */
66
- export function getLpMintPda(pool, programId) {
67
- const [pda] = PublicKey.findProgramAddressSync([SEEDS.LP_MINT, pool.toBuffer()], programId);
79
+ function getLpMintPda(pool, programId) {
80
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([constants_js_1.SEEDS.LP_MINT, pool.toBuffer()], programId);
68
81
  return pda;
69
82
  }
70
83
  /**
71
84
  * Derive LP vault PDA (holds burned/locked LP tokens)
72
85
  */
73
- export function getLpVaultPda(pool, programId) {
74
- const [pda] = PublicKey.findProgramAddressSync([SEEDS.LP_VAULT, pool.toBuffer()], programId);
86
+ function getLpVaultPda(pool, programId) {
87
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([constants_js_1.SEEDS.LP_VAULT, pool.toBuffer()], programId);
75
88
  return pda;
76
89
  }
77
90
  // ============= Holder Reward PDAs =============
@@ -79,8 +92,7 @@ export function getLpVaultPda(pool, programId) {
79
92
  * Derive holder reward account PDA for a user + token
80
93
  * Used for tracking holder rewards across buys/sells
81
94
  */
82
- export function getHolderRewardPda(tokenMint, holder, programId) {
83
- const [pda] = PublicKey.findProgramAddressSync([SEEDS.HOLDER_REWARD, tokenMint.toBuffer(), holder.toBuffer()], programId);
95
+ function getHolderRewardPda(tokenMint, holder, programId) {
96
+ const [pda] = web3_js_1.PublicKey.findProgramAddressSync([constants_js_1.SEEDS.HOLDER_REWARD, tokenMint.toBuffer(), holder.toBuffer()], programId);
84
97
  return pda;
85
98
  }
86
- //# sourceMappingURL=pda.js.map
package/dist/pool.js CHANGED
@@ -1,12 +1,19 @@
1
+ "use strict";
1
2
  /**
2
3
  * AMM Pool Operations
3
4
  * Swap tokens on graduated AMM pools
4
5
  */
5
- import { SystemProgram, TransactionInstruction, } from "@solana/web3.js";
6
- import { TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync, createAssociatedTokenAccountInstruction, createCloseAccountInstruction, getAccount, } from "@solana/spl-token";
7
- import { DISCRIMINATORS, NATIVE_MINT } from "./constants.js";
8
- import { getPoolPda, getPoolAuthorityPda, getHolderRewardPda, } from "./pda.js";
9
- import { getPoolState, getPoolBalances } from "./accounts.js";
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.getSwapSolToTokenQuote = getSwapSolToTokenQuote;
8
+ exports.getSwapTokenToSolQuote = getSwapTokenToSolQuote;
9
+ exports.buildSwapSolToTokenInstruction = buildSwapSolToTokenInstruction;
10
+ exports.buildSwapTokenToSolInstruction = buildSwapTokenToSolInstruction;
11
+ exports.buildSwapTokenToSolMaxInstruction = buildSwapTokenToSolMaxInstruction;
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);
@@ -17,9 +24,9 @@ function writeU64LE(n) {
17
24
  /**
18
25
  * Calculate swap quote for SOL -> Token
19
26
  */
20
- export async function getSwapSolToTokenQuote(connection, tokenMint, solIn, programId) {
21
- const balances = await getPoolBalances(connection, tokenMint, programId);
22
- const state = await getPoolState(connection, tokenMint, programId);
27
+ async function getSwapSolToTokenQuote(connection, tokenMint, solIn, programId) {
28
+ const balances = await (0, accounts_js_1.getPoolBalances)(connection, tokenMint, programId);
29
+ const state = await (0, accounts_js_1.getPoolState)(connection, tokenMint, programId);
23
30
  if (!balances || !state)
24
31
  return null;
25
32
  const { solBalance, tokenBalance } = balances;
@@ -48,9 +55,9 @@ export async function getSwapSolToTokenQuote(connection, tokenMint, solIn, progr
48
55
  /**
49
56
  * Calculate swap quote for Token -> SOL
50
57
  */
51
- export async function getSwapTokenToSolQuote(connection, tokenMint, tokensIn, programId) {
52
- const balances = await getPoolBalances(connection, tokenMint, programId);
53
- const state = await getPoolState(connection, tokenMint, programId);
58
+ async function getSwapTokenToSolQuote(connection, tokenMint, tokensIn, programId) {
59
+ const balances = await (0, accounts_js_1.getPoolBalances)(connection, tokenMint, programId);
60
+ const state = await (0, accounts_js_1.getPoolState)(connection, tokenMint, programId);
54
61
  if (!balances || !state)
55
62
  return null;
56
63
  const { solBalance, tokenBalance } = balances;
@@ -83,31 +90,31 @@ export async function getSwapTokenToSolQuote(connection, tokenMint, tokensIn, pr
83
90
  * IMPORTANT: Fee recipients are read from on-chain state and cannot be modified.
84
91
  * The program enforces that fees go to the correct recipients.
85
92
  */
86
- export async function buildSwapSolToTokenInstruction(connection, params, programId) {
93
+ async function buildSwapSolToTokenInstruction(connection, params, programId) {
87
94
  const { tokenMint, user, lamportsIn, minimumAmountOut } = params;
88
95
  // Fetch pool state to get fee recipients and vault addresses (enforced on-chain)
89
- const state = await getPoolState(connection, tokenMint, programId);
96
+ const state = await (0, accounts_js_1.getPoolState)(connection, tokenMint, programId);
90
97
  if (!state) {
91
98
  throw new Error("Pool not found for this token");
92
99
  }
93
100
  // Determine which vault is WSOL and which is the token based on stored mints
94
- const isTokenANative = state.tokenAMint.equals(NATIVE_MINT);
101
+ const isTokenANative = state.tokenAMint.equals(constants_js_1.NATIVE_MINT);
95
102
  const wsolVault = isTokenANative ? state.tokenAVault : state.tokenBVault;
96
103
  const tokenVault = isTokenANative ? state.tokenBVault : state.tokenAVault;
97
- const pool = getPoolPda(tokenMint, programId);
98
- const authority = getPoolAuthorityPda(pool, programId);
99
- const userTokenAta = getAssociatedTokenAddressSync(tokenMint, user);
100
- const holderRewardAccount = getHolderRewardPda(tokenMint, user, programId);
104
+ const pool = (0, pda_js_1.getPoolPda)(tokenMint, programId);
105
+ const authority = (0, pda_js_1.getPoolAuthorityPda)(pool, programId);
106
+ const userTokenAta = (0, spl_token_1.getAssociatedTokenAddressSync)(tokenMint, user);
107
+ const holderRewardAccount = (0, pda_js_1.getHolderRewardPda)(tokenMint, user, programId);
101
108
  const instructions = [];
102
109
  // Check if user's token ATA exists, create if needed
103
110
  try {
104
- await getAccount(connection, userTokenAta);
111
+ await (0, spl_token_1.getAccount)(connection, userTokenAta);
105
112
  }
106
113
  catch {
107
- instructions.push(createAssociatedTokenAccountInstruction(user, userTokenAta, user, tokenMint));
114
+ instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(user, userTokenAta, user, tokenMint));
108
115
  }
109
116
  // Build swap instruction
110
- const swapIx = new TransactionInstruction({
117
+ const swapIx = new web3_js_1.TransactionInstruction({
111
118
  programId,
112
119
  keys: [
113
120
  { pubkey: pool, isWritable: true, isSigner: false },
@@ -121,11 +128,11 @@ export async function buildSwapSolToTokenInstruction(connection, params, program
121
128
  // Holder reward account
122
129
  { pubkey: holderRewardAccount, isWritable: true, isSigner: false },
123
130
  { pubkey: user, isWritable: true, isSigner: true },
124
- { pubkey: TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
125
- { pubkey: SystemProgram.programId, isWritable: false, isSigner: false },
131
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
132
+ { pubkey: web3_js_1.SystemProgram.programId, isWritable: false, isSigner: false },
126
133
  ],
127
134
  data: Buffer.concat([
128
- DISCRIMINATORS.swap_sol_to_token,
135
+ constants_js_1.DISCRIMINATORS.swap_sol_to_token,
129
136
  writeU64LE(lamportsIn),
130
137
  writeU64LE(minimumAmountOut),
131
138
  ]),
@@ -138,32 +145,32 @@ export async function buildSwapSolToTokenInstruction(connection, params, program
138
145
  *
139
146
  * IMPORTANT: Fee recipients are read from on-chain state and cannot be modified.
140
147
  */
141
- export async function buildSwapTokenToSolInstruction(connection, params, programId) {
148
+ async function buildSwapTokenToSolInstruction(connection, params, programId) {
142
149
  const { tokenMint, user, amountIn, minimumLamportsOut } = params;
143
150
  // Fetch pool state to get fee recipients and vault addresses (enforced on-chain)
144
- const state = await getPoolState(connection, tokenMint, programId);
151
+ const state = await (0, accounts_js_1.getPoolState)(connection, tokenMint, programId);
145
152
  if (!state) {
146
153
  throw new Error("Pool not found for this token");
147
154
  }
148
155
  // Determine which vault is WSOL and which is the token based on stored mints
149
- const isTokenANative = state.tokenAMint.equals(NATIVE_MINT);
156
+ const isTokenANative = state.tokenAMint.equals(constants_js_1.NATIVE_MINT);
150
157
  const wsolVault = isTokenANative ? state.tokenAVault : state.tokenBVault;
151
158
  const tokenVault = isTokenANative ? state.tokenBVault : state.tokenAVault;
152
- const pool = getPoolPda(tokenMint, programId);
153
- const authority = getPoolAuthorityPda(pool, programId);
154
- const userTokenAta = getAssociatedTokenAddressSync(tokenMint, user);
155
- const userWsolAta = getAssociatedTokenAddressSync(NATIVE_MINT, user);
156
- const holderRewardAccount = getHolderRewardPda(tokenMint, user, programId);
159
+ const pool = (0, pda_js_1.getPoolPda)(tokenMint, programId);
160
+ const authority = (0, pda_js_1.getPoolAuthorityPda)(pool, programId);
161
+ const userTokenAta = (0, spl_token_1.getAssociatedTokenAddressSync)(tokenMint, user);
162
+ const userWsolAta = (0, spl_token_1.getAssociatedTokenAddressSync)(constants_js_1.NATIVE_MINT, user);
163
+ const holderRewardAccount = (0, pda_js_1.getHolderRewardPda)(tokenMint, user, programId);
157
164
  const instructions = [];
158
165
  // Create WSOL ATA if needed (for receiving output)
159
166
  try {
160
- await getAccount(connection, userWsolAta);
167
+ await (0, spl_token_1.getAccount)(connection, userWsolAta);
161
168
  }
162
169
  catch {
163
- instructions.push(createAssociatedTokenAccountInstruction(user, userWsolAta, user, NATIVE_MINT));
170
+ instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(user, userWsolAta, user, constants_js_1.NATIVE_MINT));
164
171
  }
165
172
  // Build swap instruction
166
- const swapIx = new TransactionInstruction({
173
+ const swapIx = new web3_js_1.TransactionInstruction({
167
174
  programId,
168
175
  keys: [
169
176
  { pubkey: pool, isWritable: true, isSigner: false },
@@ -178,49 +185,49 @@ export async function buildSwapTokenToSolInstruction(connection, params, program
178
185
  // Holder reward account
179
186
  { pubkey: holderRewardAccount, isWritable: true, isSigner: false },
180
187
  { pubkey: user, isWritable: true, isSigner: true },
181
- { pubkey: TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
182
- { pubkey: SystemProgram.programId, isWritable: false, isSigner: false },
188
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
189
+ { pubkey: web3_js_1.SystemProgram.programId, isWritable: false, isSigner: false },
183
190
  ],
184
191
  data: Buffer.concat([
185
- DISCRIMINATORS.swap_token_to_sol,
192
+ constants_js_1.DISCRIMINATORS.swap_token_to_sol,
186
193
  writeU64LE(amountIn),
187
194
  writeU64LE(minimumLamportsOut),
188
195
  ]),
189
196
  });
190
197
  instructions.push(swapIx);
191
198
  // Close WSOL account to unwrap to SOL
192
- instructions.push(createCloseAccountInstruction(userWsolAta, user, user));
199
+ instructions.push((0, spl_token_1.createCloseAccountInstruction)(userWsolAta, user, user));
193
200
  return instructions;
194
201
  }
195
202
  /**
196
203
  * Build swap_token_to_sol_max instruction (sell entire balance)
197
204
  */
198
- export async function buildSwapTokenToSolMaxInstruction(connection, params, programId) {
205
+ async function buildSwapTokenToSolMaxInstruction(connection, params, programId) {
199
206
  const { tokenMint, user } = params;
200
207
  // Fetch pool state to get fee recipients and vault addresses (enforced on-chain)
201
- const state = await getPoolState(connection, tokenMint, programId);
208
+ const state = await (0, accounts_js_1.getPoolState)(connection, tokenMint, programId);
202
209
  if (!state) {
203
210
  throw new Error("Pool not found for this token");
204
211
  }
205
212
  // Determine which vault is WSOL and which is the token based on stored mints
206
- const isTokenANative = state.tokenAMint.equals(NATIVE_MINT);
213
+ const isTokenANative = state.tokenAMint.equals(constants_js_1.NATIVE_MINT);
207
214
  const wsolVault = isTokenANative ? state.tokenAVault : state.tokenBVault;
208
215
  const tokenVault = isTokenANative ? state.tokenBVault : state.tokenAVault;
209
- const pool = getPoolPda(tokenMint, programId);
210
- const authority = getPoolAuthorityPda(pool, programId);
211
- const userTokenAta = getAssociatedTokenAddressSync(tokenMint, user);
212
- const userWsolAta = getAssociatedTokenAddressSync(NATIVE_MINT, user);
213
- const holderRewardAccount = getHolderRewardPda(tokenMint, user, programId);
216
+ const pool = (0, pda_js_1.getPoolPda)(tokenMint, programId);
217
+ const authority = (0, pda_js_1.getPoolAuthorityPda)(pool, programId);
218
+ const userTokenAta = (0, spl_token_1.getAssociatedTokenAddressSync)(tokenMint, user);
219
+ const userWsolAta = (0, spl_token_1.getAssociatedTokenAddressSync)(constants_js_1.NATIVE_MINT, user);
220
+ const holderRewardAccount = (0, pda_js_1.getHolderRewardPda)(tokenMint, user, programId);
214
221
  const instructions = [];
215
222
  // Create WSOL ATA if needed (for receiving output)
216
223
  try {
217
- await getAccount(connection, userWsolAta);
224
+ await (0, spl_token_1.getAccount)(connection, userWsolAta);
218
225
  }
219
226
  catch {
220
- instructions.push(createAssociatedTokenAccountInstruction(user, userWsolAta, user, NATIVE_MINT));
227
+ instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(user, userWsolAta, user, constants_js_1.NATIVE_MINT));
221
228
  }
222
229
  // Build swap max instruction
223
- const swapMaxIx = new TransactionInstruction({
230
+ const swapMaxIx = new web3_js_1.TransactionInstruction({
224
231
  programId,
225
232
  keys: [
226
233
  { pubkey: pool, isWritable: true, isSigner: false },
@@ -235,14 +242,13 @@ export async function buildSwapTokenToSolMaxInstruction(connection, params, prog
235
242
  // Holder reward account
236
243
  { pubkey: holderRewardAccount, isWritable: true, isSigner: false },
237
244
  { pubkey: user, isWritable: true, isSigner: true },
238
- { pubkey: TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
239
- { pubkey: SystemProgram.programId, isWritable: false, isSigner: false },
245
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
246
+ { pubkey: web3_js_1.SystemProgram.programId, isWritable: false, isSigner: false },
240
247
  ],
241
- data: DISCRIMINATORS.swap_token_to_sol_max,
248
+ data: constants_js_1.DISCRIMINATORS.swap_token_to_sol_max,
242
249
  });
243
250
  instructions.push(swapMaxIx);
244
251
  // Close WSOL account to unwrap to SOL
245
- instructions.push(createCloseAccountInstruction(userWsolAta, user, user));
252
+ instructions.push((0, spl_token_1.createCloseAccountInstruction)(userWsolAta, user, user));
246
253
  return instructions;
247
254
  }
248
- //# sourceMappingURL=pool.js.map
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ /**
3
+ * Holder Rewards
4
+ * Claim accumulated holder rewards from bonding curves and AMM pools
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.buildClaimHolderRewardsCurveInstruction = buildClaimHolderRewardsCurveInstruction;
8
+ exports.buildClaimHolderRewardsInstruction = buildClaimHolderRewardsInstruction;
9
+ const web3_js_1 = require("@solana/web3.js");
10
+ const spl_token_1 = require("@solana/spl-token");
11
+ const constants_js_1 = require("./constants.js");
12
+ const pda_js_1 = require("./pda.js");
13
+ const accounts_js_1 = require("./accounts.js");
14
+ // ============= Claim from Bonding Curve =============
15
+ /**
16
+ * Build claim_holder_rewards_curve instruction
17
+ *
18
+ * Claims accumulated holder rewards from a bonding curve.
19
+ * Rewards are paid in SOL directly to the holder's wallet.
20
+ */
21
+ async function buildClaimHolderRewardsCurveInstruction(connection, params, programId) {
22
+ const { tokenMint, holder } = params;
23
+ // Derive PDAs
24
+ const bondingCurve = (0, pda_js_1.getBondingCurvePda)(tokenMint, programId);
25
+ const solEscrow = (0, pda_js_1.getSolEscrowPda)(bondingCurve, programId);
26
+ const holderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(tokenMint, holder);
27
+ const holderRewardAccount = (0, pda_js_1.getHolderRewardPda)(tokenMint, holder, programId);
28
+ const claimIx = new web3_js_1.TransactionInstruction({
29
+ programId,
30
+ keys: [
31
+ { pubkey: bondingCurve, isWritable: true, isSigner: false },
32
+ { pubkey: tokenMint, isWritable: false, isSigner: false },
33
+ { pubkey: solEscrow, isWritable: true, isSigner: false },
34
+ { pubkey: holderTokenAccount, isWritable: false, isSigner: false },
35
+ { pubkey: holderRewardAccount, isWritable: true, isSigner: false },
36
+ { pubkey: holder, isWritable: true, isSigner: true },
37
+ { pubkey: web3_js_1.SystemProgram.programId, isWritable: false, isSigner: false },
38
+ ],
39
+ data: constants_js_1.DISCRIMINATORS.claim_holder_rewards_curve,
40
+ });
41
+ return [claimIx];
42
+ }
43
+ // ============= Claim from AMM Pool =============
44
+ /**
45
+ * Build claim_holder_rewards instruction
46
+ *
47
+ * Claims accumulated holder rewards from an AMM pool (post-graduation).
48
+ * Rewards are paid in WSOL which is then unwrapped to SOL.
49
+ */
50
+ async function buildClaimHolderRewardsInstruction(connection, params, programId) {
51
+ const { tokenMint, holder } = params;
52
+ // Fetch pool state
53
+ const state = await (0, accounts_js_1.getPoolState)(connection, tokenMint, programId);
54
+ if (!state) {
55
+ throw new Error('Pool not found for this token');
56
+ }
57
+ // Derive PDAs
58
+ const pool = (0, pda_js_1.getPoolPda)(tokenMint, programId);
59
+ const authority = (0, pda_js_1.getPoolAuthorityPda)(pool, programId);
60
+ const holderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(tokenMint, holder);
61
+ const holderRewardAccount = (0, pda_js_1.getHolderRewardPda)(tokenMint, holder, programId);
62
+ const holderWsolAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(constants_js_1.NATIVE_MINT, holder);
63
+ // Determine which vault is which
64
+ const isTokenANative = state.tokenAMint.equals(constants_js_1.NATIVE_MINT);
65
+ const solVault = isTokenANative ? state.tokenAVault : state.tokenBVault;
66
+ const tokenVault = isTokenANative ? state.tokenBVault : state.tokenAVault;
67
+ const instructions = [];
68
+ // Create WSOL ATA if needed
69
+ try {
70
+ await (0, spl_token_1.getAccount)(connection, holderWsolAccount);
71
+ }
72
+ catch {
73
+ instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(holder, holderWsolAccount, holder, constants_js_1.NATIVE_MINT));
74
+ }
75
+ const claimIx = new web3_js_1.TransactionInstruction({
76
+ programId,
77
+ keys: [
78
+ { pubkey: pool, isWritable: true, isSigner: false },
79
+ { pubkey: tokenMint, isWritable: false, isSigner: false },
80
+ { pubkey: state.lpMint, isWritable: false, isSigner: false },
81
+ { pubkey: tokenVault, isWritable: false, isSigner: false },
82
+ { pubkey: solVault, isWritable: true, isSigner: false },
83
+ { pubkey: holderTokenAccount, isWritable: false, isSigner: false },
84
+ { pubkey: holderWsolAccount, isWritable: true, isSigner: false },
85
+ { pubkey: holderRewardAccount, isWritable: true, isSigner: false },
86
+ { pubkey: authority, isWritable: false, isSigner: false },
87
+ { pubkey: holder, isWritable: true, isSigner: true },
88
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isWritable: false, isSigner: false },
89
+ { pubkey: web3_js_1.SystemProgram.programId, isWritable: false, isSigner: false },
90
+ ],
91
+ data: constants_js_1.DISCRIMINATORS.claim_holder_rewards,
92
+ });
93
+ instructions.push(claimIx);
94
+ // Close WSOL account to unwrap to SOL
95
+ instructions.push((0, spl_token_1.createCloseAccountInstruction)(holderWsolAccount, holder, holder));
96
+ return instructions;
97
+ }