@openzeppelin/miden-multisig-client 0.13.4 → 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 +7 -4
  38. package/dist/multisig.d.ts.map +1 -1
  39. package/dist/multisig.js +53 -35
  40. package/dist/multisig.js.map +1 -1
  41. package/dist/multisig.test.js +17 -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 +17 -29
  125. package/src/multisig.ts +61 -36
  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
@@ -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));
@@ -2,11 +2,12 @@ import {
2
2
  AdviceMap,
3
3
  Felt,
4
4
  FeltArray,
5
- Rpo256,
5
+ type MidenClient,
6
+ Poseidon2,
6
7
  TransactionRequest,
7
8
  TransactionRequestBuilder,
8
9
  TransactionScript,
9
- WebClient,
10
+ type WasmWebClient,
10
11
  Word,
11
12
  Word as WordType,
12
13
  } from '@miden-sdk/miden-sdk';
@@ -14,6 +15,7 @@ import {
14
15
  MULTISIG_ECDSA_MASM,
15
16
  MULTISIG_MASM,
16
17
  } from '../account/masm/auth.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';
@@ -35,33 +37,35 @@ function buildMultisigConfigAdvice(
35
37
  felts.push(...word.toFelts());
36
38
  }
37
39
  const payload = new FeltArray(felts);
38
- const configHash = Rpo256.hashElements(payload);
40
+ const configHash = Poseidon2.hashElements(payload);
39
41
  return { configHash, payload };
40
42
  }
41
43
 
42
- function buildUpdateSignersScript(
43
- webClient: WebClient,
44
+ async function buildUpdateSignersScript(
45
+ client: MidenClient | WasmWebClient,
44
46
  signatureScheme: SignatureScheme,
45
- ): TransactionScript {
46
- const libBuilder = webClient.createCodeBuilder();
47
+ midenRpcEndpoint?: string,
48
+ ): Promise<TransactionScript> {
47
49
  const multisigMasm = signatureScheme === 'ecdsa' ? MULTISIG_ECDSA_MASM : MULTISIG_MASM;
48
50
 
49
- const multisigLib = libBuilder.buildLibrary('auth::multisig', multisigMasm);
50
- libBuilder.linkDynamicLibrary(multisigLib);
51
-
52
51
  const scriptSource = `
53
- use auth::multisig
52
+ use oz_multisig::multisig
54
53
 
55
54
  begin
56
55
  call.multisig::update_signers_and_threshold
57
56
  end
58
57
  `;
59
58
 
60
- return libBuilder.compileTxScript(scriptSource);
59
+ return compileTxScript(
60
+ client,
61
+ scriptSource,
62
+ [{ namespace: 'oz_multisig::multisig', code: multisigMasm }],
63
+ midenRpcEndpoint,
64
+ );
61
65
  }
62
66
 
63
67
  export async function buildUpdateSignersTransactionRequest(
64
- webClient: WebClient,
68
+ client: MidenClient | WasmWebClient,
65
69
  threshold: number,
66
70
  signerCommitments: string[],
67
71
  options: SignatureOptions = {},
@@ -76,7 +80,11 @@ export async function buildUpdateSignersTransactionRequest(
76
80
  const advice = new AdviceMap();
77
81
  advice.insert(configHashForAdvice, payload);
78
82
 
79
- const script = buildUpdateSignersScript(webClient, signatureScheme);
83
+ const script = await buildUpdateSignersScript(
84
+ client,
85
+ signatureScheme,
86
+ options.midenRpcEndpoint,
87
+ );
80
88
 
81
89
  const authSaltHex = options.salt ? options.salt.toHex() : randomWord().toHex();
82
90
 
@@ -6,7 +6,7 @@ vi.mock('@miden-sdk/miden-sdk', () => ({
6
6
  AdviceMap: vi.fn(),
7
7
  Felt: vi.fn().mockImplementation((v) => ({ value: v })),
8
8
  FeltArray: vi.fn().mockImplementation((arr) => arr),
9
- Rpo256: { hashElements: vi.fn() },
9
+ Poseidon2: { hashElements: vi.fn() },
10
10
  Signature: { deserialize: vi.fn() },
11
11
  TransactionRequestBuilder: vi.fn().mockImplementation(() => ({
12
12
  withCustomScript: vi.fn().mockReturnThis(),
@@ -110,21 +110,21 @@ describe('transaction utilities', () => {
110
110
  });
111
111
 
112
112
  describe('signatureHexToBytes', () => {
113
- it('should prepend auth scheme byte (0 = RpoFalcon512)', () => {
113
+ it('should prepend auth scheme byte (2 = Falcon Poseidon2)', () => {
114
114
  const result = signatureHexToBytes('deadbeef');
115
- expect(result[0]).toBe(0); // RpoFalcon512 scheme byte
115
+ expect(result[0]).toBe(2);
116
116
  expect(result.slice(1)).toEqual(new Uint8Array([0xde, 0xad, 0xbe, 0xef]));
117
117
  });
118
118
 
119
119
  it('should prepend auth scheme byte (1 = ECDSA)', () => {
120
120
  const result = signatureHexToBytes('deadbeef', 'ecdsa');
121
- expect(result[0]).toBe(1); // ECDSA scheme byte
121
+ expect(result[0]).toBe(1);
122
122
  expect(result.slice(1)).toEqual(new Uint8Array([0xde, 0xad, 0xbe, 0xef]));
123
123
  });
124
124
 
125
125
  it('should handle 0x prefix', () => {
126
126
  const result = signatureHexToBytes('0xaabbccdd');
127
- expect(result[0]).toBe(0);
127
+ expect(result[0]).toBe(2);
128
128
  expect(result.slice(1)).toEqual(new Uint8Array([0xaa, 0xbb, 0xcc, 0xdd]));
129
129
  });
130
130
 
@@ -136,7 +136,7 @@ describe('transaction utilities', () => {
136
136
 
137
137
  it('should handle empty signature', () => {
138
138
  const result = signatureHexToBytes('');
139
- expect(result).toEqual(new Uint8Array([0])); // Just the prefix
139
+ expect(result).toEqual(new Uint8Array([2]));
140
140
  });
141
141
  });
142
142
  });
@@ -18,6 +18,8 @@ vi.mock('@miden-sdk/miden-sdk', () => ({
18
18
  }));
19
19
 
20
20
  vi.mock('./signature.js', () => ({
21
+ ECDSA_AUTH_SCHEME_ID: 1,
22
+ FALCON_AUTH_SCHEME_ID: 2,
21
23
  tryComputeCommitmentHex: vi.fn((_hex: string, _scheme: string) => '0x' + 'cc'.repeat(32)),
22
24
  }));
23
25
 
@@ -32,9 +34,9 @@ describe('PublicKeyFormat', () => {
32
34
  expect(result.publicKeyHex).toMatch(/^0x[a-f0-9]{64}$/);
33
35
  });
34
36
 
35
- it('should detect 0x00-prefixed key as falcon', () => {
37
+ it('should detect 0x02-prefixed key as falcon', () => {
36
38
  const bytes = new Uint8Array(200);
37
- bytes[0] = 0x00;
39
+ bytes[0] = 0x02;
38
40
  bytes[1] = 0xab;
39
41
  const result = PublicKeyFormat.parse(bytes);
40
42
  expect(result.scheme).toBe('falcon');