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