use ethers::providers::Middleware;
use ethers::signers::{LocalWallet, Signer, WalletError};
use ethers::types::{TransactionRequest, H160 as EthersH160, U256};
use std::str::FromStr;
use crate::neo_clients::JsonRpcProvider;
use crate::neo_x::evm::provider::NeoXProvider;
use crate::neo_x::evm::transaction::NeoXTransaction;
#[derive(Debug, Clone)]
pub struct NeoXWallet {
inner: LocalWallet,
}
impl NeoXWallet {
pub fn from_private_key(hex_key: &str) -> Result<Self, WalletError> {
let wallet = LocalWallet::from_str(hex_key)?;
Ok(Self { inner: wallet })
}
pub fn create_random() -> Self {
let mut rng = ethers::core::rand::thread_rng();
let wallet = LocalWallet::new(&mut rng);
Self { inner: wallet }
}
pub fn address(&self) -> EthersH160 {
self.inner.address()
}
pub fn inner_wallet(&self) -> &LocalWallet {
&self.inner
}
}
pub struct NeoXClient<'a, P: JsonRpcProvider> {
pub wallet: NeoXWallet,
pub provider: NeoXProvider<'a, P>,
}
impl<'a, P: JsonRpcProvider + 'static> NeoXClient<'a, P> {
pub fn new(wallet: NeoXWallet, provider: NeoXProvider<'a, P>) -> Self {
Self { wallet, provider }
}
pub async fn get_balance(&self) -> Result<U256, String> {
let evm = self.provider.evm_provider().ok_or("No EVM provider configured")?;
let address = self.wallet.address();
evm.get_balance(address, None).await.map_err(|e| e.to_string())
}
pub async fn send_transaction(
&self,
tx: NeoXTransaction,
) -> Result<ethers::types::TransactionReceipt, String> {
let evm = self.provider.evm_provider().ok_or("No EVM provider configured")?;
let chain_id = self.provider.chain_id().await.map_err(|e| e.to_string())?;
let signer = self.wallet.inner.clone().with_chain_id(chain_id);
let client = ethers::middleware::SignerMiddleware::new(evm, signer);
let req: TransactionRequest = tx.into();
let pending_tx = client.send_transaction(req, None).await.map_err(|e| e.to_string())?;
let receipt = pending_tx
.await
.map_err(|e| e.to_string())?
.ok_or("Transaction dropped from mempool")?;
Ok(receipt)
}
}