@openzeppelin/miden-multisig-client 0.15.2 → 0.16.0

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 (98) hide show
  1. package/README.md +25 -1
  2. package/dist/account/builder.d.ts +2 -1
  3. package/dist/account/builder.d.ts.map +1 -1
  4. package/dist/account/builder.js +1 -0
  5. package/dist/account/builder.js.map +1 -1
  6. package/dist/account/builder.test.js +2 -2
  7. package/dist/account/builder.test.js.map +1 -1
  8. package/dist/client.d.ts +9 -5
  9. package/dist/client.d.ts.map +1 -1
  10. package/dist/client.js +5 -5
  11. package/dist/client.js.map +1 -1
  12. package/dist/client.test.js +46 -15
  13. package/dist/client.test.js.map +1 -1
  14. package/dist/connectivity.d.ts +38 -0
  15. package/dist/connectivity.d.ts.map +1 -0
  16. package/dist/connectivity.js +97 -0
  17. package/dist/connectivity.js.map +1 -0
  18. package/dist/connectivity.test.d.ts +2 -0
  19. package/dist/connectivity.test.d.ts.map +1 -0
  20. package/dist/connectivity.test.js +61 -0
  21. package/dist/connectivity.test.js.map +1 -0
  22. package/dist/index.d.ts +9 -3
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +9 -3
  25. package/dist/index.js.map +1 -1
  26. package/dist/multisig.d.ts +68 -7
  27. package/dist/multisig.d.ts.map +1 -1
  28. package/dist/multisig.js +90 -18
  29. package/dist/multisig.js.map +1 -1
  30. package/dist/multisig.test.js +214 -79
  31. package/dist/multisig.test.js.map +1 -1
  32. package/dist/proposal/metadata.d.ts.map +1 -1
  33. package/dist/proposal/metadata.js +12 -0
  34. package/dist/proposal/metadata.js.map +1 -1
  35. package/dist/proposal/metadata.test.js +49 -0
  36. package/dist/proposal/metadata.test.js.map +1 -1
  37. package/dist/raw-client.d.ts +2 -2
  38. package/dist/raw-client.d.ts.map +1 -1
  39. package/dist/raw-client.js +14 -4
  40. package/dist/raw-client.js.map +1 -1
  41. package/dist/raw-client.test.js +25 -3
  42. package/dist/raw-client.test.js.map +1 -1
  43. package/dist/transaction/consumeNotes.d.ts +6 -2
  44. package/dist/transaction/consumeNotes.d.ts.map +1 -1
  45. package/dist/transaction/consumeNotes.js +0 -4
  46. package/dist/transaction/consumeNotes.js.map +1 -1
  47. package/dist/transaction/options.d.ts +3 -0
  48. package/dist/transaction/options.d.ts.map +1 -1
  49. package/dist/transaction/p2id.d.ts +20 -2
  50. package/dist/transaction/p2id.d.ts.map +1 -1
  51. package/dist/transaction/p2id.js +46 -3
  52. package/dist/transaction/p2id.js.map +1 -1
  53. package/dist/transaction/p2id.test.js +66 -6
  54. package/dist/transaction/p2id.test.js.map +1 -1
  55. package/dist/transaction/summary.d.ts +2 -1
  56. package/dist/transaction/summary.d.ts.map +1 -1
  57. package/dist/transaction/summary.js.map +1 -1
  58. package/dist/transaction/updateGuardian.d.ts +6 -2
  59. package/dist/transaction/updateGuardian.d.ts.map +1 -1
  60. package/dist/transaction/updateGuardian.js.map +1 -1
  61. package/dist/transaction/updateProcedureThreshold.d.ts +7 -2
  62. package/dist/transaction/updateProcedureThreshold.d.ts.map +1 -1
  63. package/dist/transaction/updateProcedureThreshold.js.map +1 -1
  64. package/dist/transaction/updateSigners.d.ts +7 -2
  65. package/dist/transaction/updateSigners.d.ts.map +1 -1
  66. package/dist/transaction/updateSigners.js.map +1 -1
  67. package/dist/transaction.d.ts +1 -1
  68. package/dist/transaction.d.ts.map +1 -1
  69. package/dist/transaction.js +1 -1
  70. package/dist/transaction.js.map +1 -1
  71. package/dist/types/proposal.d.ts +5 -0
  72. package/dist/types/proposal.d.ts.map +1 -1
  73. package/dist/types/proposal.js +3 -0
  74. package/dist/types/proposal.js.map +1 -1
  75. package/package.json +3 -3
  76. package/src/account/builder.test.ts +19 -11
  77. package/src/account/builder.ts +2 -1
  78. package/src/client.test.ts +67 -15
  79. package/src/client.ts +18 -10
  80. package/src/connectivity.test.ts +67 -0
  81. package/src/connectivity.ts +111 -0
  82. package/src/index.ts +20 -1
  83. package/src/multisig.test.ts +267 -80
  84. package/src/multisig.ts +109 -20
  85. package/src/proposal/metadata.test.ts +60 -0
  86. package/src/proposal/metadata.ts +14 -0
  87. package/src/raw-client.test.ts +41 -3
  88. package/src/raw-client.ts +15 -5
  89. package/src/transaction/consumeNotes.ts +11 -1
  90. package/src/transaction/options.ts +4 -0
  91. package/src/transaction/p2id.test.ts +98 -8
  92. package/src/transaction/p2id.ts +64 -4
  93. package/src/transaction/summary.ts +12 -0
  94. package/src/transaction/updateGuardian.ts +11 -1
  95. package/src/transaction/updateProcedureThreshold.ts +13 -1
  96. package/src/transaction/updateSigners.ts +13 -1
  97. package/src/transaction.ts +3 -0
  98. package/src/types/proposal.ts +9 -0
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Classification for codeless transport failures (feature
3
+ * `009-human-readable-errors`, User Story 3).
4
+ *
5
+ * When Guardian *is* reached, errors arrive as a {@link GuardianHttpError}
6
+ * carrying the server's stable `code` and user-safe `message` — use those.
7
+ * When Guardian is *not* reached (connection refused, DNS, timeout, TLS, or a
8
+ * proxy 5xx with no Guardian body) no error object exists, so the wallet-facing
9
+ * client must classify the failure and supply a friendly connectivity message
10
+ * rather than surfacing raw `"Failed to fetch"` / `"NetworkError"` text.
11
+ *
12
+ * The detection is intentionally string-matching, mirroring the 0xMiden/wallet
13
+ * `connectivity-classify.ts` heuristic: fetch / DOMException / TypeError each
14
+ * surface failures with different shapes, so the message string is the only
15
+ * stable join key.
16
+ */
17
+ import { GuardianHttpError } from '@openzeppelin/guardian-client';
18
+
19
+ /**
20
+ * Connectivity category for a codeless transport failure:
21
+ * - `network` — the browser/OS reports no connectivity at all
22
+ * (`navigator.onLine === false`); the problem is on the user's side.
23
+ * - `timeout` — the request was sent but timed out or was aborted.
24
+ * - `unreachable` — everything else: Guardian (or an intermediary) could not
25
+ * be reached or did not answer with a Guardian error object.
26
+ */
27
+ export type ConnectivityCategory = 'network' | 'unreachable' | 'timeout';
28
+
29
+ const CONNECTIVITY_MESSAGE = "Can't reach Guardian right now. Check your connection and try again.";
30
+ const GENERIC_MESSAGE = 'Something went wrong. Please try again.';
31
+
32
+ /**
33
+ * `navigator.onLine` is unreliable as a positive signal, but a `false` means
34
+ * the browser/OS is certain there is no connectivity — categorize as
35
+ * `network` rather than `unreachable` (mirrors the wallet's
36
+ * `isDefinitelyOffline`). Guarded for non-browser (Node) contexts.
37
+ */
38
+ function isDefinitelyOffline(): boolean {
39
+ if (typeof navigator === 'undefined') return false;
40
+ if (typeof navigator.onLine !== 'boolean') return false;
41
+ return navigator.onLine === false;
42
+ }
43
+
44
+ /** Classify a codeless transport failure into a {@link ConnectivityCategory}. */
45
+ function classifyTransportError(err: unknown): ConnectivityCategory {
46
+ if (isDefinitelyOffline()) return 'network';
47
+ const message = (err as { message?: string } | null | undefined)?.message ?? String(err ?? '');
48
+ const lower = message.toLowerCase();
49
+ if (lower.includes('timeout') || lower.includes('timed out') || lower.includes('abort')) {
50
+ return 'timeout';
51
+ }
52
+ return 'unreachable';
53
+ }
54
+
55
+ /**
56
+ * Does this error look like a codeless transport/connectivity failure (vs a
57
+ * semantic Guardian error)? String heuristic — see module docs.
58
+ */
59
+ export function isLikelyNetworkError(err: unknown): boolean {
60
+ const message = (err as { message?: string } | null | undefined)?.message ?? String(err ?? '');
61
+ const lower = message.toLowerCase();
62
+ if (lower.includes('failed to fetch')) return true;
63
+ if (lower.includes('networkerror')) return true;
64
+ if (lower.includes('network error')) return true;
65
+ if (lower.includes('load failed')) return true;
66
+ if (lower.includes('abort')) return true;
67
+ if (lower.includes('timeout') || lower.includes('timed out')) return true;
68
+ if (lower.includes('connection')) return true;
69
+ if (lower.includes('econnrefused') || lower.includes('enotfound')) return true;
70
+ if (lower.includes('dns')) return true;
71
+ return false;
72
+ }
73
+
74
+ /** A normalized, wallet-displayable view of any error thrown by a Guardian call. */
75
+ export interface UserFacingError {
76
+ /** Stable Guardian error code, when the server was reached. */
77
+ code?: string;
78
+ /** Connectivity category, when this was a codeless transport failure. */
79
+ category?: ConnectivityCategory;
80
+ /** Short message safe to display verbatim in a wallet UI. */
81
+ userMessage: string;
82
+ /** The original error, for logging/diagnostics. */
83
+ cause: unknown;
84
+ }
85
+
86
+ /**
87
+ * Normalize any error thrown by a Guardian call into a user-facing shape.
88
+ *
89
+ * - A {@link GuardianHttpError} with a parsed `{ code, message }` → the
90
+ * server's stable code + user-safe message (feature 009).
91
+ * - A reachable host that returned no Guardian error object (e.g. a proxy 5xx
92
+ * with an HTML body) → treated as a connectivity failure.
93
+ * - A codeless transport rejection (server never reached) → classified and
94
+ * given the generic connectivity message; the raw transport text is never
95
+ * surfaced as the primary message.
96
+ */
97
+ export function toUserFacingError(err: unknown): UserFacingError {
98
+ if (err instanceof GuardianHttpError) {
99
+ if (err.code && err.userMessage) {
100
+ return { code: err.code, userMessage: err.userMessage, cause: err };
101
+ }
102
+ if (err.status >= 500) {
103
+ return { category: 'unreachable', userMessage: CONNECTIVITY_MESSAGE, cause: err };
104
+ }
105
+ return { userMessage: GENERIC_MESSAGE, cause: err };
106
+ }
107
+ if (isLikelyNetworkError(err)) {
108
+ return { category: classifyTransportError(err), userMessage: CONNECTIVITY_MESSAGE, cause: err };
109
+ }
110
+ return { userMessage: GENERIC_MESSAGE, cause: err };
111
+ }
package/src/index.ts CHANGED
@@ -20,7 +20,8 @@
20
20
  * // Create a signer
21
21
  * const signer = new FalconSigner(secretKey);
22
22
  *
23
- * // Create multisig client
23
+ * // Create multisig client. Both endpoints are required; midenRpcEndpoint
24
+ * // must point at the same network as the injected MidenClient.
24
25
  * const client = new MultisigClient(midenClient, {
25
26
  * guardianEndpoint: 'http://localhost:3000',
26
27
  * midenRpcEndpoint: 'https://rpc.devnet.miden.io',
@@ -54,9 +55,25 @@ export {
54
55
  buildUpdateGuardianTransactionRequest,
55
56
  buildConsumeNotesTransactionRequest,
56
57
  buildP2idTransactionRequest,
58
+ parseP2idNoteType,
59
+ p2idNoteTypeToMetadata,
60
+ type P2idTransactionOptions,
57
61
  } from './transaction.js';
58
62
 
59
63
  export { GuardianHttpClient, GuardianHttpError } from '@openzeppelin/guardian-client';
64
+ export type { GuardianErrorMeta } from '@openzeppelin/guardian-client';
65
+ // Typed error-code vocabulary (issue #318): branch on GuardianErrorCode,
66
+ // never on message text; unknown wire codes surface via rawCode.
67
+ export {
68
+ GUARDIAN_ERROR_CODES,
69
+ isGuardianErrorCode,
70
+ normalizeGuardianErrorCode,
71
+ } from '@openzeppelin/guardian-client';
72
+ export type { GuardianErrorCode } from '@openzeppelin/guardian-client';
73
+
74
+ // Codeless transport-failure classification (feature 009, User Story 3).
75
+ export { isLikelyNetworkError, toUserFacingError } from './connectivity.js';
76
+ export type { ConnectivityCategory, UserFacingError } from './connectivity.js';
60
77
 
61
78
  export {
62
79
  FalconSigner,
@@ -84,6 +101,8 @@ export {
84
101
  MAX_CONSUME_NOTES_METADATA_BYTES,
85
102
  isConsumeNotesV1,
86
103
  isConsumeNotesV2,
104
+ isP2idNoteVisibility,
105
+ type P2idNoteVisibility,
87
106
  } from './types/proposal.js';
88
107
 
89
108
  export {