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