@argonprotocol/testing 1.4.3-dev.4408f4ff → 1.4.3-dev.4544e954

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,53 +30,147 @@ 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,
35
36
  TestEthereum: () => TestEthereum,
36
37
  TestMainchain: () => TestMainchain,
38
+ TestMintingAuthorityActor: () => TestMintingAuthorityActor,
39
+ TestMintingGateway: () => TestMintingGateway,
37
40
  TestNotary: () => TestNotary,
38
41
  TestOracle: () => TestOracle,
39
42
  activateNotary: () => activateNotary,
40
43
  addTeardown: () => addTeardown,
41
- argonTokenArtifact: () => argonTokenArtifact,
42
44
  cleanHostForDocker: () => cleanHostForDocker,
43
45
  closeOnTeardown: () => closeOnTeardown,
44
46
  disconnectOnTeardown: () => disconnectOnTeardown,
45
47
  getDockerPortMapping: () => getDockerPortMapping,
46
48
  getProxy: () => getProxy,
47
- mintingGatewayArtifact: () => mintingGatewayArtifact,
49
+ getReadyEthereumGatewayUpdates: () => getReadyEthereumGatewayUpdates,
50
+ mineLaterExecutionAnchorReceipt: () => mineLaterExecutionAnchorReceipt,
48
51
  projectRoot: () => projectRoot,
49
52
  runOnTeardown: () => runOnTeardown,
50
53
  runTestScript: () => runTestScript,
54
+ signGatewayPermit: () => signGatewayPermit,
51
55
  startNetwork: () => startNetwork,
52
56
  stringifyExt: () => stringifyExt,
53
57
  sudo: () => sudo,
54
- teardown: () => teardown
58
+ syncEthereumVerifierUntilAnchorCovers: () => syncEthereumVerifierUntilAnchorCovers,
59
+ teardown: () => teardown,
60
+ toArgonKeccakSignature: () => toArgonKeccakSignature,
61
+ toEvmRecoverableSignature: () => toEvmRecoverableSignature,
62
+ waitForExecutionReceipt: () => waitForExecutionReceipt2,
63
+ waitForFinalizedBeaconExecutionAtOrAbove: () => waitForFinalizedBeaconExecutionAtOrAbove
55
64
  });
56
65
  module.exports = __toCommonJS(index_exports);
57
-
58
- // node_modules/tsup/assets/cjs_shims.js
59
- var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.src || new URL("main.js", document.baseURI).href;
60
- var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
61
-
62
- // src/index.ts
63
- var import_mainchain4 = require("@argonprotocol/mainchain");
64
- var process4 = __toESM(require("process"), 1);
65
- var import_http_proxy = __toESM(require("http-proxy"), 1);
66
- var child_process4 = __toESM(require("child_process"), 1);
67
- var http2 = __toESM(require("http"), 1);
68
- var url = __toESM(require("url"), 1);
69
- var Path7 = __toESM(require("path"), 1);
66
+ var import_mainchain8 = require("@argonprotocol/mainchain");
70
67
 
71
68
  // src/TestNotary.ts
72
69
  var import_nanoid = require("nanoid");
73
70
  var import_pg = __toESM(require("pg"), 1);
74
- var child_process = __toESM(require("child_process"), 1);
71
+ var child_process2 = __toESM(require("child_process"), 1);
75
72
  var import_mainchain = require("@argonprotocol/mainchain");
76
73
  var fs = __toESM(require("fs"), 1);
77
74
  var readline = __toESM(require("readline"), 1);
75
+
76
+ // src/support.ts
78
77
  var process2 = __toESM(require("process"), 1);
78
+ var import_http_proxy = __toESM(require("http-proxy"), 1);
79
+ var child_process = __toESM(require("child_process"), 1);
80
+ var http = __toESM(require("http"), 1);
81
+ var url = __toESM(require("url"), 1);
79
82
  var Path = __toESM(require("path"), 1);
83
+ var toTeardown = [];
84
+ var proxy = null;
85
+ var proxyServer = null;
86
+ var SKIP_E2E = process2.env.SKIP_E2E === "true" || process2.env.SKIP_E2E === "1";
87
+ async function getProxy() {
88
+ if (!proxy) {
89
+ proxy = import_http_proxy.default.createProxyServer({
90
+ changeOrigin: true,
91
+ ws: true,
92
+ autoRewrite: true
93
+ });
94
+ proxy.on("error", () => null);
95
+ proxyServer = http.createServer(function(req, res) {
96
+ const queryData = url.parse(req.url, true).query;
97
+ if (!queryData.target) {
98
+ res.writeHead(500, { "Content-Type": "text/plain" });
99
+ res.end("Target parameter is required");
100
+ return;
101
+ }
102
+ console.log("Proxying http request", queryData.target);
103
+ proxy?.web(req, res, { target: queryData.target });
104
+ });
105
+ proxyServer.on("upgrade", function(req, clientSocket, head) {
106
+ const queryData = url.parse(req.url, true).query;
107
+ const target = url.parse(queryData.target);
108
+ proxy?.ws(req, clientSocket, head, {
109
+ target: target.href,
110
+ ws: true
111
+ });
112
+ clientSocket.on("error", console.error);
113
+ });
114
+ await new Promise((resolve3) => proxyServer.listen(0, resolve3));
115
+ toTeardown.push({
116
+ teardown: () => new Promise((resolve3) => {
117
+ proxy?.close();
118
+ proxyServer?.close((_) => null);
119
+ proxy = null;
120
+ proxyServer = null;
121
+ resolve3();
122
+ })
123
+ });
124
+ }
125
+ const port2 = proxyServer.address().port;
126
+ return `ws://host.docker.internal:${port2}`;
127
+ }
128
+ function projectRoot() {
129
+ if (process2.env.ARGON_PROJECT_ROOT) {
130
+ return Path.join(process2.env.ARGON_PROJECT_ROOT);
131
+ }
132
+ return Path.join(__dirname, `../../..`);
133
+ }
134
+ async function runTestScript(relativePath) {
135
+ const scriptPath = Path.resolve(projectRoot(), relativePath);
136
+ return child_process.execSync(scriptPath, { encoding: "utf8" }).trim();
137
+ }
138
+ async function getDockerPortMapping(containerName, port2) {
139
+ return child_process.execSync(`docker port ${containerName} ${port2}`, { encoding: "utf8" }).trim().split(":").pop();
140
+ }
141
+ async function teardown() {
142
+ for (const t of toTeardown) {
143
+ try {
144
+ await t.teardown().catch(console.error);
145
+ } catch {
146
+ }
147
+ }
148
+ toTeardown.length = 0;
149
+ }
150
+ function cleanHostForDocker(host, replacer = "host.docker.internal") {
151
+ if (process2.env.ARGON_USE_DOCKER_BINS) {
152
+ return host.replace("localhost", replacer).replace("127.0.0.1", replacer).replace("0.0.0.0", replacer);
153
+ }
154
+ return host;
155
+ }
156
+ function addTeardown(teardownable) {
157
+ toTeardown.push(teardownable);
158
+ }
159
+ function runOnTeardown(teardown2) {
160
+ addTeardown({ teardown: teardown2 });
161
+ }
162
+ function closeOnTeardown(closeable) {
163
+ addTeardown({ teardown: () => closeable.close() });
164
+ return closeable;
165
+ }
166
+ function disconnectOnTeardown(closeable) {
167
+ addTeardown({ teardown: () => closeable.disconnect() });
168
+ return closeable;
169
+ }
170
+
171
+ // src/TestNotary.ts
172
+ var process3 = __toESM(require("process"), 1);
173
+ var Path2 = __toESM(require("path"), 1);
80
174
  var { Client: PgClient } = import_pg.default;
81
175
  var nanoid = (0, import_nanoid.customAlphabet)("0123456789abcdefghijklmnopqrstuvwxyz", 4);
82
176
  function createUid() {
@@ -102,7 +196,7 @@ var TestNotary = class {
102
196
  return `ws://${this.ip}:${this.port}`;
103
197
  }
104
198
  constructor(dbConnectionString) {
105
- this.#dbConnectionString = dbConnectionString ?? process2.env.NOTARY_DB_URL ?? "postgres://postgres:postgres@localhost:5432";
199
+ this.#dbConnectionString = dbConnectionString ?? process3.env.NOTARY_DB_URL ?? "postgres://postgres:postgres@localhost:5432";
106
200
  addTeardown(this);
107
201
  }
108
202
  /**
@@ -114,10 +208,10 @@ var TestNotary = class {
114
208
  this.registeredPublicKey = new import_mainchain.Keyring({ type: "ed25519" }).createFromUri(
115
209
  "//Ferdie//notary"
116
210
  ).publicKey;
117
- let notaryPath = pathToNotaryBin ?? Path.join(projectRoot(), "target/debug/argon-notary");
118
- if (process2.env.ARGON_USE_DOCKER_BINS) {
211
+ let notaryPath = pathToNotaryBin ?? Path2.join(projectRoot(), "target/debug/argon-notary");
212
+ if (process3.env.ARGON_USE_DOCKER_BINS) {
119
213
  this.containerName = "notary_" + uuid;
120
- const addHost = process2.env.ADD_DOCKER_HOST ? ` --add-host=host.docker.internal:host-gateway` : "";
214
+ const addHost = process3.env.ADD_DOCKER_HOST ? ` --add-host=host.docker.internal:host-gateway` : "";
121
215
  notaryPath = `docker run --rm -p=0:9925${addHost} --name=${this.containerName} -e RUST_LOG=warn ghcr.io/argonprotocol/argon-notary:dev`;
122
216
  this.#dbConnectionString = cleanHostForDocker(this.#dbConnectionString);
123
217
  } else if (!fs.existsSync(notaryPath)) {
@@ -140,7 +234,7 @@ var TestNotary = class {
140
234
  } finally {
141
235
  await client.end();
142
236
  }
143
- const result = child_process.execSync(
237
+ const result = child_process2.execSync(
144
238
  `${notaryPath} migrate --db-url ${this.#dbConnectionString}/${this.#dbName}`,
145
239
  {
146
240
  encoding: "utf-8"
@@ -163,18 +257,18 @@ var TestNotary = class {
163
257
  `--archive-bucket=${bucketName}`,
164
258
  `--operator-address=${this.operator.address}`
165
259
  ];
166
- if (process2.env.ARGON_USE_DOCKER_BINS) {
167
- process2.env.AWS_S3_ENDPOINT = "http://host.docker.internal:9000";
260
+ if (process3.env.ARGON_USE_DOCKER_BINS) {
261
+ process3.env.AWS_S3_ENDPOINT = "http://host.docker.internal:9000";
168
262
  execArgs.unshift(...notaryPath.replace("docker run", "run").split(" "));
169
263
  execArgs.push("-b=0.0.0.0:9925");
170
264
  notaryPath = "docker";
171
265
  }
172
- if (process2.env.AWS_S3_ENDPOINT) {
173
- execArgs.push(`--archive-endpoint=${process2.env.AWS_S3_ENDPOINT}`);
266
+ if (process3.env.AWS_S3_ENDPOINT) {
267
+ execArgs.push(`--archive-endpoint=${process3.env.AWS_S3_ENDPOINT}`);
174
268
  }
175
- this.#childProcess = child_process.spawn(notaryPath, execArgs, {
269
+ this.#childProcess = child_process2.spawn(notaryPath, execArgs, {
176
270
  stdio: ["ignore", "pipe", "pipe"],
177
- env: { ...process2.env, RUST_LOG: "warn" }
271
+ env: { ...process3.env, RUST_LOG: "warn" }
178
272
  });
179
273
  this.#childProcess.stdout.setEncoding("utf8");
180
274
  this.#childProcess.stderr.setEncoding("utf8");
@@ -231,7 +325,7 @@ var TestNotary = class {
231
325
  }
232
326
  if (this.containerName) {
233
327
  try {
234
- child_process.execSync(`docker rm -f ${this.containerName}`);
328
+ child_process2.execSync(`docker rm -f ${this.containerName}`);
235
329
  } catch {
236
330
  }
237
331
  }
@@ -251,14 +345,14 @@ var TestNotary = class {
251
345
  // src/TestMainchain.ts
252
346
  var fs2 = __toESM(require("fs"), 1);
253
347
  var import_node_child_process = require("child_process");
254
- var Path2 = __toESM(require("path"), 1);
348
+ var Path3 = __toESM(require("path"), 1);
255
349
  var readline2 = __toESM(require("readline"), 1);
256
350
  var import_detect_port = require("detect-port");
257
351
  var import_nanoid2 = require("nanoid");
258
352
  var lockfile = __toESM(require("proper-lockfile"), 1);
259
353
  var import_mainchain2 = require("@argonprotocol/mainchain");
260
354
  var nanoid2 = (0, import_nanoid2.customAlphabet)("0123456789abcdefghijklmnopqrstuvwxyz", 4);
261
- var lockPath = Path2.join(process.cwd(), ".port-lock");
355
+ var lockPath = Path3.join(process.cwd(), ".port-lock");
262
356
  var TestMainchain = class {
263
357
  ip = "127.0.0.1";
264
358
  port;
@@ -281,8 +375,8 @@ var TestMainchain = class {
281
375
  return `ws://${this.ip}:${this.port}`;
282
376
  }
283
377
  constructor(binPath) {
284
- this.#binPath = binPath ?? Path2.join(projectRoot(), `target/debug/argon-node`);
285
- this.#binPath = Path2.resolve(this.#binPath);
378
+ this.#binPath = binPath ?? Path3.join(projectRoot(), `target/debug/argon-node`);
379
+ this.#binPath = Path3.resolve(this.#binPath);
286
380
  if (!process.env.ARGON_USE_DOCKER_BINS && !fs2.existsSync(this.#binPath)) {
287
381
  throw new Error(`Mainchain binary not found at ${this.#binPath}`);
288
382
  }
@@ -443,7 +537,7 @@ var TestMainchain = class {
443
537
  const release = await lockfile.lock(lockPath, { retries: 10 });
444
538
  try {
445
539
  rpcPort = await (0, import_detect_port.detectPort)();
446
- const path = (0, import_node_child_process.execSync)(Path2.join(projectRoot(), `target/debug/argon-testing-bitcoin`), {
540
+ const path = (0, import_node_child_process.execSync)(Path3.join(projectRoot(), `target/debug/argon-testing-bitcoin`), {
447
541
  encoding: "utf8"
448
542
  }).trim();
449
543
  const tmpDir = fs2.mkdtempSync("/tmp/argon-bitcoin-" + this.uuid);
@@ -531,16 +625,16 @@ var BitcoinRpcClient = class {
531
625
  };
532
626
 
533
627
  // src/TestBitcoinCli.ts
534
- var child_process2 = __toESM(require("child_process"), 1);
535
- var Path3 = __toESM(require("path"), 1);
628
+ var child_process3 = __toESM(require("child_process"), 1);
629
+ var Path4 = __toESM(require("path"), 1);
536
630
  var TestBitcoinCli = class {
537
631
  /**
538
632
  * Returns the localhost address of the notary (NOTE: not accessible from containers)
539
633
  */
540
634
  static run(command) {
541
- const binPath = Path3.join(`${projectRoot()}`, "target/debug/argon-bitcoin-cli");
635
+ const binPath = Path4.join(`${projectRoot()}`, "target/debug/argon-bitcoin-cli");
542
636
  try {
543
- return child_process2.execSync(`${binPath} ${command}`, {
637
+ return child_process3.execSync(`${binPath} ${command}`, {
544
638
  encoding: "utf8"
545
639
  }).trim();
546
640
  } catch (e) {
@@ -552,12 +646,12 @@ var TestBitcoinCli = class {
552
646
  };
553
647
 
554
648
  // src/TestOracle.ts
555
- var child_process3 = __toESM(require("child_process"), 1);
649
+ var child_process4 = __toESM(require("child_process"), 1);
556
650
  var import_mainchain3 = require("@argonprotocol/mainchain");
557
651
  var fs3 = __toESM(require("fs"), 1);
558
652
  var readline3 = __toESM(require("readline"), 1);
559
- var process3 = __toESM(require("process"), 1);
560
- var Path4 = __toESM(require("path"), 1);
653
+ var process4 = __toESM(require("process"), 1);
654
+ var Path5 = __toESM(require("path"), 1);
561
655
  var TestOracle = class _TestOracle {
562
656
  static BitcoinOperator = "//Dave";
563
657
  static PriceIndexOperator = "//Eve";
@@ -572,7 +666,7 @@ var TestOracle = class _TestOracle {
572
666
  const { pathToBin, mainchainUrl, bitcoinRpcUrl } = options;
573
667
  const operatorSuri = service == "bitcoin" ? _TestOracle.BitcoinOperator : _TestOracle.PriceIndexOperator;
574
668
  this.operator = new import_mainchain3.Keyring({ type: "sr25519" }).createFromUri(operatorSuri);
575
- const binPath = pathToBin ?? Path4.join(projectRoot(), "target/debug/argon-oracle");
669
+ const binPath = pathToBin ?? Path5.join(projectRoot(), "target/debug/argon-oracle");
576
670
  if (!fs3.existsSync(binPath)) {
577
671
  throw new Error(`Oracle binary not found at ${binPath}`);
578
672
  }
@@ -584,9 +678,9 @@ var TestOracle = class _TestOracle {
584
678
  }
585
679
  execArgs.push("--bitcoin-rpc-url", bitcoinRpcUrl);
586
680
  }
587
- this.#childProcess = child_process3.spawn(binPath, execArgs, {
681
+ this.#childProcess = child_process4.spawn(binPath, execArgs, {
588
682
  stdio: ["ignore", "pipe", "pipe"],
589
- env: { ...process3.env, RUST_LOG: "info", ...options.env }
683
+ env: { ...process4.env, RUST_LOG: "info", ...options.env }
590
684
  });
591
685
  this.#childProcess.stdout.setEncoding("utf8");
592
686
  this.#childProcess.stderr.setEncoding("utf8");
@@ -609,26 +703,20 @@ var TestOracle = class _TestOracle {
609
703
  // src/TestEthereum.ts
610
704
  var fs4 = __toESM(require("fs/promises"), 1);
611
705
  var os = __toESM(require("os"), 1);
612
- var Path5 = __toESM(require("path"), 1);
706
+ var Path6 = __toESM(require("path"), 1);
613
707
  var import_node_child_process2 = require("child_process");
614
708
  var import_detect_port2 = require("detect-port");
615
-
616
- // src/ethereumContracts.ts
617
- var import_node_fs = require("fs");
618
- function loadArtifact(fileName) {
619
- return JSON.parse(
620
- (0, import_node_fs.readFileSync)(new URL(`./ethereum-contracts/${fileName}`, importMetaUrl), "utf8")
621
- );
622
- }
623
- var argonTokenArtifact = loadArtifact("ArgonToken.json");
624
- var argonotTokenArtifact = loadArtifact("ArgonotToken.json");
625
- var mintingGatewayArtifact = loadArtifact("MintingGateway.json");
626
- var proxyAdminArtifact = loadArtifact("ProxyAdmin.json");
627
- var transparentUpgradeableProxyArtifact = loadArtifact("TransparentUpgradeableProxy.json");
628
-
629
- // src/TestEthereum.ts
709
+ var import_mainchain4 = require("@argonprotocol/mainchain");
630
710
  var import_accounts = require("viem/accounts");
631
711
  var import_viem = require("viem");
712
+ var {
713
+ argonTokenArtifact,
714
+ argonotTokenArtifact,
715
+ hashMintingGatewayGlobalIssuanceCouncil,
716
+ mintingGatewayArtifact,
717
+ proxyAdminArtifact,
718
+ transparentUpgradeableProxyArtifact
719
+ } = import_mainchain4.EvmContracts;
632
720
  var DEFAULT_KURTOSIS_BIN = "kurtosis";
633
721
  var DEFAULT_ETHEREUM_PACKAGE = "github.com/ethpandaops/ethereum-package";
634
722
  var DEFAULT_EL_PORT_START = 32e3;
@@ -640,6 +728,7 @@ var PROBE_TIMEOUT_MS = 6e4;
640
728
  var LIGHT_CLIENT_READY_TIMEOUT_MS = 5 * 6e4;
641
729
  var KURTOSIS_RUN_TIMEOUT_MS = 20 * 6e4;
642
730
  var DEFAULT_SEED_ARGON_AMOUNT_BASE_UNITS = 1000000000n;
731
+ var DEFAULT_INITIAL_MICROGONS_PER_ARGONOT = 1000000n;
643
732
  var ERC1967_ADMIN_SLOT = "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103";
644
733
  var TestEthereum = class {
645
734
  enclaveName;
@@ -668,8 +757,8 @@ var TestEthereum = class {
668
757
  } = options ?? {};
669
758
  const elPublicPortStart = await findFreePortRange(DEFAULT_EL_PORT_START, PORT_RANGE_SIZE);
670
759
  const clPublicPortStart = await findFreePortRange(DEFAULT_CL_PORT_START, PORT_RANGE_SIZE);
671
- this.#argsDir = await fs4.mkdtemp(Path5.join(os.tmpdir(), "argon-ethereum-devnet-"));
672
- const argsFile = Path5.join(this.#argsDir, "network-params.yaml");
760
+ this.#argsDir = await fs4.mkdtemp(Path6.join(os.tmpdir(), "argon-ethereum-devnet-"));
761
+ const argsFile = Path6.join(this.#argsDir, "network-params.yaml");
673
762
  await fs4.writeFile(
674
763
  argsFile,
675
764
  renderEthereumArgs(
@@ -766,6 +855,15 @@ var TestEthereum = class {
766
855
  chain,
767
856
  transport: (0, import_viem.http)(executionRpcUrl)
768
857
  });
858
+ const bootstrapCouncil = {
859
+ signers: [adminSafe],
860
+ weights: [1n]
861
+ };
862
+ const initialMicrogonsPerArgonot = options.initialMicrogonsPerArgonot ?? DEFAULT_INITIAL_MICROGONS_PER_ARGONOT;
863
+ const bootstrapCouncilHash = hashMintingGatewayGlobalIssuanceCouncil({
864
+ ...bootstrapCouncil,
865
+ epochMicrogonsPerArgonot: initialMicrogonsPerArgonot
866
+ });
769
867
  const bootstrapImplementationAddress = await deployContract(walletClient, publicClient, {
770
868
  abi: mintingGatewayArtifact.abi,
771
869
  bytecode: mintingGatewayArtifact.bytecode,
@@ -774,7 +872,14 @@ var TestEthereum = class {
774
872
  const initializeData = (0, import_viem.encodeFunctionData)({
775
873
  abi: mintingGatewayArtifact.abi,
776
874
  functionName: "initialize",
777
- args: [adminSafe, guardianSafe]
875
+ args: [
876
+ adminSafe,
877
+ guardianSafe,
878
+ bootstrapCouncilHash,
879
+ BigInt(bootstrapCouncil.signers.length),
880
+ 1n,
881
+ initialMicrogonsPerArgonot
882
+ ]
778
883
  });
779
884
  const gatewayAddress = await deployContract(walletClient, publicClient, {
780
885
  abi: transparentUpgradeableProxyArtifact.abi,
@@ -819,17 +924,22 @@ var TestEthereum = class {
819
924
  to: gatewayAddress,
820
925
  data: (0, import_viem.encodeFunctionData)({
821
926
  abi: mintingGatewayArtifact.abi,
822
- functionName: "adminMintBatch",
927
+ functionName: "migrate",
823
928
  args: [
824
- argonTokenAddress,
825
- [options.seedArgonRecipient],
826
- [options.seedArgonAmountBaseUnits ?? DEFAULT_SEED_ARGON_AMOUNT_BASE_UNITS]
929
+ {
930
+ recipients: [options.seedArgonRecipient],
931
+ amounts: [options.seedArgonAmountBaseUnits ?? DEFAULT_SEED_ARGON_AMOUNT_BASE_UNITS]
932
+ },
933
+ {
934
+ recipients: [],
935
+ amounts: []
936
+ }
827
937
  ]
828
938
  })
829
939
  });
830
940
  const mintReceipt = await waitForExecutionReceipt(publicClient, mintHash);
831
941
  if (mintReceipt.status !== "success") {
832
- throw new Error("MintingGateway admin mint failed");
942
+ throw new Error("MintingGateway migrate failed");
833
943
  }
834
944
  }
835
945
  return {
@@ -1048,9 +1158,9 @@ async function delay(ms) {
1048
1158
 
1049
1159
  // src/TestNetwork.ts
1050
1160
  var docker = __toESM(require("docker-compose"), 1);
1051
- var Path6 = __toESM(require("path"), 1);
1161
+ var Path7 = __toESM(require("path"), 1);
1052
1162
  async function startNetwork(testName, options) {
1053
- const config = Path6.join(__dirname, `dev.docker-compose.yml`);
1163
+ const config = Path7.join(__dirname, `dev.docker-compose.yml`);
1054
1164
  const env4 = {
1055
1165
  VERSION: "dev",
1056
1166
  ARGON_CHAIN: "dev-docker",
@@ -1082,52 +1192,1053 @@ async function startNetwork(testName, options) {
1082
1192
  };
1083
1193
  }
1084
1194
 
1085
- // src/index.ts
1086
- var toTeardown = [];
1087
- var proxy = null;
1088
- var proxyServer = null;
1089
- var SKIP_E2E = process4.env.SKIP_E2E === "true" || process4.env.SKIP_E2E === "1";
1090
- async function getProxy() {
1091
- if (!proxy) {
1092
- proxy = import_http_proxy.default.createProxyServer({
1093
- changeOrigin: true,
1094
- ws: true,
1095
- autoRewrite: true
1195
+ // src/EthereumE2eUtils.ts
1196
+ var import_mainchain5 = require("@argonprotocol/mainchain");
1197
+ var import_viem2 = require("viem");
1198
+ async function signGatewayPermit(args) {
1199
+ const signature = (0, import_viem2.parseSignature)(
1200
+ await args.account.signTypedData({
1201
+ domain: {
1202
+ name: "Argon",
1203
+ version: "1",
1204
+ chainId: args.chainId,
1205
+ verifyingContract: args.tokenAddress
1206
+ },
1207
+ types: {
1208
+ Permit: [
1209
+ { name: "owner", type: "address" },
1210
+ { name: "spender", type: "address" },
1211
+ { name: "value", type: "uint256" },
1212
+ { name: "nonce", type: "uint256" },
1213
+ { name: "deadline", type: "uint256" }
1214
+ ]
1215
+ },
1216
+ primaryType: "Permit",
1217
+ message: {
1218
+ owner: args.owner,
1219
+ spender: args.gatewayAddress,
1220
+ value: args.value,
1221
+ nonce: args.nonce,
1222
+ deadline: args.deadline
1223
+ }
1224
+ })
1225
+ );
1226
+ return {
1227
+ v: Number(signature.v),
1228
+ r: signature.r,
1229
+ s: signature.s
1230
+ };
1231
+ }
1232
+ async function waitForFinalizedBeaconExecutionAtOrAbove(ethereum, minimumExecutionBlockNumber, options = {}) {
1233
+ const startedAt = Date.now();
1234
+ const minimumFinalizedSlot = options.minimumFinalizedSlot ?? 0n;
1235
+ let lastSeenExecutionBlockNumber = 0n;
1236
+ let lastSeenHeadSlot = 0n;
1237
+ let lastSeenFinalizedSlot = 0n;
1238
+ let lastError;
1239
+ while (Date.now() - startedAt < 3e5) {
1240
+ try {
1241
+ const [headHeader, finalizedHeader] = await Promise.all([
1242
+ ethereum.getBeacon("/eth/v1/beacon/headers/head"),
1243
+ ethereum.getBeacon("/eth/v1/beacon/headers/finalized")
1244
+ ]);
1245
+ lastSeenHeadSlot = BigInt(headHeader.data.header.message.slot);
1246
+ lastSeenFinalizedSlot = BigInt(finalizedHeader.data.header.message.slot);
1247
+ const block = await ethereum.getBeacon(
1248
+ `/eth/v2/beacon/blocks/${finalizedHeader.data.root}`
1249
+ );
1250
+ const executionBlockNumber = BigInt(block.data.message.body.execution_payload.block_number);
1251
+ lastSeenExecutionBlockNumber = executionBlockNumber;
1252
+ lastError = void 0;
1253
+ if (executionBlockNumber >= minimumExecutionBlockNumber && lastSeenFinalizedSlot >= minimumFinalizedSlot) {
1254
+ return { header: finalizedHeader, block };
1255
+ }
1256
+ } catch (error) {
1257
+ if (!(error instanceof Error)) {
1258
+ throw error;
1259
+ }
1260
+ lastError = error;
1261
+ }
1262
+ await delay2(1e3);
1263
+ }
1264
+ const lastErrorSuffix = lastError ? `; last beacon error was: ${lastError.message}` : "";
1265
+ throw new Error(
1266
+ `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}`
1267
+ );
1268
+ }
1269
+ async function mineLaterExecutionAnchorReceipt(walletClient, chain, ethereum, account, minimumBlockNumber) {
1270
+ while (true) {
1271
+ const transactionHash = await walletClient.sendTransaction({
1272
+ account,
1273
+ chain,
1274
+ to: account.address,
1275
+ value: 0n
1096
1276
  });
1097
- proxy.on("error", () => null);
1098
- proxyServer = http2.createServer(function(req, res) {
1099
- const queryData = url.parse(req.url, true).query;
1100
- if (!queryData.target) {
1101
- res.writeHead(500, { "Content-Type": "text/plain" });
1102
- res.end("Target parameter is required");
1277
+ const receipt = await waitForExecutionReceipt2(ethereum, transactionHash);
1278
+ if (BigInt(receipt.blockNumber) > minimumBlockNumber) {
1279
+ return receipt;
1280
+ }
1281
+ }
1282
+ }
1283
+ async function waitForExecutionReceipt2(ethereum, transactionHash) {
1284
+ const startedAt = Date.now();
1285
+ while (Date.now() - startedAt < 12e4) {
1286
+ try {
1287
+ const receipt = await ethereum.callExecution(
1288
+ "eth_getTransactionReceipt",
1289
+ [transactionHash]
1290
+ );
1291
+ if (receipt) {
1292
+ return receipt;
1293
+ }
1294
+ } catch (error) {
1295
+ const errorText = error instanceof Error ? [
1296
+ error.message,
1297
+ "details" in error && typeof error.details === "string" ? error.details : void 0
1298
+ ].filter(Boolean).join(" ") : String(error);
1299
+ if (!errorText.includes("indexing is in progress")) {
1300
+ throw error;
1301
+ }
1302
+ }
1303
+ await delay2(500);
1304
+ }
1305
+ throw new Error(`Timed out waiting for execution receipt ${transactionHash}`);
1306
+ }
1307
+ async function syncEthereumVerifierUntilAnchorCovers(mainchainClient, relayer, beaconApiUrl, minimumExecutionBlockNumber) {
1308
+ const startedAt = Date.now();
1309
+ const timeoutMs = 5 * 6e4;
1310
+ let lastRetryableError;
1311
+ let lastAnchorBlockNumber;
1312
+ while (Date.now() - startedAt < timeoutMs) {
1313
+ try {
1314
+ const anchor = await (0, import_mainchain5.getLatestArgonFinalizedExecutionHeader)(mainchainClient);
1315
+ lastAnchorBlockNumber = anchor.blockNumber;
1316
+ if (anchor.blockNumber >= minimumExecutionBlockNumber) {
1103
1317
  return;
1104
1318
  }
1105
- console.log("Proxying http request", queryData.target);
1106
- proxy?.web(req, res, { target: queryData.target });
1107
- });
1108
- proxyServer.on("upgrade", function(req, clientSocket, head) {
1109
- const queryData = url.parse(req.url, true).query;
1110
- const target = url.parse(queryData.target);
1111
- proxy?.ws(req, clientSocket, head, {
1112
- target: target.href,
1113
- ws: true
1319
+ } catch {
1320
+ }
1321
+ const txs = await (0, import_mainchain5.getNextEthereumBeaconSyncTxs)(mainchainClient, beaconApiUrl);
1322
+ if (txs.length === 0) {
1323
+ await delay2(500);
1324
+ continue;
1325
+ }
1326
+ let shouldRetry = false;
1327
+ for (const tx of txs) {
1328
+ try {
1329
+ const result = await new import_mainchain5.TxSubmitter(mainchainClient, tx, relayer).submit();
1330
+ await result.waitForInFirstBlock;
1331
+ lastRetryableError = void 0;
1332
+ } catch (error) {
1333
+ if (isRetryableEthereumVerifierSyncError(error)) {
1334
+ lastRetryableError = error instanceof Error ? error : new Error(String(error));
1335
+ shouldRetry = true;
1336
+ break;
1337
+ }
1338
+ throw error;
1339
+ }
1340
+ }
1341
+ if (shouldRetry) {
1342
+ await delay2(500);
1343
+ }
1344
+ }
1345
+ throw lastRetryableError ?? new Error(
1346
+ `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"}`
1347
+ );
1348
+ }
1349
+ function toArgonKeccakSignature(signature) {
1350
+ const bytes = (0, import_mainchain5.hexToU8a)(signature);
1351
+ if (bytes.length !== 65) {
1352
+ throw new Error(`Expected 65-byte ECDSA signature, received ${bytes.length} bytes`);
1353
+ }
1354
+ if (bytes[64] >= 27) {
1355
+ bytes[64] -= 27;
1356
+ }
1357
+ return (0, import_mainchain5.u8aToHex)(bytes);
1358
+ }
1359
+ function toEvmRecoverableSignature(signature) {
1360
+ const bytes = (0, import_mainchain5.hexToU8a)(signature);
1361
+ if (bytes.length !== 65) {
1362
+ throw new Error(`Expected 65-byte ECDSA signature, received ${bytes.length} bytes`);
1363
+ }
1364
+ if (bytes[64] <= 1) {
1365
+ bytes[64] += 27;
1366
+ }
1367
+ return (0, import_mainchain5.u8aToHex)(bytes);
1368
+ }
1369
+ function isRetryableEthereumVerifierSyncError(error) {
1370
+ const message = error instanceof Error ? error.message : String(error);
1371
+ return (0, import_mainchain5.isOutdatedTransactionError)(error) || message.includes("ethereumVerifier.InvalidHeaderMerkleProof");
1372
+ }
1373
+ async function delay2(ms) {
1374
+ await new Promise((resolve3) => setTimeout(resolve3, ms));
1375
+ }
1376
+
1377
+ // src/EthereumGatewayQueue.ts
1378
+ var import_mainchain6 = require("@argonprotocol/mainchain");
1379
+ var import_viem3 = require("viem");
1380
+ var {
1381
+ encodeMintingGatewayMintingAuthorityActivationTarget,
1382
+ encodeMintingGatewayMintingAuthorityDeactivateTarget,
1383
+ hashMintingGatewayActivateMintingAuthority,
1384
+ hashMintingGatewayGatewayUpdateApproval,
1385
+ hashMintingGatewayMintingAuthorityDeactivation,
1386
+ mintingGatewayAbi,
1387
+ MINTING_GATEWAY_UPDATE_KINDS
1388
+ } = import_mainchain6.EvmContracts;
1389
+ async function getReadyEthereumGatewayUpdates(client, gatewayClient, options = {}) {
1390
+ const destinationChain = options.destinationChain ?? "Ethereum";
1391
+ const maxQueueEntries = options.maxQueueEntries ?? 100;
1392
+ if (maxQueueEntries < 1) {
1393
+ throw new Error(`maxQueueEntries must be at least 1, received ${maxQueueEntries}`);
1394
+ }
1395
+ const chainConfigOption = await client.query.crosschainTransfer.chainConfigBySourceChain(destinationChain);
1396
+ if (chainConfigOption.isNone) {
1397
+ throw new Error(`Crosschain config not found for ${destinationChain}`);
1398
+ }
1399
+ const chainConfig = chainConfigOption.unwrap();
1400
+ if (!chainConfig.isEvm) {
1401
+ throw new Error(`Chain config for ${destinationChain} is not EVM-shaped`);
1402
+ }
1403
+ const gatewayAddress = (0, import_viem3.getAddress)(toHexValue(chainConfig.asEvm.gateway));
1404
+ const chainId = chainConfig.asEvm.chainId.toBigInt();
1405
+ const hashContext = { chainId, gatewayAddress };
1406
+ const currentCouncilHashOption = await client.query.crosschainTransfer.activeGlobalIssuanceCouncilByDestinationChain(
1407
+ destinationChain
1408
+ );
1409
+ if (currentCouncilHashOption.isNone) {
1410
+ throw new Error(`Active GlobalIssuanceCouncil not found for ${destinationChain}`);
1411
+ }
1412
+ const currentCouncilHash = toHexValue(currentCouncilHashOption.unwrap());
1413
+ const councilCache = /* @__PURE__ */ new Map();
1414
+ const currentCouncil = councilToSnapshot(
1415
+ await loadCouncilByHash(client, currentCouncilHash, councilCache)
1416
+ );
1417
+ const [rawArgonApprovalsNonce, rawArgonApprovalsHash, rawPaused] = await Promise.all([
1418
+ gatewayClient.readContract({
1419
+ abi: mintingGatewayAbi,
1420
+ address: gatewayAddress,
1421
+ functionName: "argonApprovalsNonce"
1422
+ }),
1423
+ gatewayClient.readContract({
1424
+ abi: mintingGatewayAbi,
1425
+ address: gatewayAddress,
1426
+ functionName: "argonApprovalsHash"
1427
+ }),
1428
+ gatewayClient.readContract({
1429
+ abi: mintingGatewayAbi,
1430
+ address: gatewayAddress,
1431
+ functionName: "paused"
1432
+ })
1433
+ ]);
1434
+ const argonApprovalsNonce = rawArgonApprovalsNonce;
1435
+ const argonApprovalsHash = rawArgonApprovalsHash;
1436
+ const paused = rawPaused;
1437
+ const pendingClearOutQueueNonces = [];
1438
+ const candidateUpdates = [];
1439
+ let expectedPreviousApprovalHash = argonApprovalsHash;
1440
+ let readyQueueEntriesScanned = 0;
1441
+ if (!paused) {
1442
+ for (let queueNonce = argonApprovalsNonce + 1n; readyQueueEntriesScanned < maxQueueEntries; queueNonce += 1n) {
1443
+ const entryOption = await client.query.crosschainTransfer.councilApprovalQueueByDestinationChainAndNonce(
1444
+ destinationChain,
1445
+ queueNonce
1446
+ );
1447
+ if (entryOption.isNone) {
1448
+ break;
1449
+ }
1450
+ const entry = entryOption.unwrap();
1451
+ const approvingCouncilHash = toHexValue(entry.approvingCouncilHash);
1452
+ if (!await queueEntryIsReady(
1453
+ client,
1454
+ entry,
1455
+ approvingCouncilHash,
1456
+ councilCache,
1457
+ hashContext,
1458
+ queueNonce
1459
+ )) {
1460
+ break;
1461
+ }
1462
+ readyQueueEntriesScanned += 1;
1463
+ if (toHexValue(entry.previousApprovalHash) !== expectedPreviousApprovalHash) {
1464
+ throw new Error(
1465
+ `Queue nonce ${queueNonce} expected previous approval hash ${expectedPreviousApprovalHash}, received ${toHexValue(entry.previousApprovalHash)}`
1466
+ );
1467
+ }
1468
+ const update = await buildGatewayUpdate(client, destinationChain, hashContext, queueNonce, {
1469
+ entry,
1470
+ approvingCouncilHash
1114
1471
  });
1115
- clientSocket.on("error", console.error);
1472
+ candidateUpdates.push(update);
1473
+ expectedPreviousApprovalHash = toHexValue(entry.approvalHash);
1474
+ }
1475
+ }
1476
+ while (candidateUpdates.length > 0 && candidateUpdates[candidateUpdates.length - 1]?.kind === MINTING_GATEWAY_UPDATE_KINDS.mintingAuthorityDeactivate) {
1477
+ pendingClearOutQueueNonces.unshift(candidateUpdates.pop().queueNonce);
1478
+ }
1479
+ const updates = candidateUpdates;
1480
+ const firstQueueNonce = updates[0]?.queueNonce;
1481
+ const lastQueueNonce = updates[updates.length - 1]?.queueNonce;
1482
+ return {
1483
+ destinationChain,
1484
+ chainId,
1485
+ gatewayAddress,
1486
+ currentCouncilHash,
1487
+ currentCouncil,
1488
+ argonApprovalsNonce,
1489
+ argonApprovalsHash,
1490
+ paused,
1491
+ pendingClearOutQueueNonces,
1492
+ ...firstQueueNonce !== void 0 ? { firstQueueNonce, lastQueueNonce } : {},
1493
+ updates
1494
+ };
1495
+ }
1496
+ async function buildGatewayUpdate(client, destinationChain, hashContext, queueNonce, queueItem) {
1497
+ const { entry, approvingCouncilHash } = queueItem;
1498
+ if (entry.target.isMintingAuthorityActivation) {
1499
+ const signatures = getSortedSignatures(entry.signatures);
1500
+ const signingKey = (0, import_viem3.getAddress)(toHexValue(entry.target.asMintingAuthorityActivation));
1501
+ const authorityOption = await client.query.crosschainTransfer.mintingAuthoritiesBySigner(signingKey);
1502
+ if (authorityOption.isNone) {
1503
+ throw new Error(
1504
+ `Minting authority activation ${signingKey} not found for queue nonce ${queueNonce}`
1505
+ );
1506
+ }
1507
+ const authority = authorityOption.unwrap();
1508
+ if (authority.destinationChain.type !== destinationChain) {
1509
+ throw new Error(
1510
+ `Minting authority ${signingKey} belongs to ${String(authority.destinationChain.type)}, expected ${String(destinationChain)}`
1511
+ );
1512
+ }
1513
+ const target = {
1514
+ microgonCollateral: authority.gatewayRemainingMicrogonCollateral.toBigInt(),
1515
+ micronotCollateral: authority.gatewayRemainingMicronotCollateral.toBigInt(),
1516
+ signingKey
1517
+ };
1518
+ const payload = encodeMintingGatewayMintingAuthorityActivationTarget(target);
1519
+ const targetPayloadHash = payloadHashFromActivationPayload(hashContext, target);
1520
+ const approvalHash = hashMintingGatewayGatewayUpdateApproval(hashContext, {
1521
+ queueNonce,
1522
+ approvingCouncilHash,
1523
+ kind: MINTING_GATEWAY_UPDATE_KINDS.mintingAuthorityActivate,
1524
+ targetId: `0x${signingKey.slice(2).padStart(64, "0").toLowerCase()}`,
1525
+ targetPayloadHash,
1526
+ previousUpdateHash: toHexValue(entry.previousApprovalHash)
1116
1527
  });
1117
- await new Promise((resolve3) => proxyServer.listen(0, resolve3));
1118
- toTeardown.push({
1119
- teardown: () => new Promise((resolve3) => {
1120
- proxy?.close();
1121
- proxyServer?.close((_) => null);
1122
- proxy = null;
1123
- proxyServer = null;
1124
- resolve3();
1528
+ if (toHexValue(entry.targetPayloadHash) !== targetPayloadHash) {
1529
+ throw new Error(`Queue nonce ${queueNonce} target payload hash does not match authority`);
1530
+ }
1531
+ if (toHexValue(entry.approvalHash) !== approvalHash) {
1532
+ throw new Error(
1533
+ `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)}`
1534
+ );
1535
+ }
1536
+ return {
1537
+ queueNonce,
1538
+ kind: MINTING_GATEWAY_UPDATE_KINDS.mintingAuthorityActivate,
1539
+ payload,
1540
+ signatures
1541
+ };
1542
+ }
1543
+ if (entry.target.isMintingAuthorityDeactivation) {
1544
+ const { payload, signatures } = validateDeactivationEntry(
1545
+ hashContext,
1546
+ queueNonce,
1547
+ entry,
1548
+ approvingCouncilHash
1549
+ );
1550
+ return {
1551
+ queueNonce,
1552
+ kind: MINTING_GATEWAY_UPDATE_KINDS.mintingAuthorityDeactivate,
1553
+ payload,
1554
+ signatures
1555
+ };
1556
+ }
1557
+ throw new Error(`Unsupported approval queue target ${entry.target.type}`);
1558
+ }
1559
+ async function loadCouncilByHash(client, councilHash, cache) {
1560
+ const cached = cache.get(councilHash);
1561
+ if (cached) {
1562
+ return cached;
1563
+ }
1564
+ const councilOption = await client.query.crosschainTransfer.globalIssuanceCouncilByHash(councilHash);
1565
+ if (councilOption.isNone) {
1566
+ throw new Error(`GlobalIssuanceCouncil ${councilHash} not found`);
1567
+ }
1568
+ const council = councilOption.unwrap();
1569
+ const loaded = {
1570
+ totalWeight: council.totalWeight.toBigInt(),
1571
+ members: [...council.members.entries()].map(([signer, member]) => ({
1572
+ signer: (0, import_viem3.getAddress)(toHexValue(signer)),
1573
+ weight: member.weight.toBigInt()
1574
+ })).sort((left, right) => left.signer.localeCompare(right.signer))
1575
+ };
1576
+ cache.set(councilHash, loaded);
1577
+ return loaded;
1578
+ }
1579
+ function queueEntryHasQuorum(entry, council) {
1580
+ const signedWeight = [...entry.signatures.entries()].reduce((total, [signer]) => {
1581
+ const signerAddress = (0, import_viem3.getAddress)(toHexValue(signer));
1582
+ const member = council.members.find((x) => x.signer === signerAddress);
1583
+ if (!member) {
1584
+ throw new Error(`Signature submitted by ${signerAddress}, which is not in the council`);
1585
+ }
1586
+ return total + member.weight;
1587
+ }, 0n);
1588
+ return signedWeight * 2n > council.totalWeight;
1589
+ }
1590
+ async function queueEntryIsReady(client, entry, approvingCouncilHash, councilCache, hashContext, queueNonce) {
1591
+ if (entry.target.isMintingAuthorityDeactivation) {
1592
+ validateDeactivationEntry(hashContext, queueNonce, entry, approvingCouncilHash);
1593
+ return true;
1594
+ }
1595
+ const approvingCouncil = await loadCouncilByHash(client, approvingCouncilHash, councilCache);
1596
+ return queueEntryHasQuorum(entry, approvingCouncil);
1597
+ }
1598
+ function councilToSnapshot(council) {
1599
+ return {
1600
+ signers: council.members.map((member) => member.signer),
1601
+ weights: council.members.map((member) => member.weight)
1602
+ };
1603
+ }
1604
+ function payloadHashFromActivationPayload(hashContext, target) {
1605
+ return hashMintingGatewayActivateMintingAuthority(hashContext, target);
1606
+ }
1607
+ function payloadHashFromDeactivationPayload(target) {
1608
+ return (0, import_viem3.keccak256)(encodeMintingGatewayMintingAuthorityDeactivateTarget(target));
1609
+ }
1610
+ function validateDeactivationEntry(hashContext, queueNonce, entry, approvingCouncilHash) {
1611
+ const signingKey = (0, import_viem3.getAddress)(toHexValue(entry.target.asMintingAuthorityDeactivation));
1612
+ const target = { signingKey };
1613
+ const payload = encodeMintingGatewayMintingAuthorityDeactivateTarget(target);
1614
+ const targetPayloadHash = payloadHashFromDeactivationPayload(target);
1615
+ const approvalHash = hashMintingGatewayMintingAuthorityDeactivation(hashContext, {
1616
+ queueNonce,
1617
+ target,
1618
+ previousUpdateHash: toHexValue(entry.previousApprovalHash)
1619
+ });
1620
+ if (toHexValue(entry.targetPayloadHash) !== targetPayloadHash) {
1621
+ throw new Error(`Queue nonce ${queueNonce} target payload hash does not match deactivation`);
1622
+ }
1623
+ if (toHexValue(entry.approvalHash) !== approvalHash) {
1624
+ throw new Error(
1625
+ `Queue nonce ${queueNonce} approval hash does not match deactivation: actual=${toHexValue(entry.approvalHash)} expected=${approvalHash} previous=${toHexValue(entry.previousApprovalHash)} council=${approvingCouncilHash}`
1626
+ );
1627
+ }
1628
+ const deactivationSignatures = [...entry.signatures.entries()];
1629
+ if (deactivationSignatures.length !== 1) {
1630
+ throw new Error(
1631
+ `Queue nonce ${queueNonce} expected exactly one deactivation signature, received ${deactivationSignatures.length}`
1632
+ );
1633
+ }
1634
+ const [signer] = deactivationSignatures[0];
1635
+ if ((0, import_viem3.getAddress)(toHexValue(signer)) !== signingKey) {
1636
+ throw new Error(
1637
+ `Queue nonce ${queueNonce} deactivation signature was submitted by ${(0, import_viem3.getAddress)(toHexValue(signer))}, expected ${signingKey}`
1638
+ );
1639
+ }
1640
+ return {
1641
+ payload,
1642
+ signatures: getSortedSignatures(entry.signatures)
1643
+ };
1644
+ }
1645
+ function getSortedSignatures(signatures) {
1646
+ return [...signatures.entries()].sort(
1647
+ ([leftSigner], [rightSigner]) => toHexValue(leftSigner).localeCompare(toHexValue(rightSigner))
1648
+ ).map(([, signature]) => toEvmRecoverableSignature(toHexValue(signature)));
1649
+ }
1650
+ function toHexValue(value) {
1651
+ return value.toHex();
1652
+ }
1653
+
1654
+ // src/TestEthereumProofActors.ts
1655
+ var import_mainchain7 = require("@argonprotocol/mainchain");
1656
+ var import_accounts2 = require("viem/accounts");
1657
+ var import_viem4 = require("viem");
1658
+ var { argonTokenAbi, mintingGatewayAbi: mintingGatewayAbi2, MINTING_GATEWAY_RUNTIME_TO_ERC20_SCALE } = import_mainchain7.EvmContracts;
1659
+ var MINIMAL_BOOTSTRAP_FINALIZED_SLOT = 64n;
1660
+ var EthereumProofE2eHarness = class _EthereumProofE2eHarness {
1661
+ constructor(ethereum, endpoints, mainchain, mainchainClient, deployerPrivateKey, proofRelayerUri) {
1662
+ this.ethereum = ethereum;
1663
+ this.endpoints = endpoints;
1664
+ this.mainchain = mainchain;
1665
+ this.mainchainClient = mainchainClient;
1666
+ this.deployer = (0, import_accounts2.privateKeyToAccount)(deployerPrivateKey);
1667
+ this.chain = (0, import_viem4.defineChain)({
1668
+ id: Number.parseInt(endpoints.chainId, 16),
1669
+ name: "argon-test-ethereum",
1670
+ nativeCurrency: {
1671
+ name: "Ether",
1672
+ symbol: "ETH",
1673
+ decimals: 18
1674
+ },
1675
+ rpcUrls: {
1676
+ default: {
1677
+ http: [endpoints.executionRpcUrl]
1678
+ }
1679
+ }
1680
+ });
1681
+ this.publicClient = (0, import_viem4.createPublicClient)({
1682
+ chain: this.chain,
1683
+ transport: (0, import_viem4.http)(endpoints.executionRpcUrl)
1684
+ });
1685
+ this.walletClient = (0, import_viem4.createWalletClient)({
1686
+ account: this.deployer,
1687
+ chain: this.chain,
1688
+ transport: (0, import_viem4.http)(endpoints.executionRpcUrl)
1689
+ });
1690
+ this.proofRelayer = new import_mainchain7.Keyring({ type: "sr25519" }).createFromUri(proofRelayerUri);
1691
+ }
1692
+ sudoSigner = new import_mainchain7.Keyring({ type: "sr25519" }).createFromUri("//Alice");
1693
+ deployer;
1694
+ chain;
1695
+ publicClient;
1696
+ walletClient;
1697
+ mainchainClient;
1698
+ proofRelayer;
1699
+ static async launch(args) {
1700
+ const ethereum = new TestEthereum();
1701
+ const endpoints = await ethereum.launch({
1702
+ consensusClient: "lodestar",
1703
+ preset: "minimal",
1704
+ secondsPerSlot: 1,
1705
+ prefundedAccounts: {
1706
+ [args.testAccount.address]: {
1707
+ balance: args.testAccount.balance
1708
+ }
1709
+ }
1710
+ });
1711
+ const mainchain = new TestMainchain();
1712
+ await mainchain.launch();
1713
+ const mainchainClient = await mainchain.client();
1714
+ return new _EthereumProofE2eHarness(
1715
+ ethereum,
1716
+ endpoints,
1717
+ mainchain,
1718
+ mainchainClient,
1719
+ args.testAccount.privateKey,
1720
+ args.proofRelayerUri
1721
+ );
1722
+ }
1723
+ async submit(tx, signer) {
1724
+ const result = await new import_mainchain7.TxSubmitter(this.mainchainClient, tx, signer).submit();
1725
+ await result.waitForInFirstBlock;
1726
+ return result;
1727
+ }
1728
+ async sudoSubmit(tx) {
1729
+ const result = await this.submit(
1730
+ this.mainchainClient.tx.sudo.sudo(tx),
1731
+ this.sudoSigner
1732
+ );
1733
+ const sudoEvent = result.events.find((event) => this.mainchainClient.events.sudo.Sudid.is(event));
1734
+ if (!sudoEvent || !this.mainchainClient.events.sudo.Sudid.is(sudoEvent)) {
1735
+ throw new Error("sudo did not emit sudo.Sudid");
1736
+ }
1737
+ const sudoResult = sudoEvent.data[0];
1738
+ if (sudoResult.isErr) {
1739
+ throw new Error(
1740
+ `sudo failed: ${(0, import_mainchain7.dispatchErrorToString)(this.mainchainClient, sudoResult.asErr)}`
1741
+ );
1742
+ }
1743
+ return result;
1744
+ }
1745
+ async syncVerifierThrough(minimumExecutionBlockNumber) {
1746
+ await syncEthereumVerifierUntilAnchorCovers(
1747
+ this.mainchainClient,
1748
+ this.sudoSigner,
1749
+ this.endpoints.beaconApiUrl,
1750
+ minimumExecutionBlockNumber
1751
+ );
1752
+ }
1753
+ async proveGatewayActivity(gatewayAddress, throughExecutionBlockNumber) {
1754
+ const payload = await (0, import_mainchain7.buildGatewayActivityProofPayload)(this.mainchainClient, {
1755
+ executionRpcUrl: this.endpoints.executionRpcUrl,
1756
+ gatewayAddress,
1757
+ throughExecutionBlockNumber
1758
+ });
1759
+ if (!payload) {
1760
+ throw new Error("Expected uncovered gateway activity to prove");
1761
+ }
1762
+ const result = await this.submit(
1763
+ this.mainchainClient.tx.crosschainTransfer.proveGatewayActivity(
1764
+ "Ethereum",
1765
+ payload.previousGatewayActivityNonce,
1766
+ payload.proof
1767
+ ),
1768
+ this.proofRelayer
1769
+ );
1770
+ return { payload, result };
1771
+ }
1772
+ async configureEthereumRuntime(gateway, mode) {
1773
+ const calls = [
1774
+ this.mainchainClient.tx.crosschainTransfer.setChainConfig("Ethereum", {
1775
+ Evm: {
1776
+ chainId: BigInt(this.chain.id).toString(),
1777
+ gateway: gateway.gatewayAddress,
1778
+ argonToken: gateway.argonTokenAddress,
1779
+ argonotToken: gateway.argonotTokenAddress
1780
+ }
1781
+ })
1782
+ ];
1783
+ if (mode.kind === "outbound") {
1784
+ const activationPricing = {
1785
+ activationGasCost: BigInt(mode.activationPricing.activationGasCost),
1786
+ signatureGasCost: BigInt(mode.activationPricing.signatureGasCost),
1787
+ estimatedWeiPerGas: BigInt(mode.activationPricing.estimatedWeiPerGas),
1788
+ estimatedMicrogonsPerEth: BigInt(mode.activationPricing.estimatedMicrogonsPerEth)
1789
+ };
1790
+ calls.push(
1791
+ this.mainchainClient.tx.crosschainTransfer.setMintingAuthorityActivationRepaymentPricing(
1792
+ "Ethereum",
1793
+ {
1794
+ activationGasCost: activationPricing.activationGasCost.toString(),
1795
+ signatureGasCost: activationPricing.signatureGasCost.toString(),
1796
+ estimatedWeiPerGas: activationPricing.estimatedWeiPerGas.toString(),
1797
+ estimatedMicrogonsPerEth: activationPricing.estimatedMicrogonsPerEth.toString()
1798
+ }
1799
+ )
1800
+ );
1801
+ if (mode.minimumMintingAuthorityValue !== void 0) {
1802
+ calls.push(
1803
+ this.mainchainClient.tx.crosschainTransfer.setMinimumMintingAuthorityValue(
1804
+ "Ethereum",
1805
+ mode.minimumMintingAuthorityValue.toString()
1806
+ )
1807
+ );
1808
+ }
1809
+ }
1810
+ calls.push(
1811
+ await (0, import_mainchain7.getEthereumBeaconSyncBootstrapTx)(this.mainchainClient, this.endpoints.beaconApiUrl)
1812
+ );
1813
+ const result = await this.sudoSubmit(this.mainchainClient.tx.utility.batchAll(calls));
1814
+ return { result };
1815
+ }
1816
+ async fundBurnAccount(amount) {
1817
+ const burnAccount = this.mainchainClient.consts.crosschainTransfer.ethereumBurnAccount.toString();
1818
+ return this.forceSetBalance(burnAccount, amount);
1819
+ }
1820
+ async fundProofRelayer(amount = this.mainchainClient.consts.balances.existentialDeposit.toBigInt() + 1000000n) {
1821
+ return this.submit(
1822
+ this.mainchainClient.tx.balances.transferAllowDeath(this.proofRelayer.address, amount),
1823
+ this.sudoSigner
1824
+ );
1825
+ }
1826
+ async forceSetBalance(address, amount) {
1827
+ return this.sudoSubmit(this.mainchainClient.tx.balances.forceSetBalance(address, amount));
1828
+ }
1829
+ async forceSetOwnership(address, amount) {
1830
+ return this.sudoSubmit(this.mainchainClient.tx.ownership.forceSetBalance(address, amount));
1831
+ }
1832
+ async waitForExecutionFinalizedAfter(minimumExecutionBlockNumber) {
1833
+ const laterReceipt = await mineLaterExecutionAnchorReceipt(
1834
+ this.walletClient,
1835
+ this.chain,
1836
+ this.ethereum,
1837
+ this.deployer,
1838
+ minimumExecutionBlockNumber
1839
+ );
1840
+ await waitForFinalizedBeaconExecutionAtOrAbove(
1841
+ this.ethereum,
1842
+ BigInt(laterReceipt.blockNumber),
1843
+ {
1844
+ // Matches the apps/pr/gateway-proof bootstrap guard for minimal devnets.
1845
+ minimumFinalizedSlot: MINIMAL_BOOTSTRAP_FINALIZED_SLOT
1846
+ }
1847
+ );
1848
+ return laterReceipt;
1849
+ }
1850
+ };
1851
+ var TestMintingGateway = class _TestMintingGateway {
1852
+ constructor(harness, deployment) {
1853
+ this.harness = harness;
1854
+ this.deployment = deployment;
1855
+ }
1856
+ static async deploy(harness, options) {
1857
+ const deployment = await harness.ethereum.deployMintingGatewayFixture(options);
1858
+ return new _TestMintingGateway(harness, deployment);
1859
+ }
1860
+ get gatewayAddress() {
1861
+ return this.deployment.gatewayAddress;
1862
+ }
1863
+ get argonTokenAddress() {
1864
+ return this.deployment.argonTokenAddress;
1865
+ }
1866
+ get argonotTokenAddress() {
1867
+ return this.deployment.argonotTokenAddress;
1868
+ }
1869
+ async startTransferToArgon(args) {
1870
+ const permitDeadline = (await this.harness.publicClient.getBlock()).timestamp + 3600n;
1871
+ const permitNonce = await this.harness.publicClient.readContract({
1872
+ address: this.argonTokenAddress,
1873
+ abi: argonTokenAbi,
1874
+ functionName: "nonces",
1875
+ args: [args.account.address]
1876
+ });
1877
+ const permitSignature = await signGatewayPermit({
1878
+ account: args.account,
1879
+ chainId: this.harness.chain.id,
1880
+ tokenAddress: this.argonTokenAddress,
1881
+ gatewayAddress: this.gatewayAddress,
1882
+ owner: args.account.address,
1883
+ value: args.amountRuntimeUnits * MINTING_GATEWAY_RUNTIME_TO_ERC20_SCALE,
1884
+ nonce: permitNonce,
1885
+ deadline: permitDeadline
1886
+ });
1887
+ const transactionHash = await (0, import_viem4.createWalletClient)({
1888
+ account: args.account,
1889
+ chain: this.harness.chain,
1890
+ transport: (0, import_viem4.http)(this.harness.endpoints.executionRpcUrl)
1891
+ }).sendTransaction({
1892
+ account: args.account,
1893
+ chain: this.harness.chain,
1894
+ to: this.gatewayAddress,
1895
+ data: (0, import_viem4.encodeFunctionData)({
1896
+ abi: mintingGatewayAbi2,
1897
+ functionName: "startTransferToArgon",
1898
+ args: [
1899
+ this.argonTokenAddress,
1900
+ args.amountRuntimeUnits,
1901
+ args.recipientArgonAddress,
1902
+ permitDeadline,
1903
+ permitSignature.v,
1904
+ permitSignature.r,
1905
+ permitSignature.s
1906
+ ]
1125
1907
  })
1126
1908
  });
1909
+ return waitForExecutionReceipt2(this.harness.ethereum, transactionHash);
1127
1910
  }
1128
- const port2 = proxyServer.address().port;
1129
- return `ws://host.docker.internal:${port2}`;
1911
+ async forceUpdateActiveCouncil(replacementCouncil, nextMicrogonsPerArgonot) {
1912
+ return this.harness.publicClient.waitForTransactionReceipt({
1913
+ hash: await this.harness.walletClient.writeContract({
1914
+ account: this.harness.deployer,
1915
+ chain: this.harness.chain,
1916
+ address: this.gatewayAddress,
1917
+ abi: mintingGatewayAbi2,
1918
+ functionName: "forceUpdateActiveCouncil",
1919
+ args: [replacementCouncil, nextMicrogonsPerArgonot]
1920
+ })
1921
+ });
1922
+ }
1923
+ async relayReadyApprovals(batch, operatorAddress) {
1924
+ return this.harness.publicClient.waitForTransactionReceipt({
1925
+ hash: await this.harness.walletClient.writeContract({
1926
+ account: this.harness.deployer,
1927
+ chain: this.harness.chain,
1928
+ address: this.gatewayAddress,
1929
+ abi: mintingGatewayAbi2,
1930
+ functionName: "applyGatewayUpdates",
1931
+ args: [
1932
+ batch.currentCouncil,
1933
+ batch.updates,
1934
+ (0, import_viem4.toHex)((0, import_mainchain7.decodeAddress)(operatorAddress), { size: 32 })
1935
+ ]
1936
+ })
1937
+ });
1938
+ }
1939
+ async argonApprovalsNonce() {
1940
+ return await this.harness.publicClient.readContract({
1941
+ address: this.gatewayAddress,
1942
+ abi: mintingGatewayAbi2,
1943
+ functionName: "argonApprovalsNonce"
1944
+ });
1945
+ }
1946
+ async globalIssuanceCouncil() {
1947
+ return await this.harness.publicClient.readContract({
1948
+ address: this.gatewayAddress,
1949
+ abi: mintingGatewayAbi2,
1950
+ functionName: "globalIssuanceCouncil"
1951
+ });
1952
+ }
1953
+ async authorityCollateral(signingKey) {
1954
+ return await this.harness.publicClient.readContract({
1955
+ address: this.gatewayAddress,
1956
+ abi: mintingGatewayAbi2,
1957
+ functionName: "mintingAuthorityCollateralRemaining",
1958
+ args: [signingKey]
1959
+ });
1960
+ }
1961
+ async finalizeTransferOut(args) {
1962
+ return this.harness.publicClient.waitForTransactionReceipt({
1963
+ hash: await this.harness.walletClient.writeContract({
1964
+ account: this.harness.deployer,
1965
+ chain: this.harness.chain,
1966
+ address: this.gatewayAddress,
1967
+ abi: mintingGatewayAbi2,
1968
+ functionName: "finalizeTransferOutOfArgon",
1969
+ args: [
1970
+ args.transferRequest,
1971
+ {
1972
+ authorizations: [
1973
+ {
1974
+ microgonCollateral: 0n,
1975
+ micronotCollateral: args.micronotCollateral,
1976
+ signature: args.collateralizationSignature
1977
+ }
1978
+ ]
1979
+ }
1980
+ ]
1981
+ })
1982
+ });
1983
+ }
1984
+ async isFinalizedTransferOut(transferRequest) {
1985
+ return await this.harness.publicClient.readContract({
1986
+ address: this.gatewayAddress,
1987
+ abi: mintingGatewayAbi2,
1988
+ functionName: "finalizedTransferOutOfArgonIds",
1989
+ args: [import_mainchain7.EvmContracts.hashMintingGatewayTransferOutOfArgonRequest(transferRequest)]
1990
+ });
1991
+ }
1992
+ async argonBalance(address) {
1993
+ return await this.harness.publicClient.readContract({
1994
+ address: this.argonTokenAddress,
1995
+ abi: argonTokenAbi,
1996
+ functionName: "balanceOf",
1997
+ args: [address]
1998
+ });
1999
+ }
2000
+ async fundExecutionAccount(address, value) {
2001
+ return this.harness.publicClient.waitForTransactionReceipt({
2002
+ hash: await this.harness.walletClient.sendTransaction({
2003
+ account: this.harness.deployer,
2004
+ chain: this.harness.chain,
2005
+ to: address,
2006
+ value
2007
+ })
2008
+ });
2009
+ }
2010
+ };
2011
+ var TestMintingAuthorityActor = class {
2012
+ constructor(harness, args) {
2013
+ this.harness = harness;
2014
+ this.operator = new import_mainchain7.Keyring({ type: "sr25519" }).createFromUri(args.operatorUri);
2015
+ this.councilSigner = (0, import_accounts2.privateKeyToAccount)(args.councilPrivateKey);
2016
+ this.authoritySigner = (0, import_accounts2.privateKeyToAccount)(args.authorityPrivateKey);
2017
+ }
2018
+ operator;
2019
+ councilSigner;
2020
+ authoritySigner;
2021
+ gateway;
2022
+ attachGateway(gateway) {
2023
+ this.gateway = gateway;
2024
+ }
2025
+ async prepareOperator(args) {
2026
+ await this.harness.forceSetBalance(this.operator.address, args.freeBalance);
2027
+ await this.harness.forceSetOwnership(this.operator.address, args.ownershipBalance);
2028
+ const vault = await import_mainchain7.Vault.create(this.harness.mainchainClient, this.operator, {
2029
+ securitization: 1000000000n,
2030
+ securitizationRatio: 1,
2031
+ annualPercentRate: 0.05,
2032
+ baseFee: 0n,
2033
+ bitcoinXpub: args.bitcoinXpub,
2034
+ treasuryProfitSharing: 0
2035
+ });
2036
+ await vault.getVault();
2037
+ await this.harness.sudoSubmit(
2038
+ this.harness.mainchainClient.tx.priceIndex.setOperator(this.operator.address)
2039
+ );
2040
+ const currentTick = await this.harness.mainchainClient.query.ticks.currentTick();
2041
+ await this.harness.submit(
2042
+ this.harness.mainchainClient.tx.priceIndex.submit({
2043
+ btcUsdPrice: (0, import_mainchain7.toFixedNumber)(6e4, 18),
2044
+ argonotUsdPrice: (0, import_mainchain7.toFixedNumber)(1, 18),
2045
+ argonUsdPrice: (0, import_mainchain7.toFixedNumber)(1, 18),
2046
+ argonUsdTargetPrice: (0, import_mainchain7.toFixedNumber)(1, 18),
2047
+ argonTimeWeightedAverageLiquidity: (0, import_mainchain7.toFixedNumber)(1e6, 18),
2048
+ tick: currentTick.toBigInt()
2049
+ }),
2050
+ this.operator
2051
+ );
2052
+ await this.harness.submit(
2053
+ this.harness.mainchainClient.tx.vaults.setCommittedArgonots(args.committedArgonots),
2054
+ this.operator
2055
+ );
2056
+ }
2057
+ async registerCouncilSigner() {
2058
+ return this.harness.submit(
2059
+ this.harness.mainchainClient.tx.crosschainTransfer.registerCouncilSigner(
2060
+ "Ethereum",
2061
+ this.councilSigner.address,
2062
+ toArgonKeccakSignature(
2063
+ await this.councilSigner.signMessage({
2064
+ message: { raw: (0, import_viem4.toHex)(this.registrationMessage("argon/council-signer/v2")) }
2065
+ })
2066
+ )
2067
+ ),
2068
+ this.operator
2069
+ );
2070
+ }
2071
+ async forceSingleMemberCouncil() {
2072
+ await this.harness.sudoSubmit(
2073
+ this.harness.mainchainClient.tx.crosschainTransfer.forceSetGlobalIssuanceCouncil(
2074
+ "Ethereum",
2075
+ 0,
2076
+ [this.operator.address]
2077
+ )
2078
+ );
2079
+ const activeCouncilHashOption = await this.harness.mainchainClient.query.crosschainTransfer.activeGlobalIssuanceCouncilByDestinationChain(
2080
+ "Ethereum"
2081
+ );
2082
+ if (activeCouncilHashOption.isNone) {
2083
+ throw new Error("Expected active Ethereum council hash");
2084
+ }
2085
+ const activeCouncilOption = await this.harness.mainchainClient.query.crosschainTransfer.globalIssuanceCouncilByHash(
2086
+ activeCouncilHashOption.unwrap()
2087
+ );
2088
+ if (activeCouncilOption.isNone) {
2089
+ throw new Error("Expected active Ethereum council");
2090
+ }
2091
+ const activeCouncil = activeCouncilOption.unwrap();
2092
+ const currentCouncil = [...activeCouncil.members.entries()].map(([signer, member]) => ({
2093
+ signer: signer.toHex(),
2094
+ weight: member.weight.toBigInt()
2095
+ })).sort((left, right) => left.signer.localeCompare(right.signer));
2096
+ return {
2097
+ activeCouncilHash: activeCouncilHashOption.unwrap().toHex(),
2098
+ activeCouncil,
2099
+ currentCouncil: {
2100
+ signers: currentCouncil.map((member) => member.signer),
2101
+ weights: currentCouncil.map((member) => member.weight)
2102
+ }
2103
+ };
2104
+ }
2105
+ async registerMintingAuthority(micronotCollateral) {
2106
+ return this.harness.submit(
2107
+ this.harness.mainchainClient.tx.crosschainTransfer.registerMintingAuthority(
2108
+ "Ethereum",
2109
+ this.authoritySigner.address,
2110
+ toArgonKeccakSignature(
2111
+ await this.authoritySigner.signMessage({
2112
+ message: {
2113
+ raw: (0, import_viem4.toHex)(this.registrationMessage("argon/minting-authority-signer/v2"))
2114
+ }
2115
+ })
2116
+ ),
2117
+ 0n,
2118
+ micronotCollateral
2119
+ ),
2120
+ this.operator
2121
+ );
2122
+ }
2123
+ async approveActivationQueueEntry(queueNonce = 1n) {
2124
+ const approvalQueueEntry = await this.harness.mainchainClient.query.crosschainTransfer.councilApprovalQueueByDestinationChainAndNonce(
2125
+ "Ethereum",
2126
+ queueNonce
2127
+ );
2128
+ if (approvalQueueEntry.isNone) {
2129
+ throw new Error(`Expected queue nonce ${queueNonce} to exist`);
2130
+ }
2131
+ const councilApprovalSignature = await this.councilSigner.signMessage({
2132
+ message: {
2133
+ raw: approvalQueueEntry.unwrap().approvalHash.toHex()
2134
+ }
2135
+ });
2136
+ await this.harness.submit(
2137
+ this.harness.mainchainClient.tx.crosschainTransfer.approveQueueEntries(
2138
+ "Ethereum",
2139
+ new import_mainchain7.Vec(this.harness.mainchainClient.registry, import_mainchain7.U8aFixed.with(520), [
2140
+ new import_mainchain7.U8aFixed(
2141
+ this.harness.mainchainClient.registry,
2142
+ toArgonKeccakSignature(councilApprovalSignature),
2143
+ 520
2144
+ )
2145
+ ])
2146
+ ),
2147
+ this.operator
2148
+ );
2149
+ const batch = await getReadyEthereumGatewayUpdates(
2150
+ this.harness.mainchainClient,
2151
+ this.harness.publicClient
2152
+ );
2153
+ return {
2154
+ approvalQueueEntry,
2155
+ councilApprovalSignature,
2156
+ batch
2157
+ };
2158
+ }
2159
+ async collateralizeFirstPendingTransferOut() {
2160
+ const gateway = this.requireGateway();
2161
+ const pendingRequests = await this.harness.mainchainClient.query.crosschainTransfer.pendingCollateralizationRequestsByChain(
2162
+ "Ethereum"
2163
+ );
2164
+ if (pendingRequests.length === 0) {
2165
+ throw new Error("Expected a pending collateralization request");
2166
+ }
2167
+ const pendingRequest = pendingRequests[0];
2168
+ const transferId = pendingRequest.transferId.toHex();
2169
+ const transferOption = await this.harness.mainchainClient.query.crosschainTransfer.transferOutById(transferId);
2170
+ if (transferOption.isNone) {
2171
+ throw new Error(`Expected transfer out ${transferId} to exist`);
2172
+ }
2173
+ const transfer = transferOption.unwrap();
2174
+ const transferRequest = {
2175
+ argonAccountId: transfer.argonAccountId.toHex(),
2176
+ argonTransferNonce: transfer.argonTransferNonce.toBigInt(),
2177
+ chainId: BigInt(this.harness.chain.id),
2178
+ microgonsPerArgonot: transfer.microgonsPerArgonot.toBigInt(),
2179
+ recipient: transfer.destinationAccount.toHex(),
2180
+ validUntilBlock: transfer.validUntilEthereumBlock.toBigInt(),
2181
+ token: gateway.argonTokenAddress,
2182
+ amount: transfer.amount.toBigInt(),
2183
+ mintingAuthorityTip: transfer.mintingAuthorityTip.toBigInt()
2184
+ };
2185
+ const micronotCollateral = transfer.amount.toBigInt();
2186
+ const collateralizationHash = import_mainchain7.EvmContracts.hashMintingGatewayMintingAuthorization(
2187
+ { chainId: BigInt(this.harness.chain.id), gatewayAddress: gateway.gatewayAddress },
2188
+ {
2189
+ request: transferRequest,
2190
+ microgonCollateral: 0n,
2191
+ micronotCollateral
2192
+ }
2193
+ );
2194
+ const collateralizationSignature = await this.authoritySigner.signMessage({
2195
+ message: {
2196
+ raw: collateralizationHash
2197
+ }
2198
+ });
2199
+ const result = await this.harness.submit(
2200
+ this.harness.mainchainClient.tx.crosschainTransfer.collateralizeTransfer(
2201
+ transferId,
2202
+ toArgonKeccakSignature(collateralizationSignature),
2203
+ 0n,
2204
+ micronotCollateral
2205
+ ),
2206
+ this.operator
2207
+ );
2208
+ return {
2209
+ pendingRequest,
2210
+ transferId,
2211
+ transferRequest,
2212
+ micronotCollateral,
2213
+ collateralizationSignature,
2214
+ result
2215
+ };
2216
+ }
2217
+ registrationMessage(prefix) {
2218
+ const prefixBytes = this.harness.mainchainClient.registry.createType("Bytes", prefix).toU8a();
2219
+ const destinationChainBytes = this.harness.mainchainClient.registry.createType("PalletCrosschainTransferSourceChain", "Ethereum").toU8a();
2220
+ const operatorAccountIdBytes = this.harness.mainchainClient.registry.createType("AccountId32", this.operator.address).toU8a();
2221
+ return concatBytes(prefixBytes, destinationChainBytes, operatorAccountIdBytes);
2222
+ }
2223
+ requireGateway() {
2224
+ if (!this.gateway) {
2225
+ throw new Error("Minting authority actor requires an attached TestMintingGateway");
2226
+ }
2227
+ return this.gateway;
2228
+ }
2229
+ };
2230
+ function concatBytes(...parts) {
2231
+ const totalLength = parts.reduce((sum, part) => sum + part.length, 0);
2232
+ const bytes = new Uint8Array(totalLength);
2233
+ let offset = 0;
2234
+ for (const part of parts) {
2235
+ bytes.set(part, offset);
2236
+ offset += part.length;
2237
+ }
2238
+ return bytes;
1130
2239
  }
2240
+
2241
+ // src/index.ts
1131
2242
  function stringifyExt(obj) {
1132
2243
  return JSON.stringify(
1133
2244
  obj,
@@ -1143,54 +2254,12 @@ function stringifyExt(obj) {
1143
2254
  2
1144
2255
  );
1145
2256
  }
1146
- function projectRoot() {
1147
- if (process4.env.ARGON_PROJECT_ROOT) {
1148
- return Path7.join(process4.env.ARGON_PROJECT_ROOT);
1149
- }
1150
- return Path7.join(__dirname, `../../..`);
1151
- }
1152
- async function runTestScript(relativePath) {
1153
- const scriptPath = Path7.resolve(projectRoot(), relativePath);
1154
- return child_process4.execSync(scriptPath, { encoding: "utf8" }).trim();
1155
- }
1156
- async function getDockerPortMapping(containerName, port2) {
1157
- return child_process4.execSync(`docker port ${containerName} ${port2}`, { encoding: "utf8" }).trim().split(":").pop();
1158
- }
1159
- async function teardown() {
1160
- for (const t of toTeardown) {
1161
- try {
1162
- await t.teardown().catch(console.error);
1163
- } catch {
1164
- }
1165
- }
1166
- toTeardown.length = 0;
1167
- }
1168
- function cleanHostForDocker(host, replacer = "host.docker.internal") {
1169
- if (process4.env.ARGON_USE_DOCKER_BINS) {
1170
- return host.replace("localhost", replacer).replace("127.0.0.1", replacer).replace("0.0.0.0", replacer);
1171
- }
1172
- return host;
1173
- }
1174
- function addTeardown(teardownable) {
1175
- toTeardown.push(teardownable);
1176
- }
1177
- function runOnTeardown(teardown2) {
1178
- addTeardown({ teardown: teardown2 });
1179
- }
1180
- function closeOnTeardown(closeable) {
1181
- addTeardown({ teardown: () => closeable.close() });
1182
- return closeable;
1183
- }
1184
- function disconnectOnTeardown(closeable) {
1185
- addTeardown({ teardown: () => closeable.disconnect() });
1186
- return closeable;
1187
- }
1188
2257
  function sudo() {
1189
- return new import_mainchain4.Keyring({ type: "sr25519" }).createFromUri("//Alice");
2258
+ return new import_mainchain8.Keyring({ type: "sr25519" }).createFromUri("//Alice");
1190
2259
  }
1191
2260
  async function activateNotary(sudo2, client, notary) {
1192
2261
  await notary.register(client);
1193
- const txResult = await new import_mainchain4.TxSubmitter(
2262
+ const txResult = await new import_mainchain8.TxSubmitter(
1194
2263
  client,
1195
2264
  client.tx.sudo.sudo(client.tx.notaries.activate(notary.operator.publicKey)),
1196
2265
  sudo2
@@ -1199,27 +2268,36 @@ async function activateNotary(sudo2, client, notary) {
1199
2268
  }
1200
2269
  // Annotate the CommonJS export names for ESM import in node:
1201
2270
  0 && (module.exports = {
2271
+ EthereumProofE2eHarness,
1202
2272
  SKIP_E2E,
1203
2273
  TestBitcoinCli,
1204
2274
  TestEthereum,
1205
2275
  TestMainchain,
2276
+ TestMintingAuthorityActor,
2277
+ TestMintingGateway,
1206
2278
  TestNotary,
1207
2279
  TestOracle,
1208
2280
  activateNotary,
1209
2281
  addTeardown,
1210
- argonTokenArtifact,
1211
2282
  cleanHostForDocker,
1212
2283
  closeOnTeardown,
1213
2284
  disconnectOnTeardown,
1214
2285
  getDockerPortMapping,
1215
2286
  getProxy,
1216
- mintingGatewayArtifact,
2287
+ getReadyEthereumGatewayUpdates,
2288
+ mineLaterExecutionAnchorReceipt,
1217
2289
  projectRoot,
1218
2290
  runOnTeardown,
1219
2291
  runTestScript,
2292
+ signGatewayPermit,
1220
2293
  startNetwork,
1221
2294
  stringifyExt,
1222
2295
  sudo,
1223
- teardown
2296
+ syncEthereumVerifierUntilAnchorCovers,
2297
+ teardown,
2298
+ toArgonKeccakSignature,
2299
+ toEvmRecoverableSignature,
2300
+ waitForExecutionReceipt,
2301
+ waitForFinalizedBeaconExecutionAtOrAbove
1224
2302
  });
1225
2303
  //# sourceMappingURL=index.cjs.map