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 let global = js_sys::global();
49 let fetch: Function =
50 Reflect::get(&global, &JsValue::from_str("fetch")).map_err(unreachable)?.dyn_into().map_err(unreachable)?;
51 let headers = Headers::new().map_err(unreachable)?;
52 for (name, value) in &request.headers {
53 headers.append(name, value).map_err(unreachable)?;
54 }
55 let init = RequestInit::new();
56 init.set_method(match request.method {
57 Method::Get => "GET",
58 Method::Post => "POST",
59 });
60 init.set_headers(&headers);
61 if !request.body.is_empty() {
62 init.set_body(&Uint8Array::from(request.body.as_slice()));
63 }
64 let promise: Promise = fetch
65 .call2(&global, &JsValue::from_str(&request.url), &init)
66 .map_err(unreachable)?
67 .dyn_into()
68 .map_err(unreachable)?;
69 let answer: web_sys::Response =
70 JsFuture::from(promise).await.map_err(unreachable)?.dyn_into().map_err(unreachable)?;
71 let status = answer.status();
72 let headers = headers_of(&answer.headers());
73 let buffer = JsFuture::from(answer.array_buffer().map_err(unreachable)?).await.map_err(unreachable)?;
74 Ok(Response { status, headers, body: Uint8Array::new(&buffer).to_vec() })
75 }
76}
77
78fn headers_of(headers: &Headers) -> Vec<(String, String)> {
80 let Ok(Some(entries)) = js_sys::try_iter(headers) else { return Vec::new() };
81 entries
82 .filter_map(Result::ok)
83 .filter_map(|entry| {
84 let pair: Array = entry.dyn_into().ok()?;
85 Some((pair.get(0).as_string()?, pair.get(1).as_string()?))
86 })
87 .collect()
88}
89
90fn unreachable(error: JsValue) -> TransportError {
93 let message = Reflect::get(&error, &JsValue::from_str("message")).ok().and_then(|message| message.as_string());
94 TransportError::Unreachable(message.unwrap_or_else(|| "the request did not complete".to_owned()))
95}
96
97#[must_use]
100pub fn clock() -> u64 {
101 js_sys::Date::now() as u64
103}
104
105#[cfg(test)]
106#[cfg(target_arch = "wasm32")]
107#[path = "tests/fetch.rs"]
108mod tests;