use serde::{Deserialize, Deserializer};
use crate::client::http::{ApiError, Call, Transport, read};
use crate::utils::{Address, Dec};
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub struct DepositNetwork {
pub name: String,
#[serde(deserialize_with = "chain")]
pub chain_id: u64,
#[serde(default)]
pub explorer: String,
}
#[derive(Deserialize)]
struct DepositNetworks {
networks: Vec<DepositNetwork>,
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub struct LatestDeposit {
#[serde(default)]
pub source: String,
#[serde(default)]
pub source_chain_id: String,
pub amount: Dec,
#[serde(default)]
pub intent_address: String,
#[serde(default)]
pub status: String,
#[serde(default)]
pub step: String,
#[serde(default)]
pub description: String,
#[serde(default)]
pub created_at: u64,
#[serde(default)]
pub updated_at: u64,
#[serde(default)]
pub fast_bridge_tx_hash: String,
#[serde(default)]
pub batch_claim_tx_hash: String,
#[serde(default)]
pub cctp_burn_tx_hash: String,
#[serde(default)]
pub is_external_deposit: bool,
#[serde(default)]
pub is_next_bridge_fast: bool,
}
impl LatestDeposit {
#[must_use]
pub fn is_completed(&self) -> bool {
self.status == "completed"
}
}
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
pub struct IntentAddress {
pub intent_address: String,
}
#[derive(Deserialize)]
struct FastBridgeInfo {
fast_bridge_limit: Dec,
}
fn chain<'de, D: Deserializer<'de>>(deserializer: D) -> Result<u64, D::Error> {
crate::utils::ids::whole(deserializer)
}
#[must_use]
pub fn deposit_networks_call() -> Call {
Call::get("deposit/networks")
}
pub async fn deposit_networks(transport: &impl Transport) -> Result<Vec<DepositNetwork>, ApiError> {
Ok(read::<DepositNetworks>(transport, deposit_networks_call()).await?.networks)
}
#[must_use]
pub fn latest_deposit_call(l1_address: Address) -> Call {
Call::get("deposit/latest").field("l1_address", l1_address)
}
pub const NO_DEPOSIT: i64 = crate::client::http::codes::NOT_FOUND;
pub async fn latest_deposit(
transport: &impl Transport,
l1_address: Address,
) -> Result<Option<LatestDeposit>, ApiError> {
match read(transport, latest_deposit_call(l1_address)).await {
Err(error) if error.code() == Some(NO_DEPOSIT) => Ok(None),
answer => answer.map(Some),
}
}
#[must_use]
pub fn intent_address_call(chain_id: u64, from: Address, amount: Dec, external: bool) -> Call {
Call::post("createIntentAddress")
.field("chain_id", chain_id)
.field("from_addr", from)
.field("amount", amount)
.field("is_external_deposit", external)
}
pub async fn intent_address(
transport: &impl Transport,
chain_id: u64,
from: Address,
amount: Dec,
external: bool,
) -> Result<IntentAddress, ApiError> {
read(transport, intent_address_call(chain_id, from, amount, external)).await
}
#[must_use]
pub fn fast_bridge_call() -> Call {
Call::get("fastbridge/info")
}
pub async fn fast_bridge_limit(transport: &impl Transport) -> Result<Dec, ApiError> {
Ok(read::<FastBridgeInfo>(transport, fast_bridge_call()).await?.fast_bridge_limit)
}
#[cfg(test)]
#[path = "tests/bridge.rs"]
mod tests;