Skip to content

Commit

Permalink
feat: Add remaining node types for wasm
Browse files Browse the repository at this point in the history
  • Loading branch information
fl0rek committed Dec 12, 2024
1 parent 7705ece commit 143630b
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 140 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ prost-types = "0.13.3"
#libp2p = { path = "../../rust-libp2p/libp2p" }
#libp2p-core = { path = "../../rust-libp2p/core" }
#libp2p-swarm = { path = "../../rust-libp2p/swarm" }
#wasm-bindgen = { path = "../wasm-bindgen" }

# Uncomment this if you need debug symbols in release.
# Also check node-wasm's `Cargo.toml`.
Expand Down
6 changes: 3 additions & 3 deletions node-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ crate-type = ["cdylib", "rlib"]

[target.'cfg(target_arch = "wasm32")'.dependencies]
blockstore.workspace = true
celestia-types.workspace = true
celestia-types = { workspace = true, features = ["wasm-bindgen"] }
libp2p = { workspace = true, features = ["serde"] }
lumina-node.workspace = true
lumina-node = { workspace = true, features = ["wasm-bindgen"] }
tendermint.workspace = true

anyhow = "1.0.86"
Expand All @@ -46,7 +46,7 @@ tokio = { version = "1.38.0", features = ["sync"] }
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["time"] }
tracing-web = "0.1.3"
wasm-bindgen = "0.2.93"
wasm-bindgen = "0.2.99"
wasm-bindgen-futures = "0.4.43"
web-sys = { version = "0.3.70", features = [
"BroadcastChannel",
Expand Down
51 changes: 19 additions & 32 deletions node-wasm/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ use std::time::Duration;

use js_sys::Array;
use serde::{Deserialize, Serialize};
use serde_wasm_bindgen::to_value;
use tracing::{debug, error};
use wasm_bindgen::prelude::*;
use web_sys::BroadcastChannel;

use celestia_types::ExtendedHeader;
use lumina_node::blockstore::IndexedDbBlockstore;
use lumina_node::network;
use lumina_node::node::NodeBuilder;
use lumina_node::store::IndexedDbStore;
use lumina_node::store::{IndexedDbStore, SamplingMetadata};

use crate::commands::{CheckableResponseExt, NodeCommand, SingleHeaderQuery};
use crate::error::{Context, Result};
Expand Down Expand Up @@ -200,7 +200,7 @@ impl NodeClient {
/// Returns a javascript object with given structure:
/// https://docs.rs/celestia-types/latest/celestia_types/struct.ExtendedHeader.html
#[wasm_bindgen(js_name = requestHeadHeader)]
pub async fn request_head_header(&self) -> Result<JsValue> {
pub async fn request_head_header(&self) -> Result<ExtendedHeader> {
let command = NodeCommand::RequestHeader(SingleHeaderQuery::Head);
let response = self.worker.exec(command).await?;
let header = response.into_header().check_variant()?;
Expand All @@ -213,7 +213,7 @@ impl NodeClient {
/// Returns a javascript object with given structure:
/// https://docs.rs/celestia-types/latest/celestia_types/struct.ExtendedHeader.html
#[wasm_bindgen(js_name = requestHeaderByHash)]
pub async fn request_header_by_hash(&self, hash: &str) -> Result<JsValue> {
pub async fn request_header_by_hash(&self, hash: &str) -> Result<ExtendedHeader> {
let command = NodeCommand::RequestHeader(SingleHeaderQuery::ByHash(hash.parse()?));
let response = self.worker.exec(command).await?;
let header = response.into_header().check_variant()?;
Expand All @@ -226,7 +226,7 @@ impl NodeClient {
/// Returns a javascript object with given structure:
/// https://docs.rs/celestia-types/latest/celestia_types/struct.ExtendedHeader.html
#[wasm_bindgen(js_name = requestHeaderByHeight)]
pub async fn request_header_by_height(&self, height: u64) -> Result<JsValue> {
pub async fn request_header_by_height(&self, height: u64) -> Result<ExtendedHeader> {
let command = NodeCommand::RequestHeader(SingleHeaderQuery::ByHeight(height));
let response = self.worker.exec(command).await?;
let header = response.into_header().check_variant()?;
Expand All @@ -243,17 +243,12 @@ impl NodeClient {
#[wasm_bindgen(js_name = requestVerifiedHeaders)]
pub async fn request_verified_headers(
&self,
from_header: JsValue,
from: ExtendedHeader,
amount: u64,
) -> Result<Array> {
let command = NodeCommand::GetVerifiedHeaders {
from: from_header,
amount,
};
) -> Result<Vec<ExtendedHeader>> {
let command = NodeCommand::GetVerifiedHeaders { from, amount };
let response = self.worker.exec(command).await?;
let headers = response.into_headers().check_variant()?;

headers.into()
response.into_headers().check_variant()?
}

/// Get current header syncing info.
Expand All @@ -271,20 +266,18 @@ impl NodeClient {
/// Returns a javascript object with given structure:
/// https://docs.rs/celestia-types/latest/celestia_types/struct.ExtendedHeader.html
#[wasm_bindgen(js_name = getNetworkHeadHeader)]
pub async fn get_network_head_header(&self) -> Result<JsValue> {
pub async fn get_network_head_header(&self) -> Result<Option<ExtendedHeader>> {
let command = NodeCommand::LastSeenNetworkHead;
let response = self.worker.exec(command).await?;
let header = response.into_last_seen_network_head().check_variant()?;

header.into()
response.into_last_seen_network_head().check_variant()?
}

/// Get the latest locally synced header.
///
/// Returns a javascript object with given structure:
/// https://docs.rs/celestia-types/latest/celestia_types/struct.ExtendedHeader.html
#[wasm_bindgen(js_name = getLocalHeadHeader)]
pub async fn get_local_head_header(&self) -> Result<JsValue> {
pub async fn get_local_head_header(&self) -> Result<ExtendedHeader> {
let command = NodeCommand::GetHeader(SingleHeaderQuery::Head);
let response = self.worker.exec(command).await?;
let header = response.into_header().check_variant()?;
Expand All @@ -297,7 +290,7 @@ impl NodeClient {
/// Returns a javascript object with given structure:
/// https://docs.rs/celestia-types/latest/celestia_types/struct.ExtendedHeader.html
#[wasm_bindgen(js_name = getHeaderByHash)]
pub async fn get_header_by_hash(&self, hash: &str) -> Result<JsValue> {
pub async fn get_header_by_hash(&self, hash: &str) -> Result<ExtendedHeader> {
let command = NodeCommand::GetHeader(SingleHeaderQuery::ByHash(hash.parse()?));
let response = self.worker.exec(command).await?;
let header = response.into_header().check_variant()?;
Expand All @@ -310,7 +303,7 @@ impl NodeClient {
/// Returns a javascript object with given structure:
/// https://docs.rs/celestia-types/latest/celestia_types/struct.ExtendedHeader.html
#[wasm_bindgen(js_name = getHeaderByHeight)]
pub async fn get_header_by_height(&self, height: u64) -> Result<JsValue> {
pub async fn get_header_by_height(&self, height: u64) -> Result<ExtendedHeader> {
let command = NodeCommand::GetHeader(SingleHeaderQuery::ByHeight(height));
let response = self.worker.exec(command).await?;
let header = response.into_header().check_variant()?;
Expand All @@ -335,28 +328,24 @@ impl NodeClient {
&self,
start_height: Option<u64>,
end_height: Option<u64>,
) -> Result<Array> {
) -> Result<Vec<ExtendedHeader>> {
let command = NodeCommand::GetHeadersRange {
start_height,
end_height,
};
let response = self.worker.exec(command).await?;
let headers = response.into_headers().check_variant()?;

headers.into()
response.into_headers().check_variant()?
}

/// Get data sampling metadata of an already sampled height.
///
/// Returns a javascript object with given structure:
/// https://docs.rs/lumina-node/latest/lumina_node/store/struct.SamplingMetadata.html
#[wasm_bindgen(js_name = getSamplingMetadata)]
pub async fn get_sampling_metadata(&self, height: u64) -> Result<JsValue> {
pub async fn get_sampling_metadata(&self, height: u64) -> Result<Option<SamplingMetadata>> {
let command = NodeCommand::GetSamplingMetadata { height };
let response = self.worker.exec(command).await?;
let metadata = response.into_sampling_metadata().check_variant()?;

Ok(to_value(&metadata?)?)
response.into_sampling_metadata().check_variant()?
}

/// Returns a [`BroadcastChannel`] for events generated by [`Node`].
Expand Down Expand Up @@ -438,7 +427,6 @@ mod tests {
use gloo_timers::future::sleep;
use libp2p::{multiaddr::Protocol, Multiaddr};
use rexie::Rexie;
use serde_wasm_bindgen::from_value;
use wasm_bindgen_futures::spawn_local;
use wasm_bindgen_test::wasm_bindgen_test;
use web_sys::MessageChannel;
Expand All @@ -460,8 +448,7 @@ mod tests {
assert_eq!(info.num_peers, 1);

let bridge_head_header = rpc_client.header_network_head().await.unwrap();
let head_header: ExtendedHeader =
from_value(client.request_head_header().await.unwrap()).unwrap();
let head_header: ExtendedHeader = client.request_head_header().await.unwrap();
assert_eq!(head_header, bridge_head_header);
rpc_client
.p2p_close_peer(&PeerId(
Expand Down
15 changes: 6 additions & 9 deletions node-wasm/src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
use std::fmt::Debug;

use enum_as_inner::EnumAsInner;
use js_sys::Array;
use libp2p::Multiaddr;
use libp2p::PeerId;
use serde::{Deserialize, Serialize};
use tracing::error;
use wasm_bindgen::{JsError, JsValue};
use wasm_bindgen::JsError;

use celestia_types::hash::Hash;
use celestia_types::{hash::Hash, ExtendedHeader};
use lumina_node::node::{PeerTrackerInfo, SyncingInfo};
use lumina_node::store::SamplingMetadata;

use crate::client::WasmNodeConfig;
use crate::error::Error;
use crate::error::Result;
use crate::utils::JsResult;
use crate::wrapper::libp2p::NetworkInfoSnapshot;

#[derive(Debug, Serialize, Deserialize)]
Expand All @@ -40,8 +38,7 @@ pub(crate) enum NodeCommand {
GetListeners,
RequestHeader(SingleHeaderQuery),
GetVerifiedHeaders {
#[serde(with = "serde_wasm_bindgen::preserve")]
from: JsValue,
from: ExtendedHeader,
amount: u64,
},
GetHeadersRange {
Expand Down Expand Up @@ -78,9 +75,9 @@ pub(crate) enum WorkerResponse {
SetPeerTrust(Result<()>),
Connected(Result<()>),
Listeners(Result<Vec<Multiaddr>>),
Header(JsResult<JsValue, Error>),
Headers(JsResult<Array, Error>),
LastSeenNetworkHead(JsResult<JsValue, Error>),
Header(Result<ExtendedHeader, Error>),
Headers(Result<Vec<ExtendedHeader>, Error>),
LastSeenNetworkHead(Result<Option<ExtendedHeader>, Error>),
SamplingMetadata(Result<Option<SamplingMetadata>>),
}

Expand Down
49 changes: 3 additions & 46 deletions node-wasm/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ use gloo_timers::future::TimeoutFuture;
use js_sys::{Math, Promise};
use libp2p::multiaddr::Protocol;
use libp2p::{Multiaddr, PeerId};
use lumina_node::network;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use serde_repr::{Deserialize_repr, Serialize_repr};
use tracing::{info, warn};
use tracing_subscriber::filter::LevelFilter;
Expand All @@ -24,6 +22,8 @@ use web_sys::{
ServiceWorker, ServiceWorkerGlobalScope, SharedWorker, SharedWorkerGlobalScope, Worker,
};

use lumina_node::network;

use crate::error::{Context, Error, Result};

/// Supported Celestia networks.
Expand Down Expand Up @@ -110,49 +110,6 @@ impl WorkerSelf for ServiceWorker {
type GlobalScope = ServiceWorkerGlobalScope;
}

/// This type is useful in cases where we want to deal with de/serialising `Result<T, E>`, with
/// [`serde_wasm_bindgen::preserve`] where `T` is a JavaScript object (which are not serializable by
/// Rust standards, but can be passed through unchanged via cast as they implement [`JsCast`]).
///
/// [`serde_wasm_bindgen::preserve`]: https://docs.rs/serde-wasm-bindgen/latest/serde_wasm_bindgen/preserve
/// [`JsCast`]: https://docs.rs/wasm-bindgen/latest/wasm_bindgen/trait.JsCast.html
#[derive(Serialize, Deserialize, Debug)]
pub(crate) enum JsResult<T, E>
where
T: JsCast + Debug,
E: Debug,
{
#[serde(with = "serde_wasm_bindgen::preserve")]
Ok(T),
Err(E),
}

impl<T, E> From<Result<T, E>> for JsResult<T, E>
where
T: JsCast + Debug,
E: Serialize + DeserializeOwned + Debug,
{
fn from(result: Result<T, E>) -> Self {
match result {
Ok(v) => JsResult::Ok(v),
Err(e) => JsResult::Err(e),
}
}
}

impl<T, E> From<JsResult<T, E>> for Result<T, E>
where
T: JsCast + Debug,
E: Serialize + DeserializeOwned + Debug,
{
fn from(result: JsResult<T, E>) -> Self {
match result {
JsResult::Ok(v) => Ok(v),
JsResult::Err(e) => Err(e),
}
}
}

pub(crate) trait MessageEventExt {
fn get_port(&self) -> Option<JsValue>;
}
Expand Down
Loading

0 comments on commit 143630b

Please sign in to comment.