pub mod batch;
pub mod cache;
pub mod chunk;
pub mod data;
pub mod file;
pub mod merkle;
pub mod payment;
pub(crate) mod peer_cache;
pub mod quote;
use crate::data::client::cache::ChunkCache;
use crate::data::error::{Error, Result};
use crate::data::network::Network;
use ant_protocol::evm::Wallet;
use ant_protocol::transport::{MultiAddr, P2PNode, PeerId};
use ant_protocol::{XorName, CLOSE_GROUP_SIZE};
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use tracing::debug;
const DEFAULT_QUOTE_TIMEOUT_SECS: u64 = 10;
const DEFAULT_STORE_TIMEOUT_SECS: u64 = 10;
const DEFAULT_QUOTE_CONCURRENCY: usize = 32;
const DEFAULT_STORE_CONCURRENCY: usize = 8;
#[derive(Debug, Clone)]
pub struct ClientConfig {
pub quote_timeout_secs: u64,
pub store_timeout_secs: u64,
pub close_group_size: usize,
pub quote_concurrency: usize,
pub store_concurrency: usize,
pub allow_loopback: bool,
pub ipv6: bool,
}
impl Default for ClientConfig {
fn default() -> Self {
Self {
quote_timeout_secs: DEFAULT_QUOTE_TIMEOUT_SECS,
store_timeout_secs: DEFAULT_STORE_TIMEOUT_SECS,
close_group_size: CLOSE_GROUP_SIZE,
quote_concurrency: DEFAULT_QUOTE_CONCURRENCY,
store_concurrency: DEFAULT_STORE_CONCURRENCY,
allow_loopback: false,
ipv6: true,
}
}
}
pub struct Client {
config: ClientConfig,
network: Network,
wallet: Option<Arc<Wallet>>,
evm_network: Option<ant_protocol::evm::Network>,
chunk_cache: ChunkCache,
next_request_id: AtomicU64,
}
impl Client {
#[must_use]
pub fn from_node(node: Arc<P2PNode>, config: ClientConfig) -> Self {
let network = Network::from_node(node);
Self {
config,
network,
wallet: None,
evm_network: None,
chunk_cache: ChunkCache::default(),
next_request_id: AtomicU64::new(1),
}
}
pub async fn connect(
bootstrap_peers: &[std::net::SocketAddr],
config: ClientConfig,
) -> Result<Self> {
debug!(
"Connecting to Autonomi network with {} bootstrap peers (allow_loopback={}, ipv6={})",
bootstrap_peers.len(),
config.allow_loopback,
config.ipv6,
);
let network = Network::new(bootstrap_peers, config.allow_loopback, config.ipv6).await?;
Ok(Self {
config,
network,
wallet: None,
evm_network: None,
chunk_cache: ChunkCache::default(),
next_request_id: AtomicU64::new(1),
})
}
#[must_use]
pub fn with_wallet(mut self, wallet: Wallet) -> Self {
self.evm_network = Some(wallet.network().clone());
self.wallet = Some(Arc::new(wallet));
self
}
#[must_use]
pub fn with_evm_network(mut self, network: ant_protocol::evm::Network) -> Self {
self.evm_network = Some(network);
self
}
pub(crate) fn require_evm_network(&self) -> Result<&ant_protocol::evm::Network> {
if let Some(ref net) = self.evm_network {
return Ok(net);
}
if let Some(ref wallet) = self.wallet {
return Ok(wallet.network());
}
Err(Error::Payment(
"EVM network not configured — call with_evm_network() or with_wallet() first"
.to_string(),
))
}
#[must_use]
pub fn config(&self) -> &ClientConfig {
&self.config
}
pub fn config_mut(&mut self) -> &mut ClientConfig {
&mut self.config
}
#[must_use]
pub fn network(&self) -> &Network {
&self.network
}
#[must_use]
pub fn wallet(&self) -> Option<&Arc<Wallet>> {
self.wallet.as_ref()
}
#[must_use]
pub fn chunk_cache(&self) -> &ChunkCache {
&self.chunk_cache
}
pub(crate) fn next_request_id(&self) -> u64 {
self.next_request_id.fetch_add(1, Ordering::Relaxed)
}
pub(crate) async fn close_group_peers(
&self,
target: &XorName,
) -> Result<Vec<(PeerId, Vec<MultiAddr>)>> {
let peers = self
.network()
.find_closest_peers(target, self.config().close_group_size)
.await?;
if peers.is_empty() {
return Err(Error::InsufficientPeers(
"DHT returned no peers for target address".to_string(),
));
}
Ok(peers)
}
}