@0dotxyz/p0-ts-sdk 2.8.4 → 2.9.0-alpha.1

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.cjs CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  var web3_js = require('@solana/web3.js');
4
4
  var superstruct = require('superstruct');
5
+ var sha2 = require('@noble/hashes/sha2');
5
6
  var BigNumber3 = require('bignumber.js');
6
7
  var BN8 = require('bn.js');
7
8
  var Decimal3 = require('decimal.js');
@@ -286,6 +287,7 @@ var PDA_BANK_FEE_STATE_SEED = Buffer.from("feestate");
286
287
  var PDA_BANK_EMISSIONS_AUTH_SEED = Buffer.from("emissions_auth_seed");
287
288
  var PDA_BANK_EMISSIONS_VAULT_SEED = Buffer.from("emissions_vault");
288
289
  var PDA_MARGINFI_ACCOUNT_SEED = Buffer.from("marginfi_account");
290
+ var PDA_ORDER_SEED = Buffer.from("order");
289
291
  function deriveBankLiquidityVaultAuthority(programId, bank) {
290
292
  return web3_js.PublicKey.findProgramAddressSync(
291
293
  [PDA_BANK_LIQUIDITY_VAULT_AUTH_SEED, bank.toBuffer()],
@@ -350,6 +352,14 @@ function deriveMarginfiAccount(programId, group, authority, accountIndex, thirdP
350
352
  programId
351
353
  );
352
354
  }
355
+ function deriveOrderPda(programId, marginfiAccount, bankKeys) {
356
+ const sortedBankKeys = bankKeys.map((key) => key.toBuffer()).sort(Buffer.compare);
357
+ const bankKeysHash = Buffer.from(sha2.sha256(Buffer.concat(sortedBankKeys)));
358
+ return web3_js.PublicKey.findProgramAddressSync(
359
+ [PDA_ORDER_SEED, marginfiAccount.toBuffer(), bankKeysHash],
360
+ programId
361
+ );
362
+ }
353
363
  var PYTH_PUSH_ORACLE_ID = new web3_js.PublicKey("pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT");
354
364
  var PYTH_SPONSORED_SHARD_ID = 0;
355
365
  var MARGINFI_SPONSORED_SHARD_ID = 3301;
@@ -521,6 +531,19 @@ function shortenAddress(pubkey, chars = 4) {
521
531
  function bpsToPercentile(bps) {
522
532
  return bps / 1e4;
523
533
  }
534
+ var U32_MAX = 4294967295;
535
+ var MAX_ORDER_SLIPPAGE_PERCENT = 10;
536
+ function percentToMaxSlippageU32(percent) {
537
+ if (!(percent > 0) || percent > MAX_ORDER_SLIPPAGE_PERCENT) {
538
+ throw new Error(
539
+ `Max slippage percent must be in (0, ${MAX_ORDER_SLIPPAGE_PERCENT}], got ${percent}`
540
+ );
541
+ }
542
+ return Math.floor(percent / 100 * U32_MAX);
543
+ }
544
+ function maxSlippageU32ToPercent(maxSlippage) {
545
+ return maxSlippage / U32_MAX * 100;
546
+ }
524
547
  var composeRemainingAccounts = (banksAndOracles) => {
525
548
  banksAndOracles.sort((a, b) => {
526
549
  const A = a[0].toBytes();
@@ -21460,6 +21483,9 @@ var TransactionType = /* @__PURE__ */ ((TransactionType2) => {
21460
21483
  TransactionType2["UNSTAKE_LST"] = "UNSTAKE_LST";
21461
21484
  TransactionType2["WITHDRAW_EMISSIONS"] = "WITHDRAW_EMISSIONS";
21462
21485
  TransactionType2["LIQUIDATE_ACCOUNT"] = "LIQUIDATE_ACCOUNT";
21486
+ TransactionType2["PLACE_ORDER"] = "PLACE_ORDER";
21487
+ TransactionType2["CLOSE_ORDER"] = "CLOSE_ORDER";
21488
+ TransactionType2["UPDATE_ORDER"] = "UPDATE_ORDER";
21463
21489
  TransactionType2["CREATE_PERM_BANK"] = "CREATE_PERM_BANK";
21464
21490
  TransactionType2["CREATE_GROUP"] = "CREATE_GROUP";
21465
21491
  TransactionType2["JUPITER_SWAP"] = "JUPITER_SWAP";
@@ -21546,6 +21572,14 @@ var TransactionConfigMap = {
21546
21572
  ["WITHDRAW_EMISSIONS" /* WITHDRAW_EMISSIONS */]: { label: () => "Withdraw emissions" },
21547
21573
  // LIQUIDATE
21548
21574
  ["LIQUIDATE_ACCOUNT" /* LIQUIDATE_ACCOUNT */]: { label: () => "Liquidate account" },
21575
+ // ORDERS (TP/SL)
21576
+ ["PLACE_ORDER" /* PLACE_ORDER */]: {
21577
+ label: ({ collateralToken, debtToken } = {}) => collateralToken && debtToken ? `Place TP/SL order on ${collateralToken}/${debtToken}` : "Place TP/SL order"
21578
+ },
21579
+ ["CLOSE_ORDER" /* CLOSE_ORDER */]: { label: () => "Close TP/SL order" },
21580
+ ["UPDATE_ORDER" /* UPDATE_ORDER */]: {
21581
+ label: ({ collateralToken, debtToken } = {}) => collateralToken && debtToken ? `Update TP/SL order on ${collateralToken}/${debtToken}` : "Update TP/SL order"
21582
+ },
21549
21583
  // BANK and GROUPS
21550
21584
  ["CREATE_PERM_BANK" /* CREATE_PERM_BANK */]: { label: () => "Create permissionless bank" },
21551
21585
  ["CREATE_GROUP" /* CREATE_GROUP */]: { label: () => "Create marginfi group" },
@@ -22662,6 +22696,10 @@ var AccountFlags = /* @__PURE__ */ ((AccountFlags2) => {
22662
22696
  AccountFlags2[AccountFlags2["ACCOUNT_IN_FLASHLOAN"] = 2] = "ACCOUNT_IN_FLASHLOAN";
22663
22697
  AccountFlags2[AccountFlags2["ACCOUNT_FLAG_DEPRECATED"] = 4] = "ACCOUNT_FLAG_DEPRECATED";
22664
22698
  AccountFlags2[AccountFlags2["ACCOUNT_TRANSFER_AUTHORITY_ALLOWED"] = 8] = "ACCOUNT_TRANSFER_AUTHORITY_ALLOWED";
22699
+ AccountFlags2[AccountFlags2["ACCOUNT_IN_RECEIVERSHIP"] = 16] = "ACCOUNT_IN_RECEIVERSHIP";
22700
+ AccountFlags2[AccountFlags2["ACCOUNT_IN_DELEVERAGE"] = 32] = "ACCOUNT_IN_DELEVERAGE";
22701
+ AccountFlags2[AccountFlags2["ACCOUNT_FROZEN"] = 64] = "ACCOUNT_FROZEN";
22702
+ AccountFlags2[AccountFlags2["ACCOUNT_IN_ORDER_EXECUTION"] = 128] = "ACCOUNT_IN_ORDER_EXECUTION";
22665
22703
  return AccountFlags2;
22666
22704
  })(AccountFlags || {});
22667
22705
  var MarginRequirementType = /* @__PURE__ */ ((MarginRequirementType5) => {
@@ -71322,13 +71360,13 @@ function computeInterestRates(bank) {
71322
71360
  const borrowingRate = baseInterestRate.times(new BigNumber3__default.default(1).plus(rateFee)).plus(fixedFee);
71323
71361
  return { lendingRate, borrowingRate };
71324
71362
  }
71325
- var U32_MAX = 4294967295;
71363
+ var U32_MAX2 = 4294967295;
71326
71364
  function rateFromU32(rate) {
71327
- const ratio = new BigNumber3__default.default(rate).div(U32_MAX);
71365
+ const ratio = new BigNumber3__default.default(rate).div(U32_MAX2);
71328
71366
  return ratio.times(10);
71329
71367
  }
71330
71368
  function utilFromU32(util) {
71331
- return new BigNumber3__default.default(util).div(U32_MAX);
71369
+ return new BigNumber3__default.default(util).div(U32_MAX2);
71332
71370
  }
71333
71371
  function calculateRateBetweenPoints(startX, startY, endX, endY, targetX) {
71334
71372
  if (endX.lte(startX)) return startY;
@@ -71937,6 +71975,22 @@ async function makePulseHealthIx(mfProgram, accounts, remainingAccounts = []) {
71937
71975
  marginfiAccount: accounts.marginfiAccount
71938
71976
  }).remainingAccounts(remainingAccounts).instruction();
71939
71977
  }
71978
+ async function makePlaceOrderIx(mfProgram, accounts, args, remainingAccounts = []) {
71979
+ const { marginfiAccount, feePayer, authority, order, globalFeeWallet, ...optionalAccounts } = accounts;
71980
+ return mfProgram.methods.marginfiAccountPlaceOrder(args.bankKeys, args.trigger).accounts({
71981
+ marginfiAccount,
71982
+ feePayer,
71983
+ order
71984
+ }).accountsPartial({ authority, globalFeeWallet, ...optionalAccounts }).remainingAccounts(remainingAccounts).instruction();
71985
+ }
71986
+ async function makeCloseOrderIx(mfProgram, accounts, remainingAccounts = []) {
71987
+ const { marginfiAccount, authority, order, feeRecipient, ...optionalAccounts } = accounts;
71988
+ return mfProgram.methods.marginfiAccountCloseOrder().accounts({
71989
+ authority,
71990
+ order,
71991
+ feeRecipient
71992
+ }).accountsPartial({ marginfiAccount, ...optionalAccounts }).remainingAccounts(remainingAccounts).instruction();
71993
+ }
71940
71994
  var instructions = {
71941
71995
  makeDepositIx,
71942
71996
  makeJuplendDepositIx,
@@ -71962,7 +72016,9 @@ var instructions = {
71962
72016
  makeLendingPoolConfigureBankOracleIx,
71963
72017
  makeLendingPoolConfigureBankOracleScopeIx,
71964
72018
  makeLendingPoolSetOraclePriceIx,
71965
- makePulseHealthIx
72019
+ makePulseHealthIx,
72020
+ makePlaceOrderIx,
72021
+ makeCloseOrderIx
71966
72022
  };
71967
72023
  var instructions_default3 = instructions;
71968
72024
 
@@ -72128,9 +72184,25 @@ function decodeAccountRaw(encoded, idl) {
72128
72184
  const coder = new anchor.BorshCoder(idl);
72129
72185
  return coder.accounts.decode("marginfiAccount" /* MarginfiAccount */, encoded);
72130
72186
  }
72187
+ function parseOrderRaw(orderAddress, orderRaw) {
72188
+ let trigger = "stopLoss";
72189
+ if ("takeProfit" in orderRaw.trigger) trigger = "takeProfit";
72190
+ if ("both" in orderRaw.trigger) trigger = "both";
72191
+ return {
72192
+ address: orderAddress,
72193
+ marginfiAccount: orderRaw.marginfiAccount,
72194
+ trigger,
72195
+ stopLoss: trigger === "takeProfit" ? null : wrappedI80F48toBigNumber(orderRaw.stopLoss),
72196
+ takeProfit: trigger === "stopLoss" ? null : wrappedI80F48toBigNumber(orderRaw.takeProfit),
72197
+ tags: [orderRaw.tags[0], orderRaw.tags[1]],
72198
+ createdAt: orderRaw.createdAt.toNumber(),
72199
+ maxSlippagePercent: maxSlippageU32ToPercent(orderRaw.maxSlippage)
72200
+ };
72201
+ }
72131
72202
  function parseBalanceRaw(balanceRaw) {
72132
72203
  const active = typeof balanceRaw.active === "number" ? balanceRaw.active === 1 : balanceRaw.active;
72133
72204
  const bankPk = balanceRaw.bankPk;
72205
+ const tag = balanceRaw.tag;
72134
72206
  const assetShares = wrappedI80F48toBigNumber(balanceRaw.assetShares);
72135
72207
  const liabilityShares = wrappedI80F48toBigNumber(balanceRaw.liabilityShares);
72136
72208
  const emissionsOutstanding = wrappedI80F48toBigNumber(balanceRaw.emissionsOutstanding);
@@ -72138,6 +72210,7 @@ function parseBalanceRaw(balanceRaw) {
72138
72210
  return {
72139
72211
  active,
72140
72212
  bankPk,
72213
+ tag,
72141
72214
  assetShares,
72142
72215
  liabilityShares,
72143
72216
  emissionsOutstanding,
@@ -72184,7 +72257,8 @@ function parseMarginfiAccountRaw(marginfiAccountPk, accountData) {
72184
72257
  balances,
72185
72258
  accountFlags,
72186
72259
  emissionsDestinationAccount,
72187
- healthCache
72260
+ healthCache,
72261
+ activeOrders: accountData.activeOrders
72188
72262
  };
72189
72263
  }
72190
72264
  function getActiveAccountFlags(flags) {
@@ -72240,13 +72314,15 @@ function dtoToMarginfiAccount(marginfiAccountDto) {
72240
72314
  balances: marginfiAccountDto.balances.map(dtoToBalance),
72241
72315
  accountFlags: marginfiAccountDto.accountFlags,
72242
72316
  emissionsDestinationAccount: new web3_js.PublicKey(marginfiAccountDto.emissionsDestinationAccount),
72243
- healthCache: dtoToHealthCache(marginfiAccountDto.healthCache)
72317
+ healthCache: dtoToHealthCache(marginfiAccountDto.healthCache),
72318
+ activeOrders: marginfiAccountDto.activeOrders ?? 0
72244
72319
  };
72245
72320
  }
72246
72321
  function dtoToBalance(balanceDto) {
72247
72322
  return {
72248
72323
  active: balanceDto.active,
72249
72324
  bankPk: new web3_js.PublicKey(balanceDto.bankPk),
72325
+ tag: balanceDto.tag ?? 0,
72250
72326
  assetShares: new BigNumber3__default.default(balanceDto.assetShares),
72251
72327
  liabilityShares: new BigNumber3__default.default(balanceDto.liabilityShares),
72252
72328
  emissionsOutstanding: new BigNumber3__default.default(balanceDto.emissionsOutstanding),
@@ -72278,13 +72354,15 @@ function marginfiAccountToDto(marginfiAccount) {
72278
72354
  balances: marginfiAccount.balances.map(balanceToDto),
72279
72355
  accountFlags: marginfiAccount.accountFlags,
72280
72356
  emissionsDestinationAccount: marginfiAccount.emissionsDestinationAccount.toBase58(),
72281
- healthCache: healthCacheToDto(marginfiAccount.healthCache)
72357
+ healthCache: healthCacheToDto(marginfiAccount.healthCache),
72358
+ activeOrders: marginfiAccount.activeOrders
72282
72359
  };
72283
72360
  }
72284
72361
  function balanceToDto(balance) {
72285
72362
  return {
72286
72363
  active: balance.active,
72287
72364
  bankPk: balance.bankPk.toBase58(),
72365
+ tag: balance.tag,
72288
72366
  assetShares: balance.assetShares.toString(),
72289
72367
  liabilityShares: balance.liabilityShares.toString(),
72290
72368
  emissionsOutstanding: balance.emissionsOutstanding.toString(),
@@ -72593,6 +72671,23 @@ function getBalanceUsdValueWithPriceBias(params) {
72593
72671
  });
72594
72672
  return { assets: assetsValue, liabilities: liabilitiesValue };
72595
72673
  }
72674
+ function computeOrderPairNetValue(params) {
72675
+ const { collateral, debt } = params;
72676
+ const { assets: collateralUsd } = getBalanceUsdValueWithPriceBias({
72677
+ balance: collateral.balance,
72678
+ bank: collateral.bank,
72679
+ oraclePrice: collateral.oraclePrice,
72680
+ marginRequirement: 2 /* Equity */,
72681
+ assetShareValueMultiplier: collateral.assetShareValueMultiplier
72682
+ });
72683
+ const { liabilities: debtUsd } = getBalanceUsdValueWithPriceBias({
72684
+ balance: debt.balance,
72685
+ bank: debt.bank,
72686
+ oraclePrice: debt.oraclePrice,
72687
+ marginRequirement: 2 /* Equity */
72688
+ });
72689
+ return { collateralUsd, debtUsd, netUsd: collateralUsd.minus(debtUsd) };
72690
+ }
72596
72691
  function computeQuantity(balance, bank) {
72597
72692
  const assetsQuantity = getAssetQuantity(bank, balance.assetShares);
72598
72693
  const liabilitiesQuantity = getLiabilityQuantity(bank, balance.liabilityShares);
@@ -72802,6 +72897,7 @@ function createEmptyBalance(bankPk) {
72802
72897
  const balance = {
72803
72898
  active: false,
72804
72899
  bankPk,
72900
+ tag: 0,
72805
72901
  assetShares: new BigNumber3__default.default(0),
72806
72902
  liabilityShares: new BigNumber3__default.default(0),
72807
72903
  emissionsOutstanding: new BigNumber3__default.default(0),
@@ -73104,6 +73200,7 @@ function computeProjectedActiveBalancesNoCpi({
73104
73200
  const projectedBalances = account.balances.map((b) => ({
73105
73201
  active: b.active,
73106
73202
  bankPk: b.bankPk,
73203
+ tag: b.tag,
73107
73204
  assetShares: new BigNumber3__default.default(b.assetShares),
73108
73205
  liabilityShares: new BigNumber3__default.default(b.liabilityShares),
73109
73206
  emissionsOutstanding: new BigNumber3__default.default(b.emissionsOutstanding),
@@ -73377,6 +73474,49 @@ var fetchMarginfiAccountData = async (program, marginfiAccountPk, banksMap, bank
73377
73474
  return { marginfiAccount };
73378
73475
  }
73379
73476
  };
73477
+ var fetchOrder = async (program, orderAddress) => {
73478
+ const orderRaw = await program.account.order.fetchNullable(orderAddress);
73479
+ if (!orderRaw) return null;
73480
+ return parseOrderRaw(orderAddress, orderRaw);
73481
+ };
73482
+ var fetchOrdersForAccount = async (program, marginfiAccount) => {
73483
+ const orders = await program.account.order.all([
73484
+ {
73485
+ memcmp: {
73486
+ bytes: marginfiAccount.toBase58(),
73487
+ offset: 8
73488
+ // first field after the discriminator
73489
+ }
73490
+ }
73491
+ ]);
73492
+ return orders.map(({ publicKey: publicKey5, account }) => parseOrderRaw(publicKey5, account));
73493
+ };
73494
+ var resolveOrderLegs = (marginfiAccount, order) => {
73495
+ const taggedBalances = marginfiAccount.balances.filter(
73496
+ (balance) => balance.active && balance.tag !== 0 && order.tags.includes(balance.tag)
73497
+ );
73498
+ return {
73499
+ collateralBank: taggedBalances.find((balance) => balance.assetShares.gt(0))?.bankPk ?? null,
73500
+ debtBank: taggedBalances.find((balance) => balance.liabilityShares.gt(0))?.bankPk ?? null
73501
+ };
73502
+ };
73503
+ var resolveOrderBanks = (marginfiAccount, order) => {
73504
+ const { collateralBank, debtBank } = resolveOrderLegs(marginfiAccount, order);
73505
+ if (!collateralBank || !debtBank) {
73506
+ throw new Error(
73507
+ `Could not resolve banks for order ${order.address.toBase58()}: tagged balances are missing or closed`
73508
+ );
73509
+ }
73510
+ return { collateralBank, debtBank };
73511
+ };
73512
+ var fetchOrderFees = async (program) => {
73513
+ const [feeStateAddress] = deriveFeeState(program.programId);
73514
+ const feeState = await program.account.feeState.fetch(feeStateAddress);
73515
+ return {
73516
+ placementFeeLamports: feeState.orderInitFlatSolFee,
73517
+ executionMaxFee: wrappedI80F48toBigNumber(feeState.orderExecutionMaxFee)
73518
+ };
73519
+ };
73380
73520
  function randomDistinctIndices(count, maxExclusive) {
73381
73521
  const chosen = /* @__PURE__ */ new Set();
73382
73522
  while (chosen.size < count) {
@@ -78101,6 +78241,7 @@ function generateDummyAccount(group, authority, accountKey) {
78101
78241
  const dummyBalances = Array(15).fill({
78102
78242
  active: false,
78103
78243
  bankPk: new web3_js.PublicKey("11111111111111111111111111111111"),
78244
+ tag: 0,
78104
78245
  assetShares: dummyWrappedI80F48,
78105
78246
  liabilityShares: dummyWrappedI80F48,
78106
78247
  emissionsOutstanding: dummyWrappedI80F48,
@@ -78109,7 +78250,7 @@ function generateDummyAccount(group, authority, accountKey) {
78109
78250
  const rawAccount = {
78110
78251
  group,
78111
78252
  authority,
78112
- lendingAccount: { balances: dummyBalances },
78253
+ lendingAccount: { balances: dummyBalances, lastTagUsed: 0 },
78113
78254
  healthCache: {
78114
78255
  assetValue: {
78115
78256
  value: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
@@ -78131,20 +78272,22 @@ function generateDummyAccount(group, authority, accountKey) {
78131
78272
  mrgnErr: 0
78132
78273
  },
78133
78274
  emissionsDestinationAccount: new web3_js.PublicKey("11111111111111111111111111111111"),
78134
- accountFlags: new BN8__default.default([0, 0, 0])
78275
+ accountFlags: new BN8__default.default([0, 0, 0]),
78276
+ activeOrders: 0
78135
78277
  };
78136
78278
  return parseMarginfiAccountRaw(accountKey, rawAccount);
78137
78279
  }
78138
78280
 
78139
78281
  // src/models/balance.ts
78140
78282
  var Balance = class _Balance {
78141
- constructor(active, bankPk, assetShares, liabilityShares, emissionsOutstanding, lastUpdate) {
78283
+ constructor(active, bankPk, assetShares, liabilityShares, emissionsOutstanding, lastUpdate, tag) {
78142
78284
  this.active = active;
78143
78285
  this.bankPk = bankPk;
78144
78286
  this.assetShares = assetShares;
78145
78287
  this.liabilityShares = liabilityShares;
78146
78288
  this.emissionsOutstanding = emissionsOutstanding;
78147
78289
  this.lastUpdate = lastUpdate;
78290
+ this.tag = tag;
78148
78291
  }
78149
78292
  static from(balanceRaw) {
78150
78293
  const props = parseBalanceRaw(balanceRaw);
@@ -78154,7 +78297,8 @@ var Balance = class _Balance {
78154
78297
  props.assetShares,
78155
78298
  props.liabilityShares,
78156
78299
  props.emissionsOutstanding,
78157
- props.lastUpdate
78300
+ props.lastUpdate,
78301
+ props.tag
78158
78302
  );
78159
78303
  }
78160
78304
  static fromBalanceType(balance) {
@@ -78164,7 +78308,8 @@ var Balance = class _Balance {
78164
78308
  balance.assetShares,
78165
78309
  balance.liabilityShares,
78166
78310
  balance.emissionsOutstanding,
78167
- balance.lastUpdate
78311
+ balance.lastUpdate,
78312
+ balance.tag
78168
78313
  );
78169
78314
  }
78170
78315
  static createEmpty(bankPk) {
@@ -78240,7 +78385,7 @@ var HealthCache = class _HealthCache {
78240
78385
 
78241
78386
  // src/models/account.ts
78242
78387
  var MarginfiAccount = class _MarginfiAccount {
78243
- constructor(address, group, authority, balances, accountFlags, emissionsDestinationAccount, healthCache) {
78388
+ constructor(address, group, authority, balances, accountFlags, emissionsDestinationAccount, healthCache, activeOrders = 0) {
78244
78389
  this.address = address;
78245
78390
  this.group = group;
78246
78391
  this.authority = authority;
@@ -78248,6 +78393,7 @@ var MarginfiAccount = class _MarginfiAccount {
78248
78393
  this.accountFlags = accountFlags;
78249
78394
  this.emissionsDestinationAccount = emissionsDestinationAccount;
78250
78395
  this.healthCache = healthCache;
78396
+ this.activeOrders = activeOrders;
78251
78397
  }
78252
78398
  /**
78253
78399
  * Fetches a marginfi account from on-chain data.
@@ -78272,7 +78418,8 @@ var MarginfiAccount = class _MarginfiAccount {
78272
78418
  account.balances.map((b) => Balance.fromBalanceType(b)),
78273
78419
  account.accountFlags,
78274
78420
  account.emissionsDestinationAccount,
78275
- account.healthCache
78421
+ account.healthCache,
78422
+ account.activeOrders
78276
78423
  );
78277
78424
  }
78278
78425
  /**
@@ -78292,7 +78439,8 @@ var MarginfiAccount = class _MarginfiAccount {
78292
78439
  props.balances.map((b) => Balance.fromBalanceType(b)),
78293
78440
  props.accountFlags,
78294
78441
  props.emissionsDestinationAccount,
78295
- HealthCache.fromHealthCacheType(props.healthCache)
78442
+ HealthCache.fromHealthCacheType(props.healthCache),
78443
+ props.activeOrders
78296
78444
  );
78297
78445
  }
78298
78446
  /**
@@ -79128,6 +79276,41 @@ var MarginfiAccount = class _MarginfiAccount {
79128
79276
  }
79129
79277
  });
79130
79278
  }
79279
+ // ----------------------------------------------------------------------------
79280
+ // Orders (take-profit / stop-loss)
79281
+ // ----------------------------------------------------------------------------
79282
+ /**
79283
+ * Creates a place-order instruction for this marginfi account.
79284
+ *
79285
+ * @see {@link makePlaceOrderIx} for detailed implementation
79286
+ */
79287
+ async makePlaceOrderIx(params) {
79288
+ return makePlaceOrderIx2({ ...params, marginfiAccount: this });
79289
+ }
79290
+ /**
79291
+ * Creates a transaction placing a take-profit / stop-loss order on a collateral/debt pair.
79292
+ *
79293
+ * @see {@link makePlaceOrderTx} for detailed implementation
79294
+ */
79295
+ async makePlaceOrderTx(params) {
79296
+ return makePlaceOrderTx({ ...params, marginfiAccount: this });
79297
+ }
79298
+ /**
79299
+ * Creates a transaction closing an existing order.
79300
+ *
79301
+ * @see {@link makeCloseOrderTx} for detailed implementation
79302
+ */
79303
+ async makeCloseOrderTx(params) {
79304
+ return makeCloseOrderTx({ ...params, marginfiAccount: this });
79305
+ }
79306
+ /**
79307
+ * Creates a transaction replacing the pair's existing order with new thresholds.
79308
+ *
79309
+ * @see {@link makeUpdateOrderTx} for detailed implementation
79310
+ */
79311
+ async makeUpdateOrderTx(params) {
79312
+ return makeUpdateOrderTx({ ...params, marginfiAccount: this });
79313
+ }
79131
79314
  /**
79132
79315
  * Creates a repay transaction.
79133
79316
  *
@@ -79285,7 +79468,8 @@ function projectAccountAfterFirstLeg(account, firstLegFlashloanTxs, program, ban
79285
79468
  projectedBalances.map((b) => Balance.fromBalanceType(b)),
79286
79469
  account.accountFlags,
79287
79470
  account.emissionsDestinationAccount,
79288
- account.healthCache
79471
+ account.healthCache,
79472
+ account.activeOrders
79289
79473
  );
79290
79474
  }
79291
79475
  function composeBundle(firstLegTxs, secondLegTxs, payer, blockhash, maxBundleTxs) {
@@ -81688,6 +81872,100 @@ async function makeBulkRepayTx(params) {
81688
81872
  );
81689
81873
  return { transactions, actionTxIndex: 0, mustBeAtomicBundle: false };
81690
81874
  }
81875
+ function buildOrderTrigger(params) {
81876
+ const { stopLossUsd, takeProfitUsd } = params;
81877
+ const maxSlippage = percentToMaxSlippageU32(params.maxSlippagePercent);
81878
+ if (stopLossUsd && takeProfitUsd) {
81879
+ if (takeProfitUsd.lte(stopLossUsd)) {
81880
+ throw new Error(
81881
+ `Take-profit threshold (${takeProfitUsd}) must be above stop-loss threshold (${stopLossUsd})`
81882
+ );
81883
+ }
81884
+ return {
81885
+ both: {
81886
+ stopLoss: bigNumberToWrappedI80F48(stopLossUsd),
81887
+ takeProfit: bigNumberToWrappedI80F48(takeProfitUsd),
81888
+ maxSlippage
81889
+ }
81890
+ };
81891
+ }
81892
+ if (stopLossUsd) {
81893
+ return { stopLoss: { threshold: bigNumberToWrappedI80F48(stopLossUsd), maxSlippage } };
81894
+ }
81895
+ if (takeProfitUsd) {
81896
+ return { takeProfit: { threshold: bigNumberToWrappedI80F48(takeProfitUsd), maxSlippage } };
81897
+ }
81898
+ throw new Error("An order needs a stop-loss threshold, a take-profit threshold, or both");
81899
+ }
81900
+ async function makePlaceOrderIx2(params) {
81901
+ const { program, marginfiAccount, collateralBank, debtBank, trigger, feePayer } = params;
81902
+ const [order] = deriveOrderPda(program.programId, marginfiAccount.address, [
81903
+ collateralBank,
81904
+ debtBank
81905
+ ]);
81906
+ const globalFeeWallet = params.globalFeeWallet ?? (await program.account.feeState.fetch(deriveFeeState(program.programId)[0])).globalFeeWallet;
81907
+ const placeOrderIx = await instructions_default3.makePlaceOrderIx(
81908
+ program,
81909
+ {
81910
+ marginfiAccount: marginfiAccount.address,
81911
+ feePayer: feePayer ?? marginfiAccount.authority,
81912
+ authority: marginfiAccount.authority,
81913
+ order,
81914
+ globalFeeWallet,
81915
+ group: marginfiAccount.group
81916
+ },
81917
+ { bankKeys: [collateralBank, debtBank], trigger: buildOrderTrigger(trigger) }
81918
+ );
81919
+ return { instructions: [placeOrderIx], keys: [] };
81920
+ }
81921
+ async function makeCloseOrderIx2(params) {
81922
+ const { program, marginfiAccount, order, feeRecipient } = params;
81923
+ const closeOrderIx = await instructions_default3.makeCloseOrderIx(program, {
81924
+ marginfiAccount: marginfiAccount.address,
81925
+ authority: marginfiAccount.authority,
81926
+ order,
81927
+ feeRecipient: feeRecipient ?? marginfiAccount.authority,
81928
+ group: marginfiAccount.group
81929
+ });
81930
+ return { instructions: [closeOrderIx], keys: [] };
81931
+ }
81932
+ async function compileOrderTx(params, payerKey, ixs, type) {
81933
+ const blockhash = params.blockhash ?? (await params.connection.getLatestBlockhashAndContext("confirmed")).value.blockhash;
81934
+ return addTransactionMetadata(
81935
+ new web3_js.VersionedTransaction(
81936
+ new web3_js.TransactionMessage({
81937
+ instructions: ixs.flatMap((ix) => ix.instructions),
81938
+ payerKey,
81939
+ recentBlockhash: blockhash
81940
+ }).compileToV0Message(params.luts)
81941
+ ),
81942
+ { type, signers: ixs.flatMap((ix) => ix.keys), addressLookupTables: params.luts }
81943
+ );
81944
+ }
81945
+ async function makePlaceOrderTx(params) {
81946
+ const placeIxs = await makePlaceOrderIx2(params);
81947
+ const payerKey = params.feePayer ?? params.marginfiAccount.authority;
81948
+ return compileOrderTx(params, payerKey, [placeIxs], "PLACE_ORDER" /* PLACE_ORDER */);
81949
+ }
81950
+ async function makeCloseOrderTx(params) {
81951
+ const closeIxs = await makeCloseOrderIx2(params);
81952
+ return compileOrderTx(
81953
+ params,
81954
+ params.marginfiAccount.authority,
81955
+ [closeIxs],
81956
+ "CLOSE_ORDER" /* CLOSE_ORDER */
81957
+ );
81958
+ }
81959
+ async function makeUpdateOrderTx(params) {
81960
+ const [order] = deriveOrderPda(params.program.programId, params.marginfiAccount.address, [
81961
+ params.collateralBank,
81962
+ params.debtBank
81963
+ ]);
81964
+ const closeIxs = await makeCloseOrderIx2({ ...params, order, feeRecipient: params.feePayer });
81965
+ const placeIxs = await makePlaceOrderIx2(params);
81966
+ const payerKey = params.feePayer ?? params.marginfiAccount.authority;
81967
+ return compileOrderTx(params, payerKey, [closeIxs, placeIxs], "UPDATE_ORDER" /* UPDATE_ORDER */);
81968
+ }
81691
81969
 
81692
81970
  // src/services/account/services/account-simulation.service.ts
81693
81971
  async function simulateAccountHealthCacheWithFallback(params) {
@@ -84548,6 +84826,52 @@ var MarginfiAccountWrapper = class {
84548
84826
  opts
84549
84827
  });
84550
84828
  }
84829
+ // ----------------------------------------------------------------------------
84830
+ // Orders (take-profit / stop-loss)
84831
+ // ----------------------------------------------------------------------------
84832
+ /**
84833
+ * Creates a transaction placing a take-profit / stop-loss order on a collateral/debt pair.
84834
+ *
84835
+ * @param collateralBank - Bank of the asset-side balance
84836
+ * @param debtBank - Bank of the liability-side balance
84837
+ * @param trigger - USD pair-equity thresholds and max slippage
84838
+ */
84839
+ async makePlaceOrderTx(collateralBank, debtBank, trigger) {
84840
+ return this.account.makePlaceOrderTx({
84841
+ program: this.client.program,
84842
+ collateralBank,
84843
+ debtBank,
84844
+ trigger,
84845
+ luts: this.client.addressLookupTables,
84846
+ connection: this.client.program.provider.connection
84847
+ });
84848
+ }
84849
+ /**
84850
+ * Creates a transaction replacing the pair's existing order with new thresholds.
84851
+ */
84852
+ async makeUpdateOrderTx(collateralBank, debtBank, trigger) {
84853
+ return this.account.makeUpdateOrderTx({
84854
+ program: this.client.program,
84855
+ collateralBank,
84856
+ debtBank,
84857
+ trigger,
84858
+ luts: this.client.addressLookupTables,
84859
+ connection: this.client.program.provider.connection
84860
+ });
84861
+ }
84862
+ /**
84863
+ * Creates a transaction closing an existing order.
84864
+ *
84865
+ * @param order - The order PDA (from `fetchOrdersForAccount` or `deriveOrderPda`)
84866
+ */
84867
+ async makeCloseOrderTx(order) {
84868
+ return this.account.makeCloseOrderTx({
84869
+ program: this.client.program,
84870
+ order,
84871
+ luts: this.client.addressLookupTables,
84872
+ connection: this.client.program.provider.connection
84873
+ });
84874
+ }
84551
84875
  /**
84552
84876
  * Creates a repay transaction with auto-injected client data.
84553
84877
  *
@@ -85290,6 +85614,7 @@ exports.PDA_BANK_INSURANCE_VAULT_SEED = PDA_BANK_INSURANCE_VAULT_SEED;
85290
85614
  exports.PDA_BANK_LIQUIDITY_VAULT_AUTH_SEED = PDA_BANK_LIQUIDITY_VAULT_AUTH_SEED;
85291
85615
  exports.PDA_BANK_LIQUIDITY_VAULT_SEED = PDA_BANK_LIQUIDITY_VAULT_SEED;
85292
85616
  exports.PDA_MARGINFI_ACCOUNT_SEED = PDA_MARGINFI_ACCOUNT_SEED;
85617
+ exports.PDA_ORDER_SEED = PDA_ORDER_SEED;
85293
85618
  exports.PRIORITY_TX_SIZE = PRIORITY_TX_SIZE;
85294
85619
  exports.PYTH_PRICE_CONF_INTERVALS = PYTH_PRICE_CONF_INTERVALS;
85295
85620
  exports.PYTH_PUSH_ORACLE_ID = PYTH_PUSH_ORACLE_ID;
@@ -85339,6 +85664,7 @@ exports.bankRawToDto = bankRawToDto;
85339
85664
  exports.bigNumberToWrappedI80F48 = bigNumberToWrappedI80F48;
85340
85665
  exports.bpsToPercentile = bpsToPercentile;
85341
85666
  exports.buildCollateralLegIxs = buildCollateralLegIxs;
85667
+ exports.buildOrderTrigger = buildOrderTrigger;
85342
85668
  exports.calculateApyFromInterest = calculateApyFromInterest;
85343
85669
  exports.calculateInterestFromApy = calculateInterestFromApy;
85344
85670
  exports.capConfidenceInterval = capConfidenceInterval;
@@ -85399,6 +85725,7 @@ exports.computeMaxWithdrawForBank = computeMaxWithdrawForBank;
85399
85725
  exports.computeNetApy = computeNetApy;
85400
85726
  exports.computeOracleMultiplier = computeOracleMultiplier;
85401
85727
  exports.computeOracleMultipliers = computeOracleMultipliers;
85728
+ exports.computeOrderPairNetValue = computeOrderPairNetValue;
85402
85729
  exports.computeProjectedActiveBalancesNoCpi = computeProjectedActiveBalancesNoCpi;
85403
85730
  exports.computeProjectedActiveBanksNoCpi = computeProjectedActiveBanksNoCpi;
85404
85731
  exports.computePtMultiplier = computePtMultiplier;
@@ -85433,6 +85760,7 @@ exports.deriveBankLiquidityVault = deriveBankLiquidityVault;
85433
85760
  exports.deriveBankLiquidityVaultAuthority = deriveBankLiquidityVaultAuthority;
85434
85761
  exports.deriveFeeState = deriveFeeState;
85435
85762
  exports.deriveMarginfiAccount = deriveMarginfiAccount;
85763
+ exports.deriveOrderPda = deriveOrderPda;
85436
85764
  exports.deserializeInstruction = deserializeInstruction;
85437
85765
  exports.deserializeLut = deserializeLut;
85438
85766
  exports.deserializeSwapEngineRequest = deserializeSwapEngineRequest;
@@ -85472,6 +85800,9 @@ exports.fetchOracleData = fetchOracleData;
85472
85800
  exports.fetchOracleMultipliers = fetchOracleMultipliers;
85473
85801
  exports.fetchOracleMultipliersFromAPI = fetchOracleMultipliersFromAPI;
85474
85802
  exports.fetchOracleMultipliersFromChain = fetchOracleMultipliersFromChain;
85803
+ exports.fetchOrder = fetchOrder;
85804
+ exports.fetchOrderFees = fetchOrderFees;
85805
+ exports.fetchOrdersForAccount = fetchOrdersForAccount;
85475
85806
  exports.fetchProgramForMints = fetchProgramForMints;
85476
85807
  exports.fetchPythOracleData = fetchPythOracleData;
85477
85808
  exports.fetchPythOraclePricesFromAPI = fetchPythOraclePricesFromAPI;
@@ -85570,6 +85901,8 @@ exports.makeBulkWithdrawTx = makeBulkWithdrawTx;
85570
85901
  exports.makeBundleTipIx = makeBundleTipIx;
85571
85902
  exports.makeCloseMarginfiAccountIx = makeCloseMarginfiAccountIx;
85572
85903
  exports.makeCloseMarginfiAccountTx = makeCloseMarginfiAccountTx;
85904
+ exports.makeCloseOrderIx = makeCloseOrderIx2;
85905
+ exports.makeCloseOrderTx = makeCloseOrderTx;
85573
85906
  exports.makeCreateAccountIxWithProjection = makeCreateAccountIxWithProjection;
85574
85907
  exports.makeCreateAccountTxWithProjection = makeCreateAccountTxWithProjection;
85575
85908
  exports.makeCreateMarginfiAccountIx = makeCreateMarginfiAccountIx;
@@ -85594,6 +85927,8 @@ exports.makeLoopTx = makeLoopTx;
85594
85927
  exports.makeMergeStakeAccountsTx = makeMergeStakeAccountsTx;
85595
85928
  exports.makeMintStakedLstIx = makeMintStakedLstIx;
85596
85929
  exports.makeMintStakedLstTx = makeMintStakedLstTx;
85930
+ exports.makePlaceOrderIx = makePlaceOrderIx2;
85931
+ exports.makePlaceOrderTx = makePlaceOrderTx;
85597
85932
  exports.makePoolAddBankIx = makePoolAddBankIx3;
85598
85933
  exports.makePoolConfigureBankIx = makePoolConfigureBankIx3;
85599
85934
  exports.makePriorityFeeIx = makePriorityFeeIx;
@@ -85615,6 +85950,7 @@ exports.makeTxPriorityIx = makeTxPriorityIx;
85615
85950
  exports.makeUnwrapSolIx = makeUnwrapSolIx;
85616
85951
  exports.makeUpdateDriftMarketIxs = makeUpdateDriftMarketIxs;
85617
85952
  exports.makeUpdateJupLendRateIxs = makeUpdateJupLendRateIxs;
85953
+ exports.makeUpdateOrderTx = makeUpdateOrderTx;
85618
85954
  exports.makeVaultCompleteWithdrawalIx = makeVaultCompleteWithdrawalIx;
85619
85955
  exports.makeVaultCompleteWithdrawalTx = makeVaultCompleteWithdrawalTx;
85620
85956
  exports.makeVaultDepositIx = makeVaultDepositIx;
@@ -85629,6 +85965,7 @@ exports.makeWrapSolIxs = makeWrapSolIxs;
85629
85965
  exports.mapJupiterQuoteToSwapQuoteResult = mapJupiterQuoteToSwapQuoteResult;
85630
85966
  exports.mapPythBanksToOraclePrices = mapPythBanksToOraclePrices;
85631
85967
  exports.marginfiAccountToDto = marginfiAccountToDto;
85968
+ exports.maxSlippageU32ToPercent = maxSlippageU32ToPercent;
85632
85969
  exports.mergeBridgeQuotes = mergeBridgeQuotes;
85633
85970
  exports.mergeBridgeQuotesDebt = mergeBridgeQuotesDebt;
85634
85971
  exports.mergeBridgeQuotesLoop = mergeBridgeQuotesLoop;
@@ -85644,14 +85981,18 @@ exports.parseHealthCacheRaw = parseHealthCacheRaw;
85644
85981
  exports.parseMarginfiAccountRaw = parseMarginfiAccountRaw;
85645
85982
  exports.parseOperationalState = parseOperationalState;
85646
85983
  exports.parseOracleSetup = parseOracleSetup;
85984
+ exports.parseOrderRaw = parseOrderRaw;
85647
85985
  exports.parsePriceInfo = parseOraclePriceData;
85648
85986
  exports.parseRiskTier = parseRiskTier;
85649
85987
  exports.parseRpcPythPriceData = parseRpcPythPriceData;
85650
85988
  exports.patchDepositAmount = patchDepositAmount;
85989
+ exports.percentToMaxSlippageU32 = percentToMaxSlippageU32;
85651
85990
  exports.requireBank = requireBank;
85652
85991
  exports.requireTokenProgram = requireTokenProgram;
85653
85992
  exports.resolveAmount = resolveAmount;
85654
85993
  exports.resolveBridgeCandidateBanks = resolveBridgeCandidateBanks;
85994
+ exports.resolveOrderBanks = resolveOrderBanks;
85995
+ exports.resolveOrderLegs = resolveOrderLegs;
85655
85996
  exports.resolvePinnedSwapRoute = resolvePinnedSwapRoute;
85656
85997
  exports.resolveTokenProgramForMint = resolveTokenProgramForMint;
85657
85998
  exports.resolveVaultTokenProgram = resolveVaultTokenProgram;