@depthhq/maker-sdk 0.1.13 → 0.1.14

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.
@@ -39,6 +39,7 @@ export type HedgeReceipt = {
39
39
  status: "filled" | "cancelled" | "rejected" | "open" | "unknown";
40
40
  orderId?: number;
41
41
  filledSize: bigint;
42
+ filledAt?: number;
42
43
  averagePriceE8?: bigint;
43
44
  fee?: bigint;
44
45
  hashes?: string[];
package/dist/index.js CHANGED
@@ -26419,7 +26419,7 @@ function order(value, receipt = false) {
26419
26419
  return false;
26420
26420
  if (!receipt)
26421
26421
  return true;
26422
- return ["filled", "cancelled", "rejected"].includes(String(value.status)) && integer(value.completedAt) && value.completedAt >= value.nonce && amount(value.filledSize) && BigInt(value.filledSize) >= 0n && BigInt(value.filledSize) <= BigInt(value.size) && optional(value.orderId, integer) && optional(value.averagePriceE8, amount) && optional(value.fee, amount) && optional(value.reason, text) && optional(value.hashes, (hashes) => Array.isArray(hashes) && hashes.length <= 2000 && hashes.every((hash) => typeof hash === "string" && /^0x[0-9a-fA-F]{64}$/.test(hash)));
26422
+ return ["filled", "cancelled", "rejected"].includes(String(value.status)) && integer(value.completedAt) && value.completedAt >= value.nonce && amount(value.filledSize) && BigInt(value.filledSize) >= 0n && BigInt(value.filledSize) <= BigInt(value.size) && (value.filledAt === undefined || integer(value.filledAt) && value.filledAt >= value.nonce - 1000 && value.filledAt <= value.completedAt + 1000) && optional(value.orderId, integer) && optional(value.averagePriceE8, amount) && optional(value.fee, amount) && optional(value.reason, text) && optional(value.hashes, (hashes) => Array.isArray(hashes) && hashes.length <= 2000 && hashes.every((hash) => typeof hash === "string" && /^0x[0-9a-fA-F]{64}$/.test(hash)));
26423
26423
  }
26424
26424
  function hedgeView(value, owner) {
26425
26425
  if (!object(value) || value.maker !== owner || typeof value.enabled !== "boolean")
@@ -24933,7 +24933,7 @@ function order(value, receipt = false) {
24933
24933
  return false;
24934
24934
  if (!receipt)
24935
24935
  return true;
24936
- return ["filled", "cancelled", "rejected"].includes(String(value.status)) && integer(value.completedAt) && value.completedAt >= value.nonce && amount(value.filledSize) && BigInt(value.filledSize) >= 0n && BigInt(value.filledSize) <= BigInt(value.size) && optional(value.orderId, integer) && optional(value.averagePriceE8, amount) && optional(value.fee, amount) && optional(value.reason, text) && optional(value.hashes, (hashes) => Array.isArray(hashes) && hashes.length <= 2000 && hashes.every((hash) => typeof hash === "string" && /^0x[0-9a-fA-F]{64}$/.test(hash)));
24936
+ return ["filled", "cancelled", "rejected"].includes(String(value.status)) && integer(value.completedAt) && value.completedAt >= value.nonce && amount(value.filledSize) && BigInt(value.filledSize) >= 0n && BigInt(value.filledSize) <= BigInt(value.size) && (value.filledAt === undefined || integer(value.filledAt) && value.filledAt >= value.nonce - 1000 && value.filledAt <= value.completedAt + 1000) && optional(value.orderId, integer) && optional(value.averagePriceE8, amount) && optional(value.fee, amount) && optional(value.reason, text) && optional(value.hashes, (hashes) => Array.isArray(hashes) && hashes.length <= 2000 && hashes.every((hash) => typeof hash === "string" && /^0x[0-9a-fA-F]{64}$/.test(hash)));
24937
24937
  }
24938
24938
  function hedgeView(value, owner) {
24939
24939
  if (!object(value) || value.maker !== owner || typeof value.enabled !== "boolean")
package/dist/node.js CHANGED
@@ -180,7 +180,7 @@ class BotStore {
180
180
  if (!/^0x[0-9a-f]{32}$/.test(order.cloid) || !Number.isSafeInteger(order.nonce) || order.nonce < 0 || !Number.isSafeInteger(order.expiresAt) || order.expiresAt <= order.nonce || typeof order.buy !== "boolean" || typeof order.reduceOnly !== "boolean" || typeof order.size !== "bigint" || order.size <= 0n || typeof order.limitPriceE8 !== "bigint" || order.limitPriceE8 <= 0n)
181
181
  throw new Error("Hedge checkpoint order is invalid");
182
182
  for (const record of hedge.history)
183
- if (!["filled", "cancelled", "rejected"].includes(record.status) || typeof record.filledSize !== "bigint" || record.filledSize < 0n || record.filledSize > record.size || !Number.isSafeInteger(record.completedAt) || record.completedAt < record.nonce || record.orderId !== undefined && (!Number.isSafeInteger(record.orderId) || record.orderId < 0))
183
+ if (!["filled", "cancelled", "rejected"].includes(record.status) || typeof record.filledSize !== "bigint" || record.filledSize < 0n || record.filledSize > record.size || !Number.isSafeInteger(record.completedAt) || record.completedAt < record.nonce || record.filledAt !== undefined && (!Number.isSafeInteger(record.filledAt) || record.filledAt < record.nonce - 1000 || record.filledAt > record.completedAt + 1000) || record.orderId !== undefined && (!Number.isSafeInteger(record.orderId) || record.orderId < 0))
184
184
  throw new Error("Hedge checkpoint receipt is invalid");
185
185
  }
186
186
  return state;
@@ -454,8 +454,10 @@ class MakerBot {
454
454
  async hedgeTick() {
455
455
  if (!this.hedge)
456
456
  return;
457
- const account = await this.maker.read("MarketAccount", this.maker.marketAccount(), "finalized");
458
- const confirmed = await this.maker.read("MarketAccount", this.maker.marketAccount());
457
+ const [account, confirmed] = await Promise.all([
458
+ this.maker.read("MarketAccount", this.maker.marketAccount(), "finalized"),
459
+ this.maker.read("MarketAccount", this.maker.marketAccount())
460
+ ]);
459
461
  const write = this.state.quoteWrite;
460
462
  if (!this.state.hedge?.pending && (("reserving" in confirmed.status) || ("releasing" in confirmed.status))) {
461
463
  const ids = [
@@ -495,9 +497,14 @@ class MakerBot {
495
497
  if ("ready" in confirmed.status && (!this.position || this.position.status !== "ready" || this.position.position === undefined || (this.inventoryVersion ?? this.position.version) !== currentVersion && this.position.version !== currentVersion)) {
496
498
  const prior = this.position;
497
499
  this.position = await this.maker.position.summary({ timeoutMs: 0 });
498
- const fresh = await this.maker.read("MarketAccount", this.maker.marketAccount(), "finalized");
499
- const latest = await this.maker.read("MarketAccount", this.maker.marketAccount());
500
- ready = "ready" in fresh.status && "ready" in latest.status && fresh.version.toString() === latest.version.toString() && this.position.status === "ready" && this.position.version === BigInt(fresh.version.toString());
500
+ ready = false;
501
+ if (this.position.status === "ready") {
502
+ const [fresh, latest] = await Promise.all([
503
+ this.maker.read("MarketAccount", this.maker.marketAccount(), "finalized"),
504
+ this.maker.read("MarketAccount", this.maker.marketAccount())
505
+ ]);
506
+ ready = "ready" in fresh.status && "ready" in latest.status && fresh.version.toString() === latest.version.toString() && this.position.version === BigInt(fresh.version.toString());
507
+ }
501
508
  if (ready) {
502
509
  this.inventoryVersion = this.position.version;
503
510
  if (write && this.position.version >= write.version) {
@@ -551,7 +558,10 @@ class MakerBot {
551
558
  await this.cancel(true);
552
559
  return snapshot.reason ?? "hedge reconciliation pending";
553
560
  }
554
- this.state.inventoryPendingSince = undefined;
561
+ if (this.state.inventoryPendingSince !== undefined) {
562
+ this.state.inventoryPendingSince = undefined;
563
+ await this.store.save(this.state);
564
+ }
555
565
  const [book, costs] = await Promise.all([
556
566
  this.hedge.adapter.book(),
557
567
  this.hedge.adapter.costs()
@@ -1147,7 +1157,7 @@ class HedgeEngine {
1147
1157
  if (!Number.isInteger(account.leverage) || account.leverage < 1 || account.leverage > this.policy.maxLeverage)
1148
1158
  throw new Error("External leverage exceeds hedge policy");
1149
1159
  const latest = state.history[state.history.length - 1];
1150
- if (latest && account.timestamp < latest.completedAt)
1160
+ if (latest && account.timestamp < (latest.filledAt ?? latest.completedAt))
1151
1161
  return result("pending", "Waiting for the external account to include the confirmed hedge", account.position);
1152
1162
  if (account.openOrders.length)
1153
1163
  return result("blocked", "Hedge account has unmanaged open orders", account.position);
@@ -1211,7 +1221,7 @@ class HedgeEngine {
1211
1221
  state.pending = undefined;
1212
1222
  await save();
1213
1223
  }
1214
- return result(receipt.status === "rejected" ? "blocked" : "pending", receipt.reason ?? "Hedge submitted; reconciling confirmed exposure", account.position);
1224
+ return result(receipt.status === "rejected" ? "blocked" : "pending", receipt.status === "rejected" ? receipt.reason ?? "Hedge rejected" : state.pending ? "Hedge confirmation pending" : "Hedge submitted; reconciling confirmed exposure", account.position);
1215
1225
  } catch (error) {
1216
1226
  result("blocked", error instanceof Error ? error.message : "External hedge service unavailable");
1217
1227
  throw error;
@@ -1446,7 +1456,7 @@ class HyperliquidAdapter {
1446
1456
  return true;
1447
1457
  });
1448
1458
  const filledSize = matching.reduce((sum, fill) => sum + units(fill.sz, 9), 0n);
1449
- if (matching.some((fill) => fill.side === "B" !== order.buy || units(fill.sz, 9) <= 0n || units(fill.px, 8) <= 0n || fill.feeToken !== "USDC" || !/^0x[0-9a-fA-F]{64}$/.test(fill.hash)))
1459
+ if (matching.some((fill) => fill.side === "B" !== order.buy || units(fill.sz, 9) <= 0n || units(fill.px, 8) <= 0n || !Number.isSafeInteger(fill.time) || fill.time < order.nonce - 1000 || fill.time > Date.now() + 1000 || fill.feeToken !== "USDC" || !/^0x[0-9a-fA-F]{64}$/.test(fill.hash)))
1450
1460
  throw new Error("Hyperliquid fill does not match the hedge order");
1451
1461
  if (filledSize > order.size)
1452
1462
  throw new Error("Hyperliquid filled size exceeds the hedge order");
@@ -1462,6 +1472,7 @@ class HyperliquidAdapter {
1462
1472
  status: detail.status === "filled" ? "filled" : /rejected/i.test(detail.status) ? "rejected" : "cancelled",
1463
1473
  orderId: detail.order.oid,
1464
1474
  filledSize,
1475
+ filledAt: matching.length ? Math.max(...matching.map((fill) => fill.time)) : undefined,
1465
1476
  averagePriceE8: filledSize ? cost / filledSize : undefined,
1466
1477
  fee: matching.reduce((sum, fill) => sum + units(fill.fee, 6), 0n),
1467
1478
  hashes: [...new Set(matching.map((fill) => fill.hash))],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@depthhq/maker-sdk",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },