@openzeppelin/miden-multisig-client 0.13.1 → 0.13.3
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 +98 -119
- package/dist/account/builder.d.ts +18 -0
- package/dist/account/builder.d.ts.map +1 -1
- package/dist/account/builder.js +59 -29
- package/dist/account/builder.js.map +1 -1
- package/dist/account/builder.test.js +108 -32
- package/dist/account/builder.test.js.map +1 -1
- package/dist/account/index.d.ts +1 -1
- package/dist/account/index.d.ts.map +1 -1
- package/dist/account/index.js +1 -1
- package/dist/account/index.js.map +1 -1
- package/dist/account/masm/account-components/auth.d.ts +5 -0
- package/dist/account/masm/account-components/auth.d.ts.map +1 -0
- package/dist/account/masm/account-components/auth.js +67 -0
- package/dist/account/masm/account-components/auth.js.map +1 -0
- package/dist/account/masm/auth.d.ts +5 -0
- package/dist/account/masm/auth.d.ts.map +1 -0
- package/dist/account/masm/auth.js +1395 -0
- package/dist/account/masm/auth.js.map +1 -0
- package/dist/account/masm/index.d.ts +3 -0
- package/dist/account/masm/index.d.ts.map +1 -0
- package/dist/account/masm/index.js +5 -0
- package/dist/account/masm/index.js.map +1 -0
- package/dist/account/masm.d.ts +1 -4
- package/dist/account/masm.d.ts.map +1 -1
- package/dist/account/masm.js +3 -1034
- package/dist/account/masm.js.map +1 -1
- package/dist/account/storage.d.ts +2 -2
- package/dist/account/storage.d.ts.map +1 -1
- package/dist/account/storage.js +18 -16
- package/dist/account/storage.js.map +1 -1
- package/dist/client.d.ts +67 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +73 -22
- package/dist/client.js.map +1 -1
- package/dist/client.test.js +31 -32
- package/dist/client.test.js.map +1 -1
- package/dist/index.d.ts +54 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +53 -9
- package/dist/index.js.map +1 -1
- package/dist/inspector.d.ts +32 -6
- package/dist/inspector.d.ts.map +1 -1
- package/dist/inspector.js +58 -23
- package/dist/inspector.js.map +1 -1
- package/dist/inspector.test.js +18 -18
- package/dist/inspector.test.js.map +1 -1
- package/dist/multisig/proposal/execution.d.ts +4 -4
- package/dist/multisig/proposal/execution.d.ts.map +1 -1
- package/dist/multisig/proposal/execution.js +42 -31
- package/dist/multisig/proposal/execution.js.map +1 -1
- package/dist/multisig/proposal/parser.d.ts +3 -3
- package/dist/multisig/proposal/parser.d.ts.map +1 -1
- package/dist/multisig/proposal/parser.js +23 -23
- package/dist/multisig/proposal/parser.js.map +1 -1
- package/dist/multisig/signing.d.ts +3 -3
- package/dist/multisig/signing.d.ts.map +1 -1
- package/dist/multisig/signing.js +3 -3
- package/dist/multisig/signing.js.map +1 -1
- package/dist/multisig.d.ts +188 -48
- package/dist/multisig.d.ts.map +1 -1
- package/dist/multisig.js +650 -308
- package/dist/multisig.js.map +1 -1
- package/dist/multisig.test.js +1680 -241
- package/dist/multisig.test.js.map +1 -1
- package/dist/procedures.d.ts +46 -24
- package/dist/procedures.d.ts.map +1 -1
- package/dist/procedures.js +46 -21
- package/dist/procedures.js.map +1 -1
- package/dist/proposal/factory.d.ts +18 -0
- package/dist/proposal/factory.d.ts.map +1 -0
- package/dist/proposal/factory.js +99 -0
- package/dist/proposal/factory.js.map +1 -0
- package/dist/proposal/metadata.d.ts +5 -12
- package/dist/proposal/metadata.d.ts.map +1 -1
- package/dist/proposal/metadata.js +118 -174
- package/dist/proposal/metadata.js.map +1 -1
- package/dist/proposal/signatures.d.ts +10 -0
- package/dist/proposal/signatures.d.ts.map +1 -0
- package/dist/proposal/signatures.js +54 -0
- package/dist/proposal/signatures.js.map +1 -0
- package/dist/signer.d.ts +2 -0
- package/dist/signer.d.ts.map +1 -1
- package/dist/signer.js +2 -0
- package/dist/signer.js.map +1 -1
- package/dist/signers/ecdsa.d.ts +3 -0
- package/dist/signers/ecdsa.d.ts.map +1 -1
- package/dist/signers/ecdsa.js +8 -4
- package/dist/signers/ecdsa.js.map +1 -1
- package/dist/signers/ecdsa.test.d.ts +2 -0
- package/dist/signers/ecdsa.test.d.ts.map +1 -0
- package/dist/signers/ecdsa.test.js +65 -0
- package/dist/signers/ecdsa.test.js.map +1 -0
- package/dist/signers/falcon.d.ts +3 -0
- package/dist/signers/falcon.d.ts.map +1 -1
- package/dist/signers/falcon.js +8 -4
- package/dist/signers/falcon.js.map +1 -1
- package/dist/signers/falcon.test.js +12 -0
- package/dist/signers/falcon.test.js.map +1 -1
- package/dist/signers/miden-wallet.d.ts +3 -1
- package/dist/signers/miden-wallet.d.ts.map +1 -1
- package/dist/signers/miden-wallet.js +11 -2
- package/dist/signers/miden-wallet.js.map +1 -1
- package/dist/signers/miden-wallet.test.js +26 -0
- package/dist/signers/miden-wallet.test.js.map +1 -1
- package/dist/signers/para.d.ts +3 -3
- package/dist/signers/para.d.ts.map +1 -1
- package/dist/signers/para.js +15 -6
- package/dist/signers/para.js.map +1 -1
- package/dist/signers/para.test.js +39 -0
- package/dist/signers/para.test.js.map +1 -1
- package/dist/transaction/consumeNotes.d.ts.map +1 -1
- package/dist/transaction/consumeNotes.js +1 -0
- package/dist/transaction/consumeNotes.js.map +1 -1
- package/dist/transaction/index.d.ts +2 -1
- package/dist/transaction/index.d.ts.map +1 -1
- package/dist/transaction/index.js +2 -1
- package/dist/transaction/index.js.map +1 -1
- package/dist/transaction/options.d.ts +1 -1
- package/dist/transaction/options.d.ts.map +1 -1
- package/dist/transaction/p2id.d.ts +1 -0
- package/dist/transaction/p2id.d.ts.map +1 -1
- package/dist/transaction/p2id.js +9 -3
- package/dist/transaction/p2id.js.map +1 -1
- package/dist/transaction/updateGuardian.d.ts +7 -0
- package/dist/transaction/updateGuardian.d.ts.map +1 -0
- package/dist/transaction/{updatePsm.js → updateGuardian.js} +15 -29
- package/dist/transaction/updateGuardian.js.map +1 -0
- package/dist/transaction/updateProcedureThreshold.d.ts +9 -0
- package/dist/transaction/updateProcedureThreshold.d.ts.map +1 -0
- package/dist/transaction/updateProcedureThreshold.js +55 -0
- package/dist/transaction/updateProcedureThreshold.js.map +1 -0
- package/dist/transaction/updateSigners.d.ts.map +1 -1
- package/dist/transaction/updateSigners.js +5 -23
- package/dist/transaction/updateSigners.js.map +1 -1
- package/dist/transaction.d.ts +2 -1
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +2 -1
- package/dist/transaction.js.map +1 -1
- package/dist/types/proposal.d.ts +32 -15
- package/dist/types/proposal.d.ts.map +1 -1
- package/dist/types.d.ts +24 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/digest.d.ts +5 -0
- package/dist/utils/digest.d.ts.map +1 -1
- package/dist/utils/digest.js +34 -1
- package/dist/utils/digest.js.map +1 -1
- package/dist/utils/digest.test.d.ts +2 -0
- package/dist/utils/digest.test.d.ts.map +1 -0
- package/dist/utils/digest.test.js +48 -0
- package/dist/utils/digest.test.js.map +1 -0
- package/dist/utils/signature.d.ts +3 -1
- package/dist/utils/signature.d.ts.map +1 -1
- package/dist/utils/signature.js +31 -6
- package/dist/utils/signature.js.map +1 -1
- package/dist/utils/word.test.js +1 -52
- package/dist/utils/word.test.js.map +1 -1
- package/masm/account_components/auth/multisig.masm +13 -0
- package/masm/account_components/auth/multisig_ecdsa.masm +13 -0
- package/masm/account_components/auth/multisig_guardian.masm +17 -0
- package/masm/account_components/auth/multisig_guardian_ecdsa.masm +17 -0
- package/masm/auth/guardian.masm +177 -0
- package/masm/auth/guardian_ecdsa.masm +178 -0
- package/masm/{multisig.masm → auth/multisig.masm} +149 -55
- package/masm/{multisig_ecdsa.masm → auth/multisig_ecdsa.masm} +148 -56
- package/package.json +11 -9
- package/src/account/builder.test.ts +165 -0
- package/src/account/builder.ts +71 -34
- package/src/account/index.ts +1 -1
- package/src/account/masm/account-components/auth.ts +70 -0
- package/src/account/masm/auth.ts +1398 -0
- package/src/account/masm/index.ts +5 -0
- package/src/account/masm.ts +3 -1040
- package/src/account/storage.ts +18 -16
- package/src/client.test.ts +31 -35
- package/src/client.ts +98 -26
- package/src/index.ts +84 -22
- package/src/inspector.test.ts +17 -17
- package/src/inspector.ts +63 -29
- package/src/multisig/proposal/execution.ts +66 -49
- package/src/multisig/proposal/parser.ts +26 -26
- package/src/multisig/signing.ts +4 -4
- package/src/multisig.test.ts +2097 -248
- package/src/multisig.ts +882 -388
- package/src/procedures.ts +50 -26
- package/src/proposal/factory.ts +171 -0
- package/src/proposal/metadata.ts +165 -0
- package/src/proposal/signatures.ts +68 -0
- package/src/signer.ts +2 -0
- package/src/signers/ecdsa.test.ts +80 -0
- package/src/signers/ecdsa.ts +15 -4
- package/src/signers/falcon.test.ts +19 -0
- package/src/signers/falcon.ts +16 -5
- package/src/signers/miden-wallet.test.ts +47 -0
- package/src/signers/miden-wallet.ts +18 -1
- package/src/signers/para.test.ts +57 -0
- package/src/signers/para.ts +26 -7
- package/src/transaction/consumeNotes.ts +1 -0
- package/src/transaction/index.ts +2 -2
- package/src/transaction/options.ts +1 -2
- package/src/transaction/p2id.test.ts +190 -0
- package/src/transaction/p2id.ts +11 -5
- package/src/transaction/rpoRandomCoin.test.ts +64 -0
- package/src/transaction/rpoRandomCoin.ts +24 -0
- package/src/transaction/{updatePsm.ts → updateGuardian.ts} +19 -32
- package/src/transaction/updateProcedureThreshold.ts +97 -0
- package/src/transaction/updateSigners.ts +12 -27
- package/src/transaction.ts +5 -3
- package/src/types/proposal.ts +43 -11
- package/src/types.ts +29 -11
- package/src/utils/digest.test.ts +55 -0
- package/src/utils/digest.ts +51 -1
- package/src/utils/signature.ts +47 -9
- package/src/utils/word.test.ts +1 -55
- package/dist/account.d.ts +0 -104
- package/dist/account.d.ts.map +0 -1
- package/dist/account.js +0 -136
- package/dist/account.js.map +0 -1
- package/dist/builder.d.ts +0 -54
- package/dist/builder.d.ts.map +0 -1
- package/dist/builder.js +0 -78
- package/dist/builder.js.map +0 -1
- package/dist/http.d.ts +0 -64
- package/dist/http.d.ts.map +0 -1
- package/dist/http.js +0 -162
- package/dist/http.js.map +0 -1
- package/dist/keystore.d.ts +0 -65
- package/dist/keystore.d.ts.map +0 -1
- package/dist/keystore.js +0 -121
- package/dist/keystore.js.map +0 -1
- package/dist/miden.d.ts +0 -9
- package/dist/miden.d.ts.map +0 -1
- package/dist/miden.js +0 -26
- package/dist/miden.js.map +0 -1
- package/dist/multisig/metadata.d.ts +0 -18
- package/dist/multisig/metadata.d.ts.map +0 -1
- package/dist/multisig/metadata.js +0 -100
- package/dist/multisig/metadata.js.map +0 -1
- package/dist/multisig/metadata.test.d.ts +0 -2
- package/dist/multisig/metadata.test.d.ts.map +0 -1
- package/dist/multisig/metadata.test.js +0 -323
- package/dist/multisig/metadata.test.js.map +0 -1
- package/dist/proposal/exported.d.ts +0 -12
- package/dist/proposal/exported.d.ts.map +0 -1
- package/dist/proposal/exported.js +0 -88
- package/dist/proposal/exported.js.map +0 -1
- package/dist/signer.test.d.ts +0 -2
- package/dist/signer.test.d.ts.map +0 -1
- package/dist/signer.test.js +0 -123
- package/dist/signer.test.js.map +0 -1
- package/dist/transaction/p2id.interop.test.d.ts +0 -2
- package/dist/transaction/p2id.interop.test.d.ts.map +0 -1
- package/dist/transaction/p2id.interop.test.js +0 -36
- package/dist/transaction/p2id.interop.test.js.map +0 -1
- package/dist/transaction/updatePsm.d.ts +0 -7
- package/dist/transaction/updatePsm.d.ts.map +0 -1
- package/dist/transaction/updatePsm.js.map +0 -1
- package/dist/transport/http.d.ts +0 -64
- package/dist/transport/http.d.ts.map +0 -1
- package/dist/transport/http.js +0 -162
- package/dist/transport/http.js.map +0 -1
- package/dist/transport/index.d.ts +0 -5
- package/dist/transport/index.d.ts.map +0 -1
- package/dist/transport/index.js +0 -5
- package/dist/transport/index.js.map +0 -1
- package/dist/utils/state-validation.d.ts +0 -5
- package/dist/utils/state-validation.d.ts.map +0 -1
- package/dist/utils/state-validation.js +0 -30
- package/dist/utils/state-validation.js.map +0 -1
- package/dist/utils/validation.d.ts +0 -6
- package/dist/utils/validation.d.ts.map +0 -1
- package/dist/utils/validation.js +0 -52
- package/dist/utils/validation.js.map +0 -1
- package/masm/psm.masm +0 -178
- package/masm/psm_ecdsa.masm +0 -179
package/README.md
CHANGED
|
@@ -1,82 +1,77 @@
|
|
|
1
1
|
# @openzeppelin/miden-multisig-client
|
|
2
2
|
|
|
3
|
-
TypeScript SDK for private multisignature workflows on Miden. This package wraps the on-chain multisig contracts plus
|
|
3
|
+
TypeScript SDK for private multisignature workflows on Miden. This package wraps the on-chain multisig contracts plus Guardian coordination so you can:
|
|
4
4
|
|
|
5
|
-
- Create multisig accounts, register them with a
|
|
5
|
+
- Create multisig accounts, register them with a GUARDIAN, and keep state off-chain
|
|
6
6
|
- Propose, sign, and execute transactions with threshold enforcement
|
|
7
7
|
- Export/import proposals as files for sharing using side channels
|
|
8
|
-
- Integrate external wallets via the external signing API
|
|
9
|
-
- Use Falcon or ECDSA signature schemes
|
|
10
8
|
|
|
11
|
-
## How Private Multisigs &
|
|
9
|
+
## How Private Multisigs & GUARDIAN Work
|
|
12
10
|
|
|
13
|
-
Miden multisig accounts store their authentication logic on-chain, but **their state (signers, metadata, proposals)** is kept private.
|
|
11
|
+
Miden multisig accounts store their authentication logic on-chain, but **their state (signers, metadata, proposals)** is kept private. GUARDIAN acts as a coordination server:
|
|
14
12
|
|
|
15
|
-
1. A proposer pushes a delta (transaction plan) to
|
|
16
|
-
2. Cosigners fetch pending deltas, verify details locally, sign the transaction summary, and push signatures back to
|
|
17
|
-
3. Once ready, any cosigner builds the final transaction using all cosigner signatures + the
|
|
13
|
+
1. A proposer pushes a delta (transaction plan) to Guardian. GUARDIAN tracks who signed and emits an ack signature once the threshold is met.
|
|
14
|
+
2. Cosigners fetch pending deltas, verify details locally, sign the transaction summary, and push signatures back to GUARDIAN.
|
|
15
|
+
3. Once ready, any cosigner builds the final transaction using all cosigner signatures + the GUARDIAN ack, executes it on-chain.
|
|
18
16
|
|
|
19
17
|
## Installation
|
|
20
18
|
|
|
21
19
|
```bash
|
|
22
|
-
npm install @openzeppelin/miden-multisig-client @
|
|
20
|
+
npm install @openzeppelin/miden-multisig-client @demox-labs/miden-sdk
|
|
23
21
|
```
|
|
24
22
|
|
|
25
23
|
## Setup
|
|
26
24
|
|
|
27
25
|
```typescript
|
|
28
26
|
import { MultisigClient, FalconSigner } from '@openzeppelin/miden-multisig-client';
|
|
29
|
-
import { WebClient,
|
|
27
|
+
import { WebClient, SecretKey } from '@demox-labs/miden-sdk';
|
|
30
28
|
|
|
31
29
|
// Initialize Miden WebClient
|
|
32
30
|
const webClient = await WebClient.createClient('https://rpc.testnet.miden.io:443');
|
|
33
31
|
|
|
34
|
-
// Create a
|
|
35
|
-
const secretKey =
|
|
32
|
+
// Create a signer from your secret key
|
|
33
|
+
const secretKey = SecretKey.rpoFalconWithRNG(seed);
|
|
36
34
|
const signer = new FalconSigner(secretKey);
|
|
37
35
|
|
|
38
|
-
// Create MultisigClient
|
|
36
|
+
// Create MultisigClient
|
|
39
37
|
const client = new MultisigClient(webClient, {
|
|
40
|
-
|
|
38
|
+
guardianEndpoint: 'http://localhost:3000',
|
|
39
|
+
midenRpcEndpoint: 'https://rpc.testnet.miden.io:443',
|
|
41
40
|
});
|
|
42
|
-
const { psmCommitment } = await client.initialize();
|
|
43
41
|
```
|
|
44
42
|
|
|
45
|
-
|
|
43
|
+
## Usage
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
import { MultisigClient, EcdsaSigner } from '@openzeppelin/miden-multisig-client';
|
|
49
|
-
import { AuthSecretKey } from '@miden-sdk/miden-sdk';
|
|
45
|
+
### Get GUARDIAN Public Key
|
|
50
46
|
|
|
51
|
-
|
|
52
|
-
const signer = new EcdsaSigner(secretKey);
|
|
47
|
+
Before creating a multisig, get the GUARDIAN server's public key commitment:
|
|
53
48
|
|
|
54
|
-
|
|
55
|
-
const
|
|
49
|
+
```typescript
|
|
50
|
+
const guardianCommitment = await client.guardianClient.getPubkey();
|
|
56
51
|
```
|
|
57
52
|
|
|
58
|
-
## Usage
|
|
59
|
-
|
|
60
53
|
### Create a Multisig Account
|
|
61
54
|
|
|
62
55
|
```typescript
|
|
63
56
|
const config = {
|
|
64
|
-
threshold: 2,
|
|
65
|
-
signerCommitments: [
|
|
66
|
-
|
|
67
|
-
|
|
57
|
+
threshold: 2, // Require 2 signatures
|
|
58
|
+
signerCommitments: [
|
|
59
|
+
signer.commitment, // Your commitment
|
|
60
|
+
otherSigner.commitment, // Cosigner's commitment
|
|
61
|
+
],
|
|
62
|
+
guardianCommitment,
|
|
68
63
|
};
|
|
69
64
|
|
|
70
65
|
const multisig = await client.create(config, signer);
|
|
71
66
|
console.log('Account ID:', multisig.accountId);
|
|
72
67
|
```
|
|
73
68
|
|
|
74
|
-
### Register on
|
|
69
|
+
### Register on GUARDIAN
|
|
75
70
|
|
|
76
|
-
After creating the account, register it on the
|
|
71
|
+
After creating the account, register it on the GUARDIAN server:
|
|
77
72
|
|
|
78
73
|
```typescript
|
|
79
|
-
await multisig.
|
|
74
|
+
await multisig.registerOnGuardian();
|
|
80
75
|
```
|
|
81
76
|
|
|
82
77
|
### Load an Existing Multisig
|
|
@@ -87,63 +82,59 @@ The configuration is automatically detected from the account's on-chain storage:
|
|
|
87
82
|
const multisig = await client.load(accountId, signer);
|
|
88
83
|
```
|
|
89
84
|
|
|
90
|
-
###
|
|
91
|
-
|
|
92
|
-
Fetch proposals, state, consumable notes, and config in one call:
|
|
85
|
+
### Fetch Account State
|
|
93
86
|
|
|
94
87
|
```typescript
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
88
|
+
const state = await multisig.fetchState();
|
|
89
|
+
console.log('Commitment:', state.commitment);
|
|
90
|
+
console.log('Created:', state.createdAt);
|
|
99
91
|
```
|
|
100
92
|
|
|
101
|
-
###
|
|
102
|
-
|
|
103
|
-
Returns cached proposals without making a network request:
|
|
93
|
+
### Create a Proposal (Add Signer)
|
|
104
94
|
|
|
105
95
|
```typescript
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
96
|
+
// Create a proposal to add a new signer
|
|
97
|
+
const nonce = Math.floor(Math.random() * 1_000_000_000);
|
|
98
|
+
const proposal = await multisig.createAddSignerProposal(
|
|
99
|
+
webClient,
|
|
100
|
+
newSignerCommitment, // Commitment of signer to add
|
|
101
|
+
nonce, // Optional nonce (random value)
|
|
102
|
+
3, // Optional new threshold
|
|
103
|
+
);
|
|
104
|
+
console.log('Proposal ID:', proposal.id);
|
|
114
105
|
```
|
|
115
106
|
|
|
116
|
-
###
|
|
117
|
-
|
|
118
|
-
All create methods return `{ proposal, proposals }` — the new proposal plus an auto-synced full list:
|
|
107
|
+
### Sign a Proposal
|
|
119
108
|
|
|
120
109
|
```typescript
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
{ newThreshold: 3 },
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
// Remove a signer
|
|
128
|
-
await multisig.createRemoveSignerProposal(signerToRemove);
|
|
129
|
-
|
|
130
|
-
// Change threshold
|
|
131
|
-
await multisig.createChangeThresholdProposal(3);
|
|
110
|
+
const signedProposal = await multisig.signProposal(proposal.id);
|
|
111
|
+
console.log('Signatures:', signedProposal.signatures.length);
|
|
112
|
+
```
|
|
132
113
|
|
|
133
|
-
|
|
134
|
-
await multisig.createConsumeNotesProposal(noteIds);
|
|
114
|
+
### Sync Proposals
|
|
135
115
|
|
|
136
|
-
|
|
137
|
-
await multisig.createSendProposal(recipientId, faucetId, amount);
|
|
116
|
+
Fetches proposals from the GUARDIAN server and updates local state:
|
|
138
117
|
|
|
139
|
-
|
|
140
|
-
await multisig.
|
|
118
|
+
```typescript
|
|
119
|
+
const proposals = await multisig.syncProposals();
|
|
120
|
+
for (const p of proposals) {
|
|
121
|
+
console.log(`${p.id}: ${p.status}`);
|
|
122
|
+
}
|
|
141
123
|
```
|
|
142
124
|
|
|
143
|
-
###
|
|
125
|
+
### Check Proposal Status
|
|
126
|
+
|
|
127
|
+
Returns cached proposals without making a network request:
|
|
144
128
|
|
|
145
129
|
```typescript
|
|
146
|
-
const proposals =
|
|
130
|
+
const proposals = multisig.listProposals();
|
|
131
|
+
for (const p of proposals) {
|
|
132
|
+
if (p.status === 'pending') {
|
|
133
|
+
console.log(`Pending signatures: ${p.signatures.length}`);
|
|
134
|
+
} else if (p.status === 'ready') {
|
|
135
|
+
console.log('Ready to execute!');
|
|
136
|
+
}
|
|
137
|
+
}
|
|
147
138
|
```
|
|
148
139
|
|
|
149
140
|
### Execute a Proposal
|
|
@@ -151,69 +142,57 @@ const proposals = await multisig.signTransactionProposal(proposal.commitment);
|
|
|
151
142
|
When a proposal has enough signatures:
|
|
152
143
|
|
|
153
144
|
```typescript
|
|
154
|
-
if (proposal.status
|
|
155
|
-
await multisig.
|
|
145
|
+
if (proposal.status === 'ready') {
|
|
146
|
+
await multisig.executeProposal(proposal.id, webClient);
|
|
147
|
+
console.log('Transaction executed on-chain!');
|
|
156
148
|
}
|
|
157
149
|
```
|
|
158
150
|
|
|
159
|
-
###
|
|
160
|
-
|
|
161
|
-
For wallet integrations where the signing key is external (e.g., a browser wallet):
|
|
151
|
+
### Export Proposal for Offline Signing
|
|
162
152
|
|
|
163
153
|
```typescript
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
const signature = await wallet.sign(proposals[0].commitment);
|
|
169
|
-
|
|
170
|
-
// Submit the external signature
|
|
171
|
-
await multisig.signTransactionProposalExternal({
|
|
172
|
-
commitment: proposals[0].commitment,
|
|
173
|
-
signature,
|
|
174
|
-
publicKey: wallet.publicKey,
|
|
175
|
-
scheme: 'ecdsa',
|
|
176
|
-
});
|
|
154
|
+
const exported = await multisig.exportProposal(proposal.id);
|
|
155
|
+
// Send `exported` to offline signer
|
|
156
|
+
console.log('TX Summary:', exported.txSummaryBase64);
|
|
157
|
+
console.log('Commitment to sign:', exported.commitment);
|
|
177
158
|
```
|
|
178
159
|
|
|
179
|
-
###
|
|
160
|
+
### Import and Sign a Proposal Offline
|
|
180
161
|
|
|
181
|
-
|
|
162
|
+
Imported proposals are now validated against their transaction summary before they are cached or
|
|
163
|
+
signed:
|
|
182
164
|
|
|
183
165
|
```typescript
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const signer = new ParaSigner(paraContext, walletId, commitment, publicKey);
|
|
188
|
-
|
|
189
|
-
// Miden wallet integration
|
|
190
|
-
const signer = new MidenWalletSigner(walletContext, commitment, 'ecdsa');
|
|
166
|
+
const imported = await multisig.importProposal(jsonFromCosigner);
|
|
167
|
+
const signedJson = await multisig.signProposalOffline(imported.id);
|
|
168
|
+
console.log(signedJson);
|
|
191
169
|
```
|
|
192
170
|
|
|
193
|
-
|
|
171
|
+
## Transaction Utilities
|
|
194
172
|
|
|
195
|
-
|
|
173
|
+
The package also exports utility functions for building transactions:
|
|
196
174
|
|
|
197
175
|
```typescript
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
176
|
+
import {
|
|
177
|
+
normalizeHexWord,
|
|
178
|
+
hexToUint8Array,
|
|
179
|
+
signatureHexToBytes,
|
|
180
|
+
buildSignatureAdviceEntry,
|
|
181
|
+
} from '@openzeppelin/miden-multisig-client';
|
|
182
|
+
|
|
183
|
+
// Normalize hex for Word.fromHex (pads to 64 chars)
|
|
184
|
+
const normalized = normalizeHexWord('abc123');
|
|
185
|
+
// => '0x0000...abc123'
|
|
186
|
+
|
|
187
|
+
// Convert hex to bytes
|
|
188
|
+
const bytes = hexToUint8Array('deadbeef');
|
|
189
|
+
// => Uint8Array([0xde, 0xad, 0xbe, 0xef])
|
|
190
|
+
|
|
191
|
+
// Add auth scheme prefix to signature
|
|
192
|
+
const sigBytes = signatureHexToBytes(signatureHex);
|
|
193
|
+
// => Uint8Array with 0x00 prefix (RpoFalcon512)
|
|
206
194
|
```
|
|
207
195
|
|
|
208
|
-
## Signers
|
|
209
|
-
|
|
210
|
-
| Signer | Scheme | Use case |
|
|
211
|
-
|--------|--------|----------|
|
|
212
|
-
| `FalconSigner` | `falcon` | Local Falcon key (default) |
|
|
213
|
-
| `EcdsaSigner` | `ecdsa` | Local ECDSA key |
|
|
214
|
-
| `ParaSigner` | `ecdsa` | External wallet via Para protocol |
|
|
215
|
-
| `MidenWalletSigner` | any | Miden wallet browser extension |
|
|
216
|
-
|
|
217
196
|
## Testing
|
|
218
197
|
|
|
219
198
|
```bash
|
|
@@ -1,5 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account builder for creating multisig accounts with GUARDIAN authentication.
|
|
3
|
+
*
|
|
4
|
+
* This module provides functionality to create multisig accounts.
|
|
5
|
+
*/
|
|
1
6
|
import { type WebClient } from '@miden-sdk/miden-sdk';
|
|
2
7
|
import type { MultisigConfig, CreateAccountResult } from '../types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Creates a multisig account with GUARDIAN authentication.
|
|
10
|
+
*
|
|
11
|
+
* @param webClient - Initialized Miden WebClient
|
|
12
|
+
* @param config - Multisig configuration
|
|
13
|
+
* @returns The created account and seed
|
|
14
|
+
*/
|
|
3
15
|
export declare function createMultisigAccount(webClient: WebClient, config: MultisigConfig): Promise<CreateAccountResult>;
|
|
16
|
+
/**
|
|
17
|
+
* Validates a multisig configuration.
|
|
18
|
+
*
|
|
19
|
+
* @param config - The configuration to validate
|
|
20
|
+
* @throws Error if configuration is invalid
|
|
21
|
+
*/
|
|
4
22
|
export declare function validateMultisigConfig(config: MultisigConfig): void;
|
|
5
23
|
//# sourceMappingURL=builder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/account/builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/account/builder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAcvE;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,mBAAmB,CAAC,CAqD9B;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CA6CnE"}
|
package/dist/account/builder.js
CHANGED
|
@@ -1,36 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account builder for creating multisig accounts with GUARDIAN authentication.
|
|
3
|
+
*
|
|
4
|
+
* This module provides functionality to create multisig accounts.
|
|
5
|
+
*/
|
|
1
6
|
import { AccountBuilder, AccountComponent, AccountType, AccountStorageMode, } from '@miden-sdk/miden-sdk';
|
|
2
|
-
import { buildMultisigStorageSlots,
|
|
3
|
-
import { MULTISIG_MASM,
|
|
7
|
+
import { buildMultisigStorageSlots, buildGuardianStorageSlots } from './storage.js';
|
|
8
|
+
import { MULTISIG_ECDSA_MASM, MULTISIG_MASM, GUARDIAN_ECDSA_MASM, GUARDIAN_MASM, } from './masm/auth.js';
|
|
9
|
+
import { MULTISIG_GUARDIAN_ACCOUNT_COMPONENT_MASM, MULTISIG_GUARDIAN_ECDSA_ACCOUNT_COMPONENT_MASM, } from './masm/account-components/auth.js';
|
|
10
|
+
import { normalizeSignerCommitment } from '../utils/signature.js';
|
|
11
|
+
/**
|
|
12
|
+
* Creates a multisig account with GUARDIAN authentication.
|
|
13
|
+
*
|
|
14
|
+
* @param webClient - Initialized Miden WebClient
|
|
15
|
+
* @param config - Multisig configuration
|
|
16
|
+
* @returns The created account and seed
|
|
17
|
+
*/
|
|
4
18
|
export async function createMultisigAccount(webClient, config) {
|
|
5
19
|
validateMultisigConfig(config);
|
|
6
20
|
const signatureScheme = config.signatureScheme ?? 'falcon';
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
const psmComponent = AccountComponent
|
|
13
|
-
.compile(psmCode, psmSlots)
|
|
14
|
-
.withSupportsAllTypes();
|
|
21
|
+
const authSlots = [
|
|
22
|
+
...buildMultisigStorageSlots(config),
|
|
23
|
+
...buildGuardianStorageSlots(config),
|
|
24
|
+
];
|
|
25
|
+
const guardianMasm = signatureScheme === 'ecdsa' ? GUARDIAN_ECDSA_MASM : GUARDIAN_MASM;
|
|
15
26
|
const multisigMasm = signatureScheme === 'ecdsa' ? MULTISIG_ECDSA_MASM : MULTISIG_MASM;
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
const authComponentMasm = signatureScheme === 'ecdsa'
|
|
28
|
+
? MULTISIG_GUARDIAN_ECDSA_ACCOUNT_COMPONENT_MASM
|
|
29
|
+
: MULTISIG_GUARDIAN_ACCOUNT_COMPONENT_MASM;
|
|
30
|
+
const guardianLibraryPath = signatureScheme === 'ecdsa'
|
|
31
|
+
? 'openzeppelin::auth::guardian_ecdsa'
|
|
32
|
+
: 'openzeppelin::auth::guardian';
|
|
33
|
+
const multisigLibraryPath = signatureScheme === 'ecdsa'
|
|
34
|
+
? 'openzeppelin::auth::multisig_ecdsa'
|
|
35
|
+
: 'openzeppelin::auth::multisig';
|
|
36
|
+
const authBuilder = webClient.createCodeBuilder();
|
|
37
|
+
const guardianLib = authBuilder.buildLibrary(guardianLibraryPath, guardianMasm);
|
|
38
|
+
authBuilder.linkStaticLibrary(guardianLib);
|
|
39
|
+
const multisigLib = authBuilder.buildLibrary(multisigLibraryPath, multisigMasm);
|
|
40
|
+
authBuilder.linkStaticLibrary(multisigLib);
|
|
41
|
+
const authCode = authBuilder.compileAccountComponentCode(authComponentMasm);
|
|
42
|
+
const authComponent = AccountComponent
|
|
43
|
+
.compile(authCode, authSlots)
|
|
23
44
|
.withSupportsAllTypes();
|
|
24
|
-
|
|
25
|
-
|
|
45
|
+
let seed = config.seed;
|
|
46
|
+
// Generate random seed if not provided
|
|
47
|
+
if (!seed) {
|
|
48
|
+
seed = crypto.getRandomValues(new Uint8Array(32));
|
|
49
|
+
}
|
|
26
50
|
const storageMode = config.storageMode === 'public'
|
|
27
51
|
? AccountStorageMode.public()
|
|
28
52
|
: AccountStorageMode.private();
|
|
29
53
|
const accountBuilder = new AccountBuilder(seed)
|
|
30
54
|
.accountType(AccountType.RegularAccountUpdatableCode)
|
|
31
55
|
.storageMode(storageMode)
|
|
32
|
-
.withAuthComponent(
|
|
33
|
-
.withComponent(psmComponent)
|
|
56
|
+
.withAuthComponent(authComponent)
|
|
34
57
|
.withBasicWalletComponent();
|
|
35
58
|
const result = accountBuilder.build();
|
|
36
59
|
await webClient.newAccount(result.account, false);
|
|
@@ -39,6 +62,12 @@ export async function createMultisigAccount(webClient, config) {
|
|
|
39
62
|
seed,
|
|
40
63
|
};
|
|
41
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Validates a multisig configuration.
|
|
67
|
+
*
|
|
68
|
+
* @param config - The configuration to validate
|
|
69
|
+
* @throws Error if configuration is invalid
|
|
70
|
+
*/
|
|
42
71
|
export function validateMultisigConfig(config) {
|
|
43
72
|
if (config.threshold === 0) {
|
|
44
73
|
throw new Error('threshold must be greater than 0');
|
|
@@ -46,20 +75,21 @@ export function validateMultisigConfig(config) {
|
|
|
46
75
|
if (config.signerCommitments.length === 0) {
|
|
47
76
|
throw new Error('at least one signer commitment is required');
|
|
48
77
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
throw new Error(`signerCommitments must be 32-byte commitment hex (64 chars), got ${stripped.length} chars`);
|
|
78
|
+
const signerCommitments = new Set();
|
|
79
|
+
for (const signerCommitment of config.signerCommitments) {
|
|
80
|
+
const normalizedCommitment = normalizeSignerCommitment(signerCommitment);
|
|
81
|
+
if (signerCommitments.has(normalizedCommitment)) {
|
|
82
|
+
throw new Error(`duplicate signer commitment: ${normalizedCommitment}`);
|
|
55
83
|
}
|
|
84
|
+
signerCommitments.add(normalizedCommitment);
|
|
56
85
|
}
|
|
57
86
|
if (config.threshold > config.signerCommitments.length) {
|
|
58
87
|
throw new Error(`threshold (${config.threshold}) cannot exceed number of signers (${config.signerCommitments.length})`);
|
|
59
88
|
}
|
|
60
|
-
if (!config.
|
|
61
|
-
throw new Error('
|
|
89
|
+
if (!config.guardianCommitment) {
|
|
90
|
+
throw new Error('GUARDIAN commitment is required');
|
|
62
91
|
}
|
|
92
|
+
// Validate procedure thresholds if provided
|
|
63
93
|
if (config.procedureThresholds) {
|
|
64
94
|
const seen = new Set();
|
|
65
95
|
for (const pt of config.procedureThresholds) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/account/builder.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,kBAAkB,GAEnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,yBAAyB,EAAE,
|
|
1
|
+
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/account/builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,39 +1,115 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { createMultisigAccount } from './builder.js';
|
|
3
|
+
import { MULTISIG_ECDSA_MASM, MULTISIG_MASM, GUARDIAN_ECDSA_MASM, GUARDIAN_MASM, } from './masm/auth.js';
|
|
4
|
+
import { MULTISIG_GUARDIAN_ACCOUNT_COMPONENT_MASM, MULTISIG_GUARDIAN_ECDSA_ACCOUNT_COMPONENT_MASM, } from './masm/account-components/auth.js';
|
|
5
|
+
const { buildMultisigStorageSlots, buildGuardianStorageSlots, withSupportsAllTypes, compileComponent, MockAccountBuilder, } = vi.hoisted(() => {
|
|
6
|
+
const buildMultisigStorageSlots = vi.fn(() => ['multisig-slots']);
|
|
7
|
+
const buildGuardianStorageSlots = vi.fn(() => ['guardian-slots']);
|
|
8
|
+
const withSupportsAllTypes = vi.fn((component) => component);
|
|
9
|
+
const compileComponent = vi.fn((code, slots) => ({
|
|
10
|
+
code,
|
|
11
|
+
slots,
|
|
12
|
+
withSupportsAllTypes: () => withSupportsAllTypes({ code, slots }),
|
|
13
|
+
}));
|
|
14
|
+
class MockAccountBuilder {
|
|
15
|
+
accountType() {
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
storageMode() {
|
|
19
|
+
return this;
|
|
20
|
+
}
|
|
21
|
+
withAuthComponent() {
|
|
22
|
+
return this;
|
|
23
|
+
}
|
|
24
|
+
withComponent() {
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
withBasicWalletComponent() {
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
build() {
|
|
31
|
+
return {
|
|
32
|
+
account: { id: () => ({ toString: () => '0x' + 'a'.repeat(30) }) },
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
buildMultisigStorageSlots,
|
|
38
|
+
buildGuardianStorageSlots,
|
|
39
|
+
withSupportsAllTypes,
|
|
40
|
+
compileComponent,
|
|
41
|
+
MockAccountBuilder,
|
|
42
|
+
};
|
|
43
|
+
});
|
|
8
44
|
vi.mock('./storage.js', () => ({
|
|
9
|
-
buildMultisigStorageSlots
|
|
10
|
-
|
|
45
|
+
buildMultisigStorageSlots,
|
|
46
|
+
buildGuardianStorageSlots,
|
|
11
47
|
}));
|
|
12
|
-
vi.mock('
|
|
13
|
-
|
|
14
|
-
|
|
48
|
+
vi.mock('@miden-sdk/miden-sdk', () => ({
|
|
49
|
+
AccountBuilder: MockAccountBuilder,
|
|
50
|
+
AccountComponent: {
|
|
51
|
+
compile: compileComponent,
|
|
52
|
+
},
|
|
53
|
+
AccountType: {
|
|
54
|
+
RegularAccountUpdatableCode: 'regular',
|
|
55
|
+
},
|
|
56
|
+
AccountStorageMode: {
|
|
57
|
+
public: () => 'public',
|
|
58
|
+
private: () => 'private',
|
|
59
|
+
},
|
|
15
60
|
}));
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
61
|
+
describe('createMultisigAccount', () => {
|
|
62
|
+
beforeEach(() => {
|
|
63
|
+
vi.stubGlobal('crypto', {
|
|
64
|
+
getRandomValues(buffer) {
|
|
65
|
+
return buffer;
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
buildMultisigStorageSlots.mockClear();
|
|
69
|
+
buildGuardianStorageSlots.mockClear();
|
|
70
|
+
withSupportsAllTypes.mockClear();
|
|
71
|
+
compileComponent.mockClear();
|
|
72
|
+
});
|
|
73
|
+
it('uses Falcon MASM by default', async () => {
|
|
74
|
+
const authBuilder = {
|
|
75
|
+
buildLibrary: vi.fn((libraryPath, source) => ({ libraryPath, source })),
|
|
76
|
+
linkStaticLibrary: vi.fn(),
|
|
77
|
+
compileAccountComponentCode: vi.fn((source) => `auth:${source.slice(0, 16)}`),
|
|
78
|
+
};
|
|
79
|
+
const webClient = {
|
|
80
|
+
createCodeBuilder: vi.fn().mockReturnValue(authBuilder),
|
|
81
|
+
newAccount: vi.fn(),
|
|
82
|
+
};
|
|
83
|
+
await createMultisigAccount(webClient, {
|
|
84
|
+
threshold: 1,
|
|
85
|
+
signerCommitments: ['0x' + '1'.repeat(64)],
|
|
86
|
+
guardianCommitment: '0x' + '2'.repeat(64),
|
|
87
|
+
});
|
|
88
|
+
expect(authBuilder.buildLibrary).toHaveBeenNthCalledWith(1, 'openzeppelin::auth::guardian', GUARDIAN_MASM);
|
|
89
|
+
expect(authBuilder.buildLibrary).toHaveBeenNthCalledWith(2, 'openzeppelin::auth::multisig', MULTISIG_MASM);
|
|
90
|
+
expect(authBuilder.compileAccountComponentCode).toHaveBeenCalledWith(MULTISIG_GUARDIAN_ACCOUNT_COMPONENT_MASM);
|
|
91
|
+
expect(webClient.newAccount).toHaveBeenCalledTimes(1);
|
|
27
92
|
});
|
|
28
|
-
it('
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
93
|
+
it('uses ECDSA MASM when requested', async () => {
|
|
94
|
+
const authBuilder = {
|
|
95
|
+
buildLibrary: vi.fn((libraryPath, source) => ({ libraryPath, source })),
|
|
96
|
+
linkStaticLibrary: vi.fn(),
|
|
97
|
+
compileAccountComponentCode: vi.fn((source) => `auth:${source.slice(0, 16)}`),
|
|
98
|
+
};
|
|
99
|
+
const webClient = {
|
|
100
|
+
createCodeBuilder: vi.fn().mockReturnValue(authBuilder),
|
|
101
|
+
newAccount: vi.fn(),
|
|
102
|
+
};
|
|
103
|
+
await createMultisigAccount(webClient, {
|
|
104
|
+
threshold: 1,
|
|
105
|
+
signerCommitments: ['0x' + '1'.repeat(64)],
|
|
106
|
+
guardianCommitment: '0x' + '2'.repeat(64),
|
|
107
|
+
signatureScheme: 'ecdsa',
|
|
108
|
+
});
|
|
109
|
+
expect(authBuilder.buildLibrary).toHaveBeenNthCalledWith(1, 'openzeppelin::auth::guardian_ecdsa', GUARDIAN_ECDSA_MASM);
|
|
110
|
+
expect(authBuilder.buildLibrary).toHaveBeenNthCalledWith(2, 'openzeppelin::auth::multisig_ecdsa', MULTISIG_ECDSA_MASM);
|
|
111
|
+
expect(authBuilder.compileAccountComponentCode).toHaveBeenCalledWith(MULTISIG_GUARDIAN_ECDSA_ACCOUNT_COMPONENT_MASM);
|
|
112
|
+
expect(webClient.newAccount).toHaveBeenCalledTimes(1);
|
|
37
113
|
});
|
|
38
114
|
});
|
|
39
115
|
//# sourceMappingURL=builder.test.js.map
|