@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.
Files changed (275) hide show
  1. package/README.md +98 -119
  2. package/dist/account/builder.d.ts +18 -0
  3. package/dist/account/builder.d.ts.map +1 -1
  4. package/dist/account/builder.js +59 -29
  5. package/dist/account/builder.js.map +1 -1
  6. package/dist/account/builder.test.js +108 -32
  7. package/dist/account/builder.test.js.map +1 -1
  8. package/dist/account/index.d.ts +1 -1
  9. package/dist/account/index.d.ts.map +1 -1
  10. package/dist/account/index.js +1 -1
  11. package/dist/account/index.js.map +1 -1
  12. package/dist/account/masm/account-components/auth.d.ts +5 -0
  13. package/dist/account/masm/account-components/auth.d.ts.map +1 -0
  14. package/dist/account/masm/account-components/auth.js +67 -0
  15. package/dist/account/masm/account-components/auth.js.map +1 -0
  16. package/dist/account/masm/auth.d.ts +5 -0
  17. package/dist/account/masm/auth.d.ts.map +1 -0
  18. package/dist/account/masm/auth.js +1395 -0
  19. package/dist/account/masm/auth.js.map +1 -0
  20. package/dist/account/masm/index.d.ts +3 -0
  21. package/dist/account/masm/index.d.ts.map +1 -0
  22. package/dist/account/masm/index.js +5 -0
  23. package/dist/account/masm/index.js.map +1 -0
  24. package/dist/account/masm.d.ts +1 -4
  25. package/dist/account/masm.d.ts.map +1 -1
  26. package/dist/account/masm.js +3 -1034
  27. package/dist/account/masm.js.map +1 -1
  28. package/dist/account/storage.d.ts +2 -2
  29. package/dist/account/storage.d.ts.map +1 -1
  30. package/dist/account/storage.js +18 -16
  31. package/dist/account/storage.js.map +1 -1
  32. package/dist/client.d.ts +67 -9
  33. package/dist/client.d.ts.map +1 -1
  34. package/dist/client.js +73 -22
  35. package/dist/client.js.map +1 -1
  36. package/dist/client.test.js +31 -32
  37. package/dist/client.test.js.map +1 -1
  38. package/dist/index.d.ts +54 -12
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +53 -9
  41. package/dist/index.js.map +1 -1
  42. package/dist/inspector.d.ts +32 -6
  43. package/dist/inspector.d.ts.map +1 -1
  44. package/dist/inspector.js +58 -23
  45. package/dist/inspector.js.map +1 -1
  46. package/dist/inspector.test.js +18 -18
  47. package/dist/inspector.test.js.map +1 -1
  48. package/dist/multisig/proposal/execution.d.ts +4 -4
  49. package/dist/multisig/proposal/execution.d.ts.map +1 -1
  50. package/dist/multisig/proposal/execution.js +42 -31
  51. package/dist/multisig/proposal/execution.js.map +1 -1
  52. package/dist/multisig/proposal/parser.d.ts +3 -3
  53. package/dist/multisig/proposal/parser.d.ts.map +1 -1
  54. package/dist/multisig/proposal/parser.js +23 -23
  55. package/dist/multisig/proposal/parser.js.map +1 -1
  56. package/dist/multisig/signing.d.ts +3 -3
  57. package/dist/multisig/signing.d.ts.map +1 -1
  58. package/dist/multisig/signing.js +3 -3
  59. package/dist/multisig/signing.js.map +1 -1
  60. package/dist/multisig.d.ts +188 -48
  61. package/dist/multisig.d.ts.map +1 -1
  62. package/dist/multisig.js +650 -308
  63. package/dist/multisig.js.map +1 -1
  64. package/dist/multisig.test.js +1680 -241
  65. package/dist/multisig.test.js.map +1 -1
  66. package/dist/procedures.d.ts +46 -24
  67. package/dist/procedures.d.ts.map +1 -1
  68. package/dist/procedures.js +46 -21
  69. package/dist/procedures.js.map +1 -1
  70. package/dist/proposal/factory.d.ts +18 -0
  71. package/dist/proposal/factory.d.ts.map +1 -0
  72. package/dist/proposal/factory.js +99 -0
  73. package/dist/proposal/factory.js.map +1 -0
  74. package/dist/proposal/metadata.d.ts +5 -12
  75. package/dist/proposal/metadata.d.ts.map +1 -1
  76. package/dist/proposal/metadata.js +118 -174
  77. package/dist/proposal/metadata.js.map +1 -1
  78. package/dist/proposal/signatures.d.ts +10 -0
  79. package/dist/proposal/signatures.d.ts.map +1 -0
  80. package/dist/proposal/signatures.js +54 -0
  81. package/dist/proposal/signatures.js.map +1 -0
  82. package/dist/signer.d.ts +2 -0
  83. package/dist/signer.d.ts.map +1 -1
  84. package/dist/signer.js +2 -0
  85. package/dist/signer.js.map +1 -1
  86. package/dist/signers/ecdsa.d.ts +3 -0
  87. package/dist/signers/ecdsa.d.ts.map +1 -1
  88. package/dist/signers/ecdsa.js +8 -4
  89. package/dist/signers/ecdsa.js.map +1 -1
  90. package/dist/signers/ecdsa.test.d.ts +2 -0
  91. package/dist/signers/ecdsa.test.d.ts.map +1 -0
  92. package/dist/signers/ecdsa.test.js +65 -0
  93. package/dist/signers/ecdsa.test.js.map +1 -0
  94. package/dist/signers/falcon.d.ts +3 -0
  95. package/dist/signers/falcon.d.ts.map +1 -1
  96. package/dist/signers/falcon.js +8 -4
  97. package/dist/signers/falcon.js.map +1 -1
  98. package/dist/signers/falcon.test.js +12 -0
  99. package/dist/signers/falcon.test.js.map +1 -1
  100. package/dist/signers/miden-wallet.d.ts +3 -1
  101. package/dist/signers/miden-wallet.d.ts.map +1 -1
  102. package/dist/signers/miden-wallet.js +11 -2
  103. package/dist/signers/miden-wallet.js.map +1 -1
  104. package/dist/signers/miden-wallet.test.js +26 -0
  105. package/dist/signers/miden-wallet.test.js.map +1 -1
  106. package/dist/signers/para.d.ts +3 -3
  107. package/dist/signers/para.d.ts.map +1 -1
  108. package/dist/signers/para.js +15 -6
  109. package/dist/signers/para.js.map +1 -1
  110. package/dist/signers/para.test.js +39 -0
  111. package/dist/signers/para.test.js.map +1 -1
  112. package/dist/transaction/consumeNotes.d.ts.map +1 -1
  113. package/dist/transaction/consumeNotes.js +1 -0
  114. package/dist/transaction/consumeNotes.js.map +1 -1
  115. package/dist/transaction/index.d.ts +2 -1
  116. package/dist/transaction/index.d.ts.map +1 -1
  117. package/dist/transaction/index.js +2 -1
  118. package/dist/transaction/index.js.map +1 -1
  119. package/dist/transaction/options.d.ts +1 -1
  120. package/dist/transaction/options.d.ts.map +1 -1
  121. package/dist/transaction/p2id.d.ts +1 -0
  122. package/dist/transaction/p2id.d.ts.map +1 -1
  123. package/dist/transaction/p2id.js +9 -3
  124. package/dist/transaction/p2id.js.map +1 -1
  125. package/dist/transaction/updateGuardian.d.ts +7 -0
  126. package/dist/transaction/updateGuardian.d.ts.map +1 -0
  127. package/dist/transaction/{updatePsm.js → updateGuardian.js} +15 -29
  128. package/dist/transaction/updateGuardian.js.map +1 -0
  129. package/dist/transaction/updateProcedureThreshold.d.ts +9 -0
  130. package/dist/transaction/updateProcedureThreshold.d.ts.map +1 -0
  131. package/dist/transaction/updateProcedureThreshold.js +55 -0
  132. package/dist/transaction/updateProcedureThreshold.js.map +1 -0
  133. package/dist/transaction/updateSigners.d.ts.map +1 -1
  134. package/dist/transaction/updateSigners.js +5 -23
  135. package/dist/transaction/updateSigners.js.map +1 -1
  136. package/dist/transaction.d.ts +2 -1
  137. package/dist/transaction.d.ts.map +1 -1
  138. package/dist/transaction.js +2 -1
  139. package/dist/transaction.js.map +1 -1
  140. package/dist/types/proposal.d.ts +32 -15
  141. package/dist/types/proposal.d.ts.map +1 -1
  142. package/dist/types.d.ts +24 -7
  143. package/dist/types.d.ts.map +1 -1
  144. package/dist/utils/digest.d.ts +5 -0
  145. package/dist/utils/digest.d.ts.map +1 -1
  146. package/dist/utils/digest.js +34 -1
  147. package/dist/utils/digest.js.map +1 -1
  148. package/dist/utils/digest.test.d.ts +2 -0
  149. package/dist/utils/digest.test.d.ts.map +1 -0
  150. package/dist/utils/digest.test.js +48 -0
  151. package/dist/utils/digest.test.js.map +1 -0
  152. package/dist/utils/signature.d.ts +3 -1
  153. package/dist/utils/signature.d.ts.map +1 -1
  154. package/dist/utils/signature.js +31 -6
  155. package/dist/utils/signature.js.map +1 -1
  156. package/dist/utils/word.test.js +1 -52
  157. package/dist/utils/word.test.js.map +1 -1
  158. package/masm/account_components/auth/multisig.masm +13 -0
  159. package/masm/account_components/auth/multisig_ecdsa.masm +13 -0
  160. package/masm/account_components/auth/multisig_guardian.masm +17 -0
  161. package/masm/account_components/auth/multisig_guardian_ecdsa.masm +17 -0
  162. package/masm/auth/guardian.masm +177 -0
  163. package/masm/auth/guardian_ecdsa.masm +178 -0
  164. package/masm/{multisig.masm → auth/multisig.masm} +149 -55
  165. package/masm/{multisig_ecdsa.masm → auth/multisig_ecdsa.masm} +148 -56
  166. package/package.json +11 -9
  167. package/src/account/builder.test.ts +165 -0
  168. package/src/account/builder.ts +71 -34
  169. package/src/account/index.ts +1 -1
  170. package/src/account/masm/account-components/auth.ts +70 -0
  171. package/src/account/masm/auth.ts +1398 -0
  172. package/src/account/masm/index.ts +5 -0
  173. package/src/account/masm.ts +3 -1040
  174. package/src/account/storage.ts +18 -16
  175. package/src/client.test.ts +31 -35
  176. package/src/client.ts +98 -26
  177. package/src/index.ts +84 -22
  178. package/src/inspector.test.ts +17 -17
  179. package/src/inspector.ts +63 -29
  180. package/src/multisig/proposal/execution.ts +66 -49
  181. package/src/multisig/proposal/parser.ts +26 -26
  182. package/src/multisig/signing.ts +4 -4
  183. package/src/multisig.test.ts +2097 -248
  184. package/src/multisig.ts +882 -388
  185. package/src/procedures.ts +50 -26
  186. package/src/proposal/factory.ts +171 -0
  187. package/src/proposal/metadata.ts +165 -0
  188. package/src/proposal/signatures.ts +68 -0
  189. package/src/signer.ts +2 -0
  190. package/src/signers/ecdsa.test.ts +80 -0
  191. package/src/signers/ecdsa.ts +15 -4
  192. package/src/signers/falcon.test.ts +19 -0
  193. package/src/signers/falcon.ts +16 -5
  194. package/src/signers/miden-wallet.test.ts +47 -0
  195. package/src/signers/miden-wallet.ts +18 -1
  196. package/src/signers/para.test.ts +57 -0
  197. package/src/signers/para.ts +26 -7
  198. package/src/transaction/consumeNotes.ts +1 -0
  199. package/src/transaction/index.ts +2 -2
  200. package/src/transaction/options.ts +1 -2
  201. package/src/transaction/p2id.test.ts +190 -0
  202. package/src/transaction/p2id.ts +11 -5
  203. package/src/transaction/rpoRandomCoin.test.ts +64 -0
  204. package/src/transaction/rpoRandomCoin.ts +24 -0
  205. package/src/transaction/{updatePsm.ts → updateGuardian.ts} +19 -32
  206. package/src/transaction/updateProcedureThreshold.ts +97 -0
  207. package/src/transaction/updateSigners.ts +12 -27
  208. package/src/transaction.ts +5 -3
  209. package/src/types/proposal.ts +43 -11
  210. package/src/types.ts +29 -11
  211. package/src/utils/digest.test.ts +55 -0
  212. package/src/utils/digest.ts +51 -1
  213. package/src/utils/signature.ts +47 -9
  214. package/src/utils/word.test.ts +1 -55
  215. package/dist/account.d.ts +0 -104
  216. package/dist/account.d.ts.map +0 -1
  217. package/dist/account.js +0 -136
  218. package/dist/account.js.map +0 -1
  219. package/dist/builder.d.ts +0 -54
  220. package/dist/builder.d.ts.map +0 -1
  221. package/dist/builder.js +0 -78
  222. package/dist/builder.js.map +0 -1
  223. package/dist/http.d.ts +0 -64
  224. package/dist/http.d.ts.map +0 -1
  225. package/dist/http.js +0 -162
  226. package/dist/http.js.map +0 -1
  227. package/dist/keystore.d.ts +0 -65
  228. package/dist/keystore.d.ts.map +0 -1
  229. package/dist/keystore.js +0 -121
  230. package/dist/keystore.js.map +0 -1
  231. package/dist/miden.d.ts +0 -9
  232. package/dist/miden.d.ts.map +0 -1
  233. package/dist/miden.js +0 -26
  234. package/dist/miden.js.map +0 -1
  235. package/dist/multisig/metadata.d.ts +0 -18
  236. package/dist/multisig/metadata.d.ts.map +0 -1
  237. package/dist/multisig/metadata.js +0 -100
  238. package/dist/multisig/metadata.js.map +0 -1
  239. package/dist/multisig/metadata.test.d.ts +0 -2
  240. package/dist/multisig/metadata.test.d.ts.map +0 -1
  241. package/dist/multisig/metadata.test.js +0 -323
  242. package/dist/multisig/metadata.test.js.map +0 -1
  243. package/dist/proposal/exported.d.ts +0 -12
  244. package/dist/proposal/exported.d.ts.map +0 -1
  245. package/dist/proposal/exported.js +0 -88
  246. package/dist/proposal/exported.js.map +0 -1
  247. package/dist/signer.test.d.ts +0 -2
  248. package/dist/signer.test.d.ts.map +0 -1
  249. package/dist/signer.test.js +0 -123
  250. package/dist/signer.test.js.map +0 -1
  251. package/dist/transaction/p2id.interop.test.d.ts +0 -2
  252. package/dist/transaction/p2id.interop.test.d.ts.map +0 -1
  253. package/dist/transaction/p2id.interop.test.js +0 -36
  254. package/dist/transaction/p2id.interop.test.js.map +0 -1
  255. package/dist/transaction/updatePsm.d.ts +0 -7
  256. package/dist/transaction/updatePsm.d.ts.map +0 -1
  257. package/dist/transaction/updatePsm.js.map +0 -1
  258. package/dist/transport/http.d.ts +0 -64
  259. package/dist/transport/http.d.ts.map +0 -1
  260. package/dist/transport/http.js +0 -162
  261. package/dist/transport/http.js.map +0 -1
  262. package/dist/transport/index.d.ts +0 -5
  263. package/dist/transport/index.d.ts.map +0 -1
  264. package/dist/transport/index.js +0 -5
  265. package/dist/transport/index.js.map +0 -1
  266. package/dist/utils/state-validation.d.ts +0 -5
  267. package/dist/utils/state-validation.d.ts.map +0 -1
  268. package/dist/utils/state-validation.js +0 -30
  269. package/dist/utils/state-validation.js.map +0 -1
  270. package/dist/utils/validation.d.ts +0 -6
  271. package/dist/utils/validation.d.ts.map +0 -1
  272. package/dist/utils/validation.js +0 -52
  273. package/dist/utils/validation.js.map +0 -1
  274. package/masm/psm.masm +0 -178
  275. package/masm/psm_ecdsa.masm +0 -179
@@ -0,0 +1,97 @@
1
+ import {
2
+ Felt,
3
+ FeltArray,
4
+ Rpo256,
5
+ TransactionRequest,
6
+ TransactionRequestBuilder,
7
+ TransactionScript,
8
+ WebClient,
9
+ Word,
10
+ Word as WordType,
11
+ } from '@miden-sdk/miden-sdk';
12
+ import {
13
+ MULTISIG_ECDSA_MASM,
14
+ MULTISIG_MASM,
15
+ } from '../account/masm/auth.js';
16
+ import { getProcedureRoot, type ProcedureName } from '../procedures.js';
17
+ import { normalizeHexWord } from '../utils/encoding.js';
18
+ import { randomWord } from '../utils/random.js';
19
+ import type { SignatureOptions } from './options.js';
20
+ import type { SignatureScheme } from '../types.js';
21
+
22
+ function buildProcedureThresholdAdvice(
23
+ procedure: ProcedureName,
24
+ threshold: number,
25
+ ): { configHash: Word; payload: FeltArray } {
26
+ const procedureRoot = WordType.fromHex(normalizeHexWord(getProcedureRoot(procedure)));
27
+ const payload = new FeltArray([
28
+ ...procedureRoot.toFelts(),
29
+ new Felt(BigInt(threshold)),
30
+ new Felt(0n),
31
+ new Felt(0n),
32
+ new Felt(0n),
33
+ ]);
34
+ const configHash = Rpo256.hashElements(payload);
35
+ return { configHash, payload };
36
+ }
37
+
38
+ function buildUpdateProcedureThresholdScript(
39
+ webClient: WebClient,
40
+ procedure: ProcedureName,
41
+ threshold: number,
42
+ signatureScheme: SignatureScheme,
43
+ ): TransactionScript {
44
+ const libBuilder = webClient.createCodeBuilder();
45
+ const multisigMasm = signatureScheme === 'ecdsa' ? MULTISIG_ECDSA_MASM : MULTISIG_MASM;
46
+
47
+ const multisigLib = libBuilder.buildLibrary('auth::multisig', multisigMasm);
48
+ libBuilder.linkDynamicLibrary(multisigLib);
49
+ const procedureRoot = normalizeHexWord(getProcedureRoot(procedure));
50
+
51
+ const scriptSource = `
52
+ use auth::multisig
53
+
54
+ begin
55
+ push.${procedureRoot}
56
+ push.${threshold}
57
+ call.multisig::update_procedure_threshold
58
+ dropw
59
+ drop
60
+ end
61
+ `;
62
+
63
+ return libBuilder.compileTxScript(scriptSource);
64
+ }
65
+
66
+ export async function buildUpdateProcedureThresholdTransactionRequest(
67
+ webClient: WebClient,
68
+ procedure: ProcedureName,
69
+ threshold: number,
70
+ options: SignatureOptions = {},
71
+ ): Promise<{ request: TransactionRequest; salt: Word; configHash: Word }> {
72
+ const signatureScheme = options.signatureScheme ?? 'falcon';
73
+ const { configHash } = buildProcedureThresholdAdvice(procedure, threshold);
74
+
75
+ const script = buildUpdateProcedureThresholdScript(
76
+ webClient,
77
+ procedure,
78
+ threshold,
79
+ signatureScheme,
80
+ );
81
+ const authSaltHex = options.salt ? options.salt.toHex() : randomWord().toHex();
82
+ const authSalt = WordType.fromHex(normalizeHexWord(authSaltHex));
83
+
84
+ let txBuilder = new TransactionRequestBuilder();
85
+ txBuilder = txBuilder.withCustomScript(script);
86
+ txBuilder = txBuilder.withAuthArg(authSalt);
87
+
88
+ if (options.signatureAdviceMap) {
89
+ txBuilder = txBuilder.extendAdviceMap(options.signatureAdviceMap);
90
+ }
91
+
92
+ return {
93
+ request: txBuilder.build(),
94
+ salt: WordType.fromHex(normalizeHexWord(authSaltHex)),
95
+ configHash,
96
+ };
97
+ }
@@ -10,10 +10,14 @@ import {
10
10
  Word,
11
11
  Word as WordType,
12
12
  } from '@miden-sdk/miden-sdk';
13
- import { MULTISIG_ECDSA_MASM, MULTISIG_MASM, PSM_ECDSA_MASM, PSM_MASM } from '../account/masm.js';
13
+ import {
14
+ MULTISIG_ECDSA_MASM,
15
+ MULTISIG_MASM,
16
+ } from '../account/masm/auth.js';
14
17
  import { normalizeHexWord } from '../utils/encoding.js';
15
18
  import { randomWord } from '../utils/random.js';
16
19
  import type { SignatureOptions } from './options.js';
20
+ import type { SignatureScheme } from '../types.js';
17
21
 
18
22
  function buildMultisigConfigAdvice(
19
23
  threshold: number,
@@ -35,31 +39,14 @@ function buildMultisigConfigAdvice(
35
39
  return { configHash, payload };
36
40
  }
37
41
 
38
- function buildUpdateSignersFalconScript(webClient: WebClient): TransactionScript {
39
- const libBuilder = webClient.createCodeBuilder();
40
- const psmLib = libBuilder.buildLibrary('openzeppelin::psm', PSM_MASM);
41
- libBuilder.linkStaticLibrary(psmLib);
42
-
43
- const multisigLib = libBuilder.buildLibrary('auth::multisig', MULTISIG_MASM);
44
- libBuilder.linkDynamicLibrary(multisigLib);
45
-
46
- const scriptSource = `
47
- use auth::multisig
48
-
49
- begin
50
- call.multisig::update_signers_and_threshold
51
- end
52
- `;
53
-
54
- return libBuilder.compileTxScript(scriptSource);
55
- }
56
-
57
- function buildUpdateSignersEcdsaScript(webClient: WebClient): TransactionScript {
42
+ function buildUpdateSignersScript(
43
+ webClient: WebClient,
44
+ signatureScheme: SignatureScheme,
45
+ ): TransactionScript {
58
46
  const libBuilder = webClient.createCodeBuilder();
59
- const psmLib = libBuilder.buildLibrary('openzeppelin::psm_ecdsa', PSM_ECDSA_MASM);
60
- libBuilder.linkStaticLibrary(psmLib);
47
+ const multisigMasm = signatureScheme === 'ecdsa' ? MULTISIG_ECDSA_MASM : MULTISIG_MASM;
61
48
 
62
- const multisigLib = libBuilder.buildLibrary('auth::multisig', MULTISIG_ECDSA_MASM);
49
+ const multisigLib = libBuilder.buildLibrary('auth::multisig', multisigMasm);
63
50
  libBuilder.linkDynamicLibrary(multisigLib);
64
51
 
65
52
  const scriptSource = `
@@ -89,9 +76,7 @@ export async function buildUpdateSignersTransactionRequest(
89
76
  const advice = new AdviceMap();
90
77
  advice.insert(configHashForAdvice, payload);
91
78
 
92
- const script = signatureScheme === 'ecdsa'
93
- ? buildUpdateSignersEcdsaScript(webClient)
94
- : buildUpdateSignersFalconScript(webClient);
79
+ const script = buildUpdateSignersScript(webClient, signatureScheme);
95
80
 
96
81
  const authSaltHex = options.salt ? options.salt.toHex() : randomWord().toHex();
97
82
 
@@ -6,9 +6,11 @@ export {
6
6
  buildP2idTransactionRequest,
7
7
  } from './transaction/p2id.js';
8
8
  export {
9
- buildUpdatePsmTransactionRequest,
10
- } from './transaction/updatePsm.js';
9
+ buildUpdateGuardianTransactionRequest,
10
+ } from './transaction/updateGuardian.js';
11
+ export {
12
+ buildUpdateProcedureThresholdTransactionRequest,
13
+ } from './transaction/updateProcedureThreshold.js';
11
14
  export {
12
15
  buildUpdateSignersTransactionRequest,
13
16
  } from './transaction/updateSigners.js';
14
-
@@ -1,21 +1,32 @@
1
- import type { ProposalType as PsmProposalType, SignatureScheme } from '@openzeppelin/psm-client';
2
- export type ProposalType = Exclude<PsmProposalType, 'custom'>;
1
+ import type {
2
+ ProposalSignature,
3
+ ProposalType as GuardianProposalType,
4
+ SignatureScheme,
5
+ } from '@openzeppelin/guardian-client';
6
+ import type { ProcedureName } from '../procedures.js';
7
+
8
+ export type ProposalType = Exclude<GuardianProposalType, 'custom'>;
9
+
10
+ export type ProposalStatus = 'pending' | 'ready' | 'finalized';
3
11
 
4
12
  export type TransactionProposalStatus =
5
13
  | { type: 'pending'; signaturesCollected: number; signaturesRequired: number; signers: string[] }
6
14
  | { type: 'ready' }
7
15
  | { type: 'finalized' };
8
16
 
9
- export interface TransactionProposalSignature {
17
+ export interface ProposalSignatureEntry {
10
18
  signerId: string;
11
- signature: { scheme: 'falcon' | 'ecdsa'; signature: string; publicKey?: string };
19
+ signature: ProposalSignature;
12
20
  timestamp: string;
13
21
  }
14
22
 
23
+ export type TransactionProposalSignature = ProposalSignatureEntry;
24
+
15
25
  interface BaseProposalMetadata {
16
26
  proposalType: ProposalType;
17
27
  description: string;
18
28
  saltHex?: string;
29
+ requiredSignatures?: number;
19
30
  }
20
31
 
21
32
  export interface UpdateSignersProposalMetadata extends BaseProposalMetadata {
@@ -24,14 +35,20 @@ export interface UpdateSignersProposalMetadata extends BaseProposalMetadata {
24
35
  targetSignerCommitments: string[];
25
36
  }
26
37
 
27
- export interface SwitchPsmProposalMetadata extends BaseProposalMetadata {
28
- proposalType: 'switch_psm';
29
- newPsmPubkey: string;
30
- newPsmEndpoint?: string;
38
+ export interface SwitchGuardianProposalMetadata extends BaseProposalMetadata {
39
+ proposalType: 'switch_guardian';
40
+ newGuardianPubkey: string;
41
+ newGuardianEndpoint?: string;
31
42
  targetThreshold?: number;
32
43
  targetSignerCommitments?: string[];
33
44
  }
34
45
 
46
+ export interface UpdateProcedureThresholdProposalMetadata extends BaseProposalMetadata {
47
+ proposalType: 'update_procedure_threshold';
48
+ targetProcedure: ProcedureName;
49
+ targetThreshold: number;
50
+ }
51
+
35
52
  export interface ConsumeNotesProposalMetadata extends BaseProposalMetadata {
36
53
  proposalType: 'consume_notes';
37
54
  noteIds: string[];
@@ -50,11 +67,22 @@ export interface UnknownProposalMetadata extends BaseProposalMetadata {
50
67
 
51
68
  export type ProposalMetadata =
52
69
  | UpdateSignersProposalMetadata
53
- | SwitchPsmProposalMetadata
70
+ | SwitchGuardianProposalMetadata
71
+ | UpdateProcedureThresholdProposalMetadata
54
72
  | ConsumeNotesProposalMetadata
55
73
  | P2IdProposalMetadata
56
74
  | UnknownProposalMetadata;
57
75
 
76
+ export interface Proposal {
77
+ id: string;
78
+ accountId: string;
79
+ nonce: number;
80
+ status: ProposalStatus;
81
+ txSummary: string;
82
+ signatures: ProposalSignatureEntry[];
83
+ metadata: ProposalMetadata;
84
+ }
85
+
58
86
  export interface TransactionProposal {
59
87
  id: string;
60
88
  commitment: string;
@@ -66,7 +94,7 @@ export interface TransactionProposal {
66
94
  metadata: ProposalMetadata;
67
95
  }
68
96
 
69
- export interface ExportedTransactionProposal {
97
+ export interface ExportedProposal {
70
98
  accountId: string;
71
99
  nonce: number;
72
100
  commitment: string;
@@ -74,11 +102,15 @@ export interface ExportedTransactionProposal {
74
102
  signatures: Array<{
75
103
  commitment: string;
76
104
  signatureHex: string;
105
+ scheme?: SignatureScheme;
106
+ publicKey?: string;
77
107
  timestamp?: string;
78
108
  }>;
79
- metadata?: ProposalMetadata;
109
+ metadata: ProposalMetadata;
80
110
  }
81
111
 
112
+ export type ExportedTransactionProposal = ExportedProposal;
113
+
82
114
  export interface SignTransactionProposalParams {
83
115
  commitment: string;
84
116
  signature: string;
package/src/types.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import type { Account } from '@miden-sdk/miden-sdk';
2
- import type { SignatureScheme } from '@openzeppelin/psm-client';
2
+ import type { SignatureScheme } from '@openzeppelin/guardian-client';
3
3
  import type { ProcedureName } from './procedures.js';
4
- import type { TransactionProposal } from './types/proposal.js';
5
4
  import type { AccountState } from './multisig.js';
6
5
  import type { DetectedMultisigConfig } from './inspector.js';
6
+ import type { TransactionProposal } from './types/proposal.js';
7
7
 
8
8
  export type {
9
9
  Signer,
@@ -23,16 +23,20 @@ export type {
23
23
  DeltaProposalResponse,
24
24
  ProposalsResponse,
25
25
  SignProposalRequest,
26
- } from '@openzeppelin/psm-client';
26
+ } from '@openzeppelin/guardian-client';
27
27
 
28
28
  export type {
29
- TransactionProposal,
30
- TransactionProposalStatus,
31
- TransactionProposalSignature,
29
+ ExportedProposal,
32
30
  ExportedTransactionProposal,
33
- SignTransactionProposalParams,
31
+ Proposal,
34
32
  ProposalMetadata,
33
+ ProposalSignatureEntry,
34
+ ProposalStatus,
35
35
  ProposalType,
36
+ SignTransactionProposalParams,
37
+ TransactionProposal,
38
+ TransactionProposalSignature,
39
+ TransactionProposalStatus,
36
40
  } from './types/proposal.js';
37
41
 
38
42
  export interface SyncResult {
@@ -54,20 +58,33 @@ export interface MultisigAccountState {
54
58
  cosignerCommitments: string[];
55
59
  }
56
60
 
61
+ /**
62
+ * Per-procedure threshold override.
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const thresholds: ProcedureThreshold[] = [
67
+ * { procedure: 'receive_asset', threshold: 1 },
68
+ * { procedure: 'update_signers', threshold: 3 },
69
+ * ];
70
+ * ```
71
+ */
57
72
  export interface ProcedureThreshold {
58
73
  procedure: ProcedureName;
74
+ /** Threshold for this procedure (1 to numSigners) */
59
75
  threshold: number;
60
76
  }
61
77
 
62
78
  export interface MultisigConfig {
63
79
  threshold: number;
64
80
  signerCommitments: string[];
65
- psmCommitment: string;
66
- psmPublicKey?: string;
67
- psmEnabled?: boolean;
81
+ guardianCommitment: string;
82
+ guardianPublicKey?: string;
83
+ guardianEnabled?: boolean;
68
84
  storageMode?: 'private' | 'public';
69
85
  procedureThresholds?: ProcedureThreshold[];
70
86
  signatureScheme?: SignatureScheme;
87
+ seed?: Uint8Array
71
88
  }
72
89
 
73
90
  export interface CreateAccountResult {
@@ -78,7 +95,8 @@ export interface CreateAccountResult {
78
95
  export type TransactionType =
79
96
  | { type: 'p2id'; recipient: string; faucetId: string; amount: bigint }
80
97
  | { type: 'consumeNotes'; noteIds: string[] }
81
- | { type: 'updateSigners'; newThreshold: number; newSignerCommitments: string[] };
98
+ | { type: 'updateSigners'; newThreshold: number; newSignerCommitments: string[] }
99
+ | { type: 'updateProcedureThreshold'; procedure: ProcedureName; threshold: number };
82
100
 
83
101
  export interface NoteAsset {
84
102
  faucetId: string;
@@ -0,0 +1,55 @@
1
+ import { describe, expect, it, vi, beforeEach } from 'vitest';
2
+ import { AuthDigest } from './digest.js';
3
+
4
+ vi.mock('@miden-sdk/miden-sdk', () => ({
5
+ AccountId: {
6
+ fromHex: vi.fn(() => ({
7
+ prefix: () => ({ label: 'prefix' }),
8
+ suffix: () => ({ label: 'suffix' }),
9
+ })),
10
+ },
11
+ Felt: vi.fn().mockImplementation((value: bigint) => ({ value })),
12
+ FeltArray: vi.fn().mockImplementation((elements: unknown[]) => elements),
13
+ Word: {
14
+ fromHex: vi.fn((hex: string) => ({
15
+ toHex: () => hex,
16
+ toFelts: () => [],
17
+ })),
18
+ },
19
+ Rpo256: {
20
+ hashElements: vi.fn().mockReturnValue({
21
+ toHex: () => '0x' + 'aa'.repeat(32),
22
+ toFelts: () => [],
23
+ }),
24
+ },
25
+ }));
26
+
27
+ describe('AuthDigest', () => {
28
+ beforeEach(() => {
29
+ vi.clearAllMocks();
30
+ });
31
+
32
+ it('uses the legacy 4-felt digest for account auth', async () => {
33
+ const { FeltArray, Rpo256 } = await import('@miden-sdk/miden-sdk');
34
+
35
+ AuthDigest.fromAccountIdWithTimestamp('0x' + 'ab'.repeat(15), 1700000000);
36
+
37
+ expect(FeltArray).toHaveBeenCalledWith([
38
+ { label: 'prefix' },
39
+ { label: 'suffix' },
40
+ { value: 1700000000n },
41
+ { value: 0n },
42
+ ]);
43
+ expect(Rpo256.hashElements).toHaveBeenCalledTimes(1);
44
+ });
45
+
46
+ it('includes the request payload hash for request-bound auth', async () => {
47
+ const { Rpo256 } = await import('@miden-sdk/miden-sdk');
48
+
49
+ AuthDigest.fromRequest('0x' + 'ab'.repeat(15), 1700000000, {
50
+ toBytes: () => new Uint8Array([1, 2, 3, 4]),
51
+ } as never);
52
+
53
+ expect(Rpo256.hashElements).toHaveBeenCalledTimes(2);
54
+ });
55
+ });
@@ -1,3 +1,4 @@
1
+ import type { RequestAuthPayload } from '@openzeppelin/guardian-client';
1
2
  import { AccountId, Felt, FeltArray, Rpo256, Word } from '@miden-sdk/miden-sdk';
2
3
 
3
4
  export class AuthDigest {
@@ -11,7 +12,35 @@ export class AuthDigest {
11
12
  prefix,
12
13
  suffix,
13
14
  new Felt(BigInt(timestamp)),
14
- new Felt(BigInt(0)),
15
+ new Felt(0n),
16
+ ]);
17
+
18
+ return Rpo256.hashElements(feltArray);
19
+ }
20
+
21
+ static fromRequest(accountId: string, timestamp: number, requestPayload: RequestAuthPayload): Word {
22
+ return AuthDigest.fromAccountIdTimestampAndPayloadWord(
23
+ accountId,
24
+ timestamp,
25
+ AuthDigest.payloadWordFromBytes(requestPayload.toBytes()),
26
+ );
27
+ }
28
+
29
+ private static fromAccountIdTimestampAndPayloadWord(
30
+ accountId: string,
31
+ timestamp: number,
32
+ payloadWord: Word,
33
+ ): Word {
34
+ const paddedHex = accountId.startsWith('0x') ? accountId : `0x${accountId}`;
35
+ const parsedAccountId = AccountId.fromHex(paddedHex);
36
+ const prefix = parsedAccountId.prefix();
37
+ const suffix = parsedAccountId.suffix();
38
+
39
+ const feltArray = new FeltArray([
40
+ prefix,
41
+ suffix,
42
+ new Felt(BigInt(timestamp)),
43
+ ...payloadWord.toFelts(),
15
44
  ]);
16
45
 
17
46
  return Rpo256.hashElements(feltArray);
@@ -22,4 +51,25 @@ export class AuthDigest {
22
51
  const cleanHex = paddedHex.slice(2).padStart(64, '0');
23
52
  return Word.fromHex(`0x${cleanHex}`);
24
53
  }
54
+
55
+ private static emptyPayloadWord(): Word {
56
+ return Word.fromHex(`0x${'0'.repeat(64)}`);
57
+ }
58
+
59
+ private static payloadWordFromBytes(bytes: Uint8Array): Word {
60
+ if (bytes.length === 0) {
61
+ return AuthDigest.emptyPayloadWord();
62
+ }
63
+
64
+ const payloadElements: Felt[] = [];
65
+ for (let i = 0; i < bytes.length; i += 8) {
66
+ let packed = 0n;
67
+ for (let j = 0; j < 8 && i + j < bytes.length; j += 1) {
68
+ packed |= BigInt(bytes[i + j]) << (8n * BigInt(j));
69
+ }
70
+ payloadElements.push(new Felt(packed));
71
+ }
72
+
73
+ return Rpo256.hashElements(new FeltArray(payloadElements));
74
+ }
25
75
  }
@@ -1,9 +1,12 @@
1
1
  import { AdviceMap, Felt, FeltArray, Rpo256, Signature, Word } from '@miden-sdk/miden-sdk';
2
2
  import * as midenSdk from '@miden-sdk/miden-sdk';
3
3
  import { hexToBytes, normalizeHexWord } from './encoding.js';
4
- import type { SignatureScheme } from '../types.js';
4
+ import type { ProposalSignatureEntry, SignatureScheme } from '../types.js';
5
5
 
6
- export function signatureHexToBytes(hex: string, scheme: SignatureScheme = 'falcon'): Uint8Array {
6
+ export function signatureHexToBytes(
7
+ hex: string,
8
+ scheme: SignatureScheme = 'falcon',
9
+ ): Uint8Array {
7
10
  const sigBytes = hexToBytes(hex);
8
11
  const withPrefix = new Uint8Array(sigBytes.length + 1);
9
12
  withPrefix[0] = scheme === 'ecdsa' ? 1 : 0;
@@ -15,7 +18,7 @@ function bytesToPackedU32Felts(bytes: Uint8Array): Felt[] {
15
18
  const felts: Felt[] = [];
16
19
  for (let i = 0; i < bytes.length; i += 4) {
17
20
  let packed = 0;
18
- for (let j = 0; j < 4 && i + j < bytes.length; j++) {
21
+ for (let j = 0; j < 4 && i + j < bytes.length; j += 1) {
19
22
  packed |= bytes[i + j] << (j * 8);
20
23
  }
21
24
  felts.push(new Felt(BigInt(packed >>> 0)));
@@ -87,7 +90,7 @@ export function verifyEcdsaCommitment(
87
90
  const packedU32Values: number[] = [];
88
91
  for (let i = 0; i < bytes.length; i += 4) {
89
92
  let packed = 0;
90
- for (let j = 0; j < 4 && i + j < bytes.length; j++) {
93
+ for (let j = 0; j < 4 && i + j < bytes.length; j += 1) {
91
94
  packed |= bytes[i + j] << (j * 8);
92
95
  }
93
96
  packedU32Values.push(packed >>> 0);
@@ -101,19 +104,22 @@ export function verifyEcdsaCommitment(
101
104
  return {
102
105
  match: computedHex === expectedNorm,
103
106
  computedHex,
104
- packedFelts: packedU32Values.map(v => v.toString()),
107
+ packedFelts: packedU32Values.map((value) => value.toString()),
105
108
  };
106
- } catch (e) {
109
+ } catch (error) {
107
110
  return {
108
111
  match: false,
109
- computedHex: `ERROR: ${e}`,
112
+ computedHex: `ERROR: ${error}`,
110
113
  packedFelts: [],
111
- error: String(e),
114
+ error: String(error),
112
115
  };
113
116
  }
114
117
  }
115
118
 
116
- export function mergeSignatureAdviceMaps(advice: AdviceMap, entries: Array<{ key: Word; values: Felt[] }>): AdviceMap {
119
+ export function mergeSignatureAdviceMaps(
120
+ advice: AdviceMap,
121
+ entries: Array<{ key: Word; values: Felt[] }>,
122
+ ): AdviceMap {
117
123
  for (const entry of entries) {
118
124
  advice.insert(entry.key, new FeltArray(entry.values));
119
125
  }
@@ -123,3 +129,35 @@ export function mergeSignatureAdviceMaps(advice: AdviceMap, entries: Array<{ key
123
129
  export function toWord(hex: string): Word {
124
130
  return Word.fromHex(normalizeHexWord(hex));
125
131
  }
132
+
133
+ export function normalizeSignerCommitment(signerId: string): string {
134
+ const hex = signerId.startsWith('0x') || signerId.startsWith('0X')
135
+ ? signerId.slice(2)
136
+ : signerId;
137
+
138
+ if (hex.length !== 64 || !/^[0-9a-fA-F]+$/.test(hex)) {
139
+ throw new Error(`expected signerId as 32-byte hex, got ${signerId}`);
140
+ }
141
+
142
+ return normalizeHexWord(signerId);
143
+ }
144
+
145
+ export function canonicalizeSignature(
146
+ signature: ProposalSignatureEntry,
147
+ signerCommitments: Set<string>,
148
+ ): ProposalSignatureEntry {
149
+ try {
150
+ const signerId = normalizeSignerCommitment(signature.signerId);
151
+ if (!signerCommitments.has(signerId)) {
152
+ throw new Error(`signer ${signerId} is not part of this multisig`);
153
+ }
154
+
155
+ return {
156
+ ...signature,
157
+ signerId,
158
+ };
159
+ } catch (error) {
160
+ const message = error instanceof Error ? error.message : String(error);
161
+ throw new Error(message);
162
+ }
163
+ }
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect, vi } from 'vitest';
2
- import { wordElementToBigInt, wordToHex, wordToBytes } from './word.js';
2
+ import { wordElementToBigInt, wordToHex } from './word.js';
3
3
  import { Word } from '@miden-sdk/miden-sdk';
4
4
 
5
5
  // Mock the Miden SDK Word class
@@ -61,58 +61,4 @@ describe('word utilities', () => {
61
61
  expect(hex).toBe(originalHex);
62
62
  });
63
63
  });
64
-
65
- describe('wordToBytes', () => {
66
- it('should convert a word with known felt values to LE bytes', () => {
67
- const word = {
68
- toFelts: () => [
69
- { asInt: () => 1n },
70
- { asInt: () => 2n },
71
- { asInt: () => 3n },
72
- { asInt: () => 4n },
73
- ],
74
- };
75
- const bytes = wordToBytes(word);
76
- expect(bytes.length).toBe(32);
77
- expect(bytes[0]).toBe(1);
78
- expect(bytes[1]).toBe(0);
79
- expect(bytes[8]).toBe(2);
80
- expect(bytes[16]).toBe(3);
81
- expect(bytes[24]).toBe(4);
82
- });
83
-
84
- it('should encode felts in little-endian order', () => {
85
- const word = {
86
- toFelts: () => [
87
- { asInt: () => 0x0102030405060708n },
88
- { asInt: () => 0n },
89
- { asInt: () => 0n },
90
- { asInt: () => 0n },
91
- ],
92
- };
93
- const bytes = wordToBytes(word);
94
- expect(bytes[0]).toBe(0x08);
95
- expect(bytes[1]).toBe(0x07);
96
- expect(bytes[2]).toBe(0x06);
97
- expect(bytes[3]).toBe(0x05);
98
- expect(bytes[4]).toBe(0x04);
99
- expect(bytes[5]).toBe(0x03);
100
- expect(bytes[6]).toBe(0x02);
101
- expect(bytes[7]).toBe(0x01);
102
- });
103
-
104
- it('should handle zero felts', () => {
105
- const word = {
106
- toFelts: () => [
107
- { asInt: () => 0n },
108
- { asInt: () => 0n },
109
- { asInt: () => 0n },
110
- { asInt: () => 0n },
111
- ],
112
- };
113
- const bytes = wordToBytes(word);
114
- expect(bytes.length).toBe(32);
115
- expect(bytes.every((b) => b === 0)).toBe(true);
116
- });
117
- });
118
64
  });