#![forbid(unsafe_code)]
pub use aelf_client::config::{BasicAuth, ClientConfig, RetryPolicy};
pub use aelf_client::dto;
#[cfg(feature = "native-http")]
pub use aelf_client::provider::HttpProvider;
pub use aelf_client::provider::Provider;
pub use aelf_client::{AElfError, KeyPairInfo, TransactionBuilder};
pub use aelf_contract::{
AedposContract, ContractError, CrossChainContract, DynamicContract, ElectionContract,
TokenContract, VoteContract, ZeroContract,
};
pub use aelf_crypto::{
address_from_public_key, address_to_pb, base58_to_chain_id, chain_id_to_base58, decode_address,
hash_to_pb, parse_aelf_address, pb_to_address, sign_transaction,
sign_transaction_with_private_key, transaction_hash, CryptoError, Wallet, DEFAULT_BIP44_PATH,
};
pub use aelf_keystore::{Keystore, KeystoreEncryptOptions, KeystoreError, UnlockedKeystore};
pub use aelf_proto as proto;
#[derive(Clone)]
pub struct AElfClient {
inner: aelf_client::AElfClient,
}
impl AElfClient {
#[cfg(feature = "native-http")]
pub fn new(config: ClientConfig) -> Result<Self, AElfError> {
Ok(Self {
inner: aelf_client::AElfClient::new(config)?,
})
}
pub fn with_provider<P>(provider: P) -> Result<Self, AElfError>
where
P: Provider + 'static,
{
Ok(Self {
inner: aelf_client::AElfClient::with_provider(provider)?,
})
}
pub fn block(&self) -> aelf_client::BlockService {
self.inner.block()
}
pub fn chain(&self) -> aelf_client::ChainService {
self.inner.chain()
}
pub fn net(&self) -> aelf_client::NetService {
self.inner.net()
}
pub fn tx(&self) -> aelf_client::TransactionService {
self.inner.tx()
}
pub fn utils(&self) -> aelf_client::ClientUtilsService {
self.inner.utils()
}
pub fn transaction_builder(&self) -> TransactionBuilder {
self.inner.transaction_builder()
}
pub async fn contract_at(
&self,
address: impl Into<String>,
wallet: Wallet,
) -> Result<DynamicContract, ContractError> {
DynamicContract::at(self.inner.clone(), address.into(), wallet).await
}
pub fn zero_contract(&self, address: impl Into<String>, wallet: Wallet) -> ZeroContract {
ZeroContract::new(self.inner.clone(), wallet, address)
}
pub fn token_contract(&self, address: impl Into<String>, wallet: Wallet) -> TokenContract {
TokenContract::new(self.inner.clone(), wallet, address)
}
pub fn election_contract(
&self,
address: impl Into<String>,
wallet: Wallet,
) -> ElectionContract {
ElectionContract::new(self.inner.clone(), wallet, address)
}
pub fn vote_contract(&self, address: impl Into<String>, wallet: Wallet) -> VoteContract {
VoteContract::new(self.inner.clone(), wallet, address)
}
pub fn cross_chain_contract(
&self,
address: impl Into<String>,
wallet: Wallet,
) -> CrossChainContract {
CrossChainContract::new(self.inner.clone(), wallet, address)
}
pub fn aedpos_contract(&self, address: impl Into<String>, wallet: Wallet) -> AedposContract {
AedposContract::new(self.inner.clone(), wallet, address)
}
pub fn inner(&self) -> &aelf_client::AElfClient {
&self.inner
}
}
pub fn format_token_amount(amount: i64, decimals: i32) -> String {
if decimals <= 0 {
return amount.to_string();
}
let negative = amount.is_negative();
let digits = amount.unsigned_abs().to_string();
let scale = decimals as usize;
let formatted = if digits.len() <= scale {
let mut value = String::from("0.");
value.push_str(&"0".repeat(scale - digits.len()));
value.push_str(&digits);
value
} else {
let split = digits.len() - scale;
format!("{}.{}", &digits[..split], &digits[split..])
};
if negative {
format!("-{formatted}")
} else {
formatted
}
}
#[cfg(test)]
mod tests {
use super::format_token_amount;
#[test]
fn formats_token_amount_with_decimals() {
assert_eq!(format_token_amount(123_456_789, 8), "1.23456789");
assert_eq!(format_token_amount(1, 8), "0.00000001");
assert_eq!(format_token_amount(-5, 2), "-0.05");
}
}