@aztec/end-to-end 0.0.1-commit.8f9871590 → 0.0.1-commit.934299a21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dest/e2e_epochs/epochs_test.d.ts +9 -7
  2. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -1
  3. package/dest/e2e_epochs/epochs_test.js +53 -34
  4. package/dest/e2e_fees/fees_test.js +1 -1
  5. package/dest/e2e_p2p/p2p_network.d.ts +1 -1
  6. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -1
  7. package/dest/e2e_p2p/p2p_network.js +16 -2
  8. package/dest/e2e_p2p/reqresp/utils.d.ts +3 -3
  9. package/dest/e2e_p2p/reqresp/utils.d.ts.map +1 -1
  10. package/dest/e2e_p2p/reqresp/utils.js +32 -8
  11. package/dest/fixtures/e2e_prover_test.d.ts +3 -3
  12. package/dest/fixtures/e2e_prover_test.d.ts.map +1 -1
  13. package/dest/fixtures/e2e_prover_test.js +27 -34
  14. package/dest/fixtures/elu_monitor.d.ts +21 -0
  15. package/dest/fixtures/elu_monitor.d.ts.map +1 -0
  16. package/dest/fixtures/elu_monitor.js +102 -0
  17. package/dest/fixtures/fixtures.d.ts +5 -1
  18. package/dest/fixtures/fixtures.d.ts.map +1 -1
  19. package/dest/fixtures/fixtures.js +6 -0
  20. package/dest/fixtures/setup.d.ts +25 -8
  21. package/dest/fixtures/setup.d.ts.map +1 -1
  22. package/dest/fixtures/setup.js +46 -77
  23. package/dest/fixtures/setup_p2p_test.d.ts +6 -3
  24. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -1
  25. package/dest/fixtures/setup_p2p_test.js +12 -9
  26. package/dest/fixtures/token_utils.d.ts +2 -2
  27. package/dest/fixtures/token_utils.d.ts.map +1 -1
  28. package/dest/fixtures/token_utils.js +3 -2
  29. package/dest/shared/jest_setup.js +10 -1
  30. package/dest/shared/submit-transactions.d.ts +1 -1
  31. package/dest/shared/submit-transactions.d.ts.map +1 -1
  32. package/dest/spartan/setup_test_wallets.d.ts +8 -1
  33. package/dest/spartan/setup_test_wallets.d.ts.map +1 -1
  34. package/dest/spartan/setup_test_wallets.js +28 -0
  35. package/dest/spartan/utils/bot.d.ts +3 -2
  36. package/dest/spartan/utils/bot.d.ts.map +1 -1
  37. package/dest/spartan/utils/bot.js +2 -1
  38. package/dest/spartan/utils/index.d.ts +2 -2
  39. package/dest/spartan/utils/index.d.ts.map +1 -1
  40. package/dest/spartan/utils/index.js +1 -1
  41. package/dest/spartan/utils/k8s.d.ts +3 -1
  42. package/dest/spartan/utils/k8s.d.ts.map +1 -1
  43. package/dest/spartan/utils/k8s.js +6 -0
  44. package/dest/spartan/utils/nodes.d.ts +4 -5
  45. package/dest/spartan/utils/nodes.d.ts.map +1 -1
  46. package/dest/spartan/utils/nodes.js +8 -8
  47. package/dest/test-wallet/test_wallet.js +1 -1
  48. package/dest/test-wallet/wallet_worker_script.d.ts +2 -0
  49. package/dest/test-wallet/wallet_worker_script.d.ts.map +1 -0
  50. package/dest/test-wallet/wallet_worker_script.js +48 -0
  51. package/dest/test-wallet/worker_wallet.d.ts +52 -0
  52. package/dest/test-wallet/worker_wallet.d.ts.map +1 -0
  53. package/dest/test-wallet/worker_wallet.js +151 -0
  54. package/dest/test-wallet/worker_wallet_schema.d.ts +274 -0
  55. package/dest/test-wallet/worker_wallet_schema.d.ts.map +1 -0
  56. package/dest/test-wallet/worker_wallet_schema.js +10 -0
  57. package/package.json +40 -40
  58. package/src/e2e_epochs/epochs_test.ts +66 -66
  59. package/src/e2e_fees/fees_test.ts +1 -1
  60. package/src/e2e_p2p/p2p_network.ts +24 -2
  61. package/src/e2e_p2p/reqresp/utils.ts +36 -8
  62. package/src/fixtures/dumps/epoch_proof_result.json +1 -1
  63. package/src/fixtures/e2e_prover_test.ts +25 -35
  64. package/src/fixtures/elu_monitor.ts +126 -0
  65. package/src/fixtures/fixtures.ts +10 -0
  66. package/src/fixtures/setup.ts +62 -105
  67. package/src/fixtures/setup_p2p_test.ts +9 -17
  68. package/src/fixtures/token_utils.ts +2 -1
  69. package/src/shared/jest_setup.ts +16 -1
  70. package/src/shared/submit-transactions.ts +4 -1
  71. package/src/spartan/setup_test_wallets.ts +55 -3
  72. package/src/spartan/utils/bot.ts +3 -0
  73. package/src/spartan/utils/index.ts +1 -0
  74. package/src/spartan/utils/k8s.ts +8 -0
  75. package/src/spartan/utils/nodes.ts +14 -9
  76. package/src/test-wallet/test_wallet.ts +1 -1
  77. package/src/test-wallet/wallet_worker_script.ts +60 -0
  78. package/src/test-wallet/worker_wallet.ts +213 -0
  79. package/src/test-wallet/worker_wallet_schema.ts +13 -0
@@ -20,6 +20,7 @@ import { getBBConfig } from '../fixtures/get_bb_config.js';
20
20
  import { getSponsoredFPCAddress, registerSponsoredFPC } from '../fixtures/utils.js';
21
21
  import { TestWallet } from '../test-wallet/test_wallet.js';
22
22
  import { proveInteraction } from '../test-wallet/utils.js';
23
+ import { WorkerWallet } from '../test-wallet/worker_wallet.js';
23
24
 
24
25
  export interface TestAccounts {
25
26
  aztecNode: AztecNode;
@@ -87,11 +88,19 @@ export async function deploySponsoredTestAccountsWithTokens(
87
88
 
88
89
  const paymentMethod = new SponsoredFeePaymentMethod(await getSponsoredFPCAddress());
89
90
  const recipientDeployMethod = await recipientAccount.getDeployMethod();
90
- await recipientDeployMethod.send({ from: AztecAddress.ZERO, fee: { paymentMethod }, wait: { timeout: 2400 } });
91
+ await recipientDeployMethod.send({
92
+ from: AztecAddress.ZERO,
93
+ fee: { paymentMethod },
94
+ wait: { timeout: 2400 },
95
+ });
91
96
  await Promise.all(
92
97
  fundedAccounts.map(async a => {
93
98
  const deployMethod = await a.getDeployMethod();
94
- await deployMethod.send({ from: AztecAddress.ZERO, fee: { paymentMethod }, wait: { timeout: 2400 } }); // increase timeout on purpose in order to account for two empty epochs
99
+ await deployMethod.send({
100
+ from: AztecAddress.ZERO,
101
+ fee: { paymentMethod },
102
+ wait: { timeout: 2400 },
103
+ }); // increase timeout on purpose in order to account for two empty epochs
95
104
  logger.info(`Account deployed at ${a.address}`);
96
105
  }),
97
106
  );
@@ -129,7 +138,11 @@ async function deployAccountWithDiagnostics(
129
138
  const deployMethod = await account.getDeployMethod();
130
139
  let txHash;
131
140
  try {
132
- txHash = await deployMethod.send({ from: AztecAddress.ZERO, fee: { paymentMethod }, wait: NO_WAIT });
141
+ txHash = await deployMethod.send({
142
+ from: AztecAddress.ZERO,
143
+ fee: { paymentMethod },
144
+ wait: NO_WAIT,
145
+ });
133
146
  await waitForTx(aztecNode, txHash, { timeout: 2400 });
134
147
  logger.info(`${accountLabel} deployed at ${account.address}`);
135
148
  } catch (error) {
@@ -397,3 +410,42 @@ export async function createWalletAndAztecNodeClient(
397
410
  },
398
411
  };
399
412
  }
413
+
414
+ export type WorkerWalletWrapper = {
415
+ wallet: WorkerWallet;
416
+ aztecNode: AztecNode;
417
+ cleanup: () => Promise<void>;
418
+ };
419
+
420
+ export async function createWorkerWalletClient(
421
+ nodeUrl: string,
422
+ proverEnabled: boolean,
423
+ logger: Logger,
424
+ ): Promise<WorkerWalletWrapper> {
425
+ const aztecNode = createAztecNodeClient(nodeUrl);
426
+ const [bbConfig, acvmConfig] = await Promise.all([getBBConfig(logger), getACVMConfig(logger)]);
427
+
428
+ // Strip cleanup functions — they can't be structured-cloned for worker transfer
429
+ const { cleanup: bbCleanup, ...bbPaths } = bbConfig ?? {};
430
+ const { cleanup: acvmCleanup, ...acvmPaths } = acvmConfig ?? {};
431
+
432
+ const pxeConfig = {
433
+ dataDirectory: undefined,
434
+ dataStoreMapSizeKb: 1024 * 1024,
435
+ ...bbPaths,
436
+ ...acvmPaths,
437
+ proverEnabled,
438
+ };
439
+
440
+ const wallet = await WorkerWallet.create(nodeUrl, pxeConfig);
441
+
442
+ return {
443
+ wallet,
444
+ aztecNode,
445
+ async cleanup() {
446
+ await wallet.stop();
447
+ await bbCleanup?.();
448
+ await acvmCleanup?.();
449
+ },
450
+ };
451
+ }
@@ -35,6 +35,7 @@ export async function installTransferBot({
35
35
  replicas = 1,
36
36
  txIntervalSeconds = 10,
37
37
  followChain = 'CHECKPOINTED',
38
+ pxeSyncChainTip = 'proposed',
38
39
  mnemonic = process.env.LABS_INFRA_MNEMONIC ?? 'test test test test test test test test test test test junk',
39
40
  mnemonicStartIndex,
40
41
  botPrivateKey = process.env.BOT_TRANSFERS_L2_PRIVATE_KEY ?? '0xcafe01',
@@ -49,6 +50,7 @@ export async function installTransferBot({
49
50
  replicas?: number;
50
51
  txIntervalSeconds?: number;
51
52
  followChain?: string;
53
+ pxeSyncChainTip?: string;
52
54
  mnemonic?: string;
53
55
  mnemonicStartIndex?: number | string;
54
56
  botPrivateKey?: string;
@@ -67,6 +69,7 @@ export async function installTransferBot({
67
69
  'bot.replicaCount': replicas,
68
70
  'bot.txIntervalSeconds': txIntervalSeconds,
69
71
  'bot.followChain': followChain,
72
+ 'bot.pxeSyncChainTip': pxeSyncChainTip,
70
73
  'bot.botPrivateKey': botPrivateKey,
71
74
  'bot.nodeUrl': resolvedNodeUrl,
72
75
  'bot.mnemonic': mnemonic,
@@ -25,6 +25,7 @@ export {
25
25
  getRPCEndpoint,
26
26
  getEthereumEndpoint,
27
27
  createResilientPrometheusConnection,
28
+ scaleProverAgents,
28
29
  } from './k8s.js';
29
30
 
30
31
  // Chaos Mesh
@@ -522,6 +522,14 @@ export function createResilientPrometheusConnection(
522
522
  return { connect, runAlertCheck };
523
523
  }
524
524
 
525
+ /** Scales the prover-agent Deployment to the given number of replicas. */
526
+ export async function scaleProverAgents(namespace: string, replicas: number, log: Logger): Promise<void> {
527
+ const label = 'app.kubernetes.io/component=prover-agent';
528
+ const command = `kubectl scale deployment -l ${label} -n ${namespace} --replicas=${replicas} --timeout=2m`;
529
+ log.info(`Scaling prover agents to ${replicas}: ${command}`);
530
+ await execAsync(command);
531
+ }
532
+
525
533
  export function getChartDir(spartanDir: string, chartName: string) {
526
534
  return path.join(spartanDir.trim(), chartName);
527
535
  }
@@ -255,21 +255,18 @@ export async function initHADb(namespace: string): Promise<void> {
255
255
  }
256
256
 
257
257
  /**
258
- * Enables or disables probabilistic transaction dropping on validators and waits for rollout.
259
- * Wired to env vars P2P_DROP_TX and P2P_DROP_TX_CHANCE via Helm values.
258
+ * Sets probabilistic transaction dropping on validators and waits for rollout.
259
+ * Use probability=0 to disable. Wired to env var P2P_DROP_TX_CHANCE via Helm values.
260
260
  */
261
261
  export async function setValidatorTxDrop({
262
262
  namespace,
263
- enabled,
264
263
  probability,
265
264
  logger: log,
266
265
  }: {
267
266
  namespace: string;
268
- enabled: boolean;
269
267
  probability: number;
270
268
  logger: Logger;
271
269
  }) {
272
- const drop = enabled ? 'true' : 'false';
273
270
  const prob = String(probability);
274
271
 
275
272
  const selectors = ['app.kubernetes.io/name=validator', 'app.kubernetes.io/component=validator', 'app=validator'];
@@ -284,7 +281,7 @@ export async function setValidatorTxDrop({
284
281
  if (names.length === 0) {
285
282
  continue;
286
283
  }
287
- const cmd = `kubectl set env statefulset -l ${selector} -n ${namespace} P2P_DROP_TX=${drop} P2P_DROP_TX_CHANCE=${prob}`;
284
+ const cmd = `kubectl set env statefulset -l ${selector} -n ${namespace} P2P_DROP_TX_CHANCE=${prob}`;
288
285
  log.info(`command: ${cmd}`);
289
286
  await execAsync(cmd);
290
287
  updated = true;
@@ -366,16 +363,24 @@ export async function enableValidatorDynamicBootNode(
366
363
  */
367
364
  export async function rollAztecPods(namespace: string, clearState: boolean = false) {
368
365
  // Pod components use 'validator', but StatefulSets and PVCs use 'sequencer-node' for validators
366
+ // RPC nodes have nodeType='rpc-node' in Helm values, so their component label is 'rpc-node' (not 'rpc')
369
367
  const podComponents = [
370
368
  'p2p-bootstrap',
371
369
  'prover-node',
372
370
  'prover-broker',
373
371
  'prover-agent',
374
372
  'sequencer-node',
375
- 'rpc',
373
+ 'rpc-node',
374
+ 'validator-ha-db',
375
+ ];
376
+ const pvcComponents = [
377
+ 'p2p-bootstrap',
378
+ 'prover-node',
379
+ 'prover-broker',
380
+ 'sequencer-node',
381
+ 'rpc-node',
376
382
  'validator-ha-db',
377
383
  ];
378
- const pvcComponents = ['p2p-bootstrap', 'prover-node', 'prover-broker', 'sequencer-node', 'rpc', 'validator-ha-db'];
379
384
  // StatefulSet components that need to be scaled down before PVC deletion
380
385
  // Note: validators use 'sequencer-node' as component label, not 'validator'
381
386
  const statefulSetComponents = [
@@ -383,7 +388,7 @@ export async function rollAztecPods(namespace: string, clearState: boolean = fal
383
388
  'prover-node',
384
389
  'prover-broker',
385
390
  'sequencer-node',
386
- 'rpc',
391
+ 'rpc-node',
387
392
  'validator-ha-db',
388
393
  ];
389
394
 
@@ -275,7 +275,7 @@ export class TestWallet extends BaseWallet {
275
275
  async proveTx(exec: ExecutionPayload, opts: Omit<SendOptions, 'wait'>): Promise<ProvenTx> {
276
276
  const fee = await this.completeFeeOptions(opts.from, exec.feePayer, opts.fee?.gasSettings);
277
277
  const txRequest = await this.createTxExecutionRequestFromPayloadAndFee(exec, opts.from, fee);
278
- const txProvingResult = await this.pxe.proveTx(txRequest, this.scopesFor(opts.from));
278
+ const txProvingResult = await this.pxe.proveTx(txRequest, this.scopesFrom(opts.from, opts.additionalScopes));
279
279
  return new ProvenTx(
280
280
  this.aztecNode,
281
281
  await txProvingResult.toTx(),
@@ -0,0 +1,60 @@
1
+ import { createAztecNodeClient } from '@aztec/aztec.js/node';
2
+ import type { SendOptions } from '@aztec/aztec.js/wallet';
3
+ import { jsonStringify } from '@aztec/foundation/json-rpc';
4
+ import { createLogger } from '@aztec/foundation/log';
5
+ import type { ApiSchema, Fr } from '@aztec/foundation/schemas';
6
+ import { parseWithOptionals, schemaHasMethod } from '@aztec/foundation/schemas';
7
+ import { NodeListener, TransportServer } from '@aztec/foundation/transport';
8
+ import { ExecutionPayload, Tx } from '@aztec/stdlib/tx';
9
+
10
+ import { workerData } from 'worker_threads';
11
+
12
+ import { TestWallet } from './test_wallet.js';
13
+ import { WorkerWalletSchema } from './worker_wallet_schema.js';
14
+
15
+ const logger = createLogger('e2e:test-wallet:worker');
16
+
17
+ try {
18
+ const { nodeUrl, pxeConfig } = workerData as { nodeUrl: string; pxeConfig?: Record<string, unknown> };
19
+
20
+ logger.info('Initializing worker wallet', { nodeUrl });
21
+ const node = createAztecNodeClient(nodeUrl);
22
+ const wallet = await TestWallet.create(node, pxeConfig);
23
+ logger.info('Worker wallet initialized');
24
+
25
+ const customMethods = {
26
+ proveTx: async (exec: ExecutionPayload, opts: Omit<SendOptions, 'wait'>) => {
27
+ const provenTx = await wallet.proveTx(exec, opts);
28
+ return new Tx(
29
+ provenTx.getTxHash(),
30
+ provenTx.data,
31
+ provenTx.chonkProof,
32
+ provenTx.contractClassLogFields,
33
+ provenTx.publicFunctionCalldata,
34
+ );
35
+ },
36
+ registerAccount: async (secret: Fr, salt: Fr) => {
37
+ const manager = await wallet.createSchnorrAccount(secret, salt);
38
+ return manager.address;
39
+ },
40
+ };
41
+
42
+ const schema = WorkerWalletSchema as ApiSchema;
43
+ const listener = new NodeListener();
44
+ const server = new TransportServer<{ fn: string; args: string }>(listener, async msg => {
45
+ if (!schemaHasMethod(schema, msg.fn)) {
46
+ throw new Error(`Unknown method: ${msg.fn}`);
47
+ }
48
+ const jsonParams = JSON.parse(msg.args) as unknown[];
49
+ const args: any[] = await parseWithOptionals(jsonParams, schema[msg.fn].parameters());
50
+ // we have to erase the fn type in order to be able to spread ...args
51
+ const handler: ((...args: any[]) => Promise<any>) | undefined =
52
+ msg.fn in customMethods ? customMethods[msg.fn as keyof typeof customMethods] : undefined;
53
+ const result = handler ? await handler(...args) : await (wallet as any)[msg.fn](...args);
54
+ return jsonStringify(result);
55
+ });
56
+ server.start();
57
+ } catch (err: unknown) {
58
+ logger.error('Worker wallet initialization failed', { error: err instanceof Error ? err.stack : String(err) });
59
+ process.exit(1);
60
+ }
@@ -0,0 +1,213 @@
1
+ import type { CallIntent, IntentInnerHash } from '@aztec/aztec.js/authorization';
2
+ import type { InteractionWaitOptions, SendReturn } from '@aztec/aztec.js/contracts';
3
+ import type {
4
+ Aliased,
5
+ AppCapabilities,
6
+ BatchResults,
7
+ BatchedMethod,
8
+ ContractClassMetadata,
9
+ ContractMetadata,
10
+ ExecuteUtilityOptions,
11
+ PrivateEvent,
12
+ PrivateEventFilter,
13
+ ProfileOptions,
14
+ SendOptions,
15
+ SimulateOptions,
16
+ Wallet,
17
+ WalletCapabilities,
18
+ } from '@aztec/aztec.js/wallet';
19
+ import type { ChainInfo } from '@aztec/entrypoints/interfaces';
20
+ import type { Fr } from '@aztec/foundation/curves/bn254';
21
+ import { jsonStringify } from '@aztec/foundation/json-rpc';
22
+ import { createLogger } from '@aztec/foundation/log';
23
+ import { promiseWithResolvers } from '@aztec/foundation/promise';
24
+ import type { ApiSchema } from '@aztec/foundation/schemas';
25
+ import { sleep } from '@aztec/foundation/sleep';
26
+ import { NodeConnector, TransportClient } from '@aztec/foundation/transport';
27
+ import type { PXEConfig } from '@aztec/pxe/config';
28
+ import type { ContractArtifact, EventMetadataDefinition, FunctionCall } from '@aztec/stdlib/abi';
29
+ import type { AuthWitness } from '@aztec/stdlib/auth-witness';
30
+ import type { AztecAddress } from '@aztec/stdlib/aztec-address';
31
+ import type { ContractInstanceWithAddress } from '@aztec/stdlib/contract';
32
+ import type { ExecutionPayload, TxProfileResult, TxSimulationResult, UtilityExecutionResult } from '@aztec/stdlib/tx';
33
+ import { Tx } from '@aztec/stdlib/tx';
34
+
35
+ import { Worker } from 'worker_threads';
36
+
37
+ import { WorkerWalletSchema } from './worker_wallet_schema.js';
38
+
39
+ type WorkerMsg = { fn: string; args: string };
40
+
41
+ const log = createLogger('e2e:test-wallet:worker-wallet');
42
+
43
+ const WORKER_READY_TIMEOUT_MS = 120_000;
44
+
45
+ /**
46
+ * Wallet implementation that offloads all work to a worker thread.
47
+ * Implements the Wallet interface by proxying calls over a transport layer
48
+ * using JSON serialization with Zod schema parsing on both ends.
49
+ */
50
+ export class WorkerWallet implements Wallet {
51
+ private constructor(
52
+ private worker: Worker,
53
+ private client: TransportClient<WorkerMsg>,
54
+ ) {}
55
+
56
+ /**
57
+ * Creates a WorkerWallet by spawning a worker thread that creates a TestWallet internally.
58
+ * @param nodeUrl - URL of the Aztec node to connect to.
59
+ * @param pxeConfig - Optional PXE configuration overrides.
60
+ * @returns A WorkerWallet ready to use.
61
+ */
62
+ static async create(nodeUrl: string, pxeConfig?: Partial<PXEConfig>): Promise<WorkerWallet> {
63
+ // replace stc/ with dest/ so the wallet works in Jest tests
64
+ const workerUrl = new URL('./wallet_worker_script.js', import.meta.url);
65
+ workerUrl.pathname = workerUrl.pathname.replace('/src/', '/dest/');
66
+ // remove JEST_WORKER_ID so the worker uses pino-pretty transport instead of Jest's raw output.
67
+ const { JEST_WORKER_ID: _, ...parentEnv } = process.env;
68
+ const worker = new Worker(workerUrl, {
69
+ workerData: { nodeUrl, pxeConfig },
70
+ env: {
71
+ ...parentEnv,
72
+ ...(process.stderr.isTTY || process.env.FORCE_COLOR ? { FORCE_COLOR: '1' } : {}),
73
+ LOG_LEVEL: process.env.WORKER_LOG_LEVEL ?? 'warn',
74
+ },
75
+ });
76
+
77
+ const connector = new NodeConnector(worker);
78
+ const client = new TransportClient<WorkerMsg>(connector);
79
+ await client.open();
80
+
81
+ const wallet = new WorkerWallet(worker, client);
82
+
83
+ const { promise: workerDied, reject: rejectWorkerDied } = promiseWithResolvers<void>();
84
+ // reject if the worker exits or errors before the warmup completes.
85
+ const onError = (err: Error): void => {
86
+ worker.off('exit', onExit!);
87
+ rejectWorkerDied(new Error(`Worker wallet thread error: ${err.message}`));
88
+ };
89
+
90
+ const onExit = (code: number): void => {
91
+ worker.off('error', onError!);
92
+ rejectWorkerDied(new Error(`Worker wallet thread exited with code ${code} before becoming ready`));
93
+ };
94
+
95
+ worker.once('error', onError);
96
+ worker.once('exit', onExit);
97
+
98
+ const timeout = sleep(WORKER_READY_TIMEOUT_MS).then(() => {
99
+ throw new Error(`Worker wallet creation timed out after ${WORKER_READY_TIMEOUT_MS / 1000}s`);
100
+ });
101
+
102
+ try {
103
+ // wait for worker wallet to start
104
+ await Promise.race([wallet.getChainInfo(), workerDied, timeout]);
105
+ } catch (err) {
106
+ log.error('Worker wallet creation failed, cleaning up', { error: String(err) });
107
+ client.close();
108
+ await worker.terminate();
109
+ throw err;
110
+ } finally {
111
+ worker.off('error', onError);
112
+ worker.off('exit', onExit);
113
+ }
114
+
115
+ return wallet;
116
+ }
117
+
118
+ private async callRaw(fn: string, ...args: any[]): Promise<string> {
119
+ const argsJson = jsonStringify(args);
120
+ return (await this.client.request({ fn, args: argsJson })) as string;
121
+ }
122
+
123
+ private async call(fn: string, ...args: any[]): Promise<any> {
124
+ const resultJson = await this.callRaw(fn, ...args);
125
+ const methodSchema = (WorkerWalletSchema as ApiSchema)[fn];
126
+ return methodSchema.returnType().parseAsync(JSON.parse(resultJson));
127
+ }
128
+
129
+ getChainInfo(): Promise<ChainInfo> {
130
+ return this.call('getChainInfo');
131
+ }
132
+
133
+ getContractMetadata(address: AztecAddress): Promise<ContractMetadata> {
134
+ return this.call('getContractMetadata', address);
135
+ }
136
+
137
+ getContractClassMetadata(id: Fr): Promise<ContractClassMetadata> {
138
+ return this.call('getContractClassMetadata', id);
139
+ }
140
+
141
+ getPrivateEvents<T>(
142
+ eventMetadata: EventMetadataDefinition,
143
+ eventFilter: PrivateEventFilter,
144
+ ): Promise<PrivateEvent<T>[]> {
145
+ return this.call('getPrivateEvents', eventMetadata, eventFilter);
146
+ }
147
+
148
+ registerSender(address: AztecAddress, alias?: string): Promise<AztecAddress> {
149
+ return this.call('registerSender', address, alias);
150
+ }
151
+
152
+ getAddressBook(): Promise<Aliased<AztecAddress>[]> {
153
+ return this.call('getAddressBook');
154
+ }
155
+
156
+ getAccounts(): Promise<Aliased<AztecAddress>[]> {
157
+ return this.call('getAccounts');
158
+ }
159
+
160
+ registerContract(
161
+ instance: ContractInstanceWithAddress,
162
+ artifact?: ContractArtifact,
163
+ secretKey?: Fr,
164
+ ): Promise<ContractInstanceWithAddress> {
165
+ return this.call('registerContract', instance, artifact, secretKey);
166
+ }
167
+
168
+ simulateTx(exec: ExecutionPayload, opts: SimulateOptions): Promise<TxSimulationResult> {
169
+ return this.call('simulateTx', exec, opts);
170
+ }
171
+
172
+ executeUtility(call: FunctionCall, opts: ExecuteUtilityOptions): Promise<UtilityExecutionResult> {
173
+ return this.call('executeUtility', call, opts);
174
+ }
175
+
176
+ profileTx(exec: ExecutionPayload, opts: ProfileOptions): Promise<TxProfileResult> {
177
+ return this.call('profileTx', exec, opts);
178
+ }
179
+
180
+ sendTx<W extends InteractionWaitOptions = undefined>(
181
+ exec: ExecutionPayload,
182
+ opts: SendOptions<W>,
183
+ ): Promise<SendReturn<W>> {
184
+ return this.call('sendTx', exec, opts);
185
+ }
186
+
187
+ proveTx(exec: ExecutionPayload, opts: Omit<SendOptions, 'wait'>): Promise<Tx> {
188
+ return this.call('proveTx', exec, opts);
189
+ }
190
+
191
+ /** Registers an account inside the worker's TestWallet, populating its accounts map. */
192
+ registerAccount(secret: Fr, salt: Fr): Promise<AztecAddress> {
193
+ return this.call('registerAccount', secret, salt);
194
+ }
195
+
196
+ createAuthWit(from: AztecAddress, messageHashOrIntent: IntentInnerHash | CallIntent): Promise<AuthWitness> {
197
+ return this.call('createAuthWit', from, messageHashOrIntent);
198
+ }
199
+
200
+ requestCapabilities(manifest: AppCapabilities): Promise<WalletCapabilities> {
201
+ return this.call('requestCapabilities', manifest);
202
+ }
203
+
204
+ batch<const T extends readonly BatchedMethod[]>(methods: T): Promise<BatchResults<T>> {
205
+ return this.call('batch', methods);
206
+ }
207
+
208
+ /** Shuts down the worker thread and closes the transport. */
209
+ async stop(): Promise<void> {
210
+ this.client.close();
211
+ await this.worker.terminate();
212
+ }
213
+ }
@@ -0,0 +1,13 @@
1
+ import { ExecutionPayloadSchema, SendOptionsSchema, WalletSchema } from '@aztec/aztec.js/wallet';
2
+ import { schemas } from '@aztec/foundation/schemas';
3
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
4
+ import { Tx } from '@aztec/stdlib/tx';
5
+
6
+ import { z } from 'zod';
7
+
8
+ /** Schema for the WorkerWallet API — extends WalletSchema with proveTx and registerAccount. */
9
+ export const WorkerWalletSchema = {
10
+ ...WalletSchema,
11
+ proveTx: z.function().args(ExecutionPayloadSchema, SendOptionsSchema).returns(Tx.schema),
12
+ registerAccount: z.function().args(schemas.Fr, schemas.Fr).returns(AztecAddress.schema),
13
+ };