@bradthomasbrown/900ef2 1.0.0
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/README.md +42 -0
- package/dist/900ef2.d.ts +14 -0
- package/dist/900ef2.d.ts.map +1 -0
- package/dist/900ef2.js +95 -0
- package/dist/_f8a4c6_.d.ts +14 -0
- package/dist/_f8a4c6_.d.ts.map +1 -0
- package/dist/_f8a4c6_.js +93 -0
- package/package.json +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# 900ef2
|
|
2
|
+
This is function that can return classes which can create containerized EVM nodes and return interfaces for them, with some helpful features, in TypeScript/JavaScript.
|
|
3
|
+
Features include automatic cleanup and "wait until responsive" logic, as well as returning a class (see `@bradthomasbrown/ejra`) to make interacting with the EVM node more convenient.
|
|
4
|
+
|
|
5
|
+
## Why?
|
|
6
|
+
To make testing EVM nodes a little bit easier to manage.
|
|
7
|
+
|
|
8
|
+
## Dependencies
|
|
9
|
+
This has a hard dependency on having `podman` for containers and images. See [podman.io](https://podman.io/).
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
```sh
|
|
13
|
+
npm i @bradthomasbrown/900ef2
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
```js
|
|
18
|
+
import { _900ef2_ } from "@bradthomasbrown/900ef2";
|
|
19
|
+
|
|
20
|
+
const anvilPort = 8546;
|
|
21
|
+
const gethPort = 8547;
|
|
22
|
+
|
|
23
|
+
const Anvil = _900ef2_("ghcr.io/foundry-rs/foundry:v1.5.1", `anvil -b 1 -p ${anvilPort} --host 0.0.0.0`);
|
|
24
|
+
const Geth = _900ef2_("ethereum/client-go", ["--dev", "--http", "--http.addr", "0.0.0.0", "--http.port", `${gethPort}`, "--http.api", "eth,debug"]);
|
|
25
|
+
|
|
26
|
+
const [anvilNode, gethNode] = await Promise.all([Anvil.make(anvilPort), Geth.make(gethPort)]);
|
|
27
|
+
|
|
28
|
+
const [anvilChainId, gethChainId] = await Promise.all([anvilNode, gethNode].map(node => node.chainId()));
|
|
29
|
+
|
|
30
|
+
const anvilUrl = anvilNode.client.url;
|
|
31
|
+
const gethUrl = gethNode.client.url;
|
|
32
|
+
|
|
33
|
+
console.log({ anvilUrl, anvilChainId, gethUrl, gethChainId });
|
|
34
|
+
/*
|
|
35
|
+
{
|
|
36
|
+
anvilUrl: "localhost:8546",
|
|
37
|
+
anvilChainId: 31337n,
|
|
38
|
+
gethUrl: "localhost:8547",
|
|
39
|
+
gethChainId: 1337n,
|
|
40
|
+
}
|
|
41
|
+
*/
|
|
42
|
+
```
|
package/dist/900ef2.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Node } from "@bradthomasbrown/ejra";
|
|
2
|
+
declare function _900ef2_(_80_: string, _c9_: null | string | string[]): {
|
|
3
|
+
new (): {};
|
|
4
|
+
make(_d0_: number, _5c_?: {
|
|
5
|
+
verbose?: boolean;
|
|
6
|
+
i?: number;
|
|
7
|
+
b?: number;
|
|
8
|
+
e?: number;
|
|
9
|
+
j?: number;
|
|
10
|
+
t?: number;
|
|
11
|
+
}): Promise<Node>;
|
|
12
|
+
};
|
|
13
|
+
export { _900ef2_ };
|
|
14
|
+
//# sourceMappingURL=900ef2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"900ef2.d.ts","sourceRoot":"","sources":["../src/900ef2.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAuC7C,iBAAS,QAAQ,CAAC,IAAI,EAAC,MAAM,EAAE,IAAI,EAAC,IAAI,GAAC,MAAM,GAAC,MAAM,EAAE;;eAKvC,MAAM,SACN;QACD,OAAO,CAAC,EAAC,OAAO,CAAC;QACjB,CAAC,CAAC,EAAC,MAAM,CAAC;QACV,CAAC,CAAC,EAAC,MAAM,CAAC;QACV,CAAC,CAAC,EAAC,MAAM,CAAC;QACV,CAAC,CAAC,EAAC,MAAM,CAAC;QACV,CAAC,CAAC,EAAC,MAAM,CAAA;KAChB;EA0CR;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|
package/dist/900ef2.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Podman } from "@bradthomasbrown/podman";
|
|
2
|
+
import { Node } from "@bradthomasbrown/ejra";
|
|
3
|
+
/**
|
|
4
|
+
Partial Box-Muller transform to get a normally distributed random number.
|
|
5
|
+
*/
|
|
6
|
+
function _027cdb_() {
|
|
7
|
+
const theta = 2 * Math.PI * Math.random();
|
|
8
|
+
const R = Math.sqrt(-2 * Math.log(Math.random()));
|
|
9
|
+
const v = R * Math.cos(theta);
|
|
10
|
+
return v;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
@param {()=>boolean} _89_ - A nullary boolean function that when called expresses success or failure of some operation.
|
|
14
|
+
@param {number} _4a_ - The number of times to try some operation before throwing an error due to failure.
|
|
15
|
+
@param {number} _ae_ - The base delay between operation attempts.
|
|
16
|
+
@param {number} _0b_ - The exponent used to calculate the next delay.
|
|
17
|
+
@param {number} _bb_ - The scale with which to apply jitter in calculating the next delay.
|
|
18
|
+
@param {number} _7e_ - The threshold of potential next delay triggering an error thrown due to failure.
|
|
19
|
+
*/
|
|
20
|
+
async function _178fae_(_89_, _4a_, _ae_, _0b_, _bb_, _7e_, verbose = false) {
|
|
21
|
+
let i = 0;
|
|
22
|
+
let _dc_ = _ae_;
|
|
23
|
+
while (i < _4a_) {
|
|
24
|
+
_dc_ = Math.max(_ae_, _dc_ * (1 + _027cdb_() * _bb_));
|
|
25
|
+
if (_dc_ > _7e_)
|
|
26
|
+
throw new Error("max delay exceeded");
|
|
27
|
+
if (_89_()) {
|
|
28
|
+
if (verbose) {
|
|
29
|
+
console.log(`success, ${i}, ${Date.now()}`);
|
|
30
|
+
}
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (verbose) {
|
|
34
|
+
console.log(`failure, ${i}, ${Date.now()}`);
|
|
35
|
+
}
|
|
36
|
+
await new Promise(r => setTimeout(r, _dc_));
|
|
37
|
+
_dc_ = _dc_ ** _0b_;
|
|
38
|
+
i++;
|
|
39
|
+
}
|
|
40
|
+
throw new Error("max attempts exceeded");
|
|
41
|
+
}
|
|
42
|
+
const _3c_ = new Set();
|
|
43
|
+
// "ethereum/client-go", "--dev --http --http.addr 0.0.0.0 --http.api eth,debug"
|
|
44
|
+
// "ghcr.io/foundry-rs/foundry:v1.5.1", "anvil -b 1 --host 0.0.0.0"
|
|
45
|
+
function _900ef2_(_80_, _c9_) {
|
|
46
|
+
return class _33926d_ {
|
|
47
|
+
static async make(_d0_, _5c_ = {}) {
|
|
48
|
+
const id = await Podman.run([["detach"], ["publish", `${_d0_}:${_d0_}`]], _80_, _c9_);
|
|
49
|
+
_3c_.add(id);
|
|
50
|
+
let _bb_ = false;
|
|
51
|
+
async function _78_(exit) {
|
|
52
|
+
if (_bb_ === true)
|
|
53
|
+
return;
|
|
54
|
+
else
|
|
55
|
+
_bb_ = true;
|
|
56
|
+
process.off("beforeExit", _78_);
|
|
57
|
+
process.off("unhandledRejection", _78_);
|
|
58
|
+
process.off("uncaughtException", _78_);
|
|
59
|
+
process.off("SIGINT", _78_);
|
|
60
|
+
await Promise.all([..._3c_].map(id => Podman.remove([["force"], ["time", 0]], id)));
|
|
61
|
+
if (exit == "SIGINT")
|
|
62
|
+
process.exit();
|
|
63
|
+
if (exit instanceof Error)
|
|
64
|
+
throw exit;
|
|
65
|
+
}
|
|
66
|
+
process.on("beforeExit", _78_);
|
|
67
|
+
process.on("unhandledRejection", _78_);
|
|
68
|
+
process.on("uncaughtException", _78_);
|
|
69
|
+
process.on("SIGINT", _78_);
|
|
70
|
+
const node = new Node(`localhost:${_d0_}`);
|
|
71
|
+
let _cb_ = null;
|
|
72
|
+
const _fb_ = () => node.blockNumber().then(() => _cb_ = true).catch(e => _cb_ = e);
|
|
73
|
+
let _45_ = _fb_();
|
|
74
|
+
const f = () => {
|
|
75
|
+
if (_cb_ == true)
|
|
76
|
+
return true;
|
|
77
|
+
if (_cb_ instanceof Error)
|
|
78
|
+
_45_ = _fb_();
|
|
79
|
+
return false;
|
|
80
|
+
};
|
|
81
|
+
_5c_.i ??= 12;
|
|
82
|
+
_5c_.b ??= 50;
|
|
83
|
+
_5c_.e ??= 1.06;
|
|
84
|
+
_5c_.j ??= 0.05;
|
|
85
|
+
_5c_.t ??= Infinity;
|
|
86
|
+
const error = await _178fae_(f, _5c_.i, _5c_.b, _5c_.e, _5c_.j, _5c_.t, _5c_.verbose).catch(e => e);
|
|
87
|
+
if (error) {
|
|
88
|
+
error.cause = _cb_;
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
return node;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
export { _900ef2_ };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Node } from "@bradthomasbrown/ejra";
|
|
2
|
+
declare function _f8a4c6_(_80_: string, _c9_: string, _5c_?: {
|
|
3
|
+
verbose?: boolean;
|
|
4
|
+
i?: number;
|
|
5
|
+
b?: number;
|
|
6
|
+
e?: number;
|
|
7
|
+
j?: number;
|
|
8
|
+
t?: number;
|
|
9
|
+
}): {
|
|
10
|
+
new (): {};
|
|
11
|
+
make(): Promise<Node>;
|
|
12
|
+
};
|
|
13
|
+
export { _f8a4c6_ };
|
|
14
|
+
//# sourceMappingURL=_f8a4c6_.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_f8a4c6_.d.ts","sourceRoot":"","sources":["../src/_f8a4c6_.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAqC7C,iBAAS,QAAQ,CAAC,IAAI,EAAC,MAAM,EAAE,IAAI,EAAC,MAAM,EAAE,IAAI,GAAC;IAAE,OAAO,CAAC,EAAC,OAAO,CAAC;IAAC,CAAC,CAAC,EAAC,MAAM,CAAC;IAAC,CAAC,CAAC,EAAC,MAAM,CAAC;IAAC,CAAC,CAAC,EAAC,MAAM,CAAC;IAAC,CAAC,CAAC,EAAC,MAAM,CAAC;IAAC,CAAC,CAAC,EAAC,MAAM,CAAA;CAAM;;;EA6C/H;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|
package/dist/_f8a4c6_.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { Podman } from "@bradthomasbrown/podman";
|
|
2
|
+
import { Node } from "@bradthomasbrown/ejra";
|
|
3
|
+
/**
|
|
4
|
+
Partial Box-Muller transform to get a normally distributed random number.
|
|
5
|
+
*/
|
|
6
|
+
function _027cdb_() {
|
|
7
|
+
const theta = 2 * Math.PI * Math.random();
|
|
8
|
+
const R = Math.sqrt(-2 * Math.log(Math.random()));
|
|
9
|
+
const v = R * Math.cos(theta);
|
|
10
|
+
return v;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
@param {()=>boolean} _89_ - A nullary boolean function that when called expresses success or failure of some operation.
|
|
14
|
+
@param {number} _4a_ - The number of times to try some operation before throwing an error due to failure.
|
|
15
|
+
@param {number} _ae_ - The base delay between operation attempts.
|
|
16
|
+
@param {number} _0b_ - The exponent used to calculate the next delay.
|
|
17
|
+
@param {number} _bb_ - The scale with which to apply jitter in calculating the next delay.
|
|
18
|
+
@param {number} _7e_ - The threshold of potential next delay triggering an error thrown due to failure.
|
|
19
|
+
*/
|
|
20
|
+
async function _178fae_(_89_, _4a_, _ae_, _0b_, _bb_, _7e_, verbose = false) {
|
|
21
|
+
let i = 0;
|
|
22
|
+
let _dc_ = _ae_;
|
|
23
|
+
while (i < _4a_) {
|
|
24
|
+
_dc_ = Math.max(_ae_, _dc_ * (1 + _027cdb_() * _bb_));
|
|
25
|
+
if (_dc_ > _7e_)
|
|
26
|
+
throw new Error("max delay exceeded");
|
|
27
|
+
if (_89_()) {
|
|
28
|
+
if (verbose) {
|
|
29
|
+
console.log(`success, ${i}, ${Date.now()}`);
|
|
30
|
+
}
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (verbose) {
|
|
34
|
+
console.log(`failure, ${i}, ${Date.now()}`);
|
|
35
|
+
}
|
|
36
|
+
await new Promise(r => setTimeout(r, _dc_));
|
|
37
|
+
_dc_ = _dc_ ** _0b_;
|
|
38
|
+
i++;
|
|
39
|
+
}
|
|
40
|
+
throw new Error("max attempts exceeded");
|
|
41
|
+
}
|
|
42
|
+
// "ethereum/client-go", "--dev --http --http.addr 0.0.0.0 --http.api eth,debug"
|
|
43
|
+
// "ghcr.io/foundry-rs/foundry:v1.5.1", "anvil -b 1 --host 0.0.0.0"
|
|
44
|
+
function _f8a4c6_(_80_, _c9_, _5c_ = {}) {
|
|
45
|
+
return class _33926d_ {
|
|
46
|
+
static async make() {
|
|
47
|
+
const id = await Podman.run([["detach"], ["publish", "8545:8545"]], _80_, _c9_);
|
|
48
|
+
let _bb_ = false;
|
|
49
|
+
async function _78_(exit) {
|
|
50
|
+
if (_bb_ === true)
|
|
51
|
+
return;
|
|
52
|
+
else
|
|
53
|
+
_bb_ = true;
|
|
54
|
+
process.off("beforeExit", _78_);
|
|
55
|
+
process.off("unhandledRejection", _78_);
|
|
56
|
+
process.off("uncaughtException", _78_);
|
|
57
|
+
process.off("SIGINT", _78_);
|
|
58
|
+
await Podman.remove([["force"], ["time", 0]], id);
|
|
59
|
+
if (exit == "SIGINT")
|
|
60
|
+
process.exit();
|
|
61
|
+
if (exit instanceof Error)
|
|
62
|
+
throw exit;
|
|
63
|
+
}
|
|
64
|
+
process.on("beforeExit", _78_);
|
|
65
|
+
process.on("unhandledRejection", _78_);
|
|
66
|
+
process.on("uncaughtException", _78_);
|
|
67
|
+
process.on("SIGINT", _78_);
|
|
68
|
+
const node = new Node("localhost:8545");
|
|
69
|
+
let _cb_ = null;
|
|
70
|
+
const _fb_ = () => node.blockNumber().then(() => _cb_ = true).catch(e => _cb_ = e);
|
|
71
|
+
let _45_ = _fb_();
|
|
72
|
+
const f = () => {
|
|
73
|
+
if (_cb_ == true)
|
|
74
|
+
return true;
|
|
75
|
+
if (_cb_ instanceof Error)
|
|
76
|
+
_45_ = _fb_();
|
|
77
|
+
return false;
|
|
78
|
+
};
|
|
79
|
+
_5c_.i ??= 12;
|
|
80
|
+
_5c_.b ??= 50;
|
|
81
|
+
_5c_.e ??= 1.06;
|
|
82
|
+
_5c_.j ??= 0.05;
|
|
83
|
+
_5c_.t ??= Infinity;
|
|
84
|
+
const error = await _178fae_(f, _5c_.i, _5c_.b, _5c_.e, _5c_.j, _5c_.t).catch(e => e);
|
|
85
|
+
if (error) {
|
|
86
|
+
error.cause = _cb_;
|
|
87
|
+
throw error;
|
|
88
|
+
}
|
|
89
|
+
return node;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
export { _f8a4c6_ };
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bradthomasbrown/900ef2",
|
|
3
|
+
"description": "Minimal, unoptimized, and unaudited { podman, containerized evm node (foundry's anvil, go-ethereum, etc. } library in JavaScript/TypeScript.",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"author": "Brad Brown <https://t.me/bradthomasbrown>",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"bump-patch": "npm version patch && git push && npm publish --access=public",
|
|
9
|
+
"bump-minor": "npm version minor && git push && npm publish --access=public",
|
|
10
|
+
"bump-major": "npm version major && git push && npm publish --access=public",
|
|
11
|
+
"prepublishOnly": "bun test.ts"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist/"
|
|
15
|
+
],
|
|
16
|
+
"exports": {
|
|
17
|
+
".": "./dist/900ef2.js"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@bradthomasbrown/ejra": "^1.0.5",
|
|
21
|
+
"@bradthomasbrown/podman": "^1.1.7"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/bun": "^1.3.5",
|
|
25
|
+
"@types/node": "^25.0.3"
|
|
26
|
+
}
|
|
27
|
+
}
|