use bitcoin::{Amount, FeeRate, Txid};
use bitcoin::consensus::encode::serialize_hex;
use bitcoin::secp256k1::PublicKey;
use serde::{Deserialize, Serialize};
use ark::VtxoId;
use ark::offboard::OffboardRequest;
use ark::tree::signed::UnlockHash;
use ark::vtxo::VtxoPolicyKind;
#[cfg(feature = "utoipa")]
use utoipa::ToSchema;
use crate::cli::RoundStatus;
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct TipResponse {
pub tip_height: u32,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct CreateWalletRequest {
pub ark_server: String,
pub chain_source: ChainSourceConfig,
pub mnemonic: Option<String>,
pub network: BarkNetwork,
pub birthday_height: Option<u32>,
}
#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub enum BarkNetwork {
Mainnet,
Signet,
Mutinynet,
Regtest,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub enum ChainSourceConfig {
Bitcoind {
bitcoind: String,
bitcoind_auth: BitcoindAuth,
},
Esplora {
url: String,
},
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub enum BitcoindAuth {
Cookie {
cookie: String,
},
UserPass {
user: String,
pass: String,
},
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct CreateWalletResponse {
pub fingerprint: String,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct ConnectedResponse {
pub connected: bool,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct ArkAddressResponse {
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub address: String,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct VtxosQuery {
pub all: Option<bool>,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct RefreshRequest {
pub vtxos: Vec<String>,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct BoardRequest {
pub amount_sat: u64,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct SendRequest {
pub destination: String,
pub amount_sat: Option<u64>,
pub comment: Option<String>,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct SendResponse {
pub message: String,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct SendOnchainRequest {
pub destination: String,
pub amount_sat: u64,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct OffboardVtxosRequest {
pub address: Option<String>,
pub vtxos: Vec<String>,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct OffboardAllRequest {
pub address: Option<String>,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct ImportVtxoRequest {
pub vtxos: Vec<String>,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct LightningInvoiceRequest {
pub amount_sat: u64,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct LightningPayRequest {
pub destination: String,
pub amount_sat: Option<u64>,
pub comment: Option<String>,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct LightningPayResponse {
pub message: String,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct OnchainSendRequest {
pub destination: String,
pub amount_sat: u64,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct OnchainSendManyRequest {
pub destinations: Vec<String>,
pub immediate: Option<bool>,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct OnchainDrainRequest {
pub destination: String,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct ExitStatusRequest {
pub history: Option<bool>,
pub transactions: Option<bool>,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct ExitStartRequest {
pub vtxos: Vec<String>,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct ExitStartResponse {
pub message: String,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct ExitProgressRequest {
pub wait: Option<bool>,
pub fee_rate: Option<u64>,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct ExitClaimAllRequest {
pub destination: String,
pub fee_rate: Option<u64>,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct ExitClaimVtxosRequest {
pub destination: String,
pub vtxos: Vec<String>,
pub fee_rate: Option<u64>,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct ExitClaimResponse {
pub message: String,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct VtxoRequestInfo {
#[serde(rename = "amount_sat", with = "bitcoin::amount::serde::as_sat")]
#[cfg_attr(feature = "utoipa", schema(value_type = u64))]
pub amount: Amount,
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub policy_type: VtxoPolicyKind,
#[cfg_attr(feature = "utoipa", schema(value_type = String))]
pub user_pubkey: PublicKey,
}
impl<'a> From<&'a ark::VtxoRequest> for VtxoRequestInfo {
fn from(v: &'a ark::VtxoRequest) -> Self {
Self {
amount: v.amount,
policy_type: v.policy.policy_type(),
user_pubkey: v.policy.user_pubkey(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct OffboardRequestInfo {
pub script_pubkey_hex: String,
pub script_pubkey_asm: String,
#[serde(rename = "net_amount_sat", with = "bitcoin::amount::serde::as_sat")]
#[cfg_attr(feature = "utoipa", schema(value_type = u64))]
pub net_amount: Amount,
pub deduct_fees_from_gross_amount: bool,
#[serde(rename = "fee_rate_kwu")]
#[cfg_attr(feature = "utoipa", schema(value_type = u64))]
pub fee_rate: FeeRate,
}
impl<'a> From<&'a OffboardRequest> for OffboardRequestInfo {
fn from(v: &'a OffboardRequest) -> Self {
Self {
script_pubkey_hex: v.script_pubkey.to_hex_string(),
script_pubkey_asm: v.script_pubkey.to_asm_string(),
net_amount: v.net_amount,
deduct_fees_from_gross_amount: v.deduct_fees_from_gross_amount,
fee_rate: v.fee_rate,
}
}
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct RoundParticipationInfo {
#[cfg_attr(feature = "utoipa", schema(value_type = Vec<String>))]
pub inputs: Vec<VtxoId>,
pub outputs: Vec<VtxoRequestInfo>,
}
impl<'a> From<&'a bark::round::RoundParticipation> for RoundParticipationInfo {
fn from(v: &'a bark::round::RoundParticipation) -> Self {
Self {
inputs: v.inputs.iter().map(|v| v.id()).collect(),
outputs: v.outputs.iter().map(Into::into).collect(),
}
}
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct PendingRoundInfo {
pub id: u32,
pub status: RoundStatus,
pub participation: RoundParticipationInfo,
#[cfg_attr(feature = "utoipa", schema(value_type = String, nullable = true))]
pub unlock_hash: Option<UnlockHash>,
#[cfg_attr(feature = "utoipa", schema(value_type = String, nullable = true))]
pub funding_txid: Option<Txid>,
pub funding_tx_hex: Option<String>,
}
impl PendingRoundInfo {
pub fn new<'a>(
state: &'a bark::persist::models::StoredRoundState,
sync_result: anyhow::Result<bark::round::RoundStatus>,
) -> Self {
let funding_tx = state.state().funding_tx();
Self {
id: state.id().0,
status: match sync_result {
Ok(status) => status.into(),
Err(e) => RoundStatus::SyncError {
error: format!("{:#}", e),
},
},
participation: state.state().participation().into(),
unlock_hash: state.state().unlock_hash(),
funding_txid: funding_tx.map(|t| t.compute_txid()),
funding_tx_hex: funding_tx.map(|t| serialize_hex(t)),
}
}
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct WalletExistsResponse {
pub fingerprint: Option<String>,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct WalletDeleteRequest {
pub dangerous: bool,
pub fingerprint: String,
}
#[derive(Serialize, Deserialize)]
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
pub struct WalletDeleteResponse {
pub deleted: bool,
pub message: String,
}