df_hyperliquid_core/client/web/
mod.rs1pub mod socket;
25
26use crate::client::{Http, Method, Request, Response, TransportError};
27use js_sys::{Array, Function, Promise, Reflect, Uint8Array};
28use wasm_bindgen::{JsCast, JsValue};
29use wasm_bindgen_futures::JsFuture;
30use web_sys::{Headers, RequestInit};
31
32pub use socket::{Event, Feed, FeedError};
33
34#[derive(Debug, Clone, Copy, Default)]
36pub struct Web;
37
38impl Http for Web {
39 async fn send(&self, request: Request) -> Result<Response, TransportError> {
40 let global = js_sys::global();
41 let fetch: Function =
42 Reflect::get(&global, &JsValue::from_str("fetch")).map_err(unreachable)?.dyn_into().map_err(unreachable)?;
43 let headers = Headers::new().map_err(unreachable)?;
44 for (name, value) in &request.headers {
45 headers.append(name, value).map_err(unreachable)?;
46 }
47 let init = RequestInit::new();
48 init.set_method(match request.method {
49 Method::Get => "GET",
50 Method::Post => "POST",
51 });
52 init.set_headers(&headers);
53 if !request.body.is_empty() {
54 init.set_body(&Uint8Array::from(request.body.as_slice()));
55 }
56 let promise: Promise = fetch
57 .call2(&global, &JsValue::from_str(&request.url), &init)
58 .map_err(unreachable)?
59 .dyn_into()
60 .map_err(unreachable)?;
61 let answer: web_sys::Response =
62 JsFuture::from(promise).await.map_err(unreachable)?.dyn_into().map_err(unreachable)?;
63 let status = answer.status();
64 let headers = headers_of(&answer.headers());
65 let buffer = JsFuture::from(answer.array_buffer().map_err(unreachable)?).await.map_err(unreachable)?;
66 Ok(Response { status, headers, body: Uint8Array::new(&buffer).to_vec() })
67 }
68}
69
70fn headers_of(headers: &Headers) -> Vec<(String, String)> {
72 let Ok(Some(entries)) = js_sys::try_iter(headers) else { return Vec::new() };
73 entries
74 .filter_map(Result::ok)
75 .filter_map(|entry| {
76 let pair: Array = entry.dyn_into().ok()?;
77 Some((pair.get(0).as_string()?, pair.get(1).as_string()?))
78 })
79 .collect()
80}
81
82fn unreachable(error: JsValue) -> TransportError {
85 let message = Reflect::get(&error, &JsValue::from_str("message")).ok().and_then(|message| message.as_string());
86 TransportError::Unreachable(message.unwrap_or_else(|| "the request did not complete".to_owned()))
87}
88
89#[must_use]
92pub fn clock() -> u64 {
93 js_sys::Date::now() as u64
95}
96
97#[cfg(test)]
98#[cfg(target_arch = "wasm32")]
99#[path = "tests/fetch.rs"]
100mod tests;