@argonprotocol/testing 1.4.3-dev.1523df53 → 1.4.3-dev.231f708a

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/lib/index.cjs CHANGED
@@ -30,9 +30,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ EthereumProofE2eHarness: () => EthereumProofE2eHarness,
33
34
  SKIP_E2E: () => SKIP_E2E,
34
35
  TestBitcoinCli: () => TestBitcoinCli,
36
+ TestEthereum: () => TestEthereum,
35
37
  TestMainchain: () => TestMainchain,
38
+ TestMintingAuthorityActor: () => TestMintingAuthorityActor,
39
+ TestMintingGateway: () => TestMintingGateway,
36
40
  TestNotary: () => TestNotary,
37
41
  TestOracle: () => TestOracle,
38
42
  activateNotary: () => activateNotary,
@@ -42,22 +46,30 @@ __export(index_exports, {
42
46
  disconnectOnTeardown: () => disconnectOnTeardown,
43
47
  getDockerPortMapping: () => getDockerPortMapping,
44
48
  getProxy: () => getProxy,
49
+ getReadyEthereumGatewayUpdates: () => getReadyEthereumGatewayUpdates,
50
+ mineLaterExecutionAnchorReceipt: () => mineLaterExecutionAnchorReceipt,
45
51
  projectRoot: () => projectRoot,
46
52
  runOnTeardown: () => runOnTeardown,
47
53
  runTestScript: () => runTestScript,
54
+ signGatewayPermit: () => signGatewayPermit,
48
55
  startNetwork: () => startNetwork,
49
56
  stringifyExt: () => stringifyExt,
50
57
  sudo: () => sudo,
51
- teardown: () => teardown
58
+ syncEthereumVerifierUntilAnchorCovers: () => syncEthereumVerifierUntilAnchorCovers,
59
+ teardown: () => teardown,
60
+ toArgonKeccakSignature: () => toArgonKeccakSignature,
61
+ toEvmRecoverableSignature: () => toEvmRecoverableSignature,
62
+ waitForExecutionReceipt: () => waitForExecutionReceipt2,
63
+ waitForFinalizedBeaconExecutionAtOrAbove: () => waitForFinalizedBeaconExecutionAtOrAbove
52
64
  });
53
65
  module.exports = __toCommonJS(index_exports);
54
- var import_mainchain4 = require("@argonprotocol/mainchain");
66
+ var import_mainchain8 = require("@argonprotocol/mainchain");
55
67
  var process4 = __toESM(require("process"), 1);
56
68
  var import_http_proxy = __toESM(require("http-proxy"), 1);
57
69
  var child_process4 = __toESM(require("child_process"), 1);
58
- var http = __toESM(require("http"), 1);
70
+ var http3 = __toESM(require("http"), 1);
59
71
  var url = __toESM(require("url"), 1);
60
- var Path6 = __toESM(require("path"), 1);
72
+ var Path7 = __toESM(require("path"), 1);
61
73
 
62
74
  // src/TestNotary.ts
63
75
  var import_nanoid = require("nanoid");
@@ -371,9 +383,20 @@ var TestMainchain = class {
371
383
  return this.address;
372
384
  }
373
385
  async client() {
374
- const client = await (0, import_mainchain2.getClient)(this.address);
375
- disconnectOnTeardown(client);
376
- return client;
386
+ let lastError;
387
+ for (let attempt = 0; attempt < 20; attempt += 1) {
388
+ try {
389
+ const client = await (0, import_mainchain2.getClient)(this.address);
390
+ disconnectOnTeardown(client);
391
+ return client;
392
+ } catch (error) {
393
+ lastError = error;
394
+ await new Promise((resolve3) => setTimeout(resolve3, 250));
395
+ }
396
+ }
397
+ throw new Error(`Unable to connect to mainchain client at ${this.address}`, {
398
+ cause: lastError instanceof Error ? lastError : void 0
399
+ });
377
400
  }
378
401
  async bootAddress() {
379
402
  const client = await this.client();
@@ -586,11 +609,467 @@ var TestOracle = class _TestOracle {
586
609
  }
587
610
  };
588
611
 
612
+ // src/TestEthereum.ts
613
+ var fs4 = __toESM(require("fs/promises"), 1);
614
+ var os = __toESM(require("os"), 1);
615
+ var Path5 = __toESM(require("path"), 1);
616
+ var import_node_child_process2 = require("child_process");
617
+ var import_detect_port2 = require("detect-port");
618
+ var import_mainchain4 = require("@argonprotocol/mainchain");
619
+ var import_accounts = require("viem/accounts");
620
+ var import_viem = require("viem");
621
+ var {
622
+ argonTokenArtifact,
623
+ argonotTokenArtifact,
624
+ hashMintingGatewayGlobalIssuanceCouncil,
625
+ mintingGatewayArtifact,
626
+ proxyAdminArtifact,
627
+ transparentUpgradeableProxyArtifact
628
+ } = import_mainchain4.EvmContracts;
629
+ var DEFAULT_KURTOSIS_BIN = "kurtosis";
630
+ var DEFAULT_ETHEREUM_PACKAGE = "github.com/ethpandaops/ethereum-package";
631
+ var DEFAULT_EL_PORT_START = 32e3;
632
+ var DEFAULT_CL_PORT_START = 33e3;
633
+ var PORT_RANGE_SIZE = 32;
634
+ var ENCLAVE_NAME_PREFIX = "argon-eth-";
635
+ var PROBE_INTERVAL_MS = 1e3;
636
+ var PROBE_TIMEOUT_MS = 6e4;
637
+ var LIGHT_CLIENT_READY_TIMEOUT_MS = 5 * 6e4;
638
+ var KURTOSIS_RUN_TIMEOUT_MS = 20 * 6e4;
639
+ var DEFAULT_SEED_ARGON_AMOUNT_BASE_UNITS = 1000000000n;
640
+ var DEFAULT_INITIAL_MICROGONS_PER_ARGONOT = 1000000n;
641
+ var ERC1967_ADMIN_SLOT = "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103";
642
+ var TestEthereum = class {
643
+ enclaveName;
644
+ kurtosisBin;
645
+ packageRef;
646
+ executionRpcUrl;
647
+ beaconApiUrl;
648
+ chainId;
649
+ #argsDir;
650
+ constructor(enclaveName = `${ENCLAVE_NAME_PREFIX}${Math.random().toString(36).slice(2, 8)}`, kurtosisBin = DEFAULT_KURTOSIS_BIN, packageRef = DEFAULT_ETHEREUM_PACKAGE) {
651
+ this.enclaveName = enclaveName;
652
+ this.kurtosisBin = kurtosisBin;
653
+ this.packageRef = packageRef;
654
+ addTeardown(this);
655
+ }
656
+ static isInstalled(kurtosisBin = DEFAULT_KURTOSIS_BIN) {
657
+ return (0, import_node_child_process2.spawnSync)(kurtosisBin, ["version"], { stdio: "ignore" }).status === 0;
658
+ }
659
+ async launch(options) {
660
+ const {
661
+ consensusClient = "lighthouse",
662
+ preset = "mainnet",
663
+ secondsPerSlot,
664
+ waitForFinalization = true,
665
+ prefundedAccounts
666
+ } = options ?? {};
667
+ const elPublicPortStart = await findFreePortRange(DEFAULT_EL_PORT_START, PORT_RANGE_SIZE);
668
+ const clPublicPortStart = await findFreePortRange(DEFAULT_CL_PORT_START, PORT_RANGE_SIZE);
669
+ this.#argsDir = await fs4.mkdtemp(Path5.join(os.tmpdir(), "argon-ethereum-devnet-"));
670
+ const argsFile = Path5.join(this.#argsDir, "network-params.yaml");
671
+ await fs4.writeFile(
672
+ argsFile,
673
+ renderEthereumArgs(
674
+ elPublicPortStart,
675
+ clPublicPortStart,
676
+ consensusClient,
677
+ preset,
678
+ secondsPerSlot,
679
+ waitForFinalization,
680
+ prefundedAccounts
681
+ )
682
+ );
683
+ await runCommand(
684
+ this.kurtosisBin,
685
+ ["run", "--enclave", this.enclaveName, this.packageRef, "--args-file", argsFile],
686
+ KURTOSIS_RUN_TIMEOUT_MS
687
+ );
688
+ const executionRpc = await waitForProbe(
689
+ () => findExecutionRpcUrl(elPublicPortStart, PORT_RANGE_SIZE),
690
+ PROBE_TIMEOUT_MS
691
+ );
692
+ const beaconApi = await waitForProbe(
693
+ () => findBeaconApiUrl(clPublicPortStart, PORT_RANGE_SIZE),
694
+ PROBE_TIMEOUT_MS
695
+ );
696
+ this.executionRpcUrl = executionRpc.url;
697
+ this.beaconApiUrl = beaconApi.url;
698
+ this.chainId = executionRpc.chainId;
699
+ await waitForProbe(
700
+ () => this.getBeacon("/eth/v1/beacon/genesis"),
701
+ LIGHT_CLIENT_READY_TIMEOUT_MS
702
+ );
703
+ return {
704
+ executionRpcUrl: this.executionRpcUrl,
705
+ beaconApiUrl: this.beaconApiUrl,
706
+ chainId: this.chainId
707
+ };
708
+ }
709
+ async callExecution(method, params = []) {
710
+ const executionRpcUrl = this.executionRpcUrl;
711
+ if (!executionRpcUrl) {
712
+ throw new Error("Execution RPC URL is not available before launch");
713
+ }
714
+ const response = await fetch(executionRpcUrl, {
715
+ method: "POST",
716
+ headers: { "content-type": "application/json" },
717
+ body: JSON.stringify({
718
+ id: 1,
719
+ jsonrpc: "2.0",
720
+ method,
721
+ params
722
+ }),
723
+ signal: AbortSignal.timeout(1e4)
724
+ });
725
+ if (!response.ok) {
726
+ throw new Error(`Execution RPC request failed for ${method}: ${response.status}`);
727
+ }
728
+ const body = await response.json();
729
+ if (body.error) {
730
+ throw new Error(
731
+ `Execution RPC ${method} failed (${body.error.code ?? "unknown"}): ${body.error.message ?? "unknown error"}`
732
+ );
733
+ }
734
+ return body.result;
735
+ }
736
+ async getBeacon(path) {
737
+ const beaconApiUrl = this.beaconApiUrl;
738
+ if (!beaconApiUrl) {
739
+ throw new Error("Beacon API URL is not available before launch");
740
+ }
741
+ const response = await fetch(new URL(path, `${beaconApiUrl}/`), {
742
+ signal: AbortSignal.timeout(1e4)
743
+ });
744
+ if (!response.ok) {
745
+ throw new Error(`Beacon API request failed for ${path}: ${response.status}`);
746
+ }
747
+ return await response.json();
748
+ }
749
+ async deployMintingGatewayFixture(options) {
750
+ const { executionRpcUrl, chainId } = this;
751
+ if (!executionRpcUrl || !chainId) {
752
+ throw new Error("Ethereum devnet must be launched before deploying MintingGateway fixtures");
753
+ }
754
+ const account = (0, import_accounts.privateKeyToAccount)(options.deployerPrivateKey);
755
+ const adminSafe = options.adminSafe ?? account.address;
756
+ const guardianSafe = options.guardianSafe ?? adminSafe;
757
+ const chain = createExecutionChain(chainId, executionRpcUrl);
758
+ const publicClient = (0, import_viem.createPublicClient)({
759
+ chain,
760
+ transport: (0, import_viem.http)(executionRpcUrl)
761
+ });
762
+ const walletClient = (0, import_viem.createWalletClient)({
763
+ account,
764
+ chain,
765
+ transport: (0, import_viem.http)(executionRpcUrl)
766
+ });
767
+ const bootstrapCouncil = {
768
+ signers: [adminSafe],
769
+ weights: [1n]
770
+ };
771
+ const initialMicrogonsPerArgonot = options.initialMicrogonsPerArgonot ?? DEFAULT_INITIAL_MICROGONS_PER_ARGONOT;
772
+ const bootstrapCouncilHash = hashMintingGatewayGlobalIssuanceCouncil({
773
+ ...bootstrapCouncil,
774
+ epochMicrogonsPerArgonot: initialMicrogonsPerArgonot
775
+ });
776
+ const bootstrapImplementationAddress = await deployContract(walletClient, publicClient, {
777
+ abi: mintingGatewayArtifact.abi,
778
+ bytecode: mintingGatewayArtifact.bytecode,
779
+ args: [import_viem.zeroAddress, import_viem.zeroAddress]
780
+ });
781
+ const initializeData = (0, import_viem.encodeFunctionData)({
782
+ abi: mintingGatewayArtifact.abi,
783
+ functionName: "initialize",
784
+ args: [
785
+ adminSafe,
786
+ guardianSafe,
787
+ bootstrapCouncilHash,
788
+ BigInt(bootstrapCouncil.signers.length),
789
+ 1n,
790
+ initialMicrogonsPerArgonot
791
+ ]
792
+ });
793
+ const gatewayAddress = await deployContract(walletClient, publicClient, {
794
+ abi: transparentUpgradeableProxyArtifact.abi,
795
+ bytecode: transparentUpgradeableProxyArtifact.bytecode,
796
+ args: [bootstrapImplementationAddress, adminSafe, initializeData]
797
+ });
798
+ const proxyAdminAddress = getAddressFromStorage(
799
+ await publicClient.getStorageAt({
800
+ address: gatewayAddress,
801
+ slot: ERC1967_ADMIN_SLOT
802
+ })
803
+ );
804
+ const argonTokenAddress = await deployContract(walletClient, publicClient, {
805
+ abi: argonTokenArtifact.abi,
806
+ bytecode: argonTokenArtifact.bytecode,
807
+ args: [gatewayAddress]
808
+ });
809
+ const argonotTokenAddress = await deployContract(walletClient, publicClient, {
810
+ abi: argonotTokenArtifact.abi,
811
+ bytecode: argonotTokenArtifact.bytecode,
812
+ args: [gatewayAddress]
813
+ });
814
+ const finalImplementationAddress = await deployContract(walletClient, publicClient, {
815
+ abi: mintingGatewayArtifact.abi,
816
+ bytecode: mintingGatewayArtifact.bytecode,
817
+ args: [argonTokenAddress, argonotTokenAddress]
818
+ });
819
+ const upgradeHash = await walletClient.sendTransaction({
820
+ to: proxyAdminAddress,
821
+ data: (0, import_viem.encodeFunctionData)({
822
+ abi: proxyAdminArtifact.abi,
823
+ functionName: "upgradeAndCall",
824
+ args: [gatewayAddress, finalImplementationAddress, "0x"]
825
+ })
826
+ });
827
+ const upgradeReceipt = await waitForExecutionReceipt(publicClient, upgradeHash);
828
+ if (upgradeReceipt.status !== "success") {
829
+ throw new Error("MintingGateway proxy upgrade failed");
830
+ }
831
+ if (options.seedArgonRecipient) {
832
+ const mintHash = await walletClient.sendTransaction({
833
+ to: gatewayAddress,
834
+ data: (0, import_viem.encodeFunctionData)({
835
+ abi: mintingGatewayArtifact.abi,
836
+ functionName: "migrate",
837
+ args: [
838
+ {
839
+ recipients: [options.seedArgonRecipient],
840
+ amounts: [options.seedArgonAmountBaseUnits ?? DEFAULT_SEED_ARGON_AMOUNT_BASE_UNITS]
841
+ },
842
+ {
843
+ recipients: [],
844
+ amounts: []
845
+ }
846
+ ]
847
+ })
848
+ });
849
+ const mintReceipt = await waitForExecutionReceipt(publicClient, mintHash);
850
+ if (mintReceipt.status !== "success") {
851
+ throw new Error("MintingGateway migrate failed");
852
+ }
853
+ }
854
+ return {
855
+ argonTokenAddress,
856
+ argonotTokenAddress,
857
+ gatewayAddress
858
+ };
859
+ }
860
+ async teardown() {
861
+ if (this.#argsDir) {
862
+ await fs4.rm(this.#argsDir, { recursive: true, force: true });
863
+ this.#argsDir = void 0;
864
+ }
865
+ await runCommand(this.kurtosisBin, ["enclave", "rm", "-f", this.enclaveName], 6e4, true);
866
+ }
867
+ };
868
+ async function deployContract(walletClient, publicClient, request) {
869
+ const hash = await walletClient.deployContract({
870
+ ...request,
871
+ account: walletClient.account,
872
+ chain: walletClient.chain
873
+ });
874
+ const receipt = await waitForExecutionReceipt(publicClient, hash);
875
+ if (receipt.status !== "success" || !receipt.contractAddress) {
876
+ throw new Error(`Contract deployment failed for ${request.bytecode.slice(0, 10)}`);
877
+ }
878
+ return receipt.contractAddress;
879
+ }
880
+ function getAddressFromStorage(value) {
881
+ if (!value || value === "0x") {
882
+ throw new Error("Missing proxy admin address in ERC1967 admin slot");
883
+ }
884
+ return (0, import_viem.getAddress)(`0x${value.slice(-40)}`);
885
+ }
886
+ function renderEthereumArgs(elPublicPortStart, clPublicPortStart, consensusClient, preset, secondsPerSlot, waitForFinalization, prefundedAccounts) {
887
+ const lines = [
888
+ "participants:",
889
+ " - el_type: geth",
890
+ ` cl_type: ${consensusClient}`,
891
+ "network_params:",
892
+ " network: kurtosis",
893
+ ` preset: ${preset}`,
894
+ ...secondsPerSlot ? [` seconds_per_slot: ${secondsPerSlot}`] : [],
895
+ ...prefundedAccounts && Object.keys(prefundedAccounts).length > 0 ? [` prefunded_accounts: '${JSON.stringify(prefundedAccounts)}'`] : [],
896
+ "additional_services: []",
897
+ `wait_for_finalization: ${waitForFinalization ? "true" : "false"}`,
898
+ "global_log_level: warn",
899
+ "port_publisher:",
900
+ " el:",
901
+ " enabled: true",
902
+ ` public_port_start: ${elPublicPortStart}`,
903
+ " cl:",
904
+ " enabled: true",
905
+ ` public_port_start: ${clPublicPortStart}`
906
+ ];
907
+ lines.push("");
908
+ return lines.join("\n");
909
+ }
910
+ async function findExecutionRpcUrl(portStart, rangeSize) {
911
+ for (let port2 = portStart; port2 < portStart + rangeSize; port2 += 1) {
912
+ const url2 = `http://127.0.0.1:${port2}`;
913
+ const response = await fetchJsonRpc(url2, "eth_chainId");
914
+ if (typeof response === "string") {
915
+ return { url: url2, chainId: response };
916
+ }
917
+ }
918
+ throw new Error(
919
+ `Unable to find an execution RPC endpoint in ${portStart}-${portStart + rangeSize - 1}`
920
+ );
921
+ }
922
+ async function findBeaconApiUrl(portStart, rangeSize) {
923
+ for (let port2 = portStart; port2 < portStart + rangeSize; port2 += 1) {
924
+ const url2 = `http://127.0.0.1:${port2}`;
925
+ try {
926
+ const response = await fetch(new URL("/eth/v1/node/version", `${url2}/`), {
927
+ signal: AbortSignal.timeout(2e3)
928
+ });
929
+ if (!response.ok) {
930
+ continue;
931
+ }
932
+ const body = await response.json();
933
+ if (body.data?.version) {
934
+ return { url: url2 };
935
+ }
936
+ } catch {
937
+ }
938
+ }
939
+ throw new Error(
940
+ `Unable to find a Beacon API endpoint in ${portStart}-${portStart + rangeSize - 1}`
941
+ );
942
+ }
943
+ async function fetchJsonRpc(url2, method) {
944
+ try {
945
+ const response = await fetch(url2, {
946
+ method: "POST",
947
+ headers: { "content-type": "application/json" },
948
+ body: JSON.stringify({
949
+ id: 1,
950
+ jsonrpc: "2.0",
951
+ method,
952
+ params: []
953
+ }),
954
+ signal: AbortSignal.timeout(2e3)
955
+ });
956
+ if (!response.ok) {
957
+ return null;
958
+ }
959
+ const body = await response.json();
960
+ return body.result ?? null;
961
+ } catch {
962
+ return null;
963
+ }
964
+ }
965
+ function createExecutionChain(chainId, executionRpcUrl) {
966
+ return (0, import_viem.defineChain)({
967
+ id: Number.parseInt(chainId, 16),
968
+ name: "argon-test-ethereum",
969
+ nativeCurrency: {
970
+ name: "Ether",
971
+ symbol: "ETH",
972
+ decimals: 18
973
+ },
974
+ rpcUrls: {
975
+ default: {
976
+ http: [executionRpcUrl]
977
+ }
978
+ }
979
+ });
980
+ }
981
+ async function findFreePortRange(start, size) {
982
+ for (let candidate = start; candidate < start + 1e3; candidate += size) {
983
+ const ports = Array.from({ length: size }, (_, index) => candidate + index);
984
+ const results = await Promise.all(ports.map((port2) => (0, import_detect_port2.detectPort)(port2)));
985
+ if (results.every((resolvedPort, index) => resolvedPort === ports[index])) {
986
+ return candidate;
987
+ }
988
+ }
989
+ throw new Error(`Unable to find a free port range starting near ${start}`);
990
+ }
991
+ async function waitForProbe(probe, timeoutMs) {
992
+ const start = Date.now();
993
+ let lastError;
994
+ while (Date.now() - start < timeoutMs) {
995
+ try {
996
+ return await probe();
997
+ } catch (error) {
998
+ lastError = error;
999
+ await delay(PROBE_INTERVAL_MS);
1000
+ }
1001
+ }
1002
+ throw lastError instanceof Error ? lastError : new Error("Timed out waiting for probe");
1003
+ }
1004
+ async function waitForExecutionReceipt(publicClient, hash) {
1005
+ const start = Date.now();
1006
+ let lastError;
1007
+ while (Date.now() - start < 12e4) {
1008
+ try {
1009
+ const receipt = await publicClient.getTransactionReceipt({ hash });
1010
+ if (receipt) {
1011
+ return receipt;
1012
+ }
1013
+ } catch (error) {
1014
+ const errorText = error instanceof Error ? [
1015
+ error.message,
1016
+ "details" in error && typeof error.details === "string" ? error.details : void 0
1017
+ ].filter(Boolean).join(" ") : String(error);
1018
+ if (!errorText.includes("indexing is in progress") && !errorText.includes("Transaction receipt with hash") && !errorText.includes("could not be found")) {
1019
+ throw error;
1020
+ }
1021
+ lastError = error instanceof Error ? error : new Error(errorText);
1022
+ }
1023
+ await delay(500);
1024
+ }
1025
+ throw lastError ?? new Error(`Timed out waiting for execution receipt ${hash}`);
1026
+ }
1027
+ async function runCommand(command, args, timeoutMs, allowFailure = false) {
1028
+ await new Promise((resolve3, reject) => {
1029
+ const child = (0, import_node_child_process2.spawn)(command, args, {
1030
+ stdio: ["ignore", "pipe", "pipe"]
1031
+ });
1032
+ let stdout = "";
1033
+ let stderr = "";
1034
+ const timeout = setTimeout(() => {
1035
+ child.kill("SIGTERM");
1036
+ reject(new Error(`Command timed out: ${command} ${args.join(" ")}`));
1037
+ }, timeoutMs);
1038
+ child.stdout?.setEncoding("utf8");
1039
+ child.stderr?.setEncoding("utf8");
1040
+ child.stdout?.on("data", (chunk) => {
1041
+ stdout += chunk;
1042
+ });
1043
+ child.stderr?.on("data", (chunk) => {
1044
+ stderr += chunk;
1045
+ });
1046
+ child.on("error", (error) => {
1047
+ clearTimeout(timeout);
1048
+ reject(error);
1049
+ });
1050
+ child.on("exit", (code) => {
1051
+ clearTimeout(timeout);
1052
+ if (code === 0 || allowFailure) {
1053
+ resolve3();
1054
+ return;
1055
+ }
1056
+ reject(
1057
+ new Error(
1058
+ [`Command failed: ${command} ${args.join(" ")}`, stdout.trim(), stderr.trim()].filter(Boolean).join("\n")
1059
+ )
1060
+ );
1061
+ });
1062
+ });
1063
+ }
1064
+ async function delay(ms) {
1065
+ await new Promise((resolve3) => setTimeout(resolve3, ms));
1066
+ }
1067
+
589
1068
  // src/TestNetwork.ts
590
1069
  var docker = __toESM(require("docker-compose"), 1);
591
- var Path5 = __toESM(require("path"), 1);
1070
+ var Path6 = __toESM(require("path"), 1);
592
1071
  async function startNetwork(testName, options) {
593
- const config = Path5.join(__dirname, `dev.docker-compose.yml`);
1072
+ const config = Path6.join(__dirname, `dev.docker-compose.yml`);
594
1073
  const env4 = {
595
1074
  VERSION: "dev",
596
1075
  ARGON_CHAIN: "dev-docker",
@@ -622,6 +1101,961 @@ async function startNetwork(testName, options) {
622
1101
  };
623
1102
  }
624
1103
 
1104
+ // src/EthereumE2eUtils.ts
1105
+ var import_mainchain5 = require("@argonprotocol/mainchain");
1106
+ var import_viem2 = require("viem");
1107
+ async function signGatewayPermit(args) {
1108
+ const signature = (0, import_viem2.parseSignature)(
1109
+ await args.account.signTypedData({
1110
+ domain: {
1111
+ name: "Argon",
1112
+ version: "1",
1113
+ chainId: args.chainId,
1114
+ verifyingContract: args.tokenAddress
1115
+ },
1116
+ types: {
1117
+ Permit: [
1118
+ { name: "owner", type: "address" },
1119
+ { name: "spender", type: "address" },
1120
+ { name: "value", type: "uint256" },
1121
+ { name: "nonce", type: "uint256" },
1122
+ { name: "deadline", type: "uint256" }
1123
+ ]
1124
+ },
1125
+ primaryType: "Permit",
1126
+ message: {
1127
+ owner: args.owner,
1128
+ spender: args.gatewayAddress,
1129
+ value: args.value,
1130
+ nonce: args.nonce,
1131
+ deadline: args.deadline
1132
+ }
1133
+ })
1134
+ );
1135
+ return {
1136
+ v: Number(signature.v),
1137
+ r: signature.r,
1138
+ s: signature.s
1139
+ };
1140
+ }
1141
+ async function waitForFinalizedBeaconExecutionAtOrAbove(ethereum, minimumExecutionBlockNumber, options = {}) {
1142
+ const startedAt = Date.now();
1143
+ const minimumFinalizedSlot = options.minimumFinalizedSlot ?? 0n;
1144
+ let lastSeenExecutionBlockNumber = 0n;
1145
+ let lastSeenHeadSlot = 0n;
1146
+ let lastSeenFinalizedSlot = 0n;
1147
+ let lastError;
1148
+ while (Date.now() - startedAt < 3e5) {
1149
+ try {
1150
+ const [headHeader, finalizedHeader] = await Promise.all([
1151
+ ethereum.getBeacon("/eth/v1/beacon/headers/head"),
1152
+ ethereum.getBeacon("/eth/v1/beacon/headers/finalized")
1153
+ ]);
1154
+ lastSeenHeadSlot = BigInt(headHeader.data.header.message.slot);
1155
+ lastSeenFinalizedSlot = BigInt(finalizedHeader.data.header.message.slot);
1156
+ const block = await ethereum.getBeacon(
1157
+ `/eth/v2/beacon/blocks/${finalizedHeader.data.root}`
1158
+ );
1159
+ const executionBlockNumber = BigInt(block.data.message.body.execution_payload.block_number);
1160
+ lastSeenExecutionBlockNumber = executionBlockNumber;
1161
+ lastError = void 0;
1162
+ if (executionBlockNumber >= minimumExecutionBlockNumber && lastSeenFinalizedSlot >= minimumFinalizedSlot) {
1163
+ return { header: finalizedHeader, block };
1164
+ }
1165
+ } catch (error) {
1166
+ if (!(error instanceof Error)) {
1167
+ throw error;
1168
+ }
1169
+ lastError = error;
1170
+ }
1171
+ await delay2(1e3);
1172
+ }
1173
+ const lastErrorSuffix = lastError ? `; last beacon error was: ${lastError.message}` : "";
1174
+ throw new Error(
1175
+ `Timed out waiting for finalized beacon execution block at or above ${minimumExecutionBlockNumber} and finalized slot at or above ${minimumFinalizedSlot}; last seen head slot was ${lastSeenHeadSlot}, finalized slot was ${lastSeenFinalizedSlot}, and finalized execution block was ${lastSeenExecutionBlockNumber}${lastErrorSuffix}`
1176
+ );
1177
+ }
1178
+ async function mineLaterExecutionAnchorReceipt(walletClient, chain, ethereum, account, minimumBlockNumber) {
1179
+ while (true) {
1180
+ const transactionHash = await walletClient.sendTransaction({
1181
+ account,
1182
+ chain,
1183
+ to: account.address,
1184
+ value: 0n
1185
+ });
1186
+ const receipt = await waitForExecutionReceipt2(ethereum, transactionHash);
1187
+ if (BigInt(receipt.blockNumber) > minimumBlockNumber) {
1188
+ return receipt;
1189
+ }
1190
+ }
1191
+ }
1192
+ async function waitForExecutionReceipt2(ethereum, transactionHash) {
1193
+ const startedAt = Date.now();
1194
+ while (Date.now() - startedAt < 12e4) {
1195
+ try {
1196
+ const receipt = await ethereum.callExecution(
1197
+ "eth_getTransactionReceipt",
1198
+ [transactionHash]
1199
+ );
1200
+ if (receipt) {
1201
+ return receipt;
1202
+ }
1203
+ } catch (error) {
1204
+ const errorText = error instanceof Error ? [
1205
+ error.message,
1206
+ "details" in error && typeof error.details === "string" ? error.details : void 0
1207
+ ].filter(Boolean).join(" ") : String(error);
1208
+ if (!errorText.includes("indexing is in progress")) {
1209
+ throw error;
1210
+ }
1211
+ }
1212
+ await delay2(500);
1213
+ }
1214
+ throw new Error(`Timed out waiting for execution receipt ${transactionHash}`);
1215
+ }
1216
+ async function syncEthereumVerifierUntilAnchorCovers(mainchainClient, relayer, beaconApiUrl, minimumExecutionBlockNumber) {
1217
+ const startedAt = Date.now();
1218
+ const timeoutMs = 5 * 6e4;
1219
+ let lastRetryableError;
1220
+ let lastAnchorBlockNumber;
1221
+ while (Date.now() - startedAt < timeoutMs) {
1222
+ try {
1223
+ const anchor = await (0, import_mainchain5.getLatestArgonFinalizedExecutionHeader)(mainchainClient);
1224
+ lastAnchorBlockNumber = anchor.blockNumber;
1225
+ if (anchor.blockNumber >= minimumExecutionBlockNumber) {
1226
+ return;
1227
+ }
1228
+ } catch {
1229
+ }
1230
+ const txs = await (0, import_mainchain5.getNextEthereumBeaconSyncTxs)(mainchainClient, beaconApiUrl);
1231
+ if (txs.length === 0) {
1232
+ await delay2(500);
1233
+ continue;
1234
+ }
1235
+ let shouldRetry = false;
1236
+ for (const tx of txs) {
1237
+ try {
1238
+ const result = await new import_mainchain5.TxSubmitter(mainchainClient, tx, relayer).submit();
1239
+ await result.waitForInFirstBlock;
1240
+ lastRetryableError = void 0;
1241
+ } catch (error) {
1242
+ if (isRetryableEthereumVerifierSyncError(error)) {
1243
+ lastRetryableError = error instanceof Error ? error : new Error(String(error));
1244
+ shouldRetry = true;
1245
+ break;
1246
+ }
1247
+ throw error;
1248
+ }
1249
+ }
1250
+ if (shouldRetry) {
1251
+ await delay2(500);
1252
+ }
1253
+ }
1254
+ throw lastRetryableError ?? new Error(
1255
+ `Ethereum verifier did not retain an anchor at or above execution block ${minimumExecutionBlockNumber} within ${Math.floor(timeoutMs / 1e3)}s; last seen anchor was ${lastAnchorBlockNumber ?? "unavailable"}`
1256
+ );
1257
+ }
1258
+ function toArgonKeccakSignature(signature) {
1259
+ const bytes = (0, import_mainchain5.hexToU8a)(signature);
1260
+ if (bytes.length !== 65) {
1261
+ throw new Error(`Expected 65-byte ECDSA signature, received ${bytes.length} bytes`);
1262
+ }
1263
+ if (bytes[64] >= 27) {
1264
+ bytes[64] -= 27;
1265
+ }
1266
+ return (0, import_mainchain5.u8aToHex)(bytes);
1267
+ }
1268
+ function toEvmRecoverableSignature(signature) {
1269
+ const bytes = (0, import_mainchain5.hexToU8a)(signature);
1270
+ if (bytes.length !== 65) {
1271
+ throw new Error(`Expected 65-byte ECDSA signature, received ${bytes.length} bytes`);
1272
+ }
1273
+ if (bytes[64] <= 1) {
1274
+ bytes[64] += 27;
1275
+ }
1276
+ return (0, import_mainchain5.u8aToHex)(bytes);
1277
+ }
1278
+ function isRetryableEthereumVerifierSyncError(error) {
1279
+ const message = error instanceof Error ? error.message : String(error);
1280
+ return (0, import_mainchain5.isOutdatedTransactionError)(error) || message.includes("ethereumVerifier.InvalidHeaderMerkleProof");
1281
+ }
1282
+ async function delay2(ms) {
1283
+ await new Promise((resolve3) => setTimeout(resolve3, ms));
1284
+ }
1285
+
1286
+ // src/EthereumGatewayQueue.ts
1287
+ var import_mainchain6 = require("@argonprotocol/mainchain");
1288
+ var import_viem3 = require("viem");
1289
+ var {
1290
+ encodeMintingGatewayMintingAuthorityActivationTarget,
1291
+ hashMintingGatewayActivateMintingAuthority,
1292
+ hashMintingGatewayGatewayUpdateApproval,
1293
+ mintingGatewayAbi,
1294
+ MINTING_GATEWAY_UPDATE_KINDS
1295
+ } = import_mainchain6.EvmContracts;
1296
+ async function getReadyEthereumGatewayUpdates(client, gatewayClient, options = {}) {
1297
+ const destinationChain = options.destinationChain ?? "Ethereum";
1298
+ const maxQueueEntries = options.maxQueueEntries ?? 100;
1299
+ if (maxQueueEntries < 1) {
1300
+ throw new Error(`maxQueueEntries must be at least 1, received ${maxQueueEntries}`);
1301
+ }
1302
+ const chainConfigOption = await client.query.crosschainTransfer.chainConfigBySourceChain(destinationChain);
1303
+ if (chainConfigOption.isNone) {
1304
+ throw new Error(`Crosschain config not found for ${destinationChain}`);
1305
+ }
1306
+ const chainConfig = chainConfigOption.unwrap();
1307
+ if (!chainConfig.isEvm) {
1308
+ throw new Error(`Chain config for ${destinationChain} is not EVM-shaped`);
1309
+ }
1310
+ const gatewayAddress = (0, import_viem3.getAddress)(toHexValue(chainConfig.asEvm.gateway));
1311
+ const chainId = chainConfig.asEvm.chainId.toBigInt();
1312
+ const hashContext = { chainId, gatewayAddress };
1313
+ const currentCouncilHashOption = await client.query.crosschainTransfer.activeGlobalIssuanceCouncilByDestinationChain(
1314
+ destinationChain
1315
+ );
1316
+ if (currentCouncilHashOption.isNone) {
1317
+ throw new Error(`Active GlobalIssuanceCouncil not found for ${destinationChain}`);
1318
+ }
1319
+ const currentCouncilHash = toHexValue(currentCouncilHashOption.unwrap());
1320
+ const councilCache = /* @__PURE__ */ new Map();
1321
+ const currentCouncil = councilToSnapshot(
1322
+ await loadCouncilByHash(client, currentCouncilHash, councilCache)
1323
+ );
1324
+ const [rawArgonApprovalsNonce, rawArgonApprovalsHash, rawPaused] = await Promise.all([
1325
+ gatewayClient.readContract({
1326
+ abi: mintingGatewayAbi,
1327
+ address: gatewayAddress,
1328
+ functionName: "argonApprovalsNonce"
1329
+ }),
1330
+ gatewayClient.readContract({
1331
+ abi: mintingGatewayAbi,
1332
+ address: gatewayAddress,
1333
+ functionName: "argonApprovalsHash"
1334
+ }),
1335
+ gatewayClient.readContract({
1336
+ abi: mintingGatewayAbi,
1337
+ address: gatewayAddress,
1338
+ functionName: "paused"
1339
+ })
1340
+ ]);
1341
+ const argonApprovalsNonce = rawArgonApprovalsNonce;
1342
+ const argonApprovalsHash = rawArgonApprovalsHash;
1343
+ const paused = rawPaused;
1344
+ const updates = [];
1345
+ let expectedPreviousApprovalHash = argonApprovalsHash;
1346
+ let firstQueueNonce;
1347
+ let lastQueueNonce;
1348
+ if (!paused) {
1349
+ for (let queueNonce = argonApprovalsNonce + 1n; updates.length < maxQueueEntries; queueNonce += 1n) {
1350
+ const entryOption = await client.query.crosschainTransfer.councilApprovalQueueByDestinationChainAndNonce(
1351
+ destinationChain,
1352
+ queueNonce
1353
+ );
1354
+ if (entryOption.isNone) {
1355
+ break;
1356
+ }
1357
+ const entry = entryOption.unwrap();
1358
+ const approvingCouncilHash = toHexValue(entry.approvingCouncilHash);
1359
+ const approvingCouncil = await loadCouncilByHash(client, approvingCouncilHash, councilCache);
1360
+ if (!queueEntryHasQuorum(entry, approvingCouncil)) {
1361
+ break;
1362
+ }
1363
+ if (toHexValue(entry.previousApprovalHash) !== expectedPreviousApprovalHash) {
1364
+ throw new Error(
1365
+ `Queue nonce ${queueNonce} expected previous approval hash ${expectedPreviousApprovalHash}, received ${toHexValue(entry.previousApprovalHash)}`
1366
+ );
1367
+ }
1368
+ const update = await buildGatewayUpdate(client, destinationChain, hashContext, queueNonce, {
1369
+ entry,
1370
+ approvingCouncilHash
1371
+ });
1372
+ updates.push(update);
1373
+ firstQueueNonce ??= queueNonce;
1374
+ lastQueueNonce = queueNonce;
1375
+ expectedPreviousApprovalHash = toHexValue(entry.approvalHash);
1376
+ }
1377
+ }
1378
+ return {
1379
+ destinationChain,
1380
+ chainId,
1381
+ gatewayAddress,
1382
+ currentCouncilHash,
1383
+ currentCouncil,
1384
+ argonApprovalsNonce,
1385
+ argonApprovalsHash,
1386
+ paused,
1387
+ ...firstQueueNonce !== void 0 ? { firstQueueNonce, lastQueueNonce } : {},
1388
+ updates
1389
+ };
1390
+ }
1391
+ async function buildGatewayUpdate(client, destinationChain, hashContext, queueNonce, queueItem) {
1392
+ const { entry, approvingCouncilHash } = queueItem;
1393
+ const signatures = getSortedSignatures(entry.signatures);
1394
+ if (entry.target.isMintingAuthorityActivation) {
1395
+ const signingKey = (0, import_viem3.getAddress)(toHexValue(entry.target.asMintingAuthorityActivation));
1396
+ const authorityOption = await client.query.crosschainTransfer.mintingAuthoritiesBySigner(signingKey);
1397
+ if (authorityOption.isNone) {
1398
+ throw new Error(
1399
+ `Minting authority activation ${signingKey} not found for queue nonce ${queueNonce}`
1400
+ );
1401
+ }
1402
+ const authority = authorityOption.unwrap();
1403
+ if (authority.destinationChain.type !== destinationChain) {
1404
+ throw new Error(
1405
+ `Minting authority ${signingKey} belongs to ${String(authority.destinationChain.type)}, expected ${String(destinationChain)}`
1406
+ );
1407
+ }
1408
+ const target = {
1409
+ microgonCollateral: authority.gatewayRemainingMicrogonCollateral.toBigInt(),
1410
+ micronotCollateral: authority.gatewayRemainingMicronotCollateral.toBigInt(),
1411
+ signingKey
1412
+ };
1413
+ const payload = encodeMintingGatewayMintingAuthorityActivationTarget(target);
1414
+ const targetPayloadHash = payloadHashFromActivationPayload(hashContext, target);
1415
+ const approvalHash = hashMintingGatewayGatewayUpdateApproval(hashContext, {
1416
+ queueNonce,
1417
+ approvingCouncilHash,
1418
+ kind: MINTING_GATEWAY_UPDATE_KINDS.mintingAuthorityActivate,
1419
+ targetId: `0x${signingKey.slice(2).padStart(64, "0").toLowerCase()}`,
1420
+ targetPayloadHash,
1421
+ previousUpdateHash: toHexValue(entry.previousApprovalHash)
1422
+ });
1423
+ if (toHexValue(entry.targetPayloadHash) !== targetPayloadHash) {
1424
+ throw new Error(`Queue nonce ${queueNonce} target payload hash does not match authority`);
1425
+ }
1426
+ if (toHexValue(entry.approvalHash) !== approvalHash) {
1427
+ throw new Error(
1428
+ `Queue nonce ${queueNonce} approval hash does not match authority: actual=${toHexValue(entry.approvalHash)} expected=${approvalHash} previous=${toHexValue(entry.previousApprovalHash)} council=${approvingCouncilHash} targetPayload=${toHexValue(entry.targetPayloadHash)}`
1429
+ );
1430
+ }
1431
+ return {
1432
+ queueNonce,
1433
+ kind: MINTING_GATEWAY_UPDATE_KINDS.mintingAuthorityActivate,
1434
+ payload,
1435
+ signatures
1436
+ };
1437
+ }
1438
+ throw new Error(`Unsupported approval queue target ${entry.target.type}`);
1439
+ }
1440
+ async function loadCouncilByHash(client, councilHash, cache) {
1441
+ const cached = cache.get(councilHash);
1442
+ if (cached) {
1443
+ return cached;
1444
+ }
1445
+ const councilOption = await client.query.crosschainTransfer.globalIssuanceCouncilByHash(councilHash);
1446
+ if (councilOption.isNone) {
1447
+ throw new Error(`GlobalIssuanceCouncil ${councilHash} not found`);
1448
+ }
1449
+ const council = councilOption.unwrap();
1450
+ const loaded = {
1451
+ totalWeight: council.totalWeight.toBigInt(),
1452
+ members: [...council.members.entries()].map(([signer, member]) => ({
1453
+ signer: (0, import_viem3.getAddress)(toHexValue(signer)),
1454
+ weight: member.weight.toBigInt()
1455
+ })).sort((left, right) => left.signer.localeCompare(right.signer))
1456
+ };
1457
+ cache.set(councilHash, loaded);
1458
+ return loaded;
1459
+ }
1460
+ function queueEntryHasQuorum(entry, council) {
1461
+ const signedWeight = [...entry.signatures.entries()].reduce((total, [signer, signature]) => {
1462
+ const signerAddress = (0, import_viem3.getAddress)(toHexValue(signer));
1463
+ const member = council.members.find((x) => x.signer === signerAddress);
1464
+ if (!member) {
1465
+ throw new Error(`Signature submitted by ${signerAddress}, which is not in the council`);
1466
+ }
1467
+ return total + member.weight;
1468
+ }, 0n);
1469
+ return signedWeight * 2n > council.totalWeight;
1470
+ }
1471
+ function councilToSnapshot(council) {
1472
+ return {
1473
+ signers: council.members.map((member) => member.signer),
1474
+ weights: council.members.map((member) => member.weight)
1475
+ };
1476
+ }
1477
+ function payloadHashFromActivationPayload(hashContext, target) {
1478
+ return hashMintingGatewayActivateMintingAuthority(hashContext, target);
1479
+ }
1480
+ function getSortedSignatures(signatures) {
1481
+ return [...signatures.entries()].sort(
1482
+ ([leftSigner], [rightSigner]) => toHexValue(leftSigner).localeCompare(toHexValue(rightSigner))
1483
+ ).map(([, signature]) => toEvmRecoverableSignature(toHexValue(signature)));
1484
+ }
1485
+ function toHexValue(value) {
1486
+ return value.toHex();
1487
+ }
1488
+
1489
+ // src/TestEthereumProofActors.ts
1490
+ var import_mainchain7 = require("@argonprotocol/mainchain");
1491
+ var import_accounts2 = require("viem/accounts");
1492
+ var import_viem4 = require("viem");
1493
+ var { argonTokenAbi, mintingGatewayAbi: mintingGatewayAbi2, MINTING_GATEWAY_RUNTIME_TO_ERC20_SCALE } = import_mainchain7.EvmContracts;
1494
+ var MINIMAL_BOOTSTRAP_FINALIZED_SLOT = 64n;
1495
+ var EthereumProofE2eHarness = class _EthereumProofE2eHarness {
1496
+ constructor(ethereum, endpoints, mainchain, mainchainClient, deployerPrivateKey, proofRelayerUri) {
1497
+ this.ethereum = ethereum;
1498
+ this.endpoints = endpoints;
1499
+ this.mainchain = mainchain;
1500
+ this.mainchainClient = mainchainClient;
1501
+ this.deployer = (0, import_accounts2.privateKeyToAccount)(deployerPrivateKey);
1502
+ this.chain = (0, import_viem4.defineChain)({
1503
+ id: Number.parseInt(endpoints.chainId, 16),
1504
+ name: "argon-test-ethereum",
1505
+ nativeCurrency: {
1506
+ name: "Ether",
1507
+ symbol: "ETH",
1508
+ decimals: 18
1509
+ },
1510
+ rpcUrls: {
1511
+ default: {
1512
+ http: [endpoints.executionRpcUrl]
1513
+ }
1514
+ }
1515
+ });
1516
+ this.publicClient = (0, import_viem4.createPublicClient)({
1517
+ chain: this.chain,
1518
+ transport: (0, import_viem4.http)(endpoints.executionRpcUrl)
1519
+ });
1520
+ this.walletClient = (0, import_viem4.createWalletClient)({
1521
+ account: this.deployer,
1522
+ chain: this.chain,
1523
+ transport: (0, import_viem4.http)(endpoints.executionRpcUrl)
1524
+ });
1525
+ this.proofRelayer = new import_mainchain7.Keyring({ type: "sr25519" }).createFromUri(proofRelayerUri);
1526
+ }
1527
+ sudoSigner = new import_mainchain7.Keyring({ type: "sr25519" }).createFromUri("//Alice");
1528
+ deployer;
1529
+ chain;
1530
+ publicClient;
1531
+ walletClient;
1532
+ mainchainClient;
1533
+ proofRelayer;
1534
+ static async launch(args) {
1535
+ const ethereum = new TestEthereum();
1536
+ const endpoints = await ethereum.launch({
1537
+ consensusClient: "lodestar",
1538
+ preset: "minimal",
1539
+ secondsPerSlot: 1,
1540
+ prefundedAccounts: {
1541
+ [args.testAccount.address]: {
1542
+ balance: args.testAccount.balance
1543
+ }
1544
+ }
1545
+ });
1546
+ const mainchain = new TestMainchain();
1547
+ await mainchain.launch();
1548
+ const mainchainClient = await mainchain.client();
1549
+ return new _EthereumProofE2eHarness(
1550
+ ethereum,
1551
+ endpoints,
1552
+ mainchain,
1553
+ mainchainClient,
1554
+ args.testAccount.privateKey,
1555
+ args.proofRelayerUri
1556
+ );
1557
+ }
1558
+ async submit(tx, signer) {
1559
+ const result = await new import_mainchain7.TxSubmitter(this.mainchainClient, tx, signer).submit();
1560
+ await result.waitForInFirstBlock;
1561
+ return result;
1562
+ }
1563
+ async sudoSubmit(tx) {
1564
+ const result = await this.submit(
1565
+ this.mainchainClient.tx.sudo.sudo(tx),
1566
+ this.sudoSigner
1567
+ );
1568
+ const sudoEvent = result.events.find((event) => this.mainchainClient.events.sudo.Sudid.is(event));
1569
+ if (!sudoEvent || !this.mainchainClient.events.sudo.Sudid.is(sudoEvent)) {
1570
+ throw new Error("sudo did not emit sudo.Sudid");
1571
+ }
1572
+ const sudoResult = sudoEvent.data[0];
1573
+ if (sudoResult.isErr) {
1574
+ throw new Error(
1575
+ `sudo failed: ${(0, import_mainchain7.dispatchErrorToString)(this.mainchainClient, sudoResult.asErr)}`
1576
+ );
1577
+ }
1578
+ return result;
1579
+ }
1580
+ async bootstrapVerifier() {
1581
+ const checkpointTx = await (0, import_mainchain7.getEthereumBeaconSyncBootstrapTx)(
1582
+ this.mainchainClient,
1583
+ this.endpoints.beaconApiUrl
1584
+ );
1585
+ return this.sudoSubmit(checkpointTx);
1586
+ }
1587
+ async syncVerifierThrough(minimumExecutionBlockNumber) {
1588
+ await syncEthereumVerifierUntilAnchorCovers(
1589
+ this.mainchainClient,
1590
+ this.sudoSigner,
1591
+ this.endpoints.beaconApiUrl,
1592
+ minimumExecutionBlockNumber
1593
+ );
1594
+ }
1595
+ async proveGatewayActivity(gatewayAddress, throughExecutionBlockNumber) {
1596
+ const payload = await (0, import_mainchain7.buildGatewayActivityProofPayload)(this.mainchainClient, {
1597
+ executionRpcUrl: this.endpoints.executionRpcUrl,
1598
+ gatewayAddress,
1599
+ throughExecutionBlockNumber
1600
+ });
1601
+ if (!payload) {
1602
+ throw new Error("Expected uncovered gateway activity to prove");
1603
+ }
1604
+ const result = await this.submit(
1605
+ this.mainchainClient.tx.crosschainTransfer.proveGatewayActivity(
1606
+ "Ethereum",
1607
+ payload.previousGatewayActivityNonce,
1608
+ payload.proof
1609
+ ),
1610
+ this.proofRelayer
1611
+ );
1612
+ return { payload, result };
1613
+ }
1614
+ async setEthereumChainConfig(gateway) {
1615
+ return this.sudoSubmit(
1616
+ this.mainchainClient.tx.crosschainTransfer.setChainConfig("Ethereum", {
1617
+ Evm: {
1618
+ chainId: this.chain.id,
1619
+ gateway: gateway.gatewayAddress,
1620
+ argonToken: gateway.argonTokenAddress,
1621
+ argonotToken: gateway.argonotTokenAddress
1622
+ }
1623
+ })
1624
+ );
1625
+ }
1626
+ async fundBurnAccount(amount) {
1627
+ const burnAccount = this.mainchainClient.consts.crosschainTransfer.ethereumBurnAccount.toString();
1628
+ return this.forceSetBalance(burnAccount, amount);
1629
+ }
1630
+ async fundProofRelayer(amount = this.mainchainClient.consts.balances.existentialDeposit.toBigInt() + 1000000n) {
1631
+ return this.submit(
1632
+ this.mainchainClient.tx.balances.transferAllowDeath(this.proofRelayer.address, amount),
1633
+ this.sudoSigner
1634
+ );
1635
+ }
1636
+ async forceSetBalance(address, amount) {
1637
+ return this.sudoSubmit(this.mainchainClient.tx.balances.forceSetBalance(address, amount));
1638
+ }
1639
+ async forceSetOwnership(address, amount) {
1640
+ return this.sudoSubmit(this.mainchainClient.tx.ownership.forceSetBalance(address, amount));
1641
+ }
1642
+ async waitForExecutionFinalizedAfter(minimumExecutionBlockNumber) {
1643
+ const laterReceipt = await mineLaterExecutionAnchorReceipt(
1644
+ this.walletClient,
1645
+ this.chain,
1646
+ this.ethereum,
1647
+ this.deployer,
1648
+ minimumExecutionBlockNumber
1649
+ );
1650
+ await waitForFinalizedBeaconExecutionAtOrAbove(
1651
+ this.ethereum,
1652
+ BigInt(laterReceipt.blockNumber),
1653
+ {
1654
+ // Matches the apps/pr/gateway-proof bootstrap guard for minimal devnets.
1655
+ minimumFinalizedSlot: MINIMAL_BOOTSTRAP_FINALIZED_SLOT
1656
+ }
1657
+ );
1658
+ return laterReceipt;
1659
+ }
1660
+ };
1661
+ var TestMintingGateway = class _TestMintingGateway {
1662
+ constructor(harness, deployment) {
1663
+ this.harness = harness;
1664
+ this.deployment = deployment;
1665
+ }
1666
+ static async deploy(harness, options) {
1667
+ const deployment = await harness.ethereum.deployMintingGatewayFixture(options);
1668
+ return new _TestMintingGateway(harness, deployment);
1669
+ }
1670
+ get gatewayAddress() {
1671
+ return this.deployment.gatewayAddress;
1672
+ }
1673
+ get argonTokenAddress() {
1674
+ return this.deployment.argonTokenAddress;
1675
+ }
1676
+ get argonotTokenAddress() {
1677
+ return this.deployment.argonotTokenAddress;
1678
+ }
1679
+ async startTransferToArgon(args) {
1680
+ const permitDeadline = (await this.harness.publicClient.getBlock()).timestamp + 3600n;
1681
+ const permitNonce = await this.harness.publicClient.readContract({
1682
+ address: this.argonTokenAddress,
1683
+ abi: argonTokenAbi,
1684
+ functionName: "nonces",
1685
+ args: [args.account.address]
1686
+ });
1687
+ const permitSignature = await signGatewayPermit({
1688
+ account: args.account,
1689
+ chainId: this.harness.chain.id,
1690
+ tokenAddress: this.argonTokenAddress,
1691
+ gatewayAddress: this.gatewayAddress,
1692
+ owner: args.account.address,
1693
+ value: args.amountRuntimeUnits * MINTING_GATEWAY_RUNTIME_TO_ERC20_SCALE,
1694
+ nonce: permitNonce,
1695
+ deadline: permitDeadline
1696
+ });
1697
+ const transactionHash = await (0, import_viem4.createWalletClient)({
1698
+ account: args.account,
1699
+ chain: this.harness.chain,
1700
+ transport: (0, import_viem4.http)(this.harness.endpoints.executionRpcUrl)
1701
+ }).sendTransaction({
1702
+ account: args.account,
1703
+ chain: this.harness.chain,
1704
+ to: this.gatewayAddress,
1705
+ data: (0, import_viem4.encodeFunctionData)({
1706
+ abi: mintingGatewayAbi2,
1707
+ functionName: "startTransferToArgon",
1708
+ args: [
1709
+ this.argonTokenAddress,
1710
+ args.amountRuntimeUnits,
1711
+ args.recipientArgonAddress,
1712
+ permitDeadline,
1713
+ permitSignature.v,
1714
+ permitSignature.r,
1715
+ permitSignature.s
1716
+ ]
1717
+ })
1718
+ });
1719
+ return waitForExecutionReceipt2(this.harness.ethereum, transactionHash);
1720
+ }
1721
+ async forceUpdateActiveCouncil(currentCouncil) {
1722
+ return this.harness.publicClient.waitForTransactionReceipt({
1723
+ hash: await this.harness.walletClient.writeContract({
1724
+ account: this.harness.deployer,
1725
+ chain: this.harness.chain,
1726
+ address: this.gatewayAddress,
1727
+ abi: mintingGatewayAbi2,
1728
+ functionName: "forceUpdateActiveCouncil",
1729
+ args: [currentCouncil]
1730
+ })
1731
+ });
1732
+ }
1733
+ async relayReadyApprovals(batch, operatorAddress) {
1734
+ return this.harness.publicClient.waitForTransactionReceipt({
1735
+ hash: await this.harness.walletClient.writeContract({
1736
+ account: this.harness.deployer,
1737
+ chain: this.harness.chain,
1738
+ address: this.gatewayAddress,
1739
+ abi: mintingGatewayAbi2,
1740
+ functionName: "applyGatewayUpdates",
1741
+ args: [
1742
+ batch.currentCouncil,
1743
+ batch.updates,
1744
+ (0, import_viem4.toHex)((0, import_mainchain7.decodeAddress)(operatorAddress), { size: 32 })
1745
+ ]
1746
+ })
1747
+ });
1748
+ }
1749
+ async argonApprovalsNonce() {
1750
+ return await this.harness.publicClient.readContract({
1751
+ address: this.gatewayAddress,
1752
+ abi: mintingGatewayAbi2,
1753
+ functionName: "argonApprovalsNonce"
1754
+ });
1755
+ }
1756
+ async globalIssuanceCouncil() {
1757
+ return await this.harness.publicClient.readContract({
1758
+ address: this.gatewayAddress,
1759
+ abi: mintingGatewayAbi2,
1760
+ functionName: "globalIssuanceCouncil"
1761
+ });
1762
+ }
1763
+ async authorityCollateral(signingKey) {
1764
+ return await this.harness.publicClient.readContract({
1765
+ address: this.gatewayAddress,
1766
+ abi: mintingGatewayAbi2,
1767
+ functionName: "mintingAuthorityCollateralRemaining",
1768
+ args: [signingKey]
1769
+ });
1770
+ }
1771
+ async finalizeTransferOut(args) {
1772
+ return this.harness.publicClient.waitForTransactionReceipt({
1773
+ hash: await this.harness.walletClient.writeContract({
1774
+ account: this.harness.deployer,
1775
+ chain: this.harness.chain,
1776
+ address: this.gatewayAddress,
1777
+ abi: mintingGatewayAbi2,
1778
+ functionName: "finalizeTransferOutOfArgon",
1779
+ args: [
1780
+ args.transferRequest,
1781
+ {
1782
+ authorizations: [
1783
+ {
1784
+ microgonCollateral: 0n,
1785
+ micronotCollateral: args.micronotCollateral,
1786
+ signature: args.collateralizationSignature
1787
+ }
1788
+ ]
1789
+ }
1790
+ ]
1791
+ })
1792
+ });
1793
+ }
1794
+ async isFinalizedTransferOut(transferRequest) {
1795
+ return await this.harness.publicClient.readContract({
1796
+ address: this.gatewayAddress,
1797
+ abi: mintingGatewayAbi2,
1798
+ functionName: "finalizedTransferOutOfArgonIds",
1799
+ args: [import_mainchain7.EvmContracts.hashMintingGatewayTransferOutOfArgonRequest(transferRequest)]
1800
+ });
1801
+ }
1802
+ async argonBalance(address) {
1803
+ return await this.harness.publicClient.readContract({
1804
+ address: this.argonTokenAddress,
1805
+ abi: argonTokenAbi,
1806
+ functionName: "balanceOf",
1807
+ args: [address]
1808
+ });
1809
+ }
1810
+ async fundExecutionAccount(address, value) {
1811
+ return this.harness.publicClient.waitForTransactionReceipt({
1812
+ hash: await this.harness.walletClient.sendTransaction({
1813
+ account: this.harness.deployer,
1814
+ chain: this.harness.chain,
1815
+ to: address,
1816
+ value
1817
+ })
1818
+ });
1819
+ }
1820
+ };
1821
+ var TestMintingAuthorityActor = class {
1822
+ constructor(harness, args) {
1823
+ this.harness = harness;
1824
+ this.operator = new import_mainchain7.Keyring({ type: "sr25519" }).createFromUri(args.operatorUri);
1825
+ this.councilSigner = (0, import_accounts2.privateKeyToAccount)(args.councilPrivateKey);
1826
+ this.authoritySigner = (0, import_accounts2.privateKeyToAccount)(args.authorityPrivateKey);
1827
+ }
1828
+ operator;
1829
+ councilSigner;
1830
+ authoritySigner;
1831
+ gateway;
1832
+ attachGateway(gateway) {
1833
+ this.gateway = gateway;
1834
+ }
1835
+ async prepareOperator(args) {
1836
+ await this.harness.forceSetBalance(this.operator.address, args.freeBalance);
1837
+ await this.harness.forceSetOwnership(this.operator.address, args.ownershipBalance);
1838
+ const vault = await import_mainchain7.Vault.create(this.harness.mainchainClient, this.operator, {
1839
+ securitization: 1000000000n,
1840
+ securitizationRatio: 1,
1841
+ annualPercentRate: 0.05,
1842
+ baseFee: 0n,
1843
+ bitcoinXpub: args.bitcoinXpub,
1844
+ treasuryProfitSharing: 0
1845
+ });
1846
+ await vault.getVault();
1847
+ await this.harness.sudoSubmit(
1848
+ this.harness.mainchainClient.tx.priceIndex.setOperator(this.operator.address)
1849
+ );
1850
+ const currentTick = await this.harness.mainchainClient.query.ticks.currentTick();
1851
+ await this.harness.submit(
1852
+ this.harness.mainchainClient.tx.priceIndex.submit({
1853
+ btcUsdPrice: (0, import_mainchain7.toFixedNumber)(6e4, 18),
1854
+ argonotUsdPrice: (0, import_mainchain7.toFixedNumber)(1, 18),
1855
+ argonUsdPrice: (0, import_mainchain7.toFixedNumber)(1, 18),
1856
+ argonUsdTargetPrice: (0, import_mainchain7.toFixedNumber)(1, 18),
1857
+ argonTimeWeightedAverageLiquidity: (0, import_mainchain7.toFixedNumber)(1e6, 18),
1858
+ tick: currentTick.toBigInt()
1859
+ }),
1860
+ this.operator
1861
+ );
1862
+ await this.harness.submit(
1863
+ this.harness.mainchainClient.tx.vaults.setCommittedArgonots(args.committedArgonots),
1864
+ this.operator
1865
+ );
1866
+ }
1867
+ async registerCouncilSigner() {
1868
+ return this.harness.submit(
1869
+ this.harness.mainchainClient.tx.crosschainTransfer.registerCouncilSigner(
1870
+ "Ethereum",
1871
+ this.councilSigner.address,
1872
+ toArgonKeccakSignature(
1873
+ await this.councilSigner.signMessage({
1874
+ message: { raw: (0, import_viem4.toHex)(this.registrationMessage("argon/council-signer/v2")) }
1875
+ })
1876
+ )
1877
+ ),
1878
+ this.operator
1879
+ );
1880
+ }
1881
+ async forceSingleMemberCouncil() {
1882
+ await this.harness.sudoSubmit(
1883
+ this.harness.mainchainClient.tx.crosschainTransfer.forceSetGlobalIssuanceCouncil(
1884
+ "Ethereum",
1885
+ 0,
1886
+ [this.operator.address]
1887
+ )
1888
+ );
1889
+ const activeCouncilHashOption = await this.harness.mainchainClient.query.crosschainTransfer.activeGlobalIssuanceCouncilByDestinationChain(
1890
+ "Ethereum"
1891
+ );
1892
+ if (activeCouncilHashOption.isNone) {
1893
+ throw new Error("Expected active Ethereum council hash");
1894
+ }
1895
+ const activeCouncilOption = await this.harness.mainchainClient.query.crosschainTransfer.globalIssuanceCouncilByHash(
1896
+ activeCouncilHashOption.unwrap()
1897
+ );
1898
+ if (activeCouncilOption.isNone) {
1899
+ throw new Error("Expected active Ethereum council");
1900
+ }
1901
+ const activeCouncil = activeCouncilOption.unwrap();
1902
+ const currentCouncil = [...activeCouncil.members.entries()].map(([signer, member]) => ({
1903
+ signer: signer.toHex(),
1904
+ weight: member.weight.toBigInt()
1905
+ })).sort((left, right) => left.signer.localeCompare(right.signer));
1906
+ return {
1907
+ activeCouncilHash: activeCouncilHashOption.unwrap().toHex(),
1908
+ activeCouncil,
1909
+ currentCouncil: {
1910
+ signers: currentCouncil.map((member) => member.signer),
1911
+ weights: currentCouncil.map((member) => member.weight)
1912
+ }
1913
+ };
1914
+ }
1915
+ async setMinimumValue(value) {
1916
+ return this.harness.sudoSubmit(
1917
+ this.harness.mainchainClient.tx.crosschainTransfer.setMinimumMintingAuthorityValue(
1918
+ "Ethereum",
1919
+ value
1920
+ )
1921
+ );
1922
+ }
1923
+ async registerMintingAuthority(micronotCollateral) {
1924
+ return this.harness.submit(
1925
+ this.harness.mainchainClient.tx.crosschainTransfer.registerMintingAuthority(
1926
+ "Ethereum",
1927
+ this.authoritySigner.address,
1928
+ toArgonKeccakSignature(
1929
+ await this.authoritySigner.signMessage({
1930
+ message: {
1931
+ raw: (0, import_viem4.toHex)(this.registrationMessage("argon/minting-authority-signer/v2"))
1932
+ }
1933
+ })
1934
+ ),
1935
+ 0n,
1936
+ micronotCollateral
1937
+ ),
1938
+ this.operator
1939
+ );
1940
+ }
1941
+ async approveActivationQueueEntry(queueNonce = 1n) {
1942
+ const approvalQueueEntry = await this.harness.mainchainClient.query.crosschainTransfer.councilApprovalQueueByDestinationChainAndNonce(
1943
+ "Ethereum",
1944
+ queueNonce
1945
+ );
1946
+ if (approvalQueueEntry.isNone) {
1947
+ throw new Error(`Expected queue nonce ${queueNonce} to exist`);
1948
+ }
1949
+ const councilApprovalSignature = await this.councilSigner.signMessage({
1950
+ message: {
1951
+ raw: approvalQueueEntry.unwrap().approvalHash.toHex()
1952
+ }
1953
+ });
1954
+ await this.harness.submit(
1955
+ this.harness.mainchainClient.tx.crosschainTransfer.approveQueueEntries(
1956
+ "Ethereum",
1957
+ new import_mainchain7.Vec(this.harness.mainchainClient.registry, import_mainchain7.U8aFixed.with(520), [
1958
+ new import_mainchain7.U8aFixed(
1959
+ this.harness.mainchainClient.registry,
1960
+ toArgonKeccakSignature(councilApprovalSignature),
1961
+ 520
1962
+ )
1963
+ ])
1964
+ ),
1965
+ this.operator
1966
+ );
1967
+ const batch = await getReadyEthereumGatewayUpdates(
1968
+ this.harness.mainchainClient,
1969
+ this.harness.publicClient
1970
+ );
1971
+ return {
1972
+ approvalQueueEntry,
1973
+ councilApprovalSignature,
1974
+ batch
1975
+ };
1976
+ }
1977
+ async collateralizeFirstPendingTransferOut() {
1978
+ const gateway = this.requireGateway();
1979
+ const pendingRequests = await this.harness.mainchainClient.query.crosschainTransfer.pendingCollateralizationRequestsByChain(
1980
+ "Ethereum"
1981
+ );
1982
+ if (pendingRequests.length === 0) {
1983
+ throw new Error("Expected a pending collateralization request");
1984
+ }
1985
+ const pendingRequest = pendingRequests[0];
1986
+ const transferId = pendingRequest.transferId.toHex();
1987
+ const transferOption = await this.harness.mainchainClient.query.crosschainTransfer.transferOutById(transferId);
1988
+ if (transferOption.isNone) {
1989
+ throw new Error(`Expected transfer out ${transferId} to exist`);
1990
+ }
1991
+ const transfer = transferOption.unwrap();
1992
+ const transferRequest = {
1993
+ argonAccountId: transfer.argonAccountId.toHex(),
1994
+ argonTransferNonce: transfer.argonTransferNonce.toBigInt(),
1995
+ chainId: BigInt(this.harness.chain.id),
1996
+ councilHash: transfer.councilHash.toHex(),
1997
+ recipient: transfer.destinationAccount.toHex(),
1998
+ validUntilBlock: transfer.validUntilEthereumBlock.toBigInt(),
1999
+ token: gateway.argonTokenAddress,
2000
+ amount: transfer.amount.toBigInt(),
2001
+ mintingAuthorityTip: transfer.mintingAuthorityTip.toBigInt()
2002
+ };
2003
+ const micronotCollateral = transfer.amount.toBigInt();
2004
+ const collateralizationHash = import_mainchain7.EvmContracts.hashMintingGatewayMintingAuthorization(
2005
+ { chainId: BigInt(this.harness.chain.id), gatewayAddress: gateway.gatewayAddress },
2006
+ {
2007
+ request: transferRequest,
2008
+ microgonCollateral: 0n,
2009
+ micronotCollateral
2010
+ }
2011
+ );
2012
+ const collateralizationSignature = await this.authoritySigner.signMessage({
2013
+ message: {
2014
+ raw: collateralizationHash
2015
+ }
2016
+ });
2017
+ const result = await this.harness.submit(
2018
+ this.harness.mainchainClient.tx.crosschainTransfer.collateralizeTransfer(
2019
+ transferId,
2020
+ toArgonKeccakSignature(collateralizationSignature),
2021
+ 0n,
2022
+ micronotCollateral
2023
+ ),
2024
+ this.operator
2025
+ );
2026
+ return {
2027
+ pendingRequest,
2028
+ transferId,
2029
+ transferRequest,
2030
+ micronotCollateral,
2031
+ collateralizationSignature,
2032
+ result
2033
+ };
2034
+ }
2035
+ registrationMessage(prefix) {
2036
+ const prefixBytes = this.harness.mainchainClient.registry.createType("Bytes", prefix).toU8a();
2037
+ const destinationChainBytes = this.harness.mainchainClient.registry.createType("PalletCrosschainTransferSourceChain", "Ethereum").toU8a();
2038
+ const operatorAccountIdBytes = this.harness.mainchainClient.registry.createType("AccountId32", this.operator.address).toU8a();
2039
+ return concatBytes(prefixBytes, destinationChainBytes, operatorAccountIdBytes);
2040
+ }
2041
+ requireGateway() {
2042
+ if (!this.gateway) {
2043
+ throw new Error("Minting authority actor requires an attached TestMintingGateway");
2044
+ }
2045
+ return this.gateway;
2046
+ }
2047
+ };
2048
+ function concatBytes(...parts) {
2049
+ const totalLength = parts.reduce((sum, part) => sum + part.length, 0);
2050
+ const bytes = new Uint8Array(totalLength);
2051
+ let offset = 0;
2052
+ for (const part of parts) {
2053
+ bytes.set(part, offset);
2054
+ offset += part.length;
2055
+ }
2056
+ return bytes;
2057
+ }
2058
+
625
2059
  // src/index.ts
626
2060
  var toTeardown = [];
627
2061
  var proxy = null;
@@ -635,7 +2069,7 @@ async function getProxy() {
635
2069
  autoRewrite: true
636
2070
  });
637
2071
  proxy.on("error", () => null);
638
- proxyServer = http.createServer(function(req, res) {
2072
+ proxyServer = http3.createServer(function(req, res) {
639
2073
  const queryData = url.parse(req.url, true).query;
640
2074
  if (!queryData.target) {
641
2075
  res.writeHead(500, { "Content-Type": "text/plain" });
@@ -685,12 +2119,12 @@ function stringifyExt(obj) {
685
2119
  }
686
2120
  function projectRoot() {
687
2121
  if (process4.env.ARGON_PROJECT_ROOT) {
688
- return Path6.join(process4.env.ARGON_PROJECT_ROOT);
2122
+ return Path7.join(process4.env.ARGON_PROJECT_ROOT);
689
2123
  }
690
- return Path6.join(__dirname, `../../..`);
2124
+ return Path7.join(__dirname, `../../..`);
691
2125
  }
692
2126
  async function runTestScript(relativePath) {
693
- const scriptPath = Path6.resolve(projectRoot(), relativePath);
2127
+ const scriptPath = Path7.resolve(projectRoot(), relativePath);
694
2128
  return child_process4.execSync(scriptPath, { encoding: "utf8" }).trim();
695
2129
  }
696
2130
  async function getDockerPortMapping(containerName, port2) {
@@ -726,11 +2160,11 @@ function disconnectOnTeardown(closeable) {
726
2160
  return closeable;
727
2161
  }
728
2162
  function sudo() {
729
- return new import_mainchain4.Keyring({ type: "sr25519" }).createFromUri("//Alice");
2163
+ return new import_mainchain8.Keyring({ type: "sr25519" }).createFromUri("//Alice");
730
2164
  }
731
2165
  async function activateNotary(sudo2, client, notary) {
732
2166
  await notary.register(client);
733
- const txResult = await new import_mainchain4.TxSubmitter(
2167
+ const txResult = await new import_mainchain8.TxSubmitter(
734
2168
  client,
735
2169
  client.tx.sudo.sudo(client.tx.notaries.activate(notary.operator.publicKey)),
736
2170
  sudo2
@@ -739,9 +2173,13 @@ async function activateNotary(sudo2, client, notary) {
739
2173
  }
740
2174
  // Annotate the CommonJS export names for ESM import in node:
741
2175
  0 && (module.exports = {
2176
+ EthereumProofE2eHarness,
742
2177
  SKIP_E2E,
743
2178
  TestBitcoinCli,
2179
+ TestEthereum,
744
2180
  TestMainchain,
2181
+ TestMintingAuthorityActor,
2182
+ TestMintingGateway,
745
2183
  TestNotary,
746
2184
  TestOracle,
747
2185
  activateNotary,
@@ -751,12 +2189,20 @@ async function activateNotary(sudo2, client, notary) {
751
2189
  disconnectOnTeardown,
752
2190
  getDockerPortMapping,
753
2191
  getProxy,
2192
+ getReadyEthereumGatewayUpdates,
2193
+ mineLaterExecutionAnchorReceipt,
754
2194
  projectRoot,
755
2195
  runOnTeardown,
756
2196
  runTestScript,
2197
+ signGatewayPermit,
757
2198
  startNetwork,
758
2199
  stringifyExt,
759
2200
  sudo,
760
- teardown
2201
+ syncEthereumVerifierUntilAnchorCovers,
2202
+ teardown,
2203
+ toArgonKeccakSignature,
2204
+ toEvmRecoverableSignature,
2205
+ waitForExecutionReceipt,
2206
+ waitForFinalizedBeaconExecutionAtOrAbove
761
2207
  });
762
2208
  //# sourceMappingURL=index.cjs.map