@crypticdot/defituna-client 3.1.2 → 3.1.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.js CHANGED
@@ -137,6 +137,7 @@ __export(index_exports, {
137
137
  TUNA_ERROR__POSITION_IS_LIQUIDATED: () => TUNA_ERROR__POSITION_IS_LIQUIDATED,
138
138
  TUNA_ERROR__POSITION_IS_UNHEALTHY: () => TUNA_ERROR__POSITION_IS_UNHEALTHY,
139
139
  TUNA_ERROR__POSITION_NOT_EMPTY: () => TUNA_ERROR__POSITION_NOT_EMPTY,
140
+ TUNA_ERROR__POSITION_SIZE_LIMIT_EXCEEDED: () => TUNA_ERROR__POSITION_SIZE_LIMIT_EXCEEDED,
140
141
  TUNA_ERROR__PROTOCOL_FEE_IS_OUT_OF_RANGE: () => TUNA_ERROR__PROTOCOL_FEE_IS_OUT_OF_RANGE,
141
142
  TUNA_ERROR__REBALANCE_CONDITIONS_NOT_MET: () => TUNA_ERROR__REBALANCE_CONDITIONS_NOT_MET,
142
143
  TUNA_ERROR__RECIPIENT_ACCOUNT_IS_NOT_SET: () => TUNA_ERROR__RECIPIENT_ACCOUNT_IS_NOT_SET,
@@ -324,6 +325,7 @@ __export(index_exports, {
324
325
  getCreateVaultInstructionDataCodec: () => getCreateVaultInstructionDataCodec,
325
326
  getCreateVaultInstructionDataDecoder: () => getCreateVaultInstructionDataDecoder,
326
327
  getCreateVaultInstructionDataEncoder: () => getCreateVaultInstructionDataEncoder,
328
+ getDecreaseSpotPositionQuote: () => getDecreaseSpotPositionQuote,
327
329
  getDecreaseTunaLpPositionFusionDiscriminatorBytes: () => getDecreaseTunaLpPositionFusionDiscriminatorBytes,
328
330
  getDecreaseTunaLpPositionFusionInstruction: () => getDecreaseTunaLpPositionFusionInstruction,
329
331
  getDecreaseTunaLpPositionFusionInstructionDataCodec: () => getDecreaseTunaLpPositionFusionInstructionDataCodec,
@@ -948,7 +950,9 @@ function getMarketEncoder() {
948
950
  ["borrowLimitB", (0, import_kit8.getU64Encoder)()],
949
951
  ["maxSwapSlippage", (0, import_kit8.getU32Encoder)()],
950
952
  ["rebalanceProtocolFee", (0, import_kit8.getU32Encoder)()],
951
- ["reserved", (0, import_kit8.fixEncoderSize)((0, import_kit8.getBytesEncoder)(), 207)]
953
+ ["spotPositionSizeLimitA", (0, import_kit8.getU64Encoder)()],
954
+ ["spotPositionSizeLimitB", (0, import_kit8.getU64Encoder)()],
955
+ ["reserved", (0, import_kit8.fixEncoderSize)((0, import_kit8.getBytesEncoder)(), 191)]
952
956
  ]),
953
957
  (value) => ({ ...value, discriminator: MARKET_DISCRIMINATOR })
954
958
  );
@@ -975,7 +979,9 @@ function getMarketDecoder() {
975
979
  ["borrowLimitB", (0, import_kit8.getU64Decoder)()],
976
980
  ["maxSwapSlippage", (0, import_kit8.getU32Decoder)()],
977
981
  ["rebalanceProtocolFee", (0, import_kit8.getU32Decoder)()],
978
- ["reserved", (0, import_kit8.fixDecoderSize)((0, import_kit8.getBytesDecoder)(), 207)]
982
+ ["spotPositionSizeLimitA", (0, import_kit8.getU64Decoder)()],
983
+ ["spotPositionSizeLimitB", (0, import_kit8.getU64Decoder)()],
984
+ ["reserved", (0, import_kit8.fixDecoderSize)((0, import_kit8.getBytesDecoder)(), 191)]
979
985
  ]);
980
986
  }
981
987
  function getMarketCodec() {
@@ -2111,6 +2117,7 @@ var TUNA_ERROR__POSITION_IS_AUTO_REBALANCEABLE = 6057;
2111
2117
  var TUNA_ERROR__INCORRECT_POSITION_DIRECTION = 6058;
2112
2118
  var TUNA_ERROR__RECIPIENT_ACCOUNT_IS_NOT_SET = 6059;
2113
2119
  var TUNA_ERROR__M_A_PRICE_DEVIATION_THRESHOLD_EXCEEDED = 6060;
2120
+ var TUNA_ERROR__POSITION_SIZE_LIMIT_EXCEEDED = 6061;
2114
2121
  var tunaErrorMessages;
2115
2122
  if (process.env.NODE_ENV !== "production") {
2116
2123
  tunaErrorMessages = {
@@ -2146,6 +2153,7 @@ if (process.env.NODE_ENV !== "production") {
2146
2153
  [TUNA_ERROR__POSITION_IS_LIQUIDATED]: `Position is already liquidated`,
2147
2154
  [TUNA_ERROR__POSITION_IS_UNHEALTHY]: `Position is unhealthy`,
2148
2155
  [TUNA_ERROR__POSITION_NOT_EMPTY]: `Position is not empty`,
2156
+ [TUNA_ERROR__POSITION_SIZE_LIMIT_EXCEEDED]: `Position size exceeds the maximum allowed value`,
2149
2157
  [TUNA_ERROR__PROTOCOL_FEE_IS_OUT_OF_RANGE]: `Protocol fee is out of range`,
2150
2158
  [TUNA_ERROR__REBALANCE_CONDITIONS_NOT_MET]: `Rebalance conditions are not met`,
2151
2159
  [TUNA_ERROR__RECIPIENT_ACCOUNT_IS_NOT_SET]: `Optional recipient account is not set`,
@@ -3683,7 +3691,9 @@ function getCreateMarketInstructionDataEncoder() {
3683
3691
  ["borrowLimitA", (0, import_kit26.getU64Encoder)()],
3684
3692
  ["borrowLimitB", (0, import_kit26.getU64Encoder)()],
3685
3693
  ["maxSwapSlippage", (0, import_kit26.getU32Encoder)()],
3686
- ["rebalanceProtocolFee", (0, import_kit26.getU32Encoder)()]
3694
+ ["rebalanceProtocolFee", (0, import_kit26.getU32Encoder)()],
3695
+ ["spotPositionSizeLimitA", (0, import_kit26.getU64Encoder)()],
3696
+ ["spotPositionSizeLimitB", (0, import_kit26.getU64Encoder)()]
3687
3697
  ]),
3688
3698
  (value) => ({ ...value, discriminator: CREATE_MARKET_DISCRIMINATOR })
3689
3699
  );
@@ -3704,7 +3714,9 @@ function getCreateMarketInstructionDataDecoder() {
3704
3714
  ["borrowLimitA", (0, import_kit26.getU64Decoder)()],
3705
3715
  ["borrowLimitB", (0, import_kit26.getU64Decoder)()],
3706
3716
  ["maxSwapSlippage", (0, import_kit26.getU32Decoder)()],
3707
- ["rebalanceProtocolFee", (0, import_kit26.getU32Decoder)()]
3717
+ ["rebalanceProtocolFee", (0, import_kit26.getU32Decoder)()],
3718
+ ["spotPositionSizeLimitA", (0, import_kit26.getU64Decoder)()],
3719
+ ["spotPositionSizeLimitB", (0, import_kit26.getU64Decoder)()]
3708
3720
  ]);
3709
3721
  }
3710
3722
  function getCreateMarketInstructionDataCodec() {
@@ -9470,7 +9482,9 @@ function getUpdateMarketInstructionDataEncoder() {
9470
9482
  ["borrowLimitA", (0, import_kit68.getU64Encoder)()],
9471
9483
  ["borrowLimitB", (0, import_kit68.getU64Encoder)()],
9472
9484
  ["maxSwapSlippage", (0, import_kit68.getU32Encoder)()],
9473
- ["rebalanceProtocolFee", (0, import_kit68.getU32Encoder)()]
9485
+ ["rebalanceProtocolFee", (0, import_kit68.getU32Encoder)()],
9486
+ ["spotPositionSizeLimitA", (0, import_kit68.getU64Encoder)()],
9487
+ ["spotPositionSizeLimitB", (0, import_kit68.getU64Encoder)()]
9474
9488
  ]),
9475
9489
  (value) => ({ ...value, discriminator: UPDATE_MARKET_DISCRIMINATOR })
9476
9490
  );
@@ -9490,7 +9504,9 @@ function getUpdateMarketInstructionDataDecoder() {
9490
9504
  ["borrowLimitA", (0, import_kit68.getU64Decoder)()],
9491
9505
  ["borrowLimitB", (0, import_kit68.getU64Decoder)()],
9492
9506
  ["maxSwapSlippage", (0, import_kit68.getU32Decoder)()],
9493
- ["rebalanceProtocolFee", (0, import_kit68.getU32Decoder)()]
9507
+ ["rebalanceProtocolFee", (0, import_kit68.getU32Decoder)()],
9508
+ ["spotPositionSizeLimitA", (0, import_kit68.getU64Decoder)()],
9509
+ ["spotPositionSizeLimitB", (0, import_kit68.getU64Decoder)()]
9494
9510
  ]);
9495
9511
  }
9496
9512
  function getUpdateMarketInstructionDataCodec() {
@@ -10282,7 +10298,7 @@ function getIncreaseSpotPositionQuote(args) {
10282
10298
  leverage,
10283
10299
  protocolFeeRate,
10284
10300
  protocolFeeRateOnCollateral,
10285
- totalAmount,
10301
+ increaseAmount,
10286
10302
  collateralToken,
10287
10303
  positionToken
10288
10304
  } = args;
@@ -10295,52 +10311,48 @@ function getIncreaseSpotPositionQuote(args) {
10295
10311
  if (protocolFeeRateOnCollateral < 0) {
10296
10312
  throw new Error("protocolFeeRate must be greater or equal than zero");
10297
10313
  }
10298
- if (totalAmount < 0) {
10299
- throw new Error("totalAmount must be greater or equal than zero");
10300
- }
10301
- if (totalAmount == 0n) {
10302
- return {
10303
- collateral: 0n,
10304
- borrow: 0n,
10305
- protocolFeeA: 0n,
10306
- protocolFeeB: 0n,
10307
- priceImpact: 0
10308
- };
10314
+ if (increaseAmount <= 0) {
10315
+ throw new Error("increaseAmount must be greater than zero");
10309
10316
  }
10310
10317
  let borrow;
10311
10318
  let collateral;
10319
+ let estimatedAmount;
10312
10320
  let nextSqrtPrice = fusionPool.sqrtPrice;
10313
10321
  if (positionToken != collateralToken) {
10314
10322
  const price = (0, import_fusionamm_core4.sqrtPriceToPrice)(fusionPool.sqrtPrice, 1, 1);
10315
- const totalAmountInOppositeToken = BigInt(
10316
- Math.floor(positionToken == 0 /* A */ ? Number(totalAmount) / price : Number(totalAmount) * price)
10323
+ collateral = leverage > 1 ? BigInt(Math.floor(Number(increaseAmount) / leverage)) : increaseAmount;
10324
+ borrow = increaseAmount - collateral;
10325
+ estimatedAmount = BigInt(
10326
+ Math.floor(collateralToken == 0 /* A */ ? Number(increaseAmount) * price : Number(increaseAmount) / price)
10317
10327
  );
10318
- const swapQuote = (0, import_fusionamm_core4.swapQuoteByOutputToken)(
10319
- totalAmountInOppositeToken,
10320
- positionToken == 0 /* A */,
10328
+ nextSqrtPrice = (0, import_fusionamm_core4.swapQuoteByInputToken)(
10329
+ increaseAmount,
10330
+ collateralToken == 0 /* A */,
10321
10331
  0,
10322
10332
  fusionPool,
10323
10333
  tickArrays
10324
- );
10325
- nextSqrtPrice = swapQuote.nextSqrtPrice;
10326
- const inputAmount = swapQuote.tokenEstIn;
10327
- collateral = leverage > 1 ? BigInt(Math.floor(Number(inputAmount) / leverage)) : inputAmount;
10328
- borrow = inputAmount - collateral;
10334
+ ).nextSqrtPrice;
10329
10335
  } else {
10330
10336
  if (leverage > 1) {
10331
- collateral = BigInt(Math.floor(Number(totalAmount) / leverage));
10332
- const swapQuote = (0, import_fusionamm_core4.swapQuoteByOutputToken)(
10333
- totalAmount - collateral,
10337
+ const price = (0, import_fusionamm_core4.sqrtPriceToPrice)(fusionPool.sqrtPrice, 1, 1);
10338
+ collateral = BigInt(Math.floor(Number(increaseAmount) / leverage));
10339
+ borrow = BigInt(
10340
+ Math.floor(
10341
+ collateralToken == 0 /* A */ ? Number(increaseAmount - collateral) * price : Number(increaseAmount - collateral) / price
10342
+ )
10343
+ );
10344
+ estimatedAmount = increaseAmount;
10345
+ nextSqrtPrice = (0, import_fusionamm_core4.swapQuoteByOutputToken)(
10346
+ increaseAmount - collateral,
10334
10347
  positionToken == 0 /* A */,
10335
10348
  0,
10336
10349
  fusionPool,
10337
10350
  tickArrays
10338
- );
10339
- nextSqrtPrice = swapQuote.nextSqrtPrice;
10340
- borrow = swapQuote.tokenEstIn;
10351
+ ).nextSqrtPrice;
10341
10352
  } else {
10342
- collateral = totalAmount;
10353
+ collateral = increaseAmount;
10343
10354
  borrow = 0n;
10355
+ estimatedAmount = increaseAmount;
10344
10356
  }
10345
10357
  }
10346
10358
  const collateralExcludingFee = collateral;
@@ -10355,6 +10367,124 @@ function getIncreaseSpotPositionQuote(args) {
10355
10367
  return {
10356
10368
  collateral,
10357
10369
  borrow,
10370
+ estimatedAmount,
10371
+ protocolFeeA,
10372
+ protocolFeeB,
10373
+ priceImpact
10374
+ };
10375
+ }
10376
+ function getDecreaseSpotPositionQuote(args) {
10377
+ const {
10378
+ fusionPool,
10379
+ tickArrays,
10380
+ leverage,
10381
+ protocolFeeRate,
10382
+ protocolFeeRateOnCollateral,
10383
+ decreaseAmount,
10384
+ collateralToken,
10385
+ positionToken,
10386
+ positionAmount,
10387
+ positionDebt,
10388
+ reduceOnly
10389
+ } = args;
10390
+ if (leverage < 1) {
10391
+ throw new Error("leverage must be greater or equal than 1.0");
10392
+ }
10393
+ if (protocolFeeRate < 0) {
10394
+ throw new Error("protocolFeeRate must be greater or equal than zero");
10395
+ }
10396
+ if (protocolFeeRateOnCollateral < 0) {
10397
+ throw new Error("protocolFeeRate must be greater or equal than zero");
10398
+ }
10399
+ if (decreaseAmount <= 0) {
10400
+ throw new Error("decreaseAmount must be greater than zero");
10401
+ }
10402
+ let collateral = 0n;
10403
+ let borrow = 0n;
10404
+ let estimatedAmount = 0n;
10405
+ let nextSqrtPrice = fusionPool.sqrtPrice;
10406
+ let newPositionToken = positionToken;
10407
+ let decreasePercent;
10408
+ const price = (0, import_fusionamm_core4.sqrtPriceToPrice)(fusionPool.sqrtPrice, 1, 1);
10409
+ if (decreaseAmount <= positionAmount || reduceOnly) {
10410
+ let decreaseAmountInPositionToken;
10411
+ if (collateralToken == positionToken) {
10412
+ decreaseAmountInPositionToken = decreaseAmount;
10413
+ } else {
10414
+ decreaseAmountInPositionToken = BigInt(
10415
+ Math.floor(collateralToken == 0 /* A */ ? Number(decreaseAmount) * price : Number(decreaseAmount) / price)
10416
+ );
10417
+ }
10418
+ decreasePercent = Math.min(
10419
+ Math.floor(Number(decreaseAmountInPositionToken) * HUNDRED_PERCENT / Number(positionAmount)),
10420
+ HUNDRED_PERCENT
10421
+ );
10422
+ const swapOut = BigInt(Math.floor(Number(positionDebt) * decreasePercent / HUNDRED_PERCENT));
10423
+ const swapQuote = (0, import_fusionamm_core4.swapQuoteByOutputToken)(swapOut, positionToken == 1 /* B */, 0, fusionPool, tickArrays);
10424
+ nextSqrtPrice = swapQuote.nextSqrtPrice;
10425
+ estimatedAmount = decreaseAmountInPositionToken <= positionAmount ? positionAmount - decreaseAmountInPositionToken : 0n;
10426
+ } else {
10427
+ decreasePercent = HUNDRED_PERCENT;
10428
+ const positionTokenIsA = positionToken == 0 /* A */;
10429
+ newPositionToken = positionToken == 0 /* A */ ? 1 /* B */ : 0 /* A */;
10430
+ const increaseAmount = decreaseAmount - positionAmount;
10431
+ if (positionToken == collateralToken) {
10432
+ estimatedAmount = BigInt(
10433
+ Math.floor(positionTokenIsA ? Number(increaseAmount) * price : Number(increaseAmount) / price)
10434
+ );
10435
+ collateral = leverage > 1 ? BigInt(Math.floor(Number(increaseAmount) / leverage)) : estimatedAmount;
10436
+ borrow = increaseAmount - collateral;
10437
+ const borrowInNewPositionToken = BigInt(
10438
+ Math.floor(positionTokenIsA ? Number(borrow) * price : Number(borrow) / price)
10439
+ );
10440
+ nextSqrtPrice = (0, import_fusionamm_core4.swapQuoteByInputToken)(
10441
+ positionDebt + borrowInNewPositionToken,
10442
+ !positionTokenIsA,
10443
+ 0,
10444
+ fusionPool,
10445
+ tickArrays
10446
+ ).nextSqrtPrice;
10447
+ } else {
10448
+ if (leverage > 1) {
10449
+ const collateralInPositionToken = BigInt(Math.floor(Number(increaseAmount) / leverage));
10450
+ borrow = increaseAmount - collateralInPositionToken;
10451
+ collateral = BigInt(
10452
+ Math.floor(
10453
+ positionToken == 0 /* A */ ? Number(collateralInPositionToken) * price : Number(collateralInPositionToken) / price
10454
+ )
10455
+ );
10456
+ const borrowInNewPositionToken = BigInt(
10457
+ Math.floor(newPositionToken == 1 /* B */ ? Number(borrow) * price : Number(borrow) / price)
10458
+ );
10459
+ estimatedAmount = collateral + borrowInNewPositionToken;
10460
+ nextSqrtPrice = (0, import_fusionamm_core4.swapQuoteByInputToken)(
10461
+ positionAmount + borrow,
10462
+ positionTokenIsA,
10463
+ 0,
10464
+ fusionPool,
10465
+ tickArrays
10466
+ ).nextSqrtPrice;
10467
+ } else {
10468
+ collateral = increaseAmount;
10469
+ borrow = 0n;
10470
+ }
10471
+ }
10472
+ }
10473
+ const collateralExcludingFee = collateral;
10474
+ const borrowExcludingFee = borrow;
10475
+ collateral = reverseApplyTunaProtocolFee(collateral, protocolFeeRateOnCollateral);
10476
+ borrow = reverseApplyTunaProtocolFee(borrow, protocolFeeRate);
10477
+ const protocolFeeA = (collateralToken == 0 /* A */ ? collateral - collateralExcludingFee : 0n) + (positionToken == 1 /* B */ ? borrow - borrowExcludingFee : 0n);
10478
+ const protocolFeeB = (collateralToken == 1 /* B */ ? collateral - collateralExcludingFee : 0n) + (positionToken == 0 /* A */ ? borrow - borrowExcludingFee : 0n);
10479
+ const newPrice = (0, import_fusionamm_core4.sqrtPriceToPrice)(nextSqrtPrice, 1, 1);
10480
+ const priceImpact = Math.abs(newPrice / price - 1) * 100;
10481
+ return {
10482
+ decreasePercent,
10483
+ collateralToken,
10484
+ positionToken: newPositionToken,
10485
+ collateral,
10486
+ estimatedAmount,
10487
+ borrow,
10358
10488
  protocolFeeA,
10359
10489
  protocolFeeB,
10360
10490
  priceImpact
@@ -15403,6 +15533,7 @@ async function rebalanceTunaLpPositionFusionInstruction(authority, tunaPosition,
15403
15533
  TUNA_ERROR__POSITION_IS_LIQUIDATED,
15404
15534
  TUNA_ERROR__POSITION_IS_UNHEALTHY,
15405
15535
  TUNA_ERROR__POSITION_NOT_EMPTY,
15536
+ TUNA_ERROR__POSITION_SIZE_LIMIT_EXCEEDED,
15406
15537
  TUNA_ERROR__PROTOCOL_FEE_IS_OUT_OF_RANGE,
15407
15538
  TUNA_ERROR__REBALANCE_CONDITIONS_NOT_MET,
15408
15539
  TUNA_ERROR__RECIPIENT_ACCOUNT_IS_NOT_SET,
@@ -15590,6 +15721,7 @@ async function rebalanceTunaLpPositionFusionInstruction(authority, tunaPosition,
15590
15721
  getCreateVaultInstructionDataCodec,
15591
15722
  getCreateVaultInstructionDataDecoder,
15592
15723
  getCreateVaultInstructionDataEncoder,
15724
+ getDecreaseSpotPositionQuote,
15593
15725
  getDecreaseTunaLpPositionFusionDiscriminatorBytes,
15594
15726
  getDecreaseTunaLpPositionFusionInstruction,
15595
15727
  getDecreaseTunaLpPositionFusionInstructionDataCodec,
package/dist/index.mjs CHANGED
@@ -310,7 +310,9 @@ function getMarketEncoder() {
310
310
  ["borrowLimitB", getU64Encoder2()],
311
311
  ["maxSwapSlippage", getU32Encoder()],
312
312
  ["rebalanceProtocolFee", getU32Encoder()],
313
- ["reserved", fixEncoderSize2(getBytesEncoder2(), 207)]
313
+ ["spotPositionSizeLimitA", getU64Encoder2()],
314
+ ["spotPositionSizeLimitB", getU64Encoder2()],
315
+ ["reserved", fixEncoderSize2(getBytesEncoder2(), 191)]
314
316
  ]),
315
317
  (value) => ({ ...value, discriminator: MARKET_DISCRIMINATOR })
316
318
  );
@@ -337,7 +339,9 @@ function getMarketDecoder() {
337
339
  ["borrowLimitB", getU64Decoder2()],
338
340
  ["maxSwapSlippage", getU32Decoder()],
339
341
  ["rebalanceProtocolFee", getU32Decoder()],
340
- ["reserved", fixDecoderSize2(getBytesDecoder2(), 207)]
342
+ ["spotPositionSizeLimitA", getU64Decoder2()],
343
+ ["spotPositionSizeLimitB", getU64Decoder2()],
344
+ ["reserved", fixDecoderSize2(getBytesDecoder2(), 191)]
341
345
  ]);
342
346
  }
343
347
  function getMarketCodec() {
@@ -1575,6 +1579,7 @@ var TUNA_ERROR__POSITION_IS_AUTO_REBALANCEABLE = 6057;
1575
1579
  var TUNA_ERROR__INCORRECT_POSITION_DIRECTION = 6058;
1576
1580
  var TUNA_ERROR__RECIPIENT_ACCOUNT_IS_NOT_SET = 6059;
1577
1581
  var TUNA_ERROR__M_A_PRICE_DEVIATION_THRESHOLD_EXCEEDED = 6060;
1582
+ var TUNA_ERROR__POSITION_SIZE_LIMIT_EXCEEDED = 6061;
1578
1583
  var tunaErrorMessages;
1579
1584
  if (process.env.NODE_ENV !== "production") {
1580
1585
  tunaErrorMessages = {
@@ -1610,6 +1615,7 @@ if (process.env.NODE_ENV !== "production") {
1610
1615
  [TUNA_ERROR__POSITION_IS_LIQUIDATED]: `Position is already liquidated`,
1611
1616
  [TUNA_ERROR__POSITION_IS_UNHEALTHY]: `Position is unhealthy`,
1612
1617
  [TUNA_ERROR__POSITION_NOT_EMPTY]: `Position is not empty`,
1618
+ [TUNA_ERROR__POSITION_SIZE_LIMIT_EXCEEDED]: `Position size exceeds the maximum allowed value`,
1613
1619
  [TUNA_ERROR__PROTOCOL_FEE_IS_OUT_OF_RANGE]: `Protocol fee is out of range`,
1614
1620
  [TUNA_ERROR__REBALANCE_CONDITIONS_NOT_MET]: `Rebalance conditions are not met`,
1615
1621
  [TUNA_ERROR__RECIPIENT_ACCOUNT_IS_NOT_SET]: `Optional recipient account is not set`,
@@ -3271,7 +3277,9 @@ function getCreateMarketInstructionDataEncoder() {
3271
3277
  ["borrowLimitA", getU64Encoder6()],
3272
3278
  ["borrowLimitB", getU64Encoder6()],
3273
3279
  ["maxSwapSlippage", getU32Encoder7()],
3274
- ["rebalanceProtocolFee", getU32Encoder7()]
3280
+ ["rebalanceProtocolFee", getU32Encoder7()],
3281
+ ["spotPositionSizeLimitA", getU64Encoder6()],
3282
+ ["spotPositionSizeLimitB", getU64Encoder6()]
3275
3283
  ]),
3276
3284
  (value) => ({ ...value, discriminator: CREATE_MARKET_DISCRIMINATOR })
3277
3285
  );
@@ -3292,7 +3300,9 @@ function getCreateMarketInstructionDataDecoder() {
3292
3300
  ["borrowLimitA", getU64Decoder6()],
3293
3301
  ["borrowLimitB", getU64Decoder6()],
3294
3302
  ["maxSwapSlippage", getU32Decoder7()],
3295
- ["rebalanceProtocolFee", getU32Decoder7()]
3303
+ ["rebalanceProtocolFee", getU32Decoder7()],
3304
+ ["spotPositionSizeLimitA", getU64Decoder6()],
3305
+ ["spotPositionSizeLimitB", getU64Decoder6()]
3296
3306
  ]);
3297
3307
  }
3298
3308
  function getCreateMarketInstructionDataCodec() {
@@ -9576,7 +9586,9 @@ function getUpdateMarketInstructionDataEncoder() {
9576
9586
  ["borrowLimitA", getU64Encoder21()],
9577
9587
  ["borrowLimitB", getU64Encoder21()],
9578
9588
  ["maxSwapSlippage", getU32Encoder33()],
9579
- ["rebalanceProtocolFee", getU32Encoder33()]
9589
+ ["rebalanceProtocolFee", getU32Encoder33()],
9590
+ ["spotPositionSizeLimitA", getU64Encoder21()],
9591
+ ["spotPositionSizeLimitB", getU64Encoder21()]
9580
9592
  ]),
9581
9593
  (value) => ({ ...value, discriminator: UPDATE_MARKET_DISCRIMINATOR })
9582
9594
  );
@@ -9596,7 +9608,9 @@ function getUpdateMarketInstructionDataDecoder() {
9596
9608
  ["borrowLimitA", getU64Decoder21()],
9597
9609
  ["borrowLimitB", getU64Decoder21()],
9598
9610
  ["maxSwapSlippage", getU32Decoder33()],
9599
- ["rebalanceProtocolFee", getU32Decoder33()]
9611
+ ["rebalanceProtocolFee", getU32Decoder33()],
9612
+ ["spotPositionSizeLimitA", getU64Decoder21()],
9613
+ ["spotPositionSizeLimitB", getU64Decoder21()]
9600
9614
  ]);
9601
9615
  }
9602
9616
  function getUpdateMarketInstructionDataCodec() {
@@ -10444,6 +10458,7 @@ function calculateProtocolFee(collateralAmount, borrowAmount, protocolFeeRateOnC
10444
10458
  // src/utils/spotPositionMath.ts
10445
10459
  import {
10446
10460
  sqrtPriceToPrice,
10461
+ swapQuoteByInputToken,
10447
10462
  swapQuoteByOutputToken
10448
10463
  } from "@crypticdot/fusionamm-core";
10449
10464
  function getIncreaseSpotPositionQuote(args) {
@@ -10453,7 +10468,7 @@ function getIncreaseSpotPositionQuote(args) {
10453
10468
  leverage,
10454
10469
  protocolFeeRate,
10455
10470
  protocolFeeRateOnCollateral,
10456
- totalAmount,
10471
+ increaseAmount,
10457
10472
  collateralToken,
10458
10473
  positionToken
10459
10474
  } = args;
@@ -10466,52 +10481,48 @@ function getIncreaseSpotPositionQuote(args) {
10466
10481
  if (protocolFeeRateOnCollateral < 0) {
10467
10482
  throw new Error("protocolFeeRate must be greater or equal than zero");
10468
10483
  }
10469
- if (totalAmount < 0) {
10470
- throw new Error("totalAmount must be greater or equal than zero");
10471
- }
10472
- if (totalAmount == 0n) {
10473
- return {
10474
- collateral: 0n,
10475
- borrow: 0n,
10476
- protocolFeeA: 0n,
10477
- protocolFeeB: 0n,
10478
- priceImpact: 0
10479
- };
10484
+ if (increaseAmount <= 0) {
10485
+ throw new Error("increaseAmount must be greater than zero");
10480
10486
  }
10481
10487
  let borrow;
10482
10488
  let collateral;
10489
+ let estimatedAmount;
10483
10490
  let nextSqrtPrice = fusionPool.sqrtPrice;
10484
10491
  if (positionToken != collateralToken) {
10485
10492
  const price = sqrtPriceToPrice(fusionPool.sqrtPrice, 1, 1);
10486
- const totalAmountInOppositeToken = BigInt(
10487
- Math.floor(positionToken == 0 /* A */ ? Number(totalAmount) / price : Number(totalAmount) * price)
10493
+ collateral = leverage > 1 ? BigInt(Math.floor(Number(increaseAmount) / leverage)) : increaseAmount;
10494
+ borrow = increaseAmount - collateral;
10495
+ estimatedAmount = BigInt(
10496
+ Math.floor(collateralToken == 0 /* A */ ? Number(increaseAmount) * price : Number(increaseAmount) / price)
10488
10497
  );
10489
- const swapQuote = swapQuoteByOutputToken(
10490
- totalAmountInOppositeToken,
10491
- positionToken == 0 /* A */,
10498
+ nextSqrtPrice = swapQuoteByInputToken(
10499
+ increaseAmount,
10500
+ collateralToken == 0 /* A */,
10492
10501
  0,
10493
10502
  fusionPool,
10494
10503
  tickArrays
10495
- );
10496
- nextSqrtPrice = swapQuote.nextSqrtPrice;
10497
- const inputAmount = swapQuote.tokenEstIn;
10498
- collateral = leverage > 1 ? BigInt(Math.floor(Number(inputAmount) / leverage)) : inputAmount;
10499
- borrow = inputAmount - collateral;
10504
+ ).nextSqrtPrice;
10500
10505
  } else {
10501
10506
  if (leverage > 1) {
10502
- collateral = BigInt(Math.floor(Number(totalAmount) / leverage));
10503
- const swapQuote = swapQuoteByOutputToken(
10504
- totalAmount - collateral,
10507
+ const price = sqrtPriceToPrice(fusionPool.sqrtPrice, 1, 1);
10508
+ collateral = BigInt(Math.floor(Number(increaseAmount) / leverage));
10509
+ borrow = BigInt(
10510
+ Math.floor(
10511
+ collateralToken == 0 /* A */ ? Number(increaseAmount - collateral) * price : Number(increaseAmount - collateral) / price
10512
+ )
10513
+ );
10514
+ estimatedAmount = increaseAmount;
10515
+ nextSqrtPrice = swapQuoteByOutputToken(
10516
+ increaseAmount - collateral,
10505
10517
  positionToken == 0 /* A */,
10506
10518
  0,
10507
10519
  fusionPool,
10508
10520
  tickArrays
10509
- );
10510
- nextSqrtPrice = swapQuote.nextSqrtPrice;
10511
- borrow = swapQuote.tokenEstIn;
10521
+ ).nextSqrtPrice;
10512
10522
  } else {
10513
- collateral = totalAmount;
10523
+ collateral = increaseAmount;
10514
10524
  borrow = 0n;
10525
+ estimatedAmount = increaseAmount;
10515
10526
  }
10516
10527
  }
10517
10528
  const collateralExcludingFee = collateral;
@@ -10526,6 +10537,124 @@ function getIncreaseSpotPositionQuote(args) {
10526
10537
  return {
10527
10538
  collateral,
10528
10539
  borrow,
10540
+ estimatedAmount,
10541
+ protocolFeeA,
10542
+ protocolFeeB,
10543
+ priceImpact
10544
+ };
10545
+ }
10546
+ function getDecreaseSpotPositionQuote(args) {
10547
+ const {
10548
+ fusionPool,
10549
+ tickArrays,
10550
+ leverage,
10551
+ protocolFeeRate,
10552
+ protocolFeeRateOnCollateral,
10553
+ decreaseAmount,
10554
+ collateralToken,
10555
+ positionToken,
10556
+ positionAmount,
10557
+ positionDebt,
10558
+ reduceOnly
10559
+ } = args;
10560
+ if (leverage < 1) {
10561
+ throw new Error("leverage must be greater or equal than 1.0");
10562
+ }
10563
+ if (protocolFeeRate < 0) {
10564
+ throw new Error("protocolFeeRate must be greater or equal than zero");
10565
+ }
10566
+ if (protocolFeeRateOnCollateral < 0) {
10567
+ throw new Error("protocolFeeRate must be greater or equal than zero");
10568
+ }
10569
+ if (decreaseAmount <= 0) {
10570
+ throw new Error("decreaseAmount must be greater than zero");
10571
+ }
10572
+ let collateral = 0n;
10573
+ let borrow = 0n;
10574
+ let estimatedAmount = 0n;
10575
+ let nextSqrtPrice = fusionPool.sqrtPrice;
10576
+ let newPositionToken = positionToken;
10577
+ let decreasePercent;
10578
+ const price = sqrtPriceToPrice(fusionPool.sqrtPrice, 1, 1);
10579
+ if (decreaseAmount <= positionAmount || reduceOnly) {
10580
+ let decreaseAmountInPositionToken;
10581
+ if (collateralToken == positionToken) {
10582
+ decreaseAmountInPositionToken = decreaseAmount;
10583
+ } else {
10584
+ decreaseAmountInPositionToken = BigInt(
10585
+ Math.floor(collateralToken == 0 /* A */ ? Number(decreaseAmount) * price : Number(decreaseAmount) / price)
10586
+ );
10587
+ }
10588
+ decreasePercent = Math.min(
10589
+ Math.floor(Number(decreaseAmountInPositionToken) * HUNDRED_PERCENT / Number(positionAmount)),
10590
+ HUNDRED_PERCENT
10591
+ );
10592
+ const swapOut = BigInt(Math.floor(Number(positionDebt) * decreasePercent / HUNDRED_PERCENT));
10593
+ const swapQuote = swapQuoteByOutputToken(swapOut, positionToken == 1 /* B */, 0, fusionPool, tickArrays);
10594
+ nextSqrtPrice = swapQuote.nextSqrtPrice;
10595
+ estimatedAmount = decreaseAmountInPositionToken <= positionAmount ? positionAmount - decreaseAmountInPositionToken : 0n;
10596
+ } else {
10597
+ decreasePercent = HUNDRED_PERCENT;
10598
+ const positionTokenIsA = positionToken == 0 /* A */;
10599
+ newPositionToken = positionToken == 0 /* A */ ? 1 /* B */ : 0 /* A */;
10600
+ const increaseAmount = decreaseAmount - positionAmount;
10601
+ if (positionToken == collateralToken) {
10602
+ estimatedAmount = BigInt(
10603
+ Math.floor(positionTokenIsA ? Number(increaseAmount) * price : Number(increaseAmount) / price)
10604
+ );
10605
+ collateral = leverage > 1 ? BigInt(Math.floor(Number(increaseAmount) / leverage)) : estimatedAmount;
10606
+ borrow = increaseAmount - collateral;
10607
+ const borrowInNewPositionToken = BigInt(
10608
+ Math.floor(positionTokenIsA ? Number(borrow) * price : Number(borrow) / price)
10609
+ );
10610
+ nextSqrtPrice = swapQuoteByInputToken(
10611
+ positionDebt + borrowInNewPositionToken,
10612
+ !positionTokenIsA,
10613
+ 0,
10614
+ fusionPool,
10615
+ tickArrays
10616
+ ).nextSqrtPrice;
10617
+ } else {
10618
+ if (leverage > 1) {
10619
+ const collateralInPositionToken = BigInt(Math.floor(Number(increaseAmount) / leverage));
10620
+ borrow = increaseAmount - collateralInPositionToken;
10621
+ collateral = BigInt(
10622
+ Math.floor(
10623
+ positionToken == 0 /* A */ ? Number(collateralInPositionToken) * price : Number(collateralInPositionToken) / price
10624
+ )
10625
+ );
10626
+ const borrowInNewPositionToken = BigInt(
10627
+ Math.floor(newPositionToken == 1 /* B */ ? Number(borrow) * price : Number(borrow) / price)
10628
+ );
10629
+ estimatedAmount = collateral + borrowInNewPositionToken;
10630
+ nextSqrtPrice = swapQuoteByInputToken(
10631
+ positionAmount + borrow,
10632
+ positionTokenIsA,
10633
+ 0,
10634
+ fusionPool,
10635
+ tickArrays
10636
+ ).nextSqrtPrice;
10637
+ } else {
10638
+ collateral = increaseAmount;
10639
+ borrow = 0n;
10640
+ }
10641
+ }
10642
+ }
10643
+ const collateralExcludingFee = collateral;
10644
+ const borrowExcludingFee = borrow;
10645
+ collateral = reverseApplyTunaProtocolFee(collateral, protocolFeeRateOnCollateral);
10646
+ borrow = reverseApplyTunaProtocolFee(borrow, protocolFeeRate);
10647
+ const protocolFeeA = (collateralToken == 0 /* A */ ? collateral - collateralExcludingFee : 0n) + (positionToken == 1 /* B */ ? borrow - borrowExcludingFee : 0n);
10648
+ const protocolFeeB = (collateralToken == 1 /* B */ ? collateral - collateralExcludingFee : 0n) + (positionToken == 0 /* A */ ? borrow - borrowExcludingFee : 0n);
10649
+ const newPrice = sqrtPriceToPrice(nextSqrtPrice, 1, 1);
10650
+ const priceImpact = Math.abs(newPrice / price - 1) * 100;
10651
+ return {
10652
+ decreasePercent,
10653
+ collateralToken,
10654
+ positionToken: newPositionToken,
10655
+ collateral,
10656
+ estimatedAmount,
10657
+ borrow,
10529
10658
  protocolFeeA,
10530
10659
  protocolFeeB,
10531
10660
  priceImpact
@@ -15801,6 +15930,7 @@ export {
15801
15930
  TUNA_ERROR__POSITION_IS_LIQUIDATED,
15802
15931
  TUNA_ERROR__POSITION_IS_UNHEALTHY,
15803
15932
  TUNA_ERROR__POSITION_NOT_EMPTY,
15933
+ TUNA_ERROR__POSITION_SIZE_LIMIT_EXCEEDED,
15804
15934
  TUNA_ERROR__PROTOCOL_FEE_IS_OUT_OF_RANGE,
15805
15935
  TUNA_ERROR__REBALANCE_CONDITIONS_NOT_MET,
15806
15936
  TUNA_ERROR__RECIPIENT_ACCOUNT_IS_NOT_SET,
@@ -15988,6 +16118,7 @@ export {
15988
16118
  getCreateVaultInstructionDataCodec,
15989
16119
  getCreateVaultInstructionDataDecoder,
15990
16120
  getCreateVaultInstructionDataEncoder,
16121
+ getDecreaseSpotPositionQuote,
15991
16122
  getDecreaseTunaLpPositionFusionDiscriminatorBytes,
15992
16123
  getDecreaseTunaLpPositionFusionInstruction,
15993
16124
  getDecreaseTunaLpPositionFusionInstructionDataCodec,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@crypticdot/defituna-client",
3
3
  "description": "Typescript client to interact with DefiTuna's on-chain program.",
4
- "version": "3.1.2",
4
+ "version": "3.1.4",
5
5
  "private": false,
6
6
  "license": "SEE LICENSE IN LICENSE",
7
7
  "main": "./dist/index.js",
@@ -19,9 +19,9 @@
19
19
  "@orca-so/whirlpools-core": "^2.0.0",
20
20
  "@orca-so/whirlpools-client": "^3.0.0",
21
21
  "@orca-so/whirlpools": "^3.0.0",
22
- "@crypticdot/fusionamm-core": "^1.0.62",
23
- "@crypticdot/fusionamm-client": "^1.0.62",
24
- "@crypticdot/fusionamm-sdk": "^1.0.62",
22
+ "@crypticdot/fusionamm-core": "^1.0.63",
23
+ "@crypticdot/fusionamm-client": "^1.0.63",
24
+ "@crypticdot/fusionamm-sdk": "^1.0.63",
25
25
  "@solana/kit": "^2.1.0",
26
26
  "@solana/sysvars": "^2.1.0",
27
27
  "@solana-program/compute-budget": "^0.7.0",
@@ -51,7 +51,7 @@
51
51
  "rimraf": "^6.0.1",
52
52
  "vitest": "^3.1.1",
53
53
  "solana-bankrun": "^0.4.0",
54
- "@crypticdot/defituna-program": "3.1.2"
54
+ "@crypticdot/defituna-program": "3.1.3"
55
55
  },
56
56
  "scripts": {
57
57
  "build": "node ./codama.mjs && tsup src/index.ts --format cjs,esm --dts",