diff --git a/crates/erc20_payment_lib/src/contracts.rs b/crates/erc20_payment_lib/src/contracts.rs index 4ec85663..7290233c 100644 --- a/crates/erc20_payment_lib/src/contracts.rs +++ b/crates/erc20_payment_lib/src/contracts.rs @@ -5,10 +5,10 @@ use crate::error::PaymentError; use std::str::FromStr; use web3::contract::tokens::Tokenize; use web3::contract::Contract; +use web3::ethabi::{FixedBytes, Hash}; use web3::transports::Http; use web3::types::{Address, H256, U256}; use web3::{ethabi, Transport, Web3}; -use web3::ethabi::{FixedBytes, Hash}; // todo remove DUMMY_RPC_PROVIDER and use ABI instead // todo change to once_cell @@ -61,16 +61,12 @@ where .and_then(|function| function.encode_input(¶ms.into_tokens())) } -pub fn encode_get_attestation( - uid: H256, -) -> Result, web3::ethabi::Error> { - contract_encode(&EAS_CONTRACT_TEMPLATE, "getAttestation", (uid, )) +pub fn encode_get_attestation(uid: H256) -> Result, web3::ethabi::Error> { + contract_encode(&EAS_CONTRACT_TEMPLATE, "getAttestation", (uid,)) } -pub fn encode_get_schema( - uid: H256, -) -> Result, web3::ethabi::Error> { - contract_encode(&SCHEMA_REGISTRY_TEMPLATE, "getSchema", (uid, )) +pub fn encode_get_schema(uid: H256) -> Result, web3::ethabi::Error> { + contract_encode(&SCHEMA_REGISTRY_TEMPLATE, "getSchema", (uid,)) } pub fn encode_erc20_balance_of(address: Address) -> Result, web3::ethabi::Error> { diff --git a/crates/erc20_payment_lib/src/eth.rs b/crates/erc20_payment_lib/src/eth.rs index 0aa64461..a040ea21 100644 --- a/crates/erc20_payment_lib/src/eth.rs +++ b/crates/erc20_payment_lib/src/eth.rs @@ -1,14 +1,19 @@ -use crate::contracts::{encode_erc20_allowance, encode_erc20_balance_of, encode_get_attestation, encode_get_deposit_details, encode_get_schema}; +use crate::contracts::{ + encode_erc20_allowance, encode_erc20_balance_of, encode_get_attestation, + encode_get_deposit_details, encode_get_schema, +}; use crate::error::*; use crate::{err_create, err_custom_create, err_from}; -use erc20_payment_lib_common::utils::{datetime_from_u256_timestamp, datetime_from_u256_with_option, U256ConvExt}; +use chrono::{DateTime, Utc}; +use erc20_payment_lib_common::utils::{ + datetime_from_u256_timestamp, datetime_from_u256_with_option, U256ConvExt, +}; use erc20_rpc_pool::Web3RpcPool; use secp256k1::{PublicKey, SecretKey}; use serde::{Deserialize, Serialize}; use sha3::Digest; use sha3::Keccak256; use std::sync::Arc; -use chrono::{DateTime, Utc}; use web3::ethabi; use web3::types::{Address, BlockId, BlockNumber, Bytes, CallRequest, H256, U256, U64}; @@ -148,7 +153,7 @@ pub async fn get_schema_details( uid: H256::from_slice(decoded[0].clone().into_fixed_bytes().unwrap().as_slice()), resolver: decoded[1].clone().into_address().unwrap(), revocable: decoded[2].clone().into_bool().unwrap(), - schema: decoded[3].clone().into_string().unwrap() + schema: decoded[3].clone().into_string().unwrap(), }; Ok(schema) @@ -165,7 +170,7 @@ pub struct Attestation { pub recipient: Address, pub attester: Address, pub revocable: bool, - pub data: Bytes + pub data: Bytes, } pub async fn get_attestation_details( @@ -185,7 +190,6 @@ pub async fn get_attestation_details( .await .map_err(err_from!())?; - let decoded = ethabi::decode( &[ ethabi::ParamType::Tuple( @@ -214,14 +218,15 @@ pub async fn get_attestation_details( let attestation = Attestation { uid: H256::from_slice(decoded[0].clone().into_fixed_bytes().unwrap().as_slice()), schema: H256::from_slice(decoded[1].clone().into_fixed_bytes().unwrap().as_slice()), - time: datetime_from_u256_with_option(decoded[2].clone().into_uint().unwrap()).ok_or(err_custom_create!("Attestation timestamp out of range"))?, + time: datetime_from_u256_with_option(decoded[2].clone().into_uint().unwrap()) + .ok_or(err_custom_create!("Attestation timestamp out of range"))?, expiration_time: datetime_from_u256_with_option(decoded[3].clone().into_uint().unwrap()), revocation_time: datetime_from_u256_with_option(decoded[4].clone().into_uint().unwrap()), refUID: H256::from_slice(decoded[5].clone().into_fixed_bytes().unwrap().as_slice()), recipient: decoded[6].clone().into_address().unwrap(), attester: decoded[7].clone().into_address().unwrap(), revocable: decoded[8].clone().into_bool().unwrap(), - data: Bytes::from(decoded[9].clone().into_bytes().unwrap()) + data: Bytes::from(decoded[9].clone().into_bytes().unwrap()), }; Ok(attestation) diff --git a/crates/erc20_payment_lib/src/server/web.rs b/crates/erc20_payment_lib/src/server/web.rs index 0e94ae38..0381d4c3 100644 --- a/crates/erc20_payment_lib/src/server/web.rs +++ b/crates/erc20_payment_lib/src/server/web.rs @@ -1,10 +1,13 @@ -use crate::eth::{Attestation, AttestationSchema, get_attestation_details, get_balance, get_schema_details}; +use crate::eth::{ + get_attestation_details, get_balance, get_schema_details, Attestation, AttestationSchema, +}; use crate::runtime::{PaymentRuntime, SharedState, TransferArgs, TransferType}; use crate::server::ws::event_stream_websocket_endpoint; use crate::setup::{ChainSetup, PaymentSetup}; use crate::transaction::create_token_transfer; use actix_files::NamedFile; use actix_web::dev::{ServiceRequest, ServiceResponse}; +use actix_web::error::ErrorBadRequest; use actix_web::http::header::HeaderValue; use actix_web::http::{header, StatusCode}; use actix_web::web::Data; @@ -22,7 +25,6 @@ use std::collections::BTreeMap; use std::str::FromStr; use std::sync::Arc; use std::time::Duration; -use actix_web::error::ErrorBadRequest; use tokio::sync::Mutex; use web3::ethabi; use web3::types::{Address, BlockId, BlockNumber, H256, U256}; @@ -1240,27 +1242,29 @@ struct AttestationCheckResult { params: Vec, } -pub async fn check_attestation(data: Data>, req: HttpRequest) -> actix_web::Result> -{ +pub async fn check_attestation( + data: Data>, + req: HttpRequest, +) -> actix_web::Result> { let my_data = data.shared_state.lock().unwrap(); - let attestation_uid = req.match_info().get("uid").unwrap_or(""); let chain_name = req.match_info().get("chain").unwrap_or(""); let chain: &ChainSetup = data - .payment_setup - .chain_setup - .iter().find( - |(_, chain)| chain.network == chain_name - ).ok_or( - actix_web::error::ErrorBadRequest(format!("No config found for network {}", chain_name)) - )?.1; - - let web3 = data.payment_setup.get_provider( - chain.chain_id - ).map_err( - |e| ErrorBadRequest(format!("Failed to get provider: {}", e)) - )?; + .payment_setup + .chain_setup + .iter() + .find(|(_, chain)| chain.network == chain_name) + .ok_or(actix_web::error::ErrorBadRequest(format!( + "No config found for network {}", + chain_name + )))? + .1; + + let web3 = data + .payment_setup + .get_provider(chain.chain_id) + .map_err(|e| ErrorBadRequest(format!("Failed to get provider: {}", e)))?; let decoded_bytes = match hex::decode(attestation_uid.replace("0x", "")) { Ok(bytes) => bytes, @@ -1272,13 +1276,21 @@ pub async fn check_attestation(data: Data>, req: HttpRequest) -> } }; - let contract = chain.eas_contract_settings.clone().ok_or( - ErrorBadRequest(format!("No contract settings found for chain {}", chain_name)) - )?; + let contract = chain + .eas_contract_settings + .clone() + .ok_or(ErrorBadRequest(format!( + "No contract settings found for chain {}", + chain_name + )))?; - let schema_contract = chain.eas_schema_registry_settings.clone().ok_or( - ErrorBadRequest(format!("No schema contract settings found for chain {}", chain_name)) - )?; + let schema_contract = chain + .eas_schema_registry_settings + .clone() + .ok_or(ErrorBadRequest(format!( + "No schema contract settings found for chain {}", + chain_name + )))?; let uid = ethabi::Bytes::from(decoded_bytes); @@ -1292,33 +1304,8 @@ pub async fn check_attestation(data: Data>, req: HttpRequest) -> }; log::info!("Querying attestation contract: {:#x}", contract.address); - - - let attestation = match get_attestation_details( - web3.clone(), - uid, - contract.address, - ).await { - Ok(attestation) => { - attestation - } - Err(e) => { - log::error!("Failed to get attestation details: {}", e); - return Err(ErrorBadRequest(format!( - "Failed to get attestation details: {}", - e - ))); - } - }; - - let attestation_schema = match get_schema_details( - web3, - attestation.schema, - schema_contract.address, - ).await { - Ok(attestation_schema) => { - attestation_schema - } + let attestation = match get_attestation_details(web3.clone(), uid, contract.address).await { + Ok(attestation) => attestation, Err(e) => { log::error!("Failed to get attestation details: {}", e); return Err(ErrorBadRequest(format!( @@ -1328,19 +1315,41 @@ pub async fn check_attestation(data: Data>, req: HttpRequest) -> } }; + let attestation_schema = + match get_schema_details(web3, attestation.schema, schema_contract.address).await { + Ok(attestation_schema) => attestation_schema, + Err(e) => { + log::error!("Failed to get attestation details: {}", e); + return Err(ErrorBadRequest(format!( + "Failed to get attestation details: {}", + e + ))); + } + }; log::info!("Querying schema contract: {:#x}", schema_contract.address); - - println!("attestation: {}", serde_json::to_string_pretty(&attestation).map_err( - |e| ErrorBadRequest(format!("Failed to serialize attestation details: {}", e)) - )?); - - println!("schema: {}", serde_json::to_string_pretty(&attestation_schema).map_err( - |e| ErrorBadRequest(format!("Failed to serialize attestation details: {}", e)) - )?); - - let items = attestation_schema.schema.split(",").into_iter().collect::>(); + println!( + "attestation: {}", + serde_json::to_string_pretty(&attestation).map_err(|e| ErrorBadRequest(format!( + "Failed to serialize attestation details: {}", + e + )))? + ); + + println!( + "schema: {}", + serde_json::to_string_pretty(&attestation_schema).map_err(|e| ErrorBadRequest(format!( + "Failed to serialize attestation details: {}", + e + )))? + ); + + let items = attestation_schema + .schema + .split(",") + .into_iter() + .collect::>(); log::debug!("There are {} items in the schema", items.len()); let mut param_types = Vec::new(); let mut param_names = Vec::new(); @@ -1355,19 +1364,21 @@ pub async fn check_attestation(data: Data>, req: HttpRequest) -> let item_name = items2[1].trim(); log::debug!("Item name: {}, Item type: {}", item_name, item_type); - let param_type = ethabi::param_type::Reader::read(item_type).map_err( - |e| ErrorBadRequest(format!("Failed to read param type: {}", e)) - )?; + let param_type = ethabi::param_type::Reader::read(item_type) + .map_err(|e| ErrorBadRequest(format!("Failed to read param type: {}", e)))?; param_types.push(param_type); param_names.push(item_name); } - let decoded_tokens = ethabi::decode(¶m_types, &attestation.data.0).map_err( - |e| ErrorBadRequest(format!("Failed to decode attestation data: {}", e)) - )?; + let decoded_tokens = ethabi::decode(¶m_types, &attestation.data.0) + .map_err(|e| ErrorBadRequest(format!("Failed to decode attestation data: {}", e)))?; let mut decoded_items = Vec::new(); - for ((token, token_name), token_type) in decoded_tokens.iter().zip(param_names.iter()).zip(param_types.iter()) { + for ((token, token_name), token_type) in decoded_tokens + .iter() + .zip(param_names.iter()) + .zip(param_types.iter()) + { println!("Token {}: {}", token_name, token); decoded_items.push(AttestationItemInfo { name: token_name.to_string(), @@ -1382,10 +1393,9 @@ pub async fn check_attestation(data: Data>, req: HttpRequest) -> attestation, schema: attestation_schema, params: decoded_items, - })) + })); } - pub fn runtime_web_scope( scope: Scope, server_data: Data>, @@ -1397,7 +1407,10 @@ pub fn runtime_web_scope( let api_scope = Scope::new("/api"); let mut api_scope = api_scope .app_data(server_data) - .route("/attestation/{chain}/{uid}", web::get().to(check_attestation)) + .route( + "/attestation/{chain}/{uid}", + web::get().to(check_attestation), + ) .route("/allowances", web::get().to(allowances)) .route("/balance/{account}/{chain}", web::get().to(account_balance)) .route("/rpc_pool", web::get().to(rpc_pool)) diff --git a/crates/erc20_payment_lib/src/setup.rs b/crates/erc20_payment_lib/src/setup.rs index 45c328db..b2852b84 100644 --- a/crates/erc20_payment_lib/src/setup.rs +++ b/crates/erc20_payment_lib/src/setup.rs @@ -309,16 +309,16 @@ impl PaymentSetup { .distributor_contract .clone() .map(|m| m.address), - eas_contract_settings: chain_config.1.attestation_contract.clone().map(|m| { - EasContractSettings { - address: m.address, - } - }), - eas_schema_registry_settings: chain_config.1.schema_registry_contract.clone().map( - |m| EasSchemaRegistrySettings { - address: m.address, - }, - ), + eas_contract_settings: chain_config + .1 + .attestation_contract + .clone() + .map(|m| EasContractSettings { address: m.address }), + eas_schema_registry_settings: chain_config + .1 + .schema_registry_contract + .clone() + .map(|m| EasSchemaRegistrySettings { address: m.address }), faucet_setup, transaction_timeout: chain_config.1.transaction_timeout, diff --git a/src/actions.rs b/src/actions.rs index 032a1b0a..c80264d9 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -2,10 +2,10 @@ use rustc_hex::FromHexError; use std::str::FromStr; use web3::types::Address; +pub mod attestation; pub mod check_rpc; pub mod deposit; pub mod scan_chain; -pub mod attestation; pub fn check_address_name(n: &str) -> Result { match n { diff --git a/src/actions/attestation.rs b/src/actions/attestation.rs index 1e41ae91..3e8ff0fc 100644 --- a/src/actions/attestation.rs +++ b/src/actions/attestation.rs @@ -1 +1 @@ -pub mod check; \ No newline at end of file +pub mod check; diff --git a/src/main.rs b/src/main.rs index 9d50c8f3..786093c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,7 @@ use erc20_payment_lib::{ use std::env; use std::str::FromStr; +use crate::actions::attestation::check::check_attestation_local; use crate::actions::check_address_name; use crate::actions::check_rpc::check_rpc_local; use crate::actions::deposit::close::close_deposit_local; @@ -49,7 +50,6 @@ use std::sync::Arc; use structopt::StructOpt; use tokio::sync::{broadcast, Mutex}; use web3::types::U256; -use crate::actions::attestation::check::check_attestation_local; async fn main_internal() -> Result<(), PaymentError> { dotenv::dotenv().ok(); @@ -86,7 +86,9 @@ async fn main_internal() -> Result<(), PaymentError> { PaymentCommands::DecryptKeyStore { .. } => {} PaymentCommands::Cleanup { .. } => {} PaymentCommands::ShowConfig { .. } => {} - PaymentCommands::Attestation { .. } => { private_key_load_needed = false; } + PaymentCommands::Attestation { .. } => { + private_key_load_needed = false; + } } let (private_keys, public_addrs) = if private_key_load_needed { @@ -418,7 +420,7 @@ async fn main_internal() -> Result<(), PaymentError> { AttestationCommands::Check { options } => { check_attestation_local(conn.clone().unwrap(), options, config).await?; } - } + }, PaymentCommands::Deposit { deposit } => match deposit { DepositCommands::Create { make_deposit_options, diff --git a/src/options.rs b/src/options.rs index a444c771..4bf8d52e 100644 --- a/src/options.rs +++ b/src/options.rs @@ -1,5 +1,6 @@ use std::{fmt::Debug, path::PathBuf}; +use crate::actions::attestation::check::AttestationCheckOptions; use crate::actions::deposit::close::CloseDepositOptions; use crate::actions::deposit::create::CreateDepositOptions; use crate::actions::deposit::details::CheckDepositOptions; @@ -7,7 +8,6 @@ use crate::actions::deposit::terminate::TerminateDepositOptions; use erc20_payment_lib_extra::{BalanceOptions, GenerateOptions}; use structopt::StructOpt; use web3::types::Address; -use crate::actions::attestation::check::AttestationCheckOptions; #[derive(StructOpt)] #[structopt(about = "Payment admin tool - run options")]