sol-trade-sdk 0.1.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 +390 -0
- package/dist/chunk-MMQAMIKR.mjs +3735 -0
- package/dist/chunk-NEZDFAYA.mjs +7744 -0
- package/dist/clients-VITWK7B6.mjs +1370 -0
- package/dist/index-1BK_FXsW.d.mts +2327 -0
- package/dist/index-1BK_FXsW.d.ts +2327 -0
- package/dist/index.d.mts +2659 -0
- package/dist/index.d.ts +2659 -0
- package/dist/index.js +13265 -0
- package/dist/index.mjs +562 -0
- package/dist/perf/index.d.mts +2 -0
- package/dist/perf/index.d.ts +2 -0
- package/dist/perf/index.js +3742 -0
- package/dist/perf/index.mjs +214 -0
- package/package.json +101 -0
- package/src/__tests__/complete_sdk.test.ts +354 -0
- package/src/__tests__/hotpath.test.ts +486 -0
- package/src/__tests__/nonce.test.ts +45 -0
- package/src/__tests__/sdk.test.ts +425 -0
- package/src/address-lookup/index.ts +197 -0
- package/src/cache/cache.ts +308 -0
- package/src/calc/index.ts +1058 -0
- package/src/calc/pumpfun.ts +124 -0
- package/src/common/bonding_curve.ts +272 -0
- package/src/common/compute-budget.ts +148 -0
- package/src/common/confirm-any-signature.ts +184 -0
- package/src/common/fast-timing.ts +481 -0
- package/src/common/fast_fn.ts +150 -0
- package/src/common/gas-fee-strategy.ts +253 -0
- package/src/common/map-pool.ts +23 -0
- package/src/common/nonce.ts +40 -0
- package/src/common/sdk-log.ts +460 -0
- package/src/common/seed.ts +381 -0
- package/src/common/spl-token.ts +578 -0
- package/src/common/subscription-handle.ts +644 -0
- package/src/common/trading-utils.ts +239 -0
- package/src/common/wsol-manager.ts +325 -0
- package/src/compute/compute_budget_manager.ts +187 -0
- package/src/compute/index.ts +21 -0
- package/src/constants/index.ts +96 -0
- package/src/execution/execution.ts +532 -0
- package/src/execution/index.ts +42 -0
- package/src/hotpath/executor.ts +464 -0
- package/src/hotpath/index.ts +64 -0
- package/src/hotpath/state.ts +435 -0
- package/src/index.ts +2117 -0
- package/src/instruction/bonk_builder.ts +730 -0
- package/src/instruction/index.ts +24 -0
- package/src/instruction/meteora_damm_v2_builder.ts +509 -0
- package/src/instruction/pumpfun_builder.ts +1183 -0
- package/src/instruction/pumpswap.ts +1123 -0
- package/src/instruction/raydium_amm_v4_builder.ts +692 -0
- package/src/instruction/raydium_cpmm_builder.ts +795 -0
- package/src/middleware/traits.ts +407 -0
- package/src/params/index.ts +483 -0
- package/src/perf/compiler-optimization.ts +529 -0
- package/src/perf/hardware.ts +631 -0
- package/src/perf/index.ts +9 -0
- package/src/perf/kernel-bypass.ts +656 -0
- package/src/perf/protocol.ts +682 -0
- package/src/perf/realtime.ts +592 -0
- package/src/perf/simd.ts +668 -0
- package/src/perf/syscall-bypass.ts +331 -0
- package/src/perf/ultra-low-latency.ts +505 -0
- package/src/perf/zero-copy.ts +589 -0
- package/src/pool/pool.ts +294 -0
- package/src/rpc/client.ts +345 -0
- package/src/sdk-errors.ts +13 -0
- package/src/security/index.ts +26 -0
- package/src/security/secure-key.ts +303 -0
- package/src/security/validators.ts +281 -0
- package/src/seed/pda.ts +262 -0
- package/src/serialization/index.ts +28 -0
- package/src/serialization/serialization.ts +288 -0
- package/src/swqos/clients.ts +1754 -0
- package/src/swqos/index.ts +50 -0
- package/src/swqos/providers.ts +1707 -0
- package/src/trading/core/async-executor.ts +702 -0
- package/src/trading/core/confirmation-monitor.ts +711 -0
- package/src/trading/core/index.ts +82 -0
- package/src/trading/core/retry-handler.ts +683 -0
- package/src/trading/core/transaction-pool.ts +780 -0
- package/src/trading/executor.ts +385 -0
- package/src/trading/factory.ts +282 -0
- package/src/trading/index.ts +30 -0
- package/src/types.ts +8 -0
- package/src/utils/index.ts +155 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sol Trade SDK - Instruction Builders
|
|
3
|
+
*
|
|
4
|
+
* Production-grade instruction builders for Solana DEX protocols.
|
|
5
|
+
* Supports: PumpFun, PumpSwap, Bonk, Raydium CPMM, Raydium AMM V4, Meteora DAMM V2
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// PumpFun Protocol
|
|
9
|
+
export * from "./pumpfun_builder";
|
|
10
|
+
|
|
11
|
+
// PumpSwap Protocol
|
|
12
|
+
export * from "./pumpswap";
|
|
13
|
+
|
|
14
|
+
// Bonk Protocol
|
|
15
|
+
export * from "./bonk_builder";
|
|
16
|
+
|
|
17
|
+
// Raydium CPMM Protocol
|
|
18
|
+
export * from "./raydium_cpmm_builder";
|
|
19
|
+
|
|
20
|
+
// Raydium AMM V4 Protocol
|
|
21
|
+
export * from "./raydium_amm_v4_builder";
|
|
22
|
+
|
|
23
|
+
// Meteora DAMM V2 Protocol
|
|
24
|
+
export * from "./meteora_damm_v2_builder";
|
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Meteora DAMM V2 Protocol Instruction Builder
|
|
3
|
+
*
|
|
4
|
+
* Production-grade instruction builder for Meteora DAMM V2 protocol.
|
|
5
|
+
* 100% port of Rust implementation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
PublicKey,
|
|
10
|
+
Keypair,
|
|
11
|
+
AccountMeta,
|
|
12
|
+
TransactionInstruction,
|
|
13
|
+
SystemProgram,
|
|
14
|
+
} from "@solana/web3.js";
|
|
15
|
+
import {
|
|
16
|
+
getAssociatedTokenAddressSync,
|
|
17
|
+
createAssociatedTokenAccountInstruction,
|
|
18
|
+
TOKEN_PROGRAM_ID,
|
|
19
|
+
createCloseAccountInstruction,
|
|
20
|
+
NATIVE_MINT,
|
|
21
|
+
createSyncNativeInstruction,
|
|
22
|
+
} from "@solana/spl-token";
|
|
23
|
+
|
|
24
|
+
// ============================================
|
|
25
|
+
// Program IDs and Constants
|
|
26
|
+
// ============================================
|
|
27
|
+
|
|
28
|
+
/** Meteora DAMM V2 program ID */
|
|
29
|
+
export const METEORA_DAMM_V2_PROGRAM_ID = new PublicKey(
|
|
30
|
+
"cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG"
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
/** Authority */
|
|
34
|
+
export const METEORA_DAMM_V2_AUTHORITY = new PublicKey(
|
|
35
|
+
"HLnpSz9h2S4hiLQ43rnSD9XkcUThA7B8hQMKmDaiTLcC"
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
// ============================================
|
|
39
|
+
// Discriminators
|
|
40
|
+
// ============================================
|
|
41
|
+
|
|
42
|
+
/** Swap instruction discriminator */
|
|
43
|
+
export const METEORA_DAMM_V2_SWAP_DISCRIMINATOR: Buffer = Buffer.from([
|
|
44
|
+
248, 198, 158, 145, 225, 117, 135, 200,
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
// ============================================
|
|
48
|
+
// Seeds
|
|
49
|
+
// ============================================
|
|
50
|
+
|
|
51
|
+
export const METEORA_DAMM_V2_EVENT_AUTHORITY_SEED = Buffer.from("__event_authority");
|
|
52
|
+
|
|
53
|
+
// ============================================
|
|
54
|
+
// PDA Derivation Functions
|
|
55
|
+
// ============================================
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Derive the event authority PDA
|
|
59
|
+
*/
|
|
60
|
+
export function getMeteoraDammV2EventAuthorityPda(): PublicKey {
|
|
61
|
+
const [pda] = PublicKey.findProgramAddressSync(
|
|
62
|
+
[METEORA_DAMM_V2_EVENT_AUTHORITY_SEED],
|
|
63
|
+
METEORA_DAMM_V2_PROGRAM_ID
|
|
64
|
+
);
|
|
65
|
+
return pda;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ============================================
|
|
69
|
+
// Types
|
|
70
|
+
// ============================================
|
|
71
|
+
|
|
72
|
+
export interface MeteoraDammV2Params {
|
|
73
|
+
pool: PublicKey;
|
|
74
|
+
tokenAMint: PublicKey;
|
|
75
|
+
tokenBMint: PublicKey;
|
|
76
|
+
tokenAVault: PublicKey;
|
|
77
|
+
tokenBVault: PublicKey;
|
|
78
|
+
tokenAProgram: PublicKey;
|
|
79
|
+
tokenBProgram: PublicKey;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface BuildMeteoraDammV2BuyInstructionsParams {
|
|
83
|
+
payer: Keypair | PublicKey;
|
|
84
|
+
inputMint: PublicKey;
|
|
85
|
+
outputMint: PublicKey;
|
|
86
|
+
inputAmount: bigint;
|
|
87
|
+
slippageBasisPoints?: bigint;
|
|
88
|
+
fixedOutputAmount?: bigint;
|
|
89
|
+
createInputMintAta?: boolean;
|
|
90
|
+
createOutputMintAta?: boolean;
|
|
91
|
+
closeInputMintAta?: boolean;
|
|
92
|
+
protocolParams: MeteoraDammV2Params;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface BuildMeteoraDammV2SellInstructionsParams {
|
|
96
|
+
payer: Keypair | PublicKey;
|
|
97
|
+
inputMint: PublicKey;
|
|
98
|
+
outputMint: PublicKey;
|
|
99
|
+
inputAmount: bigint;
|
|
100
|
+
slippageBasisPoints?: bigint;
|
|
101
|
+
fixedOutputAmount?: bigint;
|
|
102
|
+
createOutputMintAta?: boolean;
|
|
103
|
+
closeOutputMintAta?: boolean;
|
|
104
|
+
closeInputMintAta?: boolean;
|
|
105
|
+
protocolParams: MeteoraDammV2Params;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ============================================
|
|
109
|
+
// Instruction Builders
|
|
110
|
+
// ============================================
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Build buy instructions for Meteora DAMM V2 protocol
|
|
114
|
+
*/
|
|
115
|
+
export function buildMeteoraDammV2BuyInstructions(
|
|
116
|
+
params: BuildMeteoraDammV2BuyInstructionsParams
|
|
117
|
+
): TransactionInstruction[] {
|
|
118
|
+
const {
|
|
119
|
+
payer,
|
|
120
|
+
inputMint,
|
|
121
|
+
outputMint,
|
|
122
|
+
inputAmount,
|
|
123
|
+
fixedOutputAmount,
|
|
124
|
+
createInputMintAta = true,
|
|
125
|
+
createOutputMintAta = true,
|
|
126
|
+
closeInputMintAta = false,
|
|
127
|
+
protocolParams,
|
|
128
|
+
} = params;
|
|
129
|
+
|
|
130
|
+
if (inputAmount === BigInt(0)) {
|
|
131
|
+
throw new Error("Amount cannot be zero");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (!fixedOutputAmount) {
|
|
135
|
+
throw new Error("fixedOutputAmount must be set for Meteora DAMM V2 swap");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const payerPubkey = payer instanceof Keypair ? payer.publicKey : payer;
|
|
139
|
+
const instructions: TransactionInstruction[] = [];
|
|
140
|
+
|
|
141
|
+
const WSOL_TOKEN_ACCOUNT = new PublicKey("So11111111111111111111111111111111111111112");
|
|
142
|
+
const USDC_TOKEN_ACCOUNT = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
|
|
143
|
+
|
|
144
|
+
const {
|
|
145
|
+
pool,
|
|
146
|
+
tokenAMint,
|
|
147
|
+
tokenBMint,
|
|
148
|
+
tokenAVault,
|
|
149
|
+
tokenBVault,
|
|
150
|
+
tokenAProgram,
|
|
151
|
+
tokenBProgram,
|
|
152
|
+
} = protocolParams;
|
|
153
|
+
|
|
154
|
+
// Check pool type
|
|
155
|
+
const isWsol = tokenAMint.equals(WSOL_TOKEN_ACCOUNT) || tokenBMint.equals(WSOL_TOKEN_ACCOUNT);
|
|
156
|
+
const isUsdc = tokenAMint.equals(USDC_TOKEN_ACCOUNT) || tokenBMint.equals(USDC_TOKEN_ACCOUNT);
|
|
157
|
+
|
|
158
|
+
if (!isWsol && !isUsdc) {
|
|
159
|
+
throw new Error("Pool must contain WSOL or USDC");
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Determine swap direction
|
|
163
|
+
const isAIn = tokenAMint.equals(WSOL_TOKEN_ACCOUNT) || tokenAMint.equals(USDC_TOKEN_ACCOUNT);
|
|
164
|
+
|
|
165
|
+
// Derive user token accounts
|
|
166
|
+
const inputTokenAccount = getAssociatedTokenAddressSync(
|
|
167
|
+
inputMint,
|
|
168
|
+
payerPubkey,
|
|
169
|
+
true,
|
|
170
|
+
isAIn ? tokenAProgram : tokenBProgram
|
|
171
|
+
);
|
|
172
|
+
const outputTokenAccount = getAssociatedTokenAddressSync(
|
|
173
|
+
outputMint,
|
|
174
|
+
payerPubkey,
|
|
175
|
+
true,
|
|
176
|
+
isAIn ? tokenBProgram : tokenAProgram
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
// Derive event authority
|
|
180
|
+
const eventAuthority = getMeteoraDammV2EventAuthorityPda();
|
|
181
|
+
|
|
182
|
+
// Handle WSOL wrapping
|
|
183
|
+
if (createInputMintAta && isWsol) {
|
|
184
|
+
const wsolAta = getAssociatedTokenAddressSync(NATIVE_MINT, payerPubkey, true);
|
|
185
|
+
instructions.push(
|
|
186
|
+
createAssociatedTokenAccountInstruction(
|
|
187
|
+
payerPubkey,
|
|
188
|
+
wsolAta,
|
|
189
|
+
payerPubkey,
|
|
190
|
+
NATIVE_MINT,
|
|
191
|
+
TOKEN_PROGRAM_ID
|
|
192
|
+
)
|
|
193
|
+
);
|
|
194
|
+
instructions.push(createSyncNativeInstruction(wsolAta));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Create output mint ATA if needed
|
|
198
|
+
if (createOutputMintAta) {
|
|
199
|
+
instructions.push(
|
|
200
|
+
createAssociatedTokenAccountInstruction(
|
|
201
|
+
payerPubkey,
|
|
202
|
+
outputTokenAccount,
|
|
203
|
+
payerPubkey,
|
|
204
|
+
outputMint,
|
|
205
|
+
TOKEN_PROGRAM_ID
|
|
206
|
+
)
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Build instruction data
|
|
211
|
+
const data = Buffer.alloc(24);
|
|
212
|
+
METEORA_DAMM_V2_SWAP_DISCRIMINATOR.copy(data, 0);
|
|
213
|
+
data.writeBigUInt64LE(inputAmount, 8);
|
|
214
|
+
data.writeBigUInt64LE(fixedOutputAmount, 16);
|
|
215
|
+
|
|
216
|
+
// Build accounts (14 accounts)
|
|
217
|
+
const accounts: AccountMeta[] = [
|
|
218
|
+
{ pubkey: METEORA_DAMM_V2_AUTHORITY, isSigner: false, isWritable: false },
|
|
219
|
+
{ pubkey: pool, isSigner: false, isWritable: true },
|
|
220
|
+
{ pubkey: inputTokenAccount, isSigner: false, isWritable: true },
|
|
221
|
+
{ pubkey: outputTokenAccount, isSigner: false, isWritable: true },
|
|
222
|
+
{ pubkey: tokenAVault, isSigner: false, isWritable: true },
|
|
223
|
+
{ pubkey: tokenBVault, isSigner: false, isWritable: true },
|
|
224
|
+
{ pubkey: tokenAMint, isSigner: false, isWritable: false },
|
|
225
|
+
{ pubkey: tokenBMint, isSigner: false, isWritable: false },
|
|
226
|
+
{ pubkey: payerPubkey, isSigner: true, isWritable: true },
|
|
227
|
+
{ pubkey: tokenAProgram, isSigner: false, isWritable: false },
|
|
228
|
+
{ pubkey: tokenBProgram, isSigner: false, isWritable: false },
|
|
229
|
+
{ pubkey: METEORA_DAMM_V2_PROGRAM_ID, isSigner: false, isWritable: false }, // Referral Token Account (placeholder)
|
|
230
|
+
{ pubkey: eventAuthority, isSigner: false, isWritable: false },
|
|
231
|
+
{ pubkey: METEORA_DAMM_V2_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
232
|
+
];
|
|
233
|
+
|
|
234
|
+
instructions.push(
|
|
235
|
+
new TransactionInstruction({
|
|
236
|
+
keys: accounts,
|
|
237
|
+
programId: METEORA_DAMM_V2_PROGRAM_ID,
|
|
238
|
+
data,
|
|
239
|
+
})
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
// Close WSOL ATA if requested
|
|
243
|
+
if (closeInputMintAta && isWsol) {
|
|
244
|
+
const wsolAta = getAssociatedTokenAddressSync(NATIVE_MINT, payerPubkey, true);
|
|
245
|
+
instructions.push(
|
|
246
|
+
createCloseAccountInstruction(wsolAta, payerPubkey, payerPubkey, [], TOKEN_PROGRAM_ID)
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return instructions;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Build sell instructions for Meteora DAMM V2 protocol
|
|
255
|
+
*/
|
|
256
|
+
export function buildMeteoraDammV2SellInstructions(
|
|
257
|
+
params: BuildMeteoraDammV2SellInstructionsParams
|
|
258
|
+
): TransactionInstruction[] {
|
|
259
|
+
const {
|
|
260
|
+
payer,
|
|
261
|
+
inputMint,
|
|
262
|
+
outputMint,
|
|
263
|
+
inputAmount,
|
|
264
|
+
fixedOutputAmount,
|
|
265
|
+
createOutputMintAta = true,
|
|
266
|
+
closeOutputMintAta = false,
|
|
267
|
+
closeInputMintAta = false,
|
|
268
|
+
protocolParams,
|
|
269
|
+
} = params;
|
|
270
|
+
|
|
271
|
+
if (inputAmount === BigInt(0)) {
|
|
272
|
+
throw new Error("Amount cannot be zero");
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (!fixedOutputAmount) {
|
|
276
|
+
throw new Error("fixedOutputAmount must be set for Meteora DAMM V2 swap");
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const payerPubkey = payer instanceof Keypair ? payer.publicKey : payer;
|
|
280
|
+
const instructions: TransactionInstruction[] = [];
|
|
281
|
+
|
|
282
|
+
const WSOL_TOKEN_ACCOUNT = new PublicKey("So11111111111111111111111111111111111111112");
|
|
283
|
+
const USDC_TOKEN_ACCOUNT = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
|
|
284
|
+
|
|
285
|
+
const {
|
|
286
|
+
pool,
|
|
287
|
+
tokenAMint,
|
|
288
|
+
tokenBMint,
|
|
289
|
+
tokenAVault,
|
|
290
|
+
tokenBVault,
|
|
291
|
+
tokenAProgram,
|
|
292
|
+
tokenBProgram,
|
|
293
|
+
} = protocolParams;
|
|
294
|
+
|
|
295
|
+
// Check pool type
|
|
296
|
+
const isWsol = tokenBMint.equals(WSOL_TOKEN_ACCOUNT) || tokenAMint.equals(WSOL_TOKEN_ACCOUNT);
|
|
297
|
+
const isUsdc = tokenBMint.equals(USDC_TOKEN_ACCOUNT) || tokenAMint.equals(USDC_TOKEN_ACCOUNT);
|
|
298
|
+
|
|
299
|
+
if (!isWsol && !isUsdc) {
|
|
300
|
+
throw new Error("Pool must contain WSOL or USDC");
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Determine swap direction (selling token for WSOL/USDC)
|
|
304
|
+
const isAIn = tokenBMint.equals(WSOL_TOKEN_ACCOUNT) || tokenBMint.equals(USDC_TOKEN_ACCOUNT);
|
|
305
|
+
|
|
306
|
+
// Derive user token accounts
|
|
307
|
+
const inputTokenAccount = getAssociatedTokenAddressSync(
|
|
308
|
+
inputMint,
|
|
309
|
+
payerPubkey,
|
|
310
|
+
true,
|
|
311
|
+
isAIn ? tokenAProgram : tokenBProgram
|
|
312
|
+
);
|
|
313
|
+
const outputTokenAccount = getAssociatedTokenAddressSync(
|
|
314
|
+
outputMint,
|
|
315
|
+
payerPubkey,
|
|
316
|
+
true,
|
|
317
|
+
isAIn ? tokenBProgram : tokenAProgram
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
// Derive event authority
|
|
321
|
+
const eventAuthority = getMeteoraDammV2EventAuthorityPda();
|
|
322
|
+
|
|
323
|
+
// Create WSOL ATA for receiving if needed
|
|
324
|
+
if (createOutputMintAta && isWsol) {
|
|
325
|
+
const wsolAta = getAssociatedTokenAddressSync(NATIVE_MINT, payerPubkey, true);
|
|
326
|
+
instructions.push(
|
|
327
|
+
createAssociatedTokenAccountInstruction(
|
|
328
|
+
payerPubkey,
|
|
329
|
+
wsolAta,
|
|
330
|
+
payerPubkey,
|
|
331
|
+
NATIVE_MINT,
|
|
332
|
+
TOKEN_PROGRAM_ID
|
|
333
|
+
)
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Build instruction data
|
|
338
|
+
const data = Buffer.alloc(24);
|
|
339
|
+
METEORA_DAMM_V2_SWAP_DISCRIMINATOR.copy(data, 0);
|
|
340
|
+
data.writeBigUInt64LE(inputAmount, 8);
|
|
341
|
+
data.writeBigUInt64LE(fixedOutputAmount, 16);
|
|
342
|
+
|
|
343
|
+
// Build accounts
|
|
344
|
+
const accounts: AccountMeta[] = [
|
|
345
|
+
{ pubkey: METEORA_DAMM_V2_AUTHORITY, isSigner: false, isWritable: false },
|
|
346
|
+
{ pubkey: pool, isSigner: false, isWritable: true },
|
|
347
|
+
{ pubkey: inputTokenAccount, isSigner: false, isWritable: true },
|
|
348
|
+
{ pubkey: outputTokenAccount, isSigner: false, isWritable: true },
|
|
349
|
+
{ pubkey: tokenAVault, isSigner: false, isWritable: true },
|
|
350
|
+
{ pubkey: tokenBVault, isSigner: false, isWritable: true },
|
|
351
|
+
{ pubkey: tokenAMint, isSigner: false, isWritable: false },
|
|
352
|
+
{ pubkey: tokenBMint, isSigner: false, isWritable: false },
|
|
353
|
+
{ pubkey: payerPubkey, isSigner: true, isWritable: true },
|
|
354
|
+
{ pubkey: tokenAProgram, isSigner: false, isWritable: false },
|
|
355
|
+
{ pubkey: tokenBProgram, isSigner: false, isWritable: false },
|
|
356
|
+
{ pubkey: METEORA_DAMM_V2_PROGRAM_ID, isSigner: false, isWritable: false }, // Referral Token Account
|
|
357
|
+
{ pubkey: eventAuthority, isSigner: false, isWritable: false },
|
|
358
|
+
{ pubkey: METEORA_DAMM_V2_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
359
|
+
];
|
|
360
|
+
|
|
361
|
+
instructions.push(
|
|
362
|
+
new TransactionInstruction({
|
|
363
|
+
keys: accounts,
|
|
364
|
+
programId: METEORA_DAMM_V2_PROGRAM_ID,
|
|
365
|
+
data,
|
|
366
|
+
})
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
// Close WSOL ATA if requested
|
|
370
|
+
if (closeOutputMintAta && isWsol) {
|
|
371
|
+
const wsolAta = getAssociatedTokenAddressSync(NATIVE_MINT, payerPubkey, true);
|
|
372
|
+
instructions.push(
|
|
373
|
+
createCloseAccountInstruction(wsolAta, payerPubkey, payerPubkey, [], TOKEN_PROGRAM_ID)
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Close input token ATA if requested
|
|
378
|
+
if (closeInputMintAta) {
|
|
379
|
+
instructions.push(
|
|
380
|
+
createCloseAccountInstruction(
|
|
381
|
+
inputTokenAccount,
|
|
382
|
+
payerPubkey,
|
|
383
|
+
payerPubkey,
|
|
384
|
+
[],
|
|
385
|
+
isAIn ? tokenAProgram : tokenBProgram
|
|
386
|
+
)
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return instructions;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// ===== Pool Types and Decoder - from Rust: src/instruction/utils/meteora_damm_v2_types.rs =====
|
|
394
|
+
|
|
395
|
+
/** Pool size in bytes */
|
|
396
|
+
export const METEORA_POOL_SIZE = 1104;
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Meteora DAMM V2 Pool structure (simplified for essential fields)
|
|
400
|
+
* 100% from Rust: src/instruction/utils/meteora_damm_v2_types.rs Pool
|
|
401
|
+
*/
|
|
402
|
+
export interface MeteoraDammV2Pool {
|
|
403
|
+
tokenAMint: PublicKey;
|
|
404
|
+
tokenBMint: PublicKey;
|
|
405
|
+
tokenAVault: PublicKey;
|
|
406
|
+
tokenBVault: PublicKey;
|
|
407
|
+
liquidity: bigint;
|
|
408
|
+
sqrtPrice: bigint;
|
|
409
|
+
poolStatus: number;
|
|
410
|
+
tokenAFlag: number;
|
|
411
|
+
tokenBFlag: number;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Decode a Meteora DAMM V2 pool from account data.
|
|
416
|
+
* 100% from Rust: src/instruction/utils/meteora_damm_v2_types.rs pool_decode
|
|
417
|
+
*/
|
|
418
|
+
export function decodeMeteoraPool(data: Buffer): MeteoraDammV2Pool | null {
|
|
419
|
+
if (data.length < METEORA_POOL_SIZE) {
|
|
420
|
+
return null;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
try {
|
|
424
|
+
// Skip pool_fees structure (first 248 bytes)
|
|
425
|
+
let offset = 248;
|
|
426
|
+
|
|
427
|
+
// token_a_mint: Pubkey (32 bytes)
|
|
428
|
+
const tokenAMint = new PublicKey(data.subarray(offset, offset + 32));
|
|
429
|
+
offset += 32;
|
|
430
|
+
|
|
431
|
+
// token_b_mint: Pubkey
|
|
432
|
+
const tokenBMint = new PublicKey(data.subarray(offset, offset + 32));
|
|
433
|
+
offset += 32;
|
|
434
|
+
|
|
435
|
+
// token_a_vault: Pubkey
|
|
436
|
+
const tokenAVault = new PublicKey(data.subarray(offset, offset + 32));
|
|
437
|
+
offset += 32;
|
|
438
|
+
|
|
439
|
+
// token_b_vault: Pubkey
|
|
440
|
+
const tokenBVault = new PublicKey(data.subarray(offset, offset + 32));
|
|
441
|
+
offset += 32;
|
|
442
|
+
|
|
443
|
+
// Skip whitelisted_vault, partner (64 bytes)
|
|
444
|
+
offset += 64;
|
|
445
|
+
|
|
446
|
+
// liquidity: u128 (16 bytes)
|
|
447
|
+
const liquidity = data.readBigUInt64LE(offset) | (data.readBigUInt64LE(offset + 8) << BigInt(64));
|
|
448
|
+
offset += 16;
|
|
449
|
+
|
|
450
|
+
// Skip padding (16 bytes)
|
|
451
|
+
offset += 16;
|
|
452
|
+
|
|
453
|
+
// Skip protocol_a_fee, protocol_b_fee, partner_a_fee, partner_b_fee (32 bytes)
|
|
454
|
+
offset += 32;
|
|
455
|
+
|
|
456
|
+
// Skip sqrt_min_price, sqrt_max_price (32 bytes)
|
|
457
|
+
offset += 32;
|
|
458
|
+
|
|
459
|
+
// sqrt_price: u128
|
|
460
|
+
const sqrtPrice = data.readBigUInt64LE(offset) | (data.readBigUInt64LE(offset + 8) << BigInt(64));
|
|
461
|
+
offset += 16;
|
|
462
|
+
|
|
463
|
+
// Skip activation_point (8 bytes)
|
|
464
|
+
offset += 8;
|
|
465
|
+
|
|
466
|
+
// activation_type: u8, pool_status: u8, token_a_flag: u8, token_b_flag: u8
|
|
467
|
+
const poolStatus = data.readUInt8(offset + 1);
|
|
468
|
+
const tokenAFlag = data.readUInt8(offset + 2);
|
|
469
|
+
const tokenBFlag = data.readUInt8(offset + 3);
|
|
470
|
+
|
|
471
|
+
return {
|
|
472
|
+
tokenAMint,
|
|
473
|
+
tokenBMint,
|
|
474
|
+
tokenAVault,
|
|
475
|
+
tokenBVault,
|
|
476
|
+
liquidity,
|
|
477
|
+
sqrtPrice,
|
|
478
|
+
poolStatus,
|
|
479
|
+
tokenAFlag,
|
|
480
|
+
tokenBFlag,
|
|
481
|
+
};
|
|
482
|
+
} catch {
|
|
483
|
+
return null;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// ===== Async Fetch Functions - from Rust: src/instruction/utils/meteora_damm_v2.rs =====
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Fetch a Meteora DAMM V2 pool from RPC.
|
|
491
|
+
* 100% from Rust: src/instruction/utils/meteora_damm_v2.rs fetch_pool
|
|
492
|
+
*/
|
|
493
|
+
export async function fetchMeteoraPool(
|
|
494
|
+
connection: { getAccountInfo: (pubkey: PublicKey) => Promise<{ value?: { data: Buffer; owner?: PublicKey } }> },
|
|
495
|
+
poolAddress: PublicKey
|
|
496
|
+
): Promise<MeteoraDammV2Pool | null> {
|
|
497
|
+
const account = await connection.getAccountInfo(poolAddress);
|
|
498
|
+
if (!account?.value?.data) {
|
|
499
|
+
return null;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// Verify owner is Meteora DAMM V2 program
|
|
503
|
+
if (account.value.owner && !account.value.owner.equals(METEORA_DAMM_V2_PROGRAM_ID)) {
|
|
504
|
+
return null;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// Skip 8-byte discriminator
|
|
508
|
+
return decodeMeteoraPool(account.value.data.slice(8));
|
|
509
|
+
}
|