use js_export_macro::js_export;
use miden_client::Felt as NativeFelt;
use miden_client::pswap::PswapLineageState as NativePswapLineageState;
use crate::models::account_id::AccountId;
use crate::models::pswap_lineage_record::PswapLineageRecord;
use crate::models::transaction_request::TransactionRequest;
use crate::platform::{JsErr, from_str_err};
use crate::{WebClient, js_error_with_context};
#[js_export]
impl WebClient {
#[js_export(js_name = "getPswapLineages")]
pub async fn get_pswap_lineages(&self) -> Result<Vec<PswapLineageRecord>, JsErr> {
let mut guard = self.get_mut_inner().await;
let client = guard
.as_mut()
.ok_or_else(|| from_str_err("Client not initialized while fetching pswap lineages"))?;
let lineages = client
.pswap_lineages()
.await
.map_err(|err| js_error_with_context(err, "failed to fetch pswap lineages"))?;
Ok(lineages.into_iter().map(PswapLineageRecord::from).collect())
}
#[js_export(js_name = "getPswapLineagesFor")]
pub async fn get_pswap_lineages_for(
&self,
creator: &AccountId,
) -> Result<Vec<PswapLineageRecord>, JsErr> {
let mut guard = self.get_mut_inner().await;
let client = guard
.as_mut()
.ok_or_else(|| from_str_err("Client not initialized while fetching pswap lineages"))?;
let lineages = client.pswap_lineages_for(creator.into()).await.map_err(|err| {
js_error_with_context(err, "failed to fetch pswap lineages for account")
})?;
Ok(lineages.into_iter().map(PswapLineageRecord::from).collect())
}
#[js_export(js_name = "getPswapLineage")]
pub async fn get_pswap_lineage(
&self,
order_id: String,
) -> Result<Option<PswapLineageRecord>, JsErr> {
let order_id = parse_order_id(&order_id)?;
let mut guard = self.get_mut_inner().await;
let client = guard
.as_mut()
.ok_or_else(|| from_str_err("Client not initialized while fetching pswap lineage"))?;
client
.pswap_lineage(order_id)
.await
.map(|opt| opt.map(PswapLineageRecord::from))
.map_err(|err| js_error_with_context(err, "failed to fetch pswap lineage"))
}
#[js_export(js_name = "buildPswapCancelByOrder")]
pub async fn build_pswap_cancel_by_order(
&self,
order_id: String,
) -> Result<TransactionRequest, JsErr> {
let order_felt = parse_order_id(&order_id)?;
let mut guard = self.get_mut_inner().await;
let client = guard.as_mut().ok_or_else(|| {
from_str_err("Client not initialized while building pswap cancel transaction request")
})?;
let lineage = client
.pswap_lineage(order_felt)
.await
.map_err(|err| js_error_with_context(err, "failed to fetch pswap lineage"))?
.ok_or_else(|| {
from_str_err(&format!("No PSWAP lineage tracked for order {order_id}"))
})?;
let terminal_state = match lineage.state {
NativePswapLineageState::Active => None,
NativePswapLineageState::FullyFilled => Some("FullyFilled"),
NativePswapLineageState::Reclaimed => Some("Reclaimed"),
};
if let Some(state_name) = terminal_state {
return Err(from_str_err(&format!(
"Cannot cancel PSWAP order {order_id}: lineage is {state_name}; \
only Active lineages can be cancelled."
)));
}
client
.build_pswap_cancel_by_order(order_felt)
.await
.map(Into::into)
.map_err(|err| {
js_error_with_context(
err,
"failed to build pswap cancel-by-order transaction request",
)
})
}
}
fn parse_order_id(order_id: &str) -> Result<NativeFelt, JsErr> {
let value = order_id.parse::<u64>().map_err(|_| {
from_str_err("invalid order_id: expected a decimal integer in the u64 range")
})?;
NativeFelt::new(value).map_err(|err| {
from_str_err(&format!("invalid order_id {value}: not a valid field element ({err})"))
})
}