@mysten-incubation/hashi 0.1.0 → 0.2.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @mysten-incubation/hashi
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 5f9f592: Surface deposit time delay: add `bitcoinDepositTimeDelayMs` to `GovernanceConfig`, `approvalTimestampMs` and `confirmableAtMs` to `DepositInfo`, and `confirmableAtMs` to `DepositHistoryItem`
8
+
9
+ ## 0.1.1
10
+
11
+ ### Patch Changes
12
+
13
+ - 5b3389e: Update README install instructions to use the published npm package
14
+ - 72b6efc: Expand README to document the status, balance, history, fee, polling, and Bitcoin RPC APIs
15
+
3
16
  ## 0.1.0
4
17
 
5
18
  ### Minor Changes
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @mysten-incubation/hashi
2
2
 
3
- TypeScript SDK for the [Hashi](https://github.com/MystenLabs/hashi) protocol a Sui Move bridge that mints `hBTC` against Bitcoin deposits and burns it on withdrawal back to BTC.
3
+ TypeScript SDK for the [Hashi](https://github.com/MystenLabs/hashi) protocol. Hashi is a decentralized Bitcoin collateralization primitive on Sui. Orchestrate native BTC directly from smart contracts—without centralized balance sheets.
4
4
 
5
5
  > [!CAUTION]
6
6
  > **Pre-1.0:** This package is under active development. Minor versions may contain breaking changes until the API stabilizes at 1.0.
package/dist/client.mjs CHANGED
@@ -269,12 +269,17 @@ var HashiClient = class {
269
269
  if (!depositEvent?.json) return null;
270
270
  const parsed = depositEvent.json;
271
271
  let status = "unknown";
272
+ let approvalTimestampMs = null;
273
+ let confirmableAtMs = null;
272
274
  try {
273
- await DepositRequest.get({
275
+ const reqObj = await DepositRequest.get({
274
276
  client: this.#client,
275
277
  objectId: parsed.request_id
276
278
  });
277
- const requestsBagId = (await this.#fetchBitcoinState()).deposit_queue.requests.id;
279
+ if (reqObj.json.approval_timestamp_ms != null) approvalTimestampMs = BigInt(reqObj.json.approval_timestamp_ms);
280
+ const [btcState, config$1] = await Promise.all([this.#fetchBitcoinState(), this.view.all().catch(() => null)]);
281
+ if (approvalTimestampMs !== null && config$1) confirmableAtMs = approvalTimestampMs + config$1.bitcoinDepositTimeDelayMs;
282
+ const requestsBagId = btcState.deposit_queue.requests.id;
278
283
  status = (await this.#client.core.getDynamicField({
279
284
  parentId: requestsBagId,
280
285
  name: {
@@ -293,6 +298,8 @@ var HashiClient = class {
293
298
  btcTxid: reverseTxidBytes(parsed.utxo_id.txid),
294
299
  btcVout: parsed.utxo_id.vout,
295
300
  timestampMs: BigInt(parsed.timestamp_ms),
301
+ approvalTimestampMs,
302
+ confirmableAtMs,
296
303
  status,
297
304
  suiTxDigest
298
305
  };
@@ -393,7 +400,7 @@ var HashiClient = class {
393
400
  };
394
401
  },
395
402
  transactionHistory: async (suiAddress) => {
396
- const btcState = await this.#fetchBitcoinState();
403
+ const [btcState, timeDelayMs] = await Promise.all([this.#fetchBitcoinState(), this.view.all().then((c) => c.bitcoinDepositTimeDelayMs, () => null)]);
397
404
  const confirmedIds = /* @__PURE__ */ new Set();
398
405
  const items = [];
399
406
  const userBagId = await this.#fetchUserRequestsBagId(btcState.user_requests.id, suiAddress);
@@ -401,7 +408,7 @@ var HashiClient = class {
401
408
  const requestIds = await this.#listAllDynamicFieldAddressKeys(userBagId);
402
409
  if (requestIds.length > 0) {
403
410
  const objects = await this.#batchGetObjects(requestIds, { content: true });
404
- const classified = this.#classifyRequestObjects(objects);
411
+ const classified = this.#classifyRequestObjects(objects, timeDelayMs);
405
412
  items.push(...classified.items);
406
413
  await this.#populateWithdrawalBtcTxids(items, classified.withdrawalTxnLookups);
407
414
  for (const id of requestIds) confirmedIds.add(id);
@@ -412,7 +419,7 @@ var HashiClient = class {
412
419
  const pendingIds = (await this.#queryEventRequestIds(suiAddress, depositEventType)).filter((id) => !confirmedIds.has(id));
413
420
  if (pendingIds.length > 0) {
414
421
  const objects = await this.#batchGetObjects(pendingIds, { content: true });
415
- const classified = this.#classifyRequestObjects(objects);
422
+ const classified = this.#classifyRequestObjects(objects, timeDelayMs);
416
423
  items.push(...classified.items);
417
424
  }
418
425
  } catch {}
@@ -637,6 +644,7 @@ var HashiClient = class {
637
644
  bitcoinWithdrawalMinimum,
638
645
  bitcoinConfirmationThreshold: u64("bitcoin_confirmation_threshold"),
639
646
  withdrawalCancellationCooldownMs: u64("withdrawal_cancellation_cooldown_ms"),
647
+ bitcoinDepositTimeDelayMs: u64("bitcoin_deposit_time_delay_ms"),
640
648
  depositMinimum: bitcoinDepositMinimum,
641
649
  worstCaseNetworkFee: bitcoinWithdrawalMinimum - DUST_RELAY_MIN_VALUE
642
650
  };
@@ -803,14 +811,14 @@ var HashiClient = class {
803
811
  * items plus the indices that need a follow-up `WithdrawalTransaction`
804
812
  * fetch to populate `btcTxid`.
805
813
  */
806
- #classifyRequestObjects(objects) {
814
+ #classifyRequestObjects(objects, timeDelayMs) {
807
815
  const items = [];
808
816
  const withdrawalTxnLookups = [];
809
817
  const depositRequestType = `${this.#packageId}::deposit_queue::DepositRequest`;
810
818
  const withdrawalRequestType = `${this.#packageId}::withdrawal_queue::WithdrawalRequest`;
811
819
  for (const obj of objects) {
812
820
  if (obj instanceof Error) continue;
813
- if (obj.type === depositRequestType) items.push(parseDepositHistoryItem(obj.content));
821
+ if (obj.type === depositRequestType) items.push(parseDepositHistoryItem(obj.content, timeDelayMs));
814
822
  else if (obj.type === withdrawalRequestType) {
815
823
  const item = parseWithdrawalHistoryItem(obj.content);
816
824
  items.push(item);
@@ -843,8 +851,9 @@ var HashiClient = class {
843
851
  }
844
852
  }
845
853
  };
846
- function parseDepositHistoryItem(content) {
854
+ function parseDepositHistoryItem(content, timeDelayMs) {
847
855
  const parsed = DepositRequest.parse(content);
856
+ const approvalTimestampMs = parsed.approval_timestamp_ms === null ? null : BigInt(parsed.approval_timestamp_ms);
848
857
  return {
849
858
  kind: "deposit",
850
859
  requestId: parsed.id,
@@ -855,7 +864,8 @@ function parseDepositHistoryItem(content) {
855
864
  btcTxid: reverseTxidBytes(parsed.utxo.id.txid),
856
865
  btcVout: parsed.utxo.id.vout,
857
866
  approved: parsed.approval_cert !== null,
858
- approvalTimestampMs: parsed.approval_timestamp_ms === null ? null : BigInt(parsed.approval_timestamp_ms)
867
+ approvalTimestampMs,
868
+ confirmableAtMs: approvalTimestampMs !== null && timeDelayMs !== null ? approvalTimestampMs + timeDelayMs : null
859
869
  };
860
870
  }
861
871
  function parseWithdrawalHistoryItem(content) {
package/dist/types.d.mts CHANGED
@@ -36,6 +36,7 @@ interface GovernanceConfig {
36
36
  readonly bitcoinWithdrawalMinimum: bigint;
37
37
  readonly bitcoinConfirmationThreshold: bigint;
38
38
  readonly withdrawalCancellationCooldownMs: bigint;
39
+ readonly bitcoinDepositTimeDelayMs: bigint;
39
40
  readonly depositMinimum: bigint;
40
41
  readonly worstCaseNetworkFee: bigint;
41
42
  }
@@ -120,6 +121,8 @@ interface DepositHistoryItem {
120
121
  /** `true` once the committee has approved the deposit. */
121
122
  readonly approved: boolean;
122
123
  readonly approvalTimestampMs: bigint | null;
124
+ /** Earliest wall-clock time (ms since epoch) at which the deposit can be confirmed. `null` until approved. */
125
+ readonly confirmableAtMs: bigint | null;
123
126
  }
124
127
  type WithdrawalStatus = "Requested" | "Approved" | "Processing" | "Signed" | "Confirmed";
125
128
  interface WithdrawalHistoryItem {
@@ -157,6 +160,10 @@ interface DepositInfo {
157
160
  readonly btcVout: number;
158
161
  /** Request timestamp (ms since epoch). */
159
162
  readonly timestampMs: bigint;
163
+ /** Timestamp (ms since epoch) when the committee approved this deposit. `null` if not yet approved. */
164
+ readonly approvalTimestampMs: bigint | null;
165
+ /** Earliest wall-clock time (ms since epoch) at which the deposit can be confirmed. `null` until approved or if the config could not be read. */
166
+ readonly confirmableAtMs: bigint | null;
160
167
  /** Current deposit status. */
161
168
  readonly status: DepositStatus;
162
169
  /** Sui transaction digest that created this request. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mysten-incubation/hashi",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "TypeScript SDK for the Hashi Sui Move smart contracts",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Mysten Labs <build@mystenlabs.com>",