use alloy_sol_types::SolCall as _;
use tronz_primitives::{Address, U256};
use tronz_provider::{PendingTransaction, TronProvider};
use crate::{
error::{ContractError, Result},
instance::ContractInstance,
trc20::{
ITRC20, decode_decimals_return, decode_string_return, decode_uint256_return,
encode_allowance, encode_approve, encode_balance_of, encode_transfer, encode_transfer_from,
},
};
pub type Trc20Error = ContractError;
#[derive(Clone)]
pub struct Trc20Instance<P: TronProvider> {
inner: ContractInstance<P>,
}
impl<P: TronProvider> Trc20Instance<P> {
pub fn new(provider: P, address: Address) -> Self {
Self { inner: ContractInstance::new_raw(provider, address) }
}
pub fn address(&self) -> Address {
self.inner.address()
}
pub fn provider(&self) -> &P {
self.inner.provider()
}
pub fn at(self, address: Address) -> Self {
Self { inner: self.inner.at(address) }
}
pub async fn name(&self) -> Result<String, Trc20Error> {
let out = self.inner.call_raw(ITRC20::nameCall {}.abi_encode().into()).call().await?;
Ok(decode_string_return(&out)?)
}
pub async fn symbol(&self) -> Result<String, Trc20Error> {
let out = self.inner.call_raw(ITRC20::symbolCall {}.abi_encode().into()).call().await?;
Ok(decode_string_return(&out)?)
}
pub async fn decimals(&self) -> Result<u8, Trc20Error> {
let out = self.inner.call_raw(ITRC20::decimalsCall {}.abi_encode().into()).call().await?;
Ok(decode_decimals_return(&out)?)
}
pub async fn total_supply(&self) -> Result<U256, Trc20Error> {
let out =
self.inner.call_raw(ITRC20::totalSupplyCall {}.abi_encode().into()).call().await?;
Ok(decode_uint256_return(&out)?)
}
pub async fn balance_of(&self, account: Address) -> Result<U256, Trc20Error> {
let out = self.inner.call_raw(encode_balance_of(account)).call().await?;
Ok(decode_uint256_return(&out)?)
}
pub async fn allowance(&self, owner: Address, spender: Address) -> Result<U256, Trc20Error> {
let out = self.inner.call_raw(encode_allowance(owner, spender)).call().await?;
Ok(decode_uint256_return(&out)?)
}
pub async fn transfer(
&self,
to: Address,
amount: U256,
) -> Result<PendingTransaction<P>, Trc20Error> {
self.inner.call_raw(encode_transfer(to, amount)).send().await
}
pub async fn approve(
&self,
spender: Address,
amount: U256,
) -> Result<PendingTransaction<P>, Trc20Error> {
self.inner.call_raw(encode_approve(spender, amount)).send().await
}
pub async fn transfer_from(
&self,
from: Address,
to: Address,
amount: U256,
) -> Result<PendingTransaction<P>, Trc20Error> {
self.inner.call_raw(encode_transfer_from(from, to, amount)).send().await
}
}
pub trait Trc20Ext: TronProvider + Sized {
fn trc20(&self, address: Address) -> Trc20Instance<Self> {
Trc20Instance::new(self.clone(), address)
}
}
impl<P: TronProvider> Trc20Ext for P {}