2020-05-25 10:05:00 +00:00
|
|
|
use ethers::{
|
2020-05-26 11:00:56 +00:00
|
|
|
abi::{Detokenize, InvalidOutputType, Token},
|
2020-05-26 14:43:51 +00:00
|
|
|
contract::{Contract, Event, Sender},
|
|
|
|
providers::{HttpProvider, JsonRpcClient},
|
|
|
|
signers::{Client, MainnetWallet, Signer},
|
|
|
|
types::{Address, H256},
|
2020-05-25 10:05:00 +00:00
|
|
|
};
|
2020-05-26 11:00:56 +00:00
|
|
|
|
|
|
|
use anyhow::Result;
|
2020-05-25 18:14:13 +00:00
|
|
|
use serde::Serialize;
|
2020-05-25 10:05:00 +00:00
|
|
|
use std::convert::TryFrom;
|
|
|
|
|
2020-05-25 18:14:13 +00:00
|
|
|
const ABI: &'static str = r#"[{"inputs":[{"internalType":"string","name":"value","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"author","type":"address"},{"indexed":false,"internalType":"string","name":"oldValue","type":"string"},{"indexed":false,"internalType":"string","name":"newValue","type":"string"}],"name":"ValueChanged","type":"event"},{"inputs":[],"name":"getValue","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"value","type":"string"}],"name":"setValue","outputs":[],"stateMutability":"nonpayable","type":"function"}]"#;
|
|
|
|
|
2020-05-26 14:43:51 +00:00
|
|
|
// abigen!(SimpleContract, ABI);
|
|
|
|
|
2020-05-25 18:14:13 +00:00
|
|
|
#[derive(Clone, Debug, Serialize)]
|
|
|
|
// TODO: This should be `derive`-able on such types -> similar to how Zexe's Deserialize is done
|
|
|
|
struct ValueChanged {
|
|
|
|
author: Address,
|
|
|
|
old_value: String,
|
|
|
|
new_value: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Detokenize for ValueChanged {
|
2020-05-26 11:00:56 +00:00
|
|
|
fn from_tokens(tokens: Vec<Token>) -> Result<ValueChanged, InvalidOutputType> {
|
2020-05-25 18:14:13 +00:00
|
|
|
let author: Address = tokens[0].clone().to_address().unwrap();
|
|
|
|
let old_value = tokens[1].clone().to_string().unwrap();
|
|
|
|
let new_value = tokens[2].clone().to_string().unwrap();
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
author,
|
|
|
|
old_value,
|
|
|
|
new_value,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-26 14:43:51 +00:00
|
|
|
struct SimpleContract<'a, S, P>(Contract<'a, S, P>);
|
|
|
|
|
|
|
|
impl<'a, S: Signer, P: JsonRpcClient> SimpleContract<'a, S, P> {
|
|
|
|
fn new<T: Into<Address>>(address: T, client: &'a Client<'a, S, P>) -> Self {
|
|
|
|
let contract = Contract::new(client, serde_json::from_str(&ABI).unwrap(), address.into());
|
|
|
|
Self(contract)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_value<T: Into<String>>(&self, val: T) -> Sender<'a, S, P, H256> {
|
|
|
|
self.0
|
|
|
|
.method("setValue", Some(val.into()))
|
|
|
|
.expect("method not found (this should never happen)")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn value_changed<'b>(&'a self) -> Event<'a, 'b, P, ValueChanged>
|
|
|
|
where
|
|
|
|
'a: 'b,
|
|
|
|
{
|
|
|
|
self.0.event("ValueChanged").expect("event does not exist")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_value(&self) -> Sender<'a, S, P, String> {
|
|
|
|
self.0
|
|
|
|
.method("getValue", None::<()>)
|
|
|
|
.expect("method not found (this should never happen)")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-25 10:05:00 +00:00
|
|
|
#[tokio::main]
|
2020-05-26 11:00:56 +00:00
|
|
|
async fn main() -> Result<()> {
|
2020-05-25 10:05:00 +00:00
|
|
|
// connect to the network
|
|
|
|
let provider = HttpProvider::try_from("http://localhost:8545")?;
|
|
|
|
|
|
|
|
// create a wallet and connect it to the provider
|
2020-05-26 14:43:51 +00:00
|
|
|
let client = "ea878d94d9b1ffc78b45fc7bfc72ec3d1ce6e51e80c8e376c3f7c9a861f7c214"
|
2020-05-25 10:05:00 +00:00
|
|
|
.parse::<MainnetWallet>()?
|
|
|
|
.connect(&provider);
|
|
|
|
|
|
|
|
// Contract should take both provider or a signer
|
|
|
|
|
2020-05-25 15:35:38 +00:00
|
|
|
// get the contract's address
|
2020-05-26 14:43:51 +00:00
|
|
|
let addr = "ebBe15d9C365fC8a04a82E06644d6B39aF20cC31".parse::<Address>()?;
|
2020-05-25 10:05:00 +00:00
|
|
|
|
2020-05-25 15:35:38 +00:00
|
|
|
// instantiate it
|
2020-05-26 14:43:51 +00:00
|
|
|
let contract = SimpleContract::new(addr, &client);
|
2020-05-25 15:35:38 +00:00
|
|
|
|
|
|
|
// call the method
|
2020-05-26 14:43:51 +00:00
|
|
|
let _tx_hash = contract.set_value("hi").send().await?;
|
|
|
|
|
|
|
|
let logs = contract.value_changed().from_block(0u64).query().await?;
|
|
|
|
|
|
|
|
let value = contract.get_value().call().await?;
|
2020-05-25 15:35:38 +00:00
|
|
|
|
2020-05-26 14:43:51 +00:00
|
|
|
println!("Value: {}. Logs: {}", value, serde_json::to_string(&logs)?);
|
2020-05-25 15:35:38 +00:00
|
|
|
|
2020-05-25 10:05:00 +00:00
|
|
|
Ok(())
|
|
|
|
}
|