@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
@@ -0,0 +1,56 @@
1
+ pub mod artifact;
2
+ pub mod config;
3
+ pub mod factory;
4
+ pub mod l1;
5
+ #[cfg(feature = "op")]
6
+ pub mod op;
7
+ pub mod runner;
8
+ pub mod test_results;
9
+
10
+ use std::path::Path;
11
+
12
+ use edr_eth::Bytes;
13
+ use edr_solidity::linker::{LinkOutput, Linker};
14
+ use edr_solidity_tests::{constants::LIBRARY_DEPLOYER, contracts::ContractsByArtifact};
15
+ use foundry_compilers::artifacts::Libraries;
16
+
17
+ use crate::solidity_tests::artifact::Artifact;
18
+
19
+ pub(crate) struct LinkingOutput {
20
+ pub libs_to_deploy: Vec<Bytes>,
21
+ pub known_contracts: ContractsByArtifact,
22
+ }
23
+
24
+ impl LinkingOutput {
25
+ pub fn link(project_root: &Path, artifacts: Vec<Artifact>) -> napi::Result<Self> {
26
+ let artifact_contracts = artifacts
27
+ .into_iter()
28
+ .map(|artifact| Ok((artifact.id.try_into()?, artifact.contract.try_into()?)))
29
+ .collect::<napi::Result<Vec<_>>>()?;
30
+
31
+ let linker = Linker::new(project_root, artifact_contracts);
32
+
33
+ let LinkOutput {
34
+ libraries,
35
+ libs_to_deploy,
36
+ } = linker
37
+ .link_with_nonce_or_address(
38
+ Libraries::default(),
39
+ LIBRARY_DEPLOYER,
40
+ 0,
41
+ linker.contracts.keys(),
42
+ )
43
+ .map_err(|error| napi::Error::from_reason(error.to_string()))?;
44
+
45
+ let linked_contracts = linker
46
+ .get_linked_artifacts(&libraries)
47
+ .map_err(|error| napi::Error::from_reason(error.to_string()))?;
48
+
49
+ let known_contracts = ContractsByArtifact::new(linked_contracts);
50
+
51
+ Ok(LinkingOutput {
52
+ libs_to_deploy,
53
+ known_contracts,
54
+ })
55
+ }
56
+ }
@@ -0,0 +1,32 @@
1
+ use napi::{bindgen_prelude::BigInt, JsFunction};
2
+ use napi_derive::napi;
3
+
4
+ /// Configuration for subscriptions.
5
+ #[napi(object)]
6
+ pub struct SubscriptionConfig {
7
+ /// Callback to be called when a new event is received.
8
+ #[napi(ts_type = "(event: SubscriptionEvent) => void")]
9
+ pub subscription_callback: JsFunction,
10
+ }
11
+
12
+ impl From<edr_napi_core::subscription::Config> for SubscriptionConfig {
13
+ fn from(config: edr_napi_core::subscription::Config) -> Self {
14
+ Self {
15
+ subscription_callback: config.subscription_callback,
16
+ }
17
+ }
18
+ }
19
+
20
+ impl From<SubscriptionConfig> for edr_napi_core::subscription::Config {
21
+ fn from(config: SubscriptionConfig) -> Self {
22
+ Self {
23
+ subscription_callback: config.subscription_callback,
24
+ }
25
+ }
26
+ }
27
+
28
+ #[napi(object)]
29
+ pub struct SubscriptionEvent {
30
+ pub filter_id: BigInt,
31
+ pub result: serde_json::Value,
32
+ }
@@ -6,7 +6,7 @@ use napi_derive::napi;
6
6
  use super::solidity_stack_trace::{RevertErrorStackTraceEntry, SolidityStackTrace};
7
7
  use crate::trace::return_data::ReturnData;
8
8
 
9
- #[napi]
9
+ #[napi(catch_unwind)]
10
10
  fn print_stack_trace(trace: SolidityStackTrace) -> napi::Result<()> {
11
11
  let entry_values = trace
12
12
  .into_iter()
package/src/trace/exit.rs CHANGED
@@ -3,7 +3,6 @@
3
3
 
4
4
  use std::fmt;
5
5
 
6
- use edr_evm::HaltReason;
7
6
  use napi_derive::napi;
8
7
 
9
8
  #[napi]
@@ -51,38 +50,38 @@ impl fmt::Display for ExitCode {
51
50
  }
52
51
 
53
52
  #[allow(clippy::fallible_impl_from)] // naively ported for now
54
- impl From<edr_solidity::exit_code::ExitCode> for ExitCode {
55
- fn from(code: edr_solidity::exit_code::ExitCode) -> Self {
53
+ impl From<edr_solidity::exit_code::ExitCode<edr_eth::l1::HaltReason>> for ExitCode {
54
+ fn from(code: edr_solidity::exit_code::ExitCode<edr_eth::l1::HaltReason>) -> Self {
56
55
  use edr_solidity::exit_code::ExitCode;
57
56
 
58
57
  match code {
59
58
  ExitCode::Success => Self::SUCCESS,
60
59
  ExitCode::Revert => Self::REVERT,
61
- ExitCode::Halt(HaltReason::OutOfGas(_)) => Self::OUT_OF_GAS,
62
- ExitCode::Halt(HaltReason::OpcodeNotFound | HaltReason::InvalidFEOpcode
60
+ ExitCode::Halt(edr_eth::l1::HaltReason::OutOfGas(_)) => Self::OUT_OF_GAS,
61
+ ExitCode::Halt(edr_eth::l1::HaltReason::OpcodeNotFound | edr_eth::l1::HaltReason::InvalidFEOpcode
63
62
  // Returned when an opcode is not implemented for the hardfork
64
- | HaltReason::NotActivated) => Self::INVALID_OPCODE,
65
- ExitCode::Halt(HaltReason::StackUnderflow) => Self::STACK_UNDERFLOW,
66
- ExitCode::Halt(HaltReason::CreateContractSizeLimit) => Self::CODESIZE_EXCEEDS_MAXIMUM,
67
- ExitCode::Halt(HaltReason::CreateCollision) => Self::CREATE_COLLISION,
68
- ExitCode::Halt(_) => Self::UNKNOWN_HALT_REASON,
63
+ | edr_eth::l1::HaltReason::NotActivated) => Self::INVALID_OPCODE,
64
+ ExitCode::Halt(edr_eth::l1::HaltReason::StackUnderflow) => Self::STACK_UNDERFLOW,
65
+ ExitCode::Halt(edr_eth::l1::HaltReason::CreateContractSizeLimit) => Self::CODESIZE_EXCEEDS_MAXIMUM,
66
+ ExitCode::Halt(edr_eth::l1::HaltReason::CreateCollision) => Self::CREATE_COLLISION,
67
+ _ => Self::UNKNOWN_HALT_REASON,
69
68
  }
70
69
  }
71
70
  }
72
71
 
73
72
  #[napi]
74
73
  impl Exit {
75
- #[napi(getter)]
74
+ #[napi(catch_unwind, getter)]
76
75
  pub fn kind(&self) -> ExitCode {
77
76
  self.0
78
77
  }
79
78
 
80
- #[napi]
79
+ #[napi(catch_unwind)]
81
80
  pub fn is_error(&self) -> bool {
82
81
  !matches!(self.0, ExitCode::SUCCESS)
83
82
  }
84
83
 
85
- #[napi]
84
+ #[napi(catch_unwind)]
86
85
  pub fn get_reason(&self) -> String {
87
86
  self.0.to_string()
88
87
  }
@@ -1,6 +1,6 @@
1
1
  use napi_derive::napi;
2
2
 
3
- #[napi]
3
+ #[napi(catch_unwind)]
4
4
  pub fn link_hex_string_bytecode(
5
5
  code: String,
6
6
  address: String,
@@ -20,7 +20,7 @@ pub struct ReturnData {
20
20
 
21
21
  #[napi]
22
22
  impl ReturnData {
23
- #[napi(constructor)]
23
+ #[napi(catch_unwind, constructor)]
24
24
  pub fn new(value: Uint8Array) -> Self {
25
25
  let selector = if value.len() >= 4 {
26
26
  Some(value[0..4].try_into().unwrap())
@@ -31,45 +31,45 @@ impl ReturnData {
31
31
  Self { value, selector }
32
32
  }
33
33
 
34
- #[napi]
34
+ #[napi(catch_unwind)]
35
35
  pub fn is_empty(&self) -> bool {
36
36
  self.value.is_empty()
37
37
  }
38
38
 
39
39
  pub fn matches_selector(&self, selector: impl AsRef<[u8]>) -> bool {
40
40
  self.selector
41
- .map_or(false, |value| value == selector.as_ref())
41
+ .is_some_and(|value| value == selector.as_ref())
42
42
  }
43
43
 
44
- #[napi]
44
+ #[napi(catch_unwind)]
45
45
  pub fn is_error_return_data(&self) -> bool {
46
46
  self.selector == Some(Error::SELECTOR)
47
47
  }
48
48
 
49
- #[napi]
49
+ #[napi(catch_unwind)]
50
50
  pub fn is_panic_return_data(&self) -> bool {
51
51
  self.selector == Some(Panic::SELECTOR)
52
52
  }
53
53
 
54
- #[napi]
54
+ #[napi(catch_unwind)]
55
55
  pub fn decode_error(&self) -> napi::Result<String> {
56
56
  if self.is_empty() {
57
57
  return Ok(String::new());
58
58
  }
59
59
 
60
- let result = Error::abi_decode(&self.value[..], false).map_err(|_err| {
60
+ let result = Error::abi_decode(&self.value[..]).map_err(|_err| {
61
61
  napi::Error::new(
62
62
  napi::Status::InvalidArg,
63
63
  "Expected return data to be a Error(string) and contain a valid string",
64
64
  )
65
65
  })?;
66
66
 
67
- Ok(result._0)
67
+ Ok(result.0)
68
68
  }
69
69
 
70
- #[napi]
70
+ #[napi(catch_unwind)]
71
71
  pub fn decode_panic(&self) -> napi::Result<BigInt> {
72
- let result = Panic::abi_decode(&self.value[..], false).map_err(|_err| {
72
+ let result = Panic::abi_decode(&self.value[..]).map_err(|_err| {
73
73
  napi::Error::new(
74
74
  napi::Status::InvalidArg,
75
75
  "Expected return data to be a Error(string) and contain a valid string",
@@ -78,7 +78,7 @@ impl ReturnData {
78
78
 
79
79
  Ok(BigInt {
80
80
  sign_bit: false,
81
- words: result._0.as_limbs().to_vec(),
81
+ words: result.0.as_limbs().to_vec(),
82
82
  })
83
83
  }
84
84
  }
@@ -1,8 +1,9 @@
1
1
  //! Naive rewrite of `hardhat-network/stack-traces/solidity-stack-traces.ts`
2
2
  //! from Hardhat.
3
3
 
4
- use edr_eth::U256;
5
- use edr_evm::hex;
4
+ use std::convert::Infallible;
5
+
6
+ use edr_eth::{hex, U256};
6
7
  use napi::bindgen_prelude::{BigInt, Either24, FromNapiValue, ToNapiValue, Uint8Array, Undefined};
7
8
  use napi_derive::napi;
8
9
  use serde::{Serialize, Serializer};
@@ -46,7 +47,7 @@ pub enum StackTraceEntryType {
46
47
  CONTRACT_CALL_RUN_OUT_OF_GAS_ERROR,
47
48
  }
48
49
 
49
- #[napi]
50
+ #[napi(catch_unwind)]
50
51
  pub fn stack_trace_entry_type_to_string(val: StackTraceEntryType) -> &'static str {
51
52
  val.into()
52
53
  }
@@ -107,7 +108,8 @@ impl<const ENTRY_TYPE: u8> FromNapiValue for StackTraceEntryTypeConst<ENTRY_TYPE
107
108
  env: napi::sys::napi_env,
108
109
  napi_val: napi::sys::napi_value,
109
110
  ) -> napi::Result<Self> {
110
- let inner: u8 = FromNapiValue::from_napi_value(env, napi_val)?;
111
+ // SAFETY: The safety concern is propagated in the function signature.
112
+ let inner: u8 = unsafe { FromNapiValue::from_napi_value(env, napi_val) }?;
111
113
 
112
114
  if inner != ENTRY_TYPE {
113
115
  return Err(napi::Error::new(
@@ -124,7 +126,8 @@ impl<const ENTRY_TYPE: u8> ToNapiValue for StackTraceEntryTypeConst<ENTRY_TYPE>
124
126
  env: napi::sys::napi_env,
125
127
  _val: Self,
126
128
  ) -> napi::Result<napi::sys::napi_value> {
127
- u8::to_napi_value(env, ENTRY_TYPE)
129
+ // SAFETY: The safety concern is propagated in the function signature.
130
+ unsafe { u8::to_napi_value(env, ENTRY_TYPE) }
128
131
  }
129
132
  }
130
133
 
@@ -605,7 +608,7 @@ pub type SolidityStackTraceEntry = Either24<
605
608
  >;
606
609
 
607
610
  impl TryCast<SolidityStackTraceEntry> for edr_solidity::solidity_stack_trace::StackTraceEntry {
608
- type Error = napi::Error;
611
+ type Error = Infallible;
609
612
 
610
613
  fn try_cast(self) -> Result<SolidityStackTraceEntry, Self::Error> {
611
614
  use edr_solidity::solidity_stack_trace::StackTraceEntry;
@@ -629,7 +632,7 @@ impl TryCast<SolidityStackTraceEntry> for edr_solidity::solidity_stack_trace::St
629
632
  StackTraceEntry::UnrecognizedContractCallstackEntry { address } => {
630
633
  UnrecognizedContractCallstackEntryStackTraceEntry {
631
634
  type_: StackTraceEntryTypeConst,
632
- address: Uint8Array::from(address.as_slice()),
635
+ address: Uint8Array::with_data_copied(address),
633
636
  source_reference: None,
634
637
  }
635
638
  .into()
@@ -761,7 +764,7 @@ impl TryCast<SolidityStackTraceEntry> for edr_solidity::solidity_stack_trace::St
761
764
  is_invalid_opcode_error,
762
765
  } => UnrecognizedContractErrorStackTraceEntry {
763
766
  type_: StackTraceEntryTypeConst,
764
- address: Uint8Array::from(address.as_slice()),
767
+ address: Uint8Array::with_data_copied(address),
765
768
  return_data: return_data.into(),
766
769
  is_invalid_opcode_error,
767
770
  source_reference: None,
package/src/trace.rs CHANGED
@@ -7,11 +7,9 @@
7
7
 
8
8
  use std::sync::Arc;
9
9
 
10
- use edr_evm::{interpreter::OpCode, trace::BeforeMessage};
11
- use napi::{
12
- bindgen_prelude::{BigInt, Buffer, Either3},
13
- Env, JsBuffer, JsBufferValue,
14
- };
10
+ use edr_eth::{bytecode::opcode::OpCode, l1};
11
+ use edr_evm::trace::BeforeMessage;
12
+ use napi::bindgen_prelude::{BigInt, Either3, Uint8Array};
15
13
  use napi_derive::napi;
16
14
 
17
15
  use crate::result::ExecutionResult;
@@ -28,11 +26,11 @@ pub mod solidity_stack_trace;
28
26
  pub struct TracingMessage {
29
27
  /// Sender address
30
28
  #[napi(readonly)]
31
- pub caller: Buffer,
29
+ pub caller: Uint8Array,
32
30
 
33
31
  /// Recipient address. None if it is a Create message.
34
32
  #[napi(readonly)]
35
- pub to: Option<Buffer>,
33
+ pub to: Option<Uint8Array>,
36
34
 
37
35
  /// Whether it's a static call
38
36
  #[napi(readonly)]
@@ -48,7 +46,7 @@ pub struct TracingMessage {
48
46
 
49
47
  /// Input data of the message
50
48
  #[napi(readonly)]
51
- pub data: JsBuffer,
49
+ pub data: Uint8Array,
52
50
 
53
51
  /// Value sent in the message
54
52
  #[napi(readonly)]
@@ -57,41 +55,37 @@ pub struct TracingMessage {
57
55
  /// Address of the code that is being executed. Can be different from `to`
58
56
  /// if a delegate call is being done.
59
57
  #[napi(readonly)]
60
- pub code_address: Option<Buffer>,
58
+ pub code_address: Option<Uint8Array>,
61
59
 
62
60
  /// Code of the contract that is being executed.
63
61
  #[napi(readonly)]
64
- pub code: Option<JsBuffer>,
62
+ pub code: Option<Uint8Array>,
65
63
  }
66
64
 
67
- impl TracingMessage {
68
- pub fn new(env: &Env, message: &BeforeMessage) -> napi::Result<Self> {
65
+ impl From<&BeforeMessage> for TracingMessage {
66
+ fn from(value: &BeforeMessage) -> Self {
69
67
  // Deconstruct to make sure all fields are handled
70
68
  let BeforeMessage {
71
69
  depth,
72
70
  caller,
73
- to: _,
71
+ to,
74
72
  is_static_call,
75
73
  gas_limit,
76
74
  data,
77
75
  value,
78
76
  code_address,
79
77
  code,
80
- } = message;
78
+ } = value;
81
79
 
82
- let data = env
83
- .create_buffer_with_data(data.to_vec())
84
- .map(JsBufferValue::into_raw)?;
80
+ let data = Uint8Array::with_data_copied(data);
85
81
 
86
- let code = code.as_ref().map_or(Ok(None), |code| {
87
- env.create_buffer_with_data(code.original_bytes().to_vec())
88
- .map(JsBufferValue::into_raw)
89
- .map(Some)
90
- })?;
82
+ let code = code
83
+ .as_ref()
84
+ .map(|code| Uint8Array::with_data_copied(code.original_bytes()));
91
85
 
92
- Ok(TracingMessage {
93
- caller: Buffer::from(caller.as_slice()),
94
- to: message.to.map(|to| Buffer::from(to.as_slice())),
86
+ TracingMessage {
87
+ caller: Uint8Array::with_data_copied(caller),
88
+ to: to.as_ref().map(Uint8Array::with_data_copied),
95
89
  gas_limit: BigInt::from(*gas_limit),
96
90
  is_static_call: *is_static_call,
97
91
  depth: *depth as u8,
@@ -100,9 +94,9 @@ impl TracingMessage {
100
94
  sign_bit: false,
101
95
  words: value.into_limbs().to_vec(),
102
96
  },
103
- code_address: code_address.map(|address| Buffer::from(address.to_vec())),
97
+ code_address: code_address.as_ref().map(Uint8Array::with_data_copied),
104
98
  code,
105
- })
99
+ }
106
100
  }
107
101
  }
108
102
 
@@ -124,7 +118,7 @@ pub struct TracingStep {
124
118
  pub stack: Vec<BigInt>,
125
119
  /// The memory at the step. None if verbose tracing is disabled.
126
120
  #[napi(readonly)]
127
- pub memory: Option<Buffer>,
121
+ pub memory: Option<Uint8Array>,
128
122
  }
129
123
 
130
124
  impl TracingStep {
@@ -138,7 +132,7 @@ impl TracingStep {
138
132
  },
139
133
  |stack| stack.iter().map(u256_to_bigint).collect(),
140
134
  );
141
- let memory = step.memory.as_ref().cloned().map(Buffer::from);
135
+ let memory = step.memory.as_ref().map(Uint8Array::with_data_copied);
142
136
 
143
137
  Self {
144
138
  depth: step.depth as u8,
@@ -150,7 +144,7 @@ impl TracingStep {
150
144
  }
151
145
  }
152
146
 
153
- pub(crate) fn u256_to_bigint(v: &edr_evm::U256) -> BigInt {
147
+ pub(crate) fn u256_to_bigint(v: &edr_eth::U256) -> BigInt {
154
148
  BigInt {
155
149
  sign_bit: false,
156
150
  words: v.into_limbs().to_vec(),
@@ -165,35 +159,34 @@ pub struct TracingMessageResult {
165
159
  }
166
160
 
167
161
  #[napi]
162
+ #[derive(Clone)]
168
163
  pub struct RawTrace {
169
- pub(crate) inner: Arc<edr_evm::trace::Trace>,
164
+ inner: Arc<edr_evm::trace::Trace<l1::HaltReason>>,
170
165
  }
171
166
 
172
- impl RawTrace {
173
- pub fn new(inner: Arc<edr_evm::trace::Trace>) -> Self {
174
- Self { inner }
167
+ impl From<Arc<edr_evm::trace::Trace<l1::HaltReason>>> for RawTrace {
168
+ fn from(value: Arc<edr_evm::trace::Trace<l1::HaltReason>>) -> Self {
169
+ Self { inner: value }
175
170
  }
176
171
  }
177
172
 
178
173
  #[napi]
179
174
  impl RawTrace {
180
- #[napi]
181
- pub fn trace(
182
- &self,
183
- env: Env,
184
- ) -> napi::Result<Vec<Either3<TracingMessage, TracingStep, TracingMessageResult>>> {
175
+ #[napi(getter)]
176
+ pub fn trace(&self) -> Vec<Either3<TracingMessage, TracingStep, TracingMessageResult>> {
185
177
  self.inner
186
178
  .messages
187
179
  .iter()
188
180
  .map(|message| match message {
189
181
  edr_evm::trace::TraceMessage::Before(message) => {
190
- TracingMessage::new(&env, message).map(Either3::A)
182
+ Either3::A(TracingMessage::from(message))
191
183
  }
192
- edr_evm::trace::TraceMessage::Step(step) => Ok(Either3::B(TracingStep::new(step))),
193
- edr_evm::trace::TraceMessage::After(message) => ExecutionResult::new(&env, message)
194
- .map(|execution_result| Either3::C(TracingMessageResult { execution_result })),
184
+ edr_evm::trace::TraceMessage::Step(step) => Either3::B(TracingStep::new(step)),
185
+ edr_evm::trace::TraceMessage::After(message) => Either3::C(TracingMessageResult {
186
+ execution_result: ExecutionResult::from(message),
187
+ }),
195
188
  })
196
- .collect::<napi::Result<_>>()
189
+ .collect()
197
190
  }
198
191
  }
199
192
 
package/src/withdrawal.rs CHANGED
@@ -1,8 +1,8 @@
1
1
  use edr_eth::Address;
2
- use napi::bindgen_prelude::{BigInt, Buffer};
2
+ use napi::bindgen_prelude::{BigInt, Uint8Array};
3
3
  use napi_derive::napi;
4
4
 
5
- use crate::cast::TryCast;
5
+ use crate::cast::TryCast as _;
6
6
 
7
7
  #[napi(object)]
8
8
  pub struct Withdrawal {
@@ -11,7 +11,7 @@ pub struct Withdrawal {
11
11
  /// The index of the validator that generated the withdrawal
12
12
  pub validator_index: BigInt,
13
13
  /// The recipient address for withdrawal value
14
- pub address: Buffer,
14
+ pub address: Uint8Array,
15
15
  /// The value contained in withdrawal
16
16
  pub amount: BigInt,
17
17
  }
@@ -21,7 +21,7 @@ impl From<edr_eth::withdrawal::Withdrawal> for Withdrawal {
21
21
  Self {
22
22
  index: BigInt::from(withdrawal.index),
23
23
  validator_index: BigInt::from(withdrawal.validator_index),
24
- address: Buffer::from(withdrawal.address.as_slice()),
24
+ address: Uint8Array::with_data_copied(withdrawal.address),
25
25
  amount: BigInt {
26
26
  sign_bit: false,
27
27
  words: withdrawal.amount.as_limbs().to_vec(),