@nomicfoundation/edr 0.12.0-next.8 → 0.12.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 (52) hide show
  1. package/coverage.sol +38 -0
  2. package/dist/src/ts/coverage.d.ts +6 -0
  3. package/dist/src/ts/coverage.d.ts.map +1 -0
  4. package/dist/src/ts/coverage.js +51 -0
  5. package/dist/src/ts/coverage.js.map +1 -0
  6. package/index.d.ts +267 -27
  7. package/index.js +5 -2
  8. package/package.json +23 -12
  9. package/src/account.rs +0 -124
  10. package/src/block.rs +0 -28
  11. package/src/call_override.rs +0 -116
  12. package/src/cast.rs +0 -165
  13. package/src/chains/generic.rs +0 -58
  14. package/src/chains/l1.rs +0 -268
  15. package/src/chains/op.rs +0 -424
  16. package/src/chains.rs +0 -7
  17. package/src/config.rs +0 -700
  18. package/src/context.rs +0 -447
  19. package/src/contract_decoder.rs +0 -57
  20. package/src/debug_trace.rs +0 -40
  21. package/src/gas_report.rs +0 -92
  22. package/src/instrument.rs +0 -109
  23. package/src/lib.rs +0 -50
  24. package/src/log.rs +0 -28
  25. package/src/logger.rs +0 -120
  26. package/src/mock/time.rs +0 -134
  27. package/src/mock.rs +0 -71
  28. package/src/precompile.rs +0 -50
  29. package/src/provider/factory.rs +0 -22
  30. package/src/provider/response.rs +0 -73
  31. package/src/provider.rs +0 -162
  32. package/src/result.rs +0 -212
  33. package/src/scenarios.rs +0 -53
  34. package/src/serde.rs +0 -57
  35. package/src/solidity_tests/artifact.rs +0 -184
  36. package/src/solidity_tests/config.rs +0 -793
  37. package/src/solidity_tests/factory.rs +0 -22
  38. package/src/solidity_tests/l1.rs +0 -68
  39. package/src/solidity_tests/op.rs +0 -69
  40. package/src/solidity_tests/runner.rs +0 -51
  41. package/src/solidity_tests/test_results.rs +0 -736
  42. package/src/solidity_tests.rs +0 -56
  43. package/src/subscription.rs +0 -32
  44. package/src/trace/debug.rs +0 -61
  45. package/src/trace/exit.rs +0 -89
  46. package/src/trace/library_utils.rs +0 -11
  47. package/src/trace/model.rs +0 -59
  48. package/src/trace/return_data.rs +0 -96
  49. package/src/trace/solidity_stack_trace.rs +0 -869
  50. package/src/trace.rs +0 -199
  51. package/src/ts/solidity_tests.ts +0 -46
  52. package/src/withdrawal.rs +0 -49
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nomicfoundation/edr",
3
- "version": "0.12.0-next.8",
3
+ "version": "0.12.0",
4
4
  "devDependencies": {
5
5
  "@napi-rs/cli": "^2.18.4",
6
6
  "@nomicfoundation/ethereumjs-util": "^9.0.4",
@@ -9,16 +9,16 @@
9
9
  "@types/chai-as-promised": "^7.1.8",
10
10
  "@types/mocha": ">=9.1.0",
11
11
  "@types/node": "^20.0.0",
12
- "@typescript-eslint/eslint-plugin": "5.61.0",
13
- "@typescript-eslint/parser": "5.61.0",
12
+ "@typescript-eslint/eslint-plugin": "5.62.0",
13
+ "@typescript-eslint/parser": "5.62.0",
14
14
  "chai": "^4.3.6",
15
15
  "chai-as-promised": "^7.1.1",
16
16
  "chalk": "^2.4.2",
17
17
  "eslint": "^8.44.0",
18
- "eslint-config-prettier": "9.1.0",
19
- "eslint-plugin-import": "2.27.5",
20
- "eslint-plugin-mocha": "10.4.1",
21
- "eslint-plugin-prettier": "5.2.1",
18
+ "eslint-config-prettier": "9.1.2",
19
+ "eslint-plugin-import": "2.32.0",
20
+ "eslint-plugin-mocha": "10.5.0",
21
+ "eslint-plugin-prettier": "5.5.5",
22
22
  "ethers": "^6.1.0",
23
23
  "json-stream-stringify": "^3.1.4",
24
24
  "mocha": "^10.0.0",
@@ -31,13 +31,13 @@
31
31
  },
32
32
  "exports": {
33
33
  ".": "./index.js",
34
- "./solidity-tests": "./dist/src/ts/solidity_tests.js"
34
+ "./coverage": "./dist/src/ts/coverage.js"
35
35
  },
36
36
  "files": [
37
37
  "index.js",
38
38
  "index.d.ts",
39
- "src/",
40
- "dist/src/"
39
+ "dist/src/",
40
+ "coverage.sol"
41
41
  ],
42
42
  "license": "MIT",
43
43
  "main": "index.js",
@@ -58,20 +58,31 @@
58
58
  },
59
59
  "repository": "NomicFoundation/edr.git",
60
60
  "types": "index.d.ts",
61
+ "dependencies": {
62
+ "@nomicfoundation/edr-darwin-arm64": "0.12.0",
63
+ "@nomicfoundation/edr-darwin-x64": "0.12.0",
64
+ "@nomicfoundation/edr-linux-arm64-gnu": "0.12.0",
65
+ "@nomicfoundation/edr-linux-arm64-musl": "0.12.0",
66
+ "@nomicfoundation/edr-linux-x64-gnu": "0.12.0",
67
+ "@nomicfoundation/edr-linux-x64-musl": "0.12.0",
68
+ "@nomicfoundation/edr-win32-x64-msvc": "0.12.0"
69
+ },
61
70
  "scripts": {
62
71
  "artifacts": "napi artifacts",
63
72
  "build": "pnpm run build:publish",
64
73
  "build:debug": "bash ../../scripts/build_edr_napi.sh --features op",
65
- "build:dev": "bash ../../scripts/build_edr_napi.sh --release --features op,test-mock",
74
+ "build:dev": "bash ../../scripts/build_edr_napi.sh --release --features op",
75
+ "build:perf-js": "RUSTFLAGS='-Cforce-frame-pointers=yes' bash ../../scripts/build_edr_napi.sh --profile napi-publish --features op",
66
76
  "build:publish": "bash ../../scripts/build_edr_napi.sh --profile napi-publish --features op",
67
77
  "build:scenarios": "bash ../../scripts/build_edr_napi.sh --release --features op,scenarios",
78
+ "build:test": "bash ../../scripts/build_edr_napi.sh --release --features op,test-mock",
68
79
  "build:tracing": "bash ../../scripts/build_edr_napi.sh --release --features op,tracing",
69
80
  "build:typingFile": "bash ../../scripts/build_edr_napi.sh --features op",
70
81
  "clean": "rm -rf @nomicfoundation/edr.node",
71
82
  "eslint": "eslint 'test/**/*.ts'",
72
83
  "lint": "pnpm run prettier && pnpm run eslint",
73
84
  "lint:fix": "pnpm run prettier --write",
74
- "pretest": "pnpm build:dev",
85
+ "pretest": "pnpm build:test",
75
86
  "prettier": "prettier --check \"test/**.ts\"",
76
87
  "test": "node --max-old-space-size=8192 node_modules/mocha/bin/_mocha --recursive \"test/**/*.ts\"",
77
88
  "testNoBuild": "node --max-old-space-size=8192 node_modules/mocha/bin/_mocha --recursive \"test/**/{,!(logs|mock)}.ts\"",
package/src/account.rs DELETED
@@ -1,124 +0,0 @@
1
- use derive_more::Debug;
2
- use edr_primitives::{hex, Address, HashMap, U256};
3
- use edr_solidity_tests::{backend::Predeploy, revm::state::AccountInfo};
4
- use edr_state_api::EvmStorageSlot;
5
- use napi::bindgen_prelude::{BigInt, Uint8Array};
6
- use napi_derive::napi;
7
-
8
- use crate::{
9
- cast::TryCast,
10
- serde::{
11
- serialize_bigint_as_struct, serialize_optional_bigint_as_struct,
12
- serialize_optional_uint8array_as_hex, serialize_uint8array_as_hex,
13
- },
14
- };
15
-
16
- /// Specification of overrides for an account and its storage.
17
- #[napi(object)]
18
- #[derive(Clone, Debug, serde::Serialize)]
19
- pub struct AccountOverride {
20
- /// The account's address
21
- #[debug("{}", hex::encode(address))]
22
- #[serde(serialize_with = "serialize_uint8array_as_hex")]
23
- pub address: Uint8Array,
24
- /// If present, the overwriting balance.
25
- #[serde(serialize_with = "serialize_optional_bigint_as_struct")]
26
- pub balance: Option<BigInt>,
27
- /// If present, the overwriting nonce.
28
- #[serde(serialize_with = "serialize_optional_bigint_as_struct")]
29
- pub nonce: Option<BigInt>,
30
- /// If present, the overwriting code.
31
- #[debug("{:?}", code.as_ref().map(hex::encode))]
32
- #[serde(serialize_with = "serialize_optional_uint8array_as_hex")]
33
- pub code: Option<Uint8Array>,
34
- /// BEWARE: This field is not supported yet. See <https://github.com/NomicFoundation/edr/issues/911>
35
- ///
36
- /// If present, the overwriting storage.
37
- pub storage: Option<Vec<StorageSlot>>,
38
- }
39
-
40
- impl TryFrom<AccountOverride> for (Address, edr_provider::AccountOverride) {
41
- type Error = napi::Error;
42
-
43
- fn try_from(value: AccountOverride) -> Result<Self, Self::Error> {
44
- let AccountOverride {
45
- address,
46
- balance,
47
- nonce,
48
- code,
49
- storage,
50
- } = value;
51
- let storage = storage
52
- .map(|storage| {
53
- storage
54
- .into_iter()
55
- .map(|StorageSlot { index, value }| {
56
- let value = value.try_cast()?;
57
- let slot = EvmStorageSlot::new(value, 0);
58
-
59
- let index: U256 = index.try_cast()?;
60
- Ok((index, slot))
61
- })
62
- .collect::<napi::Result<_>>()
63
- })
64
- .transpose()?;
65
-
66
- let account_override = edr_provider::AccountOverride {
67
- balance: balance.map(TryCast::try_cast).transpose()?,
68
- nonce: nonce.map(TryCast::try_cast).transpose()?,
69
- code: code.map(TryCast::try_cast).transpose()?,
70
- storage,
71
- };
72
-
73
- let address: Address = address.try_cast()?;
74
-
75
- Ok((address, account_override))
76
- }
77
- }
78
-
79
- impl TryFrom<AccountOverride> for Predeploy {
80
- type Error = napi::Error;
81
-
82
- fn try_from(value: AccountOverride) -> Result<Self, Self::Error> {
83
- let (address, account_override) = value.try_into()?;
84
-
85
- let storage = account_override.storage.unwrap_or_else(HashMap::new);
86
- let balance = account_override.balance.unwrap_or(U256::ZERO);
87
- let nonce = account_override.nonce.unwrap_or(0);
88
- let code = account_override.code.ok_or_else(|| {
89
- napi::Error::from_reason(format!("Predeploy with address '{address}' must have code"))
90
- })?;
91
-
92
- if code.is_empty() {
93
- return Err(napi::Error::from_reason(
94
- "Predeploy with address '{address}' must have non-empty code",
95
- ));
96
- }
97
- let code_hash = code.hash_slow();
98
-
99
- let account_info = AccountInfo {
100
- balance,
101
- nonce,
102
- code_hash,
103
- code: Some(code),
104
- };
105
-
106
- Ok(Self {
107
- address,
108
- account_info,
109
- storage,
110
- })
111
- }
112
- }
113
-
114
- /// A description of a storage slot's state.
115
- #[napi(object)]
116
- #[derive(Clone, Debug, serde::Serialize)]
117
- pub struct StorageSlot {
118
- /// The storage slot's index
119
- #[serde(serialize_with = "serialize_bigint_as_struct")]
120
- pub index: BigInt,
121
- /// The storage slot's value
122
- #[serde(serialize_with = "serialize_bigint_as_struct")]
123
- pub value: BigInt,
124
- }
package/src/block.rs DELETED
@@ -1,28 +0,0 @@
1
- use napi::bindgen_prelude::BigInt;
2
- use napi_derive::napi;
3
-
4
- use crate::cast::TryCast;
5
-
6
- /// Information about the blob gas used in a block.
7
- #[napi(object)]
8
- pub struct BlobGas {
9
- /// The total amount of blob gas consumed by the transactions within the
10
- /// block.
11
- pub gas_used: BigInt,
12
- /// The running total of blob gas consumed in excess of the target, prior to
13
- /// the block. Blocks with above-target blob gas consumption increase this
14
- /// value, blocks with below-target blob gas consumption decrease it
15
- /// (bounded at 0).
16
- pub excess_gas: BigInt,
17
- }
18
-
19
- impl TryFrom<BlobGas> for edr_block_header::BlobGas {
20
- type Error = napi::Error;
21
-
22
- fn try_from(value: BlobGas) -> Result<Self, Self::Error> {
23
- Ok(Self {
24
- gas_used: BigInt::try_cast(value.gas_used)?,
25
- excess_gas: BigInt::try_cast(value.excess_gas)?,
26
- })
27
- }
28
- }
@@ -1,116 +0,0 @@
1
- use std::sync::mpsc::channel;
2
-
3
- use edr_primitives::{Address, Bytes};
4
- use napi::{
5
- bindgen_prelude::{Promise, Uint8Array},
6
- threadsafe_function::{
7
- ErrorStrategy, ThreadSafeCallContext, ThreadsafeFunction, ThreadsafeFunctionCallMode,
8
- },
9
- tokio::runtime,
10
- Env, JsFunction, Status,
11
- };
12
- use napi_derive::napi;
13
-
14
- use crate::cast::TryCast;
15
-
16
- /// The result of executing a call override.
17
- #[napi(object)]
18
- pub struct CallOverrideResult {
19
- pub result: Uint8Array,
20
- pub should_revert: bool,
21
- }
22
-
23
- impl TryCast<Option<edr_provider::CallOverrideResult>> for Option<CallOverrideResult> {
24
- type Error = napi::Error;
25
-
26
- fn try_cast(self) -> Result<Option<edr_provider::CallOverrideResult>, Self::Error> {
27
- match self {
28
- None => Ok(None),
29
- Some(result) => Ok(Some(edr_provider::CallOverrideResult {
30
- output: Bytes::copy_from_slice(&result.result),
31
- should_revert: result.should_revert,
32
- })),
33
- }
34
- }
35
- }
36
-
37
- struct CallOverrideCall {
38
- contract_address: Address,
39
- data: Bytes,
40
- }
41
-
42
- #[derive(Clone)]
43
- pub struct CallOverrideCallback {
44
- call_override_callback_fn: ThreadsafeFunction<CallOverrideCall, ErrorStrategy::Fatal>,
45
- runtime: runtime::Handle,
46
- }
47
-
48
- impl CallOverrideCallback {
49
- pub fn new(
50
- env: &Env,
51
- call_override_callback: JsFunction,
52
- runtime: runtime::Handle,
53
- ) -> napi::Result<Self> {
54
- let mut call_override_callback_fn = call_override_callback.create_threadsafe_function(
55
- 0,
56
- |ctx: ThreadSafeCallContext<CallOverrideCall>| {
57
- let address = ctx
58
- .env
59
- .create_arraybuffer_with_data(ctx.value.contract_address.to_vec())?
60
- .into_raw();
61
-
62
- let data = ctx
63
- .env
64
- .create_arraybuffer_with_data(ctx.value.data.to_vec())?
65
- .into_raw();
66
-
67
- Ok(vec![address, data])
68
- },
69
- )?;
70
-
71
- // Maintain a weak reference to the function to avoid blocking the event loop
72
- // from exiting.
73
- call_override_callback_fn.unref(env)?;
74
-
75
- Ok(Self {
76
- call_override_callback_fn,
77
- runtime,
78
- })
79
- }
80
-
81
- pub fn call_override(
82
- &self,
83
- contract_address: Address,
84
- data: Bytes,
85
- ) -> Option<edr_provider::CallOverrideResult> {
86
- let (sender, receiver) = channel();
87
-
88
- let runtime = self.runtime.clone();
89
- let status = self.call_override_callback_fn.call_with_return_value(
90
- CallOverrideCall {
91
- contract_address,
92
- data,
93
- },
94
- ThreadsafeFunctionCallMode::Blocking,
95
- move |result: Promise<Option<CallOverrideResult>>| {
96
- runtime.spawn(async move {
97
- let result = result.await?.try_cast();
98
- sender.send(result).map_err(|_error| {
99
- napi::Error::new(
100
- Status::GenericFailure,
101
- "Failed to send result from call_override_callback",
102
- )
103
- })
104
- });
105
- Ok(())
106
- },
107
- );
108
-
109
- assert_eq!(status, Status::Ok, "Call override callback failed");
110
-
111
- receiver
112
- .recv()
113
- .unwrap()
114
- .expect("Failed call to call_override_callback")
115
- }
116
- }
package/src/cast.rs DELETED
@@ -1,165 +0,0 @@
1
- use edr_primitives::{Address, Bytecode, Bytes, B256, B64, U256};
2
- use napi::{
3
- bindgen_prelude::{BigInt, Uint8Array},
4
- Status,
5
- };
6
-
7
- /// An attempted conversion that consumes `self`, which may or may not be
8
- /// expensive. It is identical to [`TryInto`], but it allows us to implement
9
- /// the trait for external types.
10
- pub trait TryCast<T>: Sized {
11
- /// The type returned in the event of a conversion error.
12
- type Error;
13
-
14
- /// Performs the conversion.
15
- fn try_cast(self) -> Result<T, Self::Error>;
16
- }
17
-
18
- impl TryCast<Address> for Uint8Array {
19
- type Error = napi::Error;
20
-
21
- fn try_cast(self) -> std::result::Result<Address, Self::Error> {
22
- if self.len() != 20 {
23
- return Err(napi::Error::new(
24
- Status::InvalidArg,
25
- "Uint8Array was expected to be 20 bytes.".to_string(),
26
- ));
27
- }
28
- Ok(Address::from_slice(&self))
29
- }
30
- }
31
-
32
- impl TryCast<B64> for Uint8Array {
33
- type Error = napi::Error;
34
-
35
- fn try_cast(self) -> std::result::Result<B64, Self::Error> {
36
- if self.len() != 8 {
37
- return Err(napi::Error::new(
38
- Status::InvalidArg,
39
- "Uint8Array was expected to be 8 bytes.".to_string(),
40
- ));
41
- }
42
- Ok(B64::from_slice(&self))
43
- }
44
- }
45
-
46
- impl TryCast<B256> for Uint8Array {
47
- type Error = napi::Error;
48
-
49
- fn try_cast(self) -> std::result::Result<B256, Self::Error> {
50
- if self.len() != 32 {
51
- return Err(napi::Error::new(
52
- Status::InvalidArg,
53
- "Uint8Array was expected to be 32 bytes.".to_string(),
54
- ));
55
- }
56
- Ok(B256::from_slice(&self))
57
- }
58
- }
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
-
74
- impl TryCast<u64> for BigInt {
75
- type Error = napi::Error;
76
-
77
- fn try_cast(self) -> std::result::Result<u64, Self::Error> {
78
- let (signed, value, lossless) = self.get_u64();
79
-
80
- if signed {
81
- return Err(napi::Error::new(
82
- Status::InvalidArg,
83
- "BigInt was expected to be unsigned.".to_string(),
84
- ));
85
- }
86
-
87
- if !lossless {
88
- return Err(napi::Error::new(
89
- Status::InvalidArg,
90
- "BigInt was expected to fit within 64 bits.".to_string(),
91
- ));
92
- }
93
-
94
- Ok(value)
95
- }
96
- }
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
-
122
- impl TryCast<usize> for BigInt {
123
- type Error = napi::Error;
124
-
125
- fn try_cast(self) -> std::result::Result<usize, Self::Error> {
126
- let size: u64 = BigInt::try_cast(self)?;
127
- usize::try_from(size).map_err(|e| napi::Error::new(Status::InvalidArg, e.to_string()))
128
- }
129
- }
130
-
131
- impl TryCast<U256> for BigInt {
132
- type Error = napi::Error;
133
-
134
- fn try_cast(mut self) -> std::result::Result<U256, Self::Error> {
135
- let num_words = self.words.len();
136
- match num_words.cmp(&4) {
137
- std::cmp::Ordering::Less => self.words.append(&mut vec![0u64; 4 - num_words]),
138
- std::cmp::Ordering::Equal => (),
139
- std::cmp::Ordering::Greater => {
140
- return Err(napi::Error::new(
141
- Status::InvalidArg,
142
- "BigInt cannot have more than 4 words.".to_owned(),
143
- ));
144
- }
145
- }
146
-
147
- Ok(U256::from_limbs(self.words.try_into().unwrap()))
148
- }
149
- }
150
-
151
- impl<T> TryCast<T> for T {
152
- type Error = napi::Error;
153
-
154
- fn try_cast(self) -> std::result::Result<T, Self::Error> {
155
- Ok(self)
156
- }
157
- }
158
-
159
- impl TryCast<Option<Bytes>> for Option<Uint8Array> {
160
- type Error = napi::Error;
161
-
162
- fn try_cast(self) -> Result<Option<Bytes>, Self::Error> {
163
- Ok(self.map(|buffer| Bytes::copy_from_slice(&buffer)))
164
- }
165
- }
@@ -1,58 +0,0 @@
1
- use std::sync::Arc;
2
-
3
- use edr_generic::GenericChainSpec;
4
- use edr_napi_core::{
5
- logger::Logger,
6
- provider::{SyncProvider, SyncProviderFactory},
7
- subscription::subscriber_callback_for_chain_spec,
8
- };
9
- use edr_provider::time::CurrentTime;
10
- use edr_solidity::contract_decoder::ContractDecoder;
11
- use napi::tokio::runtime;
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(
20
- &self,
21
- runtime: runtime::Handle,
22
- provider_config: edr_napi_core::provider::Config,
23
- logger_config: edr_napi_core::logger::Config,
24
- subscription_callback: edr_napi_core::subscription::Callback,
25
- contract_decoder: Arc<ContractDecoder>,
26
- ) -> napi::Result<Arc<dyn SyncProvider>> {
27
- let logger = Logger::<GenericChainSpec, CurrentTime>::new(
28
- logger_config,
29
- Arc::clone(&contract_decoder),
30
- )?;
31
-
32
- let provider_config =
33
- edr_provider::ProviderConfig::<edr_chain_l1::Hardfork>::try_from(provider_config)?;
34
-
35
- let provider = edr_provider::Provider::<GenericChainSpec>::new(
36
- runtime.clone(),
37
- Box::new(logger),
38
- subscriber_callback_for_chain_spec::<GenericChainSpec, CurrentTime>(
39
- subscription_callback,
40
- ),
41
- provider_config,
42
- contract_decoder,
43
- CurrentTime,
44
- )
45
- .map_err(|error| napi::Error::new(napi::Status::GenericFailure, error.to_string()))?;
46
-
47
- Ok(Arc::new(provider))
48
- }
49
- }
50
-
51
- #[napi]
52
- pub const GENERIC_CHAIN_TYPE: &str = edr_generic::CHAIN_TYPE;
53
-
54
- #[napi(catch_unwind)]
55
- pub fn generic_chain_provider_factory() -> ProviderFactory {
56
- let factory: Arc<dyn SyncProviderFactory> = Arc::new(GenericChainProviderFactory);
57
- factory.into()
58
- }