Skip to content

Commit 7d25b1b

Browse files
authored
feat: add provider to edr_napi (#4578)
1 parent 37d7fc3 commit 7d25b1b

File tree

96 files changed

+325
-76
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+325
-76
lines changed

.github/workflows/edr-npm-release.yml

+15-15
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ jobs:
8989
runs-on: ${{ matrix.settings.host }}
9090
defaults:
9191
run:
92-
working-directory: ./crates/edr_evm_napi
92+
working-directory: ./crates/edr_napi
9393
steps:
9494
- uses: actions/checkout@v3
9595
- name: Setup node
@@ -144,7 +144,7 @@ jobs:
144144
if: ${{ matrix.settings.docker }}
145145
with:
146146
image: ${{ matrix.settings.docker }}
147-
options: "--user 0:0 -v ${{ github.workspace }}/.cargo-cache/git/db:/usr/local/cargo/git/db -v ${{ github.workspace }}/.cargo/registry/cache:/usr/local/cargo/registry/cache -v ${{ github.workspace }}/.cargo/registry/index:/usr/local/cargo/registry/index -v ${{ github.workspace }}:/build -w /build/crates/edr_evm_napi"
147+
options: "--user 0:0 -v ${{ github.workspace }}/.cargo-cache/git/db:/usr/local/cargo/git/db -v ${{ github.workspace }}/.cargo/registry/cache:/usr/local/cargo/registry/cache -v ${{ github.workspace }}/.cargo/registry/index:/usr/local/cargo/registry/index -v ${{ github.workspace }}:/build -w /build/crates/edr_napi"
148148
run: ${{ matrix.settings.build }}
149149
- name: Build
150150
run: ${{ matrix.settings.build }}
@@ -156,7 +156,7 @@ jobs:
156156
name: bindings-${{ matrix.settings.target }}
157157
# The upload artifact action doesn't respect the working directory setting. Unclear if this is a bug or not
158158
# https://github.com/actions/upload-artifact/issues/294
159-
path: ./crates/edr_evm_napi/${{ env.APP_NAME }}.*.node
159+
path: ./crates/edr_napi/${{ env.APP_NAME }}.*.node
160160
if-no-files-found: error
161161
test-macOS-windows-binding:
162162
name: Test bindings on ${{ matrix.settings.target }} - node@${{ matrix.node }}
@@ -176,7 +176,7 @@ jobs:
176176
runs-on: ${{ matrix.settings.host }}
177177
defaults:
178178
run:
179-
working-directory: ./crates/edr_evm_napi
179+
working-directory: ./crates/edr_napi
180180
steps:
181181
- uses: actions/checkout@v3
182182
- name: Setup node
@@ -191,7 +191,7 @@ jobs:
191191
uses: actions/download-artifact@v3
192192
with:
193193
name: bindings-${{ matrix.settings.target }}
194-
path: ./crates/edr_evm_napi/
194+
path: ./crates/edr_napi/
195195
- name: List packages
196196
run: ls -R .
197197
shell: bash
@@ -222,12 +222,12 @@ jobs:
222222
uses: actions/download-artifact@v3
223223
with:
224224
name: bindings-x86_64-unknown-linux-gnu
225-
path: ./crates/edr_evm_napi/
225+
path: ./crates/edr_napi/
226226
- name: List packages
227227
run: ls -R .
228228
shell: bash
229229
- name: Test bindings
230-
run: docker run --rm -v $(pwd):/build -w /build/crates/edr_evm_napi node:${{ matrix.node }}-slim yarn test
230+
run: docker run --rm -v $(pwd):/build -w /build/crates/edr_napi node:${{ matrix.node }}-slim yarn test
231231
test-linux-x64-musl-binding:
232232
name: Test bindings on x86_64-unknown-linux-musl - node@${{ matrix.node }}
233233
needs:
@@ -255,12 +255,12 @@ jobs:
255255
uses: actions/download-artifact@v3
256256
with:
257257
name: bindings-x86_64-unknown-linux-musl
258-
path: ./crates/edr_evm_napi/
258+
path: ./crates/edr_napi/
259259
- name: List packages
260260
run: ls -R .
261261
shell: bash
262262
- name: Test bindings
263-
run: docker run --rm -v $(pwd):/build -w /build/crates/edr_evm_napi node:${{ matrix.node }}-alpine yarn test
263+
run: docker run --rm -v $(pwd):/build -w /build/crates/edr_napi node:${{ matrix.node }}-alpine yarn test
264264
test-linux-aarch64-gnu-binding:
265265
name: Test bindings on aarch64-unknown-linux-gnu - node@${{ matrix.node }}
266266
needs:
@@ -278,7 +278,7 @@ jobs:
278278
uses: actions/download-artifact@v3
279279
with:
280280
name: bindings-aarch64-unknown-linux-gnu
281-
path: ./crates/edr_evm_napi/
281+
path: ./crates/edr_napi/
282282
- name: List packages
283283
run: ls -R .
284284
shell: bash
@@ -296,7 +296,7 @@ jobs:
296296
uses: addnab/docker-run-action@v3
297297
with:
298298
image: node:${{ matrix.node }}-slim
299-
options: "--platform linux/arm64 -v ${{ github.workspace }}:/build -w /build/crates/edr_evm_napi"
299+
options: "--platform linux/arm64 -v ${{ github.workspace }}:/build -w /build/crates/edr_napi"
300300
run: |
301301
set -e
302302
yarn test
@@ -312,7 +312,7 @@ jobs:
312312
uses: actions/download-artifact@v3
313313
with:
314314
name: bindings-aarch64-unknown-linux-musl
315-
path: ./crates/edr_evm_napi/
315+
path: ./crates/edr_napi/
316316
- name: List packages
317317
run: ls -R .
318318
shell: bash
@@ -330,7 +330,7 @@ jobs:
330330
uses: addnab/docker-run-action@v3
331331
with:
332332
image: node:lts-alpine
333-
options: "--platform linux/arm64 -v ${{ github.workspace }}:/build -w /build/crates/edr_evm_napi"
333+
options: "--platform linux/arm64 -v ${{ github.workspace }}:/build -w /build/crates/edr_napi"
334334
run: |
335335
set -e
336336
yarn test
@@ -370,7 +370,7 @@ jobs:
370370
if: ${{ needs.check_commit.outputs.match == 'true' }}
371371
defaults:
372372
run:
373-
working-directory: ./crates/edr_evm_napi
373+
working-directory: ./crates/edr_napi
374374
steps:
375375
- uses: actions/checkout@v3
376376
- name: Setup node
@@ -384,7 +384,7 @@ jobs:
384384
- name: Download all artifacts
385385
uses: actions/download-artifact@v3
386386
with:
387-
path: ./crates/edr_evm_napi/artifacts
387+
path: ./crates/edr_napi/artifacts
388388
- name: Move artifacts
389389
run: yarn artifacts
390390
- name: List packages

.github/workflows/hardhat-core-ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ jobs:
188188
RUSTFLAGS: "-Dwarnings -Ctarget-feature=+crt-static"
189189
defaults:
190190
run:
191-
working-directory: crates/edr_evm_napi
191+
working-directory: crates/edr_napi
192192
steps:
193193
- uses: actions/checkout@v3
194194

Cargo.lock

+3-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+4-4

book/src/03_release.md

+2-2

crates/README.md

+1-1
File renamed without changes.
File renamed without changes.
File renamed without changes.

crates/edr_evm_napi/Cargo.toml crates/edr_napi/Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "edr_evm_napi"
2+
name = "edr_napi"
33
version = "0.2.0-dev"
44
edition = "2021"
55

@@ -17,6 +17,8 @@ napi-derive = "2.12.3"
1717
edr_defaults = { version = "0.2.0-dev", path = "../edr_defaults" }
1818
edr_evm = { version = "0.2.0-dev", path = "../edr_evm" }
1919
edr_eth = { version = "0.2.0-dev", path = "../edr_eth" }
20+
edr_provider = { version = "0.2.0-dev", path = "../edr_provider" }
21+
edr_rpc_hardhat = {version = "0.2.0-dev", path = "../edr_rpc_hardhat" }
2022
serde_json = { version = "1.0.85", default-features = false, features = ["alloc"] }
2123
tracing = { version = "0.1.37", default-features = false, features = ["std"] }
2224
tracing-flame = { version = "0.2.0", default-features = false, features = ["smallvec"] }
File renamed without changes.

crates/edr_evm_napi/index.d.ts crates/edr_napi/index.d.ts

+50
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,49 @@ export const enum MineOrdering {
223223
}
224224
/** Mines a block using as many transactions as can fit in it. */
225225
export function mineBlock(blockchain: Blockchain, stateManager: State, memPool: MemPool, config: ConfigOptions, timestamp: bigint, beneficiary: Buffer, minGasPrice: bigint, mineOrdering: MineOrdering, reward: bigint, baseFee?: bigint | undefined | null, prevrandao?: Buffer | undefined | null, tracer?: Tracer | undefined | null): Promise<MineBlockResult>
226+
/** Configuration for forking a blockchain */
227+
export interface ForkConfig {
228+
/** The URL of the JSON-RPC endpoint to fork from */
229+
jsonRpcUrl: string
230+
/**
231+
* The block number to fork from. If not provided, the latest safe block is
232+
* used.
233+
*/
234+
blockNumber?: bigint
235+
}
236+
/** Configuration for a provider */
237+
export interface ProviderConfig {
238+
/** Whether to allow blocks with the same timestamp */
239+
allowBlocksWithSameTimestamp: boolean
240+
/** Whether to allow unlimited contract size */
241+
allowUnlimitedContractSize: boolean
242+
/** The gas limit of each block */
243+
blockGasLimit: bigint
244+
/** The directory to cache remote JSON-RPC responses */
245+
cacheDir: string
246+
/** The chain ID of the blockchain */
247+
chainId: bigint
248+
/** The address of the coinbase */
249+
coinbase: Buffer
250+
/**
251+
* The configuration for forking a blockchain. If not provided, a local
252+
* blockchain will be created
253+
*/
254+
fork?: ForkConfig
255+
/** The genesis accounts of the blockchain */
256+
genesisAccounts: Array<GenesisAccount>
257+
/** The hardfork of the blockchain */
258+
hardfork: SpecId
259+
/**
260+
* The initial base fee per gas of the blockchain. Required for EIP-1559
261+
* transactions and later
262+
*/
263+
initialBaseFeePerGas?: bigint
264+
/** The initial date of the blockchain, in seconds since the Unix epoch */
265+
initialDate?: bigint
266+
/** The network ID of the blockchain */
267+
networkId: bigint
268+
}
226269
/** Executes the provided transaction without changing state. */
227270
export function dryRun(blockchain: Blockchain, state: State, stateOverrides: StateOverrides, cfg: ConfigOptions, transaction: TransactionRequest, block: BlockConfig, withTrace: boolean, tracer?: Tracer | undefined | null): Promise<TransactionResult>
228271
/**
@@ -609,6 +652,13 @@ export class MineBlockResult {
609652
/**Retrieves the transactions' traces. */
610653
get traces(): Array<Array<TracingMessage | TracingStep | TracingMessageResult>>
611654
}
655+
/** A JSON-RPC provider for Ethereum. */
656+
export class Provider {
657+
/**Constructs a new provider with the provided configuration. */
658+
static withConfig(config: ProviderConfig): Promise<Provider>
659+
/**Handles a JSON-RPC request and returns a JSON-RPC response. */
660+
handleRequest(jsonRequest: string): Promise<string>
661+
}
612662
export class Receipt {
613663
/**Returns the hash of the block the receipt is included in. */
614664
get blockHash(): Buffer

crates/edr_evm_napi/index.js crates/edr_napi/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ if (!nativeBinding) {
252252
throw new Error(`Failed to load native binding`)
253253
}
254254

255-
const { BlockBuilder, Block, Blockchain, SpecId, Config, EdrContext, debugTraceTransaction, debugTraceCall, Log, MemPool, MineOrdering, MineBlockResult, mineBlock, Receipt, dryRun, guaranteedDryRun, run, StateOverrides, State, Tracer, OrderedTransaction, PendingTransaction, SuccessReason, ExceptionalHalt, TransactionResult } = nativeBinding
255+
const { BlockBuilder, Block, Blockchain, SpecId, Config, EdrContext, debugTraceTransaction, debugTraceCall, Log, MemPool, MineOrdering, MineBlockResult, mineBlock, Provider, Receipt, dryRun, guaranteedDryRun, run, StateOverrides, State, Tracer, OrderedTransaction, PendingTransaction, SuccessReason, ExceptionalHalt, TransactionResult } = nativeBinding
256256

257257
module.exports.BlockBuilder = BlockBuilder
258258
module.exports.Block = Block
@@ -267,6 +267,7 @@ module.exports.MemPool = MemPool
267267
module.exports.MineOrdering = MineOrdering
268268
module.exports.MineBlockResult = MineBlockResult
269269
module.exports.mineBlock = mineBlock
270+
module.exports.Provider = Provider
270271
module.exports.Receipt = Receipt
271272
module.exports.dryRun = dryRun
272273
module.exports.guaranteedDryRun = guaranteedDryRun
File renamed without changes.
File renamed without changes.

crates/edr_evm_napi/src/account.rs crates/edr_napi/src/account.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use std::fmt::Debug;
22

3-
use edr_eth::{signature::secret_key_to_address, Address, Bytes, U256};
3+
use edr_eth::{
4+
signature::{secret_key_from_str, secret_key_to_address},
5+
Address, Bytes, U256,
6+
};
47
use edr_evm::{AccountInfo, HashMap, KECCAK_EMPTY};
58
use napi::{
69
bindgen_prelude::{BigInt, Buffer},
@@ -104,6 +107,20 @@ pub struct GenesisAccount {
104107
pub balance: BigInt,
105108
}
106109

110+
impl TryFrom<GenesisAccount> for edr_provider::AccountConfig {
111+
type Error = napi::Error;
112+
113+
fn try_from(value: GenesisAccount) -> Result<Self, Self::Error> {
114+
let secret_key = secret_key_from_str(&value.secret_key)
115+
.map_err(|e| napi::Error::new(Status::InvalidArg, e.to_string()))?;
116+
117+
Ok(Self {
118+
secret_key,
119+
balance: value.balance.try_cast()?,
120+
})
121+
}
122+
}
123+
107124
#[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
108125
pub fn genesis_accounts(
109126
accounts: Vec<GenesisAccount>,
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

crates/edr_evm_napi/src/lib.rs crates/edr_napi/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ mod debug_trace;
1313
mod log;
1414
mod mempool;
1515
pub mod miner;
16+
mod provider;
1617
mod receipt;
1718
pub mod runtime;
1819
mod signature;
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

crates/edr_napi/src/provider.rs

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
mod config;
2+
3+
use std::sync::Arc;
4+
5+
use napi::{tokio::runtime, Env, JsObject, Status};
6+
use napi_derive::napi;
7+
8+
use self::config::ProviderConfig;
9+
10+
/// A JSON-RPC provider for Ethereum.
11+
#[napi]
12+
pub struct Provider {
13+
provider: Arc<edr_provider::Provider>,
14+
}
15+
16+
#[napi]
17+
impl Provider {
18+
#[doc = "Constructs a new provider with the provided configuration."]
19+
#[napi(ts_return_type = "Promise<Provider>")]
20+
pub fn with_config(env: Env, config: ProviderConfig) -> napi::Result<JsObject> {
21+
let config = edr_provider::ProviderConfig::try_from(config)?;
22+
let runtime = runtime::Handle::current();
23+
24+
let (deferred, promise) = env.create_deferred()?;
25+
runtime.clone().spawn(async move {
26+
let result = edr_provider::Provider::new(&runtime, &config)
27+
.await
28+
.map_or_else(
29+
|error| Err(napi::Error::new(Status::GenericFailure, error.to_string())),
30+
|provider| {
31+
Ok(Provider {
32+
provider: Arc::new(provider),
33+
})
34+
},
35+
);
36+
37+
deferred.resolve(|_env| result);
38+
});
39+
40+
Ok(promise)
41+
}
42+
43+
#[doc = "Handles a JSON-RPC request and returns a JSON-RPC response."]
44+
#[napi]
45+
pub async fn handle_request(&self, json_request: String) -> napi::Result<String> {
46+
let request = serde_json::from_str(&json_request).map_err(|error| {
47+
napi::Error::new(
48+
Status::InvalidArg,
49+
format!("Invalid JSON `{json_request}` due to: {error}"),
50+
)
51+
})?;
52+
53+
let response = self
54+
.provider
55+
.handle_request(request)
56+
.await
57+
.map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string()))?;
58+
59+
serde_json::to_string(&response)
60+
.map_err(|e| napi::Error::new(Status::GenericFailure, e.to_string()))
61+
}
62+
}

0 commit comments

Comments
 (0)