1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
use crate::types::{Address, Bytes, Call, TransactionRequest, H256}; use crate::{rpc, Connection, Request}; use ethane_abi::{Abi, Parameter, StateMutability}; use std::path::Path; pub struct Caller<T: Request> { abi: Abi, contract_address: Address, connection: Connection<T>, } pub struct CallOpts { pub force_call_type: Option<CallType>, pub from: Option<Address>, } pub enum CallType { Transaction, Call, } pub enum CallResult { Transaction(H256), Call(Vec<Parameter>), } impl<T> Caller<T> where T: Request, { pub fn new( connection: Connection<T>, abi_json: serde_json::Value, contract_address: Address, ) -> Caller<T> { let mut abi = Abi::new(); abi.parse_json(abi_json).expect("unable to parse abi"); Caller { abi, contract_address, connection, } } pub fn new_from_path( connection: Connection<T>, path: &str, contract_address: Address, ) -> Caller<T> { let mut abi = Abi::new(); abi.parse_file(Path::new(path)) .expect("unable to parse abi"); Caller { abi, contract_address, connection, } } pub fn call( &mut self, function_name: &str, params: Vec<Parameter>, opts: Option<CallOpts>, ) -> CallResult { let mut call_type = if let Some(m) = self.abi.get_state_mutability(function_name) { match m { StateMutability::Pure => CallType::Call, StateMutability::View => CallType::Call, StateMutability::NonPayable => CallType::Transaction, StateMutability::Payable => CallType::Transaction, } } else { CallType::Transaction }; let mut from_address: Address = Default::default(); if let Some(o) = opts { from_address = o.from.unwrap(); if let Some(ct) = o.force_call_type { call_type = ct; } } let data = self.abi.encode(function_name, params).unwrap(); match call_type { CallType::Transaction => self.eth_send_transaction(data, from_address), CallType::Call => self.eth_call(function_name, data), } } fn eth_call(&mut self, function_name: &str, data: Vec<u8>) -> CallResult { let payload = Call { to: self.contract_address, data: Some(Bytes::from_slice(&data)), ..Default::default() }; let call_result = self.connection.call(rpc::eth_call(payload, None)).unwrap(); CallResult::Call( self.abi .decode(function_name, call_result.0.as_slice()) .unwrap(), ) } fn eth_send_transaction(&mut self, data: Vec<u8>, from_address: Address) -> CallResult { let payload = TransactionRequest { from: from_address, to: Some(self.contract_address), data: Some(Bytes::from_slice(&data)), ..Default::default() }; CallResult::Transaction( self.connection .call(rpc::eth_send_transaction(payload)) .unwrap(), ) } }