@aztec/end-to-end 0.75.0-commit.c03ba01a2a4122e43e90d5133ba017e54b90e9d2 → 0.77.0-testnet-ignition.21

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 (138) hide show
  1. package/README.md +2 -0
  2. package/dest/bench/utils.d.ts +70 -0
  3. package/dest/bench/utils.d.ts.map +1 -0
  4. package/dest/bench/utils.js +24 -8
  5. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts +46 -0
  6. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.d.ts.map +1 -0
  7. package/dest/e2e_blacklist_token_contract/blacklist_token_contract_test.js +17 -17
  8. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts +47 -0
  9. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.d.ts.map +1 -0
  10. package/dest/e2e_cross_chain_messaging/cross_chain_messaging_test.js +27 -16
  11. package/dest/e2e_deploy_contract/deploy_test.d.ts +28 -0
  12. package/dest/e2e_deploy_contract/deploy_test.d.ts.map +1 -0
  13. package/dest/e2e_deploy_contract/deploy_test.js +4 -7
  14. package/dest/e2e_epochs/epochs_test.d.ts +51 -0
  15. package/dest/e2e_epochs/epochs_test.d.ts.map +1 -0
  16. package/dest/e2e_epochs/epochs_test.js +155 -0
  17. package/dest/e2e_fees/fees_test.d.ts +73 -0
  18. package/dest/e2e_fees/fees_test.d.ts.map +1 -0
  19. package/dest/e2e_fees/fees_test.js +75 -32
  20. package/dest/e2e_nested_contract/nested_contract_test.d.ts +26 -0
  21. package/dest/e2e_nested_contract/nested_contract_test.d.ts.map +1 -0
  22. package/dest/e2e_nested_contract/nested_contract_test.js +14 -12
  23. package/dest/e2e_p2p/p2p_network.d.ts +61 -0
  24. package/dest/e2e_p2p/p2p_network.d.ts.map +1 -0
  25. package/dest/e2e_p2p/p2p_network.js +54 -30
  26. package/dest/e2e_p2p/shared.d.ts +10 -0
  27. package/dest/e2e_p2p/shared.d.ts.map +1 -0
  28. package/dest/e2e_p2p/shared.js +7 -8
  29. package/dest/e2e_prover/e2e_prover_test.d.ts +56 -0
  30. package/dest/e2e_prover/e2e_prover_test.d.ts.map +1 -0
  31. package/dest/e2e_prover/e2e_prover_test.js +20 -24
  32. package/dest/e2e_token_contract/token_contract_test.d.ts +29 -0
  33. package/dest/e2e_token_contract/token_contract_test.d.ts.map +1 -0
  34. package/dest/e2e_token_contract/token_contract_test.js +4 -7
  35. package/dest/fixtures/fixtures.d.ts +17 -0
  36. package/dest/fixtures/fixtures.d.ts.map +1 -0
  37. package/dest/fixtures/fixtures.js +2 -2
  38. package/dest/fixtures/get_acvm_config.d.ts +8 -0
  39. package/dest/fixtures/get_acvm_config.d.ts.map +1 -0
  40. package/dest/fixtures/get_acvm_config.js +10 -5
  41. package/dest/fixtures/get_bb_config.d.ts +6 -0
  42. package/dest/fixtures/get_bb_config.d.ts.map +1 -0
  43. package/dest/fixtures/get_bb_config.js +9 -4
  44. package/dest/fixtures/index.d.ts +6 -0
  45. package/dest/fixtures/index.d.ts.map +1 -0
  46. package/dest/fixtures/l1_to_l2_messaging.d.ts +13 -0
  47. package/dest/fixtures/l1_to_l2_messaging.d.ts.map +1 -0
  48. package/dest/fixtures/l1_to_l2_messaging.js +1 -1
  49. package/dest/fixtures/logging.d.ts +8 -0
  50. package/dest/fixtures/logging.d.ts.map +1 -0
  51. package/dest/fixtures/setup_l1_contracts.d.ts +6 -0
  52. package/dest/fixtures/setup_l1_contracts.d.ts.map +1 -0
  53. package/dest/fixtures/setup_l1_contracts.js +6 -4
  54. package/dest/fixtures/setup_p2p_test.d.ts +22 -0
  55. package/dest/fixtures/setup_p2p_test.d.ts.map +1 -0
  56. package/dest/fixtures/setup_p2p_test.js +5 -3
  57. package/dest/fixtures/snapshot_manager.d.ts +87 -0
  58. package/dest/fixtures/snapshot_manager.d.ts.map +1 -0
  59. package/dest/fixtures/snapshot_manager.js +67 -74
  60. package/dest/fixtures/token_utils.d.ts +6 -0
  61. package/dest/fixtures/token_utils.d.ts.map +1 -0
  62. package/dest/fixtures/token_utils.js +1 -1
  63. package/dest/fixtures/utils.d.ts +155 -0
  64. package/dest/fixtures/utils.d.ts.map +1 -0
  65. package/dest/fixtures/utils.js +97 -71
  66. package/dest/fixtures/with_telemetry_utils.d.ts +3 -0
  67. package/dest/fixtures/with_telemetry_utils.d.ts.map +1 -0
  68. package/dest/index.d.ts +2 -0
  69. package/dest/index.d.ts.map +1 -0
  70. package/dest/quality_of_service/alert_checker.d.ts +41 -0
  71. package/dest/quality_of_service/alert_checker.d.ts.map +1 -0
  72. package/dest/quality_of_service/alert_checker.js +4 -1
  73. package/dest/sample-dapp/index.js +1 -1
  74. package/dest/shared/cross_chain_test_harness.d.ts +124 -0
  75. package/dest/shared/cross_chain_test_harness.d.ts.map +1 -0
  76. package/dest/shared/cross_chain_test_harness.js +6 -17
  77. package/dest/shared/gas_portal_test_harness.d.ts +80 -0
  78. package/dest/shared/gas_portal_test_harness.d.ts.map +1 -0
  79. package/dest/shared/gas_portal_test_harness.js +11 -4
  80. package/dest/shared/index.d.ts +2 -0
  81. package/dest/shared/index.d.ts.map +1 -0
  82. package/dest/shared/index.js +0 -1
  83. package/dest/shared/jest_setup.d.ts +2 -0
  84. package/dest/shared/jest_setup.d.ts.map +1 -0
  85. package/dest/shared/submit-transactions.d.ts +4 -0
  86. package/dest/shared/submit-transactions.d.ts.map +1 -0
  87. package/dest/shared/submit-transactions.js +9 -17
  88. package/dest/shared/uniswap_l1_l2.d.ts +25 -0
  89. package/dest/shared/uniswap_l1_l2.d.ts.map +1 -0
  90. package/dest/shared/uniswap_l1_l2.js +5 -10
  91. package/dest/simulators/index.d.ts +3 -0
  92. package/dest/simulators/index.d.ts.map +1 -0
  93. package/dest/simulators/lending_simulator.d.ts +69 -0
  94. package/dest/simulators/lending_simulator.d.ts.map +1 -0
  95. package/dest/simulators/lending_simulator.js +1 -3
  96. package/dest/simulators/token_simulator.d.ts +29 -0
  97. package/dest/simulators/token_simulator.d.ts.map +1 -0
  98. package/dest/spartan/setup_test_wallets.d.ts +20 -0
  99. package/dest/spartan/setup_test_wallets.d.ts.map +1 -0
  100. package/dest/spartan/setup_test_wallets.js +72 -38
  101. package/dest/spartan/utils.d.ts +415 -0
  102. package/dest/spartan/utils.d.ts.map +1 -0
  103. package/dest/spartan/utils.js +169 -43
  104. package/package.json +35 -40
  105. package/src/bench/utils.ts +30 -13
  106. package/src/e2e_blacklist_token_contract/blacklist_token_contract_test.ts +40 -30
  107. package/src/e2e_cross_chain_messaging/cross_chain_messaging_test.ts +34 -18
  108. package/src/e2e_deploy_contract/deploy_test.ts +6 -11
  109. package/src/e2e_epochs/epochs_test.ts +217 -0
  110. package/src/e2e_fees/fees_test.ts +84 -38
  111. package/src/e2e_nested_contract/nested_contract_test.ts +14 -16
  112. package/src/e2e_p2p/p2p_network.ts +67 -47
  113. package/src/e2e_p2p/shared.ts +16 -10
  114. package/src/e2e_prover/e2e_prover_test.ts +56 -37
  115. package/src/e2e_token_contract/token_contract_test.ts +10 -11
  116. package/src/fixtures/fixtures.ts +2 -2
  117. package/src/fixtures/get_acvm_config.ts +7 -3
  118. package/src/fixtures/get_bb_config.ts +6 -2
  119. package/src/fixtures/l1_to_l2_messaging.ts +6 -13
  120. package/src/fixtures/setup_l1_contracts.ts +8 -7
  121. package/src/fixtures/setup_p2p_test.ts +8 -6
  122. package/src/fixtures/snapshot_manager.ts +72 -79
  123. package/src/fixtures/token_utils.ts +2 -2
  124. package/src/fixtures/utils.ts +135 -97
  125. package/src/guides/up_quick_start.sh +10 -5
  126. package/src/quality_of_service/alert_checker.ts +6 -2
  127. package/src/sample-dapp/index.mjs +1 -1
  128. package/src/shared/cross_chain_test_harness.ts +17 -35
  129. package/src/shared/gas_portal_test_harness.ts +21 -11
  130. package/src/shared/index.ts +0 -1
  131. package/src/shared/submit-transactions.ts +16 -20
  132. package/src/shared/uniswap_l1_l2.ts +35 -26
  133. package/src/simulators/lending_simulator.ts +5 -6
  134. package/src/simulators/token_simulator.ts +1 -1
  135. package/src/spartan/setup_test_wallets.ts +111 -37
  136. package/src/spartan/utils.ts +161 -54
  137. package/dest/shared/browser.js +0 -163
  138. package/src/shared/browser.ts +0 -272
@@ -1,9 +1,9 @@
1
1
  import { createAztecNodeClient, createLogger, sleep } from '@aztec/aztec.js';
2
- import { type RollupCheatCodes } from '@aztec/aztec.js/ethereum';
2
+ import type { RollupCheatCodes } from '@aztec/aztec.js/ethereum';
3
3
  import type { Logger } from '@aztec/foundation/log';
4
4
  import type { SequencerConfig } from '@aztec/sequencer-client';
5
5
 
6
- import { exec, execSync, spawn } from 'child_process';
6
+ import { ChildProcess, exec, execSync, spawn } from 'child_process';
7
7
  import path from 'path';
8
8
  import { promisify } from 'util';
9
9
  import { z } from 'zod';
@@ -14,20 +14,38 @@ const execAsync = promisify(exec);
14
14
 
15
15
  const logger = createLogger('e2e:k8s-utils');
16
16
 
17
+ const ethereumHostsSchema = z.string().refine(
18
+ str =>
19
+ str.split(',').every(url => {
20
+ try {
21
+ new URL(url.trim());
22
+ return true;
23
+ } catch {
24
+ return false;
25
+ }
26
+ }),
27
+ 'ETHEREUM_HOSTS must be a comma-separated list of valid URLs',
28
+ );
29
+
17
30
  const k8sLocalConfigSchema = z.object({
31
+ ETHEREUM_SLOT_DURATION: z.coerce.number().min(1, 'ETHEREUM_SLOT_DURATION env variable must be set'),
32
+ AZTEC_SLOT_DURATION: z.coerce.number().min(1, 'AZTEC_SLOT_DURATION env variable must be set'),
33
+ AZTEC_EPOCH_DURATION: z.coerce.number().min(1, 'AZTEC_EPOCH_DURATION env variable must be set'),
34
+ AZTEC_PROOF_SUBMISSION_WINDOW: z.coerce.number().min(1, 'AZTEC_PROOF_SUBMISSION_WINDOW env variable must be set'),
18
35
  INSTANCE_NAME: z.string().min(1, 'INSTANCE_NAME env variable must be set'),
19
36
  NAMESPACE: z.string().min(1, 'NAMESPACE env variable must be set'),
20
- HOST_NODE_PORT: z.coerce.number().min(1, 'HOST_NODE_PORT env variable must be set'),
21
37
  CONTAINER_NODE_PORT: z.coerce.number().default(8080),
22
- HOST_PXE_PORT: z.coerce.number().min(1, 'HOST_PXE_PORT env variable must be set'),
38
+ CONTAINER_SEQUENCER_PORT: z.coerce.number().default(8080),
39
+ CONTAINER_PROVER_NODE_PORT: z.coerce.number().default(8080),
23
40
  CONTAINER_PXE_PORT: z.coerce.number().default(8080),
24
- HOST_ETHEREUM_PORT: z.coerce.number().min(1, 'HOST_ETHEREUM_PORT env variable must be set'),
25
41
  CONTAINER_ETHEREUM_PORT: z.coerce.number().default(8545),
26
- HOST_METRICS_PORT: z.coerce.number().min(1, 'HOST_METRICS_PORT env variable must be set'),
27
42
  CONTAINER_METRICS_PORT: z.coerce.number().default(80),
28
43
  GRAFANA_PASSWORD: z.string().optional(),
29
44
  METRICS_API_PATH: z.string().default('/api/datasources/proxy/uid/spartan-metrics-prometheus/api/v1'),
30
45
  SPARTAN_DIR: z.string().min(1, 'SPARTAN_DIR env variable must be set'),
46
+ ETHEREUM_HOSTS: ethereumHostsSchema.optional(),
47
+ L1_ACCOUNT_MNEMONIC: z.string().default('test test test test test test test test test test test junk'),
48
+ SEPOLIA_RUN: z.string().default('false'),
31
49
  K8S: z.literal('local'),
32
50
  });
33
51
 
@@ -40,7 +58,7 @@ const k8sGCloudConfigSchema = k8sLocalConfigSchema.extend({
40
58
  const directConfigSchema = z.object({
41
59
  PXE_URL: z.string().url('PXE_URL must be a valid URL'),
42
60
  NODE_URL: z.string().url('NODE_URL must be a valid URL'),
43
- ETHEREUM_HOST: z.string().url('ETHEREUM_HOST must be a valid URL'),
61
+ ETHEREUM_HOSTS: ethereumHostsSchema,
44
62
  K8S: z.literal('false'),
45
63
  });
46
64
 
@@ -77,49 +95,73 @@ export async function startPortForward({
77
95
  resource: string;
78
96
  namespace: string;
79
97
  containerPort: number;
80
- hostPort: number;
81
- }) {
82
- // check if kubectl is already forwarding this port
83
- try {
84
- const command = `ps aux | grep 'kubectl.*${hostPort}:${containerPort}' | grep -v grep | awk '{print $2}'`;
85
- const { stdout: processId } = await execAsync(command);
86
- if (processId) {
87
- logger.info(`Restarting port forward for ${resource}:${hostPort}`);
88
- // kill the existing port forward
89
- await execAsync(`kill -9 ${processId}`);
90
- }
91
- } catch (e) {
92
- logger.info(`No existing port forward found for ${resource}:${hostPort}`);
93
- }
94
-
95
- logger.info(`kubectl port-forward -n ${namespace} ${resource} ${hostPort}:${containerPort}`);
96
-
97
- const process = spawn('kubectl', ['port-forward', '-n', namespace, resource, `${hostPort}:${containerPort}`], {
98
- detached: true,
99
- windowsHide: true,
100
- stdio: ['ignore', 'pipe', 'pipe'],
101
- });
102
-
103
- process.stdout?.on('data', data => {
104
- const str = data.toString();
105
- if (str.includes('Starting port forward')) {
106
- logger.info(str);
107
- } else {
108
- logger.debug(str);
109
- }
110
- });
111
- process.stderr?.on('data', data => {
112
- // It's a strange thing:
113
- // If we don't pipe stderr, then the port forwarding does not work.
114
- // Log to silent because this doesn't actually report errors,
115
- // just extremely verbose debug logs.
116
- logger.silent(data.toString());
98
+ // If not provided, the port will be chosen automatically
99
+ hostPort?: number;
100
+ }): Promise<{
101
+ process: ChildProcess;
102
+ port: number;
103
+ }> {
104
+ const hostPortAsString = hostPort ? hostPort.toString() : '';
105
+
106
+ logger.info(`kubectl port-forward -n ${namespace} ${resource} ${hostPortAsString}:${containerPort}`);
107
+
108
+ const process = spawn(
109
+ 'kubectl',
110
+ ['port-forward', '-n', namespace, resource, `${hostPortAsString}:${containerPort}`],
111
+ {
112
+ detached: true,
113
+ windowsHide: true,
114
+ stdio: ['ignore', 'pipe', 'pipe'],
115
+ },
116
+ );
117
+
118
+ let isResolved = false;
119
+ const connected = new Promise<number>(resolve => {
120
+ process.stdout?.on('data', data => {
121
+ const str = data.toString() as string;
122
+ if (!isResolved && str.includes('Forwarding from')) {
123
+ isResolved = true;
124
+ logger.info(str);
125
+ const port = str.search(/:\d+/);
126
+ if (port === -1) {
127
+ throw new Error('Port not found in port forward output');
128
+ }
129
+ const portNumber = parseInt(str.slice(port + 1));
130
+ logger.info(`Port forward connected: ${portNumber}`);
131
+ logger.info(`Port forward connected: ${portNumber}`);
132
+ resolve(portNumber);
133
+ } else {
134
+ logger.silent(str);
135
+ }
136
+ });
137
+ process.stderr?.on('data', data => {
138
+ logger.info(data.toString());
139
+ // It's a strange thing:
140
+ // If we don't pipe stderr, then the port forwarding does not work.
141
+ // Log to silent because this doesn't actually report errors,
142
+ // just extremely verbose debug logs.
143
+ logger.silent(data.toString());
144
+ });
145
+ process.on('close', () => {
146
+ if (!isResolved) {
147
+ isResolved = true;
148
+ logger.warn('Port forward closed before connection established');
149
+ resolve(0);
150
+ }
151
+ });
152
+ process.on('error', error => {
153
+ logger.error(`Port forward error: ${error}`);
154
+ resolve(0);
155
+ });
156
+ process.on('exit', code => {
157
+ logger.info(`Port forward exited with code ${code}`);
158
+ resolve(0);
159
+ });
117
160
  });
118
161
 
119
- // Wait a moment for the port forward to establish
120
- await new Promise(resolve => setTimeout(resolve, 2000));
162
+ const port = await connected;
121
163
 
122
- return process;
164
+ return { process, port };
123
165
  }
124
166
 
125
167
  export async function deleteResourceByName({
@@ -305,6 +347,44 @@ export function applyProverFailure({
305
347
  });
306
348
  }
307
349
 
350
+ export function applyProverKill({
351
+ namespace,
352
+ spartanDir,
353
+ logger,
354
+ }: {
355
+ namespace: string;
356
+ spartanDir: string;
357
+ logger: Logger;
358
+ }) {
359
+ return installChaosMeshChart({
360
+ instanceName: 'prover-kill',
361
+ targetNamespace: namespace,
362
+ valuesFile: 'prover-kill.yaml',
363
+ helmChartDir: getChartDir(spartanDir, 'aztec-chaos-scenarios'),
364
+ clean: true,
365
+ logger,
366
+ });
367
+ }
368
+
369
+ export function applyProverBrokerKill({
370
+ namespace,
371
+ spartanDir,
372
+ logger,
373
+ }: {
374
+ namespace: string;
375
+ spartanDir: string;
376
+ logger: Logger;
377
+ }) {
378
+ return installChaosMeshChart({
379
+ instanceName: 'prover-broker-kill',
380
+ targetNamespace: namespace,
381
+ valuesFile: 'prover-broker-kill.yaml',
382
+ helmChartDir: getChartDir(spartanDir, 'aztec-chaos-scenarios'),
383
+ clean: true,
384
+ logger,
385
+ });
386
+ }
387
+
308
388
  export function applyBootNodeFailure({
309
389
  namespace,
310
390
  spartanDir,
@@ -419,11 +499,17 @@ export async function enableValidatorDynamicBootNode(
419
499
 
420
500
  export async function runAlertCheck(config: EnvConfig, alerts: AlertConfig[], logger: Logger) {
421
501
  if (isK8sConfig(config)) {
502
+ const { process, port } = await startPortForward({
503
+ resource: `svc/metrics-grafana`,
504
+ namespace: 'metrics',
505
+ containerPort: config.CONTAINER_METRICS_PORT,
506
+ });
422
507
  const alertChecker = new AlertChecker(logger, {
423
- grafanaEndpoint: `http://localhost:${config.HOST_METRICS_PORT}${config.METRICS_API_PATH}`,
508
+ grafanaEndpoint: `http://localhost:${port}${config.METRICS_API_PATH}`,
424
509
  grafanaCredentials: `admin:${config.GRAFANA_PASSWORD}`,
425
510
  });
426
511
  await alertChecker.runAlertCheck(alerts);
512
+ process.kill();
427
513
  } else {
428
514
  logger.info('Not running alert check in non-k8s environment');
429
515
  }
@@ -442,22 +528,21 @@ export async function getSequencers(namespace: string) {
442
528
 
443
529
  export async function updateK8sSequencersConfig(args: {
444
530
  containerPort: number;
445
- hostPort: number;
446
531
  namespace: string;
447
532
  config: Partial<SequencerConfig>;
448
533
  }) {
449
- const { containerPort, hostPort, namespace, config } = args;
534
+ const { containerPort, namespace, config } = args;
450
535
  const sequencers = await getSequencers(namespace);
451
536
  for (const sequencer of sequencers) {
452
- await startPortForward({
537
+ const { process, port } = await startPortForward({
453
538
  resource: `pod/${sequencer}`,
454
539
  namespace,
455
540
  containerPort,
456
- hostPort,
457
541
  });
458
542
 
459
- const url = `http://localhost:${hostPort}`;
543
+ const url = `http://localhost:${port}`;
460
544
  await updateSequencerConfig(url, config);
545
+ process.kill();
461
546
  }
462
547
  }
463
548
 
@@ -465,7 +550,6 @@ export async function updateSequencersConfig(env: EnvConfig, config: Partial<Seq
465
550
  if (isK8sConfig(env)) {
466
551
  await updateK8sSequencersConfig({
467
552
  containerPort: env.CONTAINER_NODE_PORT,
468
- hostPort: env.HOST_NODE_PORT,
469
553
  namespace: env.NAMESPACE,
470
554
  config,
471
555
  });
@@ -473,3 +557,26 @@ export async function updateSequencersConfig(env: EnvConfig, config: Partial<Seq
473
557
  await updateSequencerConfig(env.NODE_URL, config);
474
558
  }
475
559
  }
560
+
561
+ /**
562
+ * Rolls the Aztec pods in the given namespace.
563
+ * @param namespace - The namespace to roll the Aztec pods in.
564
+ * @dev - IMPORTANT: This function DOES NOT delete the underlying PVCs.
565
+ * This means that the pods will be restarted with the same persistent storage.
566
+ * This is useful for testing, but you should be aware of the implications.
567
+ */
568
+ export async function rollAztecPods(namespace: string) {
569
+ await deleteResourceByLabel({ resource: 'pods', namespace: namespace, label: 'app=boot-node' });
570
+ await deleteResourceByLabel({ resource: 'pods', namespace: namespace, label: 'app=prover-node' });
571
+ await deleteResourceByLabel({ resource: 'pods', namespace: namespace, label: 'app=prover-broker' });
572
+ await deleteResourceByLabel({ resource: 'pods', namespace: namespace, label: 'app=prover-agent' });
573
+ await deleteResourceByLabel({ resource: 'pods', namespace: namespace, label: 'app=validator' });
574
+ await deleteResourceByLabel({ resource: 'pods', namespace: namespace, label: 'app=pxe' });
575
+ await sleep(10 * 1000);
576
+ await waitForResourceByLabel({ resource: 'pods', namespace: namespace, label: 'app=boot-node' });
577
+ await waitForResourceByLabel({ resource: 'pods', namespace: namespace, label: 'app=prover-node' });
578
+ await waitForResourceByLabel({ resource: 'pods', namespace: namespace, label: 'app=prover-broker' });
579
+ await waitForResourceByLabel({ resource: 'pods', namespace: namespace, label: 'app=prover-agent' });
580
+ await waitForResourceByLabel({ resource: 'pods', namespace: namespace, label: 'app=validator' });
581
+ await waitForResourceByLabel({ resource: 'pods', namespace: namespace, label: 'app=pxe' });
582
+ }
@@ -1,163 +0,0 @@
1
- /* eslint-disable no-console */ import * as AztecJs from '@aztec/aztec.js';
2
- import { TokenContractArtifact } from '@aztec/noir-contracts.js/Token';
3
- import { contractArtifactToBuffer } from '@aztec/types/abi';
4
- import getPort from 'get-port';
5
- import { launch } from 'puppeteer-core';
6
- const privKey = AztecJs.GrumpkinScalar.random();
7
- export const browserTestSuite = (setup, pageLogger)=>describe('e2e_aztec.js_browser', ()=>{
8
- const initialBalance = 33n;
9
- const transferAmount = 3n;
10
- let contractAddress;
11
- let testClient;
12
- let server;
13
- let webServerURL;
14
- let pxeServer;
15
- let pxeURL;
16
- let browser;
17
- let page;
18
- beforeAll(async ()=>{
19
- ({ server, pxeURL, pxeServer, webServerURL } = await setup());
20
- testClient = AztecJs.createPXEClient(pxeURL);
21
- await AztecJs.waitForPXE(testClient);
22
- const debuggingPort = await getPort({
23
- port: 9222
24
- });
25
- browser = await launch({
26
- executablePath: process.env.CHROME_BIN,
27
- headless: true,
28
- debuggingPort,
29
- args: [
30
- '--no-sandbox',
31
- '--headless',
32
- '--disable-gpu',
33
- '--disable-dev-shm-usage',
34
- '--disable-software-rasterizer',
35
- `--remote-debugging-port=${debuggingPort}`
36
- ]
37
- });
38
- page = await browser.newPage();
39
- page.on('console', (msg)=>{
40
- pageLogger.info(msg.text());
41
- });
42
- page.on('pageerror', (err)=>{
43
- pageLogger.error(`Error on web page`, err);
44
- });
45
- await page.goto(`${webServerURL}/index.html`);
46
- while(!await page.evaluate(()=>!!window.AztecJs)){
47
- pageLogger.verbose('Waiting for window.AztecJs...');
48
- await AztecJs.sleep(1000);
49
- }
50
- });
51
- afterAll(async ()=>{
52
- await browser.close();
53
- server.close();
54
- pxeServer?.close();
55
- });
56
- it('Loads Aztec.js in the browser', async ()=>{
57
- const generatePublicKeyExists = await page.evaluate(()=>{
58
- const { generatePublicKey } = window.AztecJs;
59
- return typeof generatePublicKey === 'function';
60
- });
61
- expect(generatePublicKeyExists).toBe(true);
62
- });
63
- it('Creates an account', async ()=>{
64
- const result = await page.evaluate(async (rpcUrl, secretKeyString)=>{
65
- const { Fr, createPXEClient, getUnsafeSchnorrAccount } = window.AztecJs;
66
- const pxe = createPXEClient(rpcUrl);
67
- const secretKey = Fr.fromHexString(secretKeyString);
68
- const account = await getUnsafeSchnorrAccount(pxe, secretKey);
69
- await account.waitSetup();
70
- const completeAddress = await account.getCompleteAddress();
71
- const addressString = completeAddress.address.toString();
72
- console.log(`Created Account: ${addressString}`);
73
- return addressString;
74
- }, pxeURL, privKey.toString());
75
- const accounts = await testClient.getRegisteredAccounts();
76
- const stringAccounts = accounts.map((acc)=>acc.address.toString());
77
- expect(stringAccounts.includes(result)).toBeTruthy();
78
- });
79
- it('Deploys Token contract', async ()=>{
80
- await deployTokenContract();
81
- });
82
- it('Can access CompleteAddress class in browser', async ()=>{
83
- const result = await page.evaluate(async ()=>{
84
- const completeAddress = await window.AztecJs.CompleteAddress.fromString('0x2401bfdad7ac9282bd612e8a6bb0f6ce125b08e317e24dc04ddbba24694ac2e7261249d8b3ad8ad9ed075257eede1dcd8356bfd55e1518f07717c47609194b6500c926582f07fda6a53e3600251f2aa1401c0cd377cef064f3f59045222194541acc5f62d8907a6dc98b85e32f8097a152c3c795bb3981c64e576b014f23005e0891d109aa087560cf8720ae94098827aa009a0bcee09f98fd2a05a7cbc6185402a53516a379d7856d26e3bb5542f1fe57f1ee5a0e4c60f7a463205aa19e2f8e00bce110b9a89857b79e3f70777e38a262b04cf80c56bd833a3c4b58dde7dbdc25c807c4012229e08651fd0d48cf9d966d9ab18826692f48a4cf934bef78614023e9cb95711f532786c7c78e72c3752f03f2a4cafc1846ad9df47324e2b7683f0faaa2e6fe44f3ff68646ce7d8538cb6935ce25472c4c75a244ab0c5d2e3b74d');
85
- // NOTE: browser does not know how to serialize CompleteAddress for return, so return a string
86
- // otherwise returning a CompleteAddress makes result undefined.
87
- return completeAddress.toString();
88
- });
89
- expect(result).toBe('0x2401bfdad7ac9282bd612e8a6bb0f6ce125b08e317e24dc04ddbba24694ac2e7261249d8b3ad8ad9ed075257eede1dcd8356bfd55e1518f07717c47609194b6500c926582f07fda6a53e3600251f2aa1401c0cd377cef064f3f59045222194541acc5f62d8907a6dc98b85e32f8097a152c3c795bb3981c64e576b014f23005e0891d109aa087560cf8720ae94098827aa009a0bcee09f98fd2a05a7cbc6185402a53516a379d7856d26e3bb5542f1fe57f1ee5a0e4c60f7a463205aa19e2f8e00bce110b9a89857b79e3f70777e38a262b04cf80c56bd833a3c4b58dde7dbdc25c807c4012229e08651fd0d48cf9d966d9ab18826692f48a4cf934bef78614023e9cb95711f532786c7c78e72c3752f03f2a4cafc1846ad9df47324e2b7683f0faaa2e6fe44f3ff68646ce7d8538cb6935ce25472c4c75a244ab0c5d2e3b74d');
90
- });
91
- it("Gets the owner's balance", async ()=>{
92
- const result = await page.evaluate(async (rpcUrl, contractAddress, TokenContractArtifact)=>{
93
- const { Contract, AztecAddress, createPXEClient: createPXEClient, getDeployedTestAccountsWallets } = window.AztecJs;
94
- const pxe = createPXEClient(rpcUrl);
95
- const [wallet] = await getDeployedTestAccountsWallets(pxe);
96
- const owner = wallet.getCompleteAddress().address;
97
- const contract = await Contract.at(AztecAddress.fromString(contractAddress), TokenContractArtifact, wallet);
98
- const balance = await contract.methods.balance_of_private(owner).simulate({
99
- from: owner
100
- });
101
- return balance;
102
- }, pxeURL, (await getTokenAddress()).toString(), TokenContractArtifact);
103
- expect(result).toEqual(initialBalance);
104
- });
105
- it('Sends a transfer TX', async ()=>{
106
- const result = await page.evaluate(async (rpcUrl, contractAddress, transferAmount, TokenContractArtifact)=>{
107
- console.log(`Starting transfer tx`);
108
- const { AztecAddress, Contract, createPXEClient: createPXEClient, getDeployedTestAccountsWallets, getUnsafeSchnorrAccount } = window.AztecJs;
109
- const pxe = createPXEClient(rpcUrl);
110
- const newReceiverAccountManager = await getUnsafeSchnorrAccount(pxe, AztecJs.Fr.random());
111
- const newReceiverAccount = await newReceiverAccountManager.waitSetup();
112
- const receiverAddress = newReceiverAccount.getCompleteAddress().address;
113
- const [wallet] = await getDeployedTestAccountsWallets(pxe);
114
- const contract = await Contract.at(AztecAddress.fromString(contractAddress), TokenContractArtifact, wallet);
115
- await contract.methods.transfer(receiverAddress, transferAmount).send().wait();
116
- console.log(`Transferred ${transferAmount} tokens to new Account`);
117
- return await contract.methods.balance_of_private(receiverAddress).simulate({
118
- from: receiverAddress
119
- });
120
- }, pxeURL, (await getTokenAddress()).toString(), transferAmount, TokenContractArtifact);
121
- expect(result).toEqual(transferAmount);
122
- });
123
- const deployTokenContract = async ()=>{
124
- const [txHash, tokenAddress] = await page.evaluate(async (rpcUrl, initialBalance, serializedTokenContractArtifact)=>{
125
- const { DeployMethod, createPXEClient, getSchnorrAccount, Contract, getDeployedTestAccountsWallets, INITIAL_TEST_SECRET_KEYS, INITIAL_TEST_SIGNING_KEYS, INITIAL_TEST_ACCOUNT_SALTS, Buffer, contractArtifactFromBuffer } = window.AztecJs;
126
- // We serialize the artifact since buffers (used for bytecode) do not cross well from one realm to another
127
- const TokenContractArtifact = await contractArtifactFromBuffer(Buffer.from(serializedTokenContractArtifact, 'base64'));
128
- const pxe = createPXEClient(rpcUrl);
129
- // we need to ensure that a known account is present in order to create a wallet
130
- const knownAccounts = await getDeployedTestAccountsWallets(pxe);
131
- if (!knownAccounts.length) {
132
- const newAccountManager = await getSchnorrAccount(pxe, INITIAL_TEST_SECRET_KEYS[0], INITIAL_TEST_SIGNING_KEYS[0], INITIAL_TEST_ACCOUNT_SALTS[0]);
133
- const newAccount = await newAccountManager.waitSetup();
134
- knownAccounts.push(newAccount);
135
- }
136
- const owner = knownAccounts[0];
137
- const tx = new DeployMethod(owner.getCompleteAddress().publicKeys, owner, TokenContractArtifact, (a)=>Contract.at(a, TokenContractArtifact, owner), [
138
- owner.getCompleteAddress(),
139
- 'TokenName',
140
- 'TKN',
141
- 18
142
- ]).send();
143
- const { contract: token, txHash } = await tx.wait();
144
- console.log(`Contract Deployed: ${token.address}`);
145
- // We mint tokens to the owner
146
- const from = owner.getAddress(); // we are setting from to owner here because of TODO(#9887)
147
- await token.methods.mint_to_private(from, owner.getAddress(), initialBalance).send().wait();
148
- return [
149
- txHash.toString(),
150
- token.address.toString()
151
- ];
152
- }, pxeURL, initialBalance, contractArtifactToBuffer(TokenContractArtifact).toString('base64'));
153
- const txResult = await testClient.getTxReceipt(AztecJs.TxHash.fromString(txHash));
154
- expect(txResult.status).toEqual(AztecJs.TxStatus.SUCCESS);
155
- contractAddress = AztecJs.AztecAddress.fromString(tokenAddress);
156
- };
157
- const getTokenAddress = async ()=>{
158
- if (!contractAddress) {
159
- await deployTokenContract();
160
- }
161
- return contractAddress;
162
- };
163
- });