@openzeppelin/miden-multisig-client 0.17.0-rc.2 → 0.17.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 +172 -47
- package/dist/account/builder.d.ts +2 -2
- package/dist/account/builder.d.ts.map +1 -1
- package/dist/account/builder.js +49 -24
- package/dist/account/builder.js.map +1 -1
- package/dist/connectivity.d.ts +2 -0
- package/dist/connectivity.d.ts.map +1 -1
- package/dist/connectivity.js +7 -4
- package/dist/connectivity.js.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/multisig/authArgErrors.d.ts +59 -0
- package/dist/multisig/authArgErrors.d.ts.map +1 -0
- package/dist/multisig/authArgErrors.js +115 -0
- package/dist/multisig/authArgErrors.js.map +1 -0
- package/dist/multisig/helpers.d.ts +5 -0
- package/dist/multisig/helpers.d.ts.map +1 -1
- package/dist/multisig/helpers.js +7 -2
- package/dist/multisig/helpers.js.map +1 -1
- package/dist/multisig.d.ts +140 -0
- package/dist/multisig.d.ts.map +1 -1
- package/dist/multisig.js +419 -12
- package/dist/multisig.js.map +1 -1
- package/dist/procedures.d.ts +1 -1
- package/dist/procedures.js +1 -1
- package/dist/recovery/proposalNoteImport.d.ts +173 -0
- package/dist/recovery/proposalNoteImport.d.ts.map +1 -0
- package/dist/recovery/proposalNoteImport.js +411 -0
- package/dist/recovery/proposalNoteImport.js.map +1 -0
- package/dist/recovery/publicNoteBackfill.d.ts +168 -0
- package/dist/recovery/publicNoteBackfill.d.ts.map +1 -0
- package/dist/recovery/publicNoteBackfill.js +368 -0
- package/dist/recovery/publicNoteBackfill.js.map +1 -0
- package/dist/recovery/recoverNotes.d.ts +147 -0
- package/dist/recovery/recoverNotes.d.ts.map +1 -0
- package/dist/recovery/recoverNotes.js +163 -0
- package/dist/recovery/recoverNotes.js.map +1 -0
- package/dist/recovery/transportDrain.d.ts +124 -0
- package/dist/recovery/transportDrain.d.ts.map +1 -0
- package/dist/recovery/transportDrain.js +262 -0
- package/dist/recovery/transportDrain.js.map +1 -0
- package/dist/transaction/consumeNotes.d.ts.map +1 -1
- package/dist/transaction/consumeNotes.js +4 -1
- package/dist/transaction/consumeNotes.js.map +1 -1
- package/dist/transaction/p2id.d.ts.map +1 -1
- package/dist/transaction/p2id.js +4 -1
- package/dist/transaction/p2id.js.map +1 -1
- package/dist/transaction/summary.d.ts +10 -4
- package/dist/transaction/summary.d.ts.map +1 -1
- package/dist/transaction/summary.js +13 -7
- package/dist/transaction/summary.js.map +1 -1
- package/dist/transaction/updateGuardian.js +4 -1
- package/dist/transaction/updateGuardian.js.map +1 -1
- package/dist/transaction/updateProcedureThreshold.js +4 -1
- package/dist/transaction/updateProcedureThreshold.js.map +1 -1
- package/dist/transaction/updateSigners.js +4 -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/package.json +14 -10
- package/src/account/builder.ts +87 -35
- package/src/connectivity.ts +9 -4
- package/src/index.ts +34 -1
- package/src/multisig/authArgErrors.ts +138 -0
- package/src/multisig/helpers.ts +7 -2
- package/src/multisig.ts +513 -20
- package/src/procedures.ts +1 -1
- package/src/recovery/proposalNoteImport.ts +548 -0
- package/src/recovery/publicNoteBackfill.ts +502 -0
- package/src/recovery/recoverNotes.ts +288 -0
- package/src/recovery/transportDrain.ts +330 -0
- package/src/transaction/consumeNotes.ts +4 -1
- package/src/transaction/p2id.ts +4 -1
- package/src/transaction/summary.ts +13 -7
- package/src/transaction/updateGuardian.ts +4 -1
- package/src/transaction/updateProcedureThreshold.ts +4 -1
- package/src/transaction/updateSigners.ts +4 -1
- package/src/transaction.ts +1 -1
- package/dist/account/builder.test.d.ts +0 -2
- package/dist/account/builder.test.d.ts.map +0 -1
- package/dist/account/builder.test.js +0 -166
- package/dist/account/builder.test.js.map +0 -1
- package/dist/account/masm/account-components/auth.d.ts +0 -2
- package/dist/account/masm/account-components/auth.d.ts.map +0 -1
- package/dist/account/masm/account-components/auth.js +0 -46
- package/dist/account/masm/account-components/auth.js.map +0 -1
- package/dist/account/masm/index.d.ts +0 -2
- package/dist/account/masm/index.d.ts.map +0 -1
- package/dist/account/masm/index.js +0 -4
- package/dist/account/masm/index.js.map +0 -1
- package/dist/account/masm.d.ts +0 -2
- package/dist/account/masm.d.ts.map +0 -1
- package/dist/account/masm.js +0 -4
- package/dist/account/masm.js.map +0 -1
- package/dist/account/storage.test.d.ts +0 -2
- package/dist/account/storage.test.d.ts.map +0 -1
- package/dist/account/storage.test.js +0 -73
- package/dist/account/storage.test.js.map +0 -1
- package/dist/client.test.d.ts +0 -2
- package/dist/client.test.d.ts.map +0 -1
- package/dist/client.test.js +0 -380
- package/dist/client.test.js.map +0 -1
- package/dist/connectivity.test.d.ts +0 -2
- package/dist/connectivity.test.d.ts.map +0 -1
- package/dist/connectivity.test.js +0 -61
- package/dist/connectivity.test.js.map +0 -1
- package/dist/inspector.test.d.ts +0 -2
- package/dist/inspector.test.d.ts.map +0 -1
- package/dist/inspector.test.js +0 -425
- package/dist/inspector.test.js.map +0 -1
- package/dist/lookupAuth.test.d.ts +0 -2
- package/dist/lookupAuth.test.d.ts.map +0 -1
- package/dist/lookupAuth.test.js +0 -138
- package/dist/lookupAuth.test.js.map +0 -1
- package/dist/multisig/consumeNotesErrors.test.d.ts +0 -2
- package/dist/multisig/consumeNotesErrors.test.d.ts.map +0 -1
- package/dist/multisig/consumeNotesErrors.test.js +0 -28
- package/dist/multisig/consumeNotesErrors.test.js.map +0 -1
- package/dist/multisig/helpers.test.d.ts +0 -2
- package/dist/multisig/helpers.test.d.ts.map +0 -1
- package/dist/multisig/helpers.test.js +0 -94
- package/dist/multisig/helpers.test.js.map +0 -1
- package/dist/multisig.test.d.ts +0 -2
- package/dist/multisig.test.d.ts.map +0 -1
- package/dist/multisig.test.js +0 -4112
- package/dist/multisig.test.js.map +0 -1
- package/dist/proposal/factory.test.d.ts +0 -2
- package/dist/proposal/factory.test.d.ts.map +0 -1
- package/dist/proposal/factory.test.js +0 -32
- package/dist/proposal/factory.test.js.map +0 -1
- package/dist/proposal/metadata.test.d.ts +0 -2
- package/dist/proposal/metadata.test.d.ts.map +0 -1
- package/dist/proposal/metadata.test.js +0 -193
- package/dist/proposal/metadata.test.js.map +0 -1
- package/dist/prover/config.test.d.ts +0 -2
- package/dist/prover/config.test.d.ts.map +0 -1
- package/dist/prover/config.test.js +0 -54
- package/dist/prover/config.test.js.map +0 -1
- package/dist/prover/errors.test.d.ts +0 -2
- package/dist/prover/errors.test.d.ts.map +0 -1
- package/dist/prover/errors.test.js +0 -29
- package/dist/prover/errors.test.js.map +0 -1
- package/dist/prover/retry.test.d.ts +0 -2
- package/dist/prover/retry.test.d.ts.map +0 -1
- package/dist/prover/retry.test.js +0 -20
- package/dist/prover/retry.test.js.map +0 -1
- package/dist/prover/workflow.test.d.ts +0 -2
- package/dist/prover/workflow.test.d.ts.map +0 -1
- package/dist/prover/workflow.test.js +0 -105
- package/dist/prover/workflow.test.js.map +0 -1
- package/dist/raw-client.test.d.ts +0 -2
- package/dist/raw-client.test.d.ts.map +0 -1
- package/dist/raw-client.test.js +0 -111
- package/dist/raw-client.test.js.map +0 -1
- package/dist/rpc/config.test.d.ts +0 -2
- package/dist/rpc/config.test.d.ts.map +0 -1
- package/dist/rpc/config.test.js +0 -24
- package/dist/rpc/config.test.js.map +0 -1
- package/dist/rpc/errors.test.d.ts +0 -2
- package/dist/rpc/errors.test.d.ts.map +0 -1
- package/dist/rpc/errors.test.js +0 -34
- package/dist/rpc/errors.test.js.map +0 -1
- package/dist/rpc/retry.test.d.ts +0 -2
- package/dist/rpc/retry.test.d.ts.map +0 -1
- package/dist/rpc/retry.test.js +0 -98
- package/dist/rpc/retry.test.js.map +0 -1
- package/dist/signers/ecdsa.test.d.ts +0 -2
- package/dist/signers/ecdsa.test.d.ts.map +0 -1
- package/dist/signers/ecdsa.test.js +0 -88
- package/dist/signers/ecdsa.test.js.map +0 -1
- package/dist/signers/falcon.test.d.ts +0 -2
- package/dist/signers/falcon.test.d.ts.map +0 -1
- package/dist/signers/falcon.test.js +0 -161
- package/dist/signers/falcon.test.js.map +0 -1
- package/dist/signers/miden-wallet.ecdsa-recovery.test.d.ts +0 -2
- package/dist/signers/miden-wallet.ecdsa-recovery.test.d.ts.map +0 -1
- package/dist/signers/miden-wallet.ecdsa-recovery.test.js +0 -148
- package/dist/signers/miden-wallet.ecdsa-recovery.test.js.map +0 -1
- package/dist/signers/miden-wallet.test.d.ts +0 -2
- package/dist/signers/miden-wallet.test.d.ts.map +0 -1
- package/dist/signers/miden-wallet.test.js +0 -164
- package/dist/signers/miden-wallet.test.js.map +0 -1
- package/dist/signers/para.test.d.ts +0 -2
- package/dist/signers/para.test.d.ts.map +0 -1
- package/dist/signers/para.test.js +0 -146
- package/dist/signers/para.test.js.map +0 -1
- package/dist/transaction/index.d.ts +0 -8
- package/dist/transaction/index.d.ts.map +0 -1
- package/dist/transaction/index.js +0 -7
- package/dist/transaction/index.js.map +0 -1
- package/dist/transaction/p2id.test.d.ts +0 -2
- package/dist/transaction/p2id.test.d.ts.map +0 -1
- package/dist/transaction/p2id.test.js +0 -246
- package/dist/transaction/p2id.test.js.map +0 -1
- package/dist/transaction/rpoRandomCoin.test.d.ts +0 -2
- package/dist/transaction/rpoRandomCoin.test.d.ts.map +0 -1
- package/dist/transaction/rpoRandomCoin.test.js +0 -52
- package/dist/transaction/rpoRandomCoin.test.js.map +0 -1
- package/dist/transaction/summary.test.d.ts +0 -2
- package/dist/transaction/summary.test.d.ts.map +0 -1
- package/dist/transaction/summary.test.js +0 -26
- package/dist/transaction/summary.test.js.map +0 -1
- package/dist/transaction.test.d.ts +0 -2
- package/dist/transaction.test.d.ts.map +0 -1
- package/dist/transaction.test.js +0 -122
- package/dist/transaction.test.js.map +0 -1
- package/dist/types/proposal.test.d.ts +0 -2
- package/dist/types/proposal.test.d.ts.map +0 -1
- package/dist/types/proposal.test.js +0 -56
- package/dist/types/proposal.test.js.map +0 -1
- package/dist/utils/digest.test.d.ts +0 -2
- package/dist/utils/digest.test.d.ts.map +0 -1
- package/dist/utils/digest.test.js +0 -48
- package/dist/utils/digest.test.js.map +0 -1
- package/dist/utils/ecdsa.test.d.ts +0 -2
- package/dist/utils/ecdsa.test.d.ts.map +0 -1
- package/dist/utils/ecdsa.test.js +0 -131
- package/dist/utils/ecdsa.test.js.map +0 -1
- package/dist/utils/encoding.test.d.ts +0 -2
- package/dist/utils/encoding.test.d.ts.map +0 -1
- package/dist/utils/encoding.test.js +0 -185
- package/dist/utils/encoding.test.js.map +0 -1
- package/dist/utils/key.test.d.ts +0 -2
- package/dist/utils/key.test.d.ts.map +0 -1
- package/dist/utils/key.test.js +0 -82
- package/dist/utils/key.test.js.map +0 -1
- package/dist/utils/signature.test.d.ts +0 -2
- package/dist/utils/signature.test.d.ts.map +0 -1
- package/dist/utils/signature.test.js +0 -164
- package/dist/utils/signature.test.js.map +0 -1
- package/dist/utils/word.test.d.ts +0 -2
- package/dist/utils/word.test.d.ts.map +0 -1
- package/dist/utils/word.test.js +0 -54
- package/dist/utils/word.test.js.map +0 -1
- package/masm/account_components/auth/guarded_multisig.masm +0 -42
- package/src/account/builder.test.ts +0 -238
- package/src/account/masm/account-components/auth.ts +0 -46
- package/src/account/masm/index.ts +0 -4
- package/src/account/masm.ts +0 -4
- package/src/account/storage.test.ts +0 -90
- package/src/client.test.ts +0 -473
- package/src/connectivity.test.ts +0 -67
- package/src/inspector.test.ts +0 -542
- package/src/lookupAuth.test.ts +0 -185
- package/src/multisig/consumeNotesErrors.test.ts +0 -43
- package/src/multisig/helpers.test.ts +0 -114
- package/src/multisig.test.ts +0 -5008
- package/src/proposal/factory.test.ts +0 -40
- package/src/proposal/metadata.test.ts +0 -235
- package/src/prover/config.test.ts +0 -90
- package/src/prover/errors.test.ts +0 -61
- package/src/prover/retry.test.ts +0 -38
- package/src/prover/workflow.test.ts +0 -145
- package/src/raw-client.test.ts +0 -171
- package/src/rpc/config.test.ts +0 -45
- package/src/rpc/errors.test.ts +0 -69
- package/src/rpc/retry.test.ts +0 -144
- package/src/signers/ecdsa.test.ts +0 -111
- package/src/signers/falcon.test.ts +0 -197
- package/src/signers/miden-wallet.ecdsa-recovery.test.ts +0 -201
- package/src/signers/miden-wallet.test.ts +0 -206
- package/src/signers/para.test.ts +0 -186
- package/src/transaction/index.ts +0 -13
- package/src/transaction/p2id.test.ts +0 -371
- package/src/transaction/rpoRandomCoin.test.ts +0 -64
- package/src/transaction/summary.test.ts +0 -32
- package/src/transaction.test.ts +0 -142
- package/src/types/proposal.test.ts +0 -68
- package/src/utils/digest.test.ts +0 -55
- package/src/utils/ecdsa.test.ts +0 -164
- package/src/utils/encoding.test.ts +0 -233
- package/src/utils/key.test.ts +0 -91
- package/src/utils/signature.test.ts +0 -210
- package/src/utils/word.test.ts +0 -64
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import type { DeltaStatus } from '@openzeppelin/guardian-client';
|
|
3
|
-
import { ProposalFactory } from './factory.js';
|
|
4
|
-
|
|
5
|
-
describe('ProposalFactory.toStatus', () => {
|
|
6
|
-
const factory = new ProposalFactory({
|
|
7
|
-
accountId: '0x' + 'a'.repeat(30),
|
|
8
|
-
signerCommitments: [],
|
|
9
|
-
resolveRequiredSignatures: () => 2,
|
|
10
|
-
});
|
|
11
|
-
// TS `private` is compile-time only; the mapping is worth pinning
|
|
12
|
-
// without dragging a full tx summary through `fromDelta`.
|
|
13
|
-
const toStatus = (status: DeltaStatus) =>
|
|
14
|
-
(factory as unknown as { toStatus: (s: DeltaStatus, t: string, sigs: unknown[]) => string })
|
|
15
|
-
.toStatus(status, 'p2id', []);
|
|
16
|
-
|
|
17
|
-
it('maps every terminal delta status to finalized (issue #345)', () => {
|
|
18
|
-
// A retained delta left the active candidate path: no longer
|
|
19
|
-
// signable, so finalized here — whether it landed is resolved by
|
|
20
|
-
// background reconciliation via the delta status, not the proposal
|
|
21
|
-
// list.
|
|
22
|
-
expect(toStatus({ status: 'canonical', timestamp: 't' })).toBe('finalized');
|
|
23
|
-
// Cast until the published guardian-client types include `retained`.
|
|
24
|
-
expect(
|
|
25
|
-
toStatus({
|
|
26
|
-
status: 'retained',
|
|
27
|
-
timestamp: 't',
|
|
28
|
-
reason: 'retry_exhausted',
|
|
29
|
-
} as unknown as DeltaStatus),
|
|
30
|
-
).toBe('finalized');
|
|
31
|
-
expect(toStatus({ status: 'discarded', timestamp: 't' })).toBe('finalized');
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('maps active statuses to pending/ready', () => {
|
|
35
|
-
expect(toStatus({ status: 'candidate', timestamp: 't' })).toBe('ready');
|
|
36
|
-
expect(
|
|
37
|
-
toStatus({ status: 'pending', timestamp: 't', proposerId: 'p', cosignerSigs: [] }),
|
|
38
|
-
).toBe('pending');
|
|
39
|
-
});
|
|
40
|
-
});
|
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import type { ProposalMetadata as GuardianProposalMetadata } from '@openzeppelin/guardian-client';
|
|
3
|
-
import { ProposalMetadataCodec } from './metadata.js';
|
|
4
|
-
import type {
|
|
5
|
-
ConsumeNotesProposalMetadata,
|
|
6
|
-
CustomProposalMetadata,
|
|
7
|
-
P2IdProposalMetadata,
|
|
8
|
-
} from '../types/proposal.js';
|
|
9
|
-
|
|
10
|
-
describe('ProposalMetadataCodec consume_notes v2 round-trip (issue #229)', () => {
|
|
11
|
-
it('toGuardian threads metadataVersion and notes to the wire', () => {
|
|
12
|
-
const md: ConsumeNotesProposalMetadata = {
|
|
13
|
-
proposalType: 'consume_notes',
|
|
14
|
-
description: 'consume one note',
|
|
15
|
-
noteIds: ['0xabc'],
|
|
16
|
-
metadataVersion: 2,
|
|
17
|
-
notes: ['YmFzZTY0Tm90ZQ=='],
|
|
18
|
-
};
|
|
19
|
-
const wire = ProposalMetadataCodec.toGuardian(md);
|
|
20
|
-
expect(wire.noteIds).toEqual(['0xabc']);
|
|
21
|
-
expect(wire.consumeNotesMetadataVersion).toBe(2);
|
|
22
|
-
expect(wire.consumeNotesNotes).toEqual(['YmFzZTY0Tm90ZQ==']);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('fromGuardian reconstructs the v2 fields', () => {
|
|
26
|
-
const wire: GuardianProposalMetadata = {
|
|
27
|
-
proposalType: 'consume_notes',
|
|
28
|
-
noteIds: ['0xabc'],
|
|
29
|
-
consumeNotesMetadataVersion: 2,
|
|
30
|
-
consumeNotesNotes: ['YmFzZTY0Tm90ZQ=='],
|
|
31
|
-
};
|
|
32
|
-
const md = ProposalMetadataCodec.fromGuardian(wire) as ConsumeNotesProposalMetadata;
|
|
33
|
-
expect(md.proposalType).toBe('consume_notes');
|
|
34
|
-
expect(md.metadataVersion).toBe(2);
|
|
35
|
-
expect(md.notes).toEqual(['YmFzZTY0Tm90ZQ==']);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('round-trips a v1 (legacy) proposal without spurious v2 fields', () => {
|
|
39
|
-
const md: ConsumeNotesProposalMetadata = {
|
|
40
|
-
proposalType: 'consume_notes',
|
|
41
|
-
description: 'legacy',
|
|
42
|
-
noteIds: ['0xabc'],
|
|
43
|
-
};
|
|
44
|
-
const wire = ProposalMetadataCodec.toGuardian(md);
|
|
45
|
-
expect(wire.consumeNotesMetadataVersion).toBeUndefined();
|
|
46
|
-
expect(wire.consumeNotesNotes).toBeUndefined();
|
|
47
|
-
const back = ProposalMetadataCodec.fromGuardian(wire) as ConsumeNotesProposalMetadata;
|
|
48
|
-
expect(back.metadataVersion).toBeUndefined();
|
|
49
|
-
expect(back.notes).toBeUndefined();
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
describe('ProposalMetadataCodec custom proposal types (issue #266)', () => {
|
|
54
|
-
it('fromGuardian collapses an unmodeled type to the custom bucket, keeping the raw label', () => {
|
|
55
|
-
const wire: GuardianProposalMetadata = {
|
|
56
|
-
proposalType: 'b2agg',
|
|
57
|
-
description: 'agglayer bridge note',
|
|
58
|
-
};
|
|
59
|
-
const md = ProposalMetadataCodec.fromGuardian(wire) as CustomProposalMetadata;
|
|
60
|
-
expect(md.proposalType).toBe('custom');
|
|
61
|
-
expect(md.rawProposalType).toBe('b2agg');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('toGuardian round-trips the raw label, not the custom bucket', () => {
|
|
65
|
-
const md: CustomProposalMetadata = {
|
|
66
|
-
proposalType: 'custom',
|
|
67
|
-
description: 'agglayer bridge note',
|
|
68
|
-
rawProposalType: 'b2agg',
|
|
69
|
-
};
|
|
70
|
-
const wire = ProposalMetadataCodec.toGuardian(md);
|
|
71
|
-
expect(wire.proposalType).toBe('b2agg');
|
|
72
|
-
|
|
73
|
-
const back = ProposalMetadataCodec.fromGuardian(wire) as CustomProposalMetadata;
|
|
74
|
-
expect(back.proposalType).toBe('custom');
|
|
75
|
-
expect(back.rawProposalType).toBe('b2agg');
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('validate accepts a custom proposal', () => {
|
|
79
|
-
const md: CustomProposalMetadata = {
|
|
80
|
-
proposalType: 'custom',
|
|
81
|
-
description: 'opaque',
|
|
82
|
-
rawProposalType: 'b2agg',
|
|
83
|
-
};
|
|
84
|
-
expect(ProposalMetadataCodec.validate(md)).toBe(md);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('round-trips update_procedure_threshold through the codec', () => {
|
|
88
|
-
const wire: GuardianProposalMetadata = {
|
|
89
|
-
proposalType: 'update_procedure_threshold',
|
|
90
|
-
targetProcedure: 'send_asset',
|
|
91
|
-
targetThreshold: 2,
|
|
92
|
-
};
|
|
93
|
-
const md = ProposalMetadataCodec.fromGuardian(wire);
|
|
94
|
-
expect(md.proposalType).toBe('update_procedure_threshold');
|
|
95
|
-
const back = ProposalMetadataCodec.toGuardian(md);
|
|
96
|
-
expect(back.proposalType).toBe('update_procedure_threshold');
|
|
97
|
-
expect(back.targetProcedure).toBe('send_asset');
|
|
98
|
-
expect(back.targetThreshold).toBe(2);
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
describe('ProposalMetadataCodec p2id noteType (issue #322)', () => {
|
|
103
|
-
const baseWire: GuardianProposalMetadata = {
|
|
104
|
-
proposalType: 'p2id',
|
|
105
|
-
recipientId: '0xrecipient',
|
|
106
|
-
faucetId: '0xfaucet',
|
|
107
|
-
amount: '1000',
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
it('round-trips a private noteType through the codec', () => {
|
|
111
|
-
const md = ProposalMetadataCodec.fromGuardian({
|
|
112
|
-
...baseWire,
|
|
113
|
-
noteType: 'private',
|
|
114
|
-
}) as P2IdProposalMetadata;
|
|
115
|
-
expect(md.noteType).toBe('private');
|
|
116
|
-
|
|
117
|
-
const wire = ProposalMetadataCodec.toGuardian(md);
|
|
118
|
-
expect(wire.noteType).toBe('private');
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it('leaves noteType absent for legacy proposals (=> public)', () => {
|
|
122
|
-
const md = ProposalMetadataCodec.fromGuardian(baseWire) as P2IdProposalMetadata;
|
|
123
|
-
expect(md.noteType).toBeUndefined();
|
|
124
|
-
expect(ProposalMetadataCodec.toGuardian(md).noteType).toBeUndefined();
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('canonicalizes an explicit public noteType to absent on encode', () => {
|
|
128
|
-
const md = {
|
|
129
|
-
proposalType: 'p2id',
|
|
130
|
-
description: '',
|
|
131
|
-
recipientId: '0xrecipient',
|
|
132
|
-
faucetId: '0xfaucet',
|
|
133
|
-
amount: '1000',
|
|
134
|
-
noteType: 'public',
|
|
135
|
-
} as P2IdProposalMetadata;
|
|
136
|
-
|
|
137
|
-
// toGuardian omits the field so a public note keeps the pre-#322 wire
|
|
138
|
-
// shape and matches the Rust encoder, even if handed an explicit 'public'.
|
|
139
|
-
expect(ProposalMetadataCodec.toGuardian(md).noteType).toBeUndefined();
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it('fromGuardian rejects an unsupported noteType', () => {
|
|
143
|
-
expect(() =>
|
|
144
|
-
ProposalMetadataCodec.fromGuardian({ ...baseWire, noteType: 'encrypted' }),
|
|
145
|
-
).toThrow(/unsupported noteType/);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it('validate rejects an unsupported noteType', () => {
|
|
149
|
-
const md = {
|
|
150
|
-
proposalType: 'p2id',
|
|
151
|
-
description: '',
|
|
152
|
-
recipientId: '0xrecipient',
|
|
153
|
-
faucetId: '0xfaucet',
|
|
154
|
-
amount: '1000',
|
|
155
|
-
noteType: 'encrypted',
|
|
156
|
-
} as unknown as P2IdProposalMetadata;
|
|
157
|
-
expect(() => ProposalMetadataCodec.validate(md)).toThrow(/unsupported noteType/);
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
describe('ProposalMetadataCodec p2id P2IDE heights (issue #366)', () => {
|
|
162
|
-
const baseWire: GuardianProposalMetadata = {
|
|
163
|
-
proposalType: 'p2id',
|
|
164
|
-
recipientId: '0xrecipient',
|
|
165
|
-
faucetId: '0xfaucet',
|
|
166
|
-
amount: '1000',
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
it('round-trips reclaim and timelock heights through the codec', () => {
|
|
170
|
-
const md = ProposalMetadataCodec.fromGuardian({
|
|
171
|
-
...baseWire,
|
|
172
|
-
reclaimHeight: 12345,
|
|
173
|
-
timelockHeight: 700,
|
|
174
|
-
}) as P2IdProposalMetadata;
|
|
175
|
-
expect(md.reclaimHeight).toBe(12345);
|
|
176
|
-
expect(md.timelockHeight).toBe(700);
|
|
177
|
-
|
|
178
|
-
const wire = ProposalMetadataCodec.toGuardian(md);
|
|
179
|
-
expect(wire.reclaimHeight).toBe(12345);
|
|
180
|
-
expect(wire.timelockHeight).toBe(700);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it('leaves heights absent for plain P2ID proposals (pre-#366 wire shape)', () => {
|
|
184
|
-
const md = ProposalMetadataCodec.fromGuardian(baseWire) as P2IdProposalMetadata;
|
|
185
|
-
expect(md.reclaimHeight).toBeUndefined();
|
|
186
|
-
expect(md.timelockHeight).toBeUndefined();
|
|
187
|
-
|
|
188
|
-
const wire = ProposalMetadataCodec.toGuardian(md);
|
|
189
|
-
expect(wire.reclaimHeight).toBeUndefined();
|
|
190
|
-
expect(wire.timelockHeight).toBeUndefined();
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it('fromGuardian rejects a zero height (encodes "no constraint" on-chain)', () => {
|
|
194
|
-
expect(() =>
|
|
195
|
-
ProposalMetadataCodec.fromGuardian({ ...baseWire, reclaimHeight: 0 }),
|
|
196
|
-
).toThrow(/unsupported reclaimHeight/);
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
it('fromGuardian rejects a non-integer or out-of-range height', () => {
|
|
200
|
-
expect(() =>
|
|
201
|
-
ProposalMetadataCodec.fromGuardian({ ...baseWire, timelockHeight: 1.5 }),
|
|
202
|
-
).toThrow(/unsupported timelockHeight/);
|
|
203
|
-
expect(() =>
|
|
204
|
-
ProposalMetadataCodec.fromGuardian({ ...baseWire, reclaimHeight: 0x1_0000_0000 }),
|
|
205
|
-
).toThrow(/unsupported reclaimHeight/);
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it('validate rejects an invalid height', () => {
|
|
209
|
-
const md = {
|
|
210
|
-
proposalType: 'p2id',
|
|
211
|
-
description: '',
|
|
212
|
-
recipientId: '0xrecipient',
|
|
213
|
-
faucetId: '0xfaucet',
|
|
214
|
-
amount: '1000',
|
|
215
|
-
reclaimHeight: -1,
|
|
216
|
-
} as unknown as P2IdProposalMetadata;
|
|
217
|
-
expect(() => ProposalMetadataCodec.validate(md)).toThrow(/unsupported reclaimHeight/);
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
it('toGuardian rejects an invalid height instead of emitting it on the wire', () => {
|
|
221
|
-
const base = {
|
|
222
|
-
proposalType: 'p2id',
|
|
223
|
-
description: '',
|
|
224
|
-
recipientId: '0xrecipient',
|
|
225
|
-
faucetId: '0xfaucet',
|
|
226
|
-
amount: '1000',
|
|
227
|
-
};
|
|
228
|
-
expect(() =>
|
|
229
|
-
ProposalMetadataCodec.toGuardian({ ...base, reclaimHeight: 0 } as P2IdProposalMetadata),
|
|
230
|
-
).toThrow(/unsupported reclaimHeight/);
|
|
231
|
-
expect(() =>
|
|
232
|
-
ProposalMetadataCodec.toGuardian({ ...base, timelockHeight: 1.5 } as P2IdProposalMetadata),
|
|
233
|
-
).toThrow(/unsupported timelockHeight/);
|
|
234
|
-
});
|
|
235
|
-
});
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
import type { TransactionProver } from '@miden-sdk/miden-sdk';
|
|
3
|
-
import { describe, expect, it } from 'vitest';
|
|
4
|
-
import { resolveProverConfig } from './config.js';
|
|
5
|
-
|
|
6
|
-
interface Fixtures {
|
|
7
|
-
attemptBudgets: Array<{ input: number | null; normalized: number }>;
|
|
8
|
-
endpoints: Array<{
|
|
9
|
-
input: string;
|
|
10
|
-
valid: boolean;
|
|
11
|
-
canonical?: string;
|
|
12
|
-
}>;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function fixtures(): Fixtures {
|
|
16
|
-
return JSON.parse(
|
|
17
|
-
readFileSync(
|
|
18
|
-
new URL(
|
|
19
|
-
'../../../../fixtures/miden-multisig-client/prover-policy-fixtures.json',
|
|
20
|
-
import.meta.url,
|
|
21
|
-
),
|
|
22
|
-
'utf8',
|
|
23
|
-
),
|
|
24
|
-
) as Fixtures;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
describe('resolveProverConfig', () => {
|
|
28
|
-
it('matches shared URL vectors', () => {
|
|
29
|
-
for (const fixture of fixtures().endpoints) {
|
|
30
|
-
const resolve = () => resolveProverConfig({ url: fixture.input }, null);
|
|
31
|
-
if (fixture.valid) {
|
|
32
|
-
expect(resolve().url, fixture.input).toBe(fixture.canonical);
|
|
33
|
-
} else {
|
|
34
|
-
expect(resolve, fixture.input).toThrow();
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('matches shared attempt-budget vectors for remote proving', () => {
|
|
40
|
-
for (const fixture of fixtures().attemptBudgets) {
|
|
41
|
-
const retry = fixture.input === null ? undefined : { maxAttempts: fixture.input };
|
|
42
|
-
const resolved = resolveProverConfig(
|
|
43
|
-
{ url: 'https://prover.example', retry },
|
|
44
|
-
null,
|
|
45
|
-
);
|
|
46
|
-
expect(resolved.maxAttempts).toBe(fixture.normalized);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it.each([-1, 1.5, Number.NaN, Number.POSITIVE_INFINITY, 4_294_967_296])(
|
|
51
|
-
'rejects invalid maxAttempts value %s',
|
|
52
|
-
(maxAttempts) => {
|
|
53
|
-
expect(() =>
|
|
54
|
-
resolveProverConfig(
|
|
55
|
-
{ url: 'https://prover.example', retry: { maxAttempts } },
|
|
56
|
-
null,
|
|
57
|
-
),
|
|
58
|
-
).toThrow('prover.retry.maxAttempts');
|
|
59
|
-
},
|
|
60
|
-
);
|
|
61
|
-
|
|
62
|
-
it('keeps an endpoint-less injected prover at one attempt without serializing it', () => {
|
|
63
|
-
const serialize = () => {
|
|
64
|
-
throw new Error('callback provers cannot be serialized');
|
|
65
|
-
};
|
|
66
|
-
const callback = {
|
|
67
|
-
endpoint: () => undefined,
|
|
68
|
-
serialize,
|
|
69
|
-
} as unknown as TransactionProver;
|
|
70
|
-
|
|
71
|
-
expect(resolveProverConfig({ retry: { maxAttempts: 5 } }, callback)).toMatchObject({
|
|
72
|
-
kind: 'injected',
|
|
73
|
-
maxAttempts: 1,
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('lets a custom remote URL override an injected local prover', () => {
|
|
78
|
-
const local = {
|
|
79
|
-
serialize: () => 'local',
|
|
80
|
-
endpoint: () => undefined,
|
|
81
|
-
} as unknown as TransactionProver;
|
|
82
|
-
expect(
|
|
83
|
-
resolveProverConfig({ url: 'https://prover.example' }, local),
|
|
84
|
-
).toMatchObject({
|
|
85
|
-
kind: 'remote',
|
|
86
|
-
url: 'https://prover.example/',
|
|
87
|
-
maxAttempts: 2,
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
});
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import { isTransientProverError } from './errors.js';
|
|
4
|
-
|
|
5
|
-
interface FixtureError {
|
|
6
|
-
code?: string;
|
|
7
|
-
status?: number;
|
|
8
|
-
message: string;
|
|
9
|
-
cause?: FixtureError;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
interface Fixtures {
|
|
13
|
-
classifications: Array<{
|
|
14
|
-
name: string;
|
|
15
|
-
chain: FixtureError[];
|
|
16
|
-
transient: boolean;
|
|
17
|
-
}>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function fixtures(): Fixtures {
|
|
21
|
-
return JSON.parse(
|
|
22
|
-
readFileSync(
|
|
23
|
-
new URL(
|
|
24
|
-
'../../../../fixtures/miden-multisig-client/prover-policy-fixtures.json',
|
|
25
|
-
import.meta.url,
|
|
26
|
-
),
|
|
27
|
-
'utf8',
|
|
28
|
-
),
|
|
29
|
-
) as Fixtures;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
describe('isTransientProverError', () => {
|
|
33
|
-
it('matches every shared classification vector', () => {
|
|
34
|
-
for (const fixture of fixtures().classifications) {
|
|
35
|
-
const error = fixture.chain.reduceRight<FixtureError | undefined>(
|
|
36
|
-
(cause, item) => ({ ...item, cause }),
|
|
37
|
-
undefined,
|
|
38
|
-
);
|
|
39
|
-
expect(isTransientProverError(error), fixture.name).toBe(fixture.transient);
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('stops safely on cyclic cause graphs', () => {
|
|
44
|
-
const error: FixtureError = { code: 'Unknown', message: 'not retryable' };
|
|
45
|
-
error.cause = error;
|
|
46
|
-
expect(isTransientProverError(error)).toBe(false);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('recognizes numeric gRPC status codes', () => {
|
|
50
|
-
expect(isTransientProverError({ code: 14, message: 'unavailable' })).toBe(true);
|
|
51
|
-
expect(isTransientProverError({ code: 3, message: 'timeout text' })).toBe(false);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('reads grpc code wording out of plain message text', () => {
|
|
55
|
-
expect(isTransientProverError(new Error('grpc code: NotFound'))).toBe(false);
|
|
56
|
-
expect(
|
|
57
|
-
isTransientProverError(new Error('grpc code: Internal; nested timeout')),
|
|
58
|
-
).toBe(false);
|
|
59
|
-
expect(isTransientProverError(new Error('grpc code: Unavailable'))).toBe(true);
|
|
60
|
-
});
|
|
61
|
-
});
|
package/src/prover/retry.test.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import { retryDelay } from '../retry/runtime.js';
|
|
4
|
-
|
|
5
|
-
interface Fixtures {
|
|
6
|
-
delays: Array<{ retryIndex: number; unitRandom: number; delayMs: number }>;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function fixtures(): Fixtures {
|
|
10
|
-
return JSON.parse(
|
|
11
|
-
readFileSync(
|
|
12
|
-
new URL(
|
|
13
|
-
'../../../../fixtures/miden-multisig-client/prover-policy-fixtures.json',
|
|
14
|
-
import.meta.url,
|
|
15
|
-
),
|
|
16
|
-
'utf8',
|
|
17
|
-
),
|
|
18
|
-
) as Fixtures;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
describe('retryDelay', () => {
|
|
22
|
-
it('matches every shared delay vector', () => {
|
|
23
|
-
for (const fixture of fixtures().delays) {
|
|
24
|
-
expect(retryDelay(fixture.retryIndex, fixture.unitRandom)).toBe(fixture.delayMs);
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('remains capped after numeric overflow', () => {
|
|
29
|
-
expect(retryDelay(Number.MAX_SAFE_INTEGER, 0.5)).toBe(8_000);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it.each([Number.NaN, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY])(
|
|
33
|
-
'uses neutral jitter for non-finite randomness',
|
|
34
|
-
(unitRandom) => {
|
|
35
|
-
expect(retryDelay(0, unitRandom)).toBe(500);
|
|
36
|
-
},
|
|
37
|
-
);
|
|
38
|
-
});
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
AccountId,
|
|
3
|
-
ChainAnchor,
|
|
4
|
-
MidenClient,
|
|
5
|
-
TransactionProver,
|
|
6
|
-
TransactionRequest,
|
|
7
|
-
} from '@miden-sdk/miden-sdk';
|
|
8
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
9
|
-
import type { ResolvedProverConfig } from './config.js';
|
|
10
|
-
import type { RetryRuntime } from '../retry/runtime.js';
|
|
11
|
-
import { ProverWorkflow } from './workflow.js';
|
|
12
|
-
|
|
13
|
-
function asType<T>(value: unknown): T {
|
|
14
|
-
return value as T;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const anchor = asType<ChainAnchor>({ marker: 'anchor' });
|
|
18
|
-
|
|
19
|
-
describe('ProverWorkflow', () => {
|
|
20
|
-
it('executes once, retries proof with fresh provers, submits once, and applies once', async () => {
|
|
21
|
-
const transient = Object.assign(new Error('temporarily unavailable'), {
|
|
22
|
-
code: 'Unavailable',
|
|
23
|
-
});
|
|
24
|
-
const apply = vi.fn().mockResolvedValue({});
|
|
25
|
-
const submit = vi.fn().mockResolvedValue({ apply });
|
|
26
|
-
const prove = vi.fn().mockRejectedValueOnce(transient).mockResolvedValueOnce({ submit });
|
|
27
|
-
const execution = { marker: 'unchanged', prove };
|
|
28
|
-
const executeRequest = vi.fn().mockResolvedValue(execution);
|
|
29
|
-
const client = {
|
|
30
|
-
transactions: { executeRequest },
|
|
31
|
-
};
|
|
32
|
-
const provers: TransactionProver[] = [];
|
|
33
|
-
const config: ResolvedProverConfig = {
|
|
34
|
-
kind: 'remote',
|
|
35
|
-
url: 'https://prover.example/',
|
|
36
|
-
maxAttempts: 2,
|
|
37
|
-
createProver: () => {
|
|
38
|
-
const prover = asType<TransactionProver>({});
|
|
39
|
-
provers.push(prover);
|
|
40
|
-
return prover;
|
|
41
|
-
},
|
|
42
|
-
};
|
|
43
|
-
const runtime: RetryRuntime = {
|
|
44
|
-
sleep: vi.fn().mockResolvedValue(undefined),
|
|
45
|
-
unitRandom: () => 0.5,
|
|
46
|
-
};
|
|
47
|
-
const workflow = new ProverWorkflow(
|
|
48
|
-
asType<MidenClient>(client),
|
|
49
|
-
config,
|
|
50
|
-
runtime,
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
await workflow.submitAt(
|
|
54
|
-
asType<AccountId>({}),
|
|
55
|
-
asType<TransactionRequest>({}),
|
|
56
|
-
anchor,
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
expect(executeRequest).toHaveBeenCalledTimes(1);
|
|
60
|
-
expect(executeRequest.mock.calls[0][2]).toEqual({ anchor });
|
|
61
|
-
expect(prove).toHaveBeenCalledTimes(2);
|
|
62
|
-
expect(provers).toHaveLength(2);
|
|
63
|
-
expect(provers[0]).not.toBe(provers[1]);
|
|
64
|
-
expect(submit).toHaveBeenCalledTimes(1);
|
|
65
|
-
expect(apply).toHaveBeenCalledTimes(1);
|
|
66
|
-
expect(runtime.sleep).toHaveBeenCalledTimes(1);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('returns the final original error without sleeping after exhaustion', async () => {
|
|
70
|
-
const first = Object.assign(new Error('unavailable'), { code: 'Unavailable' });
|
|
71
|
-
const final = Object.assign(new Error('deadline exceeded'), {
|
|
72
|
-
code: 'DeadlineExceeded',
|
|
73
|
-
});
|
|
74
|
-
const prove = vi.fn().mockRejectedValueOnce(first).mockRejectedValueOnce(final);
|
|
75
|
-
const client = { transactions: { executeRequest: vi.fn().mockResolvedValue({ prove }) } };
|
|
76
|
-
const runtime: RetryRuntime = {
|
|
77
|
-
sleep: vi.fn().mockResolvedValue(undefined),
|
|
78
|
-
unitRandom: () => 0.5,
|
|
79
|
-
};
|
|
80
|
-
const workflow = new ProverWorkflow(
|
|
81
|
-
asType<MidenClient>(client),
|
|
82
|
-
{
|
|
83
|
-
kind: 'remote',
|
|
84
|
-
maxAttempts: 2,
|
|
85
|
-
createProver: () => asType<TransactionProver>({}),
|
|
86
|
-
},
|
|
87
|
-
runtime,
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
await expect(
|
|
91
|
-
workflow.submitAt(asType<AccountId>({}), asType<TransactionRequest>({}), anchor),
|
|
92
|
-
).rejects.toBe(final);
|
|
93
|
-
expect(prove).toHaveBeenCalledTimes(2);
|
|
94
|
-
expect(runtime.sleep).toHaveBeenCalledTimes(1);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('never re-submits when submission fails with transient-looking wording', async () => {
|
|
98
|
-
const rateLimited = Object.assign(new Error('Too Many Requests!'), {
|
|
99
|
-
code: 'ResourceExhausted',
|
|
100
|
-
});
|
|
101
|
-
const submit = vi.fn().mockRejectedValue(rateLimited);
|
|
102
|
-
const prove = vi.fn().mockResolvedValue({ submit });
|
|
103
|
-
const client = {
|
|
104
|
-
transactions: { executeRequest: vi.fn().mockResolvedValue({ prove }) },
|
|
105
|
-
};
|
|
106
|
-
const runtime: RetryRuntime = {
|
|
107
|
-
sleep: vi.fn().mockResolvedValue(undefined),
|
|
108
|
-
unitRandom: () => 0.5,
|
|
109
|
-
};
|
|
110
|
-
const workflow = new ProverWorkflow(
|
|
111
|
-
asType<MidenClient>(client),
|
|
112
|
-
{
|
|
113
|
-
kind: 'remote',
|
|
114
|
-
maxAttempts: 5,
|
|
115
|
-
createProver: () => asType<TransactionProver>({}),
|
|
116
|
-
},
|
|
117
|
-
runtime,
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
await expect(
|
|
121
|
-
workflow.submitAt(asType<AccountId>({}), asType<TransactionRequest>({}), anchor),
|
|
122
|
-
).rejects.toBe(rateLimited);
|
|
123
|
-
expect(prove).toHaveBeenCalledTimes(1);
|
|
124
|
-
expect(submit).toHaveBeenCalledTimes(1);
|
|
125
|
-
expect(runtime.sleep).not.toHaveBeenCalled();
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it('uses the injected prover directly when no cloneable remote override exists', async () => {
|
|
129
|
-
const apply = vi.fn().mockResolvedValue({});
|
|
130
|
-
const submit = vi.fn().mockResolvedValue({ apply });
|
|
131
|
-
const prove = vi.fn().mockResolvedValue({ submit });
|
|
132
|
-
const client = {
|
|
133
|
-
transactions: { executeRequest: vi.fn().mockResolvedValue({ prove }) },
|
|
134
|
-
};
|
|
135
|
-
const workflow = new ProverWorkflow(asType<MidenClient>(client), {
|
|
136
|
-
kind: 'injected',
|
|
137
|
-
maxAttempts: 1,
|
|
138
|
-
createProver: () => undefined,
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
await workflow.submitAt(asType<AccountId>({}), asType<TransactionRequest>({}), anchor);
|
|
142
|
-
|
|
143
|
-
expect(prove).toHaveBeenCalledWith();
|
|
144
|
-
});
|
|
145
|
-
});
|