@nomicfoundation/edr 0.11.0 → 0.12.0-alpha.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 +26 -23
- package/index.d.ts +138 -69
- package/index.js +31 -3
- package/package.json +12 -10
- package/src/account.rs +41 -11
- package/src/block.rs +1 -1
- package/src/call_override.rs +1 -1
- package/src/cast.rs +54 -2
- package/src/chains/generic.rs +51 -0
- package/src/chains/l1.rs +260 -0
- package/src/chains/op.rs +368 -0
- package/src/chains.rs +7 -0
- package/src/config.rs +393 -67
- package/src/context.rs +135 -17
- package/src/lib.rs +28 -14
- package/src/log.rs +2 -2
- package/src/logger.rs +54 -1152
- package/src/provider/factory.rs +22 -0
- package/src/provider/response.rs +70 -0
- package/src/provider.rs +55 -322
- package/src/result.rs +44 -44
- package/src/scenarios.rs +12 -18
- package/src/subscription.rs +32 -0
- package/src/trace/exit.rs +8 -9
- package/src/trace/return_data.rs +1 -1
- package/src/trace/solidity_stack_trace.rs +5 -4
- package/src/trace.rs +9 -7
- package/src/withdrawal.rs +1 -1
- package/src/provider/config.rs +0 -291
- package/src/subscribe.rs +0 -63
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
use std::sync::Arc;
|
|
2
|
+
|
|
3
|
+
use edr_napi_core::provider::SyncProviderFactory;
|
|
4
|
+
use napi_derive::napi;
|
|
5
|
+
|
|
6
|
+
#[napi]
|
|
7
|
+
pub struct ProviderFactory {
|
|
8
|
+
inner: Arc<dyn SyncProviderFactory>,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
impl ProviderFactory {
|
|
12
|
+
/// Returns a reference to the inner provider factory.
|
|
13
|
+
pub fn as_inner(&self) -> &Arc<dyn SyncProviderFactory> {
|
|
14
|
+
&self.inner
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
impl From<Arc<dyn SyncProviderFactory>> for ProviderFactory {
|
|
19
|
+
fn from(inner: Arc<dyn SyncProviderFactory>) -> Self {
|
|
20
|
+
Self { inner }
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
use edr_eth::l1;
|
|
2
|
+
use edr_napi_core::spec::SolidityTraceData;
|
|
3
|
+
use napi::Either;
|
|
4
|
+
use napi_derive::napi;
|
|
5
|
+
|
|
6
|
+
use crate::{
|
|
7
|
+
cast::TryCast,
|
|
8
|
+
trace::{RawTrace, solidity_stack_trace::SolidityStackTrace},
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
#[napi]
|
|
12
|
+
pub struct Response {
|
|
13
|
+
inner: edr_napi_core::spec::Response<l1::HaltReason>,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
impl From<edr_napi_core::spec::Response<l1::HaltReason>> for Response {
|
|
17
|
+
fn from(value: edr_napi_core::spec::Response<l1::HaltReason>) -> Self {
|
|
18
|
+
Self { inner: value }
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
#[napi]
|
|
23
|
+
impl Response {
|
|
24
|
+
#[doc = "Returns the response data as a JSON string or a JSON object."]
|
|
25
|
+
#[napi(getter)]
|
|
26
|
+
pub fn data(&self) -> Either<String, serde_json::Value> {
|
|
27
|
+
self.inner.data.clone()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Rust port of https://github.com/NomicFoundation/hardhat/blob/c20bf195a6efdc2d74e778b7a4a7799aac224841/packages/hardhat-core/src/internal/hardhat-network/provider/provider.ts#L590
|
|
31
|
+
#[doc = "Compute the error stack trace. Return the stack trace if it can be decoded, otherwise returns none. Throws if there was an error computing the stack trace."]
|
|
32
|
+
#[napi]
|
|
33
|
+
pub fn stack_trace(&self) -> napi::Result<Option<SolidityStackTrace>> {
|
|
34
|
+
let Some(SolidityTraceData {
|
|
35
|
+
trace,
|
|
36
|
+
contract_decoder,
|
|
37
|
+
}) = &self.inner.solidity_trace
|
|
38
|
+
else {
|
|
39
|
+
return Ok(None);
|
|
40
|
+
};
|
|
41
|
+
let nested_trace = edr_solidity::nested_tracer::convert_trace_messages_to_nested_trace(
|
|
42
|
+
trace.as_ref().clone(),
|
|
43
|
+
)
|
|
44
|
+
.map_err(|err| napi::Error::from_reason(err.to_string()))?;
|
|
45
|
+
|
|
46
|
+
if let Some(vm_trace) = nested_trace {
|
|
47
|
+
let decoded_trace = contract_decoder.try_to_decode_message_trace(vm_trace);
|
|
48
|
+
let stack_trace = edr_solidity::solidity_tracer::get_stack_trace(decoded_trace)
|
|
49
|
+
.map_err(|err| napi::Error::from_reason(err.to_string()))?;
|
|
50
|
+
let stack_trace = stack_trace
|
|
51
|
+
.into_iter()
|
|
52
|
+
.map(TryCast::try_cast)
|
|
53
|
+
.collect::<Result<Vec<_>, _>>()?;
|
|
54
|
+
|
|
55
|
+
Ok(Some(stack_trace))
|
|
56
|
+
} else {
|
|
57
|
+
Ok(None)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
#[doc = "Returns the raw traces of executed contracts. This maybe contain zero or more traces."]
|
|
62
|
+
#[napi(getter)]
|
|
63
|
+
pub fn traces(&self) -> Vec<RawTrace> {
|
|
64
|
+
self.inner
|
|
65
|
+
.traces
|
|
66
|
+
.iter()
|
|
67
|
+
.map(|trace| RawTrace::from(trace.clone()))
|
|
68
|
+
.collect()
|
|
69
|
+
}
|
|
70
|
+
}
|
package/src/provider.rs
CHANGED
|
@@ -1,223 +1,70 @@
|
|
|
1
|
-
|
|
1
|
+
/// Types related to provider factories.
|
|
2
|
+
pub mod factory;
|
|
3
|
+
mod response;
|
|
2
4
|
|
|
3
5
|
use std::sync::Arc;
|
|
4
6
|
|
|
5
|
-
use
|
|
6
|
-
use edr_rpc_eth::jsonrpc;
|
|
7
|
+
use edr_napi_core::provider::SyncProvider;
|
|
7
8
|
use edr_solidity::contract_decoder::ContractDecoder;
|
|
8
|
-
use napi::{
|
|
9
|
-
bindgen_prelude::Uint8Array, tokio::runtime, Either, Env, JsFunction, JsObject, Status,
|
|
10
|
-
};
|
|
9
|
+
use napi::{Env, JsFunction, JsObject, Status, tokio::runtime};
|
|
11
10
|
use napi_derive::napi;
|
|
12
11
|
|
|
13
|
-
use self::
|
|
14
|
-
use
|
|
15
|
-
|
|
16
|
-
context::EdrContext,
|
|
17
|
-
logger::{Logger, LoggerConfig, LoggerError},
|
|
18
|
-
subscribe::SubscriberCallback,
|
|
19
|
-
trace::{solidity_stack_trace::SolidityStackTrace, RawTrace},
|
|
20
|
-
};
|
|
12
|
+
pub use self::factory::ProviderFactory;
|
|
13
|
+
use self::response::Response;
|
|
14
|
+
use crate::call_override::CallOverrideCallback;
|
|
21
15
|
|
|
22
16
|
/// A JSON-RPC provider for Ethereum.
|
|
23
17
|
#[napi]
|
|
24
18
|
pub struct Provider {
|
|
25
|
-
provider: Arc<edr_provider::Provider<LoggerError>>,
|
|
26
|
-
runtime: runtime::Handle,
|
|
27
19
|
contract_decoder: Arc<ContractDecoder>,
|
|
20
|
+
provider: Arc<dyn SyncProvider>,
|
|
21
|
+
runtime: runtime::Handle,
|
|
28
22
|
#[cfg(feature = "scenarios")]
|
|
29
23
|
scenario_file: Option<napi::tokio::sync::Mutex<napi::tokio::fs::File>>,
|
|
30
24
|
}
|
|
31
25
|
|
|
32
|
-
#[napi]
|
|
33
26
|
impl Provider {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
let config = edr_provider::ProviderConfig::try_from(config)?;
|
|
48
|
-
|
|
49
|
-
// TODO https://github.com/NomicFoundation/edr/issues/760
|
|
50
|
-
let build_info_config =
|
|
51
|
-
edr_solidity::artifacts::BuildInfoConfig::parse_from_buffers((&tracing_config).into())
|
|
52
|
-
.map_err(|err| napi::Error::from_reason(err.to_string()))?;
|
|
53
|
-
let contract_decoder = ContractDecoder::new(&build_info_config)
|
|
54
|
-
.map_err(|error| napi::Error::from_reason(error.to_string()))?;
|
|
55
|
-
let contract_decoder = Arc::new(contract_decoder);
|
|
56
|
-
|
|
57
|
-
let logger = Box::new(Logger::new(
|
|
58
|
-
&env,
|
|
59
|
-
logger_config,
|
|
60
|
-
Arc::clone(&contract_decoder),
|
|
61
|
-
)?);
|
|
62
|
-
let subscriber_callback = SubscriberCallback::new(&env, subscriber_callback)?;
|
|
63
|
-
let subscriber_callback = Box::new(move |event| subscriber_callback.call(event));
|
|
64
|
-
|
|
65
|
-
let (deferred, promise) = env.create_deferred()?;
|
|
66
|
-
runtime.clone().spawn_blocking(move || {
|
|
27
|
+
/// Constructs a new instance.
|
|
28
|
+
pub fn new(
|
|
29
|
+
provider: Arc<dyn SyncProvider>,
|
|
30
|
+
runtime: runtime::Handle,
|
|
31
|
+
contract_decoder: Arc<ContractDecoder>,
|
|
32
|
+
#[cfg(feature = "scenarios")] scenario_file: Option<
|
|
33
|
+
napi::tokio::sync::Mutex<napi::tokio::fs::File>,
|
|
34
|
+
>,
|
|
35
|
+
) -> Self {
|
|
36
|
+
Self {
|
|
37
|
+
contract_decoder,
|
|
38
|
+
provider,
|
|
39
|
+
runtime,
|
|
67
40
|
#[cfg(feature = "scenarios")]
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
&config,
|
|
71
|
-
edr_provider::Logger::is_enabled(&*logger),
|
|
72
|
-
))?;
|
|
73
|
-
|
|
74
|
-
let result = edr_provider::Provider::new(
|
|
75
|
-
runtime.clone(),
|
|
76
|
-
logger,
|
|
77
|
-
subscriber_callback,
|
|
78
|
-
config,
|
|
79
|
-
Arc::clone(&contract_decoder),
|
|
80
|
-
CurrentTime,
|
|
81
|
-
)
|
|
82
|
-
.map_or_else(
|
|
83
|
-
|error| Err(napi::Error::new(Status::GenericFailure, error.to_string())),
|
|
84
|
-
|provider| {
|
|
85
|
-
Ok(Provider {
|
|
86
|
-
provider: Arc::new(provider),
|
|
87
|
-
runtime,
|
|
88
|
-
contract_decoder,
|
|
89
|
-
#[cfg(feature = "scenarios")]
|
|
90
|
-
scenario_file,
|
|
91
|
-
})
|
|
92
|
-
},
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
deferred.resolve(|_env| result);
|
|
96
|
-
Ok::<_, napi::Error>(())
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
Ok(promise)
|
|
41
|
+
scenario_file,
|
|
42
|
+
}
|
|
100
43
|
}
|
|
44
|
+
}
|
|
101
45
|
|
|
46
|
+
#[napi]
|
|
47
|
+
impl Provider {
|
|
102
48
|
#[doc = "Handles a JSON-RPC request and returns a JSON-RPC response."]
|
|
103
49
|
#[napi]
|
|
104
|
-
pub async fn handle_request(&self,
|
|
50
|
+
pub async fn handle_request(&self, request: String) -> napi::Result<Response> {
|
|
105
51
|
let provider = self.provider.clone();
|
|
106
|
-
let request = match serde_json::from_str(&json_request) {
|
|
107
|
-
Ok(request) => request,
|
|
108
|
-
Err(error) => {
|
|
109
|
-
let message = error.to_string();
|
|
110
|
-
let reason = InvalidRequestReason::new(&json_request, &message);
|
|
111
|
-
|
|
112
|
-
// HACK: We need to log failed deserialization attempts when they concern input
|
|
113
|
-
// validation.
|
|
114
|
-
if let Some((method_name, provider_error)) = reason.provider_error() {
|
|
115
|
-
// Ignore potential failure of logging, as returning the original error is more
|
|
116
|
-
// important
|
|
117
|
-
let _result = runtime::Handle::current()
|
|
118
|
-
.spawn_blocking(move || {
|
|
119
|
-
provider.log_failed_deserialization(&method_name, &provider_error)
|
|
120
|
-
})
|
|
121
|
-
.await
|
|
122
|
-
.map_err(|error| {
|
|
123
|
-
napi::Error::new(Status::GenericFailure, error.to_string())
|
|
124
|
-
})?;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
let data = serde_json::from_str(&json_request).ok();
|
|
128
|
-
let response = jsonrpc::ResponseData::<()>::Error {
|
|
129
|
-
error: jsonrpc::Error {
|
|
130
|
-
code: reason.error_code(),
|
|
131
|
-
message: reason.error_message(),
|
|
132
|
-
data,
|
|
133
|
-
},
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
return serde_json::to_string(&response)
|
|
137
|
-
.map_err(|error| {
|
|
138
|
-
napi::Error::new(
|
|
139
|
-
Status::InvalidArg,
|
|
140
|
-
format!("Invalid JSON `{json_request}` due to: {error}"),
|
|
141
|
-
)
|
|
142
|
-
})
|
|
143
|
-
.map(|json| Response {
|
|
144
|
-
solidity_trace: None,
|
|
145
|
-
data: Either::A(json),
|
|
146
|
-
traces: Vec::new(),
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
52
|
|
|
151
53
|
#[cfg(feature = "scenarios")]
|
|
152
54
|
if let Some(scenario_file) = &self.scenario_file {
|
|
153
55
|
crate::scenarios::write_request(scenario_file, &request).await?;
|
|
154
56
|
}
|
|
155
57
|
|
|
156
|
-
let
|
|
157
|
-
.spawn_blocking(move || provider.handle_request(request))
|
|
158
|
-
.await
|
|
159
|
-
.map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string()))?;
|
|
160
|
-
|
|
161
|
-
// We can take the solidity trace as it won't be used for anything else
|
|
162
|
-
let solidity_trace = response.as_mut().err().and_then(|error| {
|
|
163
|
-
if let edr_provider::ProviderError::TransactionFailed(failure) = error {
|
|
164
|
-
if matches!(
|
|
165
|
-
failure.failure.reason,
|
|
166
|
-
edr_provider::TransactionFailureReason::OutOfGas(_)
|
|
167
|
-
) {
|
|
168
|
-
None
|
|
169
|
-
} else {
|
|
170
|
-
Some(Arc::new(std::mem::take(
|
|
171
|
-
&mut failure.failure.solidity_trace,
|
|
172
|
-
)))
|
|
173
|
-
}
|
|
174
|
-
} else {
|
|
175
|
-
None
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// We can take the traces as they won't be used for anything else
|
|
180
|
-
let traces = match &mut response {
|
|
181
|
-
Ok(response) => std::mem::take(&mut response.traces),
|
|
182
|
-
Err(edr_provider::ProviderError::TransactionFailed(failure)) => {
|
|
183
|
-
std::mem::take(&mut failure.traces)
|
|
184
|
-
}
|
|
185
|
-
Err(_) => Vec::new(),
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
let response = jsonrpc::ResponseData::from(response.map(|response| response.result));
|
|
58
|
+
let contract_decoder = Arc::clone(&self.contract_decoder);
|
|
189
59
|
|
|
190
|
-
|
|
191
|
-
.
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
// > Failed to convert rust `String` into napi `string`
|
|
196
|
-
//
|
|
197
|
-
// To be safe, we're limiting string lengths to half of that.
|
|
198
|
-
const MAX_STRING_LENGTH: usize = 250_000_000;
|
|
199
|
-
|
|
200
|
-
if json.len() <= MAX_STRING_LENGTH {
|
|
201
|
-
Ok(Either::A(json))
|
|
202
|
-
} else {
|
|
203
|
-
serde_json::to_value(response).map(Either::B)
|
|
204
|
-
}
|
|
205
|
-
})
|
|
206
|
-
.map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))
|
|
207
|
-
.map(|data| {
|
|
208
|
-
let solidity_trace = solidity_trace.map(|trace| SolidityTraceData {
|
|
209
|
-
trace,
|
|
210
|
-
contract_decoder: Arc::clone(&self.contract_decoder),
|
|
211
|
-
});
|
|
212
|
-
Response {
|
|
213
|
-
solidity_trace,
|
|
214
|
-
data,
|
|
215
|
-
traces: traces.into_iter().map(Arc::new).collect(),
|
|
216
|
-
}
|
|
217
|
-
})
|
|
60
|
+
self.runtime
|
|
61
|
+
.spawn_blocking(move || provider.handle_request(request, contract_decoder))
|
|
62
|
+
.await
|
|
63
|
+
.map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))?
|
|
64
|
+
.map(Response::from)
|
|
218
65
|
}
|
|
219
66
|
|
|
220
|
-
#[napi(ts_return_type = "void")]
|
|
67
|
+
#[napi(ts_return_type = "Promise<void>")]
|
|
221
68
|
pub fn set_call_override_callback(
|
|
222
69
|
&self,
|
|
223
70
|
env: Env,
|
|
@@ -225,152 +72,38 @@ impl Provider {
|
|
|
225
72
|
ts_arg_type = "(contract_address: Buffer, data: Buffer) => Promise<CallOverrideResult | undefined>"
|
|
226
73
|
)]
|
|
227
74
|
call_override_callback: JsFunction,
|
|
228
|
-
) -> napi::Result<
|
|
229
|
-
let provider = self.provider.clone();
|
|
230
|
-
|
|
75
|
+
) -> napi::Result<JsObject> {
|
|
231
76
|
let call_override_callback =
|
|
232
77
|
CallOverrideCallback::new(&env, call_override_callback, self.runtime.clone())?;
|
|
78
|
+
|
|
233
79
|
let call_override_callback =
|
|
234
80
|
Arc::new(move |address, data| call_override_callback.call_override(address, data));
|
|
235
81
|
|
|
236
|
-
provider.
|
|
82
|
+
let provider = self.provider.clone();
|
|
83
|
+
|
|
84
|
+
let (deferred, promise) = env.create_deferred()?;
|
|
85
|
+
self.runtime.spawn_blocking(move || {
|
|
86
|
+
provider.set_call_override_callback(call_override_callback);
|
|
87
|
+
|
|
88
|
+
deferred.resolve(|_env| Ok(()));
|
|
89
|
+
});
|
|
237
90
|
|
|
238
|
-
Ok(
|
|
91
|
+
Ok(promise)
|
|
239
92
|
}
|
|
240
93
|
|
|
241
94
|
/// Set to `true` to make the traces returned with `eth_call`,
|
|
242
95
|
/// `eth_estimateGas`, `eth_sendRawTransaction`, `eth_sendTransaction`,
|
|
243
96
|
/// `evm_mine`, `hardhat_mine` include the full stack and memory. Set to
|
|
244
97
|
/// `false` to disable this.
|
|
245
|
-
#[napi(ts_return_type = "void")]
|
|
246
|
-
pub fn set_verbose_tracing(&self, verbose_tracing: bool) {
|
|
247
|
-
self.provider.set_verbose_tracing(verbose_tracing);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/// Tracing config for Solidity stack trace generation.
|
|
252
|
-
#[napi(object)]
|
|
253
|
-
pub struct TracingConfigWithBuffers {
|
|
254
|
-
/// Build information to use for decoding contracts. Either a Hardhat v2
|
|
255
|
-
/// build info file that contains both input and output or a Hardhat v3
|
|
256
|
-
/// build info file that doesn't contain output and a separate output file.
|
|
257
|
-
pub build_infos: Option<Either<Vec<Uint8Array>, Vec<BuildInfoAndOutput>>>,
|
|
258
|
-
/// Whether to ignore contracts whose name starts with "Ignored".
|
|
259
|
-
pub ignore_contracts: Option<bool>,
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/// Hardhat V3 build info where the compiler output is not part of the build
|
|
263
|
-
/// info file.
|
|
264
|
-
#[napi(object)]
|
|
265
|
-
pub struct BuildInfoAndOutput {
|
|
266
|
-
/// The build info input file
|
|
267
|
-
pub build_info: Uint8Array,
|
|
268
|
-
/// The build info output file
|
|
269
|
-
pub output: Uint8Array,
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
impl<'a> From<&'a BuildInfoAndOutput>
|
|
273
|
-
for edr_solidity::artifacts::BuildInfoBufferSeparateOutput<'a>
|
|
274
|
-
{
|
|
275
|
-
fn from(value: &'a BuildInfoAndOutput) -> Self {
|
|
276
|
-
Self {
|
|
277
|
-
build_info: value.build_info.as_ref(),
|
|
278
|
-
output: value.output.as_ref(),
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
impl<'a> From<&'a TracingConfigWithBuffers>
|
|
284
|
-
for edr_solidity::artifacts::BuildInfoConfigWithBuffers<'a>
|
|
285
|
-
{
|
|
286
|
-
fn from(value: &'a TracingConfigWithBuffers) -> Self {
|
|
287
|
-
use edr_solidity::artifacts::{BuildInfoBufferSeparateOutput, BuildInfoBuffers};
|
|
288
|
-
|
|
289
|
-
let build_infos = value.build_infos.as_ref().map(|infos| match infos {
|
|
290
|
-
Either::A(with_output) => BuildInfoBuffers::WithOutput(
|
|
291
|
-
with_output
|
|
292
|
-
.iter()
|
|
293
|
-
.map(std::convert::AsRef::as_ref)
|
|
294
|
-
.collect(),
|
|
295
|
-
),
|
|
296
|
-
Either::B(separate_output) => BuildInfoBuffers::SeparateInputOutput(
|
|
297
|
-
separate_output
|
|
298
|
-
.iter()
|
|
299
|
-
.map(BuildInfoBufferSeparateOutput::from)
|
|
300
|
-
.collect(),
|
|
301
|
-
),
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
Self {
|
|
305
|
-
build_infos,
|
|
306
|
-
ignore_contracts: value.ignore_contracts,
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
#[derive(Debug)]
|
|
312
|
-
struct SolidityTraceData {
|
|
313
|
-
trace: Arc<edr_evm::trace::Trace>,
|
|
314
|
-
contract_decoder: Arc<ContractDecoder>,
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
#[napi]
|
|
318
|
-
pub struct Response {
|
|
319
|
-
// N-API is known to be slow when marshalling `serde_json::Value`s, so we try to return a
|
|
320
|
-
// `String`. If the object is too large to be represented as a `String`, we return a `Buffer`
|
|
321
|
-
// instead.
|
|
322
|
-
data: Either<String, serde_json::Value>,
|
|
323
|
-
/// When a transaction fails to execute, the provider returns a trace of the
|
|
324
|
-
/// transaction.
|
|
325
|
-
solidity_trace: Option<SolidityTraceData>,
|
|
326
|
-
/// This may contain zero or more traces, depending on the (batch) request
|
|
327
|
-
traces: Vec<Arc<edr_evm::trace::Trace>>,
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
#[napi]
|
|
331
|
-
impl Response {
|
|
332
|
-
/// Returns the response data as a JSON string or a JSON object.
|
|
333
|
-
#[napi(getter)]
|
|
334
|
-
pub fn data(&self) -> Either<String, serde_json::Value> {
|
|
335
|
-
self.data.clone()
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
#[napi(getter)]
|
|
339
|
-
pub fn traces(&self) -> Vec<RawTrace> {
|
|
340
|
-
self.traces
|
|
341
|
-
.iter()
|
|
342
|
-
.map(|trace| RawTrace::new(trace.clone()))
|
|
343
|
-
.collect()
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// Rust port of https://github.com/NomicFoundation/hardhat/blob/c20bf195a6efdc2d74e778b7a4a7799aac224841/packages/hardhat-core/src/internal/hardhat-network/provider/provider.ts#L590
|
|
347
|
-
#[doc = "Compute the error stack trace. Return the stack trace if it can be decoded, otherwise returns none. Throws if there was an error computing the stack trace."]
|
|
348
98
|
#[napi]
|
|
349
|
-
pub fn
|
|
350
|
-
let
|
|
351
|
-
trace,
|
|
352
|
-
contract_decoder,
|
|
353
|
-
}) = &self.solidity_trace
|
|
354
|
-
else {
|
|
355
|
-
return Ok(None);
|
|
356
|
-
};
|
|
357
|
-
let nested_trace = edr_solidity::nested_tracer::convert_trace_messages_to_nested_trace(
|
|
358
|
-
trace.as_ref().clone(),
|
|
359
|
-
)
|
|
360
|
-
.map_err(|err| napi::Error::from_reason(err.to_string()))?;
|
|
361
|
-
|
|
362
|
-
if let Some(vm_trace) = nested_trace {
|
|
363
|
-
let decoded_trace = contract_decoder.try_to_decode_message_trace(vm_trace);
|
|
364
|
-
let stack_trace = edr_solidity::solidity_tracer::get_stack_trace(decoded_trace)
|
|
365
|
-
.map_err(|err| napi::Error::from_reason(err.to_string()))?;
|
|
366
|
-
let stack_trace = stack_trace
|
|
367
|
-
.into_iter()
|
|
368
|
-
.map(super::cast::TryCast::try_cast)
|
|
369
|
-
.collect::<Result<Vec<_>, _>>()?;
|
|
99
|
+
pub async fn set_verbose_tracing(&self, verbose_tracing: bool) -> napi::Result<()> {
|
|
100
|
+
let provider = self.provider.clone();
|
|
370
101
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
102
|
+
self.runtime
|
|
103
|
+
.spawn_blocking(move || {
|
|
104
|
+
provider.set_verbose_tracing(verbose_tracing);
|
|
105
|
+
})
|
|
106
|
+
.await
|
|
107
|
+
.map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))
|
|
375
108
|
}
|
|
376
109
|
}
|