@crypticdot/defituna-client 3.1.1 → 3.1.3

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,
@@ -225,6 +226,7 @@ __export(index_exports, {
225
226
  decreaseTunaSpotPositionOrcaInstructions: () => decreaseTunaSpotPositionOrcaInstructions,
226
227
  depositInstruction: () => depositInstruction,
227
228
  depositInstructions: () => depositInstructions,
229
+ extendAddressLookupTableForMarketInstructions: () => extendAddressLookupTableForMarketInstructions,
228
230
  fetchAllLendingPosition: () => fetchAllLendingPosition,
229
231
  fetchAllLendingPositionWithFilter: () => fetchAllLendingPositionWithFilter,
230
232
  fetchAllMarket: () => fetchAllMarket,
@@ -349,6 +351,7 @@ __export(index_exports, {
349
351
  getDepositInstructionDataDecoder: () => getDepositInstructionDataDecoder,
350
352
  getDepositInstructionDataEncoder: () => getDepositInstructionDataEncoder,
351
353
  getIncreaseLpPositionQuote: () => getIncreaseLpPositionQuote,
354
+ getIncreaseSpotPositionQuote: () => getIncreaseSpotPositionQuote,
352
355
  getIncreaseTunaLpPositionFusionDiscriminatorBytes: () => getIncreaseTunaLpPositionFusionDiscriminatorBytes,
353
356
  getIncreaseTunaLpPositionFusionInstruction: () => getIncreaseTunaLpPositionFusionInstruction,
354
357
  getIncreaseTunaLpPositionFusionInstructionDataCodec: () => getIncreaseTunaLpPositionFusionInstructionDataCodec,
@@ -946,7 +949,9 @@ function getMarketEncoder() {
946
949
  ["borrowLimitB", (0, import_kit8.getU64Encoder)()],
947
950
  ["maxSwapSlippage", (0, import_kit8.getU32Encoder)()],
948
951
  ["rebalanceProtocolFee", (0, import_kit8.getU32Encoder)()],
949
- ["reserved", (0, import_kit8.fixEncoderSize)((0, import_kit8.getBytesEncoder)(), 207)]
952
+ ["spotPositionSizeLimitA", (0, import_kit8.getU64Encoder)()],
953
+ ["spotPositionSizeLimitB", (0, import_kit8.getU64Encoder)()],
954
+ ["reserved", (0, import_kit8.fixEncoderSize)((0, import_kit8.getBytesEncoder)(), 191)]
950
955
  ]),
951
956
  (value) => ({ ...value, discriminator: MARKET_DISCRIMINATOR })
952
957
  );
@@ -973,7 +978,9 @@ function getMarketDecoder() {
973
978
  ["borrowLimitB", (0, import_kit8.getU64Decoder)()],
974
979
  ["maxSwapSlippage", (0, import_kit8.getU32Decoder)()],
975
980
  ["rebalanceProtocolFee", (0, import_kit8.getU32Decoder)()],
976
- ["reserved", (0, import_kit8.fixDecoderSize)((0, import_kit8.getBytesDecoder)(), 207)]
981
+ ["spotPositionSizeLimitA", (0, import_kit8.getU64Decoder)()],
982
+ ["spotPositionSizeLimitB", (0, import_kit8.getU64Decoder)()],
983
+ ["reserved", (0, import_kit8.fixDecoderSize)((0, import_kit8.getBytesDecoder)(), 191)]
977
984
  ]);
978
985
  }
979
986
  function getMarketCodec() {
@@ -2109,6 +2116,7 @@ var TUNA_ERROR__POSITION_IS_AUTO_REBALANCEABLE = 6057;
2109
2116
  var TUNA_ERROR__INCORRECT_POSITION_DIRECTION = 6058;
2110
2117
  var TUNA_ERROR__RECIPIENT_ACCOUNT_IS_NOT_SET = 6059;
2111
2118
  var TUNA_ERROR__M_A_PRICE_DEVIATION_THRESHOLD_EXCEEDED = 6060;
2119
+ var TUNA_ERROR__POSITION_SIZE_LIMIT_EXCEEDED = 6061;
2112
2120
  var tunaErrorMessages;
2113
2121
  if (process.env.NODE_ENV !== "production") {
2114
2122
  tunaErrorMessages = {
@@ -2144,6 +2152,7 @@ if (process.env.NODE_ENV !== "production") {
2144
2152
  [TUNA_ERROR__POSITION_IS_LIQUIDATED]: `Position is already liquidated`,
2145
2153
  [TUNA_ERROR__POSITION_IS_UNHEALTHY]: `Position is unhealthy`,
2146
2154
  [TUNA_ERROR__POSITION_NOT_EMPTY]: `Position is not empty`,
2155
+ [TUNA_ERROR__POSITION_SIZE_LIMIT_EXCEEDED]: `Position size exceeds the maximum allowed value`,
2147
2156
  [TUNA_ERROR__PROTOCOL_FEE_IS_OUT_OF_RANGE]: `Protocol fee is out of range`,
2148
2157
  [TUNA_ERROR__REBALANCE_CONDITIONS_NOT_MET]: `Rebalance conditions are not met`,
2149
2158
  [TUNA_ERROR__RECIPIENT_ACCOUNT_IS_NOT_SET]: `Optional recipient account is not set`,
@@ -3681,7 +3690,9 @@ function getCreateMarketInstructionDataEncoder() {
3681
3690
  ["borrowLimitA", (0, import_kit26.getU64Encoder)()],
3682
3691
  ["borrowLimitB", (0, import_kit26.getU64Encoder)()],
3683
3692
  ["maxSwapSlippage", (0, import_kit26.getU32Encoder)()],
3684
- ["rebalanceProtocolFee", (0, import_kit26.getU32Encoder)()]
3693
+ ["rebalanceProtocolFee", (0, import_kit26.getU32Encoder)()],
3694
+ ["spotPositionSizeLimitA", (0, import_kit26.getU64Encoder)()],
3695
+ ["spotPositionSizeLimitB", (0, import_kit26.getU64Encoder)()]
3685
3696
  ]),
3686
3697
  (value) => ({ ...value, discriminator: CREATE_MARKET_DISCRIMINATOR })
3687
3698
  );
@@ -3702,7 +3713,9 @@ function getCreateMarketInstructionDataDecoder() {
3702
3713
  ["borrowLimitA", (0, import_kit26.getU64Decoder)()],
3703
3714
  ["borrowLimitB", (0, import_kit26.getU64Decoder)()],
3704
3715
  ["maxSwapSlippage", (0, import_kit26.getU32Decoder)()],
3705
- ["rebalanceProtocolFee", (0, import_kit26.getU32Decoder)()]
3716
+ ["rebalanceProtocolFee", (0, import_kit26.getU32Decoder)()],
3717
+ ["spotPositionSizeLimitA", (0, import_kit26.getU64Decoder)()],
3718
+ ["spotPositionSizeLimitB", (0, import_kit26.getU64Decoder)()]
3706
3719
  ]);
3707
3720
  }
3708
3721
  function getCreateMarketInstructionDataCodec() {
@@ -9468,7 +9481,9 @@ function getUpdateMarketInstructionDataEncoder() {
9468
9481
  ["borrowLimitA", (0, import_kit68.getU64Encoder)()],
9469
9482
  ["borrowLimitB", (0, import_kit68.getU64Encoder)()],
9470
9483
  ["maxSwapSlippage", (0, import_kit68.getU32Encoder)()],
9471
- ["rebalanceProtocolFee", (0, import_kit68.getU32Encoder)()]
9484
+ ["rebalanceProtocolFee", (0, import_kit68.getU32Encoder)()],
9485
+ ["spotPositionSizeLimitA", (0, import_kit68.getU64Encoder)()],
9486
+ ["spotPositionSizeLimitB", (0, import_kit68.getU64Encoder)()]
9472
9487
  ]),
9473
9488
  (value) => ({ ...value, discriminator: UPDATE_MARKET_DISCRIMINATOR })
9474
9489
  );
@@ -9488,7 +9503,9 @@ function getUpdateMarketInstructionDataDecoder() {
9488
9503
  ["borrowLimitA", (0, import_kit68.getU64Decoder)()],
9489
9504
  ["borrowLimitB", (0, import_kit68.getU64Decoder)()],
9490
9505
  ["maxSwapSlippage", (0, import_kit68.getU32Decoder)()],
9491
- ["rebalanceProtocolFee", (0, import_kit68.getU32Decoder)()]
9506
+ ["rebalanceProtocolFee", (0, import_kit68.getU32Decoder)()],
9507
+ ["spotPositionSizeLimitA", (0, import_kit68.getU64Decoder)()],
9508
+ ["spotPositionSizeLimitB", (0, import_kit68.getU64Decoder)()]
9492
9509
  ]);
9493
9510
  }
9494
9511
  function getUpdateMarketInstructionDataCodec() {
@@ -10163,7 +10180,7 @@ async function createAddressLookupTableInstructions(authority, addresses, recent
10163
10180
  authority,
10164
10181
  payer: authority
10165
10182
  });
10166
- return { instructions: [createInstruction, extendInstruction], lookupTableAddress: pda[0] };
10183
+ return { instructions: [createInstruction, extendInstruction], lookupTableAddress: pda[0], addresses };
10167
10184
  }
10168
10185
 
10169
10186
  // src/utils/lpPositionMath.ts
@@ -10271,6 +10288,97 @@ function calculateProtocolFee(collateralAmount, borrowAmount, protocolFeeRateOnC
10271
10288
  return collateralAmount * BigInt(protocolFeeRateOnCollateral) / BigInt(HUNDRED_PERCENT) + borrowAmount * BigInt(protocolFeeRate) / BigInt(HUNDRED_PERCENT);
10272
10289
  }
10273
10290
 
10291
+ // src/utils/spotPositionMath.ts
10292
+ var import_fusionamm_core4 = require("@crypticdot/fusionamm-core");
10293
+ function getIncreaseSpotPositionQuote(args) {
10294
+ const {
10295
+ fusionPool,
10296
+ tickArrays,
10297
+ leverage,
10298
+ protocolFeeRate,
10299
+ protocolFeeRateOnCollateral,
10300
+ totalAmount,
10301
+ collateralToken,
10302
+ positionToken
10303
+ } = args;
10304
+ if (leverage < 1) {
10305
+ throw new Error("leverage must be greater or equal than 1.0");
10306
+ }
10307
+ if (protocolFeeRate < 0) {
10308
+ throw new Error("protocolFeeRate must be greater or equal than zero");
10309
+ }
10310
+ if (protocolFeeRateOnCollateral < 0) {
10311
+ throw new Error("protocolFeeRate must be greater or equal than zero");
10312
+ }
10313
+ if (totalAmount < 0) {
10314
+ throw new Error("totalAmount must be greater or equal than zero");
10315
+ }
10316
+ if (totalAmount == 0n) {
10317
+ return {
10318
+ collateral: 0n,
10319
+ borrow: 0n,
10320
+ protocolFeeA: 0n,
10321
+ protocolFeeB: 0n,
10322
+ priceImpact: 0
10323
+ };
10324
+ }
10325
+ let borrow;
10326
+ let collateral;
10327
+ let nextSqrtPrice = fusionPool.sqrtPrice;
10328
+ if (positionToken != collateralToken) {
10329
+ const price = (0, import_fusionamm_core4.sqrtPriceToPrice)(fusionPool.sqrtPrice, 1, 1);
10330
+ const totalAmountInOppositeToken = BigInt(
10331
+ Math.floor(positionToken == 0 /* A */ ? Number(totalAmount) / price : Number(totalAmount) * price)
10332
+ );
10333
+ const swapQuote = (0, import_fusionamm_core4.swapQuoteByOutputToken)(
10334
+ totalAmountInOppositeToken,
10335
+ positionToken == 0 /* A */,
10336
+ 0,
10337
+ fusionPool,
10338
+ tickArrays
10339
+ );
10340
+ nextSqrtPrice = swapQuote.nextSqrtPrice;
10341
+ const inputAmount = swapQuote.tokenEstIn;
10342
+ collateral = leverage > 1 ? BigInt(Math.floor(Number(inputAmount) / leverage)) : inputAmount;
10343
+ borrow = inputAmount - collateral;
10344
+ } else {
10345
+ if (leverage > 1) {
10346
+ collateral = BigInt(Math.floor(Number(totalAmount) / leverage));
10347
+ const swapQuote = (0, import_fusionamm_core4.swapQuoteByOutputToken)(
10348
+ totalAmount - collateral,
10349
+ positionToken == 0 /* A */,
10350
+ 0,
10351
+ fusionPool,
10352
+ tickArrays
10353
+ );
10354
+ nextSqrtPrice = swapQuote.nextSqrtPrice;
10355
+ borrow = swapQuote.tokenEstIn;
10356
+ } else {
10357
+ collateral = totalAmount;
10358
+ borrow = 0n;
10359
+ }
10360
+ }
10361
+ const collateralExcludingFee = collateral;
10362
+ const borrowExcludingFee = borrow;
10363
+ collateral = reverseApplyTunaProtocolFee(collateral, protocolFeeRateOnCollateral);
10364
+ borrow = reverseApplyTunaProtocolFee(borrow, protocolFeeRate);
10365
+ const protocolFeeA = (collateralToken == 0 /* A */ ? collateral - collateralExcludingFee : 0n) + (positionToken == 1 /* B */ ? borrow - borrowExcludingFee : 0n);
10366
+ const protocolFeeB = (collateralToken == 1 /* B */ ? collateral - collateralExcludingFee : 0n) + (positionToken == 0 /* A */ ? borrow - borrowExcludingFee : 0n);
10367
+ const oldPrice = (0, import_fusionamm_core4.sqrtPriceToPrice)(fusionPool.sqrtPrice, 1, 1);
10368
+ const newPrice = (0, import_fusionamm_core4.sqrtPriceToPrice)(nextSqrtPrice, 1, 1);
10369
+ const priceImpact = Math.abs(newPrice / oldPrice - 1) * 100;
10370
+ return {
10371
+ collateral,
10372
+ borrow,
10373
+ protocolFeeA,
10374
+ protocolFeeB,
10375
+ priceImpact
10376
+ };
10377
+ }
10378
+ function reverseApplyTunaProtocolFee(amount, protocolFeeRate) {
10379
+ return amount * BigInt(HUNDRED_PERCENT) / BigInt(HUNDRED_PERCENT - protocolFeeRate);
10380
+ }
10381
+
10274
10382
  // src/txbuilder/increaseTunaLpPositionOrca.ts
10275
10383
  var import_whirlpools_client2 = require("@orca-so/whirlpools-client");
10276
10384
  var import_whirlpools_core2 = require("@orca-so/whirlpools-core");
@@ -10504,7 +10612,7 @@ async function increaseTunaLpPositionOrcaInstruction(authority, tunaPosition, tu
10504
10612
 
10505
10613
  // src/txbuilder/increaseTunaLpPositionFusion.ts
10506
10614
  var import_fusionamm_client2 = require("@crypticdot/fusionamm-client");
10507
- var import_fusionamm_core4 = require("@crypticdot/fusionamm-core");
10615
+ var import_fusionamm_core5 = require("@crypticdot/fusionamm-core");
10508
10616
  var import_kit80 = require("@solana/kit");
10509
10617
  var import_memo2 = require("@solana-program/memo");
10510
10618
  var import_token_20223 = require("@solana-program/token-2022");
@@ -10574,12 +10682,12 @@ async function increaseTunaLpPositionFusionInstructions(rpc, authority, position
10574
10682
  mintB.programAddress
10575
10683
  );
10576
10684
  createInstructions.push(...createFeeRecipientAtaBInstructions.init);
10577
- const lowerTickArrayStartIndex = (0, import_fusionamm_core4.getTickArrayStartTickIndex)(
10685
+ const lowerTickArrayStartIndex = (0, import_fusionamm_core5.getTickArrayStartTickIndex)(
10578
10686
  tunaPosition.data.tickLowerIndex,
10579
10687
  fusionPool.data.tickSpacing
10580
10688
  );
10581
10689
  const [lowerTickArrayAddress] = await (0, import_fusionamm_client2.getTickArrayAddress)(fusionPool.address, lowerTickArrayStartIndex);
10582
- const upperTickArrayStartIndex = (0, import_fusionamm_core4.getTickArrayStartTickIndex)(
10690
+ const upperTickArrayStartIndex = (0, import_fusionamm_core5.getTickArrayStartTickIndex)(
10583
10691
  tunaPosition.data.tickUpperIndex,
10584
10692
  fusionPool.data.tickSpacing
10585
10693
  );
@@ -13503,7 +13611,7 @@ async function openAndIncreaseTunaLpPositionOrcaInstruction(authority, positionM
13503
13611
 
13504
13612
  // src/txbuilder/openAndIncreaseTunaLpPositionFusion.ts
13505
13613
  var import_fusionamm_client14 = require("@crypticdot/fusionamm-client");
13506
- var import_fusionamm_core5 = require("@crypticdot/fusionamm-core");
13614
+ var import_fusionamm_core6 = require("@crypticdot/fusionamm-core");
13507
13615
  var import_kit97 = require("@solana/kit");
13508
13616
  var import_sysvars2 = require("@solana/sysvars");
13509
13617
  var import_memo19 = require("@solana-program/memo");
@@ -13575,9 +13683,9 @@ async function openAndIncreaseTunaLpPositionFusionInstructions(rpc, authority, f
13575
13683
  mintB.programAddress
13576
13684
  );
13577
13685
  createInstructions.push(...createFeeRecipientAtaBInstructions.init);
13578
- const lowerTickArrayIndex = (0, import_fusionamm_core5.getTickArrayStartTickIndex)(args.tickLowerIndex, fusionPool.data.tickSpacing);
13686
+ const lowerTickArrayIndex = (0, import_fusionamm_core6.getTickArrayStartTickIndex)(args.tickLowerIndex, fusionPool.data.tickSpacing);
13579
13687
  const [lowerTickArrayAddress] = await (0, import_fusionamm_client14.getTickArrayAddress)(fusionPool.address, lowerTickArrayIndex);
13580
- const upperTickArrayIndex = (0, import_fusionamm_core5.getTickArrayStartTickIndex)(args.tickUpperIndex, fusionPool.data.tickSpacing);
13688
+ const upperTickArrayIndex = (0, import_fusionamm_core6.getTickArrayStartTickIndex)(args.tickUpperIndex, fusionPool.data.tickSpacing);
13581
13689
  const [upperTickArrayAddress] = await (0, import_fusionamm_client14.getTickArrayAddress)(fusionPool.address, upperTickArrayIndex);
13582
13690
  const [lowerTickArray, upperTickArray] = await (0, import_fusionamm_client14.fetchAllMaybeTickArray)(rpc, [
13583
13691
  lowerTickArrayAddress,
@@ -14645,6 +14753,7 @@ async function withdrawInstruction(authority, mint, funds, shares) {
14645
14753
  var import_fusionamm_client18 = require("@crypticdot/fusionamm-client");
14646
14754
  var import_whirlpools_client17 = require("@orca-so/whirlpools-client");
14647
14755
  var import_kit102 = require("@solana/kit");
14756
+ var import_address_lookup_table2 = require("@solana-program/address-lookup-table");
14648
14757
  var import_memo26 = require("@solana-program/memo");
14649
14758
  var import_system2 = require("@solana-program/system");
14650
14759
  var import_token2 = require("@solana-program/token");
@@ -14728,6 +14837,19 @@ async function createAddressLookupTableForMarketInstructions(rpc, poolAddress, m
14728
14837
  const addresses = await getAddressesForMarketLookupTable(rpc, poolAddress, marketMaker);
14729
14838
  return createAddressLookupTableInstructions(authority, addresses, recentSlot);
14730
14839
  }
14840
+ async function extendAddressLookupTableForMarketInstructions(rpc, poolAddress, marketMaker, authority, lookupTableAddress) {
14841
+ const marketAddresses = await getAddressesForMarketLookupTable(rpc, poolAddress, marketMaker);
14842
+ const lookupTable = await (0, import_address_lookup_table2.fetchAddressLookupTable)(rpc, lookupTableAddress);
14843
+ const existingAddresses = lookupTable.data.addresses;
14844
+ const addresses = marketAddresses.filter((addr) => !existingAddresses.includes(addr));
14845
+ const extendInstruction = (0, import_address_lookup_table2.getExtendLookupTableInstruction)({
14846
+ address: lookupTableAddress,
14847
+ addresses,
14848
+ authority,
14849
+ payer: authority
14850
+ });
14851
+ return { instructions: [extendInstruction], lookupTableAddress, addresses };
14852
+ }
14731
14853
 
14732
14854
  // src/txbuilder/repayTunaLpPositionDebt.ts
14733
14855
  var import_memo27 = require("@solana-program/memo");
@@ -15296,6 +15418,7 @@ async function rebalanceTunaLpPositionFusionInstruction(authority, tunaPosition,
15296
15418
  TUNA_ERROR__POSITION_IS_LIQUIDATED,
15297
15419
  TUNA_ERROR__POSITION_IS_UNHEALTHY,
15298
15420
  TUNA_ERROR__POSITION_NOT_EMPTY,
15421
+ TUNA_ERROR__POSITION_SIZE_LIMIT_EXCEEDED,
15299
15422
  TUNA_ERROR__PROTOCOL_FEE_IS_OUT_OF_RANGE,
15300
15423
  TUNA_ERROR__REBALANCE_CONDITIONS_NOT_MET,
15301
15424
  TUNA_ERROR__RECIPIENT_ACCOUNT_IS_NOT_SET,
@@ -15384,6 +15507,7 @@ async function rebalanceTunaLpPositionFusionInstruction(authority, tunaPosition,
15384
15507
  decreaseTunaSpotPositionOrcaInstructions,
15385
15508
  depositInstruction,
15386
15509
  depositInstructions,
15510
+ extendAddressLookupTableForMarketInstructions,
15387
15511
  fetchAllLendingPosition,
15388
15512
  fetchAllLendingPositionWithFilter,
15389
15513
  fetchAllMarket,
@@ -15508,6 +15632,7 @@ async function rebalanceTunaLpPositionFusionInstruction(authority, tunaPosition,
15508
15632
  getDepositInstructionDataDecoder,
15509
15633
  getDepositInstructionDataEncoder,
15510
15634
  getIncreaseLpPositionQuote,
15635
+ getIncreaseSpotPositionQuote,
15511
15636
  getIncreaseTunaLpPositionFusionDiscriminatorBytes,
15512
15637
  getIncreaseTunaLpPositionFusionInstruction,
15513
15638
  getIncreaseTunaLpPositionFusionInstructionDataCodec,
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() {
@@ -10325,7 +10339,7 @@ async function createAddressLookupTableInstructions(authority, addresses, recent
10325
10339
  authority,
10326
10340
  payer: authority
10327
10341
  });
10328
- return { instructions: [createInstruction, extendInstruction], lookupTableAddress: pda[0] };
10342
+ return { instructions: [createInstruction, extendInstruction], lookupTableAddress: pda[0], addresses };
10329
10343
  }
10330
10344
 
10331
10345
  // src/utils/lpPositionMath.ts
@@ -10441,6 +10455,100 @@ function calculateProtocolFee(collateralAmount, borrowAmount, protocolFeeRateOnC
10441
10455
  return collateralAmount * BigInt(protocolFeeRateOnCollateral) / BigInt(HUNDRED_PERCENT) + borrowAmount * BigInt(protocolFeeRate) / BigInt(HUNDRED_PERCENT);
10442
10456
  }
10443
10457
 
10458
+ // src/utils/spotPositionMath.ts
10459
+ import {
10460
+ sqrtPriceToPrice,
10461
+ swapQuoteByOutputToken
10462
+ } from "@crypticdot/fusionamm-core";
10463
+ function getIncreaseSpotPositionQuote(args) {
10464
+ const {
10465
+ fusionPool,
10466
+ tickArrays,
10467
+ leverage,
10468
+ protocolFeeRate,
10469
+ protocolFeeRateOnCollateral,
10470
+ totalAmount,
10471
+ collateralToken,
10472
+ positionToken
10473
+ } = args;
10474
+ if (leverage < 1) {
10475
+ throw new Error("leverage must be greater or equal than 1.0");
10476
+ }
10477
+ if (protocolFeeRate < 0) {
10478
+ throw new Error("protocolFeeRate must be greater or equal than zero");
10479
+ }
10480
+ if (protocolFeeRateOnCollateral < 0) {
10481
+ throw new Error("protocolFeeRate must be greater or equal than zero");
10482
+ }
10483
+ if (totalAmount < 0) {
10484
+ throw new Error("totalAmount must be greater or equal than zero");
10485
+ }
10486
+ if (totalAmount == 0n) {
10487
+ return {
10488
+ collateral: 0n,
10489
+ borrow: 0n,
10490
+ protocolFeeA: 0n,
10491
+ protocolFeeB: 0n,
10492
+ priceImpact: 0
10493
+ };
10494
+ }
10495
+ let borrow;
10496
+ let collateral;
10497
+ let nextSqrtPrice = fusionPool.sqrtPrice;
10498
+ if (positionToken != collateralToken) {
10499
+ const price = sqrtPriceToPrice(fusionPool.sqrtPrice, 1, 1);
10500
+ const totalAmountInOppositeToken = BigInt(
10501
+ Math.floor(positionToken == 0 /* A */ ? Number(totalAmount) / price : Number(totalAmount) * price)
10502
+ );
10503
+ const swapQuote = swapQuoteByOutputToken(
10504
+ totalAmountInOppositeToken,
10505
+ positionToken == 0 /* A */,
10506
+ 0,
10507
+ fusionPool,
10508
+ tickArrays
10509
+ );
10510
+ nextSqrtPrice = swapQuote.nextSqrtPrice;
10511
+ const inputAmount = swapQuote.tokenEstIn;
10512
+ collateral = leverage > 1 ? BigInt(Math.floor(Number(inputAmount) / leverage)) : inputAmount;
10513
+ borrow = inputAmount - collateral;
10514
+ } else {
10515
+ if (leverage > 1) {
10516
+ collateral = BigInt(Math.floor(Number(totalAmount) / leverage));
10517
+ const swapQuote = swapQuoteByOutputToken(
10518
+ totalAmount - collateral,
10519
+ positionToken == 0 /* A */,
10520
+ 0,
10521
+ fusionPool,
10522
+ tickArrays
10523
+ );
10524
+ nextSqrtPrice = swapQuote.nextSqrtPrice;
10525
+ borrow = swapQuote.tokenEstIn;
10526
+ } else {
10527
+ collateral = totalAmount;
10528
+ borrow = 0n;
10529
+ }
10530
+ }
10531
+ const collateralExcludingFee = collateral;
10532
+ const borrowExcludingFee = borrow;
10533
+ collateral = reverseApplyTunaProtocolFee(collateral, protocolFeeRateOnCollateral);
10534
+ borrow = reverseApplyTunaProtocolFee(borrow, protocolFeeRate);
10535
+ const protocolFeeA = (collateralToken == 0 /* A */ ? collateral - collateralExcludingFee : 0n) + (positionToken == 1 /* B */ ? borrow - borrowExcludingFee : 0n);
10536
+ const protocolFeeB = (collateralToken == 1 /* B */ ? collateral - collateralExcludingFee : 0n) + (positionToken == 0 /* A */ ? borrow - borrowExcludingFee : 0n);
10537
+ const oldPrice = sqrtPriceToPrice(fusionPool.sqrtPrice, 1, 1);
10538
+ const newPrice = sqrtPriceToPrice(nextSqrtPrice, 1, 1);
10539
+ const priceImpact = Math.abs(newPrice / oldPrice - 1) * 100;
10540
+ return {
10541
+ collateral,
10542
+ borrow,
10543
+ protocolFeeA,
10544
+ protocolFeeB,
10545
+ priceImpact
10546
+ };
10547
+ }
10548
+ function reverseApplyTunaProtocolFee(amount, protocolFeeRate) {
10549
+ return amount * BigInt(HUNDRED_PERCENT) / BigInt(HUNDRED_PERCENT - protocolFeeRate);
10550
+ }
10551
+
10444
10552
  // src/txbuilder/increaseTunaLpPositionOrca.ts
10445
10553
  import {
10446
10554
  fetchMaybeWhirlpool,
@@ -15009,6 +15117,7 @@ import { fetchWhirlpool as fetchWhirlpool3, getOracleAddress as getOracleAddress
15009
15117
  import {
15010
15118
  address as address3
15011
15119
  } from "@solana/kit";
15120
+ import { fetchAddressLookupTable, getExtendLookupTableInstruction as getExtendLookupTableInstruction2 } from "@solana-program/address-lookup-table";
15012
15121
  import { MEMO_PROGRAM_ADDRESS as MEMO_PROGRAM_ADDRESS26 } from "@solana-program/memo";
15013
15122
  import { SYSTEM_PROGRAM_ADDRESS } from "@solana-program/system";
15014
15123
  import { TOKEN_PROGRAM_ADDRESS as TOKEN_PROGRAM_ADDRESS2 } from "@solana-program/token";
@@ -15097,6 +15206,19 @@ async function createAddressLookupTableForMarketInstructions(rpc, poolAddress, m
15097
15206
  const addresses = await getAddressesForMarketLookupTable(rpc, poolAddress, marketMaker);
15098
15207
  return createAddressLookupTableInstructions(authority, addresses, recentSlot);
15099
15208
  }
15209
+ async function extendAddressLookupTableForMarketInstructions(rpc, poolAddress, marketMaker, authority, lookupTableAddress) {
15210
+ const marketAddresses = await getAddressesForMarketLookupTable(rpc, poolAddress, marketMaker);
15211
+ const lookupTable = await fetchAddressLookupTable(rpc, lookupTableAddress);
15212
+ const existingAddresses = lookupTable.data.addresses;
15213
+ const addresses = marketAddresses.filter((addr) => !existingAddresses.includes(addr));
15214
+ const extendInstruction = getExtendLookupTableInstruction2({
15215
+ address: lookupTableAddress,
15216
+ addresses,
15217
+ authority,
15218
+ payer: authority
15219
+ });
15220
+ return { instructions: [extendInstruction], lookupTableAddress, addresses };
15221
+ }
15100
15222
 
15101
15223
  // src/txbuilder/repayTunaLpPositionDebt.ts
15102
15224
  import { MEMO_PROGRAM_ADDRESS as MEMO_PROGRAM_ADDRESS27 } from "@solana-program/memo";
@@ -15693,6 +15815,7 @@ export {
15693
15815
  TUNA_ERROR__POSITION_IS_LIQUIDATED,
15694
15816
  TUNA_ERROR__POSITION_IS_UNHEALTHY,
15695
15817
  TUNA_ERROR__POSITION_NOT_EMPTY,
15818
+ TUNA_ERROR__POSITION_SIZE_LIMIT_EXCEEDED,
15696
15819
  TUNA_ERROR__PROTOCOL_FEE_IS_OUT_OF_RANGE,
15697
15820
  TUNA_ERROR__REBALANCE_CONDITIONS_NOT_MET,
15698
15821
  TUNA_ERROR__RECIPIENT_ACCOUNT_IS_NOT_SET,
@@ -15781,6 +15904,7 @@ export {
15781
15904
  decreaseTunaSpotPositionOrcaInstructions,
15782
15905
  depositInstruction,
15783
15906
  depositInstructions,
15907
+ extendAddressLookupTableForMarketInstructions,
15784
15908
  fetchAllLendingPosition,
15785
15909
  fetchAllLendingPositionWithFilter,
15786
15910
  fetchAllMarket,
@@ -15905,6 +16029,7 @@ export {
15905
16029
  getDepositInstructionDataDecoder,
15906
16030
  getDepositInstructionDataEncoder,
15907
16031
  getIncreaseLpPositionQuote,
16032
+ getIncreaseSpotPositionQuote,
15908
16033
  getIncreaseTunaLpPositionFusionDiscriminatorBytes,
15909
16034
  getIncreaseTunaLpPositionFusionInstruction,
15910
16035
  getIncreaseTunaLpPositionFusionInstructionDataCodec,
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.1",
4
+ "version": "3.1.3",
5
5
  "private": false,
6
6
  "license": "SEE LICENSE IN LICENSE",
7
7
  "main": "./dist/index.js",
@@ -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.1"
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",