@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.
- package/README.md +25 -1
- package/dist/account/builder.d.ts +2 -1
- package/dist/account/builder.d.ts.map +1 -1
- package/dist/account/builder.js +1 -0
- package/dist/account/builder.js.map +1 -1
- package/dist/account/builder.test.js +2 -2
- package/dist/account/builder.test.js.map +1 -1
- package/dist/client.d.ts +9 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +5 -5
- package/dist/client.js.map +1 -1
- package/dist/client.test.js +46 -15
- package/dist/client.test.js.map +1 -1
- package/dist/connectivity.d.ts +38 -0
- package/dist/connectivity.d.ts.map +1 -0
- package/dist/connectivity.js +97 -0
- package/dist/connectivity.js.map +1 -0
- package/dist/connectivity.test.d.ts +2 -0
- package/dist/connectivity.test.d.ts.map +1 -0
- package/dist/connectivity.test.js +61 -0
- package/dist/connectivity.test.js.map +1 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -3
- package/dist/index.js.map +1 -1
- package/dist/multisig.d.ts +68 -7
- package/dist/multisig.d.ts.map +1 -1
- package/dist/multisig.js +90 -18
- package/dist/multisig.js.map +1 -1
- package/dist/multisig.test.js +214 -79
- package/dist/multisig.test.js.map +1 -1
- package/dist/proposal/metadata.d.ts.map +1 -1
- package/dist/proposal/metadata.js +12 -0
- package/dist/proposal/metadata.js.map +1 -1
- package/dist/proposal/metadata.test.js +49 -0
- package/dist/proposal/metadata.test.js.map +1 -1
- package/dist/raw-client.d.ts +2 -2
- package/dist/raw-client.d.ts.map +1 -1
- package/dist/raw-client.js +14 -4
- package/dist/raw-client.js.map +1 -1
- package/dist/raw-client.test.js +25 -3
- package/dist/raw-client.test.js.map +1 -1
- package/dist/transaction/consumeNotes.d.ts +6 -2
- package/dist/transaction/consumeNotes.d.ts.map +1 -1
- package/dist/transaction/consumeNotes.js +0 -4
- package/dist/transaction/consumeNotes.js.map +1 -1
- package/dist/transaction/options.d.ts +3 -0
- package/dist/transaction/options.d.ts.map +1 -1
- package/dist/transaction/p2id.d.ts +20 -2
- package/dist/transaction/p2id.d.ts.map +1 -1
- package/dist/transaction/p2id.js +46 -3
- package/dist/transaction/p2id.js.map +1 -1
- package/dist/transaction/p2id.test.js +66 -6
- package/dist/transaction/p2id.test.js.map +1 -1
- package/dist/transaction/summary.d.ts +2 -1
- package/dist/transaction/summary.d.ts.map +1 -1
- package/dist/transaction/summary.js.map +1 -1
- package/dist/transaction/updateGuardian.d.ts +6 -2
- package/dist/transaction/updateGuardian.d.ts.map +1 -1
- package/dist/transaction/updateGuardian.js.map +1 -1
- package/dist/transaction/updateProcedureThreshold.d.ts +7 -2
- package/dist/transaction/updateProcedureThreshold.d.ts.map +1 -1
- package/dist/transaction/updateProcedureThreshold.js.map +1 -1
- package/dist/transaction/updateSigners.d.ts +7 -2
- package/dist/transaction/updateSigners.d.ts.map +1 -1
- package/dist/transaction/updateSigners.js.map +1 -1
- package/dist/transaction.d.ts +1 -1
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +1 -1
- package/dist/transaction.js.map +1 -1
- package/dist/types/proposal.d.ts +5 -0
- package/dist/types/proposal.d.ts.map +1 -1
- package/dist/types/proposal.js +3 -0
- package/dist/types/proposal.js.map +1 -1
- package/package.json +3 -3
- package/src/account/builder.test.ts +19 -11
- package/src/account/builder.ts +2 -1
- package/src/client.test.ts +67 -15
- package/src/client.ts +18 -10
- package/src/connectivity.test.ts +67 -0
- package/src/connectivity.ts +111 -0
- package/src/index.ts +20 -1
- package/src/multisig.test.ts +267 -80
- package/src/multisig.ts +109 -20
- package/src/proposal/metadata.test.ts +60 -0
- package/src/proposal/metadata.ts +14 -0
- package/src/raw-client.test.ts +41 -3
- package/src/raw-client.ts +15 -5
- package/src/transaction/consumeNotes.ts +11 -1
- package/src/transaction/options.ts +4 -0
- package/src/transaction/p2id.test.ts +98 -8
- package/src/transaction/p2id.ts +64 -4
- package/src/transaction/summary.ts +12 -0
- package/src/transaction/updateGuardian.ts +11 -1
- package/src/transaction/updateProcedureThreshold.ts +13 -1
- package/src/transaction/updateSigners.ts +13 -1
- package/src/transaction.ts +3 -0
- package/src/types/proposal.ts +9 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { GuardianHttpError } from '@openzeppelin/guardian-client';
|
|
3
|
+
import { isLikelyNetworkError, toUserFacingError } from './connectivity.js';
|
|
4
|
+
describe('isLikelyNetworkError', () => {
|
|
5
|
+
it('flags codeless transport failures', () => {
|
|
6
|
+
for (const m of [
|
|
7
|
+
'Failed to fetch',
|
|
8
|
+
'NetworkError when attempting to fetch resource',
|
|
9
|
+
'Load failed',
|
|
10
|
+
'The operation was aborted',
|
|
11
|
+
'request timed out',
|
|
12
|
+
'connection refused',
|
|
13
|
+
'getaddrinfo ENOTFOUND guardian.example',
|
|
14
|
+
]) {
|
|
15
|
+
expect(isLikelyNetworkError(new TypeError(m))).toBe(true);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
it('does not flag semantic errors', () => {
|
|
19
|
+
expect(isLikelyNetworkError(new Error('account is paused'))).toBe(false);
|
|
20
|
+
expect(isLikelyNetworkError(new Error('insufficient signatures'))).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
describe('toUserFacingError', () => {
|
|
24
|
+
it('uses the server code + user-safe message when Guardian was reached', () => {
|
|
25
|
+
const body = JSON.stringify({
|
|
26
|
+
code: 'account_paused',
|
|
27
|
+
message: "This account is paused and can't approve transactions right now.",
|
|
28
|
+
meta: { retryable: false },
|
|
29
|
+
});
|
|
30
|
+
const result = toUserFacingError(new GuardianHttpError(409, 'Conflict', body));
|
|
31
|
+
expect(result.code).toBe('account_paused');
|
|
32
|
+
expect(result.userMessage).toContain('paused');
|
|
33
|
+
expect(result.category).toBeUndefined();
|
|
34
|
+
});
|
|
35
|
+
it('classifies a codeless transport failure as connectivity', () => {
|
|
36
|
+
const result = toUserFacingError(new TypeError('Failed to fetch'));
|
|
37
|
+
expect(result.code).toBeUndefined();
|
|
38
|
+
expect(result.category).toBe('unreachable');
|
|
39
|
+
expect(result.userMessage).toContain("Can't reach Guardian");
|
|
40
|
+
// The raw transport text is never the primary message.
|
|
41
|
+
expect(result.userMessage).not.toContain('Failed to fetch');
|
|
42
|
+
});
|
|
43
|
+
it('classifies timeouts and aborts as the timeout category', () => {
|
|
44
|
+
for (const m of ['request timed out', 'The operation was aborted']) {
|
|
45
|
+
const result = toUserFacingError(new Error(m));
|
|
46
|
+
expect(result.category).toBe('timeout');
|
|
47
|
+
expect(result.userMessage).toContain("Can't reach Guardian");
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
it('treats a reachable proxy 5xx with no Guardian body as connectivity', () => {
|
|
51
|
+
const result = toUserFacingError(new GuardianHttpError(502, 'Bad Gateway', '<html>nope</html>'));
|
|
52
|
+
expect(result.category).toBe('unreachable');
|
|
53
|
+
expect(result.userMessage).toContain("Can't reach Guardian");
|
|
54
|
+
});
|
|
55
|
+
it('falls back to a generic message for unknown non-Guardian errors', () => {
|
|
56
|
+
const result = toUserFacingError(new Error('totally unexpected'));
|
|
57
|
+
expect(result.userMessage).toBe('Something went wrong. Please try again.');
|
|
58
|
+
expect(result.userMessage).not.toContain('totally unexpected');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
//# sourceMappingURL=connectivity.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectivity.test.js","sourceRoot":"","sources":["../src/connectivity.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE5E,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,KAAK,MAAM,CAAC,IAAI;YACd,iBAAiB;YACjB,gDAAgD;YAChD,aAAa;YACb,2BAA2B;YAC3B,mBAAmB;YACnB,oBAAoB;YACpB,wCAAwC;SACzC,EAAE,CAAC;YACF,MAAM,CAAC,oBAAoB,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,CAAC,oBAAoB,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzE,MAAM,CAAC,oBAAoB,CAAC,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;YAC1B,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,kEAAkE;YAC3E,IAAI,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE;SAC3B,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,iBAAiB,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;QAC/E,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC/C,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,aAAa,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACnE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;QAC7D,uDAAuD;QACvD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,KAAK,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE,2BAA2B,CAAC,EAAE,CAAC;YACnE,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACxC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,iBAAiB,CAAC,GAAG,EAAE,aAAa,EAAE,mBAAmB,CAAC,CAAC,CAAC;QACjG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;QAClE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;QAC3E,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/index.d.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',
|
|
@@ -42,14 +43,19 @@ export { MultisigClient, type MultisigClientConfig, type RecoveredAccount, } fro
|
|
|
42
43
|
export { lookupAuthDigest } from './lookupAuth.js';
|
|
43
44
|
export { Multisig, type AccountState } from './multisig.js';
|
|
44
45
|
export { AccountInspector, type DetectedMultisigConfig, type VaultBalance } from './inspector.js';
|
|
45
|
-
export { executeForSummary, buildUpdateSignersTransactionRequest, buildUpdateProcedureThresholdTransactionRequest, buildUpdateGuardianTransactionRequest, buildConsumeNotesTransactionRequest, buildP2idTransactionRequest, } from './transaction.js';
|
|
46
|
+
export { executeForSummary, buildUpdateSignersTransactionRequest, buildUpdateProcedureThresholdTransactionRequest, buildUpdateGuardianTransactionRequest, buildConsumeNotesTransactionRequest, buildP2idTransactionRequest, parseP2idNoteType, p2idNoteTypeToMetadata, type P2idTransactionOptions, } from './transaction.js';
|
|
46
47
|
export { GuardianHttpClient, GuardianHttpError } from '@openzeppelin/guardian-client';
|
|
48
|
+
export type { GuardianErrorMeta } from '@openzeppelin/guardian-client';
|
|
49
|
+
export { GUARDIAN_ERROR_CODES, isGuardianErrorCode, normalizeGuardianErrorCode, } from '@openzeppelin/guardian-client';
|
|
50
|
+
export type { GuardianErrorCode } from '@openzeppelin/guardian-client';
|
|
51
|
+
export { isLikelyNetworkError, toUserFacingError } from './connectivity.js';
|
|
52
|
+
export type { ConnectivityCategory, UserFacingError } from './connectivity.js';
|
|
47
53
|
export { FalconSigner, EcdsaSigner, ParaSigner, MidenWalletSigner, type ParaSigningContext, type WalletSigningContext, } from './signer.js';
|
|
48
54
|
export { PublicKeyFormat } from './utils/key.js';
|
|
49
55
|
export { EcdsaFormat } from './utils/ecdsa.js';
|
|
50
56
|
export { tryComputeEcdsaCommitmentHex } from './utils/signature.js';
|
|
51
57
|
export { createMultisigAccount, validateMultisigConfig, buildMultisigStorageSlots, buildGuardianStorageSlots, storageLayoutBuilder, StorageLayoutBuilder, } from './account/index.js';
|
|
52
|
-
export { CONSUME_NOTES_METADATA_VERSION_V2, MAX_CONSUME_NOTES_METADATA_BYTES, isConsumeNotesV1, isConsumeNotesV2, } from './types/proposal.js';
|
|
58
|
+
export { CONSUME_NOTES_METADATA_VERSION_V2, MAX_CONSUME_NOTES_METADATA_BYTES, isConsumeNotesV1, isConsumeNotesV2, isP2idNoteVisibility, type P2idNoteVisibility, } from './types/proposal.js';
|
|
53
59
|
export { LEGACY_CONSUME_NOTES_ENABLED, } from './multisig/config.js';
|
|
54
60
|
export { type ConsumeNotesErrorCode, NoteBindingMismatchError, UnsupportedMetadataVersionError, ConsumeNotesMetadataOversizeError, LegacyConsumeNotesNoteMissingError, } from './multisig/consumeNotesErrors.js';
|
|
55
61
|
export { noteToBase64, noteFromBase64, } from './utils/encoding.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EACL,cAAc,EACd,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,KAAK,sBAAsB,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAClG,OAAO,EACL,iBAAiB,EACjB,oCAAoC,EACpC,+CAA+C,EAC/C,qCAAqC,EACrC,mCAAmC,EACnC,2BAA2B,EAC3B,iBAAiB,EACjB,sBAAsB,EACtB,KAAK,sBAAsB,GAC5B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACtF,YAAY,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAGvE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,+BAA+B,CAAC;AACvC,YAAY,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAGvE,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,YAAY,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE/E,OAAO,EACL,YAAY,EACZ,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,iCAAiC,EACjC,gCAAgC,EAChC,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EACpB,KAAK,kBAAkB,GACxB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,KAAK,qBAAqB,EAC1B,wBAAwB,EACxB,+BAA+B,EAC/B,iCAAiC,EACjC,kCAAkC,GACnC,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,YAAY,EACZ,cAAc,GACf,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,KAAK,aAAa,GACnB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EAEV,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAGlB,QAAQ,EACR,cAAc,EACd,sBAAsB,EACtB,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,2BAA2B,EAC3B,6BAA6B,EAC7B,mBAAmB,EACnB,4BAA4B,EAC5B,yBAAyB,EAGzB,eAAe,EAGf,cAAc,EACd,SAAS,EAGT,eAAe,EACf,MAAM,EACN,eAAe,EAGf,UAAU,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,iBAAiB,EAGjB,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,cAAc,EACd,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
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',
|
|
@@ -42,14 +43,19 @@ export { MultisigClient, } from './client.js';
|
|
|
42
43
|
export { lookupAuthDigest } from './lookupAuth.js';
|
|
43
44
|
export { Multisig } from './multisig.js';
|
|
44
45
|
export { AccountInspector } from './inspector.js';
|
|
45
|
-
export { executeForSummary, buildUpdateSignersTransactionRequest, buildUpdateProcedureThresholdTransactionRequest, buildUpdateGuardianTransactionRequest, buildConsumeNotesTransactionRequest, buildP2idTransactionRequest, } from './transaction.js';
|
|
46
|
+
export { executeForSummary, buildUpdateSignersTransactionRequest, buildUpdateProcedureThresholdTransactionRequest, buildUpdateGuardianTransactionRequest, buildConsumeNotesTransactionRequest, buildP2idTransactionRequest, parseP2idNoteType, p2idNoteTypeToMetadata, } from './transaction.js';
|
|
46
47
|
export { GuardianHttpClient, GuardianHttpError } from '@openzeppelin/guardian-client';
|
|
48
|
+
// Typed error-code vocabulary (issue #318): branch on GuardianErrorCode,
|
|
49
|
+
// never on message text; unknown wire codes surface via rawCode.
|
|
50
|
+
export { GUARDIAN_ERROR_CODES, isGuardianErrorCode, normalizeGuardianErrorCode, } from '@openzeppelin/guardian-client';
|
|
51
|
+
// Codeless transport-failure classification (feature 009, User Story 3).
|
|
52
|
+
export { isLikelyNetworkError, toUserFacingError } from './connectivity.js';
|
|
47
53
|
export { FalconSigner, EcdsaSigner, ParaSigner, MidenWalletSigner, } from './signer.js';
|
|
48
54
|
export { PublicKeyFormat } from './utils/key.js';
|
|
49
55
|
export { EcdsaFormat } from './utils/ecdsa.js';
|
|
50
56
|
export { tryComputeEcdsaCommitmentHex } from './utils/signature.js';
|
|
51
57
|
export { createMultisigAccount, validateMultisigConfig, buildMultisigStorageSlots, buildGuardianStorageSlots, storageLayoutBuilder, StorageLayoutBuilder, } from './account/index.js';
|
|
52
|
-
export { CONSUME_NOTES_METADATA_VERSION_V2, MAX_CONSUME_NOTES_METADATA_BYTES, isConsumeNotesV1, isConsumeNotesV2, } from './types/proposal.js';
|
|
58
|
+
export { CONSUME_NOTES_METADATA_VERSION_V2, MAX_CONSUME_NOTES_METADATA_BYTES, isConsumeNotesV1, isConsumeNotesV2, isP2idNoteVisibility, } from './types/proposal.js';
|
|
53
59
|
export { LEGACY_CONSUME_NOTES_ENABLED, } from './multisig/config.js';
|
|
54
60
|
export { NoteBindingMismatchError, UnsupportedMetadataVersionError, ConsumeNotesMetadataOversizeError, LegacyConsumeNotesNoteMissingError, } from './multisig/consumeNotesErrors.js';
|
|
55
61
|
export { noteToBase64, noteFromBase64, } from './utils/encoding.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EACL,cAAc,GAGf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAqB,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAkD,MAAM,gBAAgB,CAAC;AAClG,OAAO,EACL,iBAAiB,EACjB,oCAAoC,EACpC,+CAA+C,EAC/C,qCAAqC,EACrC,mCAAmC,EACnC,2BAA2B,EAC3B,iBAAiB,EACjB,sBAAsB,GAEvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAEtF,yEAAyE;AACzE,iEAAiE;AACjE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,+BAA+B,CAAC;AAGvC,yEAAyE;AACzE,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAG5E,OAAO,EACL,YAAY,EACZ,WAAW,EACX,UAAU,EACV,iBAAiB,GAGlB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,yBAAyB,EACzB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,iCAAiC,EACjC,gCAAgC,EAChC,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,GAErB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAEL,wBAAwB,EACxB,+BAA+B,EAC/B,iCAAiC,EACjC,kCAAkC,GACnC,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,YAAY,EACZ,cAAc,GACf,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,iBAAiB,GAElB,MAAM,iBAAiB,CAAC"}
|
package/dist/multisig.d.ts
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* This class wraps a Miden SDK Account and provides GUARDIAN integration
|
|
5
5
|
* for proposal management.
|
|
6
6
|
*/
|
|
7
|
-
import { GuardianHttpClient, type Signer } from '@openzeppelin/guardian-client';
|
|
7
|
+
import { GuardianHttpClient, type AbandonCandidateResponse, type AbandonStatus, type Signer } from '@openzeppelin/guardian-client';
|
|
8
8
|
import type { ConsumableNote, ExportedProposal, MultisigConfig, Proposal, ProposalMetadata, ProposalType } from './types.js';
|
|
9
9
|
import type { ProcedureName } from './procedures.js';
|
|
10
10
|
import type { MidenClient } from '@miden-sdk/miden-sdk';
|
|
11
|
-
import { Account, AdviceMap, TransactionRequest } from '@miden-sdk/miden-sdk';
|
|
11
|
+
import { Account, AdviceMap, NoteType, TransactionRequest } from '@miden-sdk/miden-sdk';
|
|
12
12
|
/**
|
|
13
13
|
* Result of fetching account state from GUARDIAN.
|
|
14
14
|
*/
|
|
@@ -40,9 +40,9 @@ export declare class Multisig {
|
|
|
40
40
|
private readonly rawClientPromise;
|
|
41
41
|
private readonly transactionProver;
|
|
42
42
|
private readonly _accountId;
|
|
43
|
-
private readonly midenRpcEndpoint
|
|
43
|
+
private readonly midenRpcEndpoint;
|
|
44
44
|
private proposals;
|
|
45
|
-
constructor(account: Account, config: MultisigConfig, guardian: GuardianHttpClient, signer: Signer, midenClient: MidenClient, accountId
|
|
45
|
+
constructor(account: Account, config: MultisigConfig, guardian: GuardianHttpClient, signer: Signer, midenClient: MidenClient, accountId: string | undefined, midenRpcEndpoint: string);
|
|
46
46
|
private getMidenRpcEndpoint;
|
|
47
47
|
private getRawClient;
|
|
48
48
|
private proposalFactory;
|
|
@@ -51,6 +51,15 @@ export declare class Multisig {
|
|
|
51
51
|
get accountId(): string;
|
|
52
52
|
/** The signer's commitment */
|
|
53
53
|
get signerCommitment(): string;
|
|
54
|
+
/**
|
|
55
|
+
* Resolve the account from the web client's store, falling back to the
|
|
56
|
+
* `account` snapshot when the store has no record.
|
|
57
|
+
*
|
|
58
|
+
* Transaction execution reads the store, and other flows (e.g. consume-notes
|
|
59
|
+
* finalize) update it without refreshing the snapshot, so vault lookups must
|
|
60
|
+
* source from the store to see the same state execution will.
|
|
61
|
+
*/
|
|
62
|
+
getStoreAccount(): Promise<Account>;
|
|
54
63
|
/**
|
|
55
64
|
* Maps a proposal type to the procedure that determines its threshold.
|
|
56
65
|
*/
|
|
@@ -79,11 +88,33 @@ export declare class Multisig {
|
|
|
79
88
|
* Sync account state from GUARDIAN into the local Miden client store.
|
|
80
89
|
*
|
|
81
90
|
* If the GUARDIAN commitment differs from the local commitment (or the account
|
|
82
|
-
* is missing locally)
|
|
91
|
+
* is missing locally) and the GUARDIAN state is safe to import, the local store
|
|
92
|
+
* is overwritten with the GUARDIAN state. When the GUARDIAN is merely *behind*
|
|
93
|
+
* local — e.g. the pushed execution delta has not been canonicalized yet
|
|
94
|
+
* (see OpenZeppelin/guardian#316) — the local state is already ahead and
|
|
95
|
+
* on-chain-verifiable, so it is kept as authoritative. Either way, config is
|
|
96
|
+
* refreshed from the resulting account so callers reading `Multisig.account`
|
|
97
|
+
* (e.g. the UI) observe the current state instead of a stale snapshot.
|
|
83
98
|
*/
|
|
84
99
|
syncState(): Promise<AccountState>;
|
|
85
100
|
verifyStateCommitment(): Promise<AccountStateVerificationResult>;
|
|
86
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Decide whether GUARDIAN-provided state may overwrite the local store.
|
|
103
|
+
*
|
|
104
|
+
* Returns `false` — rather than throwing — when the GUARDIAN state is simply
|
|
105
|
+
* *behind* local (lower nonce). That happens whenever the execution delta the
|
|
106
|
+
* client pushed has not been canonicalized by the GUARDIAN's background worker
|
|
107
|
+
* yet (see OpenZeppelin/guardian#316), or permanently if that candidate was
|
|
108
|
+
* discarded (#312 / #319). In that case the local account is already ahead and
|
|
109
|
+
* is independently verifiable against chain (`verifyStateCommitment`), so it is
|
|
110
|
+
* authoritative and must be kept, not clobbered; the caller keeps local and
|
|
111
|
+
* refreshes config from it.
|
|
112
|
+
*
|
|
113
|
+
* Still throws for genuine divergence: an incoming state at the *same* nonce as
|
|
114
|
+
* local but a different commitment, or an incoming state whose commitment does
|
|
115
|
+
* not match the on-chain commitment.
|
|
116
|
+
*/
|
|
117
|
+
private isSafeToOverwriteLocalState;
|
|
87
118
|
private getOnChainCommitment;
|
|
88
119
|
private refreshConfigFromAccount;
|
|
89
120
|
/**
|
|
@@ -157,8 +188,12 @@ export declare class Multisig {
|
|
|
157
188
|
* @param faucetId - Faucet/token account ID (hex string)
|
|
158
189
|
* @param amount - Amount to send
|
|
159
190
|
* @param nonce - Optional proposal nonce (defaults to Date.now())
|
|
191
|
+
* @param options - Optional settings; `noteType` selects the created note's
|
|
192
|
+
* visibility (defaults to `NoteType.Public`, issue #322)
|
|
160
193
|
*/
|
|
161
|
-
createP2idProposal(recipientId: string, faucetId: string, amount: bigint, nonce?: number
|
|
194
|
+
createP2idProposal(recipientId: string, faucetId: string, amount: bigint, nonce?: number, options?: {
|
|
195
|
+
noteType?: NoteType;
|
|
196
|
+
}): Promise<Proposal>;
|
|
162
197
|
/**
|
|
163
198
|
* Get notes that can be consumed by this multisig account.
|
|
164
199
|
*
|
|
@@ -174,6 +209,32 @@ export declare class Multisig {
|
|
|
174
209
|
*
|
|
175
210
|
* @param proposalId - The proposal commitment/ID (this is also what gets signed)
|
|
176
211
|
*/
|
|
212
|
+
/**
|
|
213
|
+
* Request abandonment of a pending canonicalization candidate whose
|
|
214
|
+
* transaction will never land on-chain (issue #319) — e.g. after an
|
|
215
|
+
* approved transaction died client-side (RPC submit failure, prover
|
|
216
|
+
* timeout, crash).
|
|
217
|
+
*
|
|
218
|
+
* Records an abandon *intent* on GUARDIAN: the account stays locked
|
|
219
|
+
* until the guardian's canonicalization worker confirms over a short
|
|
220
|
+
* quarantine (typically well under a minute) that the transaction did
|
|
221
|
+
* not land, then releases the account. Poll {@link abandonStatus} for
|
|
222
|
+
* the resolution.
|
|
223
|
+
*
|
|
224
|
+
* `nonce` pins the exact candidate to release; it is the nonce the
|
|
225
|
+
* proposal was pushed with. Retries are idempotent and preserve the
|
|
226
|
+
* original request timestamp. Refused with `GUARDIAN_CANDIDATE_LANDED`
|
|
227
|
+
* (409) when the transaction actually landed.
|
|
228
|
+
*/
|
|
229
|
+
abandonCandidate(nonce: number): Promise<AbandonCandidateResponse>;
|
|
230
|
+
/**
|
|
231
|
+
* Poll the resolution of an abandon request made with
|
|
232
|
+
* {@link abandonCandidate}: `'waiting'` while the quarantine runs,
|
|
233
|
+
* `'landed'` if the transaction landed after all, `'abandoned'` once
|
|
234
|
+
* the account is released, `'unexpected'` for any state no abandon
|
|
235
|
+
* flow produces.
|
|
236
|
+
*/
|
|
237
|
+
abandonStatus(nonce: number): Promise<AbandonStatus>;
|
|
177
238
|
signProposal(proposalId: string): Promise<Proposal>;
|
|
178
239
|
private getProposalForSigning;
|
|
179
240
|
createTransactionProposalRequest(proposalId: string): Promise<TransactionRequest>;
|
package/dist/multisig.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multisig.d.ts","sourceRoot":"","sources":["../src/multisig.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,kBAAkB,EAA4C,KAAK,MAAM,EAAqC,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"multisig.d.ts","sourceRoot":"","sources":["../src/multisig.ts"],"names":[],"mappings":"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"}
|
package/dist/multisig.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { GuardianHttpClient } from '@openzeppelin/guardian-client';
|
|
8
8
|
import { Account, AccountId, AdviceMap, Endpoint, FeltArray, Note, RpcClient, Signature, TransactionRequest, TransactionSummary, Word, } from '@miden-sdk/miden-sdk';
|
|
9
|
-
import { executeForSummary, buildUpdateSignersTransactionRequest, buildUpdateProcedureThresholdTransactionRequest, buildUpdateGuardianTransactionRequest, buildConsumeNotesTransactionRequest, buildP2idTransactionRequest, } from './transaction.js';
|
|
9
|
+
import { executeForSummary, buildUpdateSignersTransactionRequest, buildUpdateProcedureThresholdTransactionRequest, buildUpdateGuardianTransactionRequest, buildConsumeNotesTransactionRequest, buildP2idTransactionRequest, parseP2idNoteType, p2idNoteTypeToMetadata, } from './transaction.js';
|
|
10
10
|
import { buildConsumeNotesTransactionRequestFromNotes } from './transaction/consumeNotes.js';
|
|
11
11
|
import { CONSUME_NOTES_METADATA_VERSION_V2, MAX_CONSUME_NOTES_METADATA_BYTES, } from './types/proposal.js';
|
|
12
12
|
import { LEGACY_CONSUME_NOTES_ENABLED } from './multisig/config.js';
|
|
@@ -20,7 +20,7 @@ import { AccountInspector } from './inspector.js';
|
|
|
20
20
|
import { ProposalFactory } from './proposal/factory.js';
|
|
21
21
|
import { ProposalMetadataCodec } from './proposal/metadata.js';
|
|
22
22
|
import { ProposalSignatures } from './proposal/signatures.js';
|
|
23
|
-
import { getRawMidenClient, getTransactionProver } from './raw-client.js';
|
|
23
|
+
import { getRawMidenClient, getTransactionProver, requireMidenRpcEndpoint, } from './raw-client.js';
|
|
24
24
|
/**
|
|
25
25
|
* Represents a multisig account with GUARDIAN integration.
|
|
26
26
|
*/
|
|
@@ -75,14 +75,11 @@ export class Multisig {
|
|
|
75
75
|
this.signer = signer;
|
|
76
76
|
this.midenClient = midenClient;
|
|
77
77
|
this._accountId = accountId ?? (account ? accountIdToHex(account) : '');
|
|
78
|
-
this.midenRpcEndpoint = midenRpcEndpoint;
|
|
79
|
-
this.rawClientPromise = getRawMidenClient(midenClient, midenRpcEndpoint);
|
|
78
|
+
this.midenRpcEndpoint = requireMidenRpcEndpoint(midenRpcEndpoint);
|
|
80
79
|
this.transactionProver = getTransactionProver(midenClient);
|
|
80
|
+
this.rawClientPromise = getRawMidenClient(midenClient, this.midenRpcEndpoint);
|
|
81
81
|
}
|
|
82
82
|
getMidenRpcEndpoint() {
|
|
83
|
-
if (!this.midenRpcEndpoint) {
|
|
84
|
-
throw new Error('Missing Miden RPC endpoint in MultisigClient configuration');
|
|
85
|
-
}
|
|
86
83
|
return this.midenRpcEndpoint;
|
|
87
84
|
}
|
|
88
85
|
async getRawClient() {
|
|
@@ -115,6 +112,18 @@ export class Multisig {
|
|
|
115
112
|
get signerCommitment() {
|
|
116
113
|
return this.signer.commitment;
|
|
117
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Resolve the account from the web client's store, falling back to the
|
|
117
|
+
* `account` snapshot when the store has no record.
|
|
118
|
+
*
|
|
119
|
+
* Transaction execution reads the store, and other flows (e.g. consume-notes
|
|
120
|
+
* finalize) update it without refreshing the snapshot, so vault lookups must
|
|
121
|
+
* source from the store to see the same state execution will.
|
|
122
|
+
*/
|
|
123
|
+
async getStoreAccount() {
|
|
124
|
+
const webClient = await this.getRawClient();
|
|
125
|
+
return (await webClient.getAccount(AccountId.fromHex(this._accountId))) ?? this.account;
|
|
126
|
+
}
|
|
118
127
|
/**
|
|
119
128
|
* Maps a proposal type to the procedure that determines its threshold.
|
|
120
129
|
*/
|
|
@@ -181,7 +190,13 @@ export class Multisig {
|
|
|
181
190
|
* Sync account state from GUARDIAN into the local Miden client store.
|
|
182
191
|
*
|
|
183
192
|
* If the GUARDIAN commitment differs from the local commitment (or the account
|
|
184
|
-
* is missing locally)
|
|
193
|
+
* is missing locally) and the GUARDIAN state is safe to import, the local store
|
|
194
|
+
* is overwritten with the GUARDIAN state. When the GUARDIAN is merely *behind*
|
|
195
|
+
* local — e.g. the pushed execution delta has not been canonicalized yet
|
|
196
|
+
* (see OpenZeppelin/guardian#316) — the local state is already ahead and
|
|
197
|
+
* on-chain-verifiable, so it is kept as authoritative. Either way, config is
|
|
198
|
+
* refreshed from the resulting account so callers reading `Multisig.account`
|
|
199
|
+
* (e.g. the UI) observe the current state instead of a stale snapshot.
|
|
185
200
|
*/
|
|
186
201
|
async syncState() {
|
|
187
202
|
const state = await this.fetchState();
|
|
@@ -196,9 +211,10 @@ export class Multisig {
|
|
|
196
211
|
if (!localAccount || localCommitment !== guardianCommitment) {
|
|
197
212
|
const accountBytes = base64ToUint8Array(state.stateDataBase64);
|
|
198
213
|
const incomingAccount = Account.deserialize(accountBytes);
|
|
199
|
-
await this.
|
|
200
|
-
|
|
201
|
-
|
|
214
|
+
if (await this.isSafeToOverwriteLocalState(incomingAccount, localAccount)) {
|
|
215
|
+
await webClient.newAccount(incomingAccount, true);
|
|
216
|
+
accountForConfigRefresh = incomingAccount;
|
|
217
|
+
}
|
|
202
218
|
}
|
|
203
219
|
this.refreshConfigFromAccount(accountForConfigRefresh);
|
|
204
220
|
return state;
|
|
@@ -224,23 +240,43 @@ export class Multisig {
|
|
|
224
240
|
onChainCommitment,
|
|
225
241
|
};
|
|
226
242
|
}
|
|
227
|
-
|
|
243
|
+
/**
|
|
244
|
+
* Decide whether GUARDIAN-provided state may overwrite the local store.
|
|
245
|
+
*
|
|
246
|
+
* Returns `false` — rather than throwing — when the GUARDIAN state is simply
|
|
247
|
+
* *behind* local (lower nonce). That happens whenever the execution delta the
|
|
248
|
+
* client pushed has not been canonicalized by the GUARDIAN's background worker
|
|
249
|
+
* yet (see OpenZeppelin/guardian#316), or permanently if that candidate was
|
|
250
|
+
* discarded (#312 / #319). In that case the local account is already ahead and
|
|
251
|
+
* is independently verifiable against chain (`verifyStateCommitment`), so it is
|
|
252
|
+
* authoritative and must be kept, not clobbered; the caller keeps local and
|
|
253
|
+
* refreshes config from it.
|
|
254
|
+
*
|
|
255
|
+
* Still throws for genuine divergence: an incoming state at the *same* nonce as
|
|
256
|
+
* local but a different commitment, or an incoming state whose commitment does
|
|
257
|
+
* not match the on-chain commitment.
|
|
258
|
+
*/
|
|
259
|
+
async isSafeToOverwriteLocalState(incomingAccount, localAccount) {
|
|
228
260
|
if (localAccount) {
|
|
229
261
|
const localNonce = localAccount.nonce().asInt();
|
|
230
262
|
const incomingNonce = incomingAccount.nonce().asInt();
|
|
231
|
-
if (incomingNonce
|
|
232
|
-
|
|
263
|
+
if (incomingNonce < localNonce) {
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
if (incomingNonce === localNonce) {
|
|
267
|
+
throw new Error(`Refusing to overwrite local state: incoming nonce ${incomingNonce.toString()} equals local nonce ${localNonce.toString()} but commitments differ for account ${this._accountId}`);
|
|
233
268
|
}
|
|
234
269
|
}
|
|
235
270
|
const accountId = AccountId.fromHex(this._accountId);
|
|
236
271
|
const onChainCommitment = await this.getOnChainCommitment(accountId);
|
|
237
272
|
if (!onChainCommitment) {
|
|
238
|
-
return;
|
|
273
|
+
return true;
|
|
239
274
|
}
|
|
240
275
|
const incomingCommitment = normalizeHexWord(incomingAccount.to_commitment().toHex());
|
|
241
276
|
if (incomingCommitment !== onChainCommitment) {
|
|
242
277
|
throw new Error(`Refusing to overwrite local state: incoming commitment does not match on-chain commitment for account ${this._accountId}`);
|
|
243
278
|
}
|
|
279
|
+
return true;
|
|
244
280
|
}
|
|
245
281
|
async getOnChainCommitment(accountId) {
|
|
246
282
|
const rpcClient = new RpcClient(new Endpoint(this.getMidenRpcEndpoint()));
|
|
@@ -556,13 +592,16 @@ export class Multisig {
|
|
|
556
592
|
* @param faucetId - Faucet/token account ID (hex string)
|
|
557
593
|
* @param amount - Amount to send
|
|
558
594
|
* @param nonce - Optional proposal nonce (defaults to Date.now())
|
|
595
|
+
* @param options - Optional settings; `noteType` selects the created note's
|
|
596
|
+
* visibility (defaults to `NoteType.Public`, issue #322)
|
|
559
597
|
*/
|
|
560
|
-
async createP2idProposal(recipientId, faucetId, amount, nonce) {
|
|
598
|
+
async createP2idProposal(recipientId, faucetId, amount, nonce, options = {}) {
|
|
561
599
|
const webClient = await this.getRawClient();
|
|
562
600
|
if (amount <= 0n) {
|
|
563
601
|
throw new Error('Amount must be greater than 0');
|
|
564
602
|
}
|
|
565
|
-
const
|
|
603
|
+
const account = await this.getStoreAccount();
|
|
604
|
+
const { request, salt } = buildP2idTransactionRequest(this._accountId, recipientId, faucetId, amount, account, { noteType: options.noteType });
|
|
566
605
|
const summary = await executeForSummary(webClient, this._accountId, request);
|
|
567
606
|
const summaryBase64 = uint8ArrayToBase64(summary.serialize());
|
|
568
607
|
const proposalNonce = nonce ?? Date.now();
|
|
@@ -573,6 +612,8 @@ export class Multisig {
|
|
|
573
612
|
recipientId,
|
|
574
613
|
faucetId,
|
|
575
614
|
amount: amount.toString(),
|
|
615
|
+
// Omitted for public notes so the wire shape matches pre-#322 proposals.
|
|
616
|
+
noteType: p2idNoteTypeToMetadata(options.noteType),
|
|
576
617
|
description: `Send ${amount} of asset ${faucetId.slice(0, 10)}... to ${recipientId.slice(0, 10)}...`,
|
|
577
618
|
};
|
|
578
619
|
return this.createProposal(proposalNonce, summaryBase64, metadata);
|
|
@@ -626,6 +667,36 @@ export class Multisig {
|
|
|
626
667
|
*
|
|
627
668
|
* @param proposalId - The proposal commitment/ID (this is also what gets signed)
|
|
628
669
|
*/
|
|
670
|
+
/**
|
|
671
|
+
* Request abandonment of a pending canonicalization candidate whose
|
|
672
|
+
* transaction will never land on-chain (issue #319) — e.g. after an
|
|
673
|
+
* approved transaction died client-side (RPC submit failure, prover
|
|
674
|
+
* timeout, crash).
|
|
675
|
+
*
|
|
676
|
+
* Records an abandon *intent* on GUARDIAN: the account stays locked
|
|
677
|
+
* until the guardian's canonicalization worker confirms over a short
|
|
678
|
+
* quarantine (typically well under a minute) that the transaction did
|
|
679
|
+
* not land, then releases the account. Poll {@link abandonStatus} for
|
|
680
|
+
* the resolution.
|
|
681
|
+
*
|
|
682
|
+
* `nonce` pins the exact candidate to release; it is the nonce the
|
|
683
|
+
* proposal was pushed with. Retries are idempotent and preserve the
|
|
684
|
+
* original request timestamp. Refused with `GUARDIAN_CANDIDATE_LANDED`
|
|
685
|
+
* (409) when the transaction actually landed.
|
|
686
|
+
*/
|
|
687
|
+
async abandonCandidate(nonce) {
|
|
688
|
+
return this.guardian.abandonCandidate(this._accountId, nonce);
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Poll the resolution of an abandon request made with
|
|
692
|
+
* {@link abandonCandidate}: `'waiting'` while the quarantine runs,
|
|
693
|
+
* `'landed'` if the transaction landed after all, `'abandoned'` once
|
|
694
|
+
* the account is released, `'unexpected'` for any state no abandon
|
|
695
|
+
* flow produces.
|
|
696
|
+
*/
|
|
697
|
+
async abandonStatus(nonce) {
|
|
698
|
+
return this.guardian.abandonStatus(this._accountId, nonce);
|
|
699
|
+
}
|
|
629
700
|
async signProposal(proposalId) {
|
|
630
701
|
const normalizedProposalId = normalizeHexWord(proposalId);
|
|
631
702
|
const existingProposal = await this.getProposalForSigning(proposalId, normalizedProposalId);
|
|
@@ -1166,7 +1237,8 @@ export class Multisig {
|
|
|
1166
1237
|
throw new UnsupportedMetadataVersionError(version);
|
|
1167
1238
|
}
|
|
1168
1239
|
case 'p2id': {
|
|
1169
|
-
const
|
|
1240
|
+
const account = await this.getStoreAccount();
|
|
1241
|
+
const { request } = buildP2idTransactionRequest(this._accountId, metadata.recipientId, metadata.faucetId, BigInt(metadata.amount), account, { salt, signatureAdviceMap, noteType: parseP2idNoteType(metadata.noteType) });
|
|
1170
1242
|
return request;
|
|
1171
1243
|
}
|
|
1172
1244
|
case 'custom':
|