use gloo_utils::format::JsValueSerdeExt;
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::JsFuture;
use crate::{extensions::JsErrorContext, types::Address};
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, PartialEq, Eq)]
#[wasm_bindgen(inspectable)]
pub struct Contracts {
#[serde(alias = "time")]
last_updated: String,
contracts: Vec<ContractInfo>
}
#[wasm_bindgen]
impl Contracts {
#[wasm_bindgen(constructor)]
pub fn new(js: JsValue) -> Result<Self, JsError> {
js.into_serde::<Contracts>()
.with_js_context("Failed to parse Contracts from JSON")
}
#[wasm_bindgen(js_name = "fromPath")]
pub async fn from_path(path: &str) -> Result<Self, JsError> {
let window = web_sys::window().ok_or_else(|| JsError::new("No window object found"))?;
let resp = JsFuture::from(window.fetch_with_str(path))
.await
.map_err(|err| {
JsError::new(&format!("Failed to fetch contracts from {path}: {err:?}"))
})?
.dyn_into::<web_sys::Response>()
.with_js_context("Failed to cast to Response")?;
let promise = resp
.json()
.with_js_context("Failed to get JSON from response")?;
let json = JsFuture::from(promise)
.await
.with_js_context("Failed to resolve JSON promise")?;
let result = json
.into_serde()
.with_js_context("Failed to parse Contracts from JSON")?;
crate::js::log(&format!("Loaded contracts: {:?}", result));
Ok(result)
}
#[wasm_bindgen]
pub fn get(&self, name: &str) -> Result<ContractInfo, JsError> {
let contract = self
.contracts
.iter()
.find(|c| c.name == name)
.ok_or_else(|| JsError::new(&format!("Contract with name {:?} not found", name)))?;
Ok(contract.clone())
}
}
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone, PartialEq, Eq)]
#[wasm_bindgen(getter_with_clone, inspectable)]
pub struct ContractInfo {
pub name: String,
pub package_hash: String
}
#[wasm_bindgen]
impl ContractInfo {
#[wasm_bindgen(getter)]
pub fn address(&self) -> Result<Address, JsError> {
Address::new(&self.package_hash)
}
}