@openzeppelin/miden-multisig-client 0.13.3 → 0.14.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.
Files changed (145) hide show
  1. package/README.md +10 -13
  2. package/dist/account/builder.d.ts +3 -3
  3. package/dist/account/builder.d.ts.map +1 -1
  4. package/dist/account/builder.js +10 -10
  5. package/dist/account/builder.js.map +1 -1
  6. package/dist/account/builder.test.js +16 -14
  7. package/dist/account/builder.test.js.map +1 -1
  8. package/dist/account/masm/account-components/auth.d.ts +4 -4
  9. package/dist/account/masm/account-components/auth.d.ts.map +1 -1
  10. package/dist/account/masm/account-components/auth.js +8 -12
  11. package/dist/account/masm/account-components/auth.js.map +1 -1
  12. package/dist/account/masm/auth.d.ts +4 -4
  13. package/dist/account/masm/auth.d.ts.map +1 -1
  14. package/dist/account/masm/auth.js +226 -124
  15. package/dist/account/masm/auth.js.map +1 -1
  16. package/dist/account/storage.d.ts.map +1 -1
  17. package/dist/account/storage.js +24 -6
  18. package/dist/account/storage.js.map +1 -1
  19. package/dist/account/storage.test.d.ts +2 -0
  20. package/dist/account/storage.test.d.ts.map +1 -0
  21. package/dist/account/storage.test.js +73 -0
  22. package/dist/account/storage.test.js.map +1 -0
  23. package/dist/client.d.ts +9 -9
  24. package/dist/client.d.ts.map +1 -1
  25. package/dist/client.js +24 -14
  26. package/dist/client.js.map +1 -1
  27. package/dist/client.test.js +45 -8
  28. package/dist/client.test.js.map +1 -1
  29. package/dist/index.d.ts +6 -12
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +6 -12
  32. package/dist/index.js.map +1 -1
  33. package/dist/multisig/proposal/execution.d.ts +3 -2
  34. package/dist/multisig/proposal/execution.d.ts.map +1 -1
  35. package/dist/multisig/proposal/execution.js +8 -12
  36. package/dist/multisig/proposal/execution.js.map +1 -1
  37. package/dist/multisig.d.ts +10 -4
  38. package/dist/multisig.d.ts.map +1 -1
  39. package/dist/multisig.js +97 -71
  40. package/dist/multisig.js.map +1 -1
  41. package/dist/multisig.test.js +481 -29
  42. package/dist/multisig.test.js.map +1 -1
  43. package/dist/procedures.d.ts +8 -8
  44. package/dist/procedures.js +8 -8
  45. package/dist/raw-client.d.ts +13 -0
  46. package/dist/raw-client.d.ts.map +1 -0
  47. package/dist/raw-client.js +42 -0
  48. package/dist/raw-client.js.map +1 -0
  49. package/dist/raw-client.test.d.ts +2 -0
  50. package/dist/raw-client.test.d.ts.map +1 -0
  51. package/dist/raw-client.test.js +89 -0
  52. package/dist/raw-client.test.js.map +1 -0
  53. package/dist/signers/ecdsa.d.ts +3 -1
  54. package/dist/signers/ecdsa.d.ts.map +1 -1
  55. package/dist/signers/ecdsa.js +15 -1
  56. package/dist/signers/ecdsa.js.map +1 -1
  57. package/dist/signers/ecdsa.test.js +27 -4
  58. package/dist/signers/ecdsa.test.js.map +1 -1
  59. package/dist/signers/falcon.d.ts +3 -1
  60. package/dist/signers/falcon.d.ts.map +1 -1
  61. package/dist/signers/falcon.js +15 -1
  62. package/dist/signers/falcon.js.map +1 -1
  63. package/dist/signers/falcon.test.js +39 -3
  64. package/dist/signers/falcon.test.js.map +1 -1
  65. package/dist/transaction/consumeNotes.d.ts +2 -2
  66. package/dist/transaction/consumeNotes.d.ts.map +1 -1
  67. package/dist/transaction/consumeNotes.js +5 -4
  68. package/dist/transaction/consumeNotes.js.map +1 -1
  69. package/dist/transaction/options.d.ts +1 -0
  70. package/dist/transaction/options.d.ts.map +1 -1
  71. package/dist/transaction/p2id.d.ts.map +1 -1
  72. package/dist/transaction/p2id.js +7 -10
  73. package/dist/transaction/p2id.js.map +1 -1
  74. package/dist/transaction/p2id.test.js +19 -9
  75. package/dist/transaction/p2id.test.js.map +1 -1
  76. package/dist/transaction/summary.d.ts +2 -2
  77. package/dist/transaction/summary.d.ts.map +1 -1
  78. package/dist/transaction/summary.js +4 -2
  79. package/dist/transaction/summary.js.map +1 -1
  80. package/dist/transaction/updateGuardian.d.ts +2 -2
  81. package/dist/transaction/updateGuardian.d.ts.map +1 -1
  82. package/dist/transaction/updateGuardian.js +8 -11
  83. package/dist/transaction/updateGuardian.js.map +1 -1
  84. package/dist/transaction/updateProcedureThreshold.d.ts +2 -2
  85. package/dist/transaction/updateProcedureThreshold.d.ts.map +1 -1
  86. package/dist/transaction/updateProcedureThreshold.js +8 -10
  87. package/dist/transaction/updateProcedureThreshold.js.map +1 -1
  88. package/dist/transaction/updateSigners.d.ts +2 -2
  89. package/dist/transaction/updateSigners.d.ts.map +1 -1
  90. package/dist/transaction/updateSigners.js +8 -10
  91. package/dist/transaction/updateSigners.js.map +1 -1
  92. package/dist/transaction.test.js +6 -6
  93. package/dist/transaction.test.js.map +1 -1
  94. package/dist/utils/key.d.ts.map +1 -1
  95. package/dist/utils/key.js +3 -3
  96. package/dist/utils/key.js.map +1 -1
  97. package/dist/utils/key.test.js +4 -2
  98. package/dist/utils/key.test.js.map +1 -1
  99. package/dist/utils/signature.d.ts +2 -0
  100. package/dist/utils/signature.d.ts.map +1 -1
  101. package/dist/utils/signature.js +10 -5
  102. package/dist/utils/signature.js.map +1 -1
  103. package/dist/utils/signature.test.js +9 -9
  104. package/dist/utils/signature.test.js.map +1 -1
  105. package/masm/account_components/auth/multisig.masm +2 -3
  106. package/masm/account_components/auth/multisig_ecdsa.masm +2 -3
  107. package/masm/account_components/auth/multisig_guardian.masm +2 -3
  108. package/masm/account_components/auth/multisig_guardian_ecdsa.masm +2 -3
  109. package/masm/auth/guardian.masm +30 -8
  110. package/masm/auth/guardian_ecdsa.masm +24 -7
  111. package/masm/auth/multisig.masm +86 -55
  112. package/masm/auth/multisig_ecdsa.masm +86 -54
  113. package/package.json +3 -3
  114. package/src/account/builder.test.ts +16 -14
  115. package/src/account/builder.ts +13 -12
  116. package/src/account/masm/account-components/auth.ts +8 -12
  117. package/src/account/masm/auth.ts +226 -124
  118. package/src/account/storage.test.ts +90 -0
  119. package/src/account/storage.ts +27 -6
  120. package/src/client.test.ts +52 -8
  121. package/src/client.ts +39 -16
  122. package/src/index.ts +6 -12
  123. package/src/multisig/proposal/execution.ts +18 -14
  124. package/src/multisig.test.ts +572 -29
  125. package/src/multisig.ts +121 -83
  126. package/src/procedures.ts +8 -8
  127. package/src/raw-client.test.ts +133 -0
  128. package/src/raw-client.ts +75 -0
  129. package/src/signers/ecdsa.test.ts +35 -4
  130. package/src/signers/ecdsa.ts +18 -2
  131. package/src/signers/falcon.test.ts +50 -3
  132. package/src/signers/falcon.ts +18 -2
  133. package/src/transaction/consumeNotes.ts +16 -5
  134. package/src/transaction/options.ts +1 -0
  135. package/src/transaction/p2id.test.ts +19 -9
  136. package/src/transaction/p2id.ts +8 -13
  137. package/src/transaction/summary.ts +11 -4
  138. package/src/transaction/updateGuardian.ts +22 -14
  139. package/src/transaction/updateProcedureThreshold.ts +20 -15
  140. package/src/transaction/updateSigners.ts +22 -14
  141. package/src/transaction.test.ts +6 -6
  142. package/src/utils/key.test.ts +4 -2
  143. package/src/utils/key.ts +7 -3
  144. package/src/utils/signature.test.ts +10 -10
  145. package/src/utils/signature.ts +12 -5
@@ -0,0 +1,90 @@
1
+ import { describe, expect, it, vi, beforeEach } from 'vitest';
2
+
3
+ const { storageMaps, storageSlotMap } = vi.hoisted(() => {
4
+ const storageMaps: Array<{ entries: Array<{ key: unknown; value: unknown }> }> = [];
5
+ const storageSlotMap = vi.fn((name, map) => ({ kind: 'map', name, map }));
6
+
7
+ return { storageMaps, storageSlotMap };
8
+ });
9
+
10
+ vi.mock('@miden-sdk/miden-sdk', () => {
11
+ class MockWord {
12
+ data: BigUint64Array | string;
13
+
14
+ constructor(data: BigUint64Array | string) {
15
+ this.data = data;
16
+ }
17
+
18
+ static fromHex(hex: string) {
19
+ return new MockWord(hex);
20
+ }
21
+ }
22
+
23
+ class MockStorageMap {
24
+ entries: Array<{ key: unknown; value: unknown }> = [];
25
+
26
+ constructor() {
27
+ storageMaps.push(this);
28
+ }
29
+
30
+ insert(key: unknown, value: unknown) {
31
+ this.entries.push({ key, value });
32
+ }
33
+ }
34
+
35
+ return {
36
+ Word: MockWord,
37
+ StorageMap: MockStorageMap,
38
+ StorageSlot: {
39
+ fromValue: vi.fn((name, value) => ({ kind: 'value', name, value })),
40
+ map: storageSlotMap,
41
+ },
42
+ };
43
+ });
44
+
45
+ describe('buildMultisigStorageSlots', () => {
46
+ beforeEach(() => {
47
+ storageMaps.length = 0;
48
+ storageSlotMap.mockClear();
49
+ });
50
+
51
+ it('keeps single-signer public-key and scheme maps to the configured signer count', async () => {
52
+ const { buildMultisigStorageSlots } = await import('./storage.js');
53
+
54
+ buildMultisigStorageSlots({
55
+ threshold: 1,
56
+ signerCommitments: ['0x' + '1'.repeat(64)],
57
+ guardianCommitment: '0x' + '2'.repeat(64),
58
+ signatureScheme: 'falcon',
59
+ });
60
+
61
+ const signersMap = storageMaps[0];
62
+ const signerSchemesMap = storageMaps[1];
63
+
64
+ expect(signersMap.entries).toHaveLength(1);
65
+ expect(signerSchemesMap.entries).toHaveLength(1);
66
+ expect(signersMap.entries[0].key).toMatchObject({
67
+ data: new BigUint64Array([0n, 0n, 0n, 0n]),
68
+ });
69
+ expect(signerSchemesMap.entries[0].key).toMatchObject({
70
+ data: new BigUint64Array([0n, 0n, 0n, 0n]),
71
+ });
72
+ });
73
+
74
+ it('does not pad signer maps when there are already multiple signers', async () => {
75
+ const { buildMultisigStorageSlots } = await import('./storage.js');
76
+
77
+ buildMultisigStorageSlots({
78
+ threshold: 1,
79
+ signerCommitments: ['0x' + '1'.repeat(64), '0x' + '3'.repeat(64)],
80
+ guardianCommitment: '0x' + '2'.repeat(64),
81
+ signatureScheme: 'falcon',
82
+ });
83
+
84
+ const signersMap = storageMaps[0];
85
+ const signerSchemesMap = storageMaps[1];
86
+
87
+ expect(signersMap.entries).toHaveLength(2);
88
+ expect(signerSchemesMap.entries).toHaveLength(2);
89
+ });
90
+ });
@@ -7,6 +7,7 @@ import { getProcedureRoot } from '../procedures.js';
7
7
  const MULTISIG_SLOT_NAMES = {
8
8
  THRESHOLD_CONFIG: 'openzeppelin::multisig::threshold_config',
9
9
  SIGNER_PUBLIC_KEYS: 'openzeppelin::multisig::signer_public_keys',
10
+ SIGNER_SCHEME_IDS: 'openzeppelin::multisig::signer_scheme_ids',
10
11
  EXECUTED_TRANSACTIONS: 'openzeppelin::multisig::executed_transactions',
11
12
  PROCEDURE_THRESHOLDS: 'openzeppelin::multisig::procedure_thresholds',
12
13
  } as const;
@@ -14,11 +15,17 @@ const MULTISIG_SLOT_NAMES = {
14
15
  const GUARDIAN_SLOT_NAMES = {
15
16
  SELECTOR: 'openzeppelin::guardian::selector',
16
17
  PUBLIC_KEY: 'openzeppelin::guardian::public_key',
18
+ SCHEME_ID: 'openzeppelin::guardian::scheme_id',
17
19
  } as const;
18
20
 
21
+ function signerMapKey(index: bigint): Word {
22
+ return new Word(new BigUint64Array([index, 0n, 0n, 0n]));
23
+ }
24
+
19
25
  export class StorageLayoutBuilder {
20
26
  buildMultisigSlots(config: MultisigConfig): StorageSlot[] {
21
27
  const numSigners = config.signerCommitments.length;
28
+ const schemeId = config.signatureScheme === 'ecdsa' ? 1n : 2n;
22
29
  const slot0Word = new Word(
23
30
  new BigUint64Array([
24
31
  BigInt(config.threshold),
@@ -31,13 +38,21 @@ export class StorageLayoutBuilder {
31
38
 
32
39
  const signersMap = new StorageMap();
33
40
  config.signerCommitments.forEach((commitment, index) => {
34
- const key = new Word(new BigUint64Array([BigInt(index), 0n, 0n, 0n]));
41
+ const key = signerMapKey(BigInt(index));
35
42
  const value = Word.fromHex(ensureHexPrefix(commitment));
36
43
  signersMap.insert(key, value);
37
44
  });
38
45
  const slot1 = StorageSlot.map(MULTISIG_SLOT_NAMES.SIGNER_PUBLIC_KEYS, signersMap);
39
46
 
40
- const slot2 = StorageSlot.map(MULTISIG_SLOT_NAMES.EXECUTED_TRANSACTIONS, new StorageMap());
47
+ const signerSchemesMap = new StorageMap();
48
+ config.signerCommitments.forEach((_, index) => {
49
+ const key = signerMapKey(BigInt(index));
50
+ const value = new Word(new BigUint64Array([schemeId, 0n, 0n, 0n]));
51
+ signerSchemesMap.insert(key, value);
52
+ });
53
+ const slot2 = StorageSlot.map(MULTISIG_SLOT_NAMES.SIGNER_SCHEME_IDS, signerSchemesMap);
54
+
55
+ const slot3 = StorageSlot.map(MULTISIG_SLOT_NAMES.EXECUTED_TRANSACTIONS, new StorageMap());
41
56
 
42
57
  // Map entries: PROC_ROOT => [proc_threshold, 0, 0, 0]
43
58
  // Use SDK's Word.fromHex to match how account code procedure roots are represented
@@ -50,23 +65,29 @@ export class StorageLayoutBuilder {
50
65
  procThresholdMap.insert(key, value);
51
66
  }
52
67
  }
53
- const slot3 = StorageSlot.map(MULTISIG_SLOT_NAMES.PROCEDURE_THRESHOLDS, procThresholdMap);
68
+ const slot4 = StorageSlot.map(MULTISIG_SLOT_NAMES.PROCEDURE_THRESHOLDS, procThresholdMap);
54
69
 
55
- return [slot0, slot1, slot2, slot3];
70
+ return [slot0, slot1, slot2, slot3, slot4];
56
71
  }
57
72
 
58
73
  buildGuardianSlots(config: MultisigConfig): StorageSlot[] {
59
74
  const selector = config.guardianEnabled !== false ? 1n : 0n;
75
+ const schemeId = config.signatureScheme === 'ecdsa' ? 1n : 2n;
60
76
  const selectorWord = new Word(new BigUint64Array([selector, 0n, 0n, 0n]));
61
77
  const slot0 = StorageSlot.fromValue(GUARDIAN_SLOT_NAMES.SELECTOR, selectorWord);
62
78
 
63
79
  const guardianKeyMap = new StorageMap();
64
- const zeroKey = new Word(new BigUint64Array([0n, 0n, 0n, 0n]));
80
+ const zeroKey = signerMapKey(0n);
65
81
  const guardianKey = Word.fromHex(ensureHexPrefix(config.guardianCommitment));
66
82
  guardianKeyMap.insert(zeroKey, guardianKey);
67
83
  const slot1 = StorageSlot.map(GUARDIAN_SLOT_NAMES.PUBLIC_KEY, guardianKeyMap);
68
84
 
69
- return [slot0, slot1];
85
+ const guardianSchemeMap = new StorageMap();
86
+ const guardianScheme = new Word(new BigUint64Array([schemeId, 0n, 0n, 0n]));
87
+ guardianSchemeMap.insert(zeroKey, guardianScheme);
88
+ const slot2 = StorageSlot.map(GUARDIAN_SLOT_NAMES.SCHEME_ID, guardianSchemeMap);
89
+
90
+ return [slot0, slot1, slot2];
70
91
  }
71
92
  }
72
93
 
@@ -63,14 +63,13 @@ describe('MultisigClient', () => {
63
63
  mockFetch.mockReset();
64
64
 
65
65
  webClient = {
66
- createScriptBuilder: vi.fn(),
67
- executeTransaction: vi.fn(),
68
- proveTransaction: vi.fn(),
69
- submitProvenTransaction: vi.fn(),
70
- applyTransaction: vi.fn(),
71
- syncState: vi.fn(),
72
- newAccount: vi.fn(),
73
- getAccount: vi.fn().mockResolvedValue(null),
66
+ accounts: {
67
+ get: vi.fn().mockResolvedValue(null),
68
+ insert: vi.fn().mockResolvedValue(undefined),
69
+ },
70
+ keystore: {
71
+ insert: vi.fn().mockResolvedValue(undefined),
72
+ },
74
73
  };
75
74
 
76
75
  mockSigner = {
@@ -132,6 +131,23 @@ describe('MultisigClient', () => {
132
131
  const multisig = await client.create(config, mockSigner);
133
132
  expect(multisig.signerCommitment).toBe(mockSigner.commitment);
134
133
  });
134
+
135
+ it('binds the signer auth key to the created account when supported', async () => {
136
+ const client = new MultisigClient(webClient);
137
+ const bindAccountKey = vi.fn().mockResolvedValue(undefined);
138
+ const bindingSigner = {
139
+ ...mockSigner,
140
+ bindAccountKey,
141
+ };
142
+
143
+ await client.create({
144
+ threshold: 1,
145
+ signerCommitments: ['0x' + 'a'.repeat(64)],
146
+ guardianCommitment: '0x' + 'c'.repeat(64),
147
+ }, bindingSigner);
148
+
149
+ expect(bindAccountKey).toHaveBeenCalledWith(webClient, '0x' + 'a'.repeat(30));
150
+ });
135
151
  });
136
152
 
137
153
  describe('load', () => {
@@ -160,6 +176,8 @@ describe('MultisigClient', () => {
160
176
  expect(multisig.signerCommitments).toEqual(['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)]);
161
177
  expect(multisig.guardianCommitment).toBe('0x' + 'c'.repeat(64));
162
178
  expect(multisig.account).not.toBeNull();
179
+ expect(webClient.accounts.get).toHaveBeenCalledTimes(1);
180
+ expect(webClient.accounts.insert).toHaveBeenCalledTimes(1);
163
181
  });
164
182
 
165
183
  it('should throw if account not found on GUARDIAN', async () => {
@@ -204,6 +222,32 @@ describe('MultisigClient', () => {
204
222
  const multisig = await client.load(accountId, mockSigner);
205
223
 
206
224
  await expect(multisig.registerOnGuardian()).resolves.toBeUndefined();
225
+ expect(webClient.accounts.get).toHaveBeenCalledTimes(1);
226
+ expect(webClient.accounts.insert).toHaveBeenCalledTimes(1);
227
+ });
228
+
229
+ it('binds the signer auth key after loading an account when supported', async () => {
230
+ const client = new MultisigClient(webClient);
231
+ const bindAccountKey = vi.fn().mockResolvedValue(undefined);
232
+ const bindingSigner = {
233
+ ...mockSigner,
234
+ bindAccountKey,
235
+ };
236
+
237
+ mockFetch.mockResolvedValueOnce({
238
+ ok: true,
239
+ json: async () => ({
240
+ account_id: '0x' + 'd'.repeat(30),
241
+ commitment: '0x' + 'e'.repeat(64),
242
+ state_json: { data: 'base64state' },
243
+ created_at: '2024-01-01T00:00:00Z',
244
+ updated_at: '2024-01-02T00:00:00Z',
245
+ }),
246
+ });
247
+
248
+ await client.load('0x' + 'd'.repeat(30), bindingSigner);
249
+
250
+ expect(bindAccountKey).toHaveBeenCalledWith(webClient, '0x' + 'd'.repeat(30));
207
251
  });
208
252
  });
209
253
  });
package/src/client.ts CHANGED
@@ -5,13 +5,29 @@
5
5
  * to create new multisig accounts and load existing ones.
6
6
  */
7
7
 
8
- import { type WebClient, Account, AccountId } from '@miden-sdk/miden-sdk';
8
+ import { type MidenClient, Account, AccountId } from '@miden-sdk/miden-sdk';
9
9
  import { GuardianHttpClient } from '@openzeppelin/guardian-client';
10
10
  import { Multisig } from './multisig.js';
11
11
  import { createMultisigAccount } from './account/index.js';
12
12
  import { AccountInspector } from './inspector.js';
13
+ import { getRawMidenClient, resolveMidenRpcEndpoint } from './raw-client.js';
13
14
  import type { MultisigConfig, Signer } from './types.js';
14
15
 
16
+ interface AccountKeyBindingSigner {
17
+ bindAccountKey?(midenClient: MidenClient, accountId: string): Promise<void>;
18
+ }
19
+
20
+ async function bindSignerAccountKey(
21
+ signer: Signer,
22
+ midenClient: MidenClient,
23
+ accountId: string,
24
+ ): Promise<void> {
25
+ const bindingSigner = signer as Signer & AccountKeyBindingSigner;
26
+ if (typeof bindingSigner.bindAccountKey === 'function') {
27
+ await bindingSigner.bindAccountKey(midenClient, accountId);
28
+ }
29
+ }
30
+
15
31
  /**
16
32
  * Configuration for MultisigClient.
17
33
  */
@@ -28,17 +44,17 @@ export interface MultisigClientConfig {
28
44
  * @example
29
45
  * ```typescript
30
46
  * import { MultisigClient, FalconSigner } from '@openzeppelin/miden-multisig-client';
31
- * import { WebClient, SecretKey } from '@miden-sdk/miden-sdk';
47
+ * import { MidenClient, AuthSecretKey } from '@miden-sdk/miden-sdk';
32
48
  *
33
49
  * // Initialize
34
- * const webClient = await WebClient.createClient('https://rpc.testnet.miden.io:443');
35
- * const secretKey = SecretKey.rpoFalconWithRNG(seed);
50
+ * const midenClient = await MidenClient.createDevnet();
51
+ * const secretKey = AuthSecretKey.rpoFalconWithRNG(seed);
36
52
  * const signer = new FalconSigner(secretKey);
37
53
  *
38
54
  * // Create client
39
- * const client = new MultisigClient(webClient, {
55
+ * const client = new MultisigClient(midenClient, {
40
56
  * guardianEndpoint: 'http://localhost:3000',
41
- * midenRpcEndpoint: 'https://rpc.testnet.miden.io:443',
57
+ * midenRpcEndpoint: 'https://rpc.devnet.miden.io',
42
58
  * });
43
59
  *
44
60
  * // Get GUARDIAN pubkey for config
@@ -50,13 +66,13 @@ export interface MultisigClientConfig {
50
66
  * ```
51
67
  */
52
68
  export class MultisigClient {
53
- private readonly webClient: WebClient;
54
- private readonly midenRpcEndpoint?: string;
69
+ private readonly midenClient: MidenClient;
70
+ private readonly midenRpcEndpoint: string;
55
71
  private _guardianClient: GuardianHttpClient;
56
72
 
57
- constructor(webClient: WebClient, config: MultisigClientConfig = {}) {
58
- this.webClient = webClient;
59
- this.midenRpcEndpoint = config.midenRpcEndpoint;
73
+ constructor(midenClient: MidenClient, config: MultisigClientConfig = {}) {
74
+ this.midenClient = midenClient;
75
+ this.midenRpcEndpoint = resolveMidenRpcEndpoint(config.midenRpcEndpoint);
60
76
  this._guardianClient = new GuardianHttpClient(config.guardianEndpoint ?? 'http://localhost:3000');
61
77
  }
62
78
 
@@ -86,14 +102,20 @@ export class MultisigClient {
86
102
  async create(config: MultisigConfig, signer: Signer): Promise<Multisig> {
87
103
  this._guardianClient.setSigner(signer);
88
104
 
89
- const { account } = await createMultisigAccount(this.webClient, config);
105
+ const { account } = await createMultisigAccount(
106
+ this.midenClient,
107
+ config,
108
+ this.midenRpcEndpoint,
109
+ );
110
+ const accountId = account.id().toString();
111
+ await bindSignerAccountKey(signer, this.midenClient, accountId);
90
112
 
91
113
  return new Multisig(
92
114
  account,
93
115
  config,
94
116
  this._guardianClient,
95
117
  signer,
96
- this.webClient,
118
+ this.midenClient,
97
119
  undefined,
98
120
  this.midenRpcEndpoint
99
121
  );
@@ -134,17 +156,18 @@ export class MultisigClient {
134
156
  ),
135
157
  };
136
158
 
137
- const existingAccount = await this.webClient.getAccount(AccountId.fromHex(accountId));
159
+ const existingAccount = await this.midenClient.accounts.get(AccountId.fromHex(accountId));
138
160
  if (!existingAccount) {
139
- await this.webClient.newAccount(account, true);
161
+ await this.midenClient.accounts.insert({ account, overwrite: true });
140
162
  }
163
+ await bindSignerAccountKey(signer, this.midenClient, accountId);
141
164
 
142
165
  return new Multisig(
143
166
  account,
144
167
  config,
145
168
  this._guardianClient,
146
169
  signer,
147
- this.webClient,
170
+ this.midenClient,
148
171
  accountId,
149
172
  this.midenRpcEndpoint
150
173
  );
package/src/index.ts CHANGED
@@ -9,27 +9,21 @@
9
9
  * MultisigClient,
10
10
  * FalconSigner,
11
11
  * } from '@openzeppelin/miden-multisig-client';
12
- * import { WebClient, SecretKey } from '@miden-sdk/miden-sdk';
12
+ * import { MidenClient, AuthSecretKey } from '@miden-sdk/miden-sdk';
13
13
  *
14
- * // Initialize WebClient
15
- * const webClient = await WebClient.createClient('https://rpc.testnet.miden.io:443');
16
- * await webClient.syncState();
17
- *
18
- * // Generate a key dynamically
19
- * const seed = new Uint8Array(32);
20
- * crypto.getRandomValues(seed);
21
- * const secretKey = SecretKey.rpoFalconWithRNG(seed);
14
+ * const midenClient = await MidenClient.createDevnet();
15
+ * const secretKey = AuthSecretKey.rpoFalconWithRNG(undefined);
22
16
  *
23
17
  * // Store in miden-sdk's keystore
24
- * await webClient.addAccountSecretKeyToWebStore(secretKey);
18
+ * await midenClient.keystore.insert(secretKey.publicKey(), secretKey);
25
19
  *
26
20
  * // Create a signer
27
21
  * const signer = new FalconSigner(secretKey);
28
22
  *
29
23
  * // Create multisig client
30
- * const client = new MultisigClient(webClient, {
24
+ * const client = new MultisigClient(midenClient, {
31
25
  * guardianEndpoint: 'http://localhost:3000',
32
- * midenRpcEndpoint: 'https://rpc.testnet.miden.io:443',
26
+ * midenRpcEndpoint: 'https://rpc.devnet.miden.io',
33
27
  * });
34
28
  *
35
29
  * // Get GUARDIAN pubkey for config
@@ -1,7 +1,10 @@
1
1
  import { type DeltaObject, type GuardianHttpClient } from '@openzeppelin/guardian-client';
2
- import type { WebClient, TransactionRequest } from '@miden-sdk/miden-sdk';
2
+ import type {
3
+ MidenClient,
4
+ TransactionProver,
5
+ TransactionRequest,
6
+ } from '@miden-sdk/miden-sdk';
3
7
  import {
4
- AccountId,
5
8
  AdviceMap,
6
9
  FeltArray,
7
10
  Signature,
@@ -45,7 +48,8 @@ interface ExecuteProposalWorkflowParams {
45
48
  signatureScheme: 'falcon' | 'ecdsa';
46
49
  getEffectiveThreshold: (proposalType: ProposalType) => number;
47
50
  guardian: GuardianHttpClient;
48
- webClient: WebClient;
51
+ midenClient: MidenClient;
52
+ transactionProver?: TransactionProver | null;
49
53
  }
50
54
 
51
55
  export async function executeProposalWorkflow(
@@ -89,7 +93,11 @@ export async function executeProposalWorkflow(
89
93
  executionData.saltHex,
90
94
  adviceMap,
91
95
  );
92
- await submitTransaction(params.webClient, params.accountId, finalRequest);
96
+ await submitTransaction(
97
+ params.midenClient,
98
+ params.accountId,
99
+ finalRequest,
100
+ );
93
101
  }
94
102
 
95
103
 
@@ -297,7 +305,7 @@ async function buildFinalRequest(
297
305
  );
298
306
  }
299
307
  const { request } = await buildConsumeNotesTransactionRequest(
300
- params.webClient,
308
+ params.midenClient,
301
309
  metadata.noteIds,
302
310
  { salt: normalizedSalt, signatureAdviceMap: adviceMap },
303
311
  );
@@ -310,7 +318,7 @@ async function buildFinalRequest(
310
318
  );
311
319
  }
312
320
  const { request } = await buildUpdateGuardianTransactionRequest(
313
- params.webClient,
321
+ params.midenClient,
314
322
  metadata.newGuardianPubkey,
315
323
  {
316
324
  salt: normalizedSalt,
@@ -322,7 +330,7 @@ async function buildFinalRequest(
322
330
  }
323
331
  case 'update_procedure_threshold': {
324
332
  const { request } = await buildUpdateProcedureThresholdTransactionRequest(
325
- params.webClient,
333
+ params.midenClient,
326
334
  metadata.targetProcedure,
327
335
  metadata.targetThreshold,
328
336
  {
@@ -354,7 +362,7 @@ async function buildFinalRequest(
354
362
  );
355
363
  default: {
356
364
  const { request } = await buildUpdateSignersTransactionRequest(
357
- params.webClient,
365
+ params.midenClient,
358
366
  metadata.targetThreshold,
359
367
  metadata.targetSignerCommitments,
360
368
  {
@@ -369,13 +377,9 @@ async function buildFinalRequest(
369
377
  }
370
378
 
371
379
  async function submitTransaction(
372
- webClient: WebClient,
380
+ midenClient: MidenClient,
373
381
  accountIdHex: string,
374
382
  request: TransactionRequest,
375
383
  ): Promise<void> {
376
- const accountId = AccountId.fromHex(accountIdHex);
377
- const result = await webClient.executeTransaction(accountId, request);
378
- const proven = await webClient.proveTransaction(result, null);
379
- const submissionHeight = await webClient.submitProvenTransaction(proven, result);
380
- await webClient.applyTransaction(result, submissionHeight);
384
+ await midenClient.transactions.submit(accountIdHex, request);
381
385
  }