hopr_api/chain/
accounts.rs1use futures::{future::BoxFuture, stream::BoxStream};
2use hopr_crypto_types::prelude::{OffchainKeypair, OffchainPublicKey};
3pub use hopr_internal_types::prelude::AccountEntry;
4use hopr_primitive_types::prelude::Address;
5pub use hopr_primitive_types::prelude::{Balance, Currency};
6pub use multiaddr::Multiaddr;
7
8use crate::chain::ChainReceipt;
9
10#[derive(Debug, strum::EnumIs, strum::EnumTryAs, thiserror::Error)]
14pub enum AnnouncementError<E> {
15 #[error("already announced")]
17 AlreadyAnnounced,
18 #[error("account announcement error: {0}")]
20 ProcessingError(E),
21}
22
23impl<E> AnnouncementError<E> {
24 pub fn processing<F: Into<E>>(error: F) -> Self {
26 Self::ProcessingError(error.into())
27 }
28}
29
30#[derive(Debug, strum::EnumIs, strum::EnumTryAs, thiserror::Error)]
32pub enum SafeRegistrationError<E> {
33 #[error("node is already registered with safe {0}")]
35 AlreadyRegistered(Address),
36 #[error("safe registration error: {0}")]
38 ProcessingError(E),
39}
40
41impl<E> SafeRegistrationError<E> {
42 pub fn processing<F: Into<E>>(error: F) -> Self {
44 Self::ProcessingError(error.into())
45 }
46}
47
48#[async_trait::async_trait]
50#[auto_impl::auto_impl(&, Box, Arc)]
51pub trait ChainWriteAccountOperations {
52 type Error: std::error::Error + Send + Sync + 'static;
53
54 async fn announce(
56 &self,
57 multiaddrs: &[Multiaddr],
58 key: &OffchainKeypair,
59 ) -> Result<BoxFuture<'life0, Result<ChainReceipt, Self::Error>>, AnnouncementError<Self::Error>>;
60
61 async fn withdraw<C: Currency + Send>(
63 &self,
64 balance: Balance<C>,
65 recipient: &Address,
66 ) -> Result<BoxFuture<'life0, Result<ChainReceipt, Self::Error>>, Self::Error>;
67
68 async fn register_safe(
70 &self,
71 safe_address: &Address,
72 ) -> Result<BoxFuture<'life0, Result<ChainReceipt, Self::Error>>, SafeRegistrationError<Self::Error>>;
73}
74
75#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
79pub struct AccountSelector {
80 pub public_only: bool,
82 pub chain_key: Option<Address>,
84 pub offchain_key: Option<OffchainPublicKey>,
86}
87
88impl AccountSelector {
89 #[must_use]
91 pub fn with_public_only(mut self, public_only: bool) -> Self {
92 self.public_only = public_only;
93 self
94 }
95
96 #[must_use]
98 pub fn with_chain_key(mut self, chain_key: Address) -> Self {
99 self.chain_key = Some(chain_key);
100 self
101 }
102
103 #[must_use]
105 pub fn with_offchain_key(mut self, offchain_key: OffchainPublicKey) -> Self {
106 self.offchain_key = Some(offchain_key);
107 self
108 }
109
110 pub fn satisfies(&self, account: &AccountEntry) -> bool {
112 if self.public_only && !account.has_announced_with_routing_info() {
113 return false;
114 }
115
116 if let Some(chain_key) = &self.chain_key {
117 if &account.chain_addr != chain_key {
118 return false;
119 }
120 }
121
122 if let Some(packet_key) = &self.offchain_key {
123 if &account.public_key != packet_key {
124 return false;
125 }
126 }
127
128 true
129 }
130}
131
132#[async_trait::async_trait]
134#[auto_impl::auto_impl(&, Box, Arc)]
135pub trait ChainReadAccountOperations {
136 type Error: std::error::Error + Send + Sync + 'static;
137
138 async fn stream_accounts<'a>(
140 &'a self,
141 selector: AccountSelector,
142 ) -> Result<BoxStream<'a, AccountEntry>, Self::Error>;
143
144 async fn count_accounts(&self, selector: AccountSelector) -> Result<usize, Self::Error>;
149
150 async fn await_key_binding(
152 &self,
153 offchain_key: &OffchainPublicKey,
154 timeout: std::time::Duration,
155 ) -> Result<AccountEntry, Self::Error>;
156}