use crate::error::Error;
use crate::objects::channel_fees::ChannelFees;
use crate::objects::channel_status::ChannelStatus;
use crate::objects::channel_to_transactions_connection::ChannelToTransactionsConnection;
use crate::objects::currency_amount::CurrencyAmount;
use crate::objects::entity::Entity;
use crate::objects::transaction_type::TransactionType;
use crate::types::custom_date_formats::custom_date_format;
use crate::types::entity_wrapper::EntityWrapper;
use crate::types::get_entity::GetEntity;
use crate::types::graphql_requester::GraphQLRequester;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use std::vec::Vec;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Channel {
#[serde(rename = "channel_id")]
pub id: String,
#[serde(with = "custom_date_format", rename = "channel_created_at")]
pub created_at: DateTime<Utc>,
#[serde(with = "custom_date_format", rename = "channel_updated_at")]
pub updated_at: DateTime<Utc>,
#[serde(rename = "channel_funding_transaction")]
pub funding_transaction: Option<EntityWrapper>,
#[serde(rename = "channel_capacity")]
pub capacity: Option<CurrencyAmount>,
#[serde(rename = "channel_local_balance")]
pub local_balance: Option<CurrencyAmount>,
#[serde(rename = "channel_local_unsettled_balance")]
pub local_unsettled_balance: Option<CurrencyAmount>,
#[serde(rename = "channel_remote_balance")]
pub remote_balance: Option<CurrencyAmount>,
#[serde(rename = "channel_remote_unsettled_balance")]
pub remote_unsettled_balance: Option<CurrencyAmount>,
#[serde(rename = "channel_unsettled_balance")]
pub unsettled_balance: Option<CurrencyAmount>,
#[serde(rename = "channel_total_balance")]
pub total_balance: Option<CurrencyAmount>,
#[serde(rename = "channel_status")]
pub status: Option<ChannelStatus>,
#[serde(rename = "channel_estimated_force_closure_wait_minutes")]
pub estimated_force_closure_wait_minutes: Option<i64>,
#[serde(rename = "channel_commit_fee")]
pub commit_fee: Option<CurrencyAmount>,
#[serde(rename = "channel_fees")]
pub fees: Option<ChannelFees>,
#[serde(rename = "channel_remote_node")]
pub remote_node: Option<EntityWrapper>,
#[serde(rename = "channel_local_node")]
pub local_node: EntityWrapper,
#[serde(rename = "channel_short_channel_id")]
pub short_channel_id: Option<String>,
#[serde(rename = "__typename")]
pub typename: String,
}
impl Entity for Channel {
fn get_id(&self) -> String {
self.id.clone()
}
fn get_created_at(&self) -> DateTime<Utc> {
self.created_at
}
fn get_updated_at(&self) -> DateTime<Utc> {
self.updated_at
}
fn type_name(&self) -> &'static str {
"Channel"
}
}
impl GetEntity for Channel {
fn get_entity_query() -> String {
format!(
"
query GetEntity($id: ID!) {{
entity(id: $id) {{
... on Channel {{
... ChannelFragment
}}
}}
}}
{}",
FRAGMENT
)
}
}
pub const FRAGMENT: &str = "
fragment ChannelFragment on Channel {
__typename
channel_id: id
channel_created_at: created_at
channel_updated_at: updated_at
channel_funding_transaction: funding_transaction {
id
}
channel_capacity: capacity {
__typename
currency_amount_original_value: original_value
currency_amount_original_unit: original_unit
currency_amount_preferred_currency_unit: preferred_currency_unit
currency_amount_preferred_currency_value_rounded: preferred_currency_value_rounded
currency_amount_preferred_currency_value_approx: preferred_currency_value_approx
}
channel_local_balance: local_balance {
__typename
currency_amount_original_value: original_value
currency_amount_original_unit: original_unit
currency_amount_preferred_currency_unit: preferred_currency_unit
currency_amount_preferred_currency_value_rounded: preferred_currency_value_rounded
currency_amount_preferred_currency_value_approx: preferred_currency_value_approx
}
channel_local_unsettled_balance: local_unsettled_balance {
__typename
currency_amount_original_value: original_value
currency_amount_original_unit: original_unit
currency_amount_preferred_currency_unit: preferred_currency_unit
currency_amount_preferred_currency_value_rounded: preferred_currency_value_rounded
currency_amount_preferred_currency_value_approx: preferred_currency_value_approx
}
channel_remote_balance: remote_balance {
__typename
currency_amount_original_value: original_value
currency_amount_original_unit: original_unit
currency_amount_preferred_currency_unit: preferred_currency_unit
currency_amount_preferred_currency_value_rounded: preferred_currency_value_rounded
currency_amount_preferred_currency_value_approx: preferred_currency_value_approx
}
channel_remote_unsettled_balance: remote_unsettled_balance {
__typename
currency_amount_original_value: original_value
currency_amount_original_unit: original_unit
currency_amount_preferred_currency_unit: preferred_currency_unit
currency_amount_preferred_currency_value_rounded: preferred_currency_value_rounded
currency_amount_preferred_currency_value_approx: preferred_currency_value_approx
}
channel_unsettled_balance: unsettled_balance {
__typename
currency_amount_original_value: original_value
currency_amount_original_unit: original_unit
currency_amount_preferred_currency_unit: preferred_currency_unit
currency_amount_preferred_currency_value_rounded: preferred_currency_value_rounded
currency_amount_preferred_currency_value_approx: preferred_currency_value_approx
}
channel_total_balance: total_balance {
__typename
currency_amount_original_value: original_value
currency_amount_original_unit: original_unit
currency_amount_preferred_currency_unit: preferred_currency_unit
currency_amount_preferred_currency_value_rounded: preferred_currency_value_rounded
currency_amount_preferred_currency_value_approx: preferred_currency_value_approx
}
channel_status: status
channel_estimated_force_closure_wait_minutes: estimated_force_closure_wait_minutes
channel_commit_fee: commit_fee {
__typename
currency_amount_original_value: original_value
currency_amount_original_unit: original_unit
currency_amount_preferred_currency_unit: preferred_currency_unit
currency_amount_preferred_currency_value_rounded: preferred_currency_value_rounded
currency_amount_preferred_currency_value_approx: preferred_currency_value_approx
}
channel_fees: fees {
__typename
channel_fees_base_fee: base_fee {
__typename
currency_amount_original_value: original_value
currency_amount_original_unit: original_unit
currency_amount_preferred_currency_unit: preferred_currency_unit
currency_amount_preferred_currency_value_rounded: preferred_currency_value_rounded
currency_amount_preferred_currency_value_approx: preferred_currency_value_approx
}
channel_fees_fee_rate_per_mil: fee_rate_per_mil
}
channel_remote_node: remote_node {
id
}
channel_local_node: local_node {
id
}
channel_short_channel_id: short_channel_id
}
";
impl Channel {
pub async fn get_uptime_percentage(
&self,
requester: &impl GraphQLRequester,
after_date: Option<DateTime<Utc>>,
before_date: Option<DateTime<Utc>>,
) -> Result<Option<i64>, Error> {
let query = "query FetchChannelUptimePercentage($entity_id: ID!, $after_date: DateTime, $before_date: DateTime) {
entity(id: $entity_id) {
... on Channel {
uptime_percentage(, after_date: $after_date, before_date: $before_date)
}
}
}";
let mut variables: HashMap<&str, Value> = HashMap::new();
variables.insert("entity_id", self.id.clone().into());
variables.insert("after_date", after_date.map(|dt| dt.to_rfc3339()).into());
variables.insert("before_date", before_date.map(|dt| dt.to_rfc3339()).into());
let value = serde_json::to_value(variables).map_err(Error::ConversionError)?;
let result = requester.execute_graphql(query, Some(value)).await?;
let json = result["entity"]["uptime_percentage"].clone();
let result = json.as_i64();
Ok(result)
}
pub async fn get_transactions(
&self,
requester: &impl GraphQLRequester,
types: Option<Vec<TransactionType>>,
after_date: Option<DateTime<Utc>>,
before_date: Option<DateTime<Utc>>,
) -> Result<ChannelToTransactionsConnection, Error> {
let query = "query FetchChannelToTransactionsConnection($entity_id: ID!, $types: [TransactionType!], $after_date: DateTime, $before_date: DateTime) {
entity(id: $entity_id) {
... on Channel {
transactions(, types: $types, after_date: $after_date, before_date: $before_date) {
__typename
channel_to_transactions_connection_count: count
channel_to_transactions_connection_average_fee: average_fee {
__typename
currency_amount_original_value: original_value
currency_amount_original_unit: original_unit
currency_amount_preferred_currency_unit: preferred_currency_unit
currency_amount_preferred_currency_value_rounded: preferred_currency_value_rounded
currency_amount_preferred_currency_value_approx: preferred_currency_value_approx
}
channel_to_transactions_connection_total_amount_transacted: total_amount_transacted {
__typename
currency_amount_original_value: original_value
currency_amount_original_unit: original_unit
currency_amount_preferred_currency_unit: preferred_currency_unit
currency_amount_preferred_currency_value_rounded: preferred_currency_value_rounded
currency_amount_preferred_currency_value_approx: preferred_currency_value_approx
}
channel_to_transactions_connection_total_fees: total_fees {
__typename
currency_amount_original_value: original_value
currency_amount_original_unit: original_unit
currency_amount_preferred_currency_unit: preferred_currency_unit
currency_amount_preferred_currency_value_rounded: preferred_currency_value_rounded
currency_amount_preferred_currency_value_approx: preferred_currency_value_approx
}
}
}
}
}";
let mut variables: HashMap<&str, Value> = HashMap::new();
variables.insert("entity_id", self.id.clone().into());
variables.insert("types", types.into());
variables.insert("after_date", after_date.map(|dt| dt.to_rfc3339()).into());
variables.insert("before_date", before_date.map(|dt| dt.to_rfc3339()).into());
let value = serde_json::to_value(variables).map_err(Error::ConversionError)?;
let result = requester.execute_graphql(query, Some(value)).await?;
let json = result["entity"]["transactions"].clone();
let result = serde_json::from_value(json).map_err(Error::JsonError)?;
Ok(result)
}
}