Skip to content

Commit d78309d

Browse files
fix(common): ipc provider windows (foundry-rs#5831)
* fix(common): ipc provider windows * temp: run windows action * Revert "temp: run windows action" This reverts commit a4f39a0.
1 parent 74c0318 commit d78309d

File tree

2 files changed

+65
-28
lines changed

2 files changed

+65
-28
lines changed

crates/common/src/provider.rs

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ use ethers_middleware::gas_oracle::{GasCategory, GasOracle, Polygon};
66
use ethers_providers::{is_local_endpoint, Middleware, Provider, DEFAULT_LOCAL_POLL_INTERVAL};
77
use eyre::WrapErr;
88
use reqwest::{IntoUrl, Url};
9-
use std::{borrow::Cow, env, path::Path, time::Duration};
9+
use std::{
10+
borrow::Cow,
11+
env,
12+
path::{Path, PathBuf},
13+
time::Duration,
14+
};
1015
use url::ParseError;
1116

1217
/// Helper type alias for a retry provider
@@ -68,31 +73,23 @@ impl ProviderBuilder {
6873
}
6974

7075
let url = Url::parse(url_str)
71-
.or_else(|err| {
72-
match err {
73-
ParseError::RelativeUrlWithoutBase => {
74-
let path = Path::new(url_str);
75-
let absolute_path = if path.is_absolute() {
76-
path.to_path_buf()
77-
} else {
78-
// Assume the path is relative to the current directory.
79-
// Don't use `std::fs::canonicalize` as it requires the path to exist.
80-
// It should be possible to construct a provider and only
81-
// attempt to establish a connection later
82-
let current_dir =
83-
env::current_dir().expect("Current directory should exist");
84-
current_dir.join(path)
85-
};
86-
87-
let path_str =
88-
absolute_path.to_str().expect("Path should be a valid string");
89-
90-
// invalid url: non-prefixed URL scheme is not allowed, so we assume the URL
91-
// is for a local file
92-
Url::parse(format!("file://{path_str}").as_str())
76+
.or_else(|err| match err {
77+
ParseError::RelativeUrlWithoutBase => {
78+
let path = Path::new(url_str);
79+
80+
if let Ok(path) = resolve_path(path) {
81+
Url::parse(
82+
format!(
83+
"file://{path_str}",
84+
path_str = path.to_str().expect("Should be valid string")
85+
)
86+
.as_str(),
87+
)
88+
} else {
89+
Err(err)
9390
}
94-
_ => Err(err),
9591
}
92+
_ => Err(err),
9693
})
9794
.wrap_err(format!("Invalid provider url: {url_str}"));
9895

@@ -280,6 +277,28 @@ where
280277
provider.estimate_eip1559_fees(None).await.wrap_err("Failed fetch EIP1559 fees")
281278
}
282279

280+
#[cfg(not(windows))]
281+
fn resolve_path(path: &Path) -> Result<PathBuf, ()> {
282+
if path.is_absolute() {
283+
Ok(path.to_path_buf())
284+
} else {
285+
Ok(env::current_dir()
286+
.map(|current_dir| current_dir.join(path))
287+
.expect("Current directory should exist"))
288+
}
289+
}
290+
291+
#[cfg(windows)]
292+
fn resolve_path(path: &Path) -> Result<PathBuf, ()> {
293+
let path_str = path.to_str().expect("Path should be a valid string");
294+
295+
if path_str.starts_with(r"\\.\pipe\") {
296+
Ok(PathBuf::from(path_str))
297+
} else {
298+
Err(())
299+
}
300+
}
301+
283302
#[cfg(test)]
284303
mod tests {
285304
use super::*;

crates/common/src/runtime_client.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use ethers_providers::{
99
};
1010
use reqwest::{header::HeaderValue, Url};
1111
use serde::{de::DeserializeOwned, Serialize};
12-
use std::{fmt::Debug, sync::Arc, time::Duration};
12+
use std::{fmt::Debug, path::PathBuf, sync::Arc, time::Duration};
1313
use thiserror::Error;
1414
use tokio::sync::RwLock;
1515

@@ -176,9 +176,7 @@ impl RuntimeClient {
176176
Ok(InnerClient::Ws(client))
177177
}
178178
"file" => {
179-
let path = self
180-
.url
181-
.to_file_path()
179+
let path = url_to_file_path(&self.url)
182180
.map_err(|_| RuntimeClientError::BadPath(self.url.to_string()))?;
183181

184182
let client = Ipc::connect(path)
@@ -192,6 +190,26 @@ impl RuntimeClient {
192190
}
193191
}
194192

193+
#[cfg(windows)]
194+
fn url_to_file_path(url: &Url) -> Result<PathBuf, ()> {
195+
const PREFIX: &str = "file:///pipe/";
196+
197+
let url_str = url.as_str();
198+
199+
if url_str.starts_with(PREFIX) {
200+
let pipe_name = &url_str[PREFIX.len()..];
201+
let pipe_path = format!(r"\\.\pipe\{}", pipe_name);
202+
return Ok(PathBuf::from(pipe_path))
203+
}
204+
205+
url.to_file_path()
206+
}
207+
208+
#[cfg(not(windows))]
209+
fn url_to_file_path(url: &Url) -> Result<PathBuf, ()> {
210+
url.to_file_path()
211+
}
212+
195213
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
196214
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
197215
impl JsonRpcClient for RuntimeClient {

0 commit comments

Comments
 (0)