dipcoin-cli 1.3.4 → 1.3.6

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/README.md CHANGED
@@ -181,6 +181,10 @@ dipcoin-cli position tpsl <symbol> --side <buy|sell> --quantity <q> --leverage <
181
181
  dipcoin-cli position tpsl <symbol> --side sell --quantity 0.01 --leverage 10 \
182
182
  --tp-trigger 105000 --tp-type limit --tp-price 105000
183
183
 
184
+ # Set or edit TP/SL on a vault position. Existing plan IDs are discovered automatically.
185
+ dipcoin-cli position tpsl BTC --side sell --quantity 0.01 --leverage 10 \
186
+ --vault <vaultId> --tp-trigger 105000 --sl-trigger 90000
187
+
184
188
  # Close positions — CLI figures out side & qty
185
189
  dipcoin-cli position close BTC # close 100% of BTC position
186
190
  dipcoin-cli position close BTC --percent 50 # close half
package/dist/cli.cjs CHANGED
@@ -12921,8 +12921,8 @@ async function signMessage(keypair, messageBytes) {
12921
12921
  */
12922
12922
  function buildSignature(signature, isKeyPair = false) {
12923
12923
  const signatureData = cryptography.parseSerializedSignature(signature);
12924
- let signatureHex = buffer.Buffer.from(signatureData.signature).toString("hex");
12925
- let publicKey = buffer.Buffer.from(signatureData.publicKey).toString("base64");
12924
+ const signatureHex = buffer.Buffer.from(signatureData.signature).toString("hex");
12925
+ const publicKey = buffer.Buffer.from(signatureData.publicKey).toString("base64");
12926
12926
  let flag = SignerTypes.KP_SECP256;
12927
12927
  if (signatureData.signatureScheme === "Secp256k1" ||
12928
12928
  signatureData.signatureScheme === "Secp256r1") {
@@ -13006,13 +13006,11 @@ function getModuleDir() {
13006
13006
  return path__default["default"].dirname(__filename);
13007
13007
  }
13008
13008
  }
13009
- catch (e) {
13009
+ catch {
13010
13010
  // Fall through to CommonJS
13011
13011
  }
13012
13012
  // CommonJS: use __dirname (will be available after compilation)
13013
- // @ts-ignore - __dirname may not be defined in ESM context
13014
13013
  if (typeof __dirname !== "undefined") {
13015
- // @ts-ignore
13016
13014
  return __dirname;
13017
13015
  }
13018
13016
  // Fallback to process.cwd()
@@ -16457,8 +16455,12 @@ class HttpClient {
16457
16455
  const proc = child_process.spawn("curl", args);
16458
16456
  let stdout = "";
16459
16457
  let stderr = "";
16460
- proc.stdout.on("data", (chunk) => { stdout += chunk; });
16461
- proc.stderr.on("data", (chunk) => { stderr += chunk; });
16458
+ proc.stdout.on("data", (chunk) => {
16459
+ stdout += chunk;
16460
+ });
16461
+ proc.stderr.on("data", (chunk) => {
16462
+ stderr += chunk;
16463
+ });
16462
16464
  proc.on("close", (code) => {
16463
16465
  if (!stdout) {
16464
16466
  return reject(new Error(stderr || `curl exited with code ${code}`));
@@ -16806,17 +16808,87 @@ function buildSetOraclePriceTx(deployment, args, tx, gasBudget, sender) {
16806
16808
  return t;
16807
16809
  }
16808
16810
 
16811
+ // Copyright (c) 2025 Dipcoin LLC
16812
+ // SPDX-License-Identifier: Apache-2.0
16813
+ const SUI_COIN_TYPE = "0x2::sui::SUI";
16814
+ const STALE_GAS_RETRY_DELAY_MS = 1000;
16815
+ function sleep(ms) {
16816
+ return new Promise((resolve) => setTimeout(resolve, ms));
16817
+ }
16818
+ function getErrorMessage(error) {
16819
+ if (error instanceof Error)
16820
+ return error.message;
16821
+ return String(error);
16822
+ }
16823
+ function isStaleObjectVersionError(error) {
16824
+ const message = getErrorMessage(error);
16825
+ return (message.includes("Transaction needs to be rebuilt") ||
16826
+ message.includes("unavailable for consumption") ||
16827
+ message.includes("current version:"));
16828
+ }
16829
+ async function getFreshGasObjectRef(suiClient, owner) {
16830
+ const coins = [];
16831
+ let cursor;
16832
+ do {
16833
+ const page = await suiClient.getCoins({ owner, coinType: SUI_COIN_TYPE, cursor });
16834
+ coins.push(...page.data);
16835
+ cursor = page.hasNextPage ? page.nextCursor : null;
16836
+ } while (cursor);
16837
+ if (!coins.length) {
16838
+ throw new Error(`No SUI gas coins found for ${owner}`);
16839
+ }
16840
+ const gasCoin = coins.slice().sort((a, b) => {
16841
+ const aBalance = BigInt(a.balance);
16842
+ const bBalance = BigInt(b.balance);
16843
+ if (aBalance === bBalance)
16844
+ return 0;
16845
+ return aBalance < bBalance ? 1 : -1;
16846
+ })[0];
16847
+ const fresh = await suiClient.getObject({ id: gasCoin.coinObjectId });
16848
+ const ref = fresh.data;
16849
+ if (!ref?.objectId || !ref.version || !ref.digest) {
16850
+ throw new Error(`Failed to refresh gas coin object ref for ${gasCoin.coinObjectId}`);
16851
+ }
16852
+ return {
16853
+ objectId: ref.objectId,
16854
+ version: ref.version,
16855
+ digest: ref.digest,
16856
+ };
16857
+ }
16858
+ async function setFreshGasPayment(suiClient, tx, owner) {
16859
+ tx.setGasPayment([await getFreshGasObjectRef(suiClient, owner)]);
16860
+ }
16861
+ async function signAndExecuteTransactionWithFreshGas(suiClient, tx, signer, options) {
16862
+ const sender = signer.getPublicKey().toSuiAddress();
16863
+ tx.setSender(sender);
16864
+ await setFreshGasPayment(suiClient, tx, sender);
16865
+ for (let attempt = 0; attempt < 2; attempt++) {
16866
+ try {
16867
+ return await suiClient.signAndExecuteTransaction({
16868
+ signer,
16869
+ transaction: tx,
16870
+ options,
16871
+ });
16872
+ }
16873
+ catch (error) {
16874
+ if (attempt === 0 && isStaleObjectVersionError(error)) {
16875
+ await sleep(STALE_GAS_RETRY_DELAY_MS);
16876
+ await setFreshGasPayment(suiClient, tx, sender);
16877
+ continue;
16878
+ }
16879
+ throw error;
16880
+ }
16881
+ }
16882
+ throw new Error("Transaction failed after refreshing gas payment");
16883
+ }
16884
+
16809
16885
  // Copyright (c) 2025 Dipcoin LLC
16810
16886
  async function executeTxBlock(suiClient, tx, signer) {
16811
- return suiClient.signAndExecuteTransaction({
16812
- signer,
16813
- transaction: tx,
16814
- options: {
16815
- showObjectChanges: true,
16816
- showEffects: true,
16817
- showEvents: true,
16818
- showInput: true,
16819
- },
16887
+ return signAndExecuteTransactionWithFreshGas(suiClient, tx, signer, {
16888
+ showObjectChanges: true,
16889
+ showEffects: true,
16890
+ showEvents: true,
16891
+ showInput: true,
16820
16892
  });
16821
16893
  }
16822
16894
  function getDeploymentPerpetualID(deployment, market) {
@@ -16825,7 +16897,8 @@ function getDeploymentPerpetualID(deployment, market) {
16825
16897
  async function getOraclePrice(suiClient, deployment, market) {
16826
16898
  const objId = getPriceOracleObjectId(deployment, market);
16827
16899
  const obj = await suiClient.getObject({ id: objId, options: { showContent: true } });
16828
- const fields = obj.data?.content?.fields?.price_info?.fields?.price_feed?.fields?.price?.fields;
16900
+ const fields = obj.data?.content?.fields?.price_info?.fields?.price_feed?.fields?.price
16901
+ ?.fields;
16829
16902
  if (!fields)
16830
16903
  throw new Error(`Failed to read oracle price for ${market}`);
16831
16904
  return Number(fields.price.fields.magnitude) / Math.pow(10, Number(fields.expo.fields.magnitude));
@@ -17627,7 +17700,8 @@ class DipCoinPerpSDK {
17627
17700
  }
17628
17701
  // Use sub-account keypair for signing if available
17629
17702
  const signingKeypair = this.subKeypair || this.keypair;
17630
- const { symbol, market, side, isLong, leverage, quantity, reduceOnly = true, postOnly = false, orderbookOnly = true, ioc = false, tp, sl, } = params;
17703
+ const { symbol, market, creator, side, isLong, leverage, quantity, reduceOnly = true, postOnly = false, orderbookOnly = true, ioc = false, tp, sl, } = params;
17704
+ const orderCreator = creator || this.walletAddress;
17631
17705
  if (!this.isPositiveNumber(quantity)) {
17632
17706
  return {
17633
17707
  status: false,
@@ -17651,7 +17725,7 @@ class DipCoinPerpSDK {
17651
17725
  symbol,
17652
17726
  side,
17653
17727
  leverage: leverageWei,
17654
- creator: this.walletAddress,
17728
+ creator: orderCreator,
17655
17729
  };
17656
17730
  const sendPlanCloseRequest = async (payload) => {
17657
17731
  let response = await this.httpClient.post(API_ENDPOINTS.PLAN_CLOSE_ORDER, payload);
@@ -17681,7 +17755,7 @@ class DipCoinPerpSDK {
17681
17755
  : new BigNumber__default["default"](0);
17682
17756
  const tpOrder = {
17683
17757
  market,
17684
- creator: this.walletAddress,
17758
+ creator: orderCreator,
17685
17759
  isLong: !isLong,
17686
17760
  reduceOnly,
17687
17761
  postOnly,
@@ -17726,7 +17800,7 @@ class DipCoinPerpSDK {
17726
17800
  : new BigNumber__default["default"](0);
17727
17801
  const slOrder = {
17728
17802
  market,
17729
- creator: this.walletAddress,
17803
+ creator: orderCreator,
17730
17804
  isLong: !isLong,
17731
17805
  reduceOnly,
17732
17806
  postOnly,
@@ -17784,9 +17858,7 @@ class DipCoinPerpSDK {
17784
17858
  return {
17785
17859
  status: false,
17786
17860
  data: results,
17787
- error: results.tpResult?.message ||
17788
- results.slResult?.message ||
17789
- "Failed to place TP/SL order",
17861
+ error: results.tpResult?.message || results.slResult?.message || "Failed to place TP/SL order",
17790
17862
  };
17791
17863
  }
17792
17864
  catch (error) {
@@ -17800,7 +17872,7 @@ class DipCoinPerpSDK {
17800
17872
  /**
17801
17873
  * Get TP/SL orders for a position
17802
17874
  */
17803
- async getPositionTpSl(positionId, tpslType = "normal") {
17875
+ async getPositionTpSl(positionId, tpslType = "normal", parentAddress) {
17804
17876
  try {
17805
17877
  const authResult = await this.authenticate();
17806
17878
  if (!authResult.status) {
@@ -17812,6 +17884,7 @@ class DipCoinPerpSDK {
17812
17884
  const params = {
17813
17885
  positionId,
17814
17886
  tpslType,
17887
+ ...(parentAddress ? { parentAddress } : {}),
17815
17888
  };
17816
17889
  let response = await this.httpClient.get(API_ENDPOINTS.GET_POSITION_TPSL, { params });
17817
17890
  if (response.code === 1000) {
@@ -18355,12 +18428,8 @@ class DipCoinPerpSDK {
18355
18428
  tpOrderPrice: toNormal(raw.tpOrderPrice),
18356
18429
  slTriggerPrice: toNormal(raw.slTriggerPrice),
18357
18430
  slOrderPrice: toNormal(raw.slOrderPrice),
18358
- tpPlanId: planOrderType === "takeProfit"
18359
- ? raw.tpPlanId ?? raw.id ?? null
18360
- : raw.tpPlanId ?? null,
18361
- slPlanId: planOrderType === "stopLoss"
18362
- ? raw.slPlanId ?? raw.id ?? null
18363
- : raw.slPlanId ?? null,
18431
+ tpPlanId: planOrderType === "takeProfit" ? raw.tpPlanId ?? raw.id ?? null : raw.tpPlanId ?? null,
18432
+ slPlanId: planOrderType === "stopLoss" ? raw.slPlanId ?? raw.id ?? null : raw.slPlanId ?? null,
18364
18433
  tpslType: raw.tpslType,
18365
18434
  createdAt: raw.createdAt,
18366
18435
  updatedAt: raw.updatedAt,
@@ -18713,7 +18782,7 @@ class DipCoinPerpSDK {
18713
18782
  * Build ExchangeOnChain call args for margin adjustments
18714
18783
  */
18715
18784
  buildMarginCallArgs(params, action) {
18716
- const { amount, accountAddress, symbol, market, perpId, subAccountsMapId, gasBudget, txHash, } = params;
18785
+ const { amount, accountAddress, symbol, market, perpId, subAccountsMapId, gasBudget, txHash } = params;
18717
18786
  if (!this.isPositiveNumber(amount)) {
18718
18787
  throw new Error(`Amount must be greater than zero to ${action} margin`);
18719
18788
  }
@@ -18869,7 +18938,8 @@ class DipCoinPerpSDK {
18869
18938
  }
18870
18939
  async buildMarginTransaction(params, action) {
18871
18940
  const payload = this.buildMarginCallArgs(params, action);
18872
- const signedMarket = payload.perpID || (payload.market ? this.resolvePerpIdFromDeployment(payload.market) : undefined);
18941
+ const signedMarket = payload.perpID ||
18942
+ (payload.market ? this.resolvePerpIdFromDeployment(payload.market) : undefined);
18873
18943
  if (!signedMarket) {
18874
18944
  throw new Error("PerpetualID is required for signed margin payload");
18875
18945
  }
@@ -19106,7 +19176,10 @@ class DipCoinPerpSDK {
19106
19176
  if (!metadata) {
19107
19177
  return { status: false, error: "Coin metadata not found" };
19108
19178
  }
19109
- return { status: true, data: { decimals: metadata.decimals, symbol: metadata.symbol, name: metadata.name } };
19179
+ return {
19180
+ status: true,
19181
+ data: { decimals: metadata.decimals, symbol: metadata.symbol, name: metadata.name },
19182
+ };
19110
19183
  }
19111
19184
  catch (error) {
19112
19185
  return { status: false, error: formatError(error) };
@@ -19220,7 +19293,8 @@ class DipCoinPerpSDK {
19220
19293
  // to catch up before submitting the PTB. Public RPC backends can disagree by
19221
19294
  // a few seconds, so target a timestamp that is already ~10s old.
19222
19295
  const start = Date.now();
19223
- while (true) {
19296
+ const deadline = start + 180_000;
19297
+ while (Date.now() <= deadline) {
19224
19298
  const clock = await this.suiClient.getObject({
19225
19299
  id: "0x6",
19226
19300
  options: { showContent: true },
@@ -19231,7 +19305,7 @@ class DipCoinPerpSDK {
19231
19305
  const waitMs = timestamp - clockMs + 10_000;
19232
19306
  if (waitMs <= 0)
19233
19307
  return;
19234
- if (Date.now() - start + waitMs > 180_000) {
19308
+ if (Date.now() + waitMs > deadline) {
19235
19309
  throw new Error(`Signed price feed is too far ahead of Sui Clock (${Math.ceil(waitMs / 1000)}s). Try again later.`);
19236
19310
  }
19237
19311
  await this.sleep(Math.min(waitMs, 15_000));
@@ -19244,7 +19318,8 @@ class DipCoinPerpSDK {
19244
19318
  const maxTimestamp = Math.max(...timestamps);
19245
19319
  const minTimestamp = Math.min(...timestamps);
19246
19320
  const start = Date.now();
19247
- while (true) {
19321
+ const deadline = start + 180_000;
19322
+ while (Date.now() <= deadline) {
19248
19323
  const clock = await this.suiClient.getObject({
19249
19324
  id: "0x6",
19250
19325
  options: { showContent: true },
@@ -19259,7 +19334,7 @@ class DipCoinPerpSDK {
19259
19334
  }
19260
19335
  return;
19261
19336
  }
19262
- if (Date.now() - start + waitMs > 180_000) {
19337
+ if (Date.now() + waitMs > deadline) {
19263
19338
  throw new Error(`Signed price feed is too far ahead of Sui Clock (${Math.ceil(waitMs / 1000)}s). Try again later.`);
19264
19339
  }
19265
19340
  await this.sleep(Math.min(waitMs, 15_000));
@@ -19338,10 +19413,7 @@ class DipCoinPerpSDK {
19338
19413
  await this.sleep(2_000 * (attempt + 1));
19339
19414
  continue;
19340
19415
  }
19341
- return Array.from(new Map(entries.map((feed) => [
19342
- Buffer.from(feed.payload).toString("hex"),
19343
- feed,
19344
- ])).values());
19416
+ return Array.from(new Map(entries.map((feed) => [Buffer.from(feed.payload).toString("hex"), feed])).values());
19345
19417
  }
19346
19418
  throw lastClockError || new Error("Failed to fetch usable signed price feed chunks");
19347
19419
  }
@@ -19444,11 +19516,9 @@ class DipCoinPerpSDK {
19444
19516
  return { nav, tx: t };
19445
19517
  }
19446
19518
  async signAndExecuteVaultTx(tx) {
19447
- tx.setSender(this.keypair.getPublicKey().toSuiAddress());
19448
- return await this.suiClient.signAndExecuteTransaction({
19449
- signer: this.keypair,
19450
- transaction: tx,
19451
- options: { showEffects: true, showObjectChanges: true },
19519
+ return signAndExecuteTransactionWithFreshGas(this.suiClient, tx, this.keypair, {
19520
+ showEffects: true,
19521
+ showObjectChanges: true,
19452
19522
  });
19453
19523
  }
19454
19524
  /**
@@ -20146,9 +20216,13 @@ function tryAutoBindReferral(sdk) {
20146
20216
  try {
20147
20217
  fs__default["default"].writeFileSync(markerPath, "");
20148
20218
  }
20149
- catch { }
20219
+ catch {
20220
+ // Marker creation is best-effort; retrying referral binding is harmless.
20221
+ }
20150
20222
  })
20151
- .catch(() => { });
20223
+ .catch(() => {
20224
+ // Auto-binding should never block normal CLI startup.
20225
+ });
20152
20226
  }
20153
20227
  /**
20154
20228
  * Get or create the SDK instance (singleton).
@@ -20668,6 +20742,9 @@ function registerPositionCommands(program) {
20668
20742
  .option("--sl-trigger <price>", "SL trigger price")
20669
20743
  .option("--sl-type <type>", "SL order type: market or limit", "market")
20670
20744
  .option("--sl-price <price>", "SL order price (for limit)")
20745
+ .option("--vault <address>", "Target a vault position (vault object ID)")
20746
+ .option("--tp-plan-id <id>", "Existing TP plan ID to edit")
20747
+ .option("--sl-plan-id <id>", "Existing SL plan ID to edit")
20671
20748
  .action(async (symbol, opts) => {
20672
20749
  try {
20673
20750
  const sdk = getSDK();
@@ -20675,11 +20752,94 @@ function registerPositionCommands(program) {
20675
20752
  const perpId = await sdk.getPerpetualID(symbol);
20676
20753
  if (!perpId)
20677
20754
  return handleError(`PerpetualID not found for ${symbol}`);
20678
- const side = opts.side.toUpperCase() === "BUY" ? OrderSide.BUY : OrderSide.SELL;
20755
+ const sideInput = String(opts.side).toUpperCase();
20756
+ if (sideInput !== OrderSide.BUY && sideInput !== OrderSide.SELL) {
20757
+ return handleError(`--side must be buy or sell, got ${opts.side}`);
20758
+ }
20759
+ const side = sideInput;
20679
20760
  const isLong = side === OrderSide.SELL;
20761
+ if (!opts.tpTrigger && !opts.slTrigger) {
20762
+ return handleError("At least one of --tp-trigger or --sl-trigger is required.");
20763
+ }
20764
+ if (opts.tpPlanId && !opts.tpTrigger) {
20765
+ return handleError("--tp-plan-id requires --tp-trigger.");
20766
+ }
20767
+ if (opts.slPlanId && !opts.slTrigger) {
20768
+ return handleError("--sl-plan-id requires --sl-trigger.");
20769
+ }
20770
+ let tpPlanId = opts.tpPlanId;
20771
+ let slPlanId = opts.slPlanId;
20772
+ const shouldFindTpPlan = Boolean(opts.tpTrigger && !tpPlanId);
20773
+ const shouldFindSlPlan = Boolean(opts.slTrigger && !slPlanId);
20774
+ const parentAddress = opts.vault || sdk.address;
20775
+ const positionsResult = await sdk.getPositions({ parentAddress, symbol });
20776
+ if (!positionsResult.status) {
20777
+ return handleError(positionsResult.error || "Failed to fetch position");
20778
+ }
20779
+ const matchingPositions = (positionsResult.data || []).filter((position) => position.symbol === symbol);
20780
+ if (matchingPositions.length !== 1) {
20781
+ return handleError(matchingPositions.length === 0
20782
+ ? `No open position for ${symbol}.`
20783
+ : `Multiple positions found for ${symbol}; cannot choose one safely.`);
20784
+ }
20785
+ const activePosition = matchingPositions[0];
20786
+ const positionSide = String(activePosition.side).toUpperCase();
20787
+ const expectedClosingSide = positionSide === "BUY" || positionSide === "LONG"
20788
+ ? OrderSide.SELL
20789
+ : positionSide === "SELL" || positionSide === "SHORT"
20790
+ ? OrderSide.BUY
20791
+ : undefined;
20792
+ if (!expectedClosingSide) {
20793
+ return handleError(`Unsupported position side: ${activePosition.side}`);
20794
+ }
20795
+ if (side !== expectedClosingSide) {
20796
+ return handleError(`--side must be ${expectedClosingSide.toLowerCase()} to close a ${positionSide} position.`);
20797
+ }
20798
+ const requestedQuantity = new BigNumber__default["default"](opts.quantity);
20799
+ const positionQuantity = new BigNumber__default["default"](activePosition.quantity).shiftedBy(-18);
20800
+ if (!requestedQuantity.isFinite() ||
20801
+ requestedQuantity.lte(0) ||
20802
+ requestedQuantity.gt(positionQuantity)) {
20803
+ return handleError(`--quantity must be greater than 0 and no more than the position quantity (${positionQuantity.toFixed()}).`);
20804
+ }
20805
+ const requestedLeverage = new BigNumber__default["default"](opts.leverage);
20806
+ const positionLeverage = new BigNumber__default["default"](activePosition.leverage).shiftedBy(-18);
20807
+ if (!requestedLeverage.isFinite() || !requestedLeverage.eq(positionLeverage)) {
20808
+ return handleError(`--leverage must match the position leverage (${positionLeverage.toFixed()}).`);
20809
+ }
20810
+ // Editing a plan requires its existing ID. Resolve it automatically for the
20811
+ // position-wide TP/SL pair so repeating this command updates instead of duplicates.
20812
+ if (shouldFindTpPlan || shouldFindSlPlan) {
20813
+ const positionId = activePosition.id ?? activePosition.positionId;
20814
+ if (positionId === undefined || positionId === null) {
20815
+ return handleError(`Position ID missing for ${symbol}.`);
20816
+ }
20817
+ const plansResult = await sdk.getPositionTpSl(positionId, "position", opts.vault);
20818
+ if (!plansResult.status) {
20819
+ return handleError(plansResult.error || "Failed to fetch existing TP/SL orders");
20820
+ }
20821
+ const findExistingPlanId = (planOrderType) => {
20822
+ const matches = (plansResult.data || []).filter((order) => String(order.planOrderType).toLowerCase() === planOrderType.toLowerCase());
20823
+ if (matches.length > 1) {
20824
+ throw new Error(`Multiple ${planOrderType} plans found; use --${planOrderType === "takeProfit" ? "tp" : "sl"}-plan-id to choose one.`);
20825
+ }
20826
+ if (!matches.length)
20827
+ return undefined;
20828
+ const planId = planOrderType === "takeProfit" ? matches[0].tpPlanId : matches[0].slPlanId;
20829
+ if (planId === undefined || planId === null) {
20830
+ throw new Error(`${planOrderType} plan is missing its editable plan ID.`);
20831
+ }
20832
+ return planId;
20833
+ };
20834
+ if (shouldFindTpPlan)
20835
+ tpPlanId = findExistingPlanId("takeProfit");
20836
+ if (shouldFindSlPlan)
20837
+ slPlanId = findExistingPlanId("stopLoss");
20838
+ }
20680
20839
  const params = {
20681
20840
  symbol,
20682
20841
  market: perpId,
20842
+ ...(opts.vault ? { creator: opts.vault } : {}),
20683
20843
  side,
20684
20844
  isLong,
20685
20845
  quantity: opts.quantity,
@@ -20690,6 +20850,7 @@ function registerPositionCommands(program) {
20690
20850
  triggerPrice: opts.tpTrigger,
20691
20851
  orderType: opts.tpType?.toUpperCase() === "LIMIT" ? OrderType.LIMIT : OrderType.MARKET,
20692
20852
  ...(opts.tpPrice ? { orderPrice: opts.tpPrice } : {}),
20853
+ ...(tpPlanId !== undefined ? { planId: tpPlanId } : {}),
20693
20854
  tpslType: "position",
20694
20855
  };
20695
20856
  }
@@ -20698,6 +20859,7 @@ function registerPositionCommands(program) {
20698
20859
  triggerPrice: opts.slTrigger,
20699
20860
  orderType: opts.slType?.toUpperCase() === "LIMIT" ? OrderType.LIMIT : OrderType.MARKET,
20700
20861
  ...(opts.slPrice ? { orderPrice: opts.slPrice } : {}),
20862
+ ...(slPlanId !== undefined ? { planId: slPlanId } : {}),
20701
20863
  tpslType: "position",
20702
20864
  };
20703
20865
  }
@@ -20831,7 +20993,10 @@ function registerMarketCommands(program) {
20831
20993
  const ob = result.data;
20832
20994
  console.log(`\n Order Book: ${symbol}`);
20833
20995
  console.log(" --- Asks (sell) ---");
20834
- ob.asks.slice(0, 10).reverse().forEach((a) => {
20996
+ ob.asks
20997
+ .slice(0, 10)
20998
+ .reverse()
20999
+ .forEach((a) => {
20835
21000
  console.log(` ${formatWei(a.price).padStart(14)} | ${formatWei(a.quantity)}`);
20836
21001
  });
20837
21002
  console.log(" --- Bids (buy) ---");
@@ -21138,7 +21303,9 @@ function registerVaultCommands(program) {
21138
21303
  return handleError(result.error);
21139
21304
  let vaults = result.data || [];
21140
21305
  if (!vaults.length)
21141
- return isJson(program) ? printJson({ records: [], total: 0, pageNum: 1, pageSize: 10 }) : console.log("No vaults found.");
21306
+ return isJson(program)
21307
+ ? printJson({ records: [], total: 0, pageNum: 1, pageSize: 10 })
21308
+ : console.log("No vaults found.");
21142
21309
  // Client-side filter
21143
21310
  const filter = opts.filter;
21144
21311
  if (filter && filter !== "All") {
@@ -21166,7 +21333,16 @@ function registerVaultCommands(program) {
21166
21333
  return printJson({ records: pageVaults, total, pageNum, pageSize, totalPages });
21167
21334
  if (!pageVaults.length)
21168
21335
  return console.log(`No vaults on page ${pageNum}. Total: ${total}, pages: ${totalPages}.`);
21169
- printTable(["Name", "Vault ID", "TVL (USDC)", "APR (%)", "Depositors", "Age (d)", "Deposit", "Status"], pageVaults.map((v) => {
21336
+ printTable([
21337
+ "Name",
21338
+ "Vault ID",
21339
+ "TVL (USDC)",
21340
+ "APR (%)",
21341
+ "Depositors",
21342
+ "Age (d)",
21343
+ "Deposit",
21344
+ "Status",
21345
+ ], pageVaults.map((v) => {
21170
21346
  const tvl = new BigNumber__default["default"](v.tvl || "0").dividedBy(new BigNumber__default["default"](10).pow(18)).toFixed(2);
21171
21347
  const apr = new BigNumber__default["default"](v.apr || "0").dividedBy(new BigNumber__default["default"](10).pow(14)).toFixed(2);
21172
21348
  const depositors = new BigNumber__default["default"](v.currentDepositors || "0")
@@ -21208,7 +21384,10 @@ function registerVaultCommands(program) {
21208
21384
  ["Name", d.name || "-"],
21209
21385
  ["Creator", d.creator || "-"],
21210
21386
  ["Trader", d.trader || "-"],
21211
- ["Deposit Status", d.deposit_status === true || d.deposit_status === "true" ? "Open" : "Closed"],
21387
+ [
21388
+ "Deposit Status",
21389
+ d.deposit_status === true || d.deposit_status === "true" ? "Open" : "Closed",
21390
+ ],
21212
21391
  ["Total Shares", formatWeiValue(d.total_shares)],
21213
21392
  ["Max Cap", formatWeiValue(d.max_cap)],
21214
21393
  ["Min Deposit", formatWeiValue(d.min_deposit_amount)],
@@ -21480,7 +21659,10 @@ function registerVaultCommands(program) {
21480
21659
  .action(async (vaultId, amount) => {
21481
21660
  try {
21482
21661
  const sdk = getSDK();
21483
- const tx = await sdk.setVaultMinDepositAmount({ vaultID: vaultId, minDepositAmount: parseAmount(amount) });
21662
+ const tx = await sdk.setVaultMinDepositAmount({
21663
+ vaultID: vaultId,
21664
+ minDepositAmount: parseAmount(amount),
21665
+ });
21484
21666
  printTxResult(program, tx, `Min deposit set to ${amount} USDC.`);
21485
21667
  }
21486
21668
  catch (e) {
@@ -21497,7 +21679,10 @@ function registerVaultCommands(program) {
21497
21679
  try {
21498
21680
  const sdk = getSDK();
21499
21681
  const enabled = !opts.disable;
21500
- const tx = await sdk.setVaultAutoCloseOnWithdraw({ vaultID: vaultId, autoCloseOnWithdraw: enabled });
21682
+ const tx = await sdk.setVaultAutoCloseOnWithdraw({
21683
+ vaultID: vaultId,
21684
+ autoCloseOnWithdraw: enabled,
21685
+ });
21501
21686
  printTxResult(program, tx, `Auto-close on withdraw ${enabled ? "enabled" : "disabled"}.`);
21502
21687
  }
21503
21688
  catch (e) {