@nomicfoundation/edr 0.11.3 → 0.12.0-next.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.
Files changed (46) hide show
  1. package/Cargo.toml +61 -27
  2. package/LICENSE +5 -1
  3. package/index.d.ts +875 -137
  4. package/index.js +61 -3
  5. package/package.json +20 -16
  6. package/src/account.rs +109 -32
  7. package/src/block.rs +2 -103
  8. package/src/call_override.rs +7 -7
  9. package/src/cast.rs +47 -17
  10. package/src/chains/generic.rs +51 -0
  11. package/src/chains/l1.rs +262 -0
  12. package/src/chains/op.rs +425 -0
  13. package/src/chains.rs +7 -0
  14. package/src/config.rs +537 -67
  15. package/src/context.rs +374 -17
  16. package/src/debug_trace.rs +2 -2
  17. package/src/instrument.rs +109 -0
  18. package/src/lib.rs +38 -14
  19. package/src/log.rs +12 -14
  20. package/src/logger.rs +77 -1177
  21. package/src/mock.rs +68 -0
  22. package/src/precompile.rs +50 -0
  23. package/src/provider/factory.rs +22 -0
  24. package/src/provider/response.rs +73 -0
  25. package/src/provider.rs +64 -325
  26. package/src/result.rs +60 -69
  27. package/src/scenarios.rs +11 -17
  28. package/src/serde.rs +57 -0
  29. package/src/solidity_tests/artifact.rs +184 -0
  30. package/src/solidity_tests/config.rs +725 -0
  31. package/src/solidity_tests/factory.rs +22 -0
  32. package/src/solidity_tests/l1.rs +68 -0
  33. package/src/solidity_tests/op.rs +69 -0
  34. package/src/solidity_tests/runner.rs +51 -0
  35. package/src/solidity_tests/test_results.rs +668 -0
  36. package/src/solidity_tests.rs +56 -0
  37. package/src/subscription.rs +32 -0
  38. package/src/trace/debug.rs +1 -1
  39. package/src/trace/exit.rs +12 -13
  40. package/src/trace/library_utils.rs +1 -1
  41. package/src/trace/return_data.rs +11 -11
  42. package/src/trace/solidity_stack_trace.rs +11 -8
  43. package/src/trace.rs +37 -44
  44. package/src/withdrawal.rs +4 -4
  45. package/src/provider/config.rs +0 -291
  46. package/src/subscribe.rs +0 -63
package/index.js CHANGED
@@ -310,15 +310,73 @@ if (!nativeBinding) {
310
310
  throw new Error(`Failed to load native binding`)
311
311
  }
312
312
 
313
- const { SpecId, EdrContext, MineOrdering, Provider, Response, SuccessReason, ExceptionalHalt, linkHexStringBytecode, printStackTrace, Exit, ExitCode, BytecodeWrapper, ContractFunctionType, ReturnData, StackTraceEntryType, stackTraceEntryTypeToString, FALLBACK_FUNCTION_NAME, RECEIVE_FUNCTION_NAME, CONSTRUCTOR_FUNCTION_NAME, UNRECOGNIZED_FUNCTION_NAME, UNKNOWN_FUNCTION_NAME, PRECOMPILE_FUNCTION_NAME, UNRECOGNIZED_CONTRACT_NAME, RawTrace, getLatestSupportedSolcVersion } = nativeBinding
313
+ const { GENERIC_CHAIN_TYPE, genericChainProviderFactory, L1_CHAIN_TYPE, l1GenesisState, l1ProviderFactory, SpecId, l1HardforkFromString, l1HardforkToString, l1HardforkLatest, FRONTIER, FRONTIER_THAWING, HOMESTEAD, DAO_FORK, TANGERINE, SPURIOUS_DRAGON, BYZANTIUM, CONSTANTINOPLE, PETERSBURG, ISTANBUL, MUIR_GLACIER, BERLIN, LONDON, ARROW_GLACIER, GRAY_GLACIER, MERGE, SHANGHAI, CANCUN, PRAGUE, OpHardfork, opHardforkFromString, opHardforkToString, opLatestHardfork, OP_CHAIN_TYPE, opGenesisState, opProviderFactory, BEDROCK, REGOLITH, CANYON, ECOTONE, FJORD, GRANITE, HOLOCENE, ISTHMUS, MineOrdering, EdrContext, addStatementCoverageInstrumentation, Precompile, precompileP256Verify, ProviderFactory, Response, Provider, SuccessReason, ExceptionalHalt, CachedChains, CachedEndpoints, FsAccessPermission, IncludeTraces, SolidityTestRunnerFactory, l1SolidityTestRunnerFactory, opSolidityTestRunnerFactory, SuiteResult, TestResult, TestStatus, CallKind, LogKind, linkHexStringBytecode, printStackTrace, Exit, ExitCode, BytecodeWrapper, ContractFunctionType, ReturnData, StackTraceEntryType, stackTraceEntryTypeToString, FALLBACK_FUNCTION_NAME, RECEIVE_FUNCTION_NAME, CONSTRUCTOR_FUNCTION_NAME, UNRECOGNIZED_FUNCTION_NAME, UNKNOWN_FUNCTION_NAME, PRECOMPILE_FUNCTION_NAME, UNRECOGNIZED_CONTRACT_NAME, RawTrace, getLatestSupportedSolcVersion } = nativeBinding
314
314
 
315
+ module.exports.GENERIC_CHAIN_TYPE = GENERIC_CHAIN_TYPE
316
+ module.exports.genericChainProviderFactory = genericChainProviderFactory
317
+ module.exports.L1_CHAIN_TYPE = L1_CHAIN_TYPE
318
+ module.exports.l1GenesisState = l1GenesisState
319
+ module.exports.l1ProviderFactory = l1ProviderFactory
315
320
  module.exports.SpecId = SpecId
316
- module.exports.EdrContext = EdrContext
321
+ module.exports.l1HardforkFromString = l1HardforkFromString
322
+ module.exports.l1HardforkToString = l1HardforkToString
323
+ module.exports.l1HardforkLatest = l1HardforkLatest
324
+ module.exports.FRONTIER = FRONTIER
325
+ module.exports.FRONTIER_THAWING = FRONTIER_THAWING
326
+ module.exports.HOMESTEAD = HOMESTEAD
327
+ module.exports.DAO_FORK = DAO_FORK
328
+ module.exports.TANGERINE = TANGERINE
329
+ module.exports.SPURIOUS_DRAGON = SPURIOUS_DRAGON
330
+ module.exports.BYZANTIUM = BYZANTIUM
331
+ module.exports.CONSTANTINOPLE = CONSTANTINOPLE
332
+ module.exports.PETERSBURG = PETERSBURG
333
+ module.exports.ISTANBUL = ISTANBUL
334
+ module.exports.MUIR_GLACIER = MUIR_GLACIER
335
+ module.exports.BERLIN = BERLIN
336
+ module.exports.LONDON = LONDON
337
+ module.exports.ARROW_GLACIER = ARROW_GLACIER
338
+ module.exports.GRAY_GLACIER = GRAY_GLACIER
339
+ module.exports.MERGE = MERGE
340
+ module.exports.SHANGHAI = SHANGHAI
341
+ module.exports.CANCUN = CANCUN
342
+ module.exports.PRAGUE = PRAGUE
343
+ module.exports.OpHardfork = OpHardfork
344
+ module.exports.opHardforkFromString = opHardforkFromString
345
+ module.exports.opHardforkToString = opHardforkToString
346
+ module.exports.opLatestHardfork = opLatestHardfork
347
+ module.exports.OP_CHAIN_TYPE = OP_CHAIN_TYPE
348
+ module.exports.opGenesisState = opGenesisState
349
+ module.exports.opProviderFactory = opProviderFactory
350
+ module.exports.BEDROCK = BEDROCK
351
+ module.exports.REGOLITH = REGOLITH
352
+ module.exports.CANYON = CANYON
353
+ module.exports.ECOTONE = ECOTONE
354
+ module.exports.FJORD = FJORD
355
+ module.exports.GRANITE = GRANITE
356
+ module.exports.HOLOCENE = HOLOCENE
357
+ module.exports.ISTHMUS = ISTHMUS
317
358
  module.exports.MineOrdering = MineOrdering
318
- module.exports.Provider = Provider
359
+ module.exports.EdrContext = EdrContext
360
+ module.exports.addStatementCoverageInstrumentation = addStatementCoverageInstrumentation
361
+ module.exports.Precompile = Precompile
362
+ module.exports.precompileP256Verify = precompileP256Verify
363
+ module.exports.ProviderFactory = ProviderFactory
319
364
  module.exports.Response = Response
365
+ module.exports.Provider = Provider
320
366
  module.exports.SuccessReason = SuccessReason
321
367
  module.exports.ExceptionalHalt = ExceptionalHalt
368
+ module.exports.CachedChains = CachedChains
369
+ module.exports.CachedEndpoints = CachedEndpoints
370
+ module.exports.FsAccessPermission = FsAccessPermission
371
+ module.exports.IncludeTraces = IncludeTraces
372
+ module.exports.SolidityTestRunnerFactory = SolidityTestRunnerFactory
373
+ module.exports.l1SolidityTestRunnerFactory = l1SolidityTestRunnerFactory
374
+ module.exports.opSolidityTestRunnerFactory = opSolidityTestRunnerFactory
375
+ module.exports.SuiteResult = SuiteResult
376
+ module.exports.TestResult = TestResult
377
+ module.exports.TestStatus = TestStatus
378
+ module.exports.CallKind = CallKind
379
+ module.exports.LogKind = LogKind
322
380
  module.exports.linkHexStringBytecode = linkHexStringBytecode
323
381
  module.exports.printStackTrace = printStackTrace
324
382
  module.exports.Exit = Exit
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@nomicfoundation/edr",
3
- "version": "0.11.3",
3
+ "version": "0.12.0-next.0",
4
4
  "devDependencies": {
5
5
  "@napi-rs/cli": "^2.18.4",
6
+ "@nomicfoundation/ethereumjs-util": "^9.0.4",
6
7
  "@types/chai": "^4.2.0",
7
8
  "@types/chai-as-promised": "^7.1.8",
8
9
  "@types/mocha": ">=9.1.0",
@@ -21,7 +22,7 @@
21
22
  "mocha": "^10.0.0",
22
23
  "prettier": "^3.2.5",
23
24
  "ts-node": "^10.8.0",
24
- "typescript": "~5.0.0"
25
+ "typescript": "~5.8.2"
25
26
  },
26
27
  "engines": {
27
28
  "node": ">= 18"
@@ -52,29 +53,32 @@
52
53
  },
53
54
  "repository": "NomicFoundation/edr.git",
54
55
  "types": "index.d.ts",
55
- "dependencies": {
56
- "@nomicfoundation/edr-darwin-arm64": "0.11.3",
57
- "@nomicfoundation/edr-darwin-x64": "0.11.3",
58
- "@nomicfoundation/edr-linux-arm64-gnu": "0.11.3",
59
- "@nomicfoundation/edr-linux-arm64-musl": "0.11.3",
60
- "@nomicfoundation/edr-linux-x64-gnu": "0.11.3",
61
- "@nomicfoundation/edr-linux-x64-musl": "0.11.3",
62
- "@nomicfoundation/edr-win32-x64-msvc": "0.11.3"
56
+ "optionalDependencies": {
57
+ "@nomicfoundation/edr-darwin-arm64": "0.12.0-next.0",
58
+ "@nomicfoundation/edr-darwin-x64": "0.12.0-next.0",
59
+ "@nomicfoundation/edr-linux-arm64-gnu": "0.12.0-next.0",
60
+ "@nomicfoundation/edr-linux-arm64-musl": "0.12.0-next.0",
61
+ "@nomicfoundation/edr-linux-x64-gnu": "0.12.0-next.0",
62
+ "@nomicfoundation/edr-linux-x64-musl": "0.12.0-next.0",
63
+ "@nomicfoundation/edr-win32-x64-msvc": "0.12.0-next.0"
63
64
  },
64
65
  "scripts": {
65
66
  "artifacts": "napi artifacts",
66
- "build": "napi build --platform --release --no-const-enum",
67
- "build:debug": "napi build --platform --no-const-enum",
68
- "build:scenarios": "napi build --platform --release --no-const-enum --features scenarios",
69
- "build:tracing": "napi build --platform --release --no-const-enum --features tracing",
67
+ "build": "pnpm run build:publish",
68
+ "build:debug": "napi build --platform --no-const-enum --features op",
69
+ "build:dev": "napi build --platform --release --no-const-enum --features op,test-mock",
70
+ "build:publish": "napi build --platform --profile napi-publish --no-const-enum --features op",
71
+ "build:scenarios": "napi build --platform --release --no-const-enum --features op,scenarios",
72
+ "build:tracing": "napi build --platform --release --no-const-enum --features op,tracing",
73
+ "build:typingFile": "napi build --platform --no-const-enum --features op",
70
74
  "clean": "rm -rf @nomicfoundation/edr.node",
71
75
  "eslint": "eslint 'test/**/*.ts'",
72
76
  "lint": "pnpm run prettier && pnpm run eslint",
73
77
  "lint:fix": "pnpm run prettier --write",
74
- "pretest": "pnpm build",
78
+ "pretest": "pnpm build:dev",
75
79
  "prettier": "prettier --check \"test/**.ts\"",
76
80
  "test": "pnpm tsc && node --max-old-space-size=8192 node_modules/mocha/bin/_mocha --recursive \"test/**/*.ts\"",
77
- "testNoBuild": "pnpm tsc && node --max-old-space-size=8192 node_modules/mocha/bin/_mocha --recursive \"test/**/*.ts\"",
81
+ "testNoBuild": "pnpm tsc && node --max-old-space-size=8192 node_modules/mocha/bin/_mocha --recursive \"test/**/{,!(mock)}.ts\"",
78
82
  "universal": "napi universal",
79
83
  "version": "napi version"
80
84
  }
package/src/account.rs CHANGED
@@ -1,46 +1,123 @@
1
- use std::fmt::{Debug, Display};
2
-
3
- #[allow(deprecated)]
4
- // This is the only source file in production code where it's allowed to create
5
- // `DangerousSecretKeyStr`.
6
- use edr_eth::signature::{secret_key_from_str, DangerousSecretKeyStr};
7
- use napi::{bindgen_prelude::BigInt, JsString, Status};
1
+ use derive_more::Debug;
2
+ use edr_eth::{hex, HashMap, U256};
3
+ use edr_solidity_tests::{backend::Predeploy, revm::state::AccountInfo};
4
+ use napi::bindgen_prelude::{BigInt, Uint8Array};
8
5
  use napi_derive::napi;
9
- use serde::Serialize;
10
6
 
11
- use crate::cast::TryCast;
7
+ use crate::{
8
+ cast::TryCast,
9
+ serde::{
10
+ serialize_bigint_as_struct, serialize_optional_bigint_as_struct,
11
+ serialize_optional_uint8array_as_hex, serialize_uint8array_as_hex,
12
+ },
13
+ };
12
14
 
13
- /// An account that needs to be created during the genesis block.
15
+ /// Specification of overrides for an account and its storage.
14
16
  #[napi(object)]
15
- pub struct GenesisAccount {
16
- // Using JsString here as it doesn't have `Debug`, `Display` and `Serialize` implementation
17
- // which prevents accidentally leaking the secret keys to error messages and logs.
18
- /// Account secret key
19
- pub secret_key: JsString,
20
- /// Account balance
21
- pub balance: BigInt,
17
+ #[derive(Clone, Debug, serde::Serialize)]
18
+ pub struct AccountOverride {
19
+ /// The account's address
20
+ #[debug("{}", hex::encode(address))]
21
+ #[serde(serialize_with = "serialize_uint8array_as_hex")]
22
+ pub address: Uint8Array,
23
+ /// If present, the overwriting balance.
24
+ #[serde(serialize_with = "serialize_optional_bigint_as_struct")]
25
+ pub balance: Option<BigInt>,
26
+ /// If present, the overwriting nonce.
27
+ #[serde(serialize_with = "serialize_optional_bigint_as_struct")]
28
+ pub nonce: Option<BigInt>,
29
+ /// If present, the overwriting code.
30
+ #[debug("{:?}", code.as_ref().map(hex::encode))]
31
+ #[serde(serialize_with = "serialize_optional_uint8array_as_hex")]
32
+ pub code: Option<Uint8Array>,
33
+ /// BEWARE: This field is not supported yet. See <https://github.com/NomicFoundation/edr/issues/911>
34
+ ///
35
+ /// If present, the overwriting storage.
36
+ pub storage: Option<Vec<StorageSlot>>,
22
37
  }
23
38
 
24
- impl TryFrom<GenesisAccount> for edr_provider::AccountConfig {
39
+ impl TryFrom<AccountOverride> for (edr_eth::Address, edr_provider::AccountOverride) {
25
40
  type Error = napi::Error;
26
41
 
27
- fn try_from(value: GenesisAccount) -> Result<Self, Self::Error> {
28
- static_assertions::assert_not_impl_all!(JsString: Debug, Display, Serialize);
29
- // `k256::SecretKey` has `Debug` implementation, but it's opaque (only shows the
30
- // type name)
31
- static_assertions::assert_not_impl_any!(k256::SecretKey: Display, Serialize);
42
+ fn try_from(value: AccountOverride) -> Result<Self, Self::Error> {
43
+ let AccountOverride {
44
+ address,
45
+ balance,
46
+ nonce,
47
+ code,
48
+ storage,
49
+ } = value;
50
+ let storage = storage
51
+ .map(|storage| {
52
+ storage
53
+ .into_iter()
54
+ .map(|StorageSlot { index, value }| {
55
+ let value = value.try_cast()?;
56
+ let slot = edr_evm::state::EvmStorageSlot::new(value);
57
+
58
+ let index: edr_eth::U256 = index.try_cast()?;
59
+ Ok((index, slot))
60
+ })
61
+ .collect::<napi::Result<_>>()
62
+ })
63
+ .transpose()?;
64
+
65
+ let account_override = edr_provider::AccountOverride {
66
+ balance: balance.map(TryCast::try_cast).transpose()?,
67
+ nonce: nonce.map(TryCast::try_cast).transpose()?,
68
+ code: code.map(TryCast::try_cast).transpose()?,
69
+ storage,
70
+ };
71
+
72
+ let address: edr_eth::Address = address.try_cast()?;
32
73
 
33
- let secret_key = value.secret_key.into_utf8()?;
34
- // This is the only place in production code where it's allowed to use
35
- // `DangerousSecretKeyStr`.
36
- #[allow(deprecated)]
37
- let secret_key_str = DangerousSecretKeyStr(secret_key.as_str()?);
38
- let secret_key: k256::SecretKey = secret_key_from_str(secret_key_str)
39
- .map_err(|e| napi::Error::new(Status::InvalidArg, e.to_string()))?;
74
+ Ok((address, account_override))
75
+ }
76
+ }
77
+
78
+ impl TryFrom<AccountOverride> for Predeploy {
79
+ type Error = napi::Error;
80
+
81
+ fn try_from(value: AccountOverride) -> Result<Self, Self::Error> {
82
+ let (address, account_override) = value.try_into()?;
83
+
84
+ let storage = account_override.storage.unwrap_or_else(HashMap::new);
85
+ let balance = account_override.balance.unwrap_or(U256::ZERO);
86
+ let nonce = account_override.nonce.unwrap_or(0);
87
+ let code = account_override.code.ok_or_else(|| {
88
+ napi::Error::from_reason(format!("Predeploy with address '{address}' must have code"))
89
+ })?;
90
+
91
+ if code.is_empty() {
92
+ return Err(napi::Error::from_reason(
93
+ "Predeploy with address '{address}' must have non-empty code",
94
+ ));
95
+ }
96
+ let code_hash = code.hash_slow();
97
+
98
+ let account_info = AccountInfo {
99
+ balance,
100
+ nonce,
101
+ code_hash,
102
+ code: Some(code),
103
+ };
40
104
 
41
105
  Ok(Self {
42
- secret_key,
43
- balance: value.balance.try_cast()?,
106
+ address,
107
+ account_info,
108
+ storage,
44
109
  })
45
110
  }
46
111
  }
112
+
113
+ /// A description of a storage slot's state.
114
+ #[napi(object)]
115
+ #[derive(Clone, Debug, serde::Serialize)]
116
+ pub struct StorageSlot {
117
+ /// The storage slot's index
118
+ #[serde(serialize_with = "serialize_bigint_as_struct")]
119
+ pub index: BigInt,
120
+ /// The storage slot's value
121
+ #[serde(serialize_with = "serialize_bigint_as_struct")]
122
+ pub value: BigInt,
123
+ }
package/src/block.rs CHANGED
@@ -1,108 +1,7 @@
1
- use edr_eth::{Address, Bytes, B256, B64};
2
- use napi::bindgen_prelude::{BigInt, Buffer};
1
+ use napi::bindgen_prelude::BigInt;
3
2
  use napi_derive::napi;
4
3
 
5
- use crate::{cast::TryCast, withdrawal::Withdrawal};
6
-
7
- #[napi(object)]
8
- pub struct BlockOptions {
9
- /// The parent block's hash
10
- pub parent_hash: Option<Buffer>,
11
- /// The block's beneficiary
12
- pub beneficiary: Option<Buffer>,
13
- /// The state's root hash
14
- pub state_root: Option<Buffer>,
15
- /// The block's difficulty
16
- pub difficulty: Option<BigInt>,
17
- /// The block's number
18
- pub number: Option<BigInt>,
19
- /// The block's gas limit
20
- pub gas_limit: Option<BigInt>,
21
- /// The block's timestamp
22
- pub timestamp: Option<BigInt>,
23
- /// The block's extra data
24
- pub extra_data: Option<Buffer>,
25
- /// The block's mix hash (or prevrandao)
26
- pub mix_hash: Option<Buffer>,
27
- /// The block's nonce
28
- pub nonce: Option<Buffer>,
29
- /// The block's base gas fee
30
- pub base_fee: Option<BigInt>,
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>,
35
- /// The hash tree root of the parent beacon block for the given execution
36
- /// block (EIP-4788).
37
- pub parent_beacon_block_root: Option<Buffer>,
38
- /// The commitment hash calculated for a list of [EIP-7685] data requests.
39
- ///
40
- /// [EIP-7685]: https://eips.ethereum.org/EIPS/eip-7685
41
- pub requests_hash: Option<Buffer>,
42
- }
43
-
44
- impl TryFrom<BlockOptions> for edr_eth::block::BlockOptions {
45
- type Error = napi::Error;
46
-
47
- #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
48
- fn try_from(value: BlockOptions) -> Result<Self, Self::Error> {
49
- Ok(Self {
50
- parent_hash: value
51
- .parent_hash
52
- .map(TryCast::<B256>::try_cast)
53
- .transpose()?,
54
- beneficiary: value
55
- .beneficiary
56
- .map(TryCast::<Address>::try_cast)
57
- .transpose()?,
58
- state_root: value
59
- .state_root
60
- .map(TryCast::<B256>::try_cast)
61
- .transpose()?,
62
- difficulty: value
63
- .difficulty
64
- .map_or(Ok(None), |difficulty| difficulty.try_cast().map(Some))?,
65
- number: value
66
- .number
67
- .map_or(Ok(None), |number| number.try_cast().map(Some))?,
68
- gas_limit: value
69
- .gas_limit
70
- .map_or(Ok(None), |gas_limit| gas_limit.try_cast().map(Some))?,
71
- timestamp: value
72
- .timestamp
73
- .map_or(Ok(None), |timestamp| timestamp.try_cast().map(Some))?,
74
- extra_data: value
75
- .extra_data
76
- .map(|extra_data| Bytes::copy_from_slice(&extra_data)),
77
- mix_hash: value.mix_hash.map(TryCast::<B256>::try_cast).transpose()?,
78
- nonce: value.nonce.map(TryCast::<B64>::try_cast).transpose()?,
79
- base_fee: value
80
- .base_fee
81
- .map_or(Ok(None), |basefee| basefee.try_cast().map(Some))?,
82
- withdrawals: value
83
- .withdrawals
84
- .map(|withdrawals| {
85
- withdrawals
86
- .into_iter()
87
- .map(edr_eth::withdrawal::Withdrawal::try_from)
88
- .collect()
89
- })
90
- .transpose()?,
91
- blob_gas: value
92
- .blob_gas
93
- .map(edr_eth::block::BlobGas::try_from)
94
- .transpose()?,
95
- parent_beacon_block_root: value
96
- .parent_beacon_block_root
97
- .map(TryCast::<B256>::try_cast)
98
- .transpose()?,
99
- requests_hash: value
100
- .requests_hash
101
- .map(TryCast::<B256>::try_cast)
102
- .transpose()?,
103
- })
104
- }
105
- }
4
+ use crate::cast::TryCast;
106
5
 
107
6
  /// Information about the blob gas used in a block.
108
7
  #[napi(object)]
@@ -2,7 +2,7 @@ use std::sync::mpsc::channel;
2
2
 
3
3
  use edr_eth::{Address, Bytes};
4
4
  use napi::{
5
- bindgen_prelude::{Buffer, Promise},
5
+ bindgen_prelude::{Promise, Uint8Array},
6
6
  threadsafe_function::{
7
7
  ErrorStrategy, ThreadSafeCallContext, ThreadsafeFunction, ThreadsafeFunctionCallMode,
8
8
  },
@@ -16,7 +16,7 @@ use crate::cast::TryCast;
16
16
  /// The result of executing a call override.
17
17
  #[napi(object)]
18
18
  pub struct CallOverrideResult {
19
- pub result: Buffer,
19
+ pub result: Uint8Array,
20
20
  pub should_revert: bool,
21
21
  }
22
22
 
@@ -27,7 +27,7 @@ impl TryCast<Option<edr_provider::CallOverrideResult>> for Option<CallOverrideRe
27
27
  match self {
28
28
  None => Ok(None),
29
29
  Some(result) => Ok(Some(edr_provider::CallOverrideResult {
30
- output: result.result.try_cast()?,
30
+ output: Bytes::copy_from_slice(&result.result),
31
31
  should_revert: result.should_revert,
32
32
  })),
33
33
  }
@@ -56,20 +56,20 @@ impl CallOverrideCallback {
56
56
  |ctx: ThreadSafeCallContext<CallOverrideCall>| {
57
57
  let address = ctx
58
58
  .env
59
- .create_buffer_with_data(ctx.value.contract_address.to_vec())?
59
+ .create_arraybuffer_with_data(ctx.value.contract_address.to_vec())?
60
60
  .into_raw();
61
61
 
62
62
  let data = ctx
63
63
  .env
64
- .create_buffer_with_data(ctx.value.data.to_vec())?
64
+ .create_arraybuffer_with_data(ctx.value.data.to_vec())?
65
65
  .into_raw();
66
66
 
67
67
  Ok(vec![address, data])
68
68
  },
69
69
  )?;
70
70
 
71
- // Maintain a weak reference to the function to avoid the event loop from
72
- // exiting.
71
+ // Maintain a weak reference to the function to avoid blocking the event loop
72
+ // from exiting.
73
73
  call_override_callback_fn.unref(env)?;
74
74
 
75
75
  Ok(Self {
package/src/cast.rs CHANGED
@@ -1,6 +1,6 @@
1
- use edr_eth::{Address, Bytes, B256, B64, U256};
1
+ use edr_eth::{Address, Bytecode, Bytes, B256, B64, U256};
2
2
  use napi::{
3
- bindgen_prelude::{BigInt, Buffer},
3
+ bindgen_prelude::{BigInt, Uint8Array},
4
4
  Status,
5
5
  };
6
6
 
@@ -15,48 +15,62 @@ pub trait TryCast<T>: Sized {
15
15
  fn try_cast(self) -> Result<T, Self::Error>;
16
16
  }
17
17
 
18
- impl TryCast<Address> for Buffer {
18
+ impl TryCast<Address> for Uint8Array {
19
19
  type Error = napi::Error;
20
20
 
21
21
  fn try_cast(self) -> std::result::Result<Address, Self::Error> {
22
22
  if self.len() != 20 {
23
23
  return Err(napi::Error::new(
24
24
  Status::InvalidArg,
25
- "Buffer was expected to be 20 bytes.".to_string(),
25
+ "Uint8Array was expected to be 20 bytes.".to_string(),
26
26
  ));
27
27
  }
28
28
  Ok(Address::from_slice(&self))
29
29
  }
30
30
  }
31
31
 
32
- impl TryCast<B64> for Buffer {
32
+ impl TryCast<B64> for Uint8Array {
33
33
  type Error = napi::Error;
34
34
 
35
35
  fn try_cast(self) -> std::result::Result<B64, Self::Error> {
36
36
  if self.len() != 8 {
37
37
  return Err(napi::Error::new(
38
38
  Status::InvalidArg,
39
- "Buffer was expected to be 8 bytes.".to_string(),
39
+ "Uint8Array was expected to be 8 bytes.".to_string(),
40
40
  ));
41
41
  }
42
42
  Ok(B64::from_slice(&self))
43
43
  }
44
44
  }
45
45
 
46
- impl TryCast<B256> for Buffer {
46
+ impl TryCast<B256> for Uint8Array {
47
47
  type Error = napi::Error;
48
48
 
49
49
  fn try_cast(self) -> std::result::Result<B256, Self::Error> {
50
50
  if self.len() != 32 {
51
51
  return Err(napi::Error::new(
52
52
  Status::InvalidArg,
53
- "Buffer was expected to be 32 bytes.".to_string(),
53
+ "Uint8Array was expected to be 32 bytes.".to_string(),
54
54
  ));
55
55
  }
56
56
  Ok(B256::from_slice(&self))
57
57
  }
58
58
  }
59
59
 
60
+ impl TryCast<Bytecode> for Uint8Array {
61
+ type Error = napi::Error;
62
+
63
+ fn try_cast(self) -> std::result::Result<Bytecode, Self::Error> {
64
+ let bytes = Bytes::copy_from_slice(&self);
65
+ Bytecode::new_raw_checked(bytes).map_err(|error| {
66
+ napi::Error::new(
67
+ Status::InvalidArg,
68
+ format!("Uint8Array was not valid bytecode: {error}"),
69
+ )
70
+ })
71
+ }
72
+ }
73
+
60
74
  impl TryCast<u64> for BigInt {
61
75
  type Error = napi::Error;
62
76
 
@@ -81,6 +95,30 @@ impl TryCast<u64> for BigInt {
81
95
  }
82
96
  }
83
97
 
98
+ impl TryCast<u128> for BigInt {
99
+ type Error = napi::Error;
100
+
101
+ fn try_cast(self) -> std::result::Result<u128, Self::Error> {
102
+ let (signed, value, lossless) = self.get_u128();
103
+
104
+ if signed {
105
+ return Err(napi::Error::new(
106
+ Status::InvalidArg,
107
+ "BigInt was expected to be unsigned.".to_string(),
108
+ ));
109
+ }
110
+
111
+ if !lossless {
112
+ return Err(napi::Error::new(
113
+ Status::InvalidArg,
114
+ "BigInt was expected to fit within 128 bits.".to_string(),
115
+ ));
116
+ }
117
+
118
+ Ok(value)
119
+ }
120
+ }
121
+
84
122
  impl TryCast<usize> for BigInt {
85
123
  type Error = napi::Error;
86
124
 
@@ -118,15 +156,7 @@ impl<T> TryCast<T> for T {
118
156
  }
119
157
  }
120
158
 
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> {
159
+ impl TryCast<Option<Bytes>> for Option<Uint8Array> {
130
160
  type Error = napi::Error;
131
161
 
132
162
  fn try_cast(self) -> Result<Option<Bytes>, Self::Error> {
@@ -0,0 +1,51 @@
1
+ use std::sync::Arc;
2
+
3
+ use edr_eth::l1;
4
+ use edr_generic::GenericChainSpec;
5
+ use edr_napi_core::{
6
+ logger::{self, Logger},
7
+ provider::{self, ProviderBuilder, SyncProviderFactory},
8
+ spec::SyncNapiSpec as _,
9
+ subscription,
10
+ };
11
+ use edr_solidity::contract_decoder::ContractDecoder;
12
+ use napi_derive::napi;
13
+
14
+ use crate::provider::ProviderFactory;
15
+
16
+ pub struct GenericChainProviderFactory;
17
+
18
+ impl SyncProviderFactory for GenericChainProviderFactory {
19
+ fn create_provider_builder(
20
+ &self,
21
+ env: &napi::Env,
22
+ provider_config: edr_napi_core::provider::Config,
23
+ logger_config: logger::Config,
24
+ subscription_config: subscription::Config,
25
+ contract_decoder: Arc<ContractDecoder>,
26
+ ) -> napi::Result<Box<dyn provider::Builder>> {
27
+ let logger = Logger::<GenericChainSpec>::new(logger_config, Arc::clone(&contract_decoder))?;
28
+
29
+ let provider_config =
30
+ edr_provider::ProviderConfig::<l1::SpecId>::try_from(provider_config)?;
31
+
32
+ let subscription_callback =
33
+ subscription::Callback::new(env, subscription_config.subscription_callback)?;
34
+
35
+ Ok(Box::new(ProviderBuilder::new(
36
+ contract_decoder,
37
+ Box::new(logger),
38
+ provider_config,
39
+ subscription_callback,
40
+ )))
41
+ }
42
+ }
43
+
44
+ #[napi]
45
+ pub const GENERIC_CHAIN_TYPE: &str = GenericChainSpec::CHAIN_TYPE;
46
+
47
+ #[napi(catch_unwind)]
48
+ pub fn generic_chain_provider_factory() -> ProviderFactory {
49
+ let factory: Arc<dyn SyncProviderFactory> = Arc::new(GenericChainProviderFactory);
50
+ factory.into()
51
+ }