-
Notifications
You must be signed in to change notification settings - Fork 117
[r2r] broadcast tx to txhlp / refactor tx errors #1245
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 41 commits
daeafc8
860163c
43862b6
b02ce08
f3747f7
7acdd35
06ecd56
5a73d5d
9a4c496
4a5d9c5
a9f2e6b
840d022
658ff56
f8ed4cc
fedbc32
78d64e3
e9d16a9
8545045
5c24769
1c3d7bd
b11fe2c
98df7cf
b1f9745
f136301
9a203e7
b6c8ecb
d10d4a9
3a2b0e9
3299524
d2cbe7b
6534913
1778350
903526f
6b9e579
19a493d
aa43384
21f2b6a
7811106
9c9db1c
f461dcc
bad90b6
8ca638f
ed574a5
46ad808
d456326
7e6c215
9444eda
5ba0dd1
f87cef3
21f9684
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,14 +59,14 @@ use super::{BalanceError, BalanceFut, CoinBalance, CoinProtocol, CoinTransportMe | |
| NumConversResult, RawTransactionError, RawTransactionFut, RawTransactionRequest, RawTransactionRes, | ||
| RawTransactionResult, RpcClientType, RpcTransportEventHandler, RpcTransportEventHandlerShared, SwapOps, | ||
| TradeFee, TradePreimageError, TradePreimageFut, TradePreimageResult, TradePreimageValue, Transaction, | ||
| TransactionDetails, TransactionEnum, TransactionFut, ValidateAddressResult, WithdrawError, WithdrawFee, | ||
| WithdrawFut, WithdrawRequest, WithdrawResult}; | ||
| TransactionDetails, TransactionEnum, ValidateAddressResult, WithdrawError, WithdrawFee, WithdrawFut, | ||
| WithdrawRequest, WithdrawResult}; | ||
|
|
||
| pub use ethcore_transaction::SignedTransaction as SignedEthTx; | ||
| pub use rlp; | ||
|
|
||
| mod web3_transport; | ||
| use crate::ValidatePaymentInput; | ||
| use crate::{TransactionErr, TransactionFut, ValidatePaymentInput}; | ||
| use common::mm_number::MmNumber; | ||
| use common::privkey::key_pair_from_secret; | ||
| use web3_transport::{EthFeeHistoryNamespace, Web3Transport}; | ||
|
|
@@ -685,10 +685,11 @@ impl Deref for EthCoin { | |
| #[async_trait] | ||
| impl SwapOps for EthCoin { | ||
| fn send_taker_fee(&self, fee_addr: &[u8], amount: BigDecimal, _uuid: &[u8]) -> TransactionFut { | ||
| let address = try_fus!(addr_from_raw_pubkey(fee_addr)); | ||
| let address = try_tx_fus!(addr_from_raw_pubkey(fee_addr)); | ||
|
|
||
| Box::new( | ||
| self.send_to_address(address, try_fus!(wei_from_big_decimal(&amount, self.decimals))) | ||
| self.send_to_address(address, try_tx_fus!(wei_from_big_decimal(&amount, self.decimals))) | ||
| .map_err(TransactionErr::PlainError) | ||
| .map(TransactionEnum::from), | ||
| ) | ||
| } | ||
|
|
@@ -702,18 +703,19 @@ impl SwapOps for EthCoin { | |
| amount: BigDecimal, | ||
| swap_contract_address: &Option<BytesJson>, | ||
| ) -> TransactionFut { | ||
| let taker_addr = try_fus!(addr_from_raw_pubkey(taker_pub)); | ||
| let swap_contract_address = try_fus!(swap_contract_address.try_to_address()); | ||
| let taker_addr = try_tx_fus!(addr_from_raw_pubkey(taker_pub)); | ||
| let swap_contract_address = try_tx_fus!(swap_contract_address.try_to_address()); | ||
|
|
||
| Box::new( | ||
| self.send_hash_time_locked_payment( | ||
|
sergeyboyko0791 marked this conversation as resolved.
|
||
| self.etomic_swap_id(time_lock, secret_hash), | ||
| try_fus!(wei_from_big_decimal(&amount, self.decimals)), | ||
| try_tx_fus!(wei_from_big_decimal(&amount, self.decimals)), | ||
| time_lock, | ||
| secret_hash, | ||
| taker_addr, | ||
| swap_contract_address, | ||
| ) | ||
| .map_err(TransactionErr::PlainError) | ||
| .map(TransactionEnum::from), | ||
| ) | ||
| } | ||
|
|
@@ -727,18 +729,19 @@ impl SwapOps for EthCoin { | |
| amount: BigDecimal, | ||
| swap_contract_address: &Option<BytesJson>, | ||
| ) -> TransactionFut { | ||
| let maker_addr = try_fus!(addr_from_raw_pubkey(maker_pub)); | ||
| let swap_contract_address = try_fus!(swap_contract_address.try_to_address()); | ||
| let maker_addr = try_tx_fus!(addr_from_raw_pubkey(maker_pub)); | ||
| let swap_contract_address = try_tx_fus!(swap_contract_address.try_to_address()); | ||
|
|
||
| Box::new( | ||
| self.send_hash_time_locked_payment( | ||
|
sergeyboyko0791 marked this conversation as resolved.
|
||
| self.etomic_swap_id(time_lock, secret_hash), | ||
| try_fus!(wei_from_big_decimal(&amount, self.decimals)), | ||
| try_tx_fus!(wei_from_big_decimal(&amount, self.decimals)), | ||
| time_lock, | ||
| secret_hash, | ||
| maker_addr, | ||
| swap_contract_address, | ||
| ) | ||
| .map_err(TransactionErr::PlainError) | ||
| .map(TransactionEnum::from), | ||
| ) | ||
| } | ||
|
|
@@ -752,12 +755,13 @@ impl SwapOps for EthCoin { | |
| _htlc_privkey: &[u8], | ||
| swap_contract_address: &Option<BytesJson>, | ||
| ) -> TransactionFut { | ||
| let tx: UnverifiedTransaction = try_fus!(rlp::decode(taker_payment_tx)); | ||
| let signed = try_fus!(SignedEthTx::new(tx)); | ||
| let swap_contract_address = try_fus!(swap_contract_address.try_to_address()); | ||
| let tx: UnverifiedTransaction = try_tx_fus!(rlp::decode(taker_payment_tx)); | ||
| let signed = try_tx_fus!(SignedEthTx::new(tx)); | ||
| let swap_contract_address = try_tx_fus!(swap_contract_address.try_to_address()); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you think, should we return
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should, why not if we can just return it right? |
||
|
|
||
| Box::new( | ||
| self.spend_hash_time_locked_payment(signed, swap_contract_address, secret) | ||
| .map_err(TransactionErr::PlainError) | ||
| .map(TransactionEnum::from), | ||
| ) | ||
| } | ||
|
|
@@ -771,11 +775,12 @@ impl SwapOps for EthCoin { | |
| _htlc_privkey: &[u8], | ||
| swap_contract_address: &Option<BytesJson>, | ||
| ) -> TransactionFut { | ||
| let tx: UnverifiedTransaction = try_fus!(rlp::decode(maker_payment_tx)); | ||
| let signed = try_fus!(SignedEthTx::new(tx)); | ||
| let swap_contract_address = try_fus!(swap_contract_address.try_to_address()); | ||
| let tx: UnverifiedTransaction = try_tx_fus!(rlp::decode(maker_payment_tx)); | ||
| let signed = try_tx_fus!(SignedEthTx::new(tx)); | ||
| let swap_contract_address = try_tx_fus!(swap_contract_address.try_to_address()); | ||
| Box::new( | ||
| self.spend_hash_time_locked_payment(signed, swap_contract_address, secret) | ||
| .map_err(TransactionErr::PlainError) | ||
| .map(TransactionEnum::from), | ||
| ) | ||
| } | ||
|
|
@@ -789,12 +794,13 @@ impl SwapOps for EthCoin { | |
| _htlc_privkey: &[u8], | ||
| swap_contract_address: &Option<BytesJson>, | ||
| ) -> TransactionFut { | ||
| let tx: UnverifiedTransaction = try_fus!(rlp::decode(taker_payment_tx)); | ||
| let signed = try_fus!(SignedEthTx::new(tx)); | ||
| let swap_contract_address = try_fus!(swap_contract_address.try_to_address()); | ||
| let tx: UnverifiedTransaction = try_tx_fus!(rlp::decode(taker_payment_tx)); | ||
| let signed = try_tx_fus!(SignedEthTx::new(tx)); | ||
| let swap_contract_address = try_tx_fus!(swap_contract_address.try_to_address()); | ||
|
|
||
| Box::new( | ||
| self.refund_hash_time_locked_payment(swap_contract_address, signed) | ||
|
sergeyboyko0791 marked this conversation as resolved.
|
||
| .map_err(TransactionErr::PlainError) | ||
| .map(TransactionEnum::from), | ||
| ) | ||
| } | ||
|
|
@@ -808,12 +814,13 @@ impl SwapOps for EthCoin { | |
| _htlc_privkey: &[u8], | ||
| swap_contract_address: &Option<BytesJson>, | ||
| ) -> TransactionFut { | ||
| let tx: UnverifiedTransaction = try_fus!(rlp::decode(maker_payment_tx)); | ||
| let signed = try_fus!(SignedEthTx::new(tx)); | ||
| let swap_contract_address = try_fus!(swap_contract_address.try_to_address()); | ||
| let tx: UnverifiedTransaction = try_tx_fus!(rlp::decode(maker_payment_tx)); | ||
| let signed = try_tx_fus!(SignedEthTx::new(tx)); | ||
| let swap_contract_address = try_tx_fus!(swap_contract_address.try_to_address()); | ||
|
|
||
| Box::new( | ||
| self.refund_hash_time_locked_payment(swap_contract_address, signed) | ||
| .map_err(TransactionErr::PlainError) | ||
| .map(TransactionEnum::from), | ||
| ) | ||
| } | ||
|
|
@@ -1138,6 +1145,16 @@ impl MarketCoinOps for EthCoin { | |
| ) | ||
| } | ||
|
|
||
| fn send_raw_tx_bytes(&self, tx: &[u8]) -> Box<dyn Future<Item = String, Error = String> + Send> { | ||
| Box::new( | ||
| self.web3 | ||
| .eth() | ||
| .send_raw_transaction(tx.into()) | ||
| .map(|res| format!("{:02x}", res)) | ||
| .map_err(|e| ERRL!("{}", e)), | ||
| ) | ||
| } | ||
|
|
||
| fn wait_for_confirmations( | ||
| &self, | ||
| tx: &[u8], | ||
|
|
@@ -1215,17 +1232,17 @@ impl MarketCoinOps for EthCoin { | |
| from_block: u64, | ||
| swap_contract_address: &Option<BytesJson>, | ||
| ) -> TransactionFut { | ||
| let unverified: UnverifiedTransaction = try_fus!(rlp::decode(tx_bytes)); | ||
| let tx = try_fus!(SignedEthTx::new(unverified)); | ||
| let swap_contract_address = try_fus!(swap_contract_address.try_to_address()); | ||
| let unverified: UnverifiedTransaction = try_tx_fus!(rlp::decode(tx_bytes)); | ||
| let tx = try_tx_fus!(SignedEthTx::new(unverified)); | ||
| let swap_contract_address = try_tx_fus!(swap_contract_address.try_to_address()); | ||
|
|
||
| let func_name = match self.coin_type { | ||
| EthCoinType::Eth => "ethPayment", | ||
| EthCoinType::Erc20 { .. } => "erc20Payment", | ||
| }; | ||
|
|
||
| let payment_func = try_fus!(SWAP_CONTRACT.function(func_name)); | ||
| let decoded = try_fus!(payment_func.decode_input(&tx.data)); | ||
| let payment_func = try_tx_fus!(SWAP_CONTRACT.function(func_name)); | ||
| let decoded = try_tx_fus!(payment_func.decode_input(&tx.data)); | ||
| let id = match &decoded[0] { | ||
| Token::FixedBytes(bytes) => bytes.clone(), | ||
| _ => panic!(), | ||
|
|
@@ -1280,15 +1297,15 @@ impl MarketCoinOps for EthCoin { | |
| }, | ||
| }; | ||
|
|
||
| return Ok(TransactionEnum::from(try_s!(signed_tx_from_web3_tx(transaction)))); | ||
| return Ok(TransactionEnum::from(try_tx_s!(signed_tx_from_web3_tx(transaction)))); | ||
| } | ||
| } | ||
|
|
||
| if now_ms() / 1000 > wait_until { | ||
| return ERR!( | ||
| return TX_ERR!( | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems that
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, macros normally have snake_case naming convention, but here we are providing a compatibility for a macro that is already exists. We have to change all of them to avoid confusion(which we will do for #1247 ). |
||
| "Waited too long until {} for transaction {:?} to be spent ", | ||
| wait_until, | ||
| tx | ||
| tx, | ||
| ); | ||
| } | ||
| Timer::sleep(5.).await; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -97,6 +97,43 @@ macro_rules! try_f { | |
| }; | ||
| } | ||
|
|
||
| /// `TransactionErr:PlainError` compatible `try_fus` macro. | ||
| macro_rules! try_tx_fus { | ||
| ($e: expr) => { | ||
| match $e { | ||
| Ok(ok) => ok, | ||
| Err(err) => { | ||
| return Box::new(futures01::future::err(crate::TransactionErr::PlainError(ERRL!( | ||
| "{:?}", err | ||
| )))) | ||
| }, | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| /// `TransactionErr:PlainError` compatible `try_s` macro. | ||
| macro_rules! try_tx_s { | ||
| ($e: expr) => { | ||
| match $e { | ||
| Ok(ok) => ok, | ||
| Err(err) => { | ||
| return Err(crate::TransactionErr::PlainError(format!( | ||
| "{}:{}] {:?}", | ||
| file!(), | ||
| line!(), | ||
| err | ||
| ))) | ||
| }, | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| /// `TransactionErr:PlainError` compatible `ERR` macro. | ||
| macro_rules! TX_ERR { | ||
| ($format: expr, $($args: tt)+) => { Err(crate::TransactionErr::PlainError((ERRL!($format, $($args)+)))) }; | ||
| ($format: expr) => { Err(crate::TransactionErr::PlainError(ERRL!($format))) } | ||
| } | ||
|
|
||
| pub mod coin_balance; | ||
| #[doc(hidden)] | ||
| #[cfg(test)] | ||
|
|
@@ -276,7 +313,36 @@ impl Deref for TransactionEnum { | |
| } | ||
| } | ||
|
|
||
| pub type TransactionFut = Box<dyn Future<Item = TransactionEnum, Error = String> + Send>; | ||
| #[derive(Debug, Clone)] | ||
| #[allow(clippy::large_enum_variant)] | ||
| pub enum TransactionErr { | ||
| /// Keeps transactions while throwing errors. | ||
| TxRecoverableError(TransactionEnum, String), | ||
| /// Simply for plain error messages. | ||
| PlainError(String), | ||
| } | ||
|
|
||
| impl TransactionErr { | ||
| /// Returns transaction if the error includes it. | ||
| #[inline] | ||
| pub fn get_tx(&self) -> Option<TransactionEnum> { | ||
| match self { | ||
| TransactionErr::TxRecoverableError(tx, _) => Some(tx.clone()), | ||
| _ => None, | ||
| } | ||
| } | ||
|
|
||
| #[inline] | ||
| /// Returns plain text part of error. | ||
| pub fn get_plain_text_format(&self) -> String { | ||
| match self { | ||
| TransactionErr::TxRecoverableError(_, err) => err.to_string(), | ||
| TransactionErr::PlainError(err) => err.to_string(), | ||
| } | ||
| } | ||
| } | ||
|
|
||
| pub type TransactionFut = Box<dyn Future<Item = TransactionEnum, Error = TransactionErr> + Send>; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please consider this comment? #1258 (comment)
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think both ways are fine. Declaring on top of the module or just keep them close to it's couples. But, have to apply only one of them in the project, otherwise it will complicate things more. @artemii235 which way we should follow? The choice will effect all the project (either all the types will move to the top, or will move to it's couple structs/functions). |
||
|
|
||
| #[derive(Debug, PartialEq)] | ||
| pub enum FoundSwapTxSpend { | ||
|
|
@@ -473,6 +539,9 @@ pub trait MarketCoinOps { | |
| /// Receives raw transaction bytes in hexadecimal format as input and returns tx hash in hexadecimal format | ||
| fn send_raw_tx(&self, tx: &str) -> Box<dyn Future<Item = String, Error = String> + Send>; | ||
|
|
||
| /// Receives raw transaction bytes as input and returns tx hash in hexadecimal format | ||
| fn send_raw_tx_bytes(&self, tx: &[u8]) -> Box<dyn Future<Item = String, Error = String> + Send>; | ||
|
|
||
| fn wait_for_confirmations( | ||
| &self, | ||
| tx: &[u8], | ||
|
|
@@ -735,7 +804,7 @@ impl Default for TransactionType { | |
| /// Transaction details | ||
| #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] | ||
| pub struct TransactionDetails { | ||
| /// Raw bytes of signed transaction in hexadecimal string, this should be sent as is to send_raw_transaction RPC to broadcast the transaction | ||
| /// Raw bytes of signed transaction, this should be sent as is to `send_raw_transaction_bytes` RPC to broadcast the transaction | ||
| pub tx_hex: BytesJson, | ||
| /// Transaction hash in hexadecimal format | ||
| tx_hash: String, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EthCoin::send_to_addressshould returnTransactionErr::TxRecoverableError. Please look at thesign_and_send_transaction_implfunction:https://github.com/KomodoPlatform/atomicDEX-API/blob/c23b1f7bb2941b51297709aee3ac3c46f5370c6f/mm2src/coins/eth.rs#L1382