@nomicfoundation/edr 0.2.0-alpha.2 → 0.2.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/Cargo.toml +3 -0
- package/artifacts/bindings-aarch64-apple-darwin/edr.darwin-arm64.node +0 -0
- package/artifacts/bindings-aarch64-pc-windows-msvc/edr.win32-arm64-msvc.node +0 -0
- package/artifacts/bindings-aarch64-unknown-linux-gnu/edr.linux-arm64-gnu.node +0 -0
- package/artifacts/bindings-aarch64-unknown-linux-musl/edr.linux-arm64-musl.node +0 -0
- package/artifacts/bindings-i686-pc-windows-msvc/edr.win32-ia32-msvc.node +0 -0
- package/artifacts/bindings-x86_64-apple-darwin/edr.darwin-x64.node +0 -0
- package/artifacts/bindings-x86_64-pc-windows-msvc/edr.win32-x64-msvc.node +0 -0
- package/artifacts/bindings-x86_64-unknown-linux-gnu/edr.linux-x64-gnu.node +0 -0
- package/artifacts/bindings-x86_64-unknown-linux-musl/edr.linux-x64-musl.node +0 -0
- package/index.d.ts +20 -2
- package/index.js +43 -0
- package/npm/darwin-arm64/edr.darwin-arm64.node +0 -0
- package/npm/darwin-arm64/package.json +1 -1
- package/npm/darwin-x64/edr.darwin-x64.node +0 -0
- package/npm/darwin-x64/package.json +1 -1
- package/npm/linux-arm64-gnu/edr.linux-arm64-gnu.node +0 -0
- package/npm/linux-arm64-gnu/package.json +1 -1
- package/npm/linux-arm64-musl/edr.linux-arm64-musl.node +0 -0
- package/npm/linux-arm64-musl/package.json +1 -1
- package/npm/linux-x64-gnu/edr.linux-x64-gnu.node +0 -0
- package/npm/linux-x64-gnu/package.json +1 -1
- package/npm/linux-x64-musl/edr.linux-x64-musl.node +0 -0
- package/npm/linux-x64-musl/package.json +1 -1
- package/npm/win32-arm64-msvc/edr.win32-arm64-msvc.node +0 -0
- package/npm/win32-arm64-msvc/package.json +1 -1
- package/npm/win32-ia32-msvc/edr.win32-ia32-msvc.node +0 -0
- package/npm/win32-ia32-msvc/package.json +1 -1
- package/npm/win32-x64-msvc/edr.win32-x64-msvc.node +0 -0
- package/npm/win32-x64-msvc/package.json +1 -1
- package/package.json +12 -11
- package/src/block.rs +17 -6
- package/src/call_override.rs +102 -0
- package/src/cast.rs +17 -1
- package/src/lib.rs +4 -0
- package/src/logger.rs +5 -7
- package/src/provider.rs +38 -0
- package/src/scenarios.rs +59 -0
- package/src/withdrawal.rs +49 -0
package/Cargo.toml
CHANGED
|
@@ -27,6 +27,8 @@ tracing-flame = { version = "0.2.0", default-features = false, features = ["smal
|
|
|
27
27
|
tracing-subscriber = { version = "0.3.18", default-features = false, features = ["ansi", "env-filter", "fmt", "parking_lot", "smallvec", "std"] }
|
|
28
28
|
parking_lot = { version = "0.12.1", default-features = false }
|
|
29
29
|
lazy_static = { version = "1.4.0", features = [] }
|
|
30
|
+
rand = { version = "0.8.4", optional = true }
|
|
31
|
+
serde = { version = "1.0.189", features = ["derive"] }
|
|
30
32
|
|
|
31
33
|
[target.x86_64-unknown-linux-gnu.dependencies]
|
|
32
34
|
openssl-sys = { version = "0.9.93", features = ["vendored"] }
|
|
@@ -45,6 +47,7 @@ napi-build = "2.0.1"
|
|
|
45
47
|
|
|
46
48
|
[features]
|
|
47
49
|
tracing = ["edr_evm/tracing"]
|
|
50
|
+
scenarios = ["rand"]
|
|
48
51
|
|
|
49
52
|
[profile.release]
|
|
50
53
|
lto = true
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/index.d.ts
CHANGED
|
@@ -33,8 +33,10 @@ export interface BlockOptions {
|
|
|
33
33
|
nonce?: Buffer
|
|
34
34
|
/** The block's base gas fee */
|
|
35
35
|
baseFee?: bigint
|
|
36
|
-
/** The block's withdrawals
|
|
37
|
-
|
|
36
|
+
/** The block's withdrawals */
|
|
37
|
+
withdrawals?: Array<Withdrawal>
|
|
38
|
+
/** Blob gas was added by EIP-4844 and is ignored in older headers. */
|
|
39
|
+
blobGas?: BlobGas
|
|
38
40
|
/**
|
|
39
41
|
* The hash tree root of the parent beacon block for the given execution
|
|
40
42
|
* block (EIP-4788).
|
|
@@ -56,6 +58,11 @@ export interface BlobGas {
|
|
|
56
58
|
*/
|
|
57
59
|
excessGas: bigint
|
|
58
60
|
}
|
|
61
|
+
/** The result of executing a call override. */
|
|
62
|
+
export interface CallOverrideResult {
|
|
63
|
+
result: Buffer
|
|
64
|
+
shouldRevert: boolean
|
|
65
|
+
}
|
|
59
66
|
/** Identifier for the Ethereum spec. */
|
|
60
67
|
export const enum SpecId {
|
|
61
68
|
/** Frontier */
|
|
@@ -362,6 +369,16 @@ export interface TracingMessageResult {
|
|
|
362
369
|
/** Execution result */
|
|
363
370
|
readonly executionResult: ExecutionResult
|
|
364
371
|
}
|
|
372
|
+
export interface Withdrawal {
|
|
373
|
+
/** The index of withdrawal */
|
|
374
|
+
index: bigint
|
|
375
|
+
/** The index of the validator that generated the withdrawal */
|
|
376
|
+
validatorIndex: bigint
|
|
377
|
+
/** The recipient address for withdrawal value */
|
|
378
|
+
address: Buffer
|
|
379
|
+
/** The value contained in withdrawal */
|
|
380
|
+
amount: bigint
|
|
381
|
+
}
|
|
365
382
|
export class EdrContext {
|
|
366
383
|
/**Creates a new [`EdrContext`] instance. Should only be called once! */
|
|
367
384
|
constructor()
|
|
@@ -372,6 +389,7 @@ export class Provider {
|
|
|
372
389
|
static withConfig(context: EdrContext, config: ProviderConfig, loggerConfig: LoggerConfig, subscriberCallback: (event: SubscriptionEvent) => void): Promise<Provider>
|
|
373
390
|
/**Handles a JSON-RPC request and returns a JSON-RPC response. */
|
|
374
391
|
handleRequest(jsonRequest: string): Promise<Response>
|
|
392
|
+
setCallOverrideCallback(callOverrideCallback: (contract_address: Buffer, data: Buffer) => Promise<CallOverrideResult | undefined>): void
|
|
375
393
|
}
|
|
376
394
|
export class Response {
|
|
377
395
|
get json(): string
|
package/index.js
CHANGED
|
@@ -237,6 +237,49 @@ switch (platform) {
|
|
|
237
237
|
loadError = e
|
|
238
238
|
}
|
|
239
239
|
break
|
|
240
|
+
case 'riscv64':
|
|
241
|
+
if (isMusl()) {
|
|
242
|
+
localFileExisted = existsSync(
|
|
243
|
+
join(__dirname, 'edr.linux-riscv64-musl.node')
|
|
244
|
+
)
|
|
245
|
+
try {
|
|
246
|
+
if (localFileExisted) {
|
|
247
|
+
nativeBinding = require('./edr.linux-riscv64-musl.node')
|
|
248
|
+
} else {
|
|
249
|
+
nativeBinding = require('@nomicfoundation/edr-linux-riscv64-musl')
|
|
250
|
+
}
|
|
251
|
+
} catch (e) {
|
|
252
|
+
loadError = e
|
|
253
|
+
}
|
|
254
|
+
} else {
|
|
255
|
+
localFileExisted = existsSync(
|
|
256
|
+
join(__dirname, 'edr.linux-riscv64-gnu.node')
|
|
257
|
+
)
|
|
258
|
+
try {
|
|
259
|
+
if (localFileExisted) {
|
|
260
|
+
nativeBinding = require('./edr.linux-riscv64-gnu.node')
|
|
261
|
+
} else {
|
|
262
|
+
nativeBinding = require('@nomicfoundation/edr-linux-riscv64-gnu')
|
|
263
|
+
}
|
|
264
|
+
} catch (e) {
|
|
265
|
+
loadError = e
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
break
|
|
269
|
+
case 's390x':
|
|
270
|
+
localFileExisted = existsSync(
|
|
271
|
+
join(__dirname, 'edr.linux-s390x-gnu.node')
|
|
272
|
+
)
|
|
273
|
+
try {
|
|
274
|
+
if (localFileExisted) {
|
|
275
|
+
nativeBinding = require('./edr.linux-s390x-gnu.node')
|
|
276
|
+
} else {
|
|
277
|
+
nativeBinding = require('@nomicfoundation/edr-linux-s390x-gnu')
|
|
278
|
+
}
|
|
279
|
+
} catch (e) {
|
|
280
|
+
loadError = e
|
|
281
|
+
}
|
|
282
|
+
break
|
|
240
283
|
default:
|
|
241
284
|
throw new Error(`Unsupported architecture on Linux: ${arch}`)
|
|
242
285
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nomicfoundation/edr",
|
|
3
|
-
"version": "0.2.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "index.d.ts",
|
|
6
6
|
"repository": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@types/chai": "^4.2.0",
|
|
27
27
|
"@types/chai-as-promised": "^7.1.8",
|
|
28
28
|
"@types/mocha": ">=9.1.0",
|
|
29
|
-
"@types/node": "^
|
|
29
|
+
"@types/node": "^18.0.0",
|
|
30
30
|
"chai": "^4.3.6",
|
|
31
31
|
"chai-as-promised": "^7.1.1",
|
|
32
32
|
"mocha": "^10.0.0",
|
|
@@ -36,21 +36,22 @@
|
|
|
36
36
|
"node": ">= 18"
|
|
37
37
|
},
|
|
38
38
|
"optionalDependencies": {
|
|
39
|
-
"@nomicfoundation/edr-win32-x64-msvc": "0.2.0
|
|
40
|
-
"@nomicfoundation/edr-darwin-x64": "0.2.0
|
|
41
|
-
"@nomicfoundation/edr-linux-x64-gnu": "0.2.0
|
|
42
|
-
"@nomicfoundation/edr-darwin-arm64": "0.2.0
|
|
43
|
-
"@nomicfoundation/edr-win32-arm64-msvc": "0.2.0
|
|
44
|
-
"@nomicfoundation/edr-linux-arm64-gnu": "0.2.0
|
|
45
|
-
"@nomicfoundation/edr-linux-arm64-musl": "0.2.0
|
|
46
|
-
"@nomicfoundation/edr-linux-x64-musl": "0.2.0
|
|
47
|
-
"@nomicfoundation/edr-win32-ia32-msvc": "0.2.0
|
|
39
|
+
"@nomicfoundation/edr-win32-x64-msvc": "0.2.0",
|
|
40
|
+
"@nomicfoundation/edr-darwin-x64": "0.2.0",
|
|
41
|
+
"@nomicfoundation/edr-linux-x64-gnu": "0.2.0",
|
|
42
|
+
"@nomicfoundation/edr-darwin-arm64": "0.2.0",
|
|
43
|
+
"@nomicfoundation/edr-win32-arm64-msvc": "0.2.0",
|
|
44
|
+
"@nomicfoundation/edr-linux-arm64-gnu": "0.2.0",
|
|
45
|
+
"@nomicfoundation/edr-linux-arm64-musl": "0.2.0",
|
|
46
|
+
"@nomicfoundation/edr-linux-x64-musl": "0.2.0",
|
|
47
|
+
"@nomicfoundation/edr-win32-ia32-msvc": "0.2.0"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"artifacts": "napi artifacts",
|
|
51
51
|
"build": "napi build --platform --release",
|
|
52
52
|
"build:debug": "napi build --platform",
|
|
53
53
|
"build:tracing": "napi build --release --features tracing",
|
|
54
|
+
"build:scenarios": "napi build --release --features scenarios",
|
|
54
55
|
"universal": "napi universal",
|
|
55
56
|
"version": "napi version",
|
|
56
57
|
"pretest": "pnpm build",
|
package/src/block.rs
CHANGED
|
@@ -2,7 +2,7 @@ use edr_eth::{Address, Bytes, B256, B64};
|
|
|
2
2
|
use napi::bindgen_prelude::{BigInt, Buffer};
|
|
3
3
|
use napi_derive::napi;
|
|
4
4
|
|
|
5
|
-
use crate::cast::TryCast;
|
|
5
|
+
use crate::{cast::TryCast, withdrawal::Withdrawal};
|
|
6
6
|
|
|
7
7
|
#[napi(object)]
|
|
8
8
|
pub struct BlockOptions {
|
|
@@ -28,8 +28,10 @@ pub struct BlockOptions {
|
|
|
28
28
|
pub nonce: Option<Buffer>,
|
|
29
29
|
/// The block's base gas fee
|
|
30
30
|
pub base_fee: Option<BigInt>,
|
|
31
|
-
/// The block's withdrawals
|
|
32
|
-
pub
|
|
31
|
+
/// The block's withdrawals
|
|
32
|
+
pub withdrawals: Option<Vec<Withdrawal>>,
|
|
33
|
+
/// Blob gas was added by EIP-4844 and is ignored in older headers.
|
|
34
|
+
pub blob_gas: Option<BlobGas>,
|
|
33
35
|
/// The hash tree root of the parent beacon block for the given execution
|
|
34
36
|
/// block (EIP-4788).
|
|
35
37
|
pub parent_beacon_block_root: Option<Buffer>,
|
|
@@ -73,9 +75,18 @@ impl TryFrom<BlockOptions> for edr_eth::block::BlockOptions {
|
|
|
73
75
|
base_fee: value
|
|
74
76
|
.base_fee
|
|
75
77
|
.map_or(Ok(None), |basefee| basefee.try_cast().map(Some))?,
|
|
76
|
-
|
|
77
|
-
.
|
|
78
|
-
.map(
|
|
78
|
+
withdrawals: value
|
|
79
|
+
.withdrawals
|
|
80
|
+
.map(|withdrawals| {
|
|
81
|
+
withdrawals
|
|
82
|
+
.into_iter()
|
|
83
|
+
.map(edr_eth::withdrawal::Withdrawal::try_from)
|
|
84
|
+
.collect()
|
|
85
|
+
})
|
|
86
|
+
.transpose()?,
|
|
87
|
+
blob_gas: value
|
|
88
|
+
.blob_gas
|
|
89
|
+
.map(edr_eth::block::BlobGas::try_from)
|
|
79
90
|
.transpose()?,
|
|
80
91
|
parent_beacon_block_root: value
|
|
81
92
|
.parent_beacon_block_root
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
use std::sync::mpsc::{channel, Sender};
|
|
2
|
+
|
|
3
|
+
use edr_eth::{Address, Bytes};
|
|
4
|
+
use napi::{bindgen_prelude::Buffer, Env, JsFunction, NapiRaw, Status};
|
|
5
|
+
use napi_derive::napi;
|
|
6
|
+
|
|
7
|
+
use crate::{
|
|
8
|
+
cast::TryCast,
|
|
9
|
+
sync::{await_promise, handle_error},
|
|
10
|
+
threadsafe_function::{ThreadSafeCallContext, ThreadsafeFunction, ThreadsafeFunctionCallMode},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/// The result of executing a call override.
|
|
14
|
+
#[napi(object)]
|
|
15
|
+
pub struct CallOverrideResult {
|
|
16
|
+
pub result: Buffer,
|
|
17
|
+
pub should_revert: bool,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
impl TryCast<Option<edr_provider::CallOverrideResult>> for Option<CallOverrideResult> {
|
|
21
|
+
type Error = napi::Error;
|
|
22
|
+
|
|
23
|
+
fn try_cast(self) -> Result<Option<edr_provider::CallOverrideResult>, Self::Error> {
|
|
24
|
+
match self {
|
|
25
|
+
None => Ok(None),
|
|
26
|
+
Some(result) => Ok(Some(edr_provider::CallOverrideResult {
|
|
27
|
+
result: result.result.try_cast()?,
|
|
28
|
+
should_revert: result.should_revert,
|
|
29
|
+
})),
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
struct CallOverrideCall {
|
|
35
|
+
contract_address: Address,
|
|
36
|
+
data: Bytes,
|
|
37
|
+
sender: Sender<napi::Result<Option<edr_provider::CallOverrideResult>>>,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#[derive(Clone)]
|
|
41
|
+
pub struct CallOverrideCallback {
|
|
42
|
+
call_override_callback_fn: ThreadsafeFunction<CallOverrideCall>,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
impl CallOverrideCallback {
|
|
46
|
+
pub fn new(env: &Env, call_override_callback: JsFunction) -> napi::Result<Self> {
|
|
47
|
+
let call_override_callback_fn = ThreadsafeFunction::create(
|
|
48
|
+
env.raw(),
|
|
49
|
+
// SAFETY: The callback is guaranteed to be valid for the lifetime of the inspector.
|
|
50
|
+
unsafe { call_override_callback.raw() },
|
|
51
|
+
0,
|
|
52
|
+
|ctx: ThreadSafeCallContext<CallOverrideCall>| {
|
|
53
|
+
let address = ctx
|
|
54
|
+
.env
|
|
55
|
+
.create_buffer_with_data(ctx.value.contract_address.to_vec())?
|
|
56
|
+
.into_raw();
|
|
57
|
+
|
|
58
|
+
let data = ctx
|
|
59
|
+
.env
|
|
60
|
+
.create_buffer_with_data(ctx.value.data.to_vec())?
|
|
61
|
+
.into_raw();
|
|
62
|
+
|
|
63
|
+
let sender = ctx.value.sender.clone();
|
|
64
|
+
let promise = ctx.callback.call(None, &[address, data])?;
|
|
65
|
+
let result = await_promise::<
|
|
66
|
+
Option<CallOverrideResult>,
|
|
67
|
+
Option<edr_provider::CallOverrideResult>,
|
|
68
|
+
>(ctx.env, promise, ctx.value.sender);
|
|
69
|
+
|
|
70
|
+
handle_error(sender, result)
|
|
71
|
+
},
|
|
72
|
+
)?;
|
|
73
|
+
|
|
74
|
+
Ok(Self {
|
|
75
|
+
call_override_callback_fn,
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
pub fn call_override(
|
|
80
|
+
&self,
|
|
81
|
+
contract_address: Address,
|
|
82
|
+
data: Bytes,
|
|
83
|
+
) -> Option<edr_provider::CallOverrideResult> {
|
|
84
|
+
let (sender, receiver) = channel();
|
|
85
|
+
|
|
86
|
+
let status = self.call_override_callback_fn.call(
|
|
87
|
+
CallOverrideCall {
|
|
88
|
+
contract_address,
|
|
89
|
+
data,
|
|
90
|
+
sender,
|
|
91
|
+
},
|
|
92
|
+
ThreadsafeFunctionCallMode::Blocking,
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
assert_eq!(status, Status::Ok, "Call override callback failed");
|
|
96
|
+
|
|
97
|
+
receiver
|
|
98
|
+
.recv()
|
|
99
|
+
.unwrap()
|
|
100
|
+
.expect("Failed call to call_override_callback")
|
|
101
|
+
}
|
|
102
|
+
}
|
package/src/cast.rs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
use edr_eth::{Address, B256, B64, U256};
|
|
1
|
+
use edr_eth::{Address, Bytes, B256, B64, U256};
|
|
2
2
|
use napi::{
|
|
3
3
|
bindgen_prelude::{BigInt, Buffer},
|
|
4
4
|
Status,
|
|
@@ -117,3 +117,19 @@ impl<T> TryCast<T> for T {
|
|
|
117
117
|
Ok(self)
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
|
+
|
|
121
|
+
impl TryCast<Bytes> for Buffer {
|
|
122
|
+
type Error = napi::Error;
|
|
123
|
+
|
|
124
|
+
fn try_cast(self) -> Result<Bytes, Self::Error> {
|
|
125
|
+
Ok(Bytes::copy_from_slice(&self))
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
impl TryCast<Option<Bytes>> for Option<Buffer> {
|
|
130
|
+
type Error = napi::Error;
|
|
131
|
+
|
|
132
|
+
fn try_cast(self) -> Result<Option<Bytes>, Self::Error> {
|
|
133
|
+
Ok(self.map(|buffer| Bytes::copy_from_slice(&buffer)))
|
|
134
|
+
}
|
|
135
|
+
}
|
package/src/lib.rs
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
mod account;
|
|
6
6
|
mod block;
|
|
7
|
+
mod call_override;
|
|
7
8
|
mod cast;
|
|
8
9
|
mod config;
|
|
9
10
|
mod context;
|
|
@@ -12,7 +13,10 @@ mod log;
|
|
|
12
13
|
mod logger;
|
|
13
14
|
mod provider;
|
|
14
15
|
mod result;
|
|
16
|
+
#[cfg(feature = "scenarios")]
|
|
17
|
+
mod scenarios;
|
|
15
18
|
mod subscribe;
|
|
16
19
|
mod sync;
|
|
17
20
|
mod threadsafe_function;
|
|
18
21
|
mod trace;
|
|
22
|
+
mod withdrawal;
|
package/src/logger.rs
CHANGED
|
@@ -410,11 +410,9 @@ impl LogCollector {
|
|
|
410
410
|
|
|
411
411
|
logger.log_console_log_messages(console_log_inputs);
|
|
412
412
|
|
|
413
|
-
if let Some(transaction_failure) =
|
|
414
|
-
execution_result,
|
|
415
|
-
|
|
416
|
-
trace,
|
|
417
|
-
) {
|
|
413
|
+
if let Some(transaction_failure) =
|
|
414
|
+
TransactionFailure::from_execution_result(execution_result, None, trace)
|
|
415
|
+
{
|
|
418
416
|
logger.log_transaction_failure(&transaction_failure);
|
|
419
417
|
}
|
|
420
418
|
});
|
|
@@ -782,7 +780,7 @@ impl LogCollector {
|
|
|
782
780
|
|
|
783
781
|
let transaction_failure = edr_provider::TransactionFailure::from_execution_result(
|
|
784
782
|
result,
|
|
785
|
-
transaction_hash,
|
|
783
|
+
Some(transaction_hash),
|
|
786
784
|
trace,
|
|
787
785
|
);
|
|
788
786
|
|
|
@@ -1158,7 +1156,7 @@ impl LogCollector {
|
|
|
1158
1156
|
|
|
1159
1157
|
let transaction_failure = edr_provider::TransactionFailure::from_execution_result(
|
|
1160
1158
|
transaction_result,
|
|
1161
|
-
transaction_hash,
|
|
1159
|
+
Some(transaction_hash),
|
|
1162
1160
|
trace,
|
|
1163
1161
|
);
|
|
1164
1162
|
|
package/src/provider.rs
CHANGED
|
@@ -9,6 +9,7 @@ use napi_derive::napi;
|
|
|
9
9
|
|
|
10
10
|
use self::config::ProviderConfig;
|
|
11
11
|
use crate::{
|
|
12
|
+
call_override::CallOverrideCallback,
|
|
12
13
|
context::EdrContext,
|
|
13
14
|
logger::{Logger, LoggerConfig, LoggerError},
|
|
14
15
|
subscribe::SubscriberCallback,
|
|
@@ -19,6 +20,8 @@ use crate::{
|
|
|
19
20
|
#[napi]
|
|
20
21
|
pub struct Provider {
|
|
21
22
|
provider: Arc<edr_provider::Provider<LoggerError>>,
|
|
23
|
+
#[cfg(feature = "scenarios")]
|
|
24
|
+
scenario_file: Option<napi::tokio::sync::Mutex<napi::tokio::fs::File>>,
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
#[napi]
|
|
@@ -42,17 +45,27 @@ impl Provider {
|
|
|
42
45
|
|
|
43
46
|
let (deferred, promise) = env.create_deferred()?;
|
|
44
47
|
runtime.clone().spawn_blocking(move || {
|
|
48
|
+
#[cfg(feature = "scenarios")]
|
|
49
|
+
let scenario_file =
|
|
50
|
+
runtime::Handle::current().block_on(crate::scenarios::scenario_file(
|
|
51
|
+
&config,
|
|
52
|
+
edr_provider::Logger::is_enabled(&*logger),
|
|
53
|
+
))?;
|
|
54
|
+
|
|
45
55
|
let result = edr_provider::Provider::new(runtime, logger, subscriber_callback, config)
|
|
46
56
|
.map_or_else(
|
|
47
57
|
|error| Err(napi::Error::new(Status::GenericFailure, error.to_string())),
|
|
48
58
|
|provider| {
|
|
49
59
|
Ok(Provider {
|
|
50
60
|
provider: Arc::new(provider),
|
|
61
|
+
#[cfg(feature = "scenarios")]
|
|
62
|
+
scenario_file,
|
|
51
63
|
})
|
|
52
64
|
},
|
|
53
65
|
);
|
|
54
66
|
|
|
55
67
|
deferred.resolve(|_env| result);
|
|
68
|
+
Ok::<_, napi::Error>(())
|
|
56
69
|
});
|
|
57
70
|
|
|
58
71
|
Ok(promise)
|
|
@@ -107,6 +120,11 @@ impl Provider {
|
|
|
107
120
|
}
|
|
108
121
|
};
|
|
109
122
|
|
|
123
|
+
#[cfg(feature = "scenarios")]
|
|
124
|
+
if let Some(scenario_file) = &self.scenario_file {
|
|
125
|
+
crate::scenarios::write_request(scenario_file, &request).await?;
|
|
126
|
+
}
|
|
127
|
+
|
|
110
128
|
let mut response = runtime::Handle::current()
|
|
111
129
|
.spawn_blocking(move || provider.handle_request(request))
|
|
112
130
|
.await
|
|
@@ -149,6 +167,26 @@ impl Provider {
|
|
|
149
167
|
traces: traces.into_iter().map(Arc::new).collect(),
|
|
150
168
|
})
|
|
151
169
|
}
|
|
170
|
+
|
|
171
|
+
#[napi(ts_return_type = "void")]
|
|
172
|
+
pub fn set_call_override_callback(
|
|
173
|
+
&self,
|
|
174
|
+
env: Env,
|
|
175
|
+
#[napi(
|
|
176
|
+
ts_arg_type = "(contract_address: Buffer, data: Buffer) => Promise<CallOverrideResult | undefined>"
|
|
177
|
+
)]
|
|
178
|
+
call_override_callback: JsFunction,
|
|
179
|
+
) -> napi::Result<()> {
|
|
180
|
+
let provider = self.provider.clone();
|
|
181
|
+
|
|
182
|
+
let call_override_callback = CallOverrideCallback::new(&env, call_override_callback)?;
|
|
183
|
+
let call_override_callback =
|
|
184
|
+
Arc::new(move |address, data| call_override_callback.call_override(address, data));
|
|
185
|
+
|
|
186
|
+
provider.set_call_override_callback(Some(call_override_callback));
|
|
187
|
+
|
|
188
|
+
Ok(())
|
|
189
|
+
}
|
|
152
190
|
}
|
|
153
191
|
|
|
154
192
|
#[napi]
|
package/src/scenarios.rs
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
use std::time::{SystemTime, UNIX_EPOCH};
|
|
2
|
+
|
|
3
|
+
use edr_provider::ProviderRequest;
|
|
4
|
+
use napi::tokio::{fs::File, io::AsyncWriteExt, sync::Mutex};
|
|
5
|
+
use rand::{distributions::Alphanumeric, Rng};
|
|
6
|
+
use serde::Serialize;
|
|
7
|
+
|
|
8
|
+
const SCENARIO_FILE_PREFIX: &str = "EDR_SCENARIO_PREFIX";
|
|
9
|
+
|
|
10
|
+
#[derive(Clone, Debug, Serialize)]
|
|
11
|
+
struct ScenarioConfig<'a> {
|
|
12
|
+
provider_config: &'a edr_provider::ProviderConfig,
|
|
13
|
+
logger_enabled: bool,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
pub(crate) async fn scenario_file(
|
|
17
|
+
provider_config: &edr_provider::ProviderConfig,
|
|
18
|
+
logger_enabled: bool,
|
|
19
|
+
) -> Result<Option<Mutex<File>>, napi::Error> {
|
|
20
|
+
if let Ok(scenario_prefix) = std::env::var(SCENARIO_FILE_PREFIX) {
|
|
21
|
+
let timestamp = SystemTime::now()
|
|
22
|
+
.duration_since(UNIX_EPOCH)
|
|
23
|
+
.expect("Time went backwards")
|
|
24
|
+
.as_secs();
|
|
25
|
+
let suffix = rand::thread_rng()
|
|
26
|
+
.sample_iter(&Alphanumeric)
|
|
27
|
+
.take(4)
|
|
28
|
+
.map(char::from)
|
|
29
|
+
.collect::<String>();
|
|
30
|
+
|
|
31
|
+
let mut scenario_file =
|
|
32
|
+
File::create(format!("{scenario_prefix}_{timestamp}_{suffix}.json")).await?;
|
|
33
|
+
|
|
34
|
+
let config = ScenarioConfig {
|
|
35
|
+
provider_config,
|
|
36
|
+
logger_enabled,
|
|
37
|
+
};
|
|
38
|
+
let mut line = serde_json::to_string(&config)?;
|
|
39
|
+
line.push('\n');
|
|
40
|
+
scenario_file.write_all(line.as_bytes()).await?;
|
|
41
|
+
|
|
42
|
+
Ok(Some(Mutex::new(scenario_file)))
|
|
43
|
+
} else {
|
|
44
|
+
Ok(None)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
pub(crate) async fn write_request(
|
|
49
|
+
scenario_file: &Mutex<File>,
|
|
50
|
+
request: &ProviderRequest,
|
|
51
|
+
) -> napi::Result<()> {
|
|
52
|
+
let mut line = serde_json::to_string(request)?;
|
|
53
|
+
line.push('\n');
|
|
54
|
+
{
|
|
55
|
+
let mut scenario_file = scenario_file.lock().await;
|
|
56
|
+
scenario_file.write_all(line.as_bytes()).await?;
|
|
57
|
+
}
|
|
58
|
+
Ok(())
|
|
59
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
use edr_eth::Address;
|
|
2
|
+
use napi::bindgen_prelude::{BigInt, Buffer};
|
|
3
|
+
use napi_derive::napi;
|
|
4
|
+
|
|
5
|
+
use crate::cast::TryCast;
|
|
6
|
+
|
|
7
|
+
#[napi(object)]
|
|
8
|
+
pub struct Withdrawal {
|
|
9
|
+
/// The index of withdrawal
|
|
10
|
+
pub index: BigInt,
|
|
11
|
+
/// The index of the validator that generated the withdrawal
|
|
12
|
+
pub validator_index: BigInt,
|
|
13
|
+
/// The recipient address for withdrawal value
|
|
14
|
+
pub address: Buffer,
|
|
15
|
+
/// The value contained in withdrawal
|
|
16
|
+
pub amount: BigInt,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
impl From<edr_eth::withdrawal::Withdrawal> for Withdrawal {
|
|
20
|
+
fn from(withdrawal: edr_eth::withdrawal::Withdrawal) -> Self {
|
|
21
|
+
Self {
|
|
22
|
+
index: BigInt::from(withdrawal.index),
|
|
23
|
+
validator_index: BigInt::from(withdrawal.validator_index),
|
|
24
|
+
address: Buffer::from(withdrawal.address.as_slice()),
|
|
25
|
+
amount: BigInt {
|
|
26
|
+
sign_bit: false,
|
|
27
|
+
words: withdrawal.amount.as_limbs().to_vec(),
|
|
28
|
+
},
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
impl TryFrom<Withdrawal> for edr_eth::withdrawal::Withdrawal {
|
|
34
|
+
type Error = napi::Error;
|
|
35
|
+
|
|
36
|
+
fn try_from(value: Withdrawal) -> Result<Self, Self::Error> {
|
|
37
|
+
let index: u64 = BigInt::try_cast(value.index)?;
|
|
38
|
+
let validator_index: u64 = BigInt::try_cast(value.validator_index)?;
|
|
39
|
+
let amount = BigInt::try_cast(value.amount)?;
|
|
40
|
+
let address = Address::from_slice(&value.address);
|
|
41
|
+
|
|
42
|
+
Ok(Self {
|
|
43
|
+
index,
|
|
44
|
+
validator_index,
|
|
45
|
+
address,
|
|
46
|
+
amount,
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
}
|