dipcoin-cli 1.3.4 → 1.3.5

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/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));
@@ -17784,9 +17857,7 @@ class DipCoinPerpSDK {
17784
17857
  return {
17785
17858
  status: false,
17786
17859
  data: results,
17787
- error: results.tpResult?.message ||
17788
- results.slResult?.message ||
17789
- "Failed to place TP/SL order",
17860
+ error: results.tpResult?.message || results.slResult?.message || "Failed to place TP/SL order",
17790
17861
  };
17791
17862
  }
17792
17863
  catch (error) {
@@ -18355,12 +18426,8 @@ class DipCoinPerpSDK {
18355
18426
  tpOrderPrice: toNormal(raw.tpOrderPrice),
18356
18427
  slTriggerPrice: toNormal(raw.slTriggerPrice),
18357
18428
  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,
18429
+ tpPlanId: planOrderType === "takeProfit" ? raw.tpPlanId ?? raw.id ?? null : raw.tpPlanId ?? null,
18430
+ slPlanId: planOrderType === "stopLoss" ? raw.slPlanId ?? raw.id ?? null : raw.slPlanId ?? null,
18364
18431
  tpslType: raw.tpslType,
18365
18432
  createdAt: raw.createdAt,
18366
18433
  updatedAt: raw.updatedAt,
@@ -18713,7 +18780,7 @@ class DipCoinPerpSDK {
18713
18780
  * Build ExchangeOnChain call args for margin adjustments
18714
18781
  */
18715
18782
  buildMarginCallArgs(params, action) {
18716
- const { amount, accountAddress, symbol, market, perpId, subAccountsMapId, gasBudget, txHash, } = params;
18783
+ const { amount, accountAddress, symbol, market, perpId, subAccountsMapId, gasBudget, txHash } = params;
18717
18784
  if (!this.isPositiveNumber(amount)) {
18718
18785
  throw new Error(`Amount must be greater than zero to ${action} margin`);
18719
18786
  }
@@ -18869,7 +18936,8 @@ class DipCoinPerpSDK {
18869
18936
  }
18870
18937
  async buildMarginTransaction(params, action) {
18871
18938
  const payload = this.buildMarginCallArgs(params, action);
18872
- const signedMarket = payload.perpID || (payload.market ? this.resolvePerpIdFromDeployment(payload.market) : undefined);
18939
+ const signedMarket = payload.perpID ||
18940
+ (payload.market ? this.resolvePerpIdFromDeployment(payload.market) : undefined);
18873
18941
  if (!signedMarket) {
18874
18942
  throw new Error("PerpetualID is required for signed margin payload");
18875
18943
  }
@@ -19106,7 +19174,10 @@ class DipCoinPerpSDK {
19106
19174
  if (!metadata) {
19107
19175
  return { status: false, error: "Coin metadata not found" };
19108
19176
  }
19109
- return { status: true, data: { decimals: metadata.decimals, symbol: metadata.symbol, name: metadata.name } };
19177
+ return {
19178
+ status: true,
19179
+ data: { decimals: metadata.decimals, symbol: metadata.symbol, name: metadata.name },
19180
+ };
19110
19181
  }
19111
19182
  catch (error) {
19112
19183
  return { status: false, error: formatError(error) };
@@ -19220,7 +19291,8 @@ class DipCoinPerpSDK {
19220
19291
  // to catch up before submitting the PTB. Public RPC backends can disagree by
19221
19292
  // a few seconds, so target a timestamp that is already ~10s old.
19222
19293
  const start = Date.now();
19223
- while (true) {
19294
+ const deadline = start + 180_000;
19295
+ while (Date.now() <= deadline) {
19224
19296
  const clock = await this.suiClient.getObject({
19225
19297
  id: "0x6",
19226
19298
  options: { showContent: true },
@@ -19231,7 +19303,7 @@ class DipCoinPerpSDK {
19231
19303
  const waitMs = timestamp - clockMs + 10_000;
19232
19304
  if (waitMs <= 0)
19233
19305
  return;
19234
- if (Date.now() - start + waitMs > 180_000) {
19306
+ if (Date.now() + waitMs > deadline) {
19235
19307
  throw new Error(`Signed price feed is too far ahead of Sui Clock (${Math.ceil(waitMs / 1000)}s). Try again later.`);
19236
19308
  }
19237
19309
  await this.sleep(Math.min(waitMs, 15_000));
@@ -19244,7 +19316,8 @@ class DipCoinPerpSDK {
19244
19316
  const maxTimestamp = Math.max(...timestamps);
19245
19317
  const minTimestamp = Math.min(...timestamps);
19246
19318
  const start = Date.now();
19247
- while (true) {
19319
+ const deadline = start + 180_000;
19320
+ while (Date.now() <= deadline) {
19248
19321
  const clock = await this.suiClient.getObject({
19249
19322
  id: "0x6",
19250
19323
  options: { showContent: true },
@@ -19259,7 +19332,7 @@ class DipCoinPerpSDK {
19259
19332
  }
19260
19333
  return;
19261
19334
  }
19262
- if (Date.now() - start + waitMs > 180_000) {
19335
+ if (Date.now() + waitMs > deadline) {
19263
19336
  throw new Error(`Signed price feed is too far ahead of Sui Clock (${Math.ceil(waitMs / 1000)}s). Try again later.`);
19264
19337
  }
19265
19338
  await this.sleep(Math.min(waitMs, 15_000));
@@ -19338,10 +19411,7 @@ class DipCoinPerpSDK {
19338
19411
  await this.sleep(2_000 * (attempt + 1));
19339
19412
  continue;
19340
19413
  }
19341
- return Array.from(new Map(entries.map((feed) => [
19342
- Buffer.from(feed.payload).toString("hex"),
19343
- feed,
19344
- ])).values());
19414
+ return Array.from(new Map(entries.map((feed) => [Buffer.from(feed.payload).toString("hex"), feed])).values());
19345
19415
  }
19346
19416
  throw lastClockError || new Error("Failed to fetch usable signed price feed chunks");
19347
19417
  }
@@ -19444,11 +19514,9 @@ class DipCoinPerpSDK {
19444
19514
  return { nav, tx: t };
19445
19515
  }
19446
19516
  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 },
19517
+ return signAndExecuteTransactionWithFreshGas(this.suiClient, tx, this.keypair, {
19518
+ showEffects: true,
19519
+ showObjectChanges: true,
19452
19520
  });
19453
19521
  }
19454
19522
  /**
@@ -20146,9 +20214,13 @@ function tryAutoBindReferral(sdk) {
20146
20214
  try {
20147
20215
  fs__default["default"].writeFileSync(markerPath, "");
20148
20216
  }
20149
- catch { }
20217
+ catch {
20218
+ // Marker creation is best-effort; retrying referral binding is harmless.
20219
+ }
20150
20220
  })
20151
- .catch(() => { });
20221
+ .catch(() => {
20222
+ // Auto-binding should never block normal CLI startup.
20223
+ });
20152
20224
  }
20153
20225
  /**
20154
20226
  * Get or create the SDK instance (singleton).
@@ -20831,7 +20903,10 @@ function registerMarketCommands(program) {
20831
20903
  const ob = result.data;
20832
20904
  console.log(`\n Order Book: ${symbol}`);
20833
20905
  console.log(" --- Asks (sell) ---");
20834
- ob.asks.slice(0, 10).reverse().forEach((a) => {
20906
+ ob.asks
20907
+ .slice(0, 10)
20908
+ .reverse()
20909
+ .forEach((a) => {
20835
20910
  console.log(` ${formatWei(a.price).padStart(14)} | ${formatWei(a.quantity)}`);
20836
20911
  });
20837
20912
  console.log(" --- Bids (buy) ---");
@@ -21138,7 +21213,9 @@ function registerVaultCommands(program) {
21138
21213
  return handleError(result.error);
21139
21214
  let vaults = result.data || [];
21140
21215
  if (!vaults.length)
21141
- return isJson(program) ? printJson({ records: [], total: 0, pageNum: 1, pageSize: 10 }) : console.log("No vaults found.");
21216
+ return isJson(program)
21217
+ ? printJson({ records: [], total: 0, pageNum: 1, pageSize: 10 })
21218
+ : console.log("No vaults found.");
21142
21219
  // Client-side filter
21143
21220
  const filter = opts.filter;
21144
21221
  if (filter && filter !== "All") {
@@ -21166,7 +21243,16 @@ function registerVaultCommands(program) {
21166
21243
  return printJson({ records: pageVaults, total, pageNum, pageSize, totalPages });
21167
21244
  if (!pageVaults.length)
21168
21245
  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) => {
21246
+ printTable([
21247
+ "Name",
21248
+ "Vault ID",
21249
+ "TVL (USDC)",
21250
+ "APR (%)",
21251
+ "Depositors",
21252
+ "Age (d)",
21253
+ "Deposit",
21254
+ "Status",
21255
+ ], pageVaults.map((v) => {
21170
21256
  const tvl = new BigNumber__default["default"](v.tvl || "0").dividedBy(new BigNumber__default["default"](10).pow(18)).toFixed(2);
21171
21257
  const apr = new BigNumber__default["default"](v.apr || "0").dividedBy(new BigNumber__default["default"](10).pow(14)).toFixed(2);
21172
21258
  const depositors = new BigNumber__default["default"](v.currentDepositors || "0")
@@ -21208,7 +21294,10 @@ function registerVaultCommands(program) {
21208
21294
  ["Name", d.name || "-"],
21209
21295
  ["Creator", d.creator || "-"],
21210
21296
  ["Trader", d.trader || "-"],
21211
- ["Deposit Status", d.deposit_status === true || d.deposit_status === "true" ? "Open" : "Closed"],
21297
+ [
21298
+ "Deposit Status",
21299
+ d.deposit_status === true || d.deposit_status === "true" ? "Open" : "Closed",
21300
+ ],
21212
21301
  ["Total Shares", formatWeiValue(d.total_shares)],
21213
21302
  ["Max Cap", formatWeiValue(d.max_cap)],
21214
21303
  ["Min Deposit", formatWeiValue(d.min_deposit_amount)],
@@ -21480,7 +21569,10 @@ function registerVaultCommands(program) {
21480
21569
  .action(async (vaultId, amount) => {
21481
21570
  try {
21482
21571
  const sdk = getSDK();
21483
- const tx = await sdk.setVaultMinDepositAmount({ vaultID: vaultId, minDepositAmount: parseAmount(amount) });
21572
+ const tx = await sdk.setVaultMinDepositAmount({
21573
+ vaultID: vaultId,
21574
+ minDepositAmount: parseAmount(amount),
21575
+ });
21484
21576
  printTxResult(program, tx, `Min deposit set to ${amount} USDC.`);
21485
21577
  }
21486
21578
  catch (e) {
@@ -21497,7 +21589,10 @@ function registerVaultCommands(program) {
21497
21589
  try {
21498
21590
  const sdk = getSDK();
21499
21591
  const enabled = !opts.disable;
21500
- const tx = await sdk.setVaultAutoCloseOnWithdraw({ vaultID: vaultId, autoCloseOnWithdraw: enabled });
21592
+ const tx = await sdk.setVaultAutoCloseOnWithdraw({
21593
+ vaultID: vaultId,
21594
+ autoCloseOnWithdraw: enabled,
21595
+ });
21501
21596
  printTxResult(program, tx, `Auto-close on withdraw ${enabled ? "enabled" : "disabled"}.`);
21502
21597
  }
21503
21598
  catch (e) {