@openzeppelin/miden-multisig-client 0.13.1 → 0.13.2
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 +98 -119
- package/dist/account/builder.d.ts +18 -0
- package/dist/account/builder.d.ts.map +1 -1
- package/dist/account/builder.js +59 -29
- package/dist/account/builder.js.map +1 -1
- package/dist/account/builder.test.js +108 -32
- package/dist/account/builder.test.js.map +1 -1
- package/dist/account/index.d.ts +1 -1
- package/dist/account/index.d.ts.map +1 -1
- package/dist/account/index.js +1 -1
- package/dist/account/index.js.map +1 -1
- package/dist/account/masm/account-components/auth.d.ts +5 -0
- package/dist/account/masm/account-components/auth.d.ts.map +1 -0
- package/dist/account/masm/account-components/auth.js +67 -0
- package/dist/account/masm/account-components/auth.js.map +1 -0
- package/dist/account/masm/auth.d.ts +5 -0
- package/dist/account/masm/auth.d.ts.map +1 -0
- package/dist/account/masm/auth.js +1395 -0
- package/dist/account/masm/auth.js.map +1 -0
- package/dist/account/masm/index.d.ts +3 -0
- package/dist/account/masm/index.d.ts.map +1 -0
- package/dist/account/masm/index.js +5 -0
- package/dist/account/masm/index.js.map +1 -0
- package/dist/account/masm.d.ts +1 -4
- package/dist/account/masm.d.ts.map +1 -1
- package/dist/account/masm.js +3 -1034
- package/dist/account/masm.js.map +1 -1
- package/dist/account/storage.d.ts +2 -2
- package/dist/account/storage.d.ts.map +1 -1
- package/dist/account/storage.js +18 -16
- package/dist/account/storage.js.map +1 -1
- package/dist/client.d.ts +67 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +73 -22
- package/dist/client.js.map +1 -1
- package/dist/client.test.js +31 -32
- package/dist/client.test.js.map +1 -1
- package/dist/index.d.ts +54 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +53 -9
- package/dist/index.js.map +1 -1
- package/dist/inspector.d.ts +32 -6
- package/dist/inspector.d.ts.map +1 -1
- package/dist/inspector.js +58 -23
- package/dist/inspector.js.map +1 -1
- package/dist/inspector.test.js +18 -18
- package/dist/inspector.test.js.map +1 -1
- package/dist/multisig/proposal/execution.d.ts +4 -4
- package/dist/multisig/proposal/execution.d.ts.map +1 -1
- package/dist/multisig/proposal/execution.js +42 -31
- package/dist/multisig/proposal/execution.js.map +1 -1
- package/dist/multisig/proposal/parser.d.ts +3 -3
- package/dist/multisig/proposal/parser.d.ts.map +1 -1
- package/dist/multisig/proposal/parser.js +23 -23
- package/dist/multisig/proposal/parser.js.map +1 -1
- package/dist/multisig/signing.d.ts +3 -3
- package/dist/multisig/signing.d.ts.map +1 -1
- package/dist/multisig/signing.js +3 -3
- package/dist/multisig/signing.js.map +1 -1
- package/dist/multisig.d.ts +188 -48
- package/dist/multisig.d.ts.map +1 -1
- package/dist/multisig.js +650 -308
- package/dist/multisig.js.map +1 -1
- package/dist/multisig.test.js +1680 -241
- package/dist/multisig.test.js.map +1 -1
- package/dist/procedures.d.ts +46 -24
- package/dist/procedures.d.ts.map +1 -1
- package/dist/procedures.js +46 -21
- package/dist/procedures.js.map +1 -1
- package/dist/proposal/factory.d.ts +18 -0
- package/dist/proposal/factory.d.ts.map +1 -0
- package/dist/proposal/factory.js +99 -0
- package/dist/proposal/factory.js.map +1 -0
- package/dist/proposal/metadata.d.ts +5 -12
- package/dist/proposal/metadata.d.ts.map +1 -1
- package/dist/proposal/metadata.js +118 -174
- package/dist/proposal/metadata.js.map +1 -1
- package/dist/proposal/signatures.d.ts +10 -0
- package/dist/proposal/signatures.d.ts.map +1 -0
- package/dist/proposal/signatures.js +54 -0
- package/dist/proposal/signatures.js.map +1 -0
- package/dist/signer.d.ts +2 -0
- package/dist/signer.d.ts.map +1 -1
- package/dist/signer.js +2 -0
- package/dist/signer.js.map +1 -1
- package/dist/signers/ecdsa.d.ts +3 -0
- package/dist/signers/ecdsa.d.ts.map +1 -1
- package/dist/signers/ecdsa.js +8 -4
- package/dist/signers/ecdsa.js.map +1 -1
- package/dist/signers/ecdsa.test.d.ts +2 -0
- package/dist/signers/ecdsa.test.d.ts.map +1 -0
- package/dist/signers/ecdsa.test.js +65 -0
- package/dist/signers/ecdsa.test.js.map +1 -0
- package/dist/signers/falcon.d.ts +3 -0
- package/dist/signers/falcon.d.ts.map +1 -1
- package/dist/signers/falcon.js +8 -4
- package/dist/signers/falcon.js.map +1 -1
- package/dist/signers/falcon.test.js +12 -0
- package/dist/signers/falcon.test.js.map +1 -1
- package/dist/signers/miden-wallet.d.ts +3 -1
- package/dist/signers/miden-wallet.d.ts.map +1 -1
- package/dist/signers/miden-wallet.js +11 -2
- package/dist/signers/miden-wallet.js.map +1 -1
- package/dist/signers/miden-wallet.test.js +26 -0
- package/dist/signers/miden-wallet.test.js.map +1 -1
- package/dist/signers/para.d.ts +3 -3
- package/dist/signers/para.d.ts.map +1 -1
- package/dist/signers/para.js +15 -6
- package/dist/signers/para.js.map +1 -1
- package/dist/signers/para.test.js +39 -0
- package/dist/signers/para.test.js.map +1 -1
- package/dist/transaction/consumeNotes.d.ts.map +1 -1
- package/dist/transaction/consumeNotes.js +1 -0
- package/dist/transaction/consumeNotes.js.map +1 -1
- package/dist/transaction/index.d.ts +2 -1
- package/dist/transaction/index.d.ts.map +1 -1
- package/dist/transaction/index.js +2 -1
- package/dist/transaction/index.js.map +1 -1
- package/dist/transaction/options.d.ts +1 -1
- package/dist/transaction/options.d.ts.map +1 -1
- package/dist/transaction/p2id.d.ts +1 -0
- package/dist/transaction/p2id.d.ts.map +1 -1
- package/dist/transaction/p2id.js +9 -3
- package/dist/transaction/p2id.js.map +1 -1
- package/dist/transaction/updateGuardian.d.ts +7 -0
- package/dist/transaction/updateGuardian.d.ts.map +1 -0
- package/dist/transaction/{updatePsm.js → updateGuardian.js} +15 -29
- package/dist/transaction/updateGuardian.js.map +1 -0
- package/dist/transaction/updateProcedureThreshold.d.ts +9 -0
- package/dist/transaction/updateProcedureThreshold.d.ts.map +1 -0
- package/dist/transaction/updateProcedureThreshold.js +55 -0
- package/dist/transaction/updateProcedureThreshold.js.map +1 -0
- package/dist/transaction/updateSigners.d.ts.map +1 -1
- package/dist/transaction/updateSigners.js +5 -23
- package/dist/transaction/updateSigners.js.map +1 -1
- package/dist/transaction.d.ts +2 -1
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +2 -1
- package/dist/transaction.js.map +1 -1
- package/dist/types/proposal.d.ts +32 -15
- package/dist/types/proposal.d.ts.map +1 -1
- package/dist/types.d.ts +24 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/digest.d.ts +5 -0
- package/dist/utils/digest.d.ts.map +1 -1
- package/dist/utils/digest.js +34 -1
- package/dist/utils/digest.js.map +1 -1
- package/dist/utils/digest.test.d.ts +2 -0
- package/dist/utils/digest.test.d.ts.map +1 -0
- package/dist/utils/digest.test.js +48 -0
- package/dist/utils/digest.test.js.map +1 -0
- package/dist/utils/signature.d.ts +3 -1
- package/dist/utils/signature.d.ts.map +1 -1
- package/dist/utils/signature.js +31 -6
- package/dist/utils/signature.js.map +1 -1
- package/dist/utils/word.test.js +1 -52
- package/dist/utils/word.test.js.map +1 -1
- package/masm/account_components/auth/multisig.masm +13 -0
- package/masm/account_components/auth/multisig_ecdsa.masm +13 -0
- package/masm/account_components/auth/multisig_guardian.masm +17 -0
- package/masm/account_components/auth/multisig_guardian_ecdsa.masm +17 -0
- package/masm/auth/guardian.masm +177 -0
- package/masm/auth/guardian_ecdsa.masm +178 -0
- package/masm/{multisig.masm → auth/multisig.masm} +149 -55
- package/masm/{multisig_ecdsa.masm → auth/multisig_ecdsa.masm} +148 -56
- package/package.json +11 -9
- package/src/account/builder.test.ts +165 -0
- package/src/account/builder.ts +71 -34
- package/src/account/index.ts +1 -1
- package/src/account/masm/account-components/auth.ts +70 -0
- package/src/account/masm/auth.ts +1398 -0
- package/src/account/masm/index.ts +5 -0
- package/src/account/masm.ts +3 -1040
- package/src/account/storage.ts +18 -16
- package/src/client.test.ts +31 -35
- package/src/client.ts +98 -26
- package/src/index.ts +84 -22
- package/src/inspector.test.ts +17 -17
- package/src/inspector.ts +63 -29
- package/src/multisig/proposal/execution.ts +66 -49
- package/src/multisig/proposal/parser.ts +26 -26
- package/src/multisig/signing.ts +4 -4
- package/src/multisig.test.ts +2097 -248
- package/src/multisig.ts +882 -388
- package/src/procedures.ts +50 -26
- package/src/proposal/factory.ts +171 -0
- package/src/proposal/metadata.ts +165 -0
- package/src/proposal/signatures.ts +68 -0
- package/src/signer.ts +2 -0
- package/src/signers/ecdsa.test.ts +80 -0
- package/src/signers/ecdsa.ts +15 -4
- package/src/signers/falcon.test.ts +19 -0
- package/src/signers/falcon.ts +16 -5
- package/src/signers/miden-wallet.test.ts +47 -0
- package/src/signers/miden-wallet.ts +18 -1
- package/src/signers/para.test.ts +57 -0
- package/src/signers/para.ts +26 -7
- package/src/transaction/consumeNotes.ts +1 -0
- package/src/transaction/index.ts +2 -2
- package/src/transaction/options.ts +1 -2
- package/src/transaction/p2id.test.ts +190 -0
- package/src/transaction/p2id.ts +11 -5
- package/src/transaction/rpoRandomCoin.test.ts +64 -0
- package/src/transaction/rpoRandomCoin.ts +24 -0
- package/src/transaction/{updatePsm.ts → updateGuardian.ts} +19 -32
- package/src/transaction/updateProcedureThreshold.ts +97 -0
- package/src/transaction/updateSigners.ts +12 -27
- package/src/transaction.ts +5 -3
- package/src/types/proposal.ts +43 -11
- package/src/types.ts +29 -11
- package/src/utils/digest.test.ts +55 -0
- package/src/utils/digest.ts +51 -1
- package/src/utils/signature.ts +47 -9
- package/src/utils/word.test.ts +1 -55
- package/dist/account.d.ts +0 -104
- package/dist/account.d.ts.map +0 -1
- package/dist/account.js +0 -136
- package/dist/account.js.map +0 -1
- package/dist/builder.d.ts +0 -54
- package/dist/builder.d.ts.map +0 -1
- package/dist/builder.js +0 -78
- package/dist/builder.js.map +0 -1
- package/dist/http.d.ts +0 -64
- package/dist/http.d.ts.map +0 -1
- package/dist/http.js +0 -162
- package/dist/http.js.map +0 -1
- package/dist/keystore.d.ts +0 -65
- package/dist/keystore.d.ts.map +0 -1
- package/dist/keystore.js +0 -121
- package/dist/keystore.js.map +0 -1
- package/dist/miden.d.ts +0 -9
- package/dist/miden.d.ts.map +0 -1
- package/dist/miden.js +0 -26
- package/dist/miden.js.map +0 -1
- package/dist/multisig/metadata.d.ts +0 -18
- package/dist/multisig/metadata.d.ts.map +0 -1
- package/dist/multisig/metadata.js +0 -100
- package/dist/multisig/metadata.js.map +0 -1
- package/dist/multisig/metadata.test.d.ts +0 -2
- package/dist/multisig/metadata.test.d.ts.map +0 -1
- package/dist/multisig/metadata.test.js +0 -323
- package/dist/multisig/metadata.test.js.map +0 -1
- package/dist/proposal/exported.d.ts +0 -12
- package/dist/proposal/exported.d.ts.map +0 -1
- package/dist/proposal/exported.js +0 -88
- package/dist/proposal/exported.js.map +0 -1
- package/dist/signer.test.d.ts +0 -2
- package/dist/signer.test.d.ts.map +0 -1
- package/dist/signer.test.js +0 -123
- package/dist/signer.test.js.map +0 -1
- package/dist/transaction/p2id.interop.test.d.ts +0 -2
- package/dist/transaction/p2id.interop.test.d.ts.map +0 -1
- package/dist/transaction/p2id.interop.test.js +0 -36
- package/dist/transaction/p2id.interop.test.js.map +0 -1
- package/dist/transaction/updatePsm.d.ts +0 -7
- package/dist/transaction/updatePsm.d.ts.map +0 -1
- package/dist/transaction/updatePsm.js.map +0 -1
- package/dist/transport/http.d.ts +0 -64
- package/dist/transport/http.d.ts.map +0 -1
- package/dist/transport/http.js +0 -162
- package/dist/transport/http.js.map +0 -1
- package/dist/transport/index.d.ts +0 -5
- package/dist/transport/index.d.ts.map +0 -1
- package/dist/transport/index.js +0 -5
- package/dist/transport/index.js.map +0 -1
- package/dist/utils/state-validation.d.ts +0 -5
- package/dist/utils/state-validation.d.ts.map +0 -1
- package/dist/utils/state-validation.js +0 -30
- package/dist/utils/state-validation.js.map +0 -1
- package/dist/utils/validation.d.ts +0 -6
- package/dist/utils/validation.d.ts.map +0 -1
- package/dist/utils/validation.js +0 -52
- package/dist/utils/validation.js.map +0 -1
- package/masm/psm.masm +0 -178
- package/masm/psm_ecdsa.masm +0 -179
package/src/account/storage.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { MultisigConfig } from '../types.js';
|
|
2
2
|
import { StorageSlot, StorageMap, Word } from '@miden-sdk/miden-sdk';
|
|
3
|
-
import {
|
|
3
|
+
import { ensureHexPrefix } from '../utils/encoding.js';
|
|
4
4
|
import { getProcedureRoot } from '../procedures.js';
|
|
5
5
|
|
|
6
|
+
// Storage slot names matching the MASM definitions
|
|
6
7
|
const MULTISIG_SLOT_NAMES = {
|
|
7
8
|
THRESHOLD_CONFIG: 'openzeppelin::multisig::threshold_config',
|
|
8
9
|
SIGNER_PUBLIC_KEYS: 'openzeppelin::multisig::signer_public_keys',
|
|
@@ -10,9 +11,9 @@ const MULTISIG_SLOT_NAMES = {
|
|
|
10
11
|
PROCEDURE_THRESHOLDS: 'openzeppelin::multisig::procedure_thresholds',
|
|
11
12
|
} as const;
|
|
12
13
|
|
|
13
|
-
const
|
|
14
|
-
SELECTOR: 'openzeppelin::
|
|
15
|
-
PUBLIC_KEY: 'openzeppelin::
|
|
14
|
+
const GUARDIAN_SLOT_NAMES = {
|
|
15
|
+
SELECTOR: 'openzeppelin::guardian::selector',
|
|
16
|
+
PUBLIC_KEY: 'openzeppelin::guardian::public_key',
|
|
16
17
|
} as const;
|
|
17
18
|
|
|
18
19
|
export class StorageLayoutBuilder {
|
|
@@ -31,18 +32,19 @@ export class StorageLayoutBuilder {
|
|
|
31
32
|
const signersMap = new StorageMap();
|
|
32
33
|
config.signerCommitments.forEach((commitment, index) => {
|
|
33
34
|
const key = new Word(new BigUint64Array([BigInt(index), 0n, 0n, 0n]));
|
|
34
|
-
const value = Word.fromHex(
|
|
35
|
+
const value = Word.fromHex(ensureHexPrefix(commitment));
|
|
35
36
|
signersMap.insert(key, value);
|
|
36
37
|
});
|
|
37
38
|
const slot1 = StorageSlot.map(MULTISIG_SLOT_NAMES.SIGNER_PUBLIC_KEYS, signersMap);
|
|
38
39
|
|
|
39
40
|
const slot2 = StorageSlot.map(MULTISIG_SLOT_NAMES.EXECUTED_TRANSACTIONS, new StorageMap());
|
|
40
41
|
|
|
42
|
+
// Map entries: PROC_ROOT => [proc_threshold, 0, 0, 0]
|
|
43
|
+
// Use SDK's Word.fromHex to match how account code procedure roots are represented
|
|
41
44
|
const procThresholdMap = new StorageMap();
|
|
42
45
|
if (config.procedureThresholds) {
|
|
43
|
-
const signatureScheme = config.signatureScheme ?? 'falcon';
|
|
44
46
|
for (const pt of config.procedureThresholds) {
|
|
45
|
-
const rootHex = getProcedureRoot(pt.procedure
|
|
47
|
+
const rootHex = getProcedureRoot(pt.procedure);
|
|
46
48
|
const key = Word.fromHex(rootHex);
|
|
47
49
|
const value = new Word(new BigUint64Array([BigInt(pt.threshold), 0n, 0n, 0n]));
|
|
48
50
|
procThresholdMap.insert(key, value);
|
|
@@ -53,16 +55,16 @@ export class StorageLayoutBuilder {
|
|
|
53
55
|
return [slot0, slot1, slot2, slot3];
|
|
54
56
|
}
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
const selector = config.
|
|
58
|
+
buildGuardianSlots(config: MultisigConfig): StorageSlot[] {
|
|
59
|
+
const selector = config.guardianEnabled !== false ? 1n : 0n;
|
|
58
60
|
const selectorWord = new Word(new BigUint64Array([selector, 0n, 0n, 0n]));
|
|
59
|
-
const slot0 = StorageSlot.fromValue(
|
|
61
|
+
const slot0 = StorageSlot.fromValue(GUARDIAN_SLOT_NAMES.SELECTOR, selectorWord);
|
|
60
62
|
|
|
61
|
-
const
|
|
63
|
+
const guardianKeyMap = new StorageMap();
|
|
62
64
|
const zeroKey = new Word(new BigUint64Array([0n, 0n, 0n, 0n]));
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
const slot1 = StorageSlot.map(
|
|
65
|
+
const guardianKey = Word.fromHex(ensureHexPrefix(config.guardianCommitment));
|
|
66
|
+
guardianKeyMap.insert(zeroKey, guardianKey);
|
|
67
|
+
const slot1 = StorageSlot.map(GUARDIAN_SLOT_NAMES.PUBLIC_KEY, guardianKeyMap);
|
|
66
68
|
|
|
67
69
|
return [slot0, slot1];
|
|
68
70
|
}
|
|
@@ -74,8 +76,8 @@ export function buildMultisigStorageSlots(config: MultisigConfig): StorageSlot[]
|
|
|
74
76
|
return defaultStorageBuilder.buildMultisigSlots(config);
|
|
75
77
|
}
|
|
76
78
|
|
|
77
|
-
export function
|
|
78
|
-
return defaultStorageBuilder.
|
|
79
|
+
export function buildGuardianStorageSlots(config: MultisigConfig): StorageSlot[] {
|
|
80
|
+
return defaultStorageBuilder.buildGuardianSlots(config);
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
export const storageLayoutBuilder = defaultStorageBuilder;
|
package/src/client.test.ts
CHANGED
|
@@ -14,6 +14,7 @@ vi.mock('@miden-sdk/miden-sdk', () => ({
|
|
|
14
14
|
prefix: () => ({ asInt: () => BigInt(1) }),
|
|
15
15
|
suffix: () => ({ asInt: () => BigInt(2) }),
|
|
16
16
|
}),
|
|
17
|
+
serialize: () => new Uint8Array([1, 2, 3]),
|
|
17
18
|
storage: vi.fn(),
|
|
18
19
|
vault: vi.fn(),
|
|
19
20
|
})),
|
|
@@ -27,8 +28,8 @@ vi.mock('./inspector.js', () => ({
|
|
|
27
28
|
threshold: 2,
|
|
28
29
|
numSigners: 2,
|
|
29
30
|
signerCommitments: ['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)],
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
guardianEnabled: true,
|
|
32
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
32
33
|
vaultBalances: [],
|
|
33
34
|
procedureThresholds: new Map(),
|
|
34
35
|
})),
|
|
@@ -50,7 +51,7 @@ vi.mock('./account/index.js', () => ({
|
|
|
50
51
|
}),
|
|
51
52
|
}));
|
|
52
53
|
|
|
53
|
-
// Mock fetch for
|
|
54
|
+
// Mock fetch for GUARDIAN client
|
|
54
55
|
const mockFetch = vi.fn();
|
|
55
56
|
vi.stubGlobal('fetch', mockFetch);
|
|
56
57
|
|
|
@@ -73,30 +74,31 @@ describe('MultisigClient', () => {
|
|
|
73
74
|
};
|
|
74
75
|
|
|
75
76
|
mockSigner = {
|
|
76
|
-
scheme: 'falcon',
|
|
77
77
|
commitment: '0x' + '1'.repeat(64),
|
|
78
78
|
publicKey: '0x' + '2'.repeat(64),
|
|
79
|
+
scheme: 'falcon',
|
|
79
80
|
signAccountIdWithTimestamp: vi.fn().mockResolvedValue('0x' + 'a'.repeat(128)),
|
|
80
|
-
|
|
81
|
+
signRequest: vi.fn().mockReturnValue('0x' + 'a'.repeat(128)),
|
|
82
|
+
signCommitment: vi.fn().mockReturnValue('0x' + 'b'.repeat(128)),
|
|
81
83
|
};
|
|
82
84
|
});
|
|
83
85
|
|
|
84
86
|
describe('constructor', () => {
|
|
85
|
-
it('should create client with default
|
|
87
|
+
it('should create client with default GUARDIAN endpoint', () => {
|
|
86
88
|
const client = new MultisigClient(webClient);
|
|
87
89
|
expect(client).toBeInstanceOf(MultisigClient);
|
|
88
90
|
});
|
|
89
91
|
|
|
90
|
-
it('should create client with custom
|
|
91
|
-
const client = new MultisigClient(webClient, {
|
|
92
|
+
it('should create client with custom GUARDIAN endpoint', () => {
|
|
93
|
+
const client = new MultisigClient(webClient, { guardianEndpoint: 'http://custom:8080' });
|
|
92
94
|
expect(client).toBeInstanceOf(MultisigClient);
|
|
93
95
|
});
|
|
94
96
|
});
|
|
95
97
|
|
|
96
|
-
describe('
|
|
97
|
-
it('should expose
|
|
98
|
+
describe('guardianClient getter', () => {
|
|
99
|
+
it('should expose GUARDIAN client for getting pubkey', () => {
|
|
98
100
|
const client = new MultisigClient(webClient);
|
|
99
|
-
expect(client.
|
|
101
|
+
expect(client.guardianClient).toBeDefined();
|
|
100
102
|
});
|
|
101
103
|
});
|
|
102
104
|
|
|
@@ -107,7 +109,7 @@ describe('MultisigClient', () => {
|
|
|
107
109
|
const config = {
|
|
108
110
|
threshold: 2,
|
|
109
111
|
signerCommitments: ['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)],
|
|
110
|
-
|
|
112
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
111
113
|
};
|
|
112
114
|
|
|
113
115
|
const multisig = await client.create(config, mockSigner);
|
|
@@ -115,16 +117,16 @@ describe('MultisigClient', () => {
|
|
|
115
117
|
expect(multisig).toBeDefined();
|
|
116
118
|
expect(multisig.threshold).toBe(2);
|
|
117
119
|
expect(multisig.signerCommitments).toEqual(config.signerCommitments);
|
|
118
|
-
expect(multisig.
|
|
120
|
+
expect(multisig.guardianCommitment).toBe(config.guardianCommitment);
|
|
119
121
|
});
|
|
120
122
|
|
|
121
|
-
it('should set signer on
|
|
123
|
+
it('should set signer on GUARDIAN client', async () => {
|
|
122
124
|
const client = new MultisigClient(webClient);
|
|
123
125
|
|
|
124
126
|
const config = {
|
|
125
127
|
threshold: 1,
|
|
126
128
|
signerCommitments: ['0x' + 'a'.repeat(64)],
|
|
127
|
-
|
|
129
|
+
guardianCommitment: '0x' + 'c'.repeat(64),
|
|
128
130
|
};
|
|
129
131
|
|
|
130
132
|
const multisig = await client.create(config, mockSigner);
|
|
@@ -156,11 +158,11 @@ describe('MultisigClient', () => {
|
|
|
156
158
|
// Config is detected from account storage via AccountInspector
|
|
157
159
|
expect(multisig.threshold).toBe(2);
|
|
158
160
|
expect(multisig.signerCommitments).toEqual(['0x' + 'a'.repeat(64), '0x' + 'b'.repeat(64)]);
|
|
159
|
-
expect(multisig.
|
|
161
|
+
expect(multisig.guardianCommitment).toBe('0x' + 'c'.repeat(64));
|
|
160
162
|
expect(multisig.account).not.toBeNull();
|
|
161
163
|
});
|
|
162
164
|
|
|
163
|
-
it('should throw if account not found on
|
|
165
|
+
it('should throw if account not found on GUARDIAN', async () => {
|
|
164
166
|
const client = new MultisigClient(webClient);
|
|
165
167
|
|
|
166
168
|
mockFetch.mockResolvedValueOnce({
|
|
@@ -174,40 +176,34 @@ describe('MultisigClient', () => {
|
|
|
174
176
|
client.load('0xnonexistent', mockSigner)
|
|
175
177
|
).rejects.toThrow();
|
|
176
178
|
});
|
|
177
|
-
});
|
|
178
179
|
|
|
179
|
-
|
|
180
|
-
it('should fetch PSM pubkey and return commitment', async () => {
|
|
180
|
+
it('should allow registerOnGuardian after load without explicit initial state', async () => {
|
|
181
181
|
const client = new MultisigClient(webClient);
|
|
182
182
|
|
|
183
183
|
mockFetch.mockResolvedValueOnce({
|
|
184
184
|
ok: true,
|
|
185
185
|
json: async () => ({
|
|
186
|
-
|
|
187
|
-
|
|
186
|
+
account_id: '0x' + 'd'.repeat(30),
|
|
187
|
+
commitment: '0x' + 'e'.repeat(64),
|
|
188
|
+
state_json: { data: 'base64state' },
|
|
189
|
+
created_at: '2024-01-01T00:00:00Z',
|
|
190
|
+
updated_at: '2024-01-02T00:00:00Z',
|
|
188
191
|
}),
|
|
189
192
|
});
|
|
190
193
|
|
|
191
|
-
const result = await client.initialize('falcon');
|
|
192
|
-
|
|
193
|
-
expect(result.psmCommitment).toBe('0x' + 'f'.repeat(64));
|
|
194
|
-
expect(result.psmPublicKey).toBe('0x' + 'e'.repeat(64));
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it('should work without specifying scheme', async () => {
|
|
198
|
-
const client = new MultisigClient(webClient);
|
|
199
|
-
|
|
200
194
|
mockFetch.mockResolvedValueOnce({
|
|
201
195
|
ok: true,
|
|
202
196
|
json: async () => ({
|
|
203
|
-
|
|
197
|
+
success: true,
|
|
198
|
+
message: 'Account configured',
|
|
199
|
+
ack_pubkey: '0x' + 'f'.repeat(64),
|
|
204
200
|
}),
|
|
205
201
|
});
|
|
206
202
|
|
|
207
|
-
const
|
|
203
|
+
const accountId = '0x' + 'd'.repeat(30);
|
|
204
|
+
const multisig = await client.load(accountId, mockSigner);
|
|
208
205
|
|
|
209
|
-
expect(
|
|
210
|
-
expect(result.psmPublicKey).toBeUndefined();
|
|
206
|
+
await expect(multisig.registerOnGuardian()).resolves.toBeUndefined();
|
|
211
207
|
});
|
|
212
208
|
});
|
|
213
209
|
});
|
package/src/client.ts
CHANGED
|
@@ -1,52 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MultisigClient - Factory for creating and loading multisig accounts.
|
|
3
|
+
*
|
|
4
|
+
* This is the main entry point for the multisig SDK. It provides methods
|
|
5
|
+
* to create new multisig accounts and load existing ones.
|
|
6
|
+
*/
|
|
7
|
+
|
|
1
8
|
import { type WebClient, Account, AccountId } from '@miden-sdk/miden-sdk';
|
|
2
|
-
import {
|
|
9
|
+
import { GuardianHttpClient } from '@openzeppelin/guardian-client';
|
|
3
10
|
import { Multisig } from './multisig.js';
|
|
4
11
|
import { createMultisigAccount } from './account/index.js';
|
|
5
12
|
import { AccountInspector } from './inspector.js';
|
|
6
13
|
import type { MultisigConfig, Signer } from './types.js';
|
|
7
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Configuration for MultisigClient.
|
|
17
|
+
*/
|
|
8
18
|
export interface MultisigClientConfig {
|
|
9
|
-
|
|
19
|
+
/** GUARDIAN server endpoint */
|
|
20
|
+
guardianEndpoint?: string;
|
|
21
|
+
/** Miden node RPC endpoint used for state commitment verification */
|
|
22
|
+
midenRpcEndpoint?: string;
|
|
10
23
|
}
|
|
11
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Client for creating and loading multisig accounts.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* import { MultisigClient, FalconSigner } from '@openzeppelin/miden-multisig-client';
|
|
31
|
+
* import { WebClient, SecretKey } from '@miden-sdk/miden-sdk';
|
|
32
|
+
*
|
|
33
|
+
* // Initialize
|
|
34
|
+
* const webClient = await WebClient.createClient('https://rpc.testnet.miden.io:443');
|
|
35
|
+
* const secretKey = SecretKey.rpoFalconWithRNG(seed);
|
|
36
|
+
* const signer = new FalconSigner(secretKey);
|
|
37
|
+
*
|
|
38
|
+
* // Create client
|
|
39
|
+
* const client = new MultisigClient(webClient, {
|
|
40
|
+
* guardianEndpoint: 'http://localhost:3000',
|
|
41
|
+
* midenRpcEndpoint: 'https://rpc.testnet.miden.io:443',
|
|
42
|
+
* });
|
|
43
|
+
*
|
|
44
|
+
* // Get GUARDIAN pubkey for config
|
|
45
|
+
* const guardianCommitment = await client.guardianClient.getPubkey();
|
|
46
|
+
*
|
|
47
|
+
* // Create multisig
|
|
48
|
+
* const config = { threshold: 2, signerCommitments: [...], guardianCommitment };
|
|
49
|
+
* const multisig = await client.create(config, signer);
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
12
52
|
export class MultisigClient {
|
|
13
53
|
private readonly webClient: WebClient;
|
|
14
|
-
private
|
|
54
|
+
private readonly midenRpcEndpoint?: string;
|
|
55
|
+
private _guardianClient: GuardianHttpClient;
|
|
15
56
|
|
|
16
57
|
constructor(webClient: WebClient, config: MultisigClientConfig = {}) {
|
|
17
58
|
this.webClient = webClient;
|
|
18
|
-
this.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
setPsmEndpoint(endpoint: string): void {
|
|
22
|
-
this._psmClient = new PsmHttpClient(endpoint);
|
|
59
|
+
this.midenRpcEndpoint = config.midenRpcEndpoint;
|
|
60
|
+
this._guardianClient = new GuardianHttpClient(config.guardianEndpoint ?? 'http://localhost:3000');
|
|
23
61
|
}
|
|
24
62
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Change the GUARDIAN endpoint.
|
|
65
|
+
*
|
|
66
|
+
* @param endpoint - The new GUARDIAN server endpoint URL
|
|
67
|
+
*/
|
|
68
|
+
setGuardianEndpoint(endpoint: string): void {
|
|
69
|
+
this._guardianClient = new GuardianHttpClient(endpoint);
|
|
28
70
|
}
|
|
29
71
|
|
|
30
|
-
|
|
31
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Access the internal GUARDIAN client.
|
|
74
|
+
*/
|
|
75
|
+
get guardianClient(): GuardianHttpClient {
|
|
76
|
+
return this._guardianClient;
|
|
32
77
|
}
|
|
33
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Create a new multisig account.
|
|
81
|
+
*
|
|
82
|
+
* @param config - Multisig configuration (threshold, signers, GUARDIAN commitment)
|
|
83
|
+
* @param signer - The signer for this client (one of the cosigners)
|
|
84
|
+
* @returns A Multisig instance wrapping the created account
|
|
85
|
+
*/
|
|
34
86
|
async create(config: MultisigConfig, signer: Signer): Promise<Multisig> {
|
|
35
|
-
this.
|
|
87
|
+
this._guardianClient.setSigner(signer);
|
|
36
88
|
|
|
37
89
|
const { account } = await createMultisigAccount(this.webClient, config);
|
|
38
90
|
|
|
39
|
-
return new Multisig(
|
|
91
|
+
return new Multisig(
|
|
92
|
+
account,
|
|
93
|
+
config,
|
|
94
|
+
this._guardianClient,
|
|
95
|
+
signer,
|
|
96
|
+
this.webClient,
|
|
97
|
+
undefined,
|
|
98
|
+
this.midenRpcEndpoint
|
|
99
|
+
);
|
|
40
100
|
}
|
|
41
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Load an existing multisig account from GUARDIAN.
|
|
104
|
+
*
|
|
105
|
+
* @param accountId - The account ID to load
|
|
106
|
+
* @param signer - The signer for this client
|
|
107
|
+
* @returns A Multisig instance for the loaded account
|
|
108
|
+
*/
|
|
42
109
|
async load(accountId: string, signer: Signer): Promise<Multisig> {
|
|
43
|
-
this.
|
|
110
|
+
this._guardianClient.setSigner(signer);
|
|
44
111
|
|
|
45
|
-
const stateResponse = await this.
|
|
112
|
+
const stateResponse = await this._guardianClient.getState(accountId);
|
|
46
113
|
|
|
47
114
|
const accountBase64 = stateResponse.stateJson.data;
|
|
48
115
|
if (!accountBase64) {
|
|
49
|
-
throw new Error('No account data found in
|
|
116
|
+
throw new Error('No account data found in GUARDIAN state');
|
|
50
117
|
}
|
|
51
118
|
|
|
52
119
|
const binaryString = atob(accountBase64);
|
|
@@ -56,15 +123,12 @@ export class MultisigClient {
|
|
|
56
123
|
}
|
|
57
124
|
const account = Account.deserialize(accountBytes);
|
|
58
125
|
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
const detected = AccountInspector.fromAccount(account, detectedScheme);
|
|
126
|
+
const detected = AccountInspector.fromAccount(account);
|
|
62
127
|
const config: MultisigConfig = {
|
|
63
128
|
threshold: detected.threshold,
|
|
64
129
|
signerCommitments: detected.signerCommitments,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
signatureScheme: detected.signatureScheme,
|
|
130
|
+
guardianCommitment: detected.guardianCommitment ?? '',
|
|
131
|
+
guardianEnabled: detected.guardianEnabled,
|
|
68
132
|
procedureThresholds: Array.from(detected.procedureThresholds.entries()).map(
|
|
69
133
|
([procedure, threshold]) => ({ procedure, threshold })
|
|
70
134
|
),
|
|
@@ -72,9 +136,17 @@ export class MultisigClient {
|
|
|
72
136
|
|
|
73
137
|
const existingAccount = await this.webClient.getAccount(AccountId.fromHex(accountId));
|
|
74
138
|
if (!existingAccount) {
|
|
75
|
-
|
|
139
|
+
await this.webClient.newAccount(account, true);
|
|
76
140
|
}
|
|
77
141
|
|
|
78
|
-
return new Multisig(
|
|
142
|
+
return new Multisig(
|
|
143
|
+
account,
|
|
144
|
+
config,
|
|
145
|
+
this._guardianClient,
|
|
146
|
+
signer,
|
|
147
|
+
this.webClient,
|
|
148
|
+
accountId,
|
|
149
|
+
this.midenRpcEndpoint
|
|
150
|
+
);
|
|
79
151
|
}
|
|
80
152
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,38 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @openzeppelin/miden-multisig-client
|
|
3
|
+
*
|
|
4
|
+
* TypeScript SDK for Miden multisig accounts with Guardian integration.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import {
|
|
9
|
+
* MultisigClient,
|
|
10
|
+
* FalconSigner,
|
|
11
|
+
* } from '@openzeppelin/miden-multisig-client';
|
|
12
|
+
* import { WebClient, SecretKey } from '@miden-sdk/miden-sdk';
|
|
13
|
+
*
|
|
14
|
+
* // Initialize WebClient
|
|
15
|
+
* const webClient = await WebClient.createClient('https://rpc.testnet.miden.io:443');
|
|
16
|
+
* await webClient.syncState();
|
|
17
|
+
*
|
|
18
|
+
* // Generate a key dynamically
|
|
19
|
+
* const seed = new Uint8Array(32);
|
|
20
|
+
* crypto.getRandomValues(seed);
|
|
21
|
+
* const secretKey = SecretKey.rpoFalconWithRNG(seed);
|
|
22
|
+
*
|
|
23
|
+
* // Store in miden-sdk's keystore
|
|
24
|
+
* await webClient.addAccountSecretKeyToWebStore(secretKey);
|
|
25
|
+
*
|
|
26
|
+
* // Create a signer
|
|
27
|
+
* const signer = new FalconSigner(secretKey);
|
|
28
|
+
*
|
|
29
|
+
* // Create multisig client
|
|
30
|
+
* const client = new MultisigClient(webClient, {
|
|
31
|
+
* guardianEndpoint: 'http://localhost:3000',
|
|
32
|
+
* midenRpcEndpoint: 'https://rpc.testnet.miden.io:443',
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* // Get GUARDIAN pubkey for config
|
|
36
|
+
* const guardianCommitment = await client.guardianClient.getPubkey();
|
|
37
|
+
*
|
|
38
|
+
* // Create multisig account
|
|
39
|
+
* const config = { threshold: 2, signerCommitments: [signer.commitment, ...], guardianCommitment };
|
|
40
|
+
* const multisig = await client.create(config, signer);
|
|
41
|
+
*
|
|
42
|
+
* // Register on GUARDIAN and work with proposals
|
|
43
|
+
* await multisig.registerOnGuardian();
|
|
44
|
+
* await multisig.syncProposals();
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
|
|
1
48
|
export { MultisigClient, type MultisigClientConfig } from './client.js';
|
|
2
49
|
export { Multisig, type AccountState } from './multisig.js';
|
|
3
50
|
export { AccountInspector, type DetectedMultisigConfig, type VaultBalance } from './inspector.js';
|
|
4
51
|
export {
|
|
5
52
|
executeForSummary,
|
|
6
53
|
buildUpdateSignersTransactionRequest,
|
|
7
|
-
|
|
54
|
+
buildUpdateProcedureThresholdTransactionRequest,
|
|
55
|
+
buildUpdateGuardianTransactionRequest,
|
|
8
56
|
buildConsumeNotesTransactionRequest,
|
|
9
57
|
buildP2idTransactionRequest,
|
|
10
58
|
} from './transaction.js';
|
|
11
59
|
|
|
12
|
-
export {
|
|
60
|
+
export { GuardianHttpClient, GuardianHttpError } from '@openzeppelin/guardian-client';
|
|
13
61
|
|
|
14
|
-
export {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
62
|
+
export {
|
|
63
|
+
FalconSigner,
|
|
64
|
+
EcdsaSigner,
|
|
65
|
+
ParaSigner,
|
|
66
|
+
MidenWalletSigner,
|
|
67
|
+
type ParaSigningContext,
|
|
68
|
+
type WalletSigningContext,
|
|
69
|
+
} from './signer.js';
|
|
19
70
|
export { PublicKeyFormat } from './utils/key.js';
|
|
20
|
-
export {
|
|
21
|
-
export { tryComputeEcdsaCommitmentHex
|
|
71
|
+
export { EcdsaFormat } from './utils/ecdsa.js';
|
|
72
|
+
export { tryComputeEcdsaCommitmentHex } from './utils/signature.js';
|
|
22
73
|
|
|
23
74
|
export {
|
|
24
75
|
createMultisigAccount,
|
|
25
76
|
validateMultisigConfig,
|
|
26
77
|
buildMultisigStorageSlots,
|
|
27
|
-
|
|
78
|
+
buildGuardianStorageSlots,
|
|
28
79
|
storageLayoutBuilder,
|
|
29
80
|
StorageLayoutBuilder,
|
|
30
81
|
} from './account/index.js';
|
|
31
82
|
|
|
32
83
|
export {
|
|
33
84
|
PROCEDURE_ROOTS,
|
|
34
|
-
PROCEDURE_ROOTS_FALCON,
|
|
35
|
-
PROCEDURE_ROOTS_ECDSA,
|
|
36
85
|
getProcedureRoot,
|
|
37
86
|
isProcedureName,
|
|
38
87
|
getProcedureNames,
|
|
@@ -40,32 +89,45 @@ export {
|
|
|
40
89
|
} from './procedures.js';
|
|
41
90
|
|
|
42
91
|
export type {
|
|
92
|
+
// Account types
|
|
43
93
|
MultisigAccountState,
|
|
44
94
|
MultisigConfig,
|
|
45
95
|
CreateAccountResult,
|
|
46
96
|
ProcedureThreshold,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
SyncResult,
|
|
53
|
-
TransactionProposalResult,
|
|
97
|
+
|
|
98
|
+
// Proposal types
|
|
99
|
+
Proposal,
|
|
100
|
+
ProposalStatus,
|
|
101
|
+
ProposalSignatureEntry,
|
|
54
102
|
ProposalMetadata,
|
|
55
103
|
ProposalType,
|
|
104
|
+
ExportedProposal,
|
|
105
|
+
ExportedTransactionProposal,
|
|
106
|
+
SignTransactionProposalParams,
|
|
107
|
+
TransactionProposal,
|
|
108
|
+
TransactionProposalSignature,
|
|
109
|
+
TransactionProposalStatus,
|
|
110
|
+
|
|
111
|
+
// Transaction types
|
|
56
112
|
TransactionType,
|
|
113
|
+
|
|
114
|
+
// Note types
|
|
57
115
|
ConsumableNote,
|
|
58
116
|
NoteAsset,
|
|
117
|
+
|
|
118
|
+
// Signature types
|
|
59
119
|
FalconSignature,
|
|
60
|
-
EcdsaSignature,
|
|
61
|
-
ProposalSignature,
|
|
62
|
-
SignatureScheme,
|
|
63
120
|
Signer,
|
|
121
|
+
SignatureScheme,
|
|
122
|
+
|
|
123
|
+
// GUARDIAN API types
|
|
64
124
|
AuthConfig,
|
|
65
125
|
DeltaObject,
|
|
66
126
|
DeltaStatus,
|
|
67
127
|
StateObject,
|
|
68
128
|
CosignerSignature,
|
|
129
|
+
|
|
130
|
+
// Request/Response types
|
|
69
131
|
ConfigureRequest,
|
|
70
132
|
ConfigureResponse,
|
|
71
133
|
DeltaProposalRequest,
|
package/src/inspector.test.ts
CHANGED
|
@@ -9,9 +9,9 @@ const MULTISIG_SLOT_NAMES = {
|
|
|
9
9
|
PROCEDURE_THRESHOLDS: 'openzeppelin::multisig::procedure_thresholds',
|
|
10
10
|
} as const;
|
|
11
11
|
|
|
12
|
-
const
|
|
13
|
-
SELECTOR: 'openzeppelin::
|
|
14
|
-
PUBLIC_KEY: 'openzeppelin::
|
|
12
|
+
const GUARDIAN_SLOT_NAMES = {
|
|
13
|
+
SELECTOR: 'openzeppelin::guardian::selector',
|
|
14
|
+
PUBLIC_KEY: 'openzeppelin::guardian::public_key',
|
|
15
15
|
} as const;
|
|
16
16
|
|
|
17
17
|
// Mock the Miden SDK
|
|
@@ -44,25 +44,25 @@ vi.mock('@miden-sdk/miden-sdk', () => {
|
|
|
44
44
|
Account: {
|
|
45
45
|
deserialize: vi.fn((bytes: Uint8Array) => {
|
|
46
46
|
// Return different mocked accounts based on test scenario
|
|
47
|
-
// Default: 2-of-3 multisig with
|
|
47
|
+
// Default: 2-of-3 multisig with GUARDIAN enabled
|
|
48
48
|
const slot0 = createMockWord([2n, 3n, 0n, 0n]); // threshold=2, numSigners=3
|
|
49
|
-
const slot4 = createMockWord([1n, 0n, 0n, 0n]); //
|
|
49
|
+
const slot4 = createMockWord([1n, 0n, 0n, 0n]); // GUARDIAN enabled
|
|
50
50
|
|
|
51
51
|
const signerMap = new Map<string, any>();
|
|
52
52
|
signerMap.set('0', createMockWord([BigInt('0x1111111111111111'), BigInt('0x2222222222222222'), BigInt('0x3333333333333333'), BigInt('0x4444444444444444')]));
|
|
53
53
|
signerMap.set('1', createMockWord([BigInt('0x5555555555555555'), BigInt('0x6666666666666666'), BigInt('0x7777777777777777'), BigInt('0x8888888888888888')]));
|
|
54
54
|
signerMap.set('2', createMockWord([BigInt('0xaaaaaaaaaaaaaaaa'), BigInt('0xbbbbbbbbbbbbbbbb'), BigInt('0xcccccccccccccccc'), BigInt('0xdddddddddddddddd')]));
|
|
55
55
|
|
|
56
|
-
const
|
|
57
|
-
|
|
56
|
+
const guardianMap = new Map<string, any>();
|
|
57
|
+
guardianMap.set('0', createMockWord([BigInt('0xeeeeeeeeeeeeeeee'), BigInt('0xffffffffffffffff'), BigInt('0x0000000000000001'), BigInt('0x0000000000000002')]));
|
|
58
58
|
|
|
59
59
|
const slots = new Map<string, any>();
|
|
60
60
|
slots.set('openzeppelin::multisig::threshold_config', slot0);
|
|
61
|
-
slots.set('openzeppelin::
|
|
61
|
+
slots.set('openzeppelin::guardian::selector', slot4);
|
|
62
62
|
|
|
63
63
|
const maps = new Map<string, Map<string, any>>();
|
|
64
64
|
maps.set('openzeppelin::multisig::signer_public_keys', signerMap);
|
|
65
|
-
maps.set('openzeppelin::
|
|
65
|
+
maps.set('openzeppelin::guardian::public_key', guardianMap);
|
|
66
66
|
|
|
67
67
|
return {
|
|
68
68
|
storage: () => createMockStorage(slots, maps),
|
|
@@ -94,12 +94,12 @@ describe('AccountInspector', () => {
|
|
|
94
94
|
expect(config.numSigners).toBe(3);
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
-
it('extracts
|
|
97
|
+
it('extracts GUARDIAN status', () => {
|
|
98
98
|
const base64 = btoa(String.fromCharCode(...new Uint8Array([1, 2, 3])));
|
|
99
99
|
const config = AccountInspector.fromBase64(base64);
|
|
100
100
|
|
|
101
|
-
expect(config.
|
|
102
|
-
expect(config.
|
|
101
|
+
expect(config.guardianEnabled).toBe(true);
|
|
102
|
+
expect(config.guardianCommitment).toMatch(/^0x[a-f0-9]+$/);
|
|
103
103
|
});
|
|
104
104
|
|
|
105
105
|
it('extracts signer commitments', () => {
|
|
@@ -146,7 +146,7 @@ describe('AccountInspector edge cases', () => {
|
|
|
146
146
|
vi.clearAllMocks();
|
|
147
147
|
});
|
|
148
148
|
|
|
149
|
-
it('handles account with
|
|
149
|
+
it('handles account with GUARDIAN disabled', async () => {
|
|
150
150
|
const { Account } = await import('@miden-sdk/miden-sdk');
|
|
151
151
|
|
|
152
152
|
// Override mock for this test
|
|
@@ -154,7 +154,7 @@ describe('AccountInspector edge cases', () => {
|
|
|
154
154
|
storage: () => ({
|
|
155
155
|
getItem: (slotName: string) => {
|
|
156
156
|
if (slotName === 'openzeppelin::multisig::threshold_config') return { toU64s: () => [1n, 1n, 0n, 0n] };
|
|
157
|
-
if (slotName === 'openzeppelin::
|
|
157
|
+
if (slotName === 'openzeppelin::guardian::selector') return { toU64s: () => [0n, 0n, 0n, 0n] }; // GUARDIAN disabled
|
|
158
158
|
return { toU64s: () => [0n, 0n, 0n, 0n] };
|
|
159
159
|
},
|
|
160
160
|
getMapItem: (slotName: string, key: any) => {
|
|
@@ -175,8 +175,8 @@ describe('AccountInspector edge cases', () => {
|
|
|
175
175
|
const account = Account.deserialize(new Uint8Array([1, 2, 3]));
|
|
176
176
|
const config = AccountInspector.fromAccount(account);
|
|
177
177
|
|
|
178
|
-
expect(config.
|
|
179
|
-
expect(config.
|
|
178
|
+
expect(config.guardianEnabled).toBe(false);
|
|
179
|
+
expect(config.guardianCommitment).toBeNull();
|
|
180
180
|
});
|
|
181
181
|
|
|
182
182
|
it('handles account with empty vault', async () => {
|
|
@@ -207,7 +207,7 @@ describe('AccountInspector edge cases', () => {
|
|
|
207
207
|
storage: () => ({
|
|
208
208
|
getItem: (slotName: string) => {
|
|
209
209
|
if (slotName === 'openzeppelin::multisig::threshold_config') return { toU64s: () => [2n, 5n, 0n, 0n] }; // threshold=2, numSigners=5
|
|
210
|
-
if (slotName === 'openzeppelin::
|
|
210
|
+
if (slotName === 'openzeppelin::guardian::selector') return { toU64s: () => [0n, 0n, 0n, 0n] };
|
|
211
211
|
return { toU64s: () => [0n, 0n, 0n, 0n] };
|
|
212
212
|
},
|
|
213
213
|
getMapItem: () => {
|