use std::{fmt::Formatter, time::Duration};
mod graphql;
pub mod types {
pub use super::graphql::{
ChannelStatus, DateTime, Hex32, TokenValueString, Uint64,
accounts::Account,
balances::{HoprBalance, NativeBalance, RedeemedStats, SafeHoprAllowance},
channels::{Channel, ChannelStats, ChannelsList, SafesBalance},
graph::OpenedChannelsGraphEntry,
info::{ChainInfo, Compatibility, ContractAddressMap, TicketParameters},
safe::{ModuleAddress, Safe},
txs::{SafeExecution, Transaction, TransactionStatus},
};
}
pub(crate) mod internal {
pub use super::graphql::{
accounts::{
AccountVariables, QueryAccountCount, QueryAccounts, QueryTxCount, SubscribeAccounts, TxCountVariables,
},
balances::{
BalanceVariables, QueryHoprBalance, QueryNativeBalance, QueryRedeemedStats, QuerySafeAllowance,
RedeemedStatsFilter, RedeemedStatsVariables,
},
channels::{
ChannelStatsVariables, ChannelsVariables, QueryChannelCount, QueryChannelStats, QueryChannels,
QuerySafesBalance, SafesBalanceVariables, SubscribeChannels,
},
graph::SubscribeGraph,
info::{QueryChainInfo, QueryCompatibility, QueryHealth, QueryVersion, SubscribeTicketParams},
safe::{
ModuleAddressVariables, QueryModuleAddress, QuerySafeBy, SafeByVariables, SafeSelectorInput,
SubscribeSafeDeployment,
},
txs::{
ConfirmTransactionVariables, MutateConfirmTransaction, MutateSendTransaction, MutateTrackTransaction,
QueryTransaction, SendTransactionVariables, SubscribeTransaction, TransactionsVariables,
},
};
}
pub type ChainAddress = [u8; 20];
pub type PacketKey = [u8; 32];
pub type ChannelId = [u8; 32];
pub type TxReceipt = [u8; 32];
pub type KeyId = u32;
pub type TxId = String;
#[derive(Clone)]
pub enum AccountSelector {
KeyId(KeyId),
Address(ChainAddress),
PacketKey(PacketKey),
Any,
}
impl std::fmt::Debug for AccountSelector {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::KeyId(key_id) => write!(f, "KeyId({})", key_id),
Self::Address(address) => write!(f, "Address({})", hex::encode(address)),
Self::PacketKey(packet_key) => write!(f, "PacketKey({})", hex::encode(packet_key)),
AccountSelector::Any => write!(f, "Any"),
}
}
}
#[derive(Debug, Clone, Default)]
pub struct ChannelSelector {
pub filter: Option<ChannelFilter>,
pub status: Option<types::ChannelStatus>,
pub safe_address: Option<ChainAddress>,
}
impl ChannelSelector {
pub fn matches_all(&self) -> bool {
self.filter.is_none() && self.status.is_none() && self.safe_address.is_none()
}
}
#[derive(Clone)]
pub enum ChannelFilter {
ChannelId(ChannelId),
DestinationKeyId(KeyId),
SourceKeyId(KeyId),
SourceAndDestinationKeyIds(KeyId, KeyId),
}
impl std::fmt::Debug for ChannelFilter {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::ChannelId(channel_id) => write!(f, "ChannelId({})", hex::encode(channel_id)),
Self::DestinationKeyId(key_id) => write!(f, "DestinationKeyId({})", key_id),
Self::SourceKeyId(key_id) => write!(f, "SourceKeyId({})", key_id),
Self::SourceAndDestinationKeyIds(source_key_id, destination_key_id) => write!(
f,
"SourceAndDestinationKeyIds({}, {})",
source_key_id, destination_key_id
),
}
}
}
#[derive(Clone)]
pub enum SafeSelector {
SafeAddress(ChainAddress),
Owner(ChainAddress),
ChainKey(ChainAddress),
RegisteredNode(ChainAddress),
}
impl std::fmt::Debug for SafeSelector {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::SafeAddress(address) => write!(f, "SafeAddress({})", hex::encode(address)),
Self::Owner(address) => write!(f, "Owner({})", hex::encode(address)),
Self::ChainKey(address) => write!(f, "ChainKey({})", hex::encode(address)),
Self::RegisteredNode(address) => write!(f, "RegisteredNode({})", hex::encode(address)),
}
}
}
#[derive(Clone, Copy)]
pub enum RedeemedStatsSelector {
SafeAddress(ChainAddress),
NodeAddress(ChainAddress),
SafeAndNodeAddress {
safe_address: ChainAddress,
node_address: ChainAddress,
},
}
impl std::fmt::Debug for RedeemedStatsSelector {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::SafeAddress(safe) => write!(f, "SafeAddress({})", hex::encode(safe)),
Self::NodeAddress(node) => write!(f, "NodeAddress({})", hex::encode(node)),
Self::SafeAndNodeAddress {
safe_address,
node_address,
} => write!(
f,
"SafeAndNodeAddress(safe={}, node={})",
hex::encode(safe_address),
hex::encode(node_address)
),
}
}
}
#[derive(Clone, PartialEq, Eq)]
pub struct ModulePredictionInput {
pub nonce: u64,
pub owner: ChainAddress,
pub safe_address: ChainAddress,
}
impl std::fmt::Debug for ModulePredictionInput {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ModulePredictionInput")
.field("nonce", &self.nonce)
.field("owner", &hex::encode(self.owner))
.field("safe_address", &hex::encode(self.safe_address))
.finish()
}
}
pub(crate) type Result<T> = std::result::Result<T, crate::errors::BlokliClientError>;
#[async_trait::async_trait]
pub trait BlokliQueryClient {
async fn count_accounts(&self, selector: AccountSelector) -> Result<u32>;
async fn query_accounts(&self, selector: AccountSelector) -> Result<Vec<types::Account>>;
async fn query_native_balance(&self, address: &ChainAddress) -> Result<types::NativeBalance>;
async fn query_token_balance(&self, address: &ChainAddress) -> Result<types::HoprBalance>;
async fn query_transaction_count(&self, address: &ChainAddress) -> Result<u64>;
async fn query_safe_allowance(&self, address: &ChainAddress) -> Result<types::SafeHoprAllowance>;
async fn query_redeemed_stats(&self, selector: RedeemedStatsSelector) -> Result<types::RedeemedStats>;
async fn query_safe(&self, selector: SafeSelector) -> Result<Vec<types::Safe>>;
async fn query_module_address_prediction(&self, input: ModulePredictionInput) -> Result<ChainAddress>;
#[deprecated(
since = "0.22.0",
note = "Use query_channel_stats instead, which returns both count and total wxHOPR balance."
)]
async fn count_channels(&self, selector: ChannelSelector) -> Result<u32>;
async fn query_channel_stats(&self, selector: ChannelSelector) -> Result<types::ChannelStats>;
async fn query_channels(&self, selector: ChannelSelector) -> Result<types::ChannelsList>;
async fn query_safes_balance(&self, owner_address: Option<ChainAddress>) -> Result<types::SafesBalance>;
async fn query_transaction_status(&self, tx_id: TxId) -> Result<types::Transaction>;
async fn query_chain_info(&self) -> Result<types::ChainInfo>;
async fn query_version(&self) -> Result<String>;
async fn query_compatibility(&self) -> Result<types::Compatibility>;
async fn query_health(&self) -> Result<String>;
}
pub trait BlokliSubscriptionClient {
fn subscribe_channels(
&self,
selector: ChannelSelector,
) -> Result<impl futures::Stream<Item = Result<types::Channel>> + Send>;
fn subscribe_accounts(
&self,
selector: AccountSelector,
) -> Result<impl futures::Stream<Item = Result<types::Account>> + Send>;
fn subscribe_graph(&self) -> Result<impl futures::Stream<Item = Result<types::OpenedChannelsGraphEntry>> + Send>;
fn subscribe_ticket_params(&self) -> Result<impl futures::Stream<Item = Result<types::TicketParameters>> + Send>;
fn subscribe_safe_deployments(&self) -> Result<impl futures::Stream<Item = Result<types::Safe>> + Send>;
fn subscribe_track_transaction(
&self,
tx_id: TxId,
) -> Result<impl futures::Stream<Item = Result<types::Transaction>> + Send>;
}
#[async_trait::async_trait]
pub trait BlokliTransactionClient {
async fn submit_transaction(&self, signed_tx: &[u8]) -> Result<TxReceipt>;
async fn submit_and_track_transaction(&self, signed_tx: &[u8]) -> Result<TxId>;
async fn submit_and_confirm_transaction(&self, signed_tx: &[u8], num_confirmations: usize) -> Result<TxReceipt>;
async fn track_transaction(&self, tx_id: TxId, client_timeout: Duration) -> Result<types::Transaction>;
}