Compare commits

...

2 Commits

Author SHA1 Message Date
Jon Häggblad d057a6ad9e WIP: first broadcast then poll send tx 2022-09-26 15:20:39 +03:00
Jon Häggblad c44d920a68 env qa 2022-09-26 15:20:39 +03:00
6 changed files with 127 additions and 5 deletions
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use crate::nymd::coin::Coin;
use crate::nymd::cosmwasm_client::helpers::{create_pagination, next_page_key};
use crate::nymd::cosmwasm_client::helpers::{create_pagination, next_page_key, CheckResponse};
use crate::nymd::cosmwasm_client::types::{
Account, Code, CodeDetails, Contract, ContractCodeHistoryEntry, ContractCodeId,
SequenceResponse, SimulateResponse,
@@ -203,6 +203,29 @@ pub trait CosmWasmClient: rpc::Client {
Ok(self.tx(id, false).await?)
}
async fn poll_tx(&self, id: tx::Hash) -> Result<TxResponse, NymdError> {
self.poll_tx2(id).await?.check_response()
}
async fn poll_tx2(&self, id: tx::Hash) -> Result<TxResponse, NymdError> {
let start = tokio::time::Instant::now();
loop {
log::debug!("Polling for result of including {id} in a block...");
if tokio::time::Instant::now().duration_since(start) >= self.broadcast_timeout() {
return Err(NymdError::BroadcastTimeout {
hash: id,
timeout: self.broadcast_timeout(),
});
}
if let Ok(poll_res) = self.get_tx(id).await {
return Ok(poll_res);
}
tokio::time::sleep(self.broadcast_polling_rate()).await;
}
}
async fn search_tx(&self, query: Query) -> Result<Vec<TxResponse>, NymdError> {
// according to https://docs.tendermint.com/master/rpc/#/Info/tx_search
// the maximum entries per page is 100 and the default is 30
@@ -294,6 +317,25 @@ pub trait CosmWasmClient: rpc::Client {
}
}
async fn broadcast_tx_skip_poll(
&self,
tx: Transaction,
) -> Result<broadcast::tx_sync::Response, NymdError> {
let broadcasted = CosmWasmClient::broadcast_tx_sync(self, tx).await?;
if broadcasted.code.is_err() {
let code_val = broadcasted.code.value();
return Err(NymdError::BroadcastTxErrorDeliverTx {
hash: broadcasted.hash,
height: None,
code: code_val,
raw_log: broadcasted.log.to_string(),
});
}
Ok(broadcasted)
}
async fn get_codes(&self) -> Result<Vec<Code>, NymdError> {
let path = Some("/cosmwasm.wasm.v1.Query/Codes".parse().unwrap());
@@ -395,6 +395,26 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
.check_response()
}
async fn send_tokens_skip_poll(
&self,
sender_address: &AccountId,
recipient_address: &AccountId,
amount: Vec<Coin>,
fee: Fee,
memo: impl Into<String> + Send + 'static,
) -> Result<broadcast::tx_sync::Response, NymdError> {
let send_msg = MsgSend {
from_address: sender_address.clone(),
to_address: recipient_address.clone(),
amount: amount.into_iter().map(Into::into).collect(),
}
.to_any()
.map_err(|_| NymdError::SerializationError("MsgSend".to_owned()))?;
self.sign_and_broadcast_skip_poll(sender_address, vec![send_msg], fee, memo)
.await
}
async fn send_tokens_multiple<I>(
&self,
sender_address: &AccountId,
@@ -667,6 +687,26 @@ pub trait SigningCosmWasmClient: CosmWasmClient {
self.broadcast_tx(tx_bytes.into()).await
}
async fn sign_and_broadcast_skip_poll(
&self,
signer_address: &AccountId,
messages: Vec<Any>,
fee: Fee,
memo: impl Into<String> + Send + 'static,
) -> Result<broadcast::tx_sync::Response, NymdError> {
let memo = memo.into();
let fee = self
.determine_transaction_fee(signer_address, &messages, fee, &memo)
.await?;
let tx_raw = self.sign(signer_address, messages, fee, memo).await?;
let tx_bytes = tx_raw
.to_bytes()
.map_err(|_| NymdError::SerializationError("Tx".to_owned()))?;
self.broadcast_tx_skip_poll(tx_bytes.into()).await
}
fn sign_direct(
&self,
signer_address: &AccountId,
@@ -1,16 +1,19 @@
// Copyright 2021 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
//use crate::nymd::cosmwasm_client::helpers::CheckResponse;
use crate::nymd::cosmwasm_client::signing_client;
use crate::nymd::cosmwasm_client::types::{
Account, ChangeAdminResult, ContractCodeId, ExecuteResult, InstantiateOptions,
InstantiateResult, MigrateResult, SequenceResponse, SimulateResponse, UploadResult,
};
use crate::nymd::error::NymdError;
use crate::nymd::fee::DEFAULT_SIMULATED_GAS_MULTIPLIER;
use crate::nymd::wallet::DirectSecp256k1HdWallet;
use cosmrs::cosmwasm;
use cosmrs::rpc::endpoint::block::Response as BlockResponse;
use cosmrs::rpc::endpoint::broadcast;
use cosmrs::rpc::query::Query;
use cosmrs::rpc::Error as TendermintRpcError;
use cosmrs::rpc::HttpClientUrl;
@@ -468,6 +471,13 @@ impl<C> NymdClient<C> {
self.client.get_tx(id).await
}
pub async fn poll_tx(&self, id: tx::Hash) -> Result<TxResponse, NymdError>
where
C: CosmWasmClient + Sync,
{
self.client.poll_tx(id).await
}
pub async fn search_tx(&self, query: Query) -> Result<Vec<TxResponse>, NymdError>
where
C: CosmWasmClient + Sync,
@@ -530,6 +540,25 @@ impl<C> NymdClient<C> {
.await
}
/// Send funds from one address to another.
/// Same as `send` but immediately returns after broadcasting the transaction, skipping to
/// polling step.
pub async fn send_skip_poll(
&self,
recipient: &AccountId,
amount: Vec<Coin>,
memo: impl Into<String> + Send + 'static,
fee: Option<Fee>,
) -> Result<broadcast::tx_sync::Response, NymdError>
where
C: SigningCosmWasmClient + Sync,
{
let fee = fee.unwrap_or(Fee::Auto(Some(self.simulated_gas_multiplier)));
self.client
.send_tokens_skip_poll(self.address(), recipient, amount, fee, memo)
.await
}
/// Send funds from one address to multiple others
pub async fn send_multiple(
&self,
+2 -1
View File
@@ -9,7 +9,8 @@ MIX_DENOM_DISPLAY=nym
STAKE_DENOM=unyx
STAKE_DENOM_DISPLAY=nyx
DENOMS_EXPONENT=6
MIXNET_CONTRACT_ADDRESS=n1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrsd3qaep
#MIXNET_CONTRACT_ADDRESS=n1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrsd3qaep
MIXNET_CONTRACT_ADDRESS=n1rjzps6qrmdqmf0xz4cn4x4rcmqeqzq6hnzqg4wcvd0r2lyasdq5sepn5s8
VESTING_CONTRACT_ADDRESS=n1xr3rq8yvd7qplsw5yx90ftsr2zdhg4e9z60h5duusgxpv72hud3sjkxkav
BANDWIDTH_CLAIM_CONTRACT_ADDRESS=n19lc9u84cz0yz3fww5283nucc9yvr8gsjmgeul0
COCONUT_BANDWIDTH_CONTRACT_ADDRESS=n1ghd753shjuwexxywmgs4xz7x2q732vcn7ty4yw
+2 -1
View File
@@ -160,7 +160,8 @@ mod qa {
pub(crate) const STAKE_DENOM: DenomDetails = DenomDetails::new("unyx", "nyx", 6);
pub(crate) const MIXNET_CONTRACT_ADDRESS: &str =
"n1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrsd3qaep";
"n1rjzps6qrmdqmf0xz4cn4x4rcmqeqzq6hnzqg4wcvd0r2lyasdq5sepn5s8";
//"n1suhgf5svhu4usrurvxzlgn54ksxmn8gljarjtxqnapv8kjnp4nrsd3qaep";
pub(crate) const VESTING_CONTRACT_ADDRESS: &str =
"n1xr3rq8yvd7qplsw5yx90ftsr2zdhg4e9z60h5duusgxpv72hud3sjkxkav";
pub(crate) const BANDWIDTH_CLAIM_CONTRACT_ADDRESS: &str =
@@ -27,11 +27,20 @@ pub async fn send(
to_address,
fee,
);
let raw_res = guard
// broadcast
let broadcasted = guard
.current_client()?
.nymd
.send(&to_address, vec![amount_base], memo, fee)
.send_skip_poll(&to_address, vec![amount_base], memo, fee)
.await?;
// print tx hash
let tx_hash = broadcasted.hash;
log::info!("{tx_hash}");
// wait for completion
let raw_res = guard.current_client()?.nymd.poll_tx(tx_hash).await?;
log::info!("<<< tx hash = {}", raw_res.hash.to_string());
let res = SendTxResult::new(
raw_res,