@nomicfoundation/edr 0.12.0-next.6 → 0.12.0-next.8

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/src/config.rs CHANGED
@@ -2,15 +2,14 @@ use core::fmt::{Debug, Display};
2
2
  use std::{
3
3
  num::NonZeroU64,
4
4
  path::PathBuf,
5
- sync::Arc,
6
5
  time::{Duration, SystemTime},
7
6
  };
8
7
 
9
8
  use edr_coverage::reporter::SyncOnCollectedCoverageCallback;
10
9
  use edr_eip1559::{BaseFeeActivation, ConstantBaseFeeParams};
11
- use edr_eth::{Bytes, HashMap, HashSet};
10
+ use edr_gas_report::SyncOnCollectedGasReportCallback;
11
+ use edr_primitives::{Bytes, HashMap, HashSet};
12
12
  use edr_signer::{secret_key_from_str, SecretKey};
13
- use edr_solidity::contract_decoder::ContractDecoder;
14
13
  use napi::{
15
14
  bindgen_prelude::{BigInt, Promise, Reference, Uint8Array},
16
15
  threadsafe_function::{
@@ -22,8 +21,8 @@ use napi::{
22
21
  use napi_derive::napi;
23
22
 
24
23
  use crate::{
25
- account::AccountOverride, block::BlobGas, cast::TryCast, logger::LoggerConfig,
26
- precompile::Precompile, subscription::SubscriptionConfig,
24
+ account::AccountOverride, block::BlobGas, cast::TryCast, gas_report::GasReport,
25
+ logger::LoggerConfig, precompile::Precompile, subscription::SubscriptionConfig,
27
26
  };
28
27
 
29
28
  /// Configuration for EIP-1559 parameters
@@ -36,12 +35,12 @@ pub struct BaseFeeParamActivation {
36
35
 
37
36
  #[napi(object)]
38
37
  pub struct BaseFeeActivationByBlockNumber {
39
- /// The block number at which the base_fee_params is activated
38
+ /// The block number at which the `base_fee_params` is activated
40
39
  pub block_number: BigInt,
41
40
  }
42
41
  #[napi(object)]
43
42
  pub struct BaseFeeActivationByHardfork {
44
- /// The hardfork at which the base_fee_params is activated
43
+ /// The hardfork at which the `base_fee_params` is activated
45
44
  pub hardfork: String,
46
45
  }
47
46
 
@@ -94,6 +93,17 @@ pub struct CodeCoverageConfig {
94
93
  pub on_collected_coverage_callback: JsFunction,
95
94
  }
96
95
 
96
+ #[napi(object)]
97
+ pub struct GasReportConfig {
98
+ /// Gas reports are collected after a block is mined or `eth_call` is
99
+ /// executed.
100
+ ///
101
+ /// Exceptions thrown in the callback will be propagated to the original
102
+ /// caller.
103
+ #[napi(ts_type = "(gasReport: GasReport) => Promise<void>")]
104
+ pub on_collected_gas_report_callback: JsFunction,
105
+ }
106
+
97
107
  /// Configuration for forking a blockchain
98
108
  #[napi(object)]
99
109
  pub struct ForkConfig {
@@ -171,6 +181,8 @@ pub struct MiningConfig {
171
181
  pub struct ObservabilityConfig {
172
182
  /// If present, configures runtime observability to collect code coverage.
173
183
  pub code_coverage: Option<CodeCoverageConfig>,
184
+ /// If present, configures runtime observability to collect gas reports.
185
+ pub gas_report: Option<GasReportConfig>,
174
186
  }
175
187
 
176
188
  /// Configuration for a provider
@@ -187,7 +199,7 @@ pub struct ProviderConfig {
187
199
  /// EIP-1559 base fee parameters activations to be used to calculate the
188
200
  /// block base fee.
189
201
  ///
190
- /// Provide an ordered list of base_fee_params to be
202
+ /// Provide an ordered list of `base_fee_params` to be
191
203
  /// used starting from the specified activation point (hardfork or block
192
204
  /// number).
193
205
  /// If not provided, the default values from the chain spec
@@ -387,6 +399,8 @@ impl ObservabilityConfig {
387
399
  .code_coverage
388
400
  .map(
389
401
  |code_coverage| -> napi::Result<Box<dyn SyncOnCollectedCoverageCallback>> {
402
+ let runtime = runtime.clone();
403
+
390
404
  let mut on_collected_coverage_callback: ThreadsafeFunction<
391
405
  _,
392
406
  ErrorStrategy::Fatal,
@@ -452,9 +466,61 @@ impl ObservabilityConfig {
452
466
  },
453
467
  )
454
468
  .transpose()?;
469
+ let on_collected_gas_report_fn = self.gas_report.map(
470
+ |gas_report| -> napi::Result<Box<dyn SyncOnCollectedGasReportCallback>> {
471
+ let mut on_collected_gas_report_callback: ThreadsafeFunction<
472
+ _,
473
+ ErrorStrategy::Fatal,
474
+ > = gas_report
475
+ .on_collected_gas_report_callback
476
+ .create_threadsafe_function(
477
+ 0,
478
+ |ctx: ThreadSafeCallContext<GasReport>| {
479
+ let report = ctx.value;
480
+ Ok(vec![report])
481
+ }
482
+ ,
483
+ )?;
484
+ // Maintain a weak reference to the function to avoid blocking the event loop
485
+ // from exiting.
486
+ on_collected_gas_report_callback.unref(env)?;
487
+
488
+ let on_collected_gas_report_fn: Box<dyn SyncOnCollectedGasReportCallback> =
489
+ Box::new(move |report| {
490
+ let runtime = runtime.clone();
491
+
492
+ let (sender, receiver) = std::sync::mpsc::channel();
493
+
494
+ // Convert the report to the N-API representation
495
+ let status = on_collected_gas_report_callback
496
+ .call_with_return_value(GasReport::from(report), ThreadsafeFunctionCallMode::Blocking, move |result: Promise<()>| {
497
+ // We spawn a background task to handle the async callback
498
+ runtime.spawn(async move {
499
+ let result = result.await;
500
+ sender.send(result).map_err(|_error| {
501
+ napi::Error::new(
502
+ napi::Status::GenericFailure,
503
+ "Failed to send result from on_collected_gas_report_callback",
504
+ )
505
+ })
506
+ });
507
+ Ok(())
508
+ });
509
+
510
+ assert_eq!(status, napi::Status::Ok);
511
+
512
+ let () = receiver.recv().expect("Receive can only fail if the channel is closed")?;
513
+
514
+ Ok(())
515
+ });
516
+
517
+ Ok(on_collected_gas_report_fn)
518
+ },
519
+ ).transpose()?;
455
520
 
456
521
  Ok(edr_provider::observability::Config {
457
522
  on_collected_coverage_fn,
523
+ on_collected_gas_report_fn,
458
524
  ..edr_provider::observability::Config::default()
459
525
  })
460
526
  }
@@ -511,7 +577,7 @@ impl ProviderConfig {
511
577
  .genesis_state
512
578
  .into_iter()
513
579
  .map(TryInto::try_into)
514
- .collect::<napi::Result<HashMap<edr_eth::Address, edr_provider::AccountOverride>>>()?;
580
+ .collect::<napi::Result<HashMap<edr_primitives::Address, edr_provider::AccountOverride>>>()?;
515
581
 
516
582
  let precompile_overrides = self
517
583
  .precompile_overrides
@@ -606,7 +672,6 @@ impl From<BuildInfoAndOutput> for edr_napi_core::solidity::config::BuildInfoAndO
606
672
 
607
673
  /// Result of [`resolve_configs`].
608
674
  pub struct ConfigResolution {
609
- pub contract_decoder: Arc<ContractDecoder>,
610
675
  pub logger_config: edr_napi_core::logger::Config,
611
676
  pub provider_config: edr_napi_core::provider::Config,
612
677
  pub subscription_callback: edr_napi_core::subscription::Callback,
@@ -619,28 +684,15 @@ pub fn resolve_configs(
619
684
  provider_config: ProviderConfig,
620
685
  logger_config: LoggerConfig,
621
686
  subscription_config: SubscriptionConfig,
622
- tracing_config: TracingConfigWithBuffers,
623
687
  ) -> napi::Result<ConfigResolution> {
624
688
  let provider_config = provider_config.resolve(env, runtime)?;
625
689
  let logger_config = logger_config.resolve(env)?;
626
690
 
627
- // TODO: https://github.com/NomicFoundation/edr/issues/760
628
- let build_info_config = edr_solidity::artifacts::BuildInfoConfig::parse_from_buffers(
629
- (&edr_napi_core::solidity::config::TracingConfigWithBuffers::from(tracing_config)).into(),
630
- )
631
- .map_err(|error| napi::Error::from_reason(error.to_string()))?;
632
-
633
- let contract_decoder = ContractDecoder::new(&build_info_config).map_or_else(
634
- |error| Err(napi::Error::from_reason(error.to_string())),
635
- |contract_decoder| Ok(Arc::new(contract_decoder)),
636
- )?;
637
-
638
691
  let subscription_config = edr_napi_core::subscription::Config::from(subscription_config);
639
692
  let subscription_callback =
640
693
  edr_napi_core::subscription::Callback::new(env, subscription_config.subscription_callback)?;
641
694
 
642
695
  Ok(ConfigResolution {
643
- contract_decoder,
644
696
  logger_config,
645
697
  provider_config,
646
698
  subscription_callback,
package/src/context.rs CHANGED
@@ -1,7 +1,7 @@
1
1
  use std::sync::Arc;
2
2
 
3
- use edr_eth::HashMap;
4
3
  use edr_napi_core::{provider::SyncProviderFactory, solidity};
4
+ use edr_primitives::HashMap;
5
5
  use edr_solidity_tests::{
6
6
  decode::RevertDecoder,
7
7
  multi_runner::{SuiteResultAndArtifactId, TestContract, TestContracts},
@@ -19,13 +19,14 @@ use tracing_subscriber::{prelude::*, EnvFilter, Registry};
19
19
 
20
20
  use crate::{
21
21
  config::{resolve_configs, ConfigResolution, ProviderConfig, TracingConfigWithBuffers},
22
+ contract_decoder::ContractDecoder,
22
23
  logger::LoggerConfig,
23
24
  provider::{Provider, ProviderFactory},
24
25
  solidity_tests::{
25
26
  artifact::{Artifact, ArtifactId},
26
27
  config::SolidityTestRunnerConfigArgs,
27
28
  factory::SolidityTestRunnerFactory,
28
- test_results::SuiteResult,
29
+ test_results::{SolidityTestResult, SuiteResult},
29
30
  LinkingOutput,
30
31
  },
31
32
  subscription::SubscriptionConfig,
@@ -38,7 +39,7 @@ pub struct EdrContext {
38
39
 
39
40
  #[napi]
40
41
  impl EdrContext {
41
- #[doc = "Creates a new [`EdrContext`] instance. Should only be called once!"]
42
+ /// Creates a new [`EdrContext`] instance. Should only be called once!
42
43
  #[napi(catch_unwind, constructor)]
43
44
  pub fn new() -> napi::Result<Self> {
44
45
  let context = Context::new()?;
@@ -48,7 +49,7 @@ impl EdrContext {
48
49
  })
49
50
  }
50
51
 
51
- #[doc = "Constructs a new provider with the provided configuration."]
52
+ /// Constructs a new provider with the provided configuration.
52
53
  #[napi(catch_unwind, ts_return_type = "Promise<Provider>")]
53
54
  pub fn create_provider(
54
55
  &self,
@@ -57,7 +58,7 @@ impl EdrContext {
57
58
  provider_config: ProviderConfig,
58
59
  logger_config: LoggerConfig,
59
60
  subscription_config: SubscriptionConfig,
60
- tracing_config: TracingConfigWithBuffers,
61
+ contract_decoder: &ContractDecoder,
61
62
  ) -> napi::Result<JsObject> {
62
63
  let (deferred, promise) = env.create_deferred()?;
63
64
 
@@ -76,7 +77,6 @@ impl EdrContext {
76
77
  let runtime = runtime::Handle::current();
77
78
 
78
79
  let ConfigResolution {
79
- contract_decoder,
80
80
  logger_config,
81
81
  provider_config,
82
82
  subscription_callback,
@@ -86,7 +86,6 @@ impl EdrContext {
86
86
  provider_config,
87
87
  logger_config,
88
88
  subscription_config,
89
- tracing_config
90
89
  ));
91
90
 
92
91
  #[cfg(feature = "scenarios")]
@@ -105,6 +104,7 @@ impl EdrContext {
105
104
  try_or_reject_promise!(context.get_provider_factory(&chain_type))
106
105
  };
107
106
 
107
+ let contract_decoder = Arc::clone(contract_decoder.as_inner());
108
108
  runtime.clone().spawn_blocking(move || {
109
109
  let result = factory
110
110
  .create_provider(
@@ -130,7 +130,7 @@ impl EdrContext {
130
130
  Ok(promise)
131
131
  }
132
132
 
133
- #[doc = "Registers a new provider factory for the provided chain type."]
133
+ /// Registers a new provider factory for the provided chain type.
134
134
  #[napi(catch_unwind)]
135
135
  pub async fn register_provider_factory(
136
136
  &self,
@@ -153,14 +153,29 @@ impl EdrContext {
153
153
  Ok(())
154
154
  }
155
155
 
156
- #[doc = "Executes Solidity tests."]
157
- #[doc = ""]
158
- #[doc = "The function will return as soon as test execution is started."]
159
- #[doc = "The progress callback will be called with the results of each test"]
160
- #[doc = "suite. It is up to the caller to track how many times the callback"]
161
- #[doc = "is called to know when all tests are done."]
156
+ /// Executes Solidity tests
157
+ ///
158
+ /// The function will return a promise that resolves to a
159
+ /// [`SolidityTestResult`].
160
+ ///
161
+ /// Arguments:
162
+ /// - `chainType`: the same chain type that was passed to
163
+ /// `registerProviderFactory`.
164
+ /// - `artifacts`: the project's compilation output artifacts. It's
165
+ /// important to include include all artifacts here, otherwise cheatcodes
166
+ /// that access artifacts and other functionality (e.g. auto-linking, gas
167
+ /// reports) can break.
168
+ /// - `testSuites`: the test suite ids that specify which test suites to
169
+ /// execute. The test suite artifacts must be present in `artifacts`.
170
+ /// - `configArgs`: solidity test runner configuration. See the struct docs
171
+ /// for details.
172
+ /// - `tracingConfig`: the build infos used for stack trace generation.
173
+ /// These are lazily parsed and it's important that they're passed as
174
+ /// Uint8 arrays for performance.
175
+ /// - `onTestSuiteCompletedCallback`: The progress callback will be called
176
+ /// with the results of each test suite as soon as it finished executing.
162
177
  #[allow(clippy::too_many_arguments)]
163
- #[napi(catch_unwind, ts_return_type = "Promise<void>")]
178
+ #[napi(catch_unwind, ts_return_type = "Promise<SolidityTestResult>")]
164
179
  pub fn run_solidity_tests(
165
180
  &self,
166
181
  env: Env,
@@ -291,7 +306,7 @@ impl EdrContext {
291
306
  .expect("Failed to join test runner factory thread"));
292
307
 
293
308
  let runtime_for_runner = runtime.clone();
294
- let () = try_or_reject_deferred!(runtime
309
+ let test_result = try_or_reject_deferred!(runtime
295
310
  .clone()
296
311
  .spawn_blocking(move || {
297
312
  test_runner.run_tests(
@@ -323,7 +338,7 @@ impl EdrContext {
323
338
  .await
324
339
  .expect("Failed to join test runner thread"));
325
340
 
326
- deferred.resolve(move |_env| Ok(()));
341
+ deferred.resolve(move |_env| Ok(SolidityTestResult::from(test_result)));
327
342
  });
328
343
 
329
344
  Ok(promise)
@@ -0,0 +1,57 @@
1
+ use std::sync::Arc;
2
+
3
+ use napi_derive::napi;
4
+
5
+ use crate::config::TracingConfigWithBuffers;
6
+
7
+ #[napi]
8
+ pub struct ContractDecoder {
9
+ inner: Arc<edr_solidity::contract_decoder::ContractDecoder>,
10
+ }
11
+
12
+ #[napi]
13
+ impl ContractDecoder {
14
+ #[doc = "Creates an empty instance."]
15
+ #[napi(constructor, catch_unwind)]
16
+ // Following TS convention for the constructor without arguments to be `new()`.
17
+ #[allow(clippy::new_without_default)]
18
+ pub fn new() -> Self {
19
+ Self {
20
+ inner: Arc::new(edr_solidity::contract_decoder::ContractDecoder::default()),
21
+ }
22
+ }
23
+
24
+ #[doc = "Creates a new instance with the provided configuration."]
25
+ #[napi(factory, catch_unwind)]
26
+ pub fn with_contracts(config: TracingConfigWithBuffers) -> napi::Result<Self> {
27
+ let build_info_config = edr_solidity::artifacts::BuildInfoConfig::parse_from_buffers(
28
+ (&edr_napi_core::solidity::config::TracingConfigWithBuffers::from(config)).into(),
29
+ )
30
+ .map_err(|error| napi::Error::from_reason(error.to_string()))?;
31
+
32
+ let contract_decoder =
33
+ edr_solidity::contract_decoder::ContractDecoder::new(&build_info_config).map_or_else(
34
+ |error| Err(napi::Error::from_reason(error.to_string())),
35
+ |contract_decoder| Ok(Arc::new(contract_decoder)),
36
+ )?;
37
+
38
+ Ok(Self {
39
+ inner: contract_decoder,
40
+ })
41
+ }
42
+ }
43
+
44
+ impl ContractDecoder {
45
+ /// Returns a reference to the inner contract decoder.
46
+ pub fn as_inner(&self) -> &Arc<edr_solidity::contract_decoder::ContractDecoder> {
47
+ &self.inner
48
+ }
49
+ }
50
+
51
+ impl From<Arc<edr_solidity::contract_decoder::ContractDecoder>> for ContractDecoder {
52
+ fn from(contract_decoder: Arc<edr_solidity::contract_decoder::ContractDecoder>) -> Self {
53
+ Self {
54
+ inner: contract_decoder,
55
+ }
56
+ }
57
+ }
@@ -3,6 +3,8 @@ use std::collections::HashMap;
3
3
  use napi::bindgen_prelude::{BigInt, Uint8Array};
4
4
  use napi_derive::napi;
5
5
 
6
+ // False positive: imported by HH2
7
+ #[allow(dead_code)]
6
8
  #[napi(object)]
7
9
  pub struct DebugTraceResult {
8
10
  pub pass: bool,
@@ -0,0 +1,92 @@
1
+ use std::collections::HashMap;
2
+
3
+ use napi::bindgen_prelude::BigInt;
4
+ use napi_derive::napi;
5
+
6
+ #[napi(object)]
7
+ pub struct GasReport {
8
+ pub contracts: HashMap<String, ContractGasReport>,
9
+ }
10
+
11
+ #[napi(object)]
12
+ pub struct ContractGasReport {
13
+ pub deployments: Vec<DeploymentGasReport>,
14
+ pub functions: HashMap<String, Vec<FunctionGasReport>>,
15
+ }
16
+
17
+ #[napi]
18
+ pub enum GasReportExecutionStatus {
19
+ Success,
20
+ Revert,
21
+ Halt,
22
+ }
23
+
24
+ #[napi(object)]
25
+ pub struct DeploymentGasReport {
26
+ pub gas: BigInt,
27
+ pub size: BigInt,
28
+ pub status: GasReportExecutionStatus,
29
+ }
30
+
31
+ #[napi(object)]
32
+ pub struct FunctionGasReport {
33
+ pub gas: BigInt,
34
+ pub status: GasReportExecutionStatus,
35
+ }
36
+
37
+ impl From<edr_gas_report::GasReport> for GasReport {
38
+ fn from(value: edr_gas_report::GasReport) -> Self {
39
+ Self {
40
+ contracts: value
41
+ .into_inner()
42
+ .into_iter()
43
+ .map(|(k, v)| (k, v.into()))
44
+ .collect(),
45
+ }
46
+ }
47
+ }
48
+
49
+ impl From<edr_gas_report::ContractGasReport> for ContractGasReport {
50
+ fn from(value: edr_gas_report::ContractGasReport) -> Self {
51
+ Self {
52
+ deployments: value.deployments.into_iter().map(Into::into).collect(),
53
+ functions: value
54
+ .functions
55
+ .into_iter()
56
+ .map(|(k, v)| {
57
+ let function_reports = v.into_iter().map(FunctionGasReport::from).collect();
58
+ (k, function_reports)
59
+ })
60
+ .collect(),
61
+ }
62
+ }
63
+ }
64
+
65
+ impl From<edr_gas_report::GasReportExecutionStatus> for GasReportExecutionStatus {
66
+ fn from(value: edr_gas_report::GasReportExecutionStatus) -> Self {
67
+ match value {
68
+ edr_gas_report::GasReportExecutionStatus::Success => Self::Success,
69
+ edr_gas_report::GasReportExecutionStatus::Revert => Self::Revert,
70
+ edr_gas_report::GasReportExecutionStatus::Halt => Self::Halt,
71
+ }
72
+ }
73
+ }
74
+
75
+ impl From<edr_gas_report::DeploymentGasReport> for DeploymentGasReport {
76
+ fn from(value: edr_gas_report::DeploymentGasReport) -> Self {
77
+ Self {
78
+ gas: BigInt::from(value.gas),
79
+ size: BigInt::from(value.size),
80
+ status: value.status.into(),
81
+ }
82
+ }
83
+ }
84
+
85
+ impl From<edr_gas_report::FunctionGasReport> for FunctionGasReport {
86
+ fn from(value: edr_gas_report::FunctionGasReport) -> Self {
87
+ Self {
88
+ gas: BigInt::from(value.gas),
89
+ status: value.status.into(),
90
+ }
91
+ }
92
+ }
package/src/lib.rs CHANGED
@@ -17,7 +17,10 @@ pub mod chains;
17
17
  pub mod config;
18
18
  /// Types related to an EDR N-API context.
19
19
  pub mod context;
20
+ /// Types for decoding smart contract data.
21
+ pub mod contract_decoder;
20
22
  mod debug_trace;
23
+ pub mod gas_report;
21
24
  /// Types and functions related to code coverage instrumentation.
22
25
  pub mod instrument;
23
26
  /// Types for EVM execution logs.
package/src/logger.rs CHANGED
@@ -1,7 +1,7 @@
1
1
  use std::sync::{mpsc::channel, Arc};
2
2
 
3
- use edr_eth::Bytes;
4
3
  use edr_napi_core::logger::LoggerError;
4
+ use edr_primitives::Bytes;
5
5
  use napi::{
6
6
  threadsafe_function::{
7
7
  ErrorStrategy, ThreadSafeCallContext, ThreadsafeFunction, ThreadsafeFunctionCallMode,
package/src/mock/time.rs CHANGED
@@ -1,17 +1,18 @@
1
1
  use std::sync::Arc;
2
2
 
3
- use edr_eth::B256;
4
3
  use edr_evm::spec::RuntimeSpec;
5
4
  use edr_evm_spec::ChainSpec;
6
5
  use edr_generic::GenericChainSpec;
7
6
  use edr_napi_core::logger::Logger;
8
- use edr_rpc_eth::RpcSpec;
7
+ use edr_primitives::B256;
8
+ use edr_rpc_spec::RpcSpec;
9
9
  use napi::{bindgen_prelude::BigInt, tokio::runtime, Env, JsObject};
10
10
  use napi_derive::napi;
11
11
 
12
12
  use crate::{
13
13
  cast::TryCast as _,
14
- config::{resolve_configs, ConfigResolution, ProviderConfig, TracingConfigWithBuffers},
14
+ config::{resolve_configs, ConfigResolution, ProviderConfig},
15
+ contract_decoder::ContractDecoder,
15
16
  logger::LoggerConfig,
16
17
  provider::Provider,
17
18
  subscription::SubscriptionConfig,
@@ -50,7 +51,7 @@ pub fn create_provider_with_mock_timer(
50
51
  provider_config: ProviderConfig,
51
52
  logger_config: LoggerConfig,
52
53
  subscription_config: SubscriptionConfig,
53
- tracing_config: TracingConfigWithBuffers,
54
+ contract_decoder: &ContractDecoder,
54
55
  time: &MockTime,
55
56
  ) -> napi::Result<JsObject> {
56
57
  let (deferred, promise) = env.create_deferred()?;
@@ -70,7 +71,6 @@ pub fn create_provider_with_mock_timer(
70
71
  let runtime = runtime::Handle::current();
71
72
 
72
73
  let ConfigResolution {
73
- contract_decoder,
74
74
  logger_config,
75
75
  provider_config,
76
76
  subscription_callback,
@@ -80,9 +80,9 @@ pub fn create_provider_with_mock_timer(
80
80
  provider_config,
81
81
  logger_config,
82
82
  subscription_config,
83
- tracing_config,
84
83
  ));
85
84
 
85
+ let contract_decoder = Arc::clone(contract_decoder.as_inner());
86
86
  let timer = Arc::clone(&time.inner);
87
87
 
88
88
  runtime.clone().spawn_blocking(move || {
@@ -112,7 +112,7 @@ pub fn create_provider_with_mock_timer(
112
112
  subscription_callback.call(event);
113
113
  }),
114
114
  provider_config,
115
- contract_decoder.clone(),
115
+ Arc::clone(&contract_decoder),
116
116
  timer,
117
117
  )
118
118
  .map_err(|error| napi::Error::from_reason(error.to_string()))?;
package/src/mock.rs CHANGED
@@ -23,15 +23,6 @@ impl MockProvider {
23
23
  }
24
24
 
25
25
  impl SyncProvider for MockProvider {
26
- fn add_compilation_result(
27
- &self,
28
- _solc_version: String,
29
- _compiler_input: edr_solidity::artifacts::CompilerInput,
30
- _compiler_output: edr_solidity::artifacts::CompilerOutput,
31
- ) -> napi::Result<bool> {
32
- Ok(false) // Mock provider does not handle compilation results
33
- }
34
-
35
26
  fn handle_request(
36
27
  &self,
37
28
  _request: String,
package/src/precompile.rs CHANGED
@@ -1,5 +1,5 @@
1
- use edr_eth::Address;
2
1
  use edr_evm::precompile::{self, PrecompileFn, PrecompileWithAddress};
2
+ use edr_primitives::Address;
3
3
  use napi::bindgen_prelude::Uint8Array;
4
4
  use napi_derive::napi;
5
5
 
package/src/provider.rs CHANGED
@@ -5,18 +5,18 @@ mod response;
5
5
  use std::sync::Arc;
6
6
 
7
7
  use edr_napi_core::provider::SyncProvider;
8
- use edr_solidity::contract_decoder::ContractDecoder;
8
+ use edr_solidity::compiler::create_models_and_decode_bytecodes;
9
9
  use napi::{tokio::runtime, Env, JsFunction, JsObject, Status};
10
10
  use napi_derive::napi;
11
11
 
12
12
  pub use self::factory::ProviderFactory;
13
13
  use self::response::Response;
14
- use crate::call_override::CallOverrideCallback;
14
+ use crate::{call_override::CallOverrideCallback, contract_decoder::ContractDecoder};
15
15
 
16
16
  /// A JSON-RPC provider for Ethereum.
17
17
  #[napi]
18
18
  pub struct Provider {
19
- contract_decoder: Arc<ContractDecoder>,
19
+ contract_decoder: Arc<edr_solidity::contract_decoder::ContractDecoder>,
20
20
  provider: Arc<dyn SyncProvider>,
21
21
  runtime: runtime::Handle,
22
22
  #[cfg(feature = "scenarios")]
@@ -28,7 +28,7 @@ impl Provider {
28
28
  pub fn new(
29
29
  provider: Arc<dyn SyncProvider>,
30
30
  runtime: runtime::Handle,
31
- contract_decoder: Arc<ContractDecoder>,
31
+ contract_decoder: Arc<edr_solidity::contract_decoder::ContractDecoder>,
32
32
  #[cfg(feature = "scenarios")] scenario_file: Option<
33
33
  napi::tokio::sync::Mutex<napi::tokio::fs::File>,
34
34
  >,
@@ -54,8 +54,8 @@ impl Provider {
54
54
  solc_version: String,
55
55
  compiler_input: serde_json::Value,
56
56
  compiler_output: serde_json::Value,
57
- ) -> napi::Result<bool> {
58
- let provider = self.provider.clone();
57
+ ) -> napi::Result<()> {
58
+ let contract_decoder = self.contract_decoder.clone();
59
59
 
60
60
  self.runtime
61
61
  .spawn_blocking(move || {
@@ -65,12 +65,33 @@ impl Provider {
65
65
  let compiler_output = serde_json::from_value(compiler_output)
66
66
  .map_err(|error| napi::Error::from_reason(error.to_string()))?;
67
67
 
68
- provider.add_compilation_result(solc_version, compiler_input, compiler_output)
68
+ let contracts = match create_models_and_decode_bytecodes(
69
+ solc_version,
70
+ &compiler_input,
71
+ &compiler_output,
72
+ ) {
73
+ Ok(contracts) => contracts,
74
+ Err(error) => {
75
+ return Err(napi::Error::from_reason(format!("Contract decoder failed to be updated. Please report this to help us improve Hardhat.\n{error}")));
76
+ }
77
+ };
78
+
79
+ for contract in contracts {
80
+ contract_decoder.add_contract_metadata(contract);
81
+ }
82
+
83
+ Ok(())
69
84
  })
70
85
  .await
71
86
  .map_err(|error| napi::Error::new(Status::GenericFailure, error.to_string()))?
72
87
  }
73
88
 
89
+ #[doc = "Retrieves the instance's contract decoder."]
90
+ #[napi(catch_unwind)]
91
+ pub fn contract_decoder(&self) -> ContractDecoder {
92
+ ContractDecoder::from(Arc::clone(&self.contract_decoder))
93
+ }
94
+
74
95
  #[doc = "Handles a JSON-RPC request and returns a JSON-RPC response."]
75
96
  #[napi(catch_unwind)]
76
97
  pub async fn handle_request(&self, request: String) -> napi::Result<Response> {