use std::{fmt::Formatter, time::Duration};
pub(crate) mod graphql;
pub mod types {
#[cfg(feature = "curvy")]
pub use super::graphql::curvy::{
CurvyAddress, CurvyAggregatorFees, CurvyAggregatorState, CurvyBooleanValue, CurvyCommittedNote,
CurvyCommittedNotes, CurvyCommittedNullifier, CurvyCommittedNullifiers, CurvyEventCursor, CurvyEventPosition,
CurvyGasFees, CurvyNoteStatus, CurvyPendingNote, CurvyPendingNotes, CurvyShardRoot, CurvyShardRootPage,
CurvySyncCheckpoint, CurvySyncNote, CurvySyncNotePage, CurvySyncNullifierPage, CurvyVaultFees, CurvyVaultToken,
CurvyVaultTokenCount,
};
pub use super::graphql::{
ChannelStatus, DateTime, Hex32, ReadinessState, Token, TokenValueString, Uint64, Uint256,
accounts::Account,
balances::{HoprBalance, NativeBalance, RedeemedStats, SafeHoprAllowance},
channels::{Channel, ChannelStats, ChannelsList, SafesBalance},
graph::OpenedChannelsGraphEntry,
info::{ChainInfo, Compatibility, ContractAddressMap, TicketParameters},
safe::{ModuleAddress, Safe},
services::{
ServiceEntry, ServiceRegistryConfig, ServiceTypeInfo, ServiceTypeUpdate, ServiceTypeUpdateKind,
ServiceUpdate, ServiceUpdateKind,
},
tickets::{RedeemTicketDetails, RedemptionResult},
txs::{SafeExecution, Transaction, TransactionStatus},
};
}
pub(crate) mod internal {
#[cfg(feature = "curvy")]
pub use super::graphql::curvy::{
CurvyCheckpointVariables, CurvyEntryPortalVariables, CurvyEventPageVariables, CurvyEventSubscriptionVariables,
CurvyExitPortalVariables, CurvyNoteIdVariables, CurvyNullifierVariables, CurvyPortalVariables,
CurvyRootVariables, CurvySyncPageVariables, CurvyVaultTokenVariables, QueryCurvyAggregatorFees,
QueryCurvyAggregatorState, QueryCurvyCommittedNotes, QueryCurvyCommittedNullifiers,
QueryCurvyEntryPortalAddress, QueryCurvyExitPortalAddress, QueryCurvyNoteStatus, QueryCurvyNullifierSpent,
QueryCurvyPendingNotes, QueryCurvyPortalRegistered, QueryCurvyShardRoots, QueryCurvySyncCheckpoint,
QueryCurvySyncNotes, QueryCurvySyncNullifiers, QueryCurvyValidNotesRoot, QueryCurvyVaultFees,
QueryCurvyVaultToken, QueryCurvyVaultTokenCount, SubscribeCurvyCommittedNote, SubscribeCurvyCommittedNullifier,
SubscribeCurvyPendingNote,
};
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, SubscribeHealth, SubscribeTicketParams},
safe::{
ModuleAddressVariables, QueryModuleAddress, QuerySafeBy, SafeByVariables, SafeSelectorInput,
SubscribeSafeDeployment,
},
services::{
QueryServiceCount, QueryServiceRegistryConfig, QueryServiceTypes, QueryServices, ServicePageVariables,
ServiceTypeVariables, ServiceVariables, SubscribeServiceRegistryConfig, SubscribeServiceTypes,
SubscribeServices,
},
tickets::{SubscribeTicketRedeemed, TicketRedeemedVariables},
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 ServiceTypeId = [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 ServiceSelector {
ServiceType(ServiceTypeId),
Node(ChainAddress),
ServiceTypeAndNode {
service_type: ServiceTypeId,
node: ChainAddress,
},
Any,
}
impl std::fmt::Debug for ServiceSelector {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::ServiceType(service_type) => write!(f, "ServiceType({})", hex::encode(service_type)),
Self::Node(node) => write!(f, "Node({})", hex::encode(node)),
Self::ServiceTypeAndNode { service_type, node } => write!(
f,
"ServiceTypeAndNode(service_type={}, node={})",
hex::encode(service_type),
hex::encode(node)
),
Self::Any => write!(f, "Any"),
}
}
}
#[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)]
pub enum TicketSelector {
ChannelId(ChannelId),
IssuerAddress(ChainAddress),
RecipientAddress(ChainAddress),
Any,
}
impl std::fmt::Debug for TicketSelector {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::ChannelId(channel_id) => write!(f, "ChannelId({})", hex::encode(channel_id)),
Self::IssuerAddress(address) => write!(f, "IssuerAddress({})", hex::encode(address)),
Self::RecipientAddress(address) => write!(f, "RecipientAddress({})", hex::encode(address)),
Self::Any => write!(f, "Any"),
}
}
}
#[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 {
#[cfg(feature = "curvy")]
async fn query_curvy_pending_notes(
&self,
from_block: Option<u64>,
after: Option<types::CurvyEventCursor>,
first: u32,
) -> Result<types::CurvyPendingNotes>;
#[cfg(feature = "curvy")]
async fn query_curvy_committed_notes(
&self,
from_block: Option<u64>,
after: Option<types::CurvyEventCursor>,
first: u32,
) -> Result<types::CurvyCommittedNotes>;
#[cfg(feature = "curvy")]
async fn query_curvy_committed_nullifiers(
&self,
from_block: Option<u64>,
after: Option<types::CurvyEventCursor>,
first: u32,
) -> Result<types::CurvyCommittedNullifiers>;
#[cfg(feature = "curvy")]
async fn query_curvy_sync_checkpoint(&self, block_hash: Option<String>) -> Result<types::CurvySyncCheckpoint>;
#[cfg(feature = "curvy")]
async fn query_curvy_sync_notes(
&self,
checkpoint: String,
from_index: Option<u64>,
first: u32,
) -> Result<types::CurvySyncNotePage>;
#[cfg(feature = "curvy")]
async fn query_curvy_sync_nullifiers(
&self,
checkpoint: String,
from_index: Option<u64>,
first: u32,
) -> Result<types::CurvySyncNullifierPage>;
#[cfg(feature = "curvy")]
async fn query_curvy_shard_roots(
&self,
checkpoint: String,
from_index: Option<u64>,
first: u32,
) -> Result<types::CurvyShardRootPage>;
#[cfg(feature = "curvy")]
async fn query_curvy_aggregator_state(&self) -> Result<types::CurvyAggregatorState>;
#[cfg(feature = "curvy")]
async fn query_curvy_note_status(&self, note_id: String) -> Result<types::CurvyNoteStatus>;
#[cfg(feature = "curvy")]
async fn query_curvy_valid_notes_root(&self, root: String) -> Result<bool>;
#[cfg(feature = "curvy")]
async fn query_curvy_nullifier_spent(&self, nullifier: String) -> Result<bool>;
#[cfg(feature = "curvy")]
async fn query_curvy_vault_fees(&self) -> Result<types::CurvyVaultFees>;
#[cfg(feature = "curvy")]
async fn query_curvy_aggregator_fees(&self) -> Result<types::CurvyAggregatorFees>;
#[cfg(feature = "curvy")]
async fn query_curvy_vault_token_count(&self) -> Result<types::CurvyVaultTokenCount>;
#[cfg(feature = "curvy")]
async fn query_curvy_vault_token(&self, token_id: String) -> Result<types::CurvyVaultToken>;
#[cfg(feature = "curvy")]
async fn query_curvy_entry_portal_address(&self, owner_hash: String, recovery: String) -> Result<String>;
#[cfg(feature = "curvy")]
async fn query_curvy_exit_portal_address(
&self,
exit_address: String,
exit_chain_id: String,
recovery: String,
) -> Result<String>;
#[cfg(feature = "curvy")]
async fn query_curvy_portal_registered(&self, portal_address: String) -> Result<bool>;
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, token: types::Token) -> 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 count_services(&self, selector: ServiceSelector) -> Result<u32>;
async fn query_services(&self, selector: ServiceSelector) -> Result<Vec<types::ServiceEntry>>;
async fn query_live_services(&self, selector: ServiceSelector) -> Result<Vec<types::ServiceEntry>>;
async fn query_service_types(&self, service_type: Option<ServiceTypeId>) -> Result<Vec<types::ServiceTypeInfo>>;
async fn query_service_registry_config(&self) -> Result<types::ServiceRegistryConfig>;
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_health(&self) -> Result<String>;
async fn query_compatibility(&self) -> Result<types::Compatibility>;
}
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_health(&self) -> Result<impl futures::Stream<Item = Result<types::ReadinessState>> + Send>;
fn subscribe_safe_deployments(&self) -> Result<impl futures::Stream<Item = Result<types::Safe>> + Send>;
fn subscribe_services(
&self,
selector: ServiceSelector,
) -> Result<impl futures::Stream<Item = Result<types::ServiceUpdate>> + Send>;
fn subscribe_service_types(
&self,
service_type: Option<ServiceTypeId>,
) -> Result<impl futures::Stream<Item = Result<types::ServiceTypeUpdate>> + Send>;
fn subscribe_service_registry_config(
&self,
) -> Result<impl futures::Stream<Item = Result<types::ServiceRegistryConfig>> + Send + 'static>;
fn subscribe_track_transaction(
&self,
tx_id: TxId,
) -> Result<impl futures::Stream<Item = Result<types::Transaction>> + Send>;
fn subscribe_ticket_redeemed(
&self,
selector: TicketSelector,
) -> Result<impl futures::Stream<Item = Result<types::RedeemTicketDetails>> + Send>;
#[cfg(feature = "curvy")]
fn subscribe_curvy_pending_notes(
&self,
from_block: Option<u64>,
) -> Result<impl futures::Stream<Item = Result<types::CurvyPendingNote>> + Send>;
#[cfg(feature = "curvy")]
fn subscribe_curvy_committed_notes(
&self,
from_block: Option<u64>,
) -> Result<impl futures::Stream<Item = Result<types::CurvyCommittedNote>> + Send>;
#[cfg(feature = "curvy")]
fn subscribe_curvy_committed_nullifiers(
&self,
from_block: Option<u64>,
) -> Result<impl futures::Stream<Item = Result<types::CurvyCommittedNullifier>> + 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>;
}