use ethers::{
providers::Middleware,
types::{Address, Eip1559TransactionRequest, TxHash, H160, U256},
};
use std::str::FromStr;
use crate::{
bindings::iwavax::IWAVAX,
constants::{GET_ACCOUNT_INVENTORY, WAVAX_CONTRACT_ADDRESS},
types::{MarketplaceSnapshot, PaginationConfig},
};
use super::{HyperspaceClient, HyperspaceClientError, HyperspaceSignerMiddleware};
mod types;
use types::{GetInventoryRequest, GetInventoryResponse};
pub struct Account<'a>(pub(crate) &'a HyperspaceClient);
impl<'a> Account<'a> {
async fn get_wavax_contract(&self) -> IWAVAX<HyperspaceSignerMiddleware> {
let wavax_contract_address = Address::from_str(WAVAX_CONTRACT_ADDRESS).unwrap();
IWAVAX::new(wavax_contract_address, self.0.signer.clone())
}
pub fn get_address(&self) -> H160 {
self.0.signer.address()
}
pub async fn get_avax_balance(&self) -> Result<U256, HyperspaceClientError> {
Ok(self.0.signer.get_balance(self.get_address(), None).await?)
}
pub async fn get_wavax_balance(&self) -> Result<U256, HyperspaceClientError> {
let wavax_contract = self.get_wavax_contract().await;
Ok(wavax_contract.balance_of(self.get_address()).call().await?)
}
pub async fn swap_avax_for_wavax(&self, amount: U256) -> Result<TxHash, HyperspaceClientError> {
let avax_balance = self.get_avax_balance().await?;
if avax_balance.is_zero() {
return Err(HyperspaceClientError::InsufficientAvaxBalance(avax_balance));
}
let wavax_contract = self.get_wavax_contract().await;
let typed_transaction = Eip1559TransactionRequest::new()
.to(wavax_contract.address())
.value(amount);
let tx_receipt = match self
.0
.signer
.send_transaction(typed_transaction, None)
.await?
.await?
{
Some(receipt) => receipt,
None => {
return Err(HyperspaceClientError::NoTransactionReceipt);
}
};
Ok(tx_receipt.transaction_hash)
}
pub async fn swap_wavax_for_avax(
&self,
amount: Option<U256>,
) -> Result<TxHash, HyperspaceClientError> {
let wavax_contract = self.get_wavax_contract().await;
let wavax_balance = self.get_wavax_balance().await?;
if wavax_balance.is_zero() {
return Err(HyperspaceClientError::InsufficientWavaxBalance(
wavax_balance,
));
}
let amount = match amount {
Some(amount) => {
if amount > wavax_balance {
return Err(HyperspaceClientError::InsufficientWavaxBalance(
wavax_balance,
));
} else {
amount
}
}
None => wavax_balance,
};
let tx_receipt = match wavax_contract.withdraw(amount).send().await?.await? {
Some(receipt) => receipt,
None => {
return Err(HyperspaceClientError::NoTransactionReceipt);
}
};
Ok(tx_receipt.transaction_hash)
}
pub async fn get_inventory(
&self,
project_id: Option<impl AsRef<str>>,
) -> Result<Vec<MarketplaceSnapshot>, HyperspaceClientError> {
let project_id = project_id.as_ref().map(|s| s.as_ref());
let body = GetInventoryRequest::new(
self.get_address(),
project_id,
Some(PaginationConfig::new(1, None)),
);
let res = self
.0
.post::<GetInventoryRequest, GetInventoryResponse>(GET_ACCOUNT_INVENTORY, body)
.await?;
Ok(res.marketplace_snapshots)
}
}
#[cfg(test)]
mod tests {
use super::*;
async fn setup() -> HyperspaceClient {
dotenv::dotenv().ok();
let api_key = dotenv::var("API_KEY").unwrap();
let private_key = dotenv::var("PRIVATE_KEY").unwrap();
HyperspaceClient::new(api_key, private_key, None::<&str>).unwrap()
}
#[tokio::test]
async fn test_get_avax_balance() {
let hs_client = setup().await;
let balance = hs_client.account().get_avax_balance().await.unwrap();
dbg!(balance);
}
#[tokio::test]
async fn test_get_wavax_balance() {
let hs_client = setup().await;
let balance = hs_client.account().get_wavax_balance().await.unwrap();
dbg!(balance);
}
#[tokio::test]
async fn test_swap_avax_for_wavax() {
let hs_client = setup().await;
let tx_hash = hs_client
.account()
.swap_avax_for_wavax(U256::from_str_radix("1000000000000000000", 10).unwrap())
.await
.unwrap();
assert_ne!(tx_hash, TxHash::zero());
}
#[tokio::test]
async fn test_swap_wavax_for_avax() {
let hs_client = setup().await;
let tx_hash = hs_client
.account()
.swap_wavax_for_avax(Some(
U256::from_str_radix("1000000000000000000", 10).unwrap(),
))
.await
.unwrap();
assert_ne!(tx_hash, TxHash::zero());
}
#[tokio::test]
async fn test_swap_all_wavax_for_avax() {
let hs_client = setup().await;
let tx_hash = hs_client.account().swap_wavax_for_avax(None).await.unwrap();
assert_ne!(tx_hash, TxHash::zero());
}
#[tokio::test]
async fn test_get_inventory() {
let hs_client = setup().await;
let owned_nfts = hs_client
.account()
.get_inventory(None::<&str>)
.await
.unwrap();
assert_eq!(owned_nfts.len(), 856);
}
}