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