@mysten-incubation/hashi 0.3.0 → 0.4.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.
@@ -1,23 +1,51 @@
1
1
  import { MoveStruct } from "../utils/index.mjs";
2
- import { Bag } from "./deps/sui/bag.mjs";
3
2
  import { Element } from "./deps/sui/group_ops.mjs";
3
+ import { Config } from "./config.mjs";
4
+ import { CommitteeSignature } from "./committee.mjs";
5
+ import { Bag } from "./deps/sui/bag.mjs";
4
6
  import { bcs } from "@mysten/sui/bcs";
5
7
 
6
8
  //#region src/contracts/hashi/committee_set.ts
7
9
  /**************************************************************
8
10
  * THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
9
11
  **************************************************************/
12
+ /**
13
+ * Registry of Hashi committee state: registered member metadata (`MemberInfo`),
14
+ * per-epoch `Committee`s, the current epoch, the MPC threshold public key, and the
15
+ * pending epoch change while a reconfiguration is in flight. Members register (and
16
+ * rotate keys/metadata) here between epochs; `start_reconfig` builds the next
17
+ * committee from Sui's active validator set, and `end_reconfig` activates it —
18
+ * storing the outgoing committee's handoff certificate for non-initial reconfigs.
19
+ */
10
20
  const $moduleName = "@local-pkg/hashi::committee_set";
21
+ const PendingEpochChange = new MoveStruct({
22
+ name: `${$moduleName}::PendingEpochChange`,
23
+ fields: {
24
+ epoch: bcs.u64(),
25
+ committee_handoff_cert: bcs.option(CommitteeSignature)
26
+ }
27
+ });
11
28
  const CommitteeSet = new MoveStruct({
12
29
  name: `${$moduleName}::CommitteeSet`,
13
30
  fields: {
14
31
  members: Bag,
15
32
  epoch: bcs.u64(),
16
33
  committees: Bag,
17
- pending_epoch_change: bcs.option(bcs.u64()),
34
+ pending_epoch_change: bcs.option(PendingEpochChange),
18
35
  mpc_public_key: bcs.vector(bcs.u8())
19
36
  }
20
37
  });
38
+ const CommitteeHandoffKey = new MoveStruct({
39
+ name: `${$moduleName}::CommitteeHandoffKey`,
40
+ fields: { epoch: bcs.u64() }
41
+ });
42
+ const CommitteeHandoff = new MoveStruct({
43
+ name: `${$moduleName}::CommitteeHandoff`,
44
+ fields: {
45
+ next_epoch: bcs.u64(),
46
+ cert: CommitteeSignature
47
+ }
48
+ });
21
49
  const MemberInfo = new MoveStruct({
22
50
  name: `${$moduleName}::MemberInfo`,
23
51
  fields: {
@@ -26,7 +54,8 @@ const MemberInfo = new MoveStruct({
26
54
  next_epoch_public_key: Element,
27
55
  endpoint_url: bcs.string(),
28
56
  tls_public_key: bcs.vector(bcs.u8()),
29
- next_epoch_encryption_public_key: bcs.vector(bcs.u8())
57
+ next_epoch_encryption_public_key: bcs.vector(bcs.u8()),
58
+ extra_fields: Config
30
59
  }
31
60
  });
32
61
 
@@ -1,8 +1,6 @@
1
1
  import { MoveStruct } from "../utils/index.mjs";
2
2
  import { VecMap } from "./deps/sui/vec_map.mjs";
3
3
  import { Value } from "./config_value.mjs";
4
- import { VecSet } from "./deps/sui/vec_set.mjs";
5
- import { UpgradeCap } from "./deps/sui/package.mjs";
6
4
  import { bcs } from "@mysten/sui/bcs";
7
5
 
8
6
  //#region src/contracts/hashi/config.ts
@@ -10,18 +8,20 @@ import { bcs } from "@mysten/sui/bcs";
10
8
  * THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
11
9
  **************************************************************/
12
10
  /**
13
- * Core configuration: versioning, pause state, upgrade management, and generic
14
- * key-value config store. Chain-specific configuration (e.g. BTC fee parameters)
15
- * lives in separate modules that use get/upsert.
11
+ * A general-purpose, typed key-value configuration store: a map from string keys
12
+ * to `config_value::Value`s, with domain-specific accessors layered on top (pause
13
+ * state, guardian, emergency thresholds). Chain-specific configuration (e.g. BTC
14
+ * fee parameters) lives in separate modules that use get/upsert.
15
+ *
16
+ * `Config` has `copy, drop, store` and carries no policy of its own (no
17
+ * versioning, no upgrade authority — those live in `versioning`), so it can be
18
+ * embedded by value wherever a bag of settings is needed: it backs the package's
19
+ * global config and is also pinned per-epoch onto a `Committee`.
16
20
  */
17
21
  const $moduleName = "@local-pkg/hashi::config";
18
22
  const Config = new MoveStruct({
19
23
  name: `${$moduleName}::Config`,
20
- fields: {
21
- config: VecMap(bcs.string(), Value),
22
- enabled_versions: VecSet(bcs.u64()),
23
- upgrade_cap: bcs.option(UpgradeCap)
24
- }
24
+ fields: { config: VecMap(bcs.string(), Value) }
25
25
  });
26
26
 
27
27
  //#endregion
@@ -5,11 +5,21 @@ import { bcs } from "@mysten/sui/bcs";
5
5
  /**************************************************************
6
6
  * THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
7
7
  **************************************************************/
8
+ /**
9
+ * Typed value wrapper for config entries: the `Value` enum carries one of the
10
+ * primitive types a configuration entry can hold, with a public constructor per
11
+ * variant and package-level helpers for variant checks (`is_*`) and extraction
12
+ * (`as_*`, aborting on a type mismatch). Storing typed values — rather than raw
13
+ * bytes — lets `config::is_valid_config_update` reject governance updates that
14
+ * would change an entry's type.
15
+ */
8
16
  const $moduleName = "@local-pkg/hashi::config_value";
9
17
  const Value = new MoveEnum({
10
18
  name: `${$moduleName}::Value`,
11
19
  fields: {
12
20
  U64: bcs.u64(),
21
+ U128: bcs.u128(),
22
+ U256: bcs.u256(),
13
23
  Address: bcs.Address,
14
24
  String: bcs.string(),
15
25
  Bool: bcs.bool(),
@@ -1,12 +1,21 @@
1
1
  import { MoveStruct, normalizeMoveArguments } from "../utils/index.mjs";
2
- import { Utxo, UtxoId } from "./utxo.mjs";
3
2
  import { CommitteeSignature } from "./committee.mjs";
3
+ import { Utxo, UtxoId } from "./utxo.mjs";
4
4
  import { bcs } from "@mysten/sui/bcs";
5
5
 
6
6
  //#region src/contracts/hashi/deposit.ts
7
7
  /**************************************************************
8
8
  * THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
9
9
  **************************************************************/
10
+ /**
11
+ * User-facing Bitcoin deposit flow. A depositor registers the UTXO they sent to
12
+ * the bridge's address, the committee approves it with a certificate over
13
+ * `(request_id, utxo)`, and — after a configurable time delay in which a faulty
14
+ * approval can be caught and the service paused — the deposit is confirmed: hBTC
15
+ * is minted to the recipient encoded in the UTXO's derivation path and the UTXO
16
+ * joins the active pool. Requests that are never confirmed can be
17
+ * garbage-collected once they expire.
18
+ */
10
19
  const $moduleName = "@local-pkg/hashi::deposit";
11
20
  const DepositConfirmationMessage = new MoveStruct({
12
21
  name: `${$moduleName}::DepositConfirmationMessage`,
@@ -15,8 +24,8 @@ const DepositConfirmationMessage = new MoveStruct({
15
24
  utxo: Utxo
16
25
  }
17
26
  });
18
- const DepositRequestedEvent = new MoveStruct({
19
- name: `${$moduleName}::DepositRequestedEvent`,
27
+ const DepositRequested = new MoveStruct({
28
+ name: `${$moduleName}::DepositRequested`,
20
29
  fields: {
21
30
  request_id: bcs.Address,
22
31
  utxo_id: UtxoId,
@@ -27,8 +36,8 @@ const DepositRequestedEvent = new MoveStruct({
27
36
  sui_tx_digest: bcs.vector(bcs.u8())
28
37
  }
29
38
  });
30
- const DepositApprovedEvent = new MoveStruct({
31
- name: `${$moduleName}::DepositApprovedEvent`,
39
+ const DepositApproved = new MoveStruct({
40
+ name: `${$moduleName}::DepositApproved`,
32
41
  fields: {
33
42
  request_id: bcs.Address,
34
43
  utxo: Utxo,
@@ -36,15 +45,15 @@ const DepositApprovedEvent = new MoveStruct({
36
45
  approval_timestamp_ms: bcs.u64()
37
46
  }
38
47
  });
39
- const DepositConfirmedEvent = new MoveStruct({
40
- name: `${$moduleName}::DepositConfirmedEvent`,
48
+ const DepositConfirmed = new MoveStruct({
49
+ name: `${$moduleName}::DepositConfirmed`,
41
50
  fields: {
42
51
  request_id: bcs.Address,
43
52
  utxo: Utxo
44
53
  }
45
54
  });
46
- const ExpiredDepositDeletedEvent = new MoveStruct({
47
- name: `${$moduleName}::ExpiredDepositDeletedEvent`,
55
+ const ExpiredDepositDeleted = new MoveStruct({
56
+ name: `${$moduleName}::ExpiredDepositDeleted`,
48
57
  fields: { request_id: bcs.Address }
49
58
  });
50
59
  function deposit(options) {
@@ -1,13 +1,20 @@
1
1
  import { MoveStruct } from "../utils/index.mjs";
2
+ import { CommitteeSignature } from "./committee.mjs";
2
3
  import { ObjectBag } from "./deps/sui/object_bag.mjs";
3
4
  import { Utxo } from "./utxo.mjs";
4
- import { CommitteeSignature } from "./committee.mjs";
5
5
  import { bcs } from "@mysten/sui/bcs";
6
6
 
7
7
  //#region src/contracts/hashi/deposit_queue.ts
8
8
  /**************************************************************
9
9
  * THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
10
10
  **************************************************************/
11
+ /**
12
+ * Storage and bookkeeping for Bitcoin deposit requests. Active requests sit in an
13
+ * ObjectBag awaiting committee approval and confirmation; confirmed requests move
14
+ * to a processed bag, and requests that were never confirmed can be deleted once
15
+ * they pass the maximum age. The state transitions themselves (certificate
16
+ * verification, minting, time-delay enforcement) are driven by `hashi::deposit`.
17
+ */
11
18
  const $moduleName = "@local-pkg/hashi::deposit_queue";
12
19
  const DepositRequestQueue = new MoveStruct({
13
20
  name: `${$moduleName}::DepositRequestQueue`,
@@ -21,11 +28,12 @@ const DepositRequest = new MoveStruct({
21
28
  fields: {
22
29
  id: bcs.Address,
23
30
  sender: bcs.Address,
24
- timestamp_ms: bcs.u64(),
31
+ created_timestamp_ms: bcs.u64(),
25
32
  sui_tx_digest: bcs.vector(bcs.u8()),
26
33
  utxo: Utxo,
27
34
  approval_cert: bcs.option(CommitteeSignature),
28
- approval_timestamp_ms: bcs.option(bcs.u64())
35
+ approved_timestamp_ms: bcs.option(bcs.u64()),
36
+ confirmed_timestamp_ms: bcs.option(bcs.u64())
29
37
  }
30
38
  });
31
39
 
@@ -1,7 +1,8 @@
1
1
  import { MoveStruct } from "../utils/index.mjs";
2
+ import { Config } from "./config.mjs";
2
3
  import { Bag } from "./deps/sui/bag.mjs";
3
4
  import { CommitteeSet } from "./committee_set.mjs";
4
- import { Config } from "./config.mjs";
5
+ import { Versioning } from "./versioning.mjs";
5
6
  import { Treasury } from "./treasury.mjs";
6
7
  import { Proposals } from "./proposals.mjs";
7
8
  import { bcs } from "@mysten/sui/bcs";
@@ -10,7 +11,15 @@ import { bcs } from "@mysten/sui/bcs";
10
11
  /**************************************************************
11
12
  * THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
12
13
  **************************************************************/
13
- /** Module: hashi */
14
+ /**
15
+ * The root shared object of the bridge. `Hashi` aggregates every subsystem —
16
+ * committee set, config, versioning, treasury, governance proposals, and TOB
17
+ * certificate storage — and hangs per-chain state (e.g. `BitcoinState`) off its
18
+ * `UID` as dynamic fields. It also provides the package-wide guards (pause,
19
+ * reconfig, committee-signature verification) that entry functions in other
20
+ * modules call through, and the one-time `finish_publish` launch switch that hands
21
+ * the package `UpgradeCap` into on-chain custody.
22
+ */
14
23
  const $moduleName = "@local-pkg/hashi::hashi";
15
24
  const Hashi = new MoveStruct({
16
25
  name: `${$moduleName}::Hashi`,
@@ -18,6 +27,7 @@ const Hashi = new MoveStruct({
18
27
  id: bcs.Address,
19
28
  committee_set: CommitteeSet,
20
29
  config: Config,
30
+ versioning: Versioning,
21
31
  treasury: Treasury,
22
32
  proposals: Proposals,
23
33
  tob: Bag,
@@ -0,0 +1,56 @@
1
+ import { MoveEnum, MoveStruct } from "../utils/index.mjs";
2
+ import { bcs } from "@mysten/sui/bcs";
3
+
4
+ //#region src/contracts/hashi/mpc_signing.ts
5
+ /**************************************************************
6
+ * THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
7
+ **************************************************************/
8
+ /**
9
+ * Durable, out-of-order accumulator for a withdrawal's per-input threshold Schnorr
10
+ * signatures. This is the MPC-protocol side of incremental signing: the dangerous
11
+ * presignature / nonce bookkeeping lives here, behind a module boundary, and is
12
+ * embedded (field-private) inside the BTC `WithdrawalTransaction` rather than
13
+ * stored as a separate object.
14
+ *
15
+ * Each input occupies one slot that is either:
16
+ *
17
+ * - `Pending(presig_index)` — awaiting its signature; carries the presignature
18
+ * index it will consume (valid within `epoch`), or
19
+ * - `Signed(bytes)` — the completed per-input MPC signature.
20
+ *
21
+ * Signatures are filled in any order (`record`), survive leader timeouts /
22
+ * rotation / restart because they live on chain, and survive committee
23
+ * reconfiguration: on an epoch change only the still-`Pending` slots are
24
+ * reassigned fresh presignatures (`reallocate`); `Signed` slots are final and
25
+ * epoch-independent (the committee group key is stable across rotation).
26
+ *
27
+ * NONCE SAFETY (a violation leaks the group secret share):
28
+ *
29
+ * - every `Pending` index is unique within (batch, epoch) — `new` / `reallocate`
30
+ * assign distinct offsets from a freshly allocated block;
31
+ * - indices are globally disjoint within an epoch — the allocator is monotonic
32
+ * (see `hashi::allocate_presigs`);
33
+ * - a stale-epoch index is never used after a reconfig — `reallocate` overwrites
34
+ * EVERY `Pending` slot before any signing happens in the new epoch, and the
35
+ * caller must `reallocate` whenever `epoch` is stale;
36
+ * - a `Signed` slot holds no index, so there is nothing stale to reuse.
37
+ */
38
+ const $moduleName = "@local-pkg/hashi::mpc_signing";
39
+ /** Per-input signing slot. */
40
+ const MpcSig = new MoveEnum({
41
+ name: `${$moduleName}::MpcSig`,
42
+ fields: {
43
+ Pending: bcs.u64(),
44
+ Signed: bcs.vector(bcs.u8())
45
+ }
46
+ });
47
+ const SigningBatch = new MoveStruct({
48
+ name: `${$moduleName}::SigningBatch`,
49
+ fields: {
50
+ signatures: bcs.vector(MpcSig),
51
+ epoch: bcs.u64()
52
+ }
53
+ });
54
+
55
+ //#endregion
56
+ export { SigningBatch };
@@ -5,6 +5,12 @@ import { ObjectBag } from "./deps/sui/object_bag.mjs";
5
5
  /**************************************************************
6
6
  * THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
7
7
  **************************************************************/
8
+ /**
9
+ * Container for the package's governance proposals, hung off `Hashi`. Active and
10
+ * executed proposals live in two separate object bags so that each set can be
11
+ * enumerated directly, and executed proposals are archived indefinitely to keep
12
+ * historical governance actions inspectable.
13
+ */
8
14
  const $moduleName = "@local-pkg/hashi::proposals";
9
15
  const Proposals = new MoveStruct({
10
16
  name: `${$moduleName}::Proposals`,
@@ -6,6 +6,12 @@ import { bcs } from "@mysten/sui/bcs";
6
6
  /**************************************************************
7
7
  * THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
8
8
  **************************************************************/
9
+ /**
10
+ * Custody of the coin capabilities for bridge-issued assets. `Treasury` holds the
11
+ * `TreasuryCap` and `MetadataCap` of each registered coin type in an `ObjectBag`
12
+ * keyed by cap type, and exposes package-only mint/burn that emit
13
+ * `Minted`/`Burned` events for off-chain watchers.
14
+ */
9
15
  const $moduleName = "@local-pkg/hashi::treasury";
10
16
  const Treasury = new MoveStruct({
11
17
  name: `${$moduleName}::Treasury`,
@@ -15,12 +21,12 @@ const Key = new MoveStruct({
15
21
  name: `${$moduleName}::Key<phantom T>`,
16
22
  fields: { dummy_field: bcs.bool() }
17
23
  });
18
- const MintEvent = new MoveStruct({
19
- name: `${$moduleName}::MintEvent<phantom T>`,
24
+ const Minted = new MoveStruct({
25
+ name: `${$moduleName}::Minted<phantom T>`,
20
26
  fields: { amount: bcs.u64() }
21
27
  });
22
- const BurnEvent = new MoveStruct({
23
- name: `${$moduleName}::BurnEvent<phantom T>`,
28
+ const Burned = new MoveStruct({
29
+ name: `${$moduleName}::Burned<phantom T>`,
24
30
  fields: { amount: bcs.u64() }
25
31
  });
26
32
 
@@ -5,6 +5,13 @@ import { bcs } from "@mysten/sui/bcs";
5
5
  /**************************************************************
6
6
  * THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
7
7
  **************************************************************/
8
+ /**
9
+ * Bitcoin UTXO value types shared by the deposit and withdrawal flows. A `UtxoId`
10
+ * identifies an outpoint (txid:vout) and a `Utxo` pairs it with its satoshi amount
11
+ * and an optional derivation path (the Sui address a deposit mints to). The
12
+ * constructors are `public` so PTBs can assemble UTXOs when calling into the
13
+ * bridge; everything else is package-only.
14
+ */
8
15
  const $moduleName = "@local-pkg/hashi::utxo";
9
16
  const UtxoId = new MoveStruct({
10
17
  name: `${$moduleName}::UtxoId`,
@@ -7,6 +7,13 @@ import { bcs } from "@mysten/sui/bcs";
7
7
  /**************************************************************
8
8
  * THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
9
9
  **************************************************************/
10
+ /**
11
+ * On-chain bookkeeping for the bridge's Bitcoin UTXO set. Confirmed deposit
12
+ * outputs and unconfirmed withdrawal change outputs live in `utxo_records` from
13
+ * insertion until the withdrawal that spends them confirms on Bitcoin, after which
14
+ * their IDs move to `spent_utxos` — kept permanently as replay protection so an
15
+ * already-spent outpoint can never be re-inserted.
16
+ */
10
17
  const $moduleName = "@local-pkg/hashi::utxo_pool";
11
18
  const UtxoPool = new MoveStruct({
12
19
  name: `${$moduleName}::UtxoPool`,
@@ -20,12 +27,12 @@ const UtxoRecord = new MoveStruct({
20
27
  fields: {
21
28
  utxo: Utxo,
22
29
  produced_by: bcs.option(bcs.Address),
23
- locked_by: bcs.option(bcs.Address),
30
+ spent_by: bcs.option(bcs.Address),
24
31
  spent_epoch: bcs.option(bcs.u64())
25
32
  }
26
33
  });
27
- const UtxoSpentEvent = new MoveStruct({
28
- name: `${$moduleName}::UtxoSpentEvent`,
34
+ const UtxoSpent = new MoveStruct({
35
+ name: `${$moduleName}::UtxoSpent`,
29
36
  fields: {
30
37
  utxo_id: UtxoId,
31
38
  spent_epoch: bcs.u64()
@@ -0,0 +1,28 @@
1
+ import { MoveStruct } from "../utils/index.mjs";
2
+ import { VecSet } from "./deps/sui/vec_set.mjs";
3
+ import { UpgradeCap } from "./deps/sui/package.mjs";
4
+ import { bcs } from "@mysten/sui/bcs";
5
+
6
+ //#region src/contracts/hashi/versioning.ts
7
+ /**************************************************************
8
+ * THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
9
+ **************************************************************/
10
+ /**
11
+ * Package version gating and upgrade authority.
12
+ *
13
+ * Holds the set of package versions allowed to run and custodies the package
14
+ * `UpgradeCap`. The two live together because they are one lifecycle: committing
15
+ * an upgrade through the cap auto-enables the new version. Every entry function
16
+ * gates on `assert_version_enabled` so a disabled version cannot be executed.
17
+ */
18
+ const $moduleName = "@local-pkg/hashi::versioning";
19
+ const Versioning = new MoveStruct({
20
+ name: `${$moduleName}::Versioning`,
21
+ fields: {
22
+ enabled_versions: VecSet(bcs.u64()),
23
+ upgrade_cap: bcs.option(UpgradeCap)
24
+ }
25
+ });
26
+
27
+ //#endregion
28
+ export { Versioning };
@@ -7,7 +7,15 @@ import { bcs } from "@mysten/sui/bcs";
7
7
  /**************************************************************
8
8
  * THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
9
9
  **************************************************************/
10
- /** Module: withdraw */
10
+ /**
11
+ * User-facing Bitcoin withdrawal flow. A user escrows hBTC against a target
12
+ * Bitcoin address; the committee approves the request, batches one or more
13
+ * requests into a withdrawal transaction (burning the hBTC and locking the input
14
+ * UTXOs), accumulates per-input MPC signatures incrementally, finalizes with the
15
+ * one-shot guardian signatures, and confirms once the transaction lands on
16
+ * Bitcoin. A not-yet-committed request can be cancelled by its requester after a
17
+ * cooldown, refunding the hBTC.
18
+ */
11
19
  const $moduleName = "@local-pkg/hashi::withdraw";
12
20
  const RequestApprovalMessage = new MoveStruct({
13
21
  name: `${$moduleName}::RequestApprovalMessage`,
@@ -31,6 +39,14 @@ const WithdrawalSignedMessage = new MoveStruct({
31
39
  guardian_signatures: bcs.vector(bcs.vector(bcs.u8()))
32
40
  }
33
41
  });
42
+ const MpcInputSignaturesMessage = new MoveStruct({
43
+ name: `${$moduleName}::MpcInputSignaturesMessage`,
44
+ fields: {
45
+ withdrawal_id: bcs.Address,
46
+ indices: bcs.vector(bcs.u64()),
47
+ signatures: bcs.vector(bcs.vector(bcs.u8()))
48
+ }
49
+ });
34
50
  const WithdrawalConfirmationMessage = new MoveStruct({
35
51
  name: `${$moduleName}::WithdrawalConfirmationMessage`,
36
52
  fields: { withdrawal_id: bcs.Address }
@@ -1,13 +1,23 @@
1
1
  import { MoveEnum, MoveStruct } from "../utils/index.mjs";
2
+ import { CommitteeSignature } from "./committee.mjs";
2
3
  import { ObjectBag } from "./deps/sui/object_bag.mjs";
3
4
  import { Utxo, UtxoId } from "./utxo.mjs";
4
5
  import { Balance } from "./deps/sui/balance.mjs";
6
+ import { SigningBatch } from "./mpc_signing.mjs";
5
7
  import { bcs } from "@mysten/sui/bcs";
6
8
 
7
9
  //#region src/contracts/hashi/withdrawal_queue.ts
8
10
  /**************************************************************
9
11
  * THIS FILE IS GENERATED AND SHOULD NOT BE MANUALLY MODIFIED *
10
12
  **************************************************************/
13
+ /**
14
+ * Storage and state machine for Bitcoin withdrawals. Holds `WithdrawalRequest`
15
+ * objects as they move from Requested through Approved, Processing, Signed, and
16
+ * Confirmed, plus the `WithdrawalTransaction` objects that batch them: each
17
+ * transaction tracks its input UTXOs, withdrawal and change outputs, and the
18
+ * incrementally collected MPC and guardian signatures. Certificate verification
19
+ * and funds movement are driven by `hashi::withdraw`.
20
+ */
11
21
  const $moduleName = "@local-pkg/hashi::withdrawal_queue";
12
22
  const WithdrawalRequestQueue = new MoveStruct({
13
23
  name: `${$moduleName}::WithdrawalRequestQueue`,
@@ -42,8 +52,10 @@ const WithdrawalRequest = new MoveStruct({
42
52
  sender: bcs.Address,
43
53
  btc_amount: bcs.u64(),
44
54
  bitcoin_address: bcs.vector(bcs.u8()),
45
- timestamp_ms: bcs.u64(),
55
+ created_timestamp_ms: bcs.u64(),
46
56
  status: WithdrawalStatus,
57
+ approval_cert: bcs.option(CommitteeSignature),
58
+ approved_timestamp_ms: bcs.option(bcs.u64()),
47
59
  withdrawal_txn_id: bcs.option(bcs.Address),
48
60
  sui_tx_digest: bcs.vector(bcs.u8()),
49
61
  btc: Balance
@@ -57,13 +69,13 @@ const WithdrawalTransaction = new MoveStruct({
57
69
  request_ids: bcs.vector(bcs.Address),
58
70
  inputs: bcs.vector(Utxo),
59
71
  withdrawal_outputs: bcs.vector(OutputUtxo),
60
- change_output: bcs.option(OutputUtxo),
61
- timestamp_ms: bcs.u64(),
72
+ change_outputs: bcs.vector(OutputUtxo),
73
+ created_timestamp_ms: bcs.u64(),
74
+ signed_timestamp_ms: bcs.option(bcs.u64()),
75
+ confirmed_timestamp_ms: bcs.option(bcs.u64()),
62
76
  randomness: bcs.vector(bcs.u8()),
63
- signatures: bcs.option(bcs.vector(bcs.vector(bcs.u8()))),
64
- guardian_signatures: bcs.option(bcs.vector(bcs.vector(bcs.u8()))),
65
- presig_start_index: bcs.u64(),
66
- epoch: bcs.u64()
77
+ signing: SigningBatch,
78
+ guardian_signatures: bcs.option(bcs.vector(bcs.vector(bcs.u8())))
67
79
  }
68
80
  });
69
81
  const CommittedRequestInfo = new MoveStruct({
@@ -73,8 +85,8 @@ const CommittedRequestInfo = new MoveStruct({
73
85
  bitcoin_address: bcs.vector(bcs.u8())
74
86
  }
75
87
  });
76
- const WithdrawalRequestedEvent = new MoveStruct({
77
- name: `${$moduleName}::WithdrawalRequestedEvent`,
88
+ const WithdrawalRequested = new MoveStruct({
89
+ name: `${$moduleName}::WithdrawalRequested`,
78
90
  fields: {
79
91
  request_id: bcs.Address,
80
92
  btc_amount: bcs.u64(),
@@ -84,25 +96,33 @@ const WithdrawalRequestedEvent = new MoveStruct({
84
96
  sui_tx_digest: bcs.vector(bcs.u8())
85
97
  }
86
98
  });
87
- const WithdrawalApprovedEvent = new MoveStruct({
88
- name: `${$moduleName}::WithdrawalApprovedEvent`,
99
+ const WithdrawalApproved = new MoveStruct({
100
+ name: `${$moduleName}::WithdrawalApproved`,
89
101
  fields: { request_id: bcs.Address }
90
102
  });
91
- const WithdrawalPickedForProcessingEvent = new MoveStruct({
92
- name: `${$moduleName}::WithdrawalPickedForProcessingEvent`,
103
+ const WithdrawalPickedForProcessing = new MoveStruct({
104
+ name: `${$moduleName}::WithdrawalPickedForProcessing`,
93
105
  fields: {
94
106
  withdrawal_txn_id: bcs.Address,
95
107
  txid: bcs.Address,
96
108
  request_ids: bcs.vector(bcs.Address),
97
109
  inputs: bcs.vector(Utxo),
98
110
  withdrawal_outputs: bcs.vector(OutputUtxo),
99
- change_output: bcs.option(OutputUtxo),
111
+ change_outputs: bcs.vector(OutputUtxo),
100
112
  timestamp_ms: bcs.u64(),
101
113
  randomness: bcs.vector(bcs.u8())
102
114
  }
103
115
  });
104
- const WithdrawalSignedEvent = new MoveStruct({
105
- name: `${$moduleName}::WithdrawalSignedEvent`,
116
+ const WithdrawalInputsSigned = new MoveStruct({
117
+ name: `${$moduleName}::WithdrawalInputsSigned`,
118
+ fields: {
119
+ withdrawal_txn_id: bcs.Address,
120
+ signed_count: bcs.u64(),
121
+ num_inputs: bcs.u64()
122
+ }
123
+ });
124
+ const WithdrawalSigned = new MoveStruct({
125
+ name: `${$moduleName}::WithdrawalSigned`,
106
126
  fields: {
107
127
  withdrawal_txn_id: bcs.Address,
108
128
  request_ids: bcs.vector(bcs.Address),
@@ -110,26 +130,26 @@ const WithdrawalSignedEvent = new MoveStruct({
110
130
  guardian_signatures: bcs.vector(bcs.vector(bcs.u8()))
111
131
  }
112
132
  });
113
- const WithdrawalPresigsReassignedEvent = new MoveStruct({
114
- name: `${$moduleName}::WithdrawalPresigsReassignedEvent`,
133
+ const WithdrawalPresigsReassigned = new MoveStruct({
134
+ name: `${$moduleName}::WithdrawalPresigsReassigned`,
115
135
  fields: {
116
136
  withdrawal_txn_id: bcs.Address,
117
137
  epoch: bcs.u64(),
118
138
  presig_start_index: bcs.u64()
119
139
  }
120
140
  });
121
- const WithdrawalConfirmedEvent = new MoveStruct({
122
- name: `${$moduleName}::WithdrawalConfirmedEvent`,
141
+ const WithdrawalConfirmed = new MoveStruct({
142
+ name: `${$moduleName}::WithdrawalConfirmed`,
123
143
  fields: {
124
144
  withdrawal_txn_id: bcs.Address,
125
145
  txid: bcs.Address,
126
- change_utxo_id: bcs.option(UtxoId),
146
+ change_utxo_ids: bcs.vector(UtxoId),
127
147
  request_ids: bcs.vector(bcs.Address),
128
- change_utxo_amount: bcs.option(bcs.u64())
148
+ change_utxo_amounts: bcs.vector(bcs.u64())
129
149
  }
130
150
  });
131
- const WithdrawalCancelledEvent = new MoveStruct({
132
- name: `${$moduleName}::WithdrawalCancelledEvent`,
151
+ const WithdrawalCancelled = new MoveStruct({
152
+ name: `${$moduleName}::WithdrawalCancelled`,
133
153
  fields: {
134
154
  request_id: bcs.Address,
135
155
  requester_address: bcs.Address,
package/dist/errors.d.mts CHANGED
@@ -36,6 +36,33 @@ declare class HashiFetchError extends Error {
36
36
  cause?: unknown;
37
37
  });
38
38
  }
39
+ /**
40
+ * Stable discriminator for `HashiGuardianError`, so callers can `switch` on
41
+ * `code` rather than string-parse the message: `not-configured` (no guardian URL
42
+ * resolvable), `unreachable` (`fetch` threw), `http-error` (non-2xx),
43
+ * `malformed-response` (bad JSON or limiter field), `not-initialized` (no limiter yet).
44
+ */
45
+ type GuardianErrorCode = "not-configured" | "unreachable" | "http-error" | "malformed-response" | "not-initialized";
46
+ /**
47
+ * Thrown by the `client.hashi.guardian.*` methods when the guardian `/info`
48
+ * endpoint can't be resolved, reached, parsed, or is not yet initialized.
49
+ * `code` is a stable discriminator for programmatic handling; `url` is the
50
+ * `/info` endpoint that failed (`null` for `not-configured`); `status` carries
51
+ * the HTTP status for `http-error`.
52
+ */
53
+ declare class HashiGuardianError extends Error {
54
+ readonly code: GuardianErrorCode;
55
+ readonly url: string | null;
56
+ readonly status?: number;
57
+ constructor(details: {
58
+ message: string;
59
+ code: GuardianErrorCode;
60
+ url?: string | null;
61
+ status?: number;
62
+ }, options?: {
63
+ cause?: unknown;
64
+ });
65
+ }
39
66
  /**
40
67
  * One amount that failed a client-side minimum check. `vout` is present for
41
68
  * deposit-UTXO violations (so callers can map each offender back to a Bitcoin
@@ -115,4 +142,4 @@ declare class InvalidBitcoinAddressError extends Error {
115
142
  });
116
143
  }
117
144
  //#endregion
118
- export { AmountBelowMinimumError, AmountViolation, HashiConfigError, HashiFetchError, HashiPausedError, InvalidBitcoinAddressCode, InvalidBitcoinAddressError, InvalidParamsError };
145
+ export { AmountBelowMinimumError, AmountViolation, GuardianErrorCode, HashiConfigError, HashiFetchError, HashiGuardianError, HashiPausedError, InvalidBitcoinAddressCode, InvalidBitcoinAddressError, InvalidParamsError };