@meteora-ag/zap-sdk 1.2.0-rc.2 → 1.2.0-rc.4

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.d.mts CHANGED
@@ -2019,6 +2019,8 @@ declare class Zap {
2019
2019
  private updateLedgerBalanceAfterSwap;
2020
2020
  private zapInDammV2;
2021
2021
  private resetOrInitializeLedgerAccount;
2022
+ private isJupiterQuoteableAmount;
2023
+ private findMinimumJupiterQuoteableAmount;
2022
2024
  private zapInDlmmForInitializedPosition;
2023
2025
  private zapInDlmmForUninitializedPosition;
2024
2026
  /**
package/dist/index.d.ts CHANGED
@@ -2019,6 +2019,8 @@ declare class Zap {
2019
2019
  private updateLedgerBalanceAfterSwap;
2020
2020
  private zapInDammV2;
2021
2021
  private resetOrInitializeLedgerAccount;
2022
+ private isJupiterQuoteableAmount;
2023
+ private findMinimumJupiterQuoteableAmount;
2022
2024
  private zapInDlmmForInitializedPosition;
2023
2025
  private zapInDlmmForUninitializedPosition;
2024
2026
  /**
package/dist/index.js CHANGED
@@ -3205,6 +3205,26 @@ function calculateIndirectPoolSwapAmount(amount, amountDecimals, price1, price2,
3205
3205
  convertUiAmountToLamports(swapAmountDecimal, amountDecimals).floor().toString()
3206
3206
  );
3207
3207
  }
3208
+ function splitIndirectSwapAmounts(amountIn, swapAmountToA) {
3209
+ if (swapAmountToA.isNeg()) {
3210
+ throw new Error("Calculated swap amount to token A cannot be negative");
3211
+ }
3212
+ if (swapAmountToA.gt(amountIn)) {
3213
+ throw new Error(
3214
+ "Calculated swap amount to token A exceeds total input amount"
3215
+ );
3216
+ }
3217
+ const swapAmountToB = amountIn.sub(swapAmountToA);
3218
+ if (swapAmountToB.isNeg()) {
3219
+ throw new Error("Calculated swap amount to token B cannot be negative");
3220
+ }
3221
+ return {
3222
+ swapAmountToA,
3223
+ swapAmountToB,
3224
+ hasSwapToA: !swapAmountToA.isZero(),
3225
+ hasSwapToB: !swapAmountToB.isZero()
3226
+ };
3227
+ }
3208
3228
  function getExtendMaxAmountTransfer(amount, percentage) {
3209
3229
  const extendAmount = new import_decimal3.default(amount).mul(percentage).div(100).floor().toString();
3210
3230
  return new import_bn4.default(amount).add(new import_bn4.default(extendAmount));
@@ -3312,6 +3332,65 @@ var Zap = class {
3312
3332
  return yield this.initializeLedgerAccount(user, user);
3313
3333
  });
3314
3334
  }
3335
+ isJupiterQuoteableAmount(inputMint, outputMint, amount, maxAccounts, slippageBps) {
3336
+ return __async(this, null, function* () {
3337
+ if (amount.isZero()) {
3338
+ return true;
3339
+ }
3340
+ const quote = yield getJupiterQuote(
3341
+ inputMint,
3342
+ outputMint,
3343
+ amount,
3344
+ maxAccounts,
3345
+ slippageBps,
3346
+ false,
3347
+ true,
3348
+ true,
3349
+ {
3350
+ jupiterApiUrl: this.jupiterApiUrl,
3351
+ jupiterApiKey: this.jupiterApiKey
3352
+ }
3353
+ );
3354
+ return quote !== null;
3355
+ });
3356
+ }
3357
+ findMinimumJupiterQuoteableAmount(inputMint, outputMint, maxAmount, maxAccounts, slippageBps) {
3358
+ return __async(this, null, function* () {
3359
+ if (maxAmount.isZero()) {
3360
+ return null;
3361
+ }
3362
+ const maxAmountQuoteable = yield this.isJupiterQuoteableAmount(
3363
+ inputMint,
3364
+ outputMint,
3365
+ maxAmount,
3366
+ maxAccounts,
3367
+ slippageBps
3368
+ );
3369
+ if (!maxAmountQuoteable) {
3370
+ return null;
3371
+ }
3372
+ let left = new import_anchor.BN(1);
3373
+ let right = maxAmount;
3374
+ let best = maxAmount;
3375
+ while (left.lte(right)) {
3376
+ const mid = left.add(right).div(new import_anchor.BN(2));
3377
+ const isQuoteable = yield this.isJupiterQuoteableAmount(
3378
+ inputMint,
3379
+ outputMint,
3380
+ mid,
3381
+ maxAccounts,
3382
+ slippageBps
3383
+ );
3384
+ if (isQuoteable) {
3385
+ best = mid;
3386
+ right = mid.sub(new import_anchor.BN(1));
3387
+ } else {
3388
+ left = mid.add(new import_anchor.BN(1));
3389
+ }
3390
+ }
3391
+ return best;
3392
+ });
3393
+ }
3315
3394
  zapInDlmmForInitializedPosition(params) {
3316
3395
  return __async(this, null, function* () {
3317
3396
  const {
@@ -3862,8 +3941,63 @@ var Zap = class {
3862
3941
  tokenBDecimal
3863
3942
  )
3864
3943
  );
3865
- const swapAmountToB = amountIn.sub(swapAmountToA);
3866
- if (swapAmountToA.isZero()) {
3944
+ let { swapAmountToA: adjustedSwapAmountToA, swapAmountToB } = splitIndirectSwapAmounts(amountIn, swapAmountToA);
3945
+ const quoteableA = yield this.isJupiterQuoteableAmount(
3946
+ inputTokenMint,
3947
+ tokenAMint,
3948
+ adjustedSwapAmountToA,
3949
+ maxAccounts,
3950
+ slippageBps
3951
+ );
3952
+ if (!quoteableA && !adjustedSwapAmountToA.isZero()) {
3953
+ const minQuoteableToA = yield this.findMinimumJupiterQuoteableAmount(
3954
+ inputTokenMint,
3955
+ tokenAMint,
3956
+ amountIn,
3957
+ maxAccounts,
3958
+ slippageBps
3959
+ );
3960
+ if (minQuoteableToA !== null) {
3961
+ adjustedSwapAmountToA = minQuoteableToA;
3962
+ swapAmountToB = amountIn.sub(adjustedSwapAmountToA);
3963
+ } else {
3964
+ adjustedSwapAmountToA = new import_anchor.BN(0);
3965
+ swapAmountToB = amountIn;
3966
+ }
3967
+ }
3968
+ const quoteableB = yield this.isJupiterQuoteableAmount(
3969
+ inputTokenMint,
3970
+ tokenBMint,
3971
+ swapAmountToB,
3972
+ maxAccounts,
3973
+ slippageBps
3974
+ );
3975
+ if (!quoteableB && !swapAmountToB.isZero()) {
3976
+ const minQuoteableToB = yield this.findMinimumJupiterQuoteableAmount(
3977
+ inputTokenMint,
3978
+ tokenBMint,
3979
+ amountIn,
3980
+ maxAccounts,
3981
+ slippageBps
3982
+ );
3983
+ if (minQuoteableToB !== null) {
3984
+ swapAmountToB = minQuoteableToB;
3985
+ adjustedSwapAmountToA = amountIn.sub(swapAmountToB);
3986
+ } else {
3987
+ swapAmountToB = new import_anchor.BN(0);
3988
+ adjustedSwapAmountToA = amountIn;
3989
+ }
3990
+ }
3991
+ const { hasSwapToA, hasSwapToB } = splitIndirectSwapAmounts(
3992
+ amountIn,
3993
+ adjustedSwapAmountToA
3994
+ );
3995
+ if (!hasSwapToA && !hasSwapToB) {
3996
+ throw new Error(
3997
+ "Calculated zero swap amount for both token routes, unable to proceed"
3998
+ );
3999
+ }
4000
+ if (!hasSwapToA) {
3867
4001
  const { transaction: swapToBTransaction2, quoteResponse: swapToBQuote2 } = yield buildJupiterSwapTransaction(
3868
4002
  user,
3869
4003
  inputTokenMint,
@@ -3909,12 +4043,12 @@ var Zap = class {
3909
4043
  }
3910
4044
  };
3911
4045
  }
3912
- if (swapAmountToB.isZero()) {
4046
+ if (!hasSwapToB) {
3913
4047
  const { transaction: swapToATransaction2, quoteResponse: swapToAQuote2 } = yield buildJupiterSwapTransaction(
3914
4048
  user,
3915
4049
  inputTokenMint,
3916
4050
  tokenAMint,
3917
- swapAmountToA,
4051
+ adjustedSwapAmountToA,
3918
4052
  maxAccounts,
3919
4053
  slippageBps,
3920
4054
  void 0,
@@ -3941,14 +4075,14 @@ var Zap = class {
3941
4075
  swapToAQuote2.outAmount,
3942
4076
  maxTransferAmountExtendPercentage
3943
4077
  ),
3944
- maxTransferAmountB: new import_anchor.BN(0),
3945
4078
  swapType: 0 /* swapToA */,
4079
+ maxTransferAmountB: new import_anchor.BN(0),
3946
4080
  preSqrtPrice: poolState.sqrtPrice,
3947
4081
  preInstructions,
3948
4082
  swapTransactions: [swapToATransaction2],
3949
4083
  cleanUpInstructions,
3950
4084
  swapInEstimate: {
3951
- inAmountA: swapAmountToA,
4085
+ inAmountA: adjustedSwapAmountToA,
3952
4086
  inAmountB: new import_anchor.BN(0),
3953
4087
  routeA: "jupiter" /* Jupiter */,
3954
4088
  routeB: "dammV2" /* DammV2 */
@@ -3959,7 +4093,7 @@ var Zap = class {
3959
4093
  user,
3960
4094
  inputTokenMint,
3961
4095
  tokenAMint,
3962
- swapAmountToA,
4096
+ adjustedSwapAmountToA,
3963
4097
  maxAccounts,
3964
4098
  slippageBps,
3965
4099
  void 0,
@@ -4009,7 +4143,7 @@ var Zap = class {
4009
4143
  swapTransactions: [swapToATransaction, swapToBTransaction],
4010
4144
  cleanUpInstructions,
4011
4145
  swapInEstimate: {
4012
- inAmountA: swapAmountToA,
4146
+ inAmountA: adjustedSwapAmountToA,
4013
4147
  inAmountB: swapAmountToB,
4014
4148
  routeA: "jupiter" /* Jupiter */,
4015
4149
  routeB: "jupiter" /* Jupiter */
package/dist/index.mjs CHANGED
@@ -3184,6 +3184,26 @@ function calculateIndirectPoolSwapAmount(amount, amountDecimals, price1, price2,
3184
3184
  convertUiAmountToLamports(swapAmountDecimal, amountDecimals).floor().toString()
3185
3185
  );
3186
3186
  }
3187
+ function splitIndirectSwapAmounts(amountIn, swapAmountToA) {
3188
+ if (swapAmountToA.isNeg()) {
3189
+ throw new Error("Calculated swap amount to token A cannot be negative");
3190
+ }
3191
+ if (swapAmountToA.gt(amountIn)) {
3192
+ throw new Error(
3193
+ "Calculated swap amount to token A exceeds total input amount"
3194
+ );
3195
+ }
3196
+ const swapAmountToB = amountIn.sub(swapAmountToA);
3197
+ if (swapAmountToB.isNeg()) {
3198
+ throw new Error("Calculated swap amount to token B cannot be negative");
3199
+ }
3200
+ return {
3201
+ swapAmountToA,
3202
+ swapAmountToB,
3203
+ hasSwapToA: !swapAmountToA.isZero(),
3204
+ hasSwapToB: !swapAmountToB.isZero()
3205
+ };
3206
+ }
3187
3207
  function getExtendMaxAmountTransfer(amount, percentage) {
3188
3208
  const extendAmount = new Decimal3(amount).mul(percentage).div(100).floor().toString();
3189
3209
  return new BN4(amount).add(new BN4(extendAmount));
@@ -3291,6 +3311,65 @@ var Zap = class {
3291
3311
  return yield this.initializeLedgerAccount(user, user);
3292
3312
  });
3293
3313
  }
3314
+ isJupiterQuoteableAmount(inputMint, outputMint, amount, maxAccounts, slippageBps) {
3315
+ return __async(this, null, function* () {
3316
+ if (amount.isZero()) {
3317
+ return true;
3318
+ }
3319
+ const quote = yield getJupiterQuote(
3320
+ inputMint,
3321
+ outputMint,
3322
+ amount,
3323
+ maxAccounts,
3324
+ slippageBps,
3325
+ false,
3326
+ true,
3327
+ true,
3328
+ {
3329
+ jupiterApiUrl: this.jupiterApiUrl,
3330
+ jupiterApiKey: this.jupiterApiKey
3331
+ }
3332
+ );
3333
+ return quote !== null;
3334
+ });
3335
+ }
3336
+ findMinimumJupiterQuoteableAmount(inputMint, outputMint, maxAmount, maxAccounts, slippageBps) {
3337
+ return __async(this, null, function* () {
3338
+ if (maxAmount.isZero()) {
3339
+ return null;
3340
+ }
3341
+ const maxAmountQuoteable = yield this.isJupiterQuoteableAmount(
3342
+ inputMint,
3343
+ outputMint,
3344
+ maxAmount,
3345
+ maxAccounts,
3346
+ slippageBps
3347
+ );
3348
+ if (!maxAmountQuoteable) {
3349
+ return null;
3350
+ }
3351
+ let left = new BN5(1);
3352
+ let right = maxAmount;
3353
+ let best = maxAmount;
3354
+ while (left.lte(right)) {
3355
+ const mid = left.add(right).div(new BN5(2));
3356
+ const isQuoteable = yield this.isJupiterQuoteableAmount(
3357
+ inputMint,
3358
+ outputMint,
3359
+ mid,
3360
+ maxAccounts,
3361
+ slippageBps
3362
+ );
3363
+ if (isQuoteable) {
3364
+ best = mid;
3365
+ right = mid.sub(new BN5(1));
3366
+ } else {
3367
+ left = mid.add(new BN5(1));
3368
+ }
3369
+ }
3370
+ return best;
3371
+ });
3372
+ }
3294
3373
  zapInDlmmForInitializedPosition(params) {
3295
3374
  return __async(this, null, function* () {
3296
3375
  const {
@@ -3841,8 +3920,63 @@ var Zap = class {
3841
3920
  tokenBDecimal
3842
3921
  )
3843
3922
  );
3844
- const swapAmountToB = amountIn.sub(swapAmountToA);
3845
- if (swapAmountToA.isZero()) {
3923
+ let { swapAmountToA: adjustedSwapAmountToA, swapAmountToB } = splitIndirectSwapAmounts(amountIn, swapAmountToA);
3924
+ const quoteableA = yield this.isJupiterQuoteableAmount(
3925
+ inputTokenMint,
3926
+ tokenAMint,
3927
+ adjustedSwapAmountToA,
3928
+ maxAccounts,
3929
+ slippageBps
3930
+ );
3931
+ if (!quoteableA && !adjustedSwapAmountToA.isZero()) {
3932
+ const minQuoteableToA = yield this.findMinimumJupiterQuoteableAmount(
3933
+ inputTokenMint,
3934
+ tokenAMint,
3935
+ amountIn,
3936
+ maxAccounts,
3937
+ slippageBps
3938
+ );
3939
+ if (minQuoteableToA !== null) {
3940
+ adjustedSwapAmountToA = minQuoteableToA;
3941
+ swapAmountToB = amountIn.sub(adjustedSwapAmountToA);
3942
+ } else {
3943
+ adjustedSwapAmountToA = new BN5(0);
3944
+ swapAmountToB = amountIn;
3945
+ }
3946
+ }
3947
+ const quoteableB = yield this.isJupiterQuoteableAmount(
3948
+ inputTokenMint,
3949
+ tokenBMint,
3950
+ swapAmountToB,
3951
+ maxAccounts,
3952
+ slippageBps
3953
+ );
3954
+ if (!quoteableB && !swapAmountToB.isZero()) {
3955
+ const minQuoteableToB = yield this.findMinimumJupiterQuoteableAmount(
3956
+ inputTokenMint,
3957
+ tokenBMint,
3958
+ amountIn,
3959
+ maxAccounts,
3960
+ slippageBps
3961
+ );
3962
+ if (minQuoteableToB !== null) {
3963
+ swapAmountToB = minQuoteableToB;
3964
+ adjustedSwapAmountToA = amountIn.sub(swapAmountToB);
3965
+ } else {
3966
+ swapAmountToB = new BN5(0);
3967
+ adjustedSwapAmountToA = amountIn;
3968
+ }
3969
+ }
3970
+ const { hasSwapToA, hasSwapToB } = splitIndirectSwapAmounts(
3971
+ amountIn,
3972
+ adjustedSwapAmountToA
3973
+ );
3974
+ if (!hasSwapToA && !hasSwapToB) {
3975
+ throw new Error(
3976
+ "Calculated zero swap amount for both token routes, unable to proceed"
3977
+ );
3978
+ }
3979
+ if (!hasSwapToA) {
3846
3980
  const { transaction: swapToBTransaction2, quoteResponse: swapToBQuote2 } = yield buildJupiterSwapTransaction(
3847
3981
  user,
3848
3982
  inputTokenMint,
@@ -3888,12 +4022,12 @@ var Zap = class {
3888
4022
  }
3889
4023
  };
3890
4024
  }
3891
- if (swapAmountToB.isZero()) {
4025
+ if (!hasSwapToB) {
3892
4026
  const { transaction: swapToATransaction2, quoteResponse: swapToAQuote2 } = yield buildJupiterSwapTransaction(
3893
4027
  user,
3894
4028
  inputTokenMint,
3895
4029
  tokenAMint,
3896
- swapAmountToA,
4030
+ adjustedSwapAmountToA,
3897
4031
  maxAccounts,
3898
4032
  slippageBps,
3899
4033
  void 0,
@@ -3920,14 +4054,14 @@ var Zap = class {
3920
4054
  swapToAQuote2.outAmount,
3921
4055
  maxTransferAmountExtendPercentage
3922
4056
  ),
3923
- maxTransferAmountB: new BN5(0),
3924
4057
  swapType: 0 /* swapToA */,
4058
+ maxTransferAmountB: new BN5(0),
3925
4059
  preSqrtPrice: poolState.sqrtPrice,
3926
4060
  preInstructions,
3927
4061
  swapTransactions: [swapToATransaction2],
3928
4062
  cleanUpInstructions,
3929
4063
  swapInEstimate: {
3930
- inAmountA: swapAmountToA,
4064
+ inAmountA: adjustedSwapAmountToA,
3931
4065
  inAmountB: new BN5(0),
3932
4066
  routeA: "jupiter" /* Jupiter */,
3933
4067
  routeB: "dammV2" /* DammV2 */
@@ -3938,7 +4072,7 @@ var Zap = class {
3938
4072
  user,
3939
4073
  inputTokenMint,
3940
4074
  tokenAMint,
3941
- swapAmountToA,
4075
+ adjustedSwapAmountToA,
3942
4076
  maxAccounts,
3943
4077
  slippageBps,
3944
4078
  void 0,
@@ -3988,7 +4122,7 @@ var Zap = class {
3988
4122
  swapTransactions: [swapToATransaction, swapToBTransaction],
3989
4123
  cleanUpInstructions,
3990
4124
  swapInEstimate: {
3991
- inAmountA: swapAmountToA,
4125
+ inAmountA: adjustedSwapAmountToA,
3992
4126
  inAmountB: swapAmountToB,
3993
4127
  routeA: "jupiter" /* Jupiter */,
3994
4128
  routeB: "jupiter" /* Jupiter */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meteora-ag/zap-sdk",
3
- "version": "1.2.0-rc.2",
3
+ "version": "1.2.0-rc.4",
4
4
  "description": "A Typescript SDK for interacting with the Zap program on Meteora.",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -32,17 +32,17 @@
32
32
  "@types/bn.js": "^5.1.0",
33
33
  "@types/bun": "latest",
34
34
  "@types/invariant": "^2.2.37",
35
- "tsup": "^8.4.0",
36
- "tsx": "^4.20.3",
37
35
  "bip39": "^3.1.0",
38
- "ed25519-hd-key": "^1.3.0"
36
+ "ed25519-hd-key": "^1.3.0",
37
+ "tsup": "^8.4.0",
38
+ "tsx": "^4.20.3"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "typescript": "^5"
42
42
  },
43
43
  "dependencies": {
44
44
  "@coral-xyz/anchor": "^0.31.1",
45
- "@meteora-ag/cp-amm-sdk": "^1.2.3",
45
+ "@meteora-ag/cp-amm-sdk": "^1.3.6",
46
46
  "@meteora-ag/dlmm": "^1.9.0",
47
47
  "@solana/spl-token": "^0.4.13",
48
48
  "@solana/web3.js": "^1.98.2",
@@ -52,6 +52,7 @@
52
52
  },
53
53
  "scripts": {
54
54
  "build": "rm -rf dist && tsup src/index.ts --format esm,cjs --dts",
55
- "clean": "rm -rf dist && rm -rf node_modules rm -rf pnpm-lock.yaml"
55
+ "clean": "rm -rf dist && rm -rf node_modules rm -rf pnpm-lock.yaml",
56
+ "test": "node --import tsx --test tests/**/*.test.ts"
56
57
  }
57
58
  }