use crate::context::Web3Context;
use crate::providers::{CallProvider, SendProvider};
use async_trait::async_trait;
use std::marker::Unpin;
use web3::contract::tokens::{Detokenize, Tokenize};
use web3::contract::Contract;
use web3::contract::Options;
use web3::transports::Http;
use web3::types::{Address, TransactionReceipt};
pub struct Web3Provider {
contract: Contract<Http>,
context: Web3Context,
}
#[async_trait]
impl CallProvider for Web3Provider {
async fn call<O: Detokenize + Unpin + Send, Params: Tokenize + Send>(
&self,
name: &'static str,
params: Params,
) -> Result<O, web3::Error> {
match self
.contract
.query(
name,
params,
Some(self.context.from()),
Default::default(),
None,
)
.await
{
Ok(v) => Ok(v),
Err(e) => match e {
web3::contract::Error::Api(e) => Err(e),
e => panic!("The ABI is out of date. Name: {}. Inner: {}", name, e),
},
}
}
}
#[async_trait]
impl SendProvider for Web3Provider {
type Out = TransactionReceipt;
async fn send<Params: Tokenize + Send>(
&self,
func: &'static str,
params: Params,
options: Option<Options>,
confirmations: Option<usize>,
) -> Result<Self::Out, web3::Error> {
self.contract
.signed_call_with_confirmations(
func,
params,
match options {
None => Default::default(),
Some(options) => options,
},
match confirmations {
None => 24,
Some(confirmations) => confirmations,
},
self.context.secret_key(),
)
.await
}
}
impl Web3Provider {
pub fn new(contract_address: Address, context: &Web3Context, json_abi: &[u8]) -> Self {
let context = context.clone();
let contract = Contract::from_json(context.eth(), contract_address, json_abi).unwrap();
Self { contract, context }
}
}