Skip to content

Commit

Permalink
Problem: Missing get_eth_transaction_receipt_blocking (fix #900) (#901)
Browse files Browse the repository at this point in the history
* Problem: Missing get_eth_transaction_receipt_blocking (fix #900)

* Hanlde no receipt case

* Add missing }

* Add missing errors

* Fix clippy

* Fix clippy: use the aysnc functions

* Do not expose to wasm32

* Add TODO notes
  • Loading branch information
damoncro authored May 12, 2023
1 parent b3c814f commit 6a46658
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 2 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 43 additions & 1 deletion bindings/cpp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ pub mod ffi {
) -> Result<Box<Wallet>>;

/// recovers/imports HD wallet from a BIP39 backup phrase (English words) and password
/// from secure storage
/// from secure storage
fn restore_wallet_load_from_securestorage(
servicename: String,
username: String,
Expand Down Expand Up @@ -600,6 +600,18 @@ pub mod ffi {
/// sent from it.
pub fn get_eth_nonce(address: &str, api_url: &str) -> Result<String>;

#[cxx_name = "get_eth_transaction_receipt_blocking"]
pub fn get_eth_transaction_receipt_by_vec_blocking(
tx_hash: Vec<u8>,
api_url: &str,
) -> Result<String>;

#[cxx_name = "get_eth_transaction_receipt_blocking"]
pub fn get_eth_transaction_receipt_by_string_blocking(
tx_hash: String,
api_url: &str,
) -> Result<String>;

/// broadcast signed cronos tx
pub fn broadcast_eth_signed_raw_tx(
raw_tx: Vec<u8>,
Expand Down Expand Up @@ -1289,6 +1301,36 @@ pub fn get_eth_nonce(address: &str, api_url: &str) -> Result<String> {
Ok(res.to_string())
}

/// Get eth transaction receipt with transaction hash, return json string
/// TODO: Provide TransactionReceipt type binding
pub fn get_eth_transaction_receipt_by_vec_blocking(
tx_hash: Vec<u8>,
api_url: &str,
) -> Result<String> {
let receipt =
defi_wallet_core_common::get_eth_transaction_receipt_by_vec_blocking(tx_hash, api_url)?;
if receipt.is_none() {
Ok("".to_string())
} else {
Ok(serde_json::to_string(&receipt)?)
}
}

/// Get eth transaction receipt with transaction hash, return json string
/// TODO: Provide TransactionReceipt type binding
pub fn get_eth_transaction_receipt_by_string_blocking(
tx_hash: String,
api_url: &str,
) -> Result<String> {
let receipt =
defi_wallet_core_common::get_eth_transaction_receipt_by_string_blocking(tx_hash, api_url)?;
if receipt.is_none() {
Ok("".to_string())
} else {
Ok(serde_json::to_string(&receipt)?)
}
}

/// broadcast signed cronos tx
pub fn broadcast_eth_signed_raw_tx(
raw_tx: Vec<u8>,
Expand Down
1 change: 1 addition & 0 deletions common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ thiserror = "1"
uniffi = { version = "^0.23", optional = true }
uniffi_macros = { version = "^0.23", optional = true }
url = "2"
hex="0.4.3"

[target.'cfg(target_arch = "wasm32")'.dependencies]
cosmos-sdk-proto = { git = "https://github.com/crypto-com/cosmos-rust.git", default-features = false, features = ["cosmwasm", "grpc"] }
Expand Down
3 changes: 3 additions & 0 deletions common/src/common.udl
Original file line number Diff line number Diff line change
Expand Up @@ -403,11 +403,14 @@ enum EthError {
"NodeUrl",
"SendTxFail",
"BroadcastTxFail",
"GetTransactionReceiptError",
"InvalidTxHash",
"MempoolDrop",
"BalanceFail",
"AsyncRuntimeError",
"ContractSendError",
"ContractCallError",
"GetTransactionError",
"SignatureError",
"ChainidError",
"IncorrectChainidError",
Expand Down
86 changes: 85 additions & 1 deletion common/src/node/ethereum/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
WalletCoinFunc,
};
use cosmrs::bip32::secp256k1::ecdsa::SigningKey;
use ethers::prelude::{Address, LocalWallet, Middleware, Signer, SignerMiddleware};
use ethers::prelude::{Address, LocalWallet, Middleware, Signer, SignerMiddleware, TxHash};
use ethers::types::transaction::eip2718::TypedTransaction;
use std::{str::FromStr, sync::Arc, time::Duration};
// use ethers Http
Expand Down Expand Up @@ -211,6 +211,90 @@ pub async fn get_eth_transaction_count(address: &str, web3api_url: &str) -> Resu
Ok(result)
}

// Wrapper of TxHash to implement TryFrom
pub struct TxHashWrapper(TxHash);

impl TryFrom<Vec<u8>> for TxHashWrapper {
type Error = EthError;

fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
if value.len() != 32 {
return Err(EthError::InvalidTxHash);
}

let mut tx_hash = [0u8; 32];
tx_hash.copy_from_slice(&value);
Ok(TxHashWrapper(TxHash::from(tx_hash)))
}
}

impl TryFrom<String> for TxHashWrapper {
type Error = EthError;

fn try_from(value: String) -> Result<Self, Self::Error> {
let value = hex::decode(value).map_err(|_| EthError::HexConversion)?;
if value.len() != 32 {
return Err(EthError::InvalidTxHash);
}

let mut tx_hash = [0u8; 32];
tx_hash.copy_from_slice(&value);
Ok(TxHashWrapper(TxHash::from(tx_hash)))
}
}

// TODO Don't expose to wasm32, to avoid clippy issue, no plan to support wasm32 for now
#[cfg(not(target_arch = "wasm32"))]
async fn get_eth_transaction_receipt_by_vec(
tx_hash: Vec<u8>,
web3api_url: &str,
) -> Result<Option<EthersTransactionReceipt>, EthError> {
let client = get_ethers_provider(web3api_url).await?;
let tx_hash = TxHashWrapper::try_from(tx_hash)?;

let receipt = client
.get_transaction_receipt(tx_hash.0)
.await
.map_err(EthError::GetTransactionReceiptError)?;

Ok(receipt)
}

// TODO Don't expose to wasm32, to avoid clippy issue, no plan to support wasm32 for now
#[cfg(not(target_arch = "wasm32"))]
async fn get_eth_transaction_receipt_by_string(
tx_hash: String,
web3api_url: &str,
) -> Result<Option<EthersTransactionReceipt>, EthError> {
let client = get_ethers_provider(web3api_url).await?;
let tx_hash = TxHashWrapper::try_from(tx_hash)?;

let receipt = client
.get_transaction_receipt(tx_hash.0)
.await
.map_err(EthError::GetTransactionReceiptError)?;

Ok(receipt)
}

#[cfg(not(target_arch = "wasm32"))]
pub fn get_eth_transaction_receipt_by_string_blocking(
tx_hash: String,
web3api_url: &str,
) -> Result<Option<EthersTransactionReceipt>, EthError> {
let rt = tokio::runtime::Runtime::new().map_err(|_err| EthError::AsyncRuntimeError)?;
rt.block_on(get_eth_transaction_receipt_by_string(tx_hash, web3api_url))
}

#[cfg(not(target_arch = "wasm32"))]
pub fn get_eth_transaction_receipt_by_vec_blocking(
tx_hash: Vec<u8>,
web3api_url: &str,
) -> Result<Option<EthersTransactionReceipt>, EthError> {
let rt = tokio::runtime::Runtime::new().map_err(|_err| EthError::AsyncRuntimeError)?;
rt.block_on(get_eth_transaction_receipt_by_vec(tx_hash, web3api_url))
}

/// given the account address and contract information, it returns the amount of ERC20/ERC721/ERC1155 token it owns
pub async fn get_contract_balance(
account_address: &str,
Expand Down
6 changes: 6 additions & 0 deletions common/src/transaction/ethereum/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ pub enum EthError {
SendTxFail(SignerMiddlewareError<Provider<Http>, Wallet<SigningKey>>),
#[error("Transaction sending failed: {0}")]
BroadcastTxFail(ProviderError),
#[error("Get Transaction Receipt failed: {0}")]
GetTransactionReceiptError(ProviderError),
#[error("Invliad Transaction Hash")]
InvalidTxHash,
#[error("Transaction dropped from the mempool")]
MempoolDrop,
#[error("Failed to obtain an account balance")]
Expand All @@ -38,6 +42,8 @@ pub enum EthError {
ContractSendError(String),
#[error("Contract Call Error: {0}")]
ContractCallError(String),
#[error("Get Transaction Error: {0}")]
GetTransactionError(String),
#[error("Signature error")]
SignatureError,
#[error("Chainid error: {0}")]
Expand Down

0 comments on commit 6a46658

Please sign in to comment.