@argonprotocol/testing 1.4.3-dev.1523df53 → 1.4.3-dev.25eec055

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.js CHANGED
@@ -10,9 +10,9 @@ import { Keyring as Keyring3, TxSubmitter as TxSubmitter2 } from "@argonprotocol
10
10
  import * as process4 from "process";
11
11
  import HttpProxy from "http-proxy";
12
12
  import * as child_process4 from "child_process";
13
- import * as http from "http";
13
+ import * as http2 from "http";
14
14
  import * as url from "url";
15
- import * as Path6 from "path";
15
+ import * as Path7 from "path";
16
16
 
17
17
  // src/TestNotary.ts
18
18
  import { customAlphabet } from "nanoid";
@@ -326,9 +326,20 @@ var TestMainchain = class {
326
326
  return this.address;
327
327
  }
328
328
  async client() {
329
- const client = await getClient(this.address);
330
- disconnectOnTeardown(client);
331
- return client;
329
+ let lastError;
330
+ for (let attempt = 0; attempt < 20; attempt += 1) {
331
+ try {
332
+ const client = await getClient(this.address);
333
+ disconnectOnTeardown(client);
334
+ return client;
335
+ } catch (error) {
336
+ lastError = error;
337
+ await new Promise((resolve3) => setTimeout(resolve3, 250));
338
+ }
339
+ }
340
+ throw new Error(`Unable to connect to mainchain client at ${this.address}`, {
341
+ cause: lastError instanceof Error ? lastError : void 0
342
+ });
332
343
  }
333
344
  async bootAddress() {
334
345
  const client = await this.client();
@@ -541,11 +552,484 @@ var TestOracle = class _TestOracle {
541
552
  }
542
553
  };
543
554
 
555
+ // src/TestEthereum.ts
556
+ import * as fs4 from "fs/promises";
557
+ import * as os from "os";
558
+ import * as Path5 from "path";
559
+ import { spawn as spawn4, spawnSync } from "child_process";
560
+ import { detectPort as detectPort2 } from "detect-port";
561
+
562
+ // src/ethereumContracts.ts
563
+ import { readFileSync } from "fs";
564
+ function loadArtifact(fileName) {
565
+ return JSON.parse(
566
+ readFileSync(new URL(`./ethereum-contracts/${fileName}`, import.meta.url), "utf8")
567
+ );
568
+ }
569
+ var argonTokenArtifact = loadArtifact("ArgonToken.json");
570
+ var argonotTokenArtifact = loadArtifact("ArgonotToken.json");
571
+ var mintingGatewayArtifact = loadArtifact("MintingGateway.json");
572
+ var proxyAdminArtifact = loadArtifact("ProxyAdmin.json");
573
+ var transparentUpgradeableProxyArtifact = loadArtifact("TransparentUpgradeableProxy.json");
574
+
575
+ // src/TestEthereum.ts
576
+ import { privateKeyToAccount } from "viem/accounts";
577
+ import {
578
+ encodeAbiParameters,
579
+ createPublicClient,
580
+ createWalletClient,
581
+ defineChain,
582
+ encodeFunctionData,
583
+ getAddress,
584
+ http,
585
+ keccak256,
586
+ zeroAddress
587
+ } from "viem";
588
+ var DEFAULT_KURTOSIS_BIN = "kurtosis";
589
+ var DEFAULT_ETHEREUM_PACKAGE = "github.com/ethpandaops/ethereum-package";
590
+ var DEFAULT_EL_PORT_START = 32e3;
591
+ var DEFAULT_CL_PORT_START = 33e3;
592
+ var PORT_RANGE_SIZE = 32;
593
+ var ENCLAVE_NAME_PREFIX = "argon-eth-";
594
+ var PROBE_INTERVAL_MS = 1e3;
595
+ var PROBE_TIMEOUT_MS = 6e4;
596
+ var LIGHT_CLIENT_READY_TIMEOUT_MS = 5 * 6e4;
597
+ var KURTOSIS_RUN_TIMEOUT_MS = 20 * 6e4;
598
+ var DEFAULT_SEED_ARGON_AMOUNT_BASE_UNITS = 1000000000n;
599
+ var DEFAULT_INITIAL_MICROGONS_PER_ARGONOT = 1000000n;
600
+ var ERC1967_ADMIN_SLOT = "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103";
601
+ var TestEthereum = class {
602
+ enclaveName;
603
+ kurtosisBin;
604
+ packageRef;
605
+ executionRpcUrl;
606
+ beaconApiUrl;
607
+ chainId;
608
+ #argsDir;
609
+ constructor(enclaveName = `${ENCLAVE_NAME_PREFIX}${Math.random().toString(36).slice(2, 8)}`, kurtosisBin = DEFAULT_KURTOSIS_BIN, packageRef = DEFAULT_ETHEREUM_PACKAGE) {
610
+ this.enclaveName = enclaveName;
611
+ this.kurtosisBin = kurtosisBin;
612
+ this.packageRef = packageRef;
613
+ addTeardown(this);
614
+ }
615
+ static isInstalled(kurtosisBin = DEFAULT_KURTOSIS_BIN) {
616
+ return spawnSync(kurtosisBin, ["version"], { stdio: "ignore" }).status === 0;
617
+ }
618
+ async launch(options) {
619
+ const {
620
+ consensusClient = "lighthouse",
621
+ preset = "mainnet",
622
+ secondsPerSlot,
623
+ waitForFinalization = true,
624
+ prefundedAccounts
625
+ } = options ?? {};
626
+ const elPublicPortStart = await findFreePortRange(DEFAULT_EL_PORT_START, PORT_RANGE_SIZE);
627
+ const clPublicPortStart = await findFreePortRange(DEFAULT_CL_PORT_START, PORT_RANGE_SIZE);
628
+ this.#argsDir = await fs4.mkdtemp(Path5.join(os.tmpdir(), "argon-ethereum-devnet-"));
629
+ const argsFile = Path5.join(this.#argsDir, "network-params.yaml");
630
+ await fs4.writeFile(
631
+ argsFile,
632
+ renderEthereumArgs(
633
+ elPublicPortStart,
634
+ clPublicPortStart,
635
+ consensusClient,
636
+ preset,
637
+ secondsPerSlot,
638
+ waitForFinalization,
639
+ prefundedAccounts
640
+ )
641
+ );
642
+ await runCommand(
643
+ this.kurtosisBin,
644
+ ["run", "--enclave", this.enclaveName, this.packageRef, "--args-file", argsFile],
645
+ KURTOSIS_RUN_TIMEOUT_MS
646
+ );
647
+ const executionRpc = await waitForProbe(
648
+ () => findExecutionRpcUrl(elPublicPortStart, PORT_RANGE_SIZE),
649
+ PROBE_TIMEOUT_MS
650
+ );
651
+ const beaconApi = await waitForProbe(
652
+ () => findBeaconApiUrl(clPublicPortStart, PORT_RANGE_SIZE),
653
+ PROBE_TIMEOUT_MS
654
+ );
655
+ this.executionRpcUrl = executionRpc.url;
656
+ this.beaconApiUrl = beaconApi.url;
657
+ this.chainId = executionRpc.chainId;
658
+ await waitForProbe(
659
+ () => this.getBeacon("/eth/v1/beacon/genesis"),
660
+ LIGHT_CLIENT_READY_TIMEOUT_MS
661
+ );
662
+ return {
663
+ executionRpcUrl: this.executionRpcUrl,
664
+ beaconApiUrl: this.beaconApiUrl,
665
+ chainId: this.chainId
666
+ };
667
+ }
668
+ async callExecution(method, params = []) {
669
+ const executionRpcUrl = this.executionRpcUrl;
670
+ if (!executionRpcUrl) {
671
+ throw new Error("Execution RPC URL is not available before launch");
672
+ }
673
+ const response = await fetch(executionRpcUrl, {
674
+ method: "POST",
675
+ headers: { "content-type": "application/json" },
676
+ body: JSON.stringify({
677
+ id: 1,
678
+ jsonrpc: "2.0",
679
+ method,
680
+ params
681
+ }),
682
+ signal: AbortSignal.timeout(1e4)
683
+ });
684
+ if (!response.ok) {
685
+ throw new Error(`Execution RPC request failed for ${method}: ${response.status}`);
686
+ }
687
+ const body = await response.json();
688
+ if (body.error) {
689
+ throw new Error(
690
+ `Execution RPC ${method} failed (${body.error.code ?? "unknown"}): ${body.error.message ?? "unknown error"}`
691
+ );
692
+ }
693
+ return body.result;
694
+ }
695
+ async getBeacon(path2) {
696
+ const beaconApiUrl = this.beaconApiUrl;
697
+ if (!beaconApiUrl) {
698
+ throw new Error("Beacon API URL is not available before launch");
699
+ }
700
+ const response = await fetch(new URL(path2, `${beaconApiUrl}/`), {
701
+ signal: AbortSignal.timeout(1e4)
702
+ });
703
+ if (!response.ok) {
704
+ throw new Error(`Beacon API request failed for ${path2}: ${response.status}`);
705
+ }
706
+ return await response.json();
707
+ }
708
+ async deployMintingGatewayFixture(options) {
709
+ const { executionRpcUrl, chainId } = this;
710
+ if (!executionRpcUrl || !chainId) {
711
+ throw new Error("Ethereum devnet must be launched before deploying MintingGateway fixtures");
712
+ }
713
+ const account = privateKeyToAccount(options.deployerPrivateKey);
714
+ const adminSafe = options.adminSafe ?? account.address;
715
+ const guardianSafe = options.guardianSafe ?? adminSafe;
716
+ const chain = createExecutionChain(chainId, executionRpcUrl);
717
+ const publicClient = createPublicClient({
718
+ chain,
719
+ transport: http(executionRpcUrl)
720
+ });
721
+ const walletClient = createWalletClient({
722
+ account,
723
+ chain,
724
+ transport: http(executionRpcUrl)
725
+ });
726
+ const bootstrapCouncil = {
727
+ signers: [adminSafe],
728
+ weights: [1n]
729
+ };
730
+ const bootstrapCouncilHash = keccak256(
731
+ encodeAbiParameters(
732
+ [{ type: "address[]" }, { type: "uint256[]" }],
733
+ [bootstrapCouncil.signers, bootstrapCouncil.weights]
734
+ )
735
+ );
736
+ const bootstrapImplementationAddress = await deployContract(walletClient, publicClient, {
737
+ abi: mintingGatewayArtifact.abi,
738
+ bytecode: mintingGatewayArtifact.bytecode,
739
+ args: [zeroAddress, zeroAddress]
740
+ });
741
+ const initializeData = encodeFunctionData({
742
+ abi: mintingGatewayArtifact.abi,
743
+ functionName: "initialize",
744
+ args: [
745
+ adminSafe,
746
+ guardianSafe,
747
+ bootstrapCouncilHash,
748
+ BigInt(bootstrapCouncil.signers.length),
749
+ 1n,
750
+ DEFAULT_INITIAL_MICROGONS_PER_ARGONOT
751
+ ]
752
+ });
753
+ const gatewayAddress = await deployContract(walletClient, publicClient, {
754
+ abi: transparentUpgradeableProxyArtifact.abi,
755
+ bytecode: transparentUpgradeableProxyArtifact.bytecode,
756
+ args: [bootstrapImplementationAddress, adminSafe, initializeData]
757
+ });
758
+ const proxyAdminAddress = getAddressFromStorage(
759
+ await publicClient.getStorageAt({
760
+ address: gatewayAddress,
761
+ slot: ERC1967_ADMIN_SLOT
762
+ })
763
+ );
764
+ const argonTokenAddress = await deployContract(walletClient, publicClient, {
765
+ abi: argonTokenArtifact.abi,
766
+ bytecode: argonTokenArtifact.bytecode,
767
+ args: [gatewayAddress]
768
+ });
769
+ const argonotTokenAddress = await deployContract(walletClient, publicClient, {
770
+ abi: argonotTokenArtifact.abi,
771
+ bytecode: argonotTokenArtifact.bytecode,
772
+ args: [gatewayAddress]
773
+ });
774
+ const finalImplementationAddress = await deployContract(walletClient, publicClient, {
775
+ abi: mintingGatewayArtifact.abi,
776
+ bytecode: mintingGatewayArtifact.bytecode,
777
+ args: [argonTokenAddress, argonotTokenAddress]
778
+ });
779
+ const upgradeHash = await walletClient.sendTransaction({
780
+ to: proxyAdminAddress,
781
+ data: encodeFunctionData({
782
+ abi: proxyAdminArtifact.abi,
783
+ functionName: "upgradeAndCall",
784
+ args: [gatewayAddress, finalImplementationAddress, "0x"]
785
+ })
786
+ });
787
+ const upgradeReceipt = await waitForExecutionReceipt(publicClient, upgradeHash);
788
+ if (upgradeReceipt.status !== "success") {
789
+ throw new Error("MintingGateway proxy upgrade failed");
790
+ }
791
+ if (options.seedArgonRecipient) {
792
+ const mintHash = await walletClient.sendTransaction({
793
+ to: gatewayAddress,
794
+ data: encodeFunctionData({
795
+ abi: mintingGatewayArtifact.abi,
796
+ functionName: "migrate",
797
+ args: [
798
+ {
799
+ recipients: [options.seedArgonRecipient],
800
+ amounts: [options.seedArgonAmountBaseUnits ?? DEFAULT_SEED_ARGON_AMOUNT_BASE_UNITS]
801
+ },
802
+ {
803
+ recipients: [],
804
+ amounts: []
805
+ }
806
+ ]
807
+ })
808
+ });
809
+ const mintReceipt = await waitForExecutionReceipt(publicClient, mintHash);
810
+ if (mintReceipt.status !== "success") {
811
+ throw new Error("MintingGateway migrate failed");
812
+ }
813
+ }
814
+ return {
815
+ argonTokenAddress,
816
+ argonotTokenAddress,
817
+ gatewayAddress
818
+ };
819
+ }
820
+ async teardown() {
821
+ if (this.#argsDir) {
822
+ await fs4.rm(this.#argsDir, { recursive: true, force: true });
823
+ this.#argsDir = void 0;
824
+ }
825
+ await runCommand(this.kurtosisBin, ["enclave", "rm", "-f", this.enclaveName], 6e4, true);
826
+ }
827
+ };
828
+ async function deployContract(walletClient, publicClient, request) {
829
+ const hash = await walletClient.deployContract({
830
+ ...request,
831
+ account: walletClient.account,
832
+ chain: walletClient.chain
833
+ });
834
+ const receipt = await waitForExecutionReceipt(publicClient, hash);
835
+ if (receipt.status !== "success" || !receipt.contractAddress) {
836
+ throw new Error(`Contract deployment failed for ${request.bytecode.slice(0, 10)}`);
837
+ }
838
+ return receipt.contractAddress;
839
+ }
840
+ function getAddressFromStorage(value) {
841
+ if (!value || value === "0x") {
842
+ throw new Error("Missing proxy admin address in ERC1967 admin slot");
843
+ }
844
+ return getAddress(`0x${value.slice(-40)}`);
845
+ }
846
+ function renderEthereumArgs(elPublicPortStart, clPublicPortStart, consensusClient, preset, secondsPerSlot, waitForFinalization, prefundedAccounts) {
847
+ const lines = [
848
+ "participants:",
849
+ " - el_type: geth",
850
+ ` cl_type: ${consensusClient}`,
851
+ "network_params:",
852
+ " network: kurtosis",
853
+ ` preset: ${preset}`,
854
+ ...secondsPerSlot ? [` seconds_per_slot: ${secondsPerSlot}`] : [],
855
+ ...prefundedAccounts && Object.keys(prefundedAccounts).length > 0 ? [` prefunded_accounts: '${JSON.stringify(prefundedAccounts)}'`] : [],
856
+ "additional_services: []",
857
+ `wait_for_finalization: ${waitForFinalization ? "true" : "false"}`,
858
+ "global_log_level: warn",
859
+ "port_publisher:",
860
+ " el:",
861
+ " enabled: true",
862
+ ` public_port_start: ${elPublicPortStart}`,
863
+ " cl:",
864
+ " enabled: true",
865
+ ` public_port_start: ${clPublicPortStart}`
866
+ ];
867
+ lines.push("");
868
+ return lines.join("\n");
869
+ }
870
+ async function findExecutionRpcUrl(portStart, rangeSize) {
871
+ for (let port2 = portStart; port2 < portStart + rangeSize; port2 += 1) {
872
+ const url2 = `http://127.0.0.1:${port2}`;
873
+ const response = await fetchJsonRpc(url2, "eth_chainId");
874
+ if (typeof response === "string") {
875
+ return { url: url2, chainId: response };
876
+ }
877
+ }
878
+ throw new Error(
879
+ `Unable to find an execution RPC endpoint in ${portStart}-${portStart + rangeSize - 1}`
880
+ );
881
+ }
882
+ async function findBeaconApiUrl(portStart, rangeSize) {
883
+ for (let port2 = portStart; port2 < portStart + rangeSize; port2 += 1) {
884
+ const url2 = `http://127.0.0.1:${port2}`;
885
+ try {
886
+ const response = await fetch(new URL("/eth/v1/node/version", `${url2}/`), {
887
+ signal: AbortSignal.timeout(2e3)
888
+ });
889
+ if (!response.ok) {
890
+ continue;
891
+ }
892
+ const body = await response.json();
893
+ if (body.data?.version) {
894
+ return { url: url2 };
895
+ }
896
+ } catch {
897
+ }
898
+ }
899
+ throw new Error(
900
+ `Unable to find a Beacon API endpoint in ${portStart}-${portStart + rangeSize - 1}`
901
+ );
902
+ }
903
+ async function fetchJsonRpc(url2, method) {
904
+ try {
905
+ const response = await fetch(url2, {
906
+ method: "POST",
907
+ headers: { "content-type": "application/json" },
908
+ body: JSON.stringify({
909
+ id: 1,
910
+ jsonrpc: "2.0",
911
+ method,
912
+ params: []
913
+ }),
914
+ signal: AbortSignal.timeout(2e3)
915
+ });
916
+ if (!response.ok) {
917
+ return null;
918
+ }
919
+ const body = await response.json();
920
+ return body.result ?? null;
921
+ } catch {
922
+ return null;
923
+ }
924
+ }
925
+ function createExecutionChain(chainId, executionRpcUrl) {
926
+ return defineChain({
927
+ id: Number.parseInt(chainId, 16),
928
+ name: "argon-test-ethereum",
929
+ nativeCurrency: {
930
+ name: "Ether",
931
+ symbol: "ETH",
932
+ decimals: 18
933
+ },
934
+ rpcUrls: {
935
+ default: {
936
+ http: [executionRpcUrl]
937
+ }
938
+ }
939
+ });
940
+ }
941
+ async function findFreePortRange(start, size) {
942
+ for (let candidate = start; candidate < start + 1e3; candidate += size) {
943
+ const ports = Array.from({ length: size }, (_, index) => candidate + index);
944
+ const results = await Promise.all(ports.map((port2) => detectPort2(port2)));
945
+ if (results.every((resolvedPort, index) => resolvedPort === ports[index])) {
946
+ return candidate;
947
+ }
948
+ }
949
+ throw new Error(`Unable to find a free port range starting near ${start}`);
950
+ }
951
+ async function waitForProbe(probe, timeoutMs) {
952
+ const start = Date.now();
953
+ let lastError;
954
+ while (Date.now() - start < timeoutMs) {
955
+ try {
956
+ return await probe();
957
+ } catch (error) {
958
+ lastError = error;
959
+ await delay(PROBE_INTERVAL_MS);
960
+ }
961
+ }
962
+ throw lastError instanceof Error ? lastError : new Error("Timed out waiting for probe");
963
+ }
964
+ async function waitForExecutionReceipt(publicClient, hash) {
965
+ const start = Date.now();
966
+ let lastError;
967
+ while (Date.now() - start < 12e4) {
968
+ try {
969
+ const receipt = await publicClient.getTransactionReceipt({ hash });
970
+ if (receipt) {
971
+ return receipt;
972
+ }
973
+ } catch (error) {
974
+ const errorText = error instanceof Error ? [
975
+ error.message,
976
+ "details" in error && typeof error.details === "string" ? error.details : void 0
977
+ ].filter(Boolean).join(" ") : String(error);
978
+ if (!errorText.includes("indexing is in progress") && !errorText.includes("Transaction receipt with hash") && !errorText.includes("could not be found")) {
979
+ throw error;
980
+ }
981
+ lastError = error instanceof Error ? error : new Error(errorText);
982
+ }
983
+ await delay(500);
984
+ }
985
+ throw lastError ?? new Error(`Timed out waiting for execution receipt ${hash}`);
986
+ }
987
+ async function runCommand(command, args, timeoutMs, allowFailure = false) {
988
+ await new Promise((resolve3, reject) => {
989
+ const child = spawn4(command, args, {
990
+ stdio: ["ignore", "pipe", "pipe"]
991
+ });
992
+ let stdout = "";
993
+ let stderr = "";
994
+ const timeout = setTimeout(() => {
995
+ child.kill("SIGTERM");
996
+ reject(new Error(`Command timed out: ${command} ${args.join(" ")}`));
997
+ }, timeoutMs);
998
+ child.stdout?.setEncoding("utf8");
999
+ child.stderr?.setEncoding("utf8");
1000
+ child.stdout?.on("data", (chunk) => {
1001
+ stdout += chunk;
1002
+ });
1003
+ child.stderr?.on("data", (chunk) => {
1004
+ stderr += chunk;
1005
+ });
1006
+ child.on("error", (error) => {
1007
+ clearTimeout(timeout);
1008
+ reject(error);
1009
+ });
1010
+ child.on("exit", (code) => {
1011
+ clearTimeout(timeout);
1012
+ if (code === 0 || allowFailure) {
1013
+ resolve3();
1014
+ return;
1015
+ }
1016
+ reject(
1017
+ new Error(
1018
+ [`Command failed: ${command} ${args.join(" ")}`, stdout.trim(), stderr.trim()].filter(Boolean).join("\n")
1019
+ )
1020
+ );
1021
+ });
1022
+ });
1023
+ }
1024
+ async function delay(ms) {
1025
+ await new Promise((resolve3) => setTimeout(resolve3, ms));
1026
+ }
1027
+
544
1028
  // src/TestNetwork.ts
545
1029
  import * as docker from "docker-compose";
546
- import * as Path5 from "path";
1030
+ import * as Path6 from "path";
547
1031
  async function startNetwork(testName, options) {
548
- const config = Path5.join(__dirname, `dev.docker-compose.yml`);
1032
+ const config = Path6.join(__dirname, `dev.docker-compose.yml`);
549
1033
  const env4 = {
550
1034
  VERSION: "dev",
551
1035
  ARGON_CHAIN: "dev-docker",
@@ -590,7 +1074,7 @@ async function getProxy() {
590
1074
  autoRewrite: true
591
1075
  });
592
1076
  proxy.on("error", () => null);
593
- proxyServer = http.createServer(function(req, res) {
1077
+ proxyServer = http2.createServer(function(req, res) {
594
1078
  const queryData = url.parse(req.url, true).query;
595
1079
  if (!queryData.target) {
596
1080
  res.writeHead(500, { "Content-Type": "text/plain" });
@@ -640,12 +1124,12 @@ function stringifyExt(obj) {
640
1124
  }
641
1125
  function projectRoot() {
642
1126
  if (process4.env.ARGON_PROJECT_ROOT) {
643
- return Path6.join(process4.env.ARGON_PROJECT_ROOT);
1127
+ return Path7.join(process4.env.ARGON_PROJECT_ROOT);
644
1128
  }
645
- return Path6.join(__dirname, `../../..`);
1129
+ return Path7.join(__dirname, `../../..`);
646
1130
  }
647
1131
  async function runTestScript(relativePath) {
648
- const scriptPath = Path6.resolve(projectRoot(), relativePath);
1132
+ const scriptPath = Path7.resolve(projectRoot(), relativePath);
649
1133
  return child_process4.execSync(scriptPath, { encoding: "utf8" }).trim();
650
1134
  }
651
1135
  async function getDockerPortMapping(containerName, port2) {
@@ -695,16 +1179,19 @@ async function activateNotary(sudo2, client, notary) {
695
1179
  export {
696
1180
  SKIP_E2E,
697
1181
  TestBitcoinCli,
1182
+ TestEthereum,
698
1183
  TestMainchain,
699
1184
  TestNotary,
700
1185
  TestOracle,
701
1186
  activateNotary,
702
1187
  addTeardown,
1188
+ argonTokenArtifact,
703
1189
  cleanHostForDocker,
704
1190
  closeOnTeardown,
705
1191
  disconnectOnTeardown,
706
1192
  getDockerPortMapping,
707
1193
  getProxy,
1194
+ mintingGatewayArtifact,
708
1195
  projectRoot,
709
1196
  runOnTeardown,
710
1197
  runTestScript,