use crate::generated;
use crate::Error;
use ark_core::server;
use ark_core::server::parse_sequence_number;
use ark_core::server::DeprecatedSigner;
use ark_core::server::FeeInfo;
use ark_core::server::IntentFeeInfo;
use ark_core::server::ScheduledSession;
use bitcoin::address::NetworkUnchecked;
use bitcoin::hex::FromHex;
use bitcoin::Address;
use bitcoin::Amount;
use bitcoin::OutPoint;
use bitcoin::ScriptBuf;
use std::str::FromStr;
impl TryFrom<generated::ark::v1::GetInfoResponse> for server::Info {
type Error = Error;
fn try_from(value: generated::ark::v1::GetInfoResponse) -> Result<Self, Self::Error> {
let signer_pk = value.signer_pubkey.parse().map_err(Error::conversion)?;
let forfeit_pk = value.forfeit_pubkey.parse().map_err(Error::conversion)?;
let network =
server::Network::from_str(value.network.as_str()).map_err(Error::conversion)?;
let network = bitcoin::Network::from(network);
let forfeit_address: Address<NetworkUnchecked> =
value.forfeit_address.parse().map_err(Error::conversion)?;
let forfeit_address = forfeit_address
.require_network(network)
.map_err(Error::conversion)?;
let checkpoint_tapscript = ScriptBuf::from_bytes(
Vec::from_hex(&value.checkpoint_tapscript).map_err(Error::conversion)?,
);
let session_duration = value.session_duration as u64;
let unilateral_exit_delay =
parse_sequence_number(value.unilateral_exit_delay).map_err(Error::conversion)?;
let boarding_exit_delay =
parse_sequence_number(value.boarding_exit_delay).map_err(Error::conversion)?;
let utxo_min_amount = match value.utxo_min_amount.is_positive() {
true => Some(Amount::from_sat(value.utxo_min_amount as u64)),
false => None,
};
let utxo_max_amount = match value.utxo_max_amount.is_positive() {
true => Some(Amount::from_sat(value.utxo_max_amount as u64)),
false => None,
};
let vtxo_min_amount = match value.vtxo_min_amount.is_positive() {
true => Some(Amount::from_sat(value.vtxo_min_amount as u64)),
false => None,
};
let vtxo_max_amount = match value.vtxo_max_amount.is_positive() {
true => Some(Amount::from_sat(value.vtxo_max_amount as u64)),
false => None,
};
let fees = value.fees.map(FeeInfo::from);
let scheduled_session = value.scheduled_session.map(ScheduledSession::from);
let deprecated_signers = value
.deprecated_signers
.into_iter()
.map(DeprecatedSigner::try_from)
.collect::<Result<Vec<_>, Error>>()?;
Ok(Self {
version: value.version,
signer_pk,
forfeit_pk,
forfeit_address,
checkpoint_tapscript,
network,
session_duration,
unilateral_exit_delay,
boarding_exit_delay,
utxo_min_amount,
utxo_max_amount,
vtxo_min_amount,
vtxo_max_amount,
dust: Amount::from_sat(value.dust as u64),
fees,
scheduled_session,
deprecated_signers,
service_status: value.service_status,
digest: value.digest,
max_tx_weight: value.max_tx_weight,
max_op_return_outputs: value.max_op_return_outputs,
})
}
}
impl From<generated::ark::v1::FeeInfo> for FeeInfo {
fn from(value: generated::ark::v1::FeeInfo) -> Self {
let intent_fee = value
.intent_fee
.map(|i| IntentFeeInfo {
offchain_input: Some(i.offchain_input),
offchain_output: Some(i.offchain_output),
onchain_input: Some(i.onchain_input),
onchain_output: Some(i.onchain_output),
})
.unwrap_or_default();
FeeInfo {
intent_fee,
tx_fee_rate: value.tx_fee_rate,
}
}
}
impl From<generated::ark::v1::ScheduledSession> for ScheduledSession {
fn from(value: generated::ark::v1::ScheduledSession) -> Self {
Self {
next_start_time: value.next_start_time,
next_end_time: value.next_end_time,
period: value.period,
duration: value.duration,
fees: value.fees.map(FeeInfo::from),
}
}
}
impl TryFrom<generated::ark::v1::DeprecatedSigner> for DeprecatedSigner {
type Error = Error;
fn try_from(value: generated::ark::v1::DeprecatedSigner) -> Result<Self, Self::Error> {
let pk = value.pubkey.parse().map_err(Error::conversion)?;
Ok(Self {
pk,
cutoff_date: value.cutoff_date,
})
}
}
impl TryFrom<&generated::ark::v1::IndexerVtxo> for server::VirtualTxOutPoint {
type Error = Error;
fn try_from(value: &generated::ark::v1::IndexerVtxo) -> Result<Self, Self::Error> {
let outpoint = value.outpoint.as_ref().expect("outpoint");
let outpoint = OutPoint {
txid: outpoint.txid.parse().map_err(Error::conversion)?,
vout: outpoint.vout,
};
let script = ScriptBuf::from_hex(&value.script).map_err(Error::conversion)?;
let spent_by = match value.spent_by.is_empty() {
true => None,
false => Some(value.spent_by.parse().map_err(Error::conversion)?),
};
let commitment_txids = value
.commitment_txids
.iter()
.map(|c| c.parse().map_err(Error::conversion))
.collect::<Result<Vec<_>, Error>>()?;
let settled_by = match value.settled_by.is_empty() {
true => None,
false => Some(value.settled_by.parse().map_err(Error::conversion)?),
};
let ark_txid = match value.ark_txid.is_empty() {
true => None,
false => Some(value.ark_txid.parse().map_err(Error::conversion)?),
};
let assets = value
.assets
.iter()
.map(|a| {
let asset_id = a.asset_id.parse().map_err(Error::conversion)?;
Ok(server::Asset {
asset_id,
amount: a.amount,
})
})
.collect::<Result<Vec<_>, _>>()?;
Ok(Self {
outpoint,
created_at: value.created_at,
expires_at: value.expires_at,
amount: Amount::from_sat(value.amount),
script,
is_preconfirmed: value.is_preconfirmed,
is_swept: value.is_swept,
is_unrolled: value.is_unrolled,
is_spent: value.is_spent,
spent_by,
commitment_txids,
settled_by,
ark_txid,
assets,
})
}
}
impl TryFrom<&generated::ark::v1::Vtxo> for server::VirtualTxOutPoint {
type Error = Error;
fn try_from(value: &generated::ark::v1::Vtxo) -> Result<Self, Self::Error> {
let outpoint = value.outpoint.as_ref().expect("outpoint");
let outpoint = OutPoint {
txid: outpoint.txid.parse().map_err(Error::conversion)?,
vout: outpoint.vout,
};
let script = ScriptBuf::from_hex(&value.script).map_err(Error::conversion)?;
let spent_by = match value.spent_by.is_empty() {
true => None,
false => Some(value.spent_by.parse().map_err(Error::conversion)?),
};
let commitment_txids = value
.commitment_txids
.iter()
.map(|c| c.parse().map_err(Error::conversion))
.collect::<Result<Vec<_>, Error>>()?;
let settled_by = match value.settled_by.is_empty() {
true => None,
false => Some(value.settled_by.parse().map_err(Error::conversion)?),
};
let ark_txid = match value.ark_txid.is_empty() {
true => None,
false => Some(value.ark_txid.parse().map_err(Error::conversion)?),
};
let assets = value
.assets
.iter()
.map(|a| {
let asset_id = a.asset_id.parse().map_err(Error::conversion)?;
Ok(server::Asset {
asset_id,
amount: a.amount,
})
})
.collect::<Result<Vec<_>, Error>>()?;
Ok(Self {
outpoint,
created_at: value.created_at,
expires_at: value.expires_at,
amount: Amount::from_sat(value.amount),
script,
is_preconfirmed: value.is_preconfirmed,
is_swept: value.is_swept,
is_unrolled: value.is_unrolled,
is_spent: value.is_spent,
spent_by,
commitment_txids,
settled_by,
ark_txid,
assets,
})
}
}