@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,75 @@
1
+ import {
2
+ MidenClient,
3
+ type TransactionProver,
4
+ type TransactionScript,
5
+ WasmWebClient,
6
+ } from '@miden-sdk/miden-sdk';
7
+
8
+ export const DEFAULT_MIDEN_RPC_URL = 'https://rpc.devnet.miden.io';
9
+
10
+ export type RawClientSource = MidenClient | WasmWebClient;
11
+ export interface ScriptLibrarySource {
12
+ namespace: string;
13
+ code: string;
14
+ linking?: 'dynamic' | 'static';
15
+ }
16
+
17
+ const rawClientCache = new WeakMap<MidenClient, Promise<WasmWebClient>>();
18
+
19
+ export function resolveMidenRpcEndpoint(endpoint?: string): string {
20
+ return endpoint ?? DEFAULT_MIDEN_RPC_URL;
21
+ }
22
+
23
+ function isPublicMidenClient(client: RawClientSource): client is MidenClient {
24
+ return 'accounts' in client && 'sync' in client;
25
+ }
26
+
27
+ export function getRawMidenClient(
28
+ client: RawClientSource,
29
+ rpcUrl?: string,
30
+ ): Promise<WasmWebClient> {
31
+ if (!isPublicMidenClient(client)) {
32
+ return Promise.resolve(client);
33
+ }
34
+
35
+ const cached = rawClientCache.get(client);
36
+ if (cached) {
37
+ return cached;
38
+ }
39
+
40
+ const rawClient = WasmWebClient.createClient(
41
+ resolveMidenRpcEndpoint(rpcUrl),
42
+ undefined,
43
+ undefined,
44
+ client.storeIdentifier(),
45
+ );
46
+ rawClientCache.set(client, rawClient);
47
+ return rawClient;
48
+ }
49
+
50
+ export function getTransactionProver(client: RawClientSource): TransactionProver | null {
51
+ return isPublicMidenClient(client) ? client.defaultProver : null;
52
+ }
53
+
54
+ export async function compileTxScript(
55
+ client: RawClientSource,
56
+ code: string,
57
+ libraries: ScriptLibrarySource[] = [],
58
+ rpcUrl?: string,
59
+ ): Promise<TransactionScript> {
60
+ if (isPublicMidenClient(client)) {
61
+ return client.compile.txScript({ code, libraries });
62
+ }
63
+
64
+ const rawClient = await getRawMidenClient(client, rpcUrl);
65
+ const builder = rawClient.createCodeBuilder();
66
+ for (const library of libraries) {
67
+ const builtLibrary = builder.buildLibrary(library.namespace, library.code);
68
+ if (library.linking === 'static') {
69
+ builder.linkStaticLibrary(builtLibrary);
70
+ } else {
71
+ builder.linkDynamicLibrary(builtLibrary);
72
+ }
73
+ }
74
+ return builder.compileTxScript(code);
75
+ }
@@ -6,10 +6,12 @@ vi.mock('@miden-sdk/miden-sdk', () => {
6
6
  serialize: () => new Uint8Array([0, 1, 2, 3, 4, 5]),
7
7
  };
8
8
 
9
+ const mockCommitment = {
10
+ toHex: () => '0x' + 'a'.repeat(64),
11
+ };
12
+
9
13
  const mockPublicKey = {
10
- toCommitment: () => ({
11
- toHex: () => '0x' + 'a'.repeat(64),
12
- }),
14
+ toCommitment: () => mockCommitment,
13
15
  serialize: () => new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
14
16
  };
15
17
 
@@ -27,7 +29,8 @@ vi.mock('@miden-sdk/miden-sdk', () => {
27
29
  })),
28
30
  },
29
31
  AccountId: {
30
- fromHex: vi.fn(() => ({
32
+ fromHex: vi.fn((hex: string) => ({
33
+ toString: () => hex,
31
34
  prefix: () => ({ asInt: () => BigInt(1) }),
32
35
  suffix: () => ({ asInt: () => BigInt(2) }),
33
36
  })),
@@ -77,4 +80,32 @@ describe('EcdsaSigner', () => {
77
80
  expect(mockSecretKey.sign).toHaveBeenCalled();
78
81
  expect(Rpo256.hashElements).toHaveBeenCalledTimes(2);
79
82
  });
83
+
84
+ it('skips rebinding when the signer key is already attached to the same account', async () => {
85
+ const accountId = '0x' + 'd'.repeat(30);
86
+ const midenClient = {
87
+ keystore: {
88
+ getAccountId: vi.fn().mockResolvedValue({ toString: () => accountId }),
89
+ insert: vi.fn().mockResolvedValue(undefined),
90
+ },
91
+ };
92
+
93
+ await signer.bindAccountKey(midenClient as never, accountId);
94
+
95
+ expect(midenClient.keystore.insert).not.toHaveBeenCalled();
96
+ });
97
+
98
+ it('throws when the signer key is already attached to a different account', async () => {
99
+ const midenClient = {
100
+ keystore: {
101
+ getAccountId: vi.fn().mockResolvedValue({ toString: () => '0x' + 'e'.repeat(30) }),
102
+ insert: vi.fn().mockResolvedValue(undefined),
103
+ },
104
+ };
105
+
106
+ await expect(
107
+ signer.bindAccountKey(midenClient as never, '0x' + 'd'.repeat(30)),
108
+ ).rejects.toThrow('already bound to account');
109
+ expect(midenClient.keystore.insert).not.toHaveBeenCalled();
110
+ });
80
111
  });
@@ -1,5 +1,5 @@
1
1
  import type { RequestAuthPayload } from '@openzeppelin/guardian-client';
2
- import { AuthSecretKey } from '@miden-sdk/miden-sdk';
2
+ import { AccountId, AuthSecretKey, type MidenClient, type Word } from '@miden-sdk/miden-sdk';
3
3
  import type { Signer, SignatureScheme } from '../types.js';
4
4
  import { bytesToHex, normalizeHexWord } from '../utils/encoding.js';
5
5
  import { AuthDigest } from '../utils/digest.js';
@@ -9,13 +9,15 @@ export class EcdsaSigner implements Signer {
9
9
  readonly publicKey: string;
10
10
  readonly scheme: SignatureScheme = 'ecdsa';
11
11
  private readonly secretKey: AuthSecretKey;
12
+ private readonly publicKeyCommitment: Word;
12
13
 
13
14
  constructor(secretKey: AuthSecretKey) {
14
15
  this.secretKey = secretKey;
15
16
  const pubKey = secretKey.publicKey();
16
17
  const serialized = pubKey.serialize();
17
18
  this.publicKey = bytesToHex(serialized.slice(1));
18
- this.commitment = normalizeHexWord(pubKey.toCommitment().toHex());
19
+ this.publicKeyCommitment = pubKey.toCommitment();
20
+ this.commitment = normalizeHexWord(this.publicKeyCommitment.toHex());
19
21
  }
20
22
 
21
23
  async signAccountIdWithTimestamp(accountId: string, timestamp: number): Promise<string> {
@@ -37,6 +39,20 @@ export class EcdsaSigner implements Signer {
37
39
  return this.signWord(word);
38
40
  }
39
41
 
42
+ async bindAccountKey(midenClient: MidenClient, accountId: string): Promise<void> {
43
+ const targetAccountId = AccountId.fromHex(accountId);
44
+ const existingAccountId = await midenClient.keystore.getAccountId(this.publicKeyCommitment);
45
+ if (existingAccountId) {
46
+ if (existingAccountId.toString().toLowerCase() === accountId.toLowerCase()) {
47
+ return;
48
+ }
49
+ throw new Error(
50
+ `Signer commitment ${this.commitment} is already bound to account ${existingAccountId.toString()}`,
51
+ );
52
+ }
53
+ await midenClient.keystore.insert(targetAccountId, this.secretKey);
54
+ }
55
+
40
56
  private signWord(word: ReturnType<typeof AuthDigest.fromCommitmentHex>): string {
41
57
  const signature = this.secretKey.sign(word);
42
58
  const signatureBytes = signature.serialize();
@@ -6,10 +6,12 @@ vi.mock('@miden-sdk/miden-sdk', () => {
6
6
  serialize: () => new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
7
7
  };
8
8
 
9
+ const mockCommitment = {
10
+ toHex: () => '0x' + 'a'.repeat(64),
11
+ };
12
+
9
13
  const mockPublicKey = {
10
- toCommitment: () => ({
11
- toHex: () => '0x' + 'a'.repeat(64),
12
- }),
14
+ toCommitment: () => mockCommitment,
13
15
  serialize: () => new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]),
14
16
  };
15
17
 
@@ -30,6 +32,7 @@ vi.mock('@miden-sdk/miden-sdk', () => {
30
32
  },
31
33
  AccountId: {
32
34
  fromHex: vi.fn((hex: string) => ({
35
+ toString: () => hex,
33
36
  prefix: () => ({ asInt: () => BigInt(1) }),
34
37
  suffix: () => ({ asInt: () => BigInt(2) }),
35
38
  })),
@@ -147,4 +150,48 @@ describe('FalconSigner', () => {
147
150
  expect(signature).toBe('0x010203040506070809');
148
151
  });
149
152
  });
153
+
154
+ describe('bindAccountKey', () => {
155
+ it('inserts the signer key when the commitment is not bound yet', async () => {
156
+ const midenClient = {
157
+ keystore: {
158
+ getAccountId: vi.fn().mockResolvedValue(null),
159
+ insert: vi.fn().mockResolvedValue(undefined),
160
+ },
161
+ };
162
+
163
+ await signer.bindAccountKey(midenClient as never, '0x' + 'd'.repeat(30));
164
+
165
+ expect(midenClient.keystore.getAccountId).toHaveBeenCalledTimes(1);
166
+ expect(midenClient.keystore.insert).toHaveBeenCalledTimes(1);
167
+ });
168
+
169
+ it('skips insert when the signer key is already bound to the same account', async () => {
170
+ const accountId = '0x' + 'd'.repeat(30);
171
+ const midenClient = {
172
+ keystore: {
173
+ getAccountId: vi.fn().mockResolvedValue({ toString: () => accountId }),
174
+ insert: vi.fn().mockResolvedValue(undefined),
175
+ },
176
+ };
177
+
178
+ await signer.bindAccountKey(midenClient as never, accountId);
179
+
180
+ expect(midenClient.keystore.insert).not.toHaveBeenCalled();
181
+ });
182
+
183
+ it('throws when the signer key is already bound to a different account', async () => {
184
+ const midenClient = {
185
+ keystore: {
186
+ getAccountId: vi.fn().mockResolvedValue({ toString: () => '0x' + 'e'.repeat(30) }),
187
+ insert: vi.fn().mockResolvedValue(undefined),
188
+ },
189
+ };
190
+
191
+ await expect(
192
+ signer.bindAccountKey(midenClient as never, '0x' + 'd'.repeat(30)),
193
+ ).rejects.toThrow('already bound to account');
194
+ expect(midenClient.keystore.insert).not.toHaveBeenCalled();
195
+ });
196
+ });
150
197
  });
@@ -1,5 +1,5 @@
1
1
  import type { RequestAuthPayload } from '@openzeppelin/guardian-client';
2
- import { AuthSecretKey, type Word } from '@miden-sdk/miden-sdk';
2
+ import { AccountId, AuthSecretKey, type MidenClient, type Word } from '@miden-sdk/miden-sdk';
3
3
  import type { Signer, SignatureScheme } from '../types.js';
4
4
  import { bytesToHex } from '../utils/encoding.js';
5
5
  import { AuthDigest } from '../utils/digest.js';
@@ -9,11 +9,13 @@ export class FalconSigner implements Signer {
9
9
  readonly publicKey: string;
10
10
  readonly scheme: SignatureScheme = 'falcon';
11
11
  private readonly secretKey: AuthSecretKey;
12
+ private readonly publicKeyCommitment: Word;
12
13
 
13
14
  constructor(secretKey: AuthSecretKey) {
14
15
  this.secretKey = secretKey;
15
16
  const pubKey = secretKey.publicKey();
16
- this.commitment = pubKey.toCommitment().toHex();
17
+ this.publicKeyCommitment = pubKey.toCommitment();
18
+ this.commitment = this.publicKeyCommitment.toHex();
17
19
  const serialized = pubKey.serialize();
18
20
  const falconPubKey = serialized.slice(1);
19
21
  this.publicKey = bytesToHex(falconPubKey);
@@ -38,6 +40,20 @@ export class FalconSigner implements Signer {
38
40
  return this.signWord(word);
39
41
  }
40
42
 
43
+ async bindAccountKey(midenClient: MidenClient, accountId: string): Promise<void> {
44
+ const targetAccountId = AccountId.fromHex(accountId);
45
+ const existingAccountId = await midenClient.keystore.getAccountId(this.publicKeyCommitment);
46
+ if (existingAccountId) {
47
+ if (existingAccountId.toString().toLowerCase() === accountId.toLowerCase()) {
48
+ return;
49
+ }
50
+ throw new Error(
51
+ `Signer commitment ${this.commitment} is already bound to account ${existingAccountId.toString()}`,
52
+ );
53
+ }
54
+ await midenClient.keystore.insert(targetAccountId, this.secretKey);
55
+ }
56
+
41
57
  private signWord(word: Word): string {
42
58
  const signature = this.secretKey.sign(word);
43
59
  const signatureBytes = signature.serialize();
@@ -1,11 +1,22 @@
1
- import type { TransactionRequest, Word, WebClient } from '@miden-sdk/miden-sdk';
2
- import { NoteAndArgs, NoteAndArgsArray, TransactionRequestBuilder, Word as WordType } from '@miden-sdk/miden-sdk';
1
+ import type {
2
+ MidenClient,
3
+ TransactionRequest,
4
+ WasmWebClient,
5
+ Word,
6
+ } from '@miden-sdk/miden-sdk';
7
+ import {
8
+ NoteAndArgs,
9
+ NoteAndArgsArray,
10
+ TransactionRequestBuilder,
11
+ Word as WordType,
12
+ } from '@miden-sdk/miden-sdk';
13
+ import { getRawMidenClient } from '../raw-client.js';
3
14
  import { randomWord } from '../utils/random.js';
4
15
  import { normalizeHexWord } from '../utils/encoding.js';
5
16
  import type { SignatureOptions } from './options.js';
6
17
 
7
18
  export async function buildConsumeNotesTransactionRequest(
8
- webClient: WebClient,
19
+ client: MidenClient | WasmWebClient,
9
20
  noteIds: string[],
10
21
  options: SignatureOptions = {},
11
22
  ): Promise<{ request: TransactionRequest; salt: Word }> {
@@ -13,10 +24,10 @@ export async function buildConsumeNotesTransactionRequest(
13
24
  throw new Error('At least one note ID is required');
14
25
  }
15
26
 
16
- // Fetch full Note objects from the client store
27
+ const rawClient = await getRawMidenClient(client, options.midenRpcEndpoint);
17
28
  const noteAndArgsArray = new NoteAndArgsArray();
18
29
  for (const noteIdHex of noteIds) {
19
- const inputNoteRecord = await webClient.getInputNote(noteIdHex);
30
+ const inputNoteRecord = await rawClient.getInputNote(noteIdHex);
20
31
  if (!inputNoteRecord) {
21
32
  throw new Error(`Note not found in local store: ${noteIdHex}`);
22
33
  }
@@ -5,4 +5,5 @@ export interface SignatureOptions {
5
5
  salt?: Word;
6
6
  signatureAdviceMap?: AdviceMap;
7
7
  signatureScheme?: SignatureScheme;
8
+ midenRpcEndpoint?: string;
8
9
  }
@@ -21,10 +21,20 @@ const {
21
21
  mockRandomWord: vi.fn().mockReturnValue({
22
22
  toHex: () => '0x' + 'aa'.repeat(32),
23
23
  }),
24
- mockWordFromHex: vi.fn((hex: string) => ({
25
- toHex: () => hex,
26
- toFelts: () => saltFelts,
27
- })),
24
+ mockWordFromHex: vi.fn((hex: string) => {
25
+ const normalized = hex.toLowerCase();
26
+ return {
27
+ toHex: () => hex,
28
+ toFelts: () => normalized === `0x${'00'.repeat(32)}`
29
+ ? [
30
+ { value: 0n },
31
+ { value: 0n },
32
+ { value: 0n },
33
+ { value: 0n },
34
+ ]
35
+ : saltFelts,
36
+ };
37
+ }),
28
38
  saltFelts,
29
39
  };
30
40
  });
@@ -50,7 +60,7 @@ vi.mock('@miden-sdk/miden-sdk', () => {
50
60
  constructor(_assets: unknown[]) {}
51
61
  }
52
62
 
53
- class NoteInputs {
63
+ class NoteStorage {
54
64
  constructor(_inputs: FeltArray) {}
55
65
  }
56
66
 
@@ -82,7 +92,7 @@ vi.mock('@miden-sdk/miden-sdk', () => {
82
92
  constructor(_faucet: unknown, _amount: bigint) {}
83
93
  }
84
94
 
85
- class OutputNoteArray {
95
+ class NoteArray {
86
96
  constructor(_notes: unknown[]) {}
87
97
  }
88
98
 
@@ -116,13 +126,13 @@ vi.mock('@miden-sdk/miden-sdk', () => {
116
126
  FeltArray,
117
127
  FungibleAsset,
118
128
  MidenArrays: {
119
- OutputNoteArray,
129
+ NoteArray,
120
130
  },
121
131
  Note,
122
132
  NoteAssets,
123
- NoteInputs,
124
133
  NoteMetadata,
125
134
  NoteRecipient,
135
+ NoteStorage,
126
136
  NoteScript: {
127
137
  p2id: vi.fn(() => ({ kind: 'p2id-script' })),
128
138
  },
@@ -135,7 +145,7 @@ vi.mock('@miden-sdk/miden-sdk', () => {
135
145
  OutputNote: {
136
146
  full: vi.fn((note: unknown) => ({ note })),
137
147
  },
138
- Rpo256: {
148
+ Poseidon2: {
139
149
  hashElements: mockHashElements,
140
150
  },
141
151
  TransactionRequestBuilder,
@@ -1,20 +1,18 @@
1
1
  import type { TransactionRequest, Word } from '@miden-sdk/miden-sdk';
2
2
  import {
3
3
  AccountId,
4
- Felt,
5
4
  FeltArray,
6
5
  FungibleAsset,
7
6
  MidenArrays,
8
7
  Note,
9
8
  NoteAssets,
10
- NoteInputs,
11
9
  NoteMetadata,
12
10
  NoteRecipient,
13
11
  NoteScript,
12
+ NoteStorage,
14
13
  NoteTag,
15
14
  NoteType,
16
- OutputNote,
17
- Rpo256,
15
+ Poseidon2,
18
16
  TransactionRequestBuilder,
19
17
  Word as WordType,
20
18
  } from '@miden-sdk/miden-sdk';
@@ -23,12 +21,10 @@ import { normalizeHexWord } from '../utils/encoding.js';
23
21
  import type { SignatureOptions } from './options.js';
24
22
 
25
23
  export function deriveP2idSerialNumber(salt: Word): Word {
26
- return Rpo256.hashElements(new FeltArray([
24
+ const zeroWord = WordType.fromHex(`0x${'00'.repeat(32)}`);
25
+ return Poseidon2.hashElements(new FeltArray([
27
26
  ...salt.toFelts(),
28
- new Felt(0n),
29
- new Felt(0n),
30
- new Felt(0n),
31
- new Felt(0n),
27
+ ...zeroWord.toFelts(),
32
28
  ]));
33
29
  }
34
30
 
@@ -43,12 +39,12 @@ function buildP2idNote(
43
39
  const serialNum = deriveP2idSerialNumber(salt);
44
40
 
45
41
  const noteScript = NoteScript.p2id();
46
- const noteInputs = new NoteInputs(new FeltArray([
42
+ const noteStorage = new NoteStorage(new FeltArray([
47
43
  recipient.suffix(),
48
44
  recipient.prefix(),
49
45
  ]));
50
46
 
51
- const noteRecipient = new NoteRecipient(serialNum, noteScript, noteInputs);
47
+ const noteRecipient = new NoteRecipient(serialNum, noteScript, noteStorage);
52
48
  const noteTag = NoteTag.withAccountTarget(recipient);
53
49
 
54
50
  const noteMetadata = new NoteMetadata(
@@ -84,8 +80,7 @@ export function buildP2idTransactionRequest(
84
80
  authSaltHex,
85
81
  );
86
82
 
87
- const outputNote = OutputNote.full(note);
88
- const outputNotes = new MidenArrays.OutputNoteArray([outputNote]);
83
+ const outputNotes = new MidenArrays.NoteArray([note]);
89
84
 
90
85
  const authSaltForBuilder = WordType.fromHex(normalizeHexWord(authSaltHex));
91
86
 
@@ -1,12 +1,19 @@
1
- import type { TransactionRequest, TransactionSummary, WebClient } from '@miden-sdk/miden-sdk';
1
+ import type {
2
+ MidenClient,
3
+ TransactionRequest,
4
+ TransactionSummary,
5
+ WasmWebClient,
6
+ } from '@miden-sdk/miden-sdk';
2
7
  import { AccountId } from '@miden-sdk/miden-sdk';
8
+ import { getRawMidenClient } from '../raw-client.js';
3
9
 
4
10
  export async function executeForSummary(
5
- client: WebClient,
11
+ client: MidenClient | WasmWebClient,
6
12
  accountId: string,
7
13
  txRequest: TransactionRequest,
14
+ midenRpcEndpoint?: string,
8
15
  ): Promise<TransactionSummary> {
9
16
  const acc = AccountId.fromHex(accountId);
10
- return (client as any).executeForSummary(acc, txRequest);
17
+ const rawClient = await getRawMidenClient(client, midenRpcEndpoint);
18
+ return rawClient.executeForSummary(acc, txRequest);
11
19
  }
12
-
@@ -1,50 +1,58 @@
1
1
  import {
2
2
  AdviceMap,
3
3
  FeltArray,
4
+ type MidenClient,
4
5
  TransactionRequest,
5
6
  TransactionRequestBuilder,
6
7
  TransactionScript,
7
- WebClient,
8
+ type WasmWebClient,
8
9
  Word,
9
10
  Word as WordType,
10
11
  } from '@miden-sdk/miden-sdk';
11
12
  import { GUARDIAN_ECDSA_MASM, GUARDIAN_MASM } from '../account/masm/auth.js';
13
+ import { compileTxScript } from '../raw-client.js';
12
14
  import { normalizeHexWord } from '../utils/encoding.js';
13
15
  import { randomWord } from '../utils/random.js';
14
16
  import type { SignatureOptions } from './options.js';
15
17
  import type { SignatureScheme } from '../types.js';
16
18
 
17
- function buildUpdateGuardianScript(
18
- webClient: WebClient,
19
+ async function buildUpdateGuardianScript(
20
+ client: MidenClient | WasmWebClient,
19
21
  signatureScheme: SignatureScheme,
20
- ): TransactionScript {
21
- const libBuilder = webClient.createCodeBuilder();
22
- const guardianLibraryPath = signatureScheme === 'ecdsa' ? 'openzeppelin::guardian_ecdsa' : 'openzeppelin::guardian';
22
+ midenRpcEndpoint?: string,
23
+ ): Promise<TransactionScript> {
24
+ const guardianLibraryPath = 'oz_guardian::guardian';
23
25
  const guardianMasm = signatureScheme === 'ecdsa' ? GUARDIAN_ECDSA_MASM : GUARDIAN_MASM;
24
- const guardianProcedure = signatureScheme === 'ecdsa' ? 'guardian_ecdsa' : 'guardian';
25
- const guardianLib = libBuilder.buildLibrary(guardianLibraryPath, guardianMasm);
26
- libBuilder.linkDynamicLibrary(guardianLib);
27
26
 
28
27
  const scriptSource = `
29
- use openzeppelin::${guardianProcedure}
28
+ use oz_guardian::guardian
30
29
 
31
30
  begin
32
31
  adv.push_mapval
33
32
  dropw
34
- call.${guardianProcedure}::update_guardian_public_key
33
+ call.guardian::update_guardian_public_key
35
34
  end
36
35
  `;
37
36
 
38
- return libBuilder.compileTxScript(scriptSource);
37
+ return compileTxScript(
38
+ client,
39
+ scriptSource,
40
+ [{ namespace: guardianLibraryPath, code: guardianMasm }],
41
+ midenRpcEndpoint,
42
+ );
39
43
  }
40
44
 
41
45
  export async function buildUpdateGuardianTransactionRequest(
42
- webClient: WebClient,
46
+ client: MidenClient | WasmWebClient,
43
47
  newGuardianPubkey: string,
44
48
  options: SignatureOptions = {},
45
49
  ): Promise<{ request: TransactionRequest; salt: Word }> {
46
50
  const signatureScheme = options.signatureScheme ?? 'falcon';
47
- const script = buildUpdateGuardianScript(webClient, signatureScheme);
51
+ const script = await buildUpdateGuardianScript(
52
+ client,
53
+ signatureScheme,
54
+ options.midenRpcEndpoint,
55
+ );
48
56
 
49
57
  const authSaltHex = options.salt ? options.salt.toHex() : randomWord().toHex();
50
58
 
@@ -1,11 +1,12 @@
1
1
  import {
2
2
  Felt,
3
3
  FeltArray,
4
- Rpo256,
4
+ type MidenClient,
5
+ Poseidon2,
5
6
  TransactionRequest,
6
7
  TransactionRequestBuilder,
7
8
  TransactionScript,
8
- WebClient,
9
+ type WasmWebClient,
9
10
  Word,
10
11
  Word as WordType,
11
12
  } from '@miden-sdk/miden-sdk';
@@ -14,6 +15,7 @@ import {
14
15
  MULTISIG_MASM,
15
16
  } from '../account/masm/auth.js';
16
17
  import { getProcedureRoot, type ProcedureName } from '../procedures.js';
18
+ import { compileTxScript } from '../raw-client.js';
17
19
  import { normalizeHexWord } from '../utils/encoding.js';
18
20
  import { randomWord } from '../utils/random.js';
19
21
  import type { SignatureOptions } from './options.js';
@@ -31,25 +33,22 @@ function buildProcedureThresholdAdvice(
31
33
  new Felt(0n),
32
34
  new Felt(0n),
33
35
  ]);
34
- const configHash = Rpo256.hashElements(payload);
36
+ const configHash = Poseidon2.hashElements(payload);
35
37
  return { configHash, payload };
36
38
  }
37
39
 
38
- function buildUpdateProcedureThresholdScript(
39
- webClient: WebClient,
40
+ async function buildUpdateProcedureThresholdScript(
41
+ client: MidenClient | WasmWebClient,
40
42
  procedure: ProcedureName,
41
43
  threshold: number,
42
44
  signatureScheme: SignatureScheme,
43
- ): TransactionScript {
44
- const libBuilder = webClient.createCodeBuilder();
45
+ midenRpcEndpoint?: string,
46
+ ): Promise<TransactionScript> {
45
47
  const multisigMasm = signatureScheme === 'ecdsa' ? MULTISIG_ECDSA_MASM : MULTISIG_MASM;
46
-
47
- const multisigLib = libBuilder.buildLibrary('auth::multisig', multisigMasm);
48
- libBuilder.linkDynamicLibrary(multisigLib);
49
48
  const procedureRoot = normalizeHexWord(getProcedureRoot(procedure));
50
49
 
51
50
  const scriptSource = `
52
- use auth::multisig
51
+ use oz_multisig::multisig
53
52
 
54
53
  begin
55
54
  push.${procedureRoot}
@@ -60,11 +59,16 @@ begin
60
59
  end
61
60
  `;
62
61
 
63
- return libBuilder.compileTxScript(scriptSource);
62
+ return compileTxScript(
63
+ client,
64
+ scriptSource,
65
+ [{ namespace: 'oz_multisig::multisig', code: multisigMasm }],
66
+ midenRpcEndpoint,
67
+ );
64
68
  }
65
69
 
66
70
  export async function buildUpdateProcedureThresholdTransactionRequest(
67
- webClient: WebClient,
71
+ client: MidenClient | WasmWebClient,
68
72
  procedure: ProcedureName,
69
73
  threshold: number,
70
74
  options: SignatureOptions = {},
@@ -72,11 +76,12 @@ export async function buildUpdateProcedureThresholdTransactionRequest(
72
76
  const signatureScheme = options.signatureScheme ?? 'falcon';
73
77
  const { configHash } = buildProcedureThresholdAdvice(procedure, threshold);
74
78
 
75
- const script = buildUpdateProcedureThresholdScript(
76
- webClient,
79
+ const script = await buildUpdateProcedureThresholdScript(
80
+ client,
77
81
  procedure,
78
82
  threshold,
79
83
  signatureScheme,
84
+ options.midenRpcEndpoint,
80
85
  );
81
86
  const authSaltHex = options.salt ? options.salt.toHex() : randomWord().toHex();
82
87
  const authSalt = WordType.fromHex(normalizeHexWord(authSaltHex));