@meteora-ag/zap-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,1022 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __async = (__this, __arguments, generator) => {
21
+ return new Promise((resolve, reject) => {
22
+ var fulfilled = (value) => {
23
+ try {
24
+ step(generator.next(value));
25
+ } catch (e) {
26
+ reject(e);
27
+ }
28
+ };
29
+ var rejected = (value) => {
30
+ try {
31
+ step(generator.throw(value));
32
+ } catch (e) {
33
+ reject(e);
34
+ }
35
+ };
36
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
37
+ step((generator = generator.apply(__this, __arguments)).next());
38
+ });
39
+ };
40
+
41
+ // src/zap.ts
42
+ import { PublicKey as PublicKey7 } from "@solana/web3.js";
43
+ import { BN as BN3, Program } from "@coral-xyz/anchor";
44
+
45
+ // src/idl/zap/idl.json
46
+ var idl_default = {
47
+ address: "zapvX9M3uf5pvy4wRPAbQgdQsM1xmuiFnkfHKPvwMiz",
48
+ metadata: {
49
+ name: "zap",
50
+ version: "0.1.0",
51
+ spec: "0.1.0",
52
+ description: "Created with Anchor"
53
+ },
54
+ instructions: [
55
+ {
56
+ name: "zap_out",
57
+ discriminator: [
58
+ 155,
59
+ 108,
60
+ 185,
61
+ 112,
62
+ 104,
63
+ 210,
64
+ 161,
65
+ 64
66
+ ],
67
+ accounts: [
68
+ {
69
+ name: "user_token_in_account",
70
+ writable: true
71
+ },
72
+ {
73
+ name: "amm_program"
74
+ }
75
+ ],
76
+ args: [
77
+ {
78
+ name: "params",
79
+ type: {
80
+ defined: {
81
+ name: "ZapOutParameters"
82
+ }
83
+ }
84
+ }
85
+ ]
86
+ }
87
+ ],
88
+ errors: [
89
+ {
90
+ code: 6e3,
91
+ name: "MathOverflow",
92
+ msg: "Math operation overflow"
93
+ },
94
+ {
95
+ code: 6001,
96
+ name: "InvalidOffset",
97
+ msg: "Invalid offset"
98
+ },
99
+ {
100
+ code: 6002,
101
+ name: "InvalidZapOutParameters",
102
+ msg: "Math operation overflow"
103
+ },
104
+ {
105
+ code: 6003,
106
+ name: "TypeCastFailed",
107
+ msg: "Type cast error"
108
+ },
109
+ {
110
+ code: 6004,
111
+ name: "AmmIsNotSupported",
112
+ msg: "Amm program is not supported"
113
+ }
114
+ ],
115
+ types: [
116
+ {
117
+ name: "ZapOutParameters",
118
+ type: {
119
+ kind: "struct",
120
+ fields: [
121
+ {
122
+ name: "percentage",
123
+ type: "u8"
124
+ },
125
+ {
126
+ name: "offset_amount_in",
127
+ type: "u16"
128
+ },
129
+ {
130
+ name: "pre_user_token_balance",
131
+ type: "u64"
132
+ },
133
+ {
134
+ name: "max_swap_amount",
135
+ type: "u64"
136
+ },
137
+ {
138
+ name: "payload_data",
139
+ type: "bytes"
140
+ }
141
+ ]
142
+ }
143
+ }
144
+ ]
145
+ };
146
+
147
+ // src/helpers/jupiter.ts
148
+ function getJupiterQuote(inputMint, outputMint, amount, maxAccounts, slippageBps, onlyDirectRoutes, restrictIntermediateTokens, apiUrl = "https://lite-api.jup.ag", apiKey) {
149
+ return __async(this, null, function* () {
150
+ const params = new URLSearchParams({
151
+ inputMint: inputMint.toString(),
152
+ outputMint: outputMint.toString(),
153
+ amount: amount.toString(),
154
+ slippageBps: slippageBps.toString(),
155
+ maxAccounts: maxAccounts.toString(),
156
+ onlyDirectRoutes: onlyDirectRoutes.toString(),
157
+ restrictIntermediateTokens: restrictIntermediateTokens.toString()
158
+ });
159
+ const url = `${apiUrl}/swap/v1/quote?${params.toString()}`;
160
+ console.log(url);
161
+ const response = yield fetch(url, {
162
+ method: "GET",
163
+ headers: __spreadValues({
164
+ Accept: "application/json"
165
+ }, apiKey ? { "x-api-key": apiKey } : {})
166
+ });
167
+ if (!response.ok) {
168
+ const errorText = yield response.text();
169
+ throw new Error(`Jupiter quote failed (${response.status}): ${errorText}`);
170
+ }
171
+ const result = yield response.json();
172
+ return result;
173
+ });
174
+ }
175
+ function getJupiterSwapInstruction(userPublicKey, quoteResponse, apiUrl = "https://lite-api.jup.ag", apiKey) {
176
+ return __async(this, null, function* () {
177
+ const url = `${apiUrl}/swap/v1/swap-instructions`;
178
+ const requestBody = {
179
+ userPublicKey: userPublicKey.toString(),
180
+ quoteResponse
181
+ };
182
+ const response = yield fetch(url, {
183
+ method: "POST",
184
+ headers: __spreadValues({
185
+ "Content-Type": "application/json",
186
+ Accept: "application/json"
187
+ }, apiKey ? { "x-api-key": apiKey } : {}),
188
+ body: JSON.stringify(requestBody)
189
+ });
190
+ if (!response.ok) {
191
+ const errorText = yield response.text();
192
+ throw new Error(
193
+ `Jupiter swap instruction failed (${response.status}): ${errorText}`
194
+ );
195
+ }
196
+ const result = yield response.json();
197
+ return result;
198
+ });
199
+ }
200
+
201
+ // src/helpers/dammV2.ts
202
+ import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
203
+
204
+ // src/constants.ts
205
+ import { PublicKey } from "@solana/web3.js";
206
+ import BN from "bn.js";
207
+ import {
208
+ BIN_ARRAY_BITMAP_SIZE,
209
+ EXTENSION_BINARRAY_BITMAP_SIZE
210
+ } from "@meteora-ag/dlmm";
211
+ var ZAP_PROGRAM_ID = new PublicKey(idl_default.address);
212
+ var JUP_V6_PROGRAM_ID = new PublicKey(
213
+ "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"
214
+ );
215
+ var DAMM_V2_PROGRAM_ID = new PublicKey(
216
+ "cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG"
217
+ );
218
+ var DLMM_PROGRAM_ID = new PublicKey(
219
+ "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo"
220
+ );
221
+ var MEMO_PROGRAM_ID = new PublicKey(
222
+ "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
223
+ );
224
+ var BIN_ARRAY_INDEX_BOUND = [
225
+ BIN_ARRAY_BITMAP_SIZE.mul(
226
+ EXTENSION_BINARRAY_BITMAP_SIZE.add(new BN(1))
227
+ ).neg(),
228
+ BIN_ARRAY_BITMAP_SIZE.mul(EXTENSION_BINARRAY_BITMAP_SIZE.add(new BN(1))).sub(
229
+ new BN(1)
230
+ )
231
+ ];
232
+ var AccountsType = {
233
+ TransferHookX: {
234
+ transferHookX: {}
235
+ },
236
+ TransferHookY: {
237
+ transferHookY: {}
238
+ },
239
+ TransferHookReward: {
240
+ transferHookReward: {}
241
+ }
242
+ };
243
+ var DLMM_SWAP_DISCRIMINATOR = [65, 75, 63, 76, 235, 91, 91, 136];
244
+ var AMOUNT_IN_DLMM_OFFSET = 8;
245
+ var AMOUNT_IN_JUP_V6_REVERSE_OFFSET = 19;
246
+ var AMOUNT_IN_DAMM_V2_OFFSET = 8;
247
+ var DAMM_V2_SWAP_DISCRIMINATOR = [
248
+ 248,
249
+ 198,
250
+ 158,
251
+ 145,
252
+ 225,
253
+ 117,
254
+ 135,
255
+ 200
256
+ ];
257
+
258
+ // src/helpers/dammV2.ts
259
+ import { CpAmm, derivePoolAuthority } from "@meteora-ag/cp-amm-sdk";
260
+
261
+ // src/helpers/pda.ts
262
+ import { PublicKey as PublicKey2 } from "@solana/web3.js";
263
+ function deriveDammV2EventAuthority() {
264
+ return PublicKey2.findProgramAddressSync(
265
+ [Buffer.from("__event_authority")],
266
+ DAMM_V2_PROGRAM_ID
267
+ )[0];
268
+ }
269
+
270
+ // src/helpers/dammV2.ts
271
+ function getDammV2Pool(connection, poolAddress) {
272
+ return __async(this, null, function* () {
273
+ const cpAmmClient = new CpAmm(connection);
274
+ return yield cpAmmClient.fetchPoolState(poolAddress);
275
+ });
276
+ }
277
+ function getDammV2RemainingAccounts(_0, _1, _2, _3) {
278
+ return __async(this, arguments, function* (poolAddress, user, userInputTokenAccount, userTokenOutAccount, tokenAProgram = TOKEN_PROGRAM_ID, tokenBProgram = TOKEN_PROGRAM_ID, poolState) {
279
+ const remainingAccounts = [
280
+ {
281
+ isSigner: false,
282
+ isWritable: false,
283
+ pubkey: derivePoolAuthority()
284
+ },
285
+ {
286
+ isSigner: false,
287
+ isWritable: true,
288
+ pubkey: poolAddress
289
+ },
290
+ {
291
+ isSigner: false,
292
+ isWritable: true,
293
+ pubkey: userInputTokenAccount
294
+ },
295
+ {
296
+ isSigner: false,
297
+ isWritable: true,
298
+ pubkey: userTokenOutAccount
299
+ },
300
+ {
301
+ isSigner: false,
302
+ isWritable: true,
303
+ pubkey: poolState.tokenAVault
304
+ },
305
+ {
306
+ isSigner: false,
307
+ isWritable: true,
308
+ pubkey: poolState.tokenBVault
309
+ },
310
+ {
311
+ isSigner: false,
312
+ isWritable: false,
313
+ pubkey: poolState.tokenAMint
314
+ },
315
+ {
316
+ isSigner: false,
317
+ isWritable: false,
318
+ pubkey: poolState.tokenBMint
319
+ },
320
+ {
321
+ isSigner: true,
322
+ isWritable: false,
323
+ pubkey: user
324
+ },
325
+ {
326
+ isSigner: false,
327
+ isWritable: false,
328
+ pubkey: tokenAProgram
329
+ },
330
+ {
331
+ isSigner: false,
332
+ isWritable: false,
333
+ pubkey: tokenBProgram
334
+ },
335
+ {
336
+ isSigner: false,
337
+ isWritable: false,
338
+ pubkey: DAMM_V2_PROGRAM_ID
339
+ },
340
+ {
341
+ isSigner: false,
342
+ isWritable: false,
343
+ pubkey: deriveDammV2EventAuthority()
344
+ },
345
+ {
346
+ isSigner: false,
347
+ isWritable: false,
348
+ pubkey: DAMM_V2_PROGRAM_ID
349
+ }
350
+ ];
351
+ return remainingAccounts;
352
+ });
353
+ }
354
+ function createDammV2SwapPayload(amountIn, minimumSwapAmountOut) {
355
+ return Buffer.concat([
356
+ Buffer.from(DAMM_V2_SWAP_DISCRIMINATOR),
357
+ amountIn.toArrayLike(Buffer, "le", 8),
358
+ minimumSwapAmountOut.toArrayLike(Buffer, "le", 8)
359
+ ]);
360
+ }
361
+
362
+ // src/helpers/common.ts
363
+ import {
364
+ NATIVE_MINT,
365
+ TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID2
366
+ } from "@solana/spl-token";
367
+ import { PublicKey as PublicKey3 } from "@solana/web3.js";
368
+ function getTokenProgramFromMint(connection, mint) {
369
+ return __async(this, null, function* () {
370
+ if (mint.equals(NATIVE_MINT)) {
371
+ return TOKEN_PROGRAM_ID2;
372
+ }
373
+ try {
374
+ const mintInfo = yield connection.getAccountInfo(mint);
375
+ if (!mintInfo) {
376
+ throw new Error(`Mint account not found: ${mint.toString()}`);
377
+ }
378
+ if (mintInfo.owner.equals(
379
+ new PublicKey3("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb")
380
+ )) {
381
+ return new PublicKey3("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");
382
+ } else {
383
+ return TOKEN_PROGRAM_ID2;
384
+ }
385
+ } catch (error) {
386
+ console.warn(
387
+ `Failed to determine token program for ${mint.toString()}, defaulting to TOKEN_PROGRAM_ID:`,
388
+ error
389
+ );
390
+ return TOKEN_PROGRAM_ID2;
391
+ }
392
+ });
393
+ }
394
+
395
+ // src/helpers/token.ts
396
+ import {
397
+ createAssociatedTokenAccountIdempotentInstruction,
398
+ createCloseAccountInstruction,
399
+ getAccount,
400
+ getAssociatedTokenAddressSync,
401
+ NATIVE_MINT as NATIVE_MINT2,
402
+ TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID3,
403
+ TokenAccountNotFoundError,
404
+ TokenInvalidAccountOwnerError
405
+ } from "@solana/spl-token";
406
+ import {
407
+ SystemProgram,
408
+ TransactionInstruction
409
+ } from "@solana/web3.js";
410
+ var getOrCreateATAInstruction = (connection, tokenMint, owner, payer, allowOwnerOffCurve = true, tokenProgram) => __async(null, null, function* () {
411
+ const toAccount = getAssociatedTokenAddressSync(
412
+ tokenMint,
413
+ owner,
414
+ allowOwnerOffCurve,
415
+ tokenProgram
416
+ );
417
+ try {
418
+ yield getAccount(connection, toAccount);
419
+ return { ataPubkey: toAccount, ix: void 0 };
420
+ } catch (e) {
421
+ if (e instanceof TokenAccountNotFoundError || e instanceof TokenInvalidAccountOwnerError) {
422
+ const ix = createAssociatedTokenAccountIdempotentInstruction(
423
+ payer,
424
+ toAccount,
425
+ owner,
426
+ tokenMint,
427
+ tokenProgram
428
+ );
429
+ return { ataPubkey: toAccount, ix };
430
+ } else {
431
+ console.error("Error::getOrCreateATAInstruction", e);
432
+ throw e;
433
+ }
434
+ }
435
+ });
436
+ function unwrapSOLInstruction(owner, receiver, allowOwnerOffCurve = true) {
437
+ const wSolATAAccount = getAssociatedTokenAddressSync(
438
+ NATIVE_MINT2,
439
+ owner,
440
+ allowOwnerOffCurve
441
+ );
442
+ if (wSolATAAccount) {
443
+ const closedWrappedSolInstruction = createCloseAccountInstruction(
444
+ wSolATAAccount,
445
+ receiver,
446
+ owner,
447
+ [],
448
+ TOKEN_PROGRAM_ID3
449
+ );
450
+ return closedWrappedSolInstruction;
451
+ }
452
+ return null;
453
+ }
454
+ function wrapSOLInstruction(from, to, amount, tokenProgram = TOKEN_PROGRAM_ID3) {
455
+ return [
456
+ SystemProgram.transfer({
457
+ fromPubkey: from,
458
+ toPubkey: to,
459
+ lamports: amount
460
+ }),
461
+ new TransactionInstruction({
462
+ keys: [
463
+ {
464
+ pubkey: to,
465
+ isSigner: false,
466
+ isWritable: true
467
+ }
468
+ ],
469
+ data: Buffer.from(new Uint8Array([17])),
470
+ programId: tokenProgram
471
+ })
472
+ ];
473
+ }
474
+
475
+ // src/helpers/dlmm.ts
476
+ import { PublicKey as PublicKey6 } from "@solana/web3.js";
477
+ import BN2 from "bn.js";
478
+ import DLMM, {
479
+ isOverflowDefaultBinArrayBitmap,
480
+ BIN_ARRAY_BITMAP_SIZE as BIN_ARRAY_BITMAP_SIZE2,
481
+ createProgram,
482
+ deriveBinArrayBitmapExtension,
483
+ deriveOracle,
484
+ deriveEventAuthority
485
+ } from "@meteora-ag/dlmm";
486
+
487
+ // src/helpers/token2022.ts
488
+ import {
489
+ createTransferCheckedWithTransferHookInstruction,
490
+ getTransferHook,
491
+ TOKEN_2022_PROGRAM_ID as TOKEN_2022_PROGRAM_ID2,
492
+ TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID4,
493
+ unpackMint
494
+ } from "@solana/spl-token";
495
+ import { PublicKey as PublicKey5 } from "@solana/web3.js";
496
+ function getExtraAccountMetasForTransferHook(connection, mint) {
497
+ return __async(this, null, function* () {
498
+ const info = yield connection.getAccountInfo(mint);
499
+ if (!info) {
500
+ return [];
501
+ }
502
+ if (info.owner.equals(TOKEN_PROGRAM_ID4)) {
503
+ return [];
504
+ }
505
+ const accountInfoWithBuffer = __spreadProps(__spreadValues({}, info), {
506
+ data: Buffer.from(info.data)
507
+ });
508
+ const mintInfo = unpackMint(
509
+ mint,
510
+ accountInfoWithBuffer,
511
+ TOKEN_2022_PROGRAM_ID2
512
+ );
513
+ const transferHook = getTransferHook(mintInfo);
514
+ if (!transferHook) {
515
+ return [];
516
+ } else {
517
+ const transferWithHookIx = createTransferCheckedWithTransferHookInstruction(
518
+ connection,
519
+ PublicKey5.default,
520
+ mint,
521
+ PublicKey5.default,
522
+ PublicKey5.default,
523
+ BigInt(0),
524
+ mintInfo.decimals,
525
+ [],
526
+ "confirmed",
527
+ TOKEN_2022_PROGRAM_ID2
528
+ );
529
+ return (yield transferWithHookIx).keys.slice(4);
530
+ }
531
+ });
532
+ }
533
+
534
+ // src/helpers/dlmm.ts
535
+ function getLbPairState(connection, lbPair) {
536
+ return __async(this, null, function* () {
537
+ const dlmmClient = yield DLMM.create(connection, lbPair, {
538
+ cluster: "mainnet-beta",
539
+ programId: new PublicKey6(DLMM_PROGRAM_ID)
540
+ });
541
+ return dlmmClient.lbPair;
542
+ });
543
+ }
544
+ function getBinArrayBitmapExtension(connection, binArray) {
545
+ return __async(this, null, function* () {
546
+ const program = createProgram(connection);
547
+ const account = yield connection.getAccountInfo(binArray);
548
+ if (!account) {
549
+ return null;
550
+ }
551
+ return program.coder.accounts.decode(
552
+ "binArrayBitmapExtension",
553
+ Buffer.from(account.data)
554
+ );
555
+ });
556
+ }
557
+ function getBitFromBinArrayIndexInBitmapExtension(binArrayIndex, state) {
558
+ const idx = binArrayIndex.isNeg() ? binArrayIndex.add(new BN2(1)).abs().sub(BIN_ARRAY_BITMAP_SIZE2) : binArrayIndex.sub(BIN_ARRAY_BITMAP_SIZE2);
559
+ const bitmapOffset = idx.div(BIN_ARRAY_BITMAP_SIZE2);
560
+ const bitmap = binArrayIndex.isNeg() ? state.negativeBinArrayBitmap[bitmapOffset.toNumber()] : state.positiveBinArrayBitmap[bitmapOffset.toNumber()];
561
+ const { div: offsetToU64InBitmap, mod: offsetToBit } = idx.divmod(new BN2(64));
562
+ const { mod: offsetToU64InChunkBitmap } = offsetToU64InBitmap.divmod(
563
+ new BN2(8)
564
+ );
565
+ if (!bitmap) {
566
+ console.log(binArrayIndex.toString());
567
+ console.log(bitmapOffset.toString());
568
+ }
569
+ const chunkedBitmap = bitmap[offsetToU64InChunkBitmap.toNumber()];
570
+ return chunkedBitmap.testn(offsetToBit.toNumber());
571
+ }
572
+ function getNextBinArrayIndexWithLiquidity(binArrayIndex, pairState, swapForY, state) {
573
+ const [minBinArrayIndex, maxBinArrayIndex] = BIN_ARRAY_INDEX_BOUND;
574
+ const step = swapForY ? new BN2(-1) : new BN2(1);
575
+ while (true) {
576
+ if (isOverflowDefaultBinArrayBitmap(binArrayIndex)) {
577
+ if (state) {
578
+ const isBitSet = getBitFromBinArrayIndexInBitmapExtension(
579
+ binArrayIndex,
580
+ state
581
+ );
582
+ if (isBitSet) {
583
+ return binArrayIndex;
584
+ }
585
+ } else {
586
+ break;
587
+ }
588
+ } else {
589
+ const actualIdx = binArrayIndex.add(BIN_ARRAY_BITMAP_SIZE2);
590
+ let { div: offsetInFullBitmap, mod: index } = actualIdx.divmod(
591
+ new BN2(64)
592
+ );
593
+ if (pairState.binArrayBitmap[offsetInFullBitmap.toNumber()].testn(
594
+ index.toNumber()
595
+ )) {
596
+ return binArrayIndex;
597
+ }
598
+ }
599
+ binArrayIndex = binArrayIndex.add(step);
600
+ if (binArrayIndex.gt(maxBinArrayIndex) || binArrayIndex.lt(minBinArrayIndex)) {
601
+ break;
602
+ }
603
+ }
604
+ return null;
605
+ }
606
+ function getDlmmRemainingAccounts(connection, lbPair, user, userInputTokenAccount, userTokenOutAccount, tokenXProgram, tokenYProgram, lbPairState) {
607
+ return __async(this, null, function* () {
608
+ let [binArrayBitmapExtension] = deriveBinArrayBitmapExtension(
609
+ lbPair,
610
+ DLMM_PROGRAM_ID
611
+ );
612
+ const binArrayBitmapExtensionState = yield connection.getAccountInfo(
613
+ binArrayBitmapExtension
614
+ );
615
+ if (!binArrayBitmapExtensionState) {
616
+ binArrayBitmapExtension = new PublicKey6(DLMM_PROGRAM_ID);
617
+ }
618
+ const transferHookXAccounts = yield getExtraAccountMetasForTransferHook(
619
+ connection,
620
+ lbPairState.tokenXMint
621
+ );
622
+ const transferHookYAccounts = yield getExtraAccountMetasForTransferHook(
623
+ connection,
624
+ lbPairState.tokenYMint
625
+ );
626
+ let remainingAccountsInfo = { slices: [] };
627
+ if (transferHookXAccounts.length > 0) {
628
+ remainingAccountsInfo.slices.push({
629
+ accountsType: AccountsType.TransferHookX,
630
+ length: transferHookXAccounts.length
631
+ });
632
+ }
633
+ if (transferHookYAccounts.length > 0) {
634
+ remainingAccountsInfo.slices.push({
635
+ accountsType: AccountsType.TransferHookY,
636
+ length: transferHookYAccounts.length
637
+ });
638
+ }
639
+ const [oracle] = deriveOracle(lbPair, DLMM_PROGRAM_ID);
640
+ const [eventAuthority] = deriveEventAuthority(DLMM_PROGRAM_ID);
641
+ const remainingAccounts = [
642
+ {
643
+ isSigner: false,
644
+ isWritable: true,
645
+ pubkey: lbPair
646
+ },
647
+ {
648
+ isSigner: false,
649
+ isWritable: false,
650
+ pubkey: binArrayBitmapExtension
651
+ },
652
+ {
653
+ isSigner: false,
654
+ isWritable: true,
655
+ pubkey: lbPairState.reserveX
656
+ },
657
+ {
658
+ isSigner: false,
659
+ isWritable: true,
660
+ pubkey: lbPairState.reserveY
661
+ },
662
+ {
663
+ isSigner: false,
664
+ isWritable: true,
665
+ pubkey: userInputTokenAccount
666
+ },
667
+ {
668
+ isSigner: false,
669
+ isWritable: true,
670
+ pubkey: userTokenOutAccount
671
+ },
672
+ {
673
+ isSigner: false,
674
+ isWritable: false,
675
+ pubkey: lbPairState.tokenXMint
676
+ },
677
+ {
678
+ isSigner: false,
679
+ isWritable: false,
680
+ pubkey: lbPairState.tokenYMint
681
+ },
682
+ {
683
+ isSigner: false,
684
+ isWritable: true,
685
+ pubkey: oracle
686
+ },
687
+ {
688
+ isSigner: false,
689
+ isWritable: true,
690
+ pubkey: new PublicKey6(DLMM_PROGRAM_ID)
691
+ // host fee option
692
+ },
693
+ {
694
+ isSigner: true,
695
+ isWritable: false,
696
+ pubkey: user
697
+ },
698
+ {
699
+ isSigner: false,
700
+ isWritable: false,
701
+ pubkey: tokenXProgram
702
+ },
703
+ {
704
+ isSigner: false,
705
+ isWritable: false,
706
+ pubkey: tokenYProgram
707
+ },
708
+ {
709
+ isSigner: false,
710
+ isWritable: false,
711
+ pubkey: MEMO_PROGRAM_ID
712
+ },
713
+ {
714
+ isSigner: false,
715
+ isWritable: false,
716
+ pubkey: eventAuthority
717
+ },
718
+ {
719
+ isSigner: false,
720
+ isWritable: false,
721
+ pubkey: DLMM_PROGRAM_ID
722
+ }
723
+ ];
724
+ const dlmmClient = yield DLMM.create(connection, lbPair, {
725
+ cluster: "mainnet-beta",
726
+ programId: new PublicKey6(DLMM_PROGRAM_ID)
727
+ });
728
+ const binArrays = yield dlmmClient.getBinArrayForSwap(true, 5);
729
+ const binArraysAccountMeta = binArrays.map((binArray) => {
730
+ return {
731
+ isSigner: false,
732
+ isWritable: true,
733
+ pubkey: binArray.publicKey
734
+ };
735
+ });
736
+ remainingAccounts.push(
737
+ ...[...transferHookXAccounts, ...transferHookYAccounts]
738
+ );
739
+ remainingAccounts.push(...binArraysAccountMeta);
740
+ return {
741
+ remainingAccounts,
742
+ remainingAccountsInfo
743
+ };
744
+ });
745
+ }
746
+ function convertAccountTypeToNumber(accountType) {
747
+ if (JSON.stringify(accountType) === JSON.stringify({ transferHookX: {} })) {
748
+ return 0;
749
+ }
750
+ if (JSON.stringify(accountType) === JSON.stringify({ transferHookY: {} })) {
751
+ return 1;
752
+ }
753
+ if (JSON.stringify(accountType) === JSON.stringify({ transferHookReward: {} })) {
754
+ return 2;
755
+ }
756
+ throw new Error(`Unknown account type: ${JSON.stringify(accountType)}`);
757
+ }
758
+ function createDlmmSwapPayload(amountIn, minimumSwapAmountOut, remainingAccountsInfo) {
759
+ const sliceCount = Buffer.alloc(4);
760
+ sliceCount.writeUInt32LE(remainingAccountsInfo.slices.length, 0);
761
+ const slicesData = Buffer.concat(
762
+ remainingAccountsInfo.slices.map((slice) => {
763
+ const sliceBuffer = Buffer.alloc(2);
764
+ sliceBuffer.writeUInt8(convertAccountTypeToNumber(slice.accountsType), 0);
765
+ sliceBuffer.writeUInt8(slice.length, 1);
766
+ return sliceBuffer;
767
+ })
768
+ );
769
+ return Buffer.concat([
770
+ Buffer.from(DLMM_SWAP_DISCRIMINATOR),
771
+ amountIn.toArrayLike(Buffer, "le", 8),
772
+ minimumSwapAmountOut.toArrayLike(Buffer, "le", 8),
773
+ sliceCount,
774
+ slicesData
775
+ ]);
776
+ }
777
+
778
+ // src/zap.ts
779
+ import { getTokenProgram } from "@meteora-ag/cp-amm-sdk";
780
+ var Zap = class {
781
+ constructor(connection) {
782
+ this.connection = connection;
783
+ this.zapProgram = new Program(idl_default, { connection });
784
+ }
785
+ /////// ZAPOUT PROGRAM ///////
786
+ /**
787
+ * Executes a generic zap out operation with custom parameters.
788
+ *
789
+ * @param params - Zap out operation parameters
790
+ * @param params.userTokenInAccount - Token ledger account to zap out from
791
+ * @param params.zapOutParams - Zap out parameters
792
+ * @param params.remainingAccounts - Additional accounts needed for the operation
793
+ * @param params.ammProgram - AMM program ID to interact with
794
+ * @param params.preInstructions - Instructions to run before the zap out
795
+ * @param params.postInstructions - Instructions to run after the zap out
796
+ * @returns builder transaction
797
+ */
798
+ zapOut(params) {
799
+ return __async(this, null, function* () {
800
+ const {
801
+ zapOutParams,
802
+ userTokenInAccount,
803
+ remainingAccounts,
804
+ ammProgram,
805
+ preInstructions,
806
+ postInstructions
807
+ } = params;
808
+ return this.zapProgram.methods.zapOut(zapOutParams).accountsPartial({
809
+ userTokenInAccount,
810
+ ammProgram
811
+ }).remainingAccounts(remainingAccounts).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
812
+ });
813
+ }
814
+ /**
815
+ * Performs a token swap using Jupiter V6 protocol as part of a zap out operation.
816
+ * Swaps tokens from the input token ledger to the user's output token account.
817
+ *
818
+ * @param params - Jupiter V6 swap parameters from Jupiter API
819
+ * @param params.user - Public key of the user performing the swap
820
+ * @param params.inputMint - Token mint being swapped from
821
+ * @param params.outputMint - Token mint being swapped to
822
+ * @param params.jupiterSwapResponse - Jupiter swap instruction response
823
+ * @param params.inputTokenProgram - Token program for the input token (defaults to SPL Token)
824
+ * @param params.outputTokenProgram - Token program for the output token (defaults to SPL Token)
825
+ * @param params.maxSwapAmount - Maximum amount of input token to swap
826
+ * @param params.percentageToZapOut - Percentage of input token to zap out
827
+ * @returns built transaction
828
+ */
829
+ zapOutThroughJupiter(params) {
830
+ return __async(this, null, function* () {
831
+ const {
832
+ inputTokenAccount,
833
+ jupiterSwapResponse,
834
+ maxSwapAmount,
835
+ percentageToZapOut,
836
+ preInstructions,
837
+ postInstructions
838
+ } = params;
839
+ const preUserTokenBalance = (yield this.connection.getTokenAccountBalance(inputTokenAccount)).value.amount;
840
+ const remainingAccounts = jupiterSwapResponse.swapInstruction.accounts.map(
841
+ (account) => {
842
+ let pubkey = typeof account.pubkey === "string" ? new PublicKey7(account.pubkey) : account.pubkey;
843
+ return {
844
+ pubkey,
845
+ isSigner: account.isSigner,
846
+ isWritable: account.isWritable
847
+ };
848
+ }
849
+ );
850
+ const payloadData = Buffer.from(
851
+ jupiterSwapResponse.swapInstruction.data,
852
+ "base64"
853
+ );
854
+ const offsetAmountIn = payloadData.length - AMOUNT_IN_JUP_V6_REVERSE_OFFSET;
855
+ return yield this.zapOut({
856
+ userTokenInAccount: inputTokenAccount,
857
+ zapOutParams: {
858
+ percentage: percentageToZapOut,
859
+ offsetAmountIn,
860
+ preUserTokenBalance: new BN3(preUserTokenBalance),
861
+ maxSwapAmount,
862
+ payloadData
863
+ },
864
+ remainingAccounts,
865
+ ammProgram: JUP_V6_PROGRAM_ID,
866
+ preInstructions: preInstructions || [],
867
+ postInstructions: postInstructions || []
868
+ });
869
+ });
870
+ }
871
+ /**
872
+ * Performs a token swap using Damms V2 protocol as part of a zap out operation.
873
+ * Swaps tokens from the input token ledger to the user's output token account.
874
+ *
875
+ * @param params - Damms V2 swap parameters
876
+ * @param params.user - Public key of the user performing the swap
877
+ * @param params.poolAddress - Address of the pool to swap through
878
+ * @param params.inputMint - Token mint being swapped from
879
+ * @param params.inputTokenProgram - Token program for the input token (defaults to SPL Token)
880
+ * @param params.amountIn - Amount of input token to swap
881
+ * @param params.minimumSwapAmountOut - Minimum amount of output token to receive
882
+ * @param params.maxSwapAmount - Maximum amount of input token to swap
883
+ * @param params.percentageToZapOut - Percentage of input token to zap out
884
+ */
885
+ zapOutThroughDammV2(params) {
886
+ return __async(this, null, function* () {
887
+ const {
888
+ user,
889
+ poolAddress,
890
+ inputTokenAccount,
891
+ outputTokenAccount,
892
+ amountIn,
893
+ minimumSwapAmountOut,
894
+ maxSwapAmount,
895
+ percentageToZapOut,
896
+ preInstructions,
897
+ postInstructions
898
+ } = params;
899
+ const poolState = yield getDammV2Pool(this.connection, poolAddress);
900
+ const preUserTokenBalance = (yield this.connection.getTokenAccountBalance(inputTokenAccount)).value.amount;
901
+ const remainingAccounts = yield getDammV2RemainingAccounts(
902
+ poolAddress,
903
+ user,
904
+ inputTokenAccount,
905
+ outputTokenAccount,
906
+ getTokenProgram(poolState.tokenAFlag),
907
+ getTokenProgram(poolState.tokenBFlag),
908
+ poolState
909
+ );
910
+ const payloadData = createDammV2SwapPayload(amountIn, minimumSwapAmountOut);
911
+ const offsetAmountIn = AMOUNT_IN_DAMM_V2_OFFSET;
912
+ return yield this.zapOut({
913
+ userTokenInAccount: inputTokenAccount,
914
+ zapOutParams: {
915
+ percentage: percentageToZapOut,
916
+ offsetAmountIn,
917
+ preUserTokenBalance: new BN3(preUserTokenBalance),
918
+ maxSwapAmount,
919
+ payloadData
920
+ },
921
+ remainingAccounts,
922
+ ammProgram: DAMM_V2_PROGRAM_ID,
923
+ preInstructions: preInstructions || [],
924
+ postInstructions: postInstructions || []
925
+ });
926
+ });
927
+ }
928
+ /**
929
+ * Performs a token swap using Dlmm protocol as part of a zap out operation.
930
+ * Swaps tokens from the input token ledger to the user's output token account.
931
+ *
932
+ * @param params - Dlmm swap parameters
933
+ * @param params.user - Public key of the user performing the swap
934
+ * @param params.lbPairAddress - Address of the lbPair to swap through
935
+ * @param params.inputMint - Token mint being swapped from
936
+ * @param params.inputTokenProgram - Token program for the input token (defaults to SPL Token)
937
+ * @param params.amountIn - Amount of input token to swap
938
+ * @param params.minimumSwapAmountOut - Minimum amount of output token to receive
939
+ * @param params.maxSwapAmount - Maximum amount of input token to swap
940
+ * @param params.percentageToZapOut - Percentage of input token to zap out
941
+ */
942
+ zapOutThroughDlmm(params) {
943
+ return __async(this, null, function* () {
944
+ const {
945
+ user,
946
+ lbPairAddress,
947
+ inputTokenAccount,
948
+ outputTokenAccount,
949
+ amountIn,
950
+ minimumSwapAmountOut,
951
+ maxSwapAmount,
952
+ percentageToZapOut,
953
+ preInstructions,
954
+ postInstructions
955
+ } = params;
956
+ const lbPairState = yield getLbPairState(this.connection, lbPairAddress);
957
+ const preUserTokenBalance = (yield this.connection.getTokenAccountBalance(inputTokenAccount)).value.amount;
958
+ const { remainingAccounts, remainingAccountsInfo } = yield getDlmmRemainingAccounts(
959
+ this.connection,
960
+ lbPairAddress,
961
+ user,
962
+ inputTokenAccount,
963
+ outputTokenAccount,
964
+ getTokenProgram(lbPairState.tokenMintXProgramFlag),
965
+ getTokenProgram(lbPairState.tokenMintYProgramFlag),
966
+ lbPairState
967
+ );
968
+ const payloadData = createDlmmSwapPayload(
969
+ amountIn,
970
+ minimumSwapAmountOut,
971
+ remainingAccountsInfo
972
+ );
973
+ return yield this.zapOut({
974
+ userTokenInAccount: inputTokenAccount,
975
+ zapOutParams: {
976
+ percentage: percentageToZapOut,
977
+ offsetAmountIn: AMOUNT_IN_DLMM_OFFSET,
978
+ preUserTokenBalance: new BN3(preUserTokenBalance),
979
+ maxSwapAmount,
980
+ payloadData
981
+ },
982
+ remainingAccounts,
983
+ ammProgram: DLMM_PROGRAM_ID,
984
+ preInstructions: preInstructions || [],
985
+ postInstructions: postInstructions || []
986
+ });
987
+ });
988
+ }
989
+ };
990
+ export {
991
+ AMOUNT_IN_DAMM_V2_OFFSET,
992
+ AMOUNT_IN_DLMM_OFFSET,
993
+ AMOUNT_IN_JUP_V6_REVERSE_OFFSET,
994
+ AccountsType,
995
+ BIN_ARRAY_INDEX_BOUND,
996
+ DAMM_V2_PROGRAM_ID,
997
+ DAMM_V2_SWAP_DISCRIMINATOR,
998
+ DLMM_PROGRAM_ID,
999
+ DLMM_SWAP_DISCRIMINATOR,
1000
+ JUP_V6_PROGRAM_ID,
1001
+ MEMO_PROGRAM_ID,
1002
+ ZAP_PROGRAM_ID,
1003
+ Zap,
1004
+ convertAccountTypeToNumber,
1005
+ createDammV2SwapPayload,
1006
+ createDlmmSwapPayload,
1007
+ deriveDammV2EventAuthority,
1008
+ getBinArrayBitmapExtension,
1009
+ getBitFromBinArrayIndexInBitmapExtension,
1010
+ getDammV2Pool,
1011
+ getDammV2RemainingAccounts,
1012
+ getDlmmRemainingAccounts,
1013
+ getExtraAccountMetasForTransferHook,
1014
+ getJupiterQuote,
1015
+ getJupiterSwapInstruction,
1016
+ getLbPairState,
1017
+ getNextBinArrayIndexWithLiquidity,
1018
+ getOrCreateATAInstruction,
1019
+ getTokenProgramFromMint,
1020
+ unwrapSOLInstruction,
1021
+ wrapSOLInstruction
1022
+ };