From f6a0fc1e44d48185402274cf988ff2410eaf44dc Mon Sep 17 00:00:00 2001 From: Ivan Frolov Date: Mon, 23 Dec 2024 19:48:24 -0500 Subject: [PATCH] fix: wait until unknown status `RpcBroadcastTxAsyncRequest` which is used in `change` method always immediately returns a transaction hash and it's to avoid an extra check on relayer's side I rewrote all methods to wait until any transaction status --- .../src/near_bridge_client.rs | 316 ++++++++++-------- .../eth-connector/src/eth_connector.rs | 29 +- .../connectors/fast-bridge/src/fast_bridge.rs | 43 ++- .../nep141-connector/src/nep141_connector.rs | 57 ++-- .../near-rpc-client/src/near_rpc_client.rs | 138 ++++---- 5 files changed, 331 insertions(+), 252 deletions(-) diff --git a/bridge-sdk/bridge-clients/near-bridge-client/src/near_bridge_client.rs b/bridge-sdk/bridge-clients/near-bridge-client/src/near_bridge_client.rs index 2723391..c6c1f5d 100644 --- a/bridge-sdk/bridge-clients/near-bridge-client/src/near_bridge_client.rs +++ b/bridge-sdk/bridge-clients/near-bridge-client/src/near_bridge_client.rs @@ -5,6 +5,7 @@ use derive_builder::Builder; use near_contract_standards::storage_management::StorageBalance; use near_crypto::SecretKey; use near_primitives::{hash::CryptoHash, types::AccountId}; +use near_rpc_client::{ChangeRequest, ViewRequest}; use near_token::NearToken; use omni_types::{ locker_args::{BindTokenArgs, ClaimFeeArgs, DeployTokenArgs, FinTransferArgs}, @@ -60,11 +61,13 @@ impl NearBridgeClient { let response = near_rpc_client::view( endpoint, - token_id, - "get_token_id".to_string(), - serde_json::json!({ - "address": token_address - }), + ViewRequest { + contract_account_id: token_id, + method_name: "get_token_id".to_string(), + args: serde_json::json!({ + "address": token_address + }), + }, ) .await?; @@ -79,11 +82,13 @@ impl NearBridgeClient { let response = near_rpc_client::view( endpoint, - token_id, - "get_native_token_id".to_string(), - serde_json::json!({ - "chain": origin_chain - }), + ViewRequest { + contract_account_id: token_id, + method_name: "get_native_token_id".to_string(), + args: serde_json::json!({ + "chain": origin_chain + }), + }, ) .await?; @@ -101,11 +106,13 @@ impl NearBridgeClient { let response = near_rpc_client::view( endpoint, - token_id, - "storage_balance_of".to_string(), - serde_json::json!({ - "account_id": account_id - }), + ViewRequest { + contract_account_id: token_id, + method_name: "storage_balance_of".to_string(), + args: serde_json::json!({ + "account_id": account_id + }), + }, ) .await?; @@ -120,13 +127,16 @@ impl NearBridgeClient { let response = near_rpc_client::view( endpoint, - token_locker_id, - "required_balance_for_account".to_string(), - serde_json::Value::Null, + ViewRequest { + contract_account_id: token_locker_id, + method_name: "required_balance_for_account".to_string(), + args: serde_json::Value::Null, + }, ) .await?; let required_balance: NearToken = serde_json::from_slice(&response)?; + Ok(required_balance.as_yoctonear()) } @@ -139,9 +149,11 @@ impl NearBridgeClient { let response = near_rpc_client::view( endpoint, - token_id.clone(), - "storage_balance_bounds".to_string(), - serde_json::Value::Null, + ViewRequest { + contract_account_id: token_id.clone(), + method_name: "storage_balance_bounds".to_string(), + args: serde_json::Value::Null, + }, ) .await?; @@ -166,18 +178,21 @@ impl NearBridgeClient { let endpoint = self.endpoint()?; let token_locker = self.token_locker_id_as_str()?; - let tx_hash = near_rpc_client::change( + let tx_hash = near_rpc_client::change_and_wait( endpoint, - self.signer()?, - token_id, - "storage_deposit".to_string(), - serde_json::json!({ - "account_id": token_locker - }) - .to_string() - .into_bytes(), - STORAGE_DEPOSIT_GAS, - amount, + ChangeRequest { + signer: self.signer()?, + receiver_id: token_id, + method_name: "storage_deposit".to_string(), + args: serde_json::json!({ + "account_id": token_locker + }) + .to_string() + .into_bytes(), + gas: STORAGE_DEPOSIT_GAS, + deposit: amount, + }, + near_primitives::views::TxExecutionStatus::Executed, ) .await?; @@ -193,23 +208,26 @@ impl NearBridgeClient { let endpoint = self.endpoint()?; let token_locker_id = self.token_locker_id_as_str()?; - let tx_hash = near_rpc_client::change( + let tx_hash = near_rpc_client::change_and_wait( endpoint, - self.signer()?, - token_locker_id.to_string(), - "storage_deposit".to_string(), - json!({ - "account_id": None:: - }) - .to_string() - .into_bytes(), - STORAGE_DEPOSIT_GAS, - amount, + ChangeRequest { + signer: self.signer()?, + receiver_id: token_locker_id.to_string(), + method_name: "storage_deposit".to_string(), + args: json!({ + "account_id": None:: + }) + .to_string() + .into_bytes(), + gas: STORAGE_DEPOSIT_GAS, + deposit: amount, + }, + near_primitives::views::TxExecutionStatus::Executed, ) .await?; tracing::info!( - tx_hash = format!("{:?}", tx_hash.to_string()), + tx_hash = tx_hash.to_string(), "Sent storage deposit transaction" ); @@ -221,18 +239,21 @@ impl NearBridgeClient { pub async fn log_token_metadata(&self, token_id: String) -> Result { let endpoint = self.endpoint()?; - let tx_hash = near_rpc_client::change( + let tx_hash = near_rpc_client::change_and_wait( endpoint, - self.signer()?, - self.token_locker_id_as_str()?.to_string(), - "log_metadata".to_string(), - serde_json::json!({ - "token_id": token_id - }) - .to_string() - .into_bytes(), - LOG_METADATA_GAS, - LOG_METADATA_DEPOSIT, + ChangeRequest { + signer: self.signer()?, + receiver_id: self.token_locker_id_as_str()?.to_string(), + method_name: "log_metadata".to_string(), + args: serde_json::json!({ + "token_id": token_id + }) + .to_string() + .into_bytes(), + gas: LOG_METADATA_GAS, + deposit: LOG_METADATA_DEPOSIT, + }, + near_primitives::views::TxExecutionStatus::Executed, ) .await?; @@ -260,19 +281,22 @@ impl NearBridgeClient { prover_args: borsh::to_vec(&prover_args).unwrap(), }; - let tx_hash = near_rpc_client::change( + let tx_hash = near_rpc_client::change_and_wait( endpoint, - self.signer()?, - token_locker_id.to_string(), - "deploy_token".to_string(), - borsh::to_vec(&args).map_err(|_| BridgeSdkError::UnknownError)?, - DEPLOY_TOKEN_WITH_VAA_GAS, - DEPLOY_TOKEN_WITH_VAA_DEPOSIT, + ChangeRequest { + signer: self.signer()?, + receiver_id: token_locker_id.to_string(), + method_name: "deploy_token".to_string(), + args: borsh::to_vec(&args).map_err(|_| BridgeSdkError::UnknownError)?, + gas: DEPLOY_TOKEN_WITH_VAA_GAS, + deposit: DEPLOY_TOKEN_WITH_VAA_DEPOSIT, + }, + near_primitives::views::TxExecutionStatus::Executed, ) .await?; tracing::info!( - tx_hash = format!("{:?}", tx_hash), + tx_hash = tx_hash.to_string(), "Sent deploy token transaction" ); @@ -285,22 +309,21 @@ impl NearBridgeClient { let endpoint = self.endpoint()?; let token_locker_id = self.token_locker_id_as_str()?; - let tx_hash = near_rpc_client::change( + let tx_hash = near_rpc_client::change_and_wait( endpoint, - self.signer()?, - token_locker_id.to_string(), - "bind_token".to_string(), - borsh::to_vec(&args).map_err(|_| BridgeSdkError::UnknownError)?, - BIND_TOKEN_GAS, - BIND_TOKEN_DEPOSIT, + ChangeRequest { + signer: self.signer()?, + receiver_id: token_locker_id.to_string(), + method_name: "bind_token".to_string(), + args: borsh::to_vec(&args).map_err(|_| BridgeSdkError::UnknownError)?, + gas: BIND_TOKEN_GAS, + deposit: BIND_TOKEN_DEPOSIT, + }, + near_primitives::views::TxExecutionStatus::Executed, ) .await?; - tracing::info!( - tx_hash = format!("{:?}", tx_hash), - "Sent bind token transaction" - ); - + tracing::info!(tx_hash = tx_hash.to_string(), "Sent bind token transaction"); Ok(tx_hash) } @@ -314,28 +337,30 @@ impl NearBridgeClient { ) -> Result { let endpoint = self.endpoint()?; - let tx_hash = near_rpc_client::change( + let tx_hash = near_rpc_client::change_and_wait( endpoint, - self.signer()?, - self.token_locker_id_as_str()?.to_string(), - "sign_transfer".to_string(), - serde_json::json!({ - "transfer_id": transfer_id, - "fee_recipient": fee_recipient, - "fee": fee, - }) - .to_string() - .into_bytes(), - SIGN_TRANSFER_GAS, - SIGN_TRANSFER_DEPOSIT, // TODO: make a contract call to signer account to determine the required deposit + ChangeRequest { + signer: self.signer()?, + receiver_id: self.token_locker_id_as_str()?.to_string(), + method_name: "sign_transfer".to_string(), + args: serde_json::json!({ + "transfer_id": transfer_id, + "fee_recipient": fee_recipient, + "fee": fee, + }) + .to_string() + .into_bytes(), + gas: SIGN_TRANSFER_GAS, + deposit: SIGN_TRANSFER_DEPOSIT, // TODO: make a contract call to signer account to determine the required deposit + }, + near_primitives::views::TxExecutionStatus::Included, ) .await?; tracing::info!( - tx_hash = format!("{:?}", tx_hash.to_string()), + tx_hash = tx_hash.to_string(), "Sent sign transfer transaction" ); - Ok(tx_hash) } @@ -350,12 +375,14 @@ impl NearBridgeClient { let response = near_rpc_client::view( endpoint, - token_locker_id, - "required_balance_for_init_transfer".to_string(), - serde_json::json!({ - "recipient": recipient, - "sender": format!("near:{}", sender) - }), + ViewRequest { + contract_account_id: token_locker_id, + method_name: "required_balance_for_init_transfer".to_string(), + args: serde_json::json!({ + "recipient": recipient, + "sender": format!("near:{}", sender) + }), + }, ) .await?; @@ -390,32 +417,31 @@ impl NearBridgeClient { let fee = 0; let native_fee = 0; - let tx_hash = near_rpc_client::change( + let tx_hash = near_rpc_client::change_and_wait( endpoint, - self.signer()?, - token_id, - "ft_transfer_call".to_string(), - serde_json::json!({ - "receiver_id": token_locker, - "amount": amount.to_string(), - "msg": serde_json::json!({ - "recipient": receiver, - "fee": fee, - "native_token_fee": native_fee + ChangeRequest { + signer: self.signer()?, + receiver_id: token_id, + method_name: "ft_transfer_call".to_string(), + args: serde_json::json!({ + "receiver_id": token_locker, + "amount": amount.to_string(), + "msg": serde_json::json!({ + "recipient": receiver, + "fee": fee, + "native_token_fee": native_fee + }) }) - }) - .to_string() - .into_bytes(), - INIT_TRANSFER_GAS, - INIT_TRANSFER_DEPOSIT, + .to_string() + .into_bytes(), + gas: INIT_TRANSFER_GAS, + deposit: INIT_TRANSFER_DEPOSIT, + }, + near_primitives::views::TxExecutionStatus::Executed, ) .await?; - tracing::info!( - tx_hash = format!("{:?}", tx_hash), - "Sent transfer transaction" - ); - + tracing::info!(tx_hash = tx_hash.to_string(), "Sent transfer transaction"); Ok(tx_hash) } @@ -424,22 +450,24 @@ impl NearBridgeClient { pub async fn fin_transfer(&self, args: FinTransferArgs) -> Result { let endpoint = self.endpoint()?; - let tx_hash = near_rpc_client::change( + let tx_hash = near_rpc_client::change_and_wait( endpoint, - self.signer()?, - self.token_locker_id_as_str()?.to_string(), - "fin_transfer".to_string(), - borsh::to_vec(&args).map_err(|_| BridgeSdkError::UnknownError)?, - FIN_TRANSFER_GAS, - FIN_TRANSFER_DEPOSIT, + ChangeRequest { + signer: self.signer()?, + receiver_id: self.token_locker_id_as_str()?.to_string(), + method_name: "fin_transfer".to_string(), + args: borsh::to_vec(&args).map_err(|_| BridgeSdkError::UnknownError)?, + gas: FIN_TRANSFER_GAS, + deposit: FIN_TRANSFER_DEPOSIT, + }, + near_primitives::views::TxExecutionStatus::Included, ) .await?; tracing::info!( - tx_hash = format!("{:?}", tx_hash), + tx_hash = tx_hash.to_string(), "Sent finalize transfer transaction" ); - Ok(tx_hash) } @@ -449,22 +477,21 @@ impl NearBridgeClient { let endpoint = self.endpoint()?; let token_locker_id = self.token_locker_id_as_str()?; - let tx_hash = near_rpc_client::change( + let tx_hash = near_rpc_client::change_and_wait( endpoint, - self.signer()?, - token_locker_id.to_string(), - "claim_fee".to_string(), - borsh::to_vec(&args).map_err(|_| BridgeSdkError::UnknownError)?, - CLAIM_FEE_GAS, - CLAIM_FEE_DEPOSIT, + ChangeRequest { + signer: self.signer()?, + receiver_id: token_locker_id.to_string(), + method_name: "claim_fee".to_string(), + args: borsh::to_vec(&args).map_err(|_| BridgeSdkError::UnknownError)?, + gas: CLAIM_FEE_GAS, + deposit: CLAIM_FEE_DEPOSIT, + }, + near_primitives::views::TxExecutionStatus::Included, ) .await?; - tracing::info!( - tx_hash = format!("{:?}", tx_hash.to_string()), - "Sent claim fee request" - ); - + tracing::info!(tx_hash = tx_hash.to_string(), "Sent claim fee request"); Ok(tx_hash) } @@ -480,9 +507,16 @@ impl NearBridgeClient { Some(id) => id, None => self.account_id()?, }; - let sign_tx = - near_rpc_client::wait_for_tx_final_outcome(transaction_hash, sender_id, endpoint, 30) - .await?; + let tx_hash = near_rpc_client::wait_for_tx( + endpoint, + transaction_hash, + sender_id.clone(), + near_primitives::views::TxExecutionStatus::Executed, + 60, + ) + .await?; + + let sign_tx = near_rpc_client::get_tx_final_outcome(endpoint, tx_hash, sender_id).await?; let transfer_log = sign_tx .receipts_outcome diff --git a/bridge-sdk/connectors/eth-connector/src/eth_connector.rs b/bridge-sdk/connectors/eth-connector/src/eth_connector.rs index 2c6cf02..7ecb856 100644 --- a/bridge-sdk/connectors/eth-connector/src/eth_connector.rs +++ b/bridge-sdk/connectors/eth-connector/src/eth_connector.rs @@ -7,6 +7,7 @@ use near_primitives::{ hash::CryptoHash, types::{AccountId, TransactionOrReceiptId}, }; +use near_rpc_client::ChangeRequest; use sha3::{Digest, Keccak256}; use std::{str::FromStr, sync::Arc}; @@ -111,12 +112,14 @@ impl EthConnector { let tx_hash = near_rpc_client::change( near_endpoint, - self.near_signer()?, - self.eth_connector_account_id()?.to_string(), - "deposit".to_string(), - args, - 300_000_000_000_000, - 0, + ChangeRequest { + method_name: "deposit".to_string(), + receiver_id: self.eth_connector_account_id()?.to_string(), + args, + gas: 300_000_000_000_000, + deposit: 0, + signer: self.near_signer()?, + }, ) .await?; @@ -145,12 +148,14 @@ impl EthConnector { let tx_hash = near_rpc_client::change( near_endpoint, - self.near_signer()?, - eth_connector_account_id, - "withdraw".to_string(), - args, - 300_000_000_000_000, - 1, + ChangeRequest { + method_name: "withdraw".to_string(), + receiver_id: eth_connector_account_id, + args, + gas: 300_000_000_000_000, + deposit: 1, + signer: self.near_signer()?, + }, ) .await?; diff --git a/bridge-sdk/connectors/fast-bridge/src/fast_bridge.rs b/bridge-sdk/connectors/fast-bridge/src/fast_bridge.rs index 853b641..a22d90f 100644 --- a/bridge-sdk/connectors/fast-bridge/src/fast_bridge.rs +++ b/bridge-sdk/connectors/fast-bridge/src/fast_bridge.rs @@ -5,6 +5,7 @@ use derive_builder::Builder; use ethers::prelude::*; use near_crypto::SecretKey; use near_primitives::{hash::CryptoHash, types::AccountId}; +use near_rpc_client::ChangeRequest; use sha3::{Digest, Keccak256}; use std::{str::FromStr, sync::Arc}; @@ -106,12 +107,14 @@ impl FastBridge { let tx_hash = near_rpc_client::change( near_endpoint, - self.near_signer()?, - token_id.to_string(), - "ft_transfer_call".to_string(), - args, - 200_000_000_000_000, - 1, + ChangeRequest { + signer: self.near_signer()?, + receiver_id: fast_bridge_account_id, + method_name: "transfer".to_string(), + args, + gas: 20_000_000_000_000, + deposit: 1, + }, ) .await?; @@ -178,12 +181,14 @@ impl FastBridge { let tx_hash = near_rpc_client::change( near_endpoint, - self.near_signer()?, - self.fast_bridge_account_id()?.to_string(), - "lp_unlock".to_string(), - args, - 120_000_000_000_000, - 0, + ChangeRequest { + signer: self.near_signer()?, + receiver_id: self.fast_bridge_account_id()?.to_string(), + method_name: "lp_unlock".to_string(), + args, + gas: 120_000_000_000_000, + deposit: 0, + }, ) .await?; @@ -222,12 +227,14 @@ impl FastBridge { let tx_hash = near_rpc_client::change( near_endpoint, - self.near_signer()?, - self.fast_bridge_account_id()?.to_string(), - "withdraw".to_string(), - args, - 20_000_000_000_000, - 0, + ChangeRequest { + signer: self.near_signer()?, + receiver_id: self.fast_bridge_account_id()?.to_string(), + method_name: "withdraw".to_string(), + args, + gas: 20_000_000_000_000, + deposit: 0, + }, ) .await?; diff --git a/bridge-sdk/connectors/nep141-connector/src/nep141_connector.rs b/bridge-sdk/connectors/nep141-connector/src/nep141_connector.rs index efd0f2b..bac310b 100644 --- a/bridge-sdk/connectors/nep141-connector/src/nep141_connector.rs +++ b/bridge-sdk/connectors/nep141-connector/src/nep141_connector.rs @@ -7,6 +7,7 @@ use near_primitives::{ hash::CryptoHash, types::{AccountId, TransactionOrReceiptId}, }; +use near_rpc_client::ChangeRequest; use sha3::{Digest, Keccak256}; use std::{str::FromStr, sync::Arc}; @@ -66,12 +67,14 @@ impl Nep141Connector { let tx_id = near_rpc_client::change( near_endpoint, - self.near_signer()?, - self.token_locker_id()?.to_string(), - "log_metadata".to_string(), - args, - 300_000_000_000_000, - 0, + ChangeRequest { + signer: self.near_signer()?, + receiver_id: self.token_locker_id()?.to_string(), + method_name: "log_metadata".to_string(), + args, + gas: 300_000_000_000_000, + deposit: 0, + }, ) .await?; @@ -94,12 +97,14 @@ impl Nep141Connector { let tx_id = near_rpc_client::change( near_endpoint, - self.near_signer()?, - near_token_id, - "storage_deposit".to_string(), - args, - 300_000_000_000_000, - amount, + ChangeRequest { + signer: self.near_signer()?, + receiver_id: near_token_id, + method_name: "storage_deposit".to_string(), + args, + gas: 300_000_000_000_000, + deposit: amount, + }, ) .await?; @@ -177,12 +182,14 @@ impl Nep141Connector { let tx_hash = near_rpc_client::change( near_endpoint, - self.near_signer()?, - near_token_id, - "ft_transfer_call".to_string(), - args, - 300_000_000_000_000, - 1, + ChangeRequest { + signer: self.near_signer()?, + receiver_id: near_token_id, + method_name: "ft_transfer_call".to_string(), + args, + gas: 300_000_000_000_000, + deposit: 1, + }, ) .await?; @@ -316,12 +323,14 @@ impl Nep141Connector { let tx_hash = near_rpc_client::change( near_endpoint, - self.near_signer()?, - self.token_locker_id()?.to_string(), - "withdraw".to_string(), - args, - 300_000_000_000_000, - 60_000_000_000_000_000_000_000, + ChangeRequest { + signer: self.near_signer()?, + receiver_id: self.token_locker_id()?.to_string(), + method_name: "withdraw".to_string(), + args, + gas: 300_000_000_000_000, + deposit: 60_000_000_000_000_000_000_000, + }, ) .await?; diff --git a/bridge-sdk/near-rpc-client/src/near_rpc_client.rs b/bridge-sdk/near-rpc-client/src/near_rpc_client.rs index 85447f4..2c5168c 100644 --- a/bridge-sdk/near-rpc-client/src/near_rpc_client.rs +++ b/bridge-sdk/near-rpc-client/src/near_rpc_client.rs @@ -19,6 +19,23 @@ lazy_static! { ); } +#[derive(Clone)] +pub struct ViewRequest { + pub contract_account_id: AccountId, + pub method_name: String, + pub args: serde_json::Value, +} + +#[derive(Clone)] +pub struct ChangeRequest { + pub signer: near_crypto::InMemorySigner, + pub receiver_id: String, + pub method_name: String, + pub args: Vec, + pub gas: u64, + pub deposit: u128, +} + fn new_near_rpc_client(timeout: Option) -> reqwest::Client { let mut headers = HeaderMap::with_capacity(2); headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json")); @@ -30,19 +47,14 @@ fn new_near_rpc_client(timeout: Option) -> reqwest::Client builder.build().unwrap() } -pub async fn view( - server_addr: &str, - contract_account_id: AccountId, - method_name: String, - args: serde_json::Value, -) -> Result, NearRpcError> { +pub async fn view(server_addr: &str, view_request: ViewRequest) -> Result, NearRpcError> { let client = DEFAULT_CONNECTOR.connect(server_addr); let request = methods::query::RpcQueryRequest { block_reference: BlockReference::Finality(Finality::Final), request: QueryRequest::CallFunction { - account_id: contract_account_id, - method_name, - args: FunctionArgs::from(args.to_string().into_bytes()), + account_id: view_request.contract_account_id, + method_name: view_request.method_name, + args: FunctionArgs::from(view_request.args.to_string().into_bytes()), }, }; @@ -102,19 +114,14 @@ pub async fn get_block( pub async fn change( server_addr: &str, - signer: near_crypto::InMemorySigner, - receiver_id: String, - method_name: String, - args: Vec, - gas: u64, - deposit: u128, + change_request: ChangeRequest, ) -> Result { let client = DEFAULT_CONNECTOR.connect(server_addr); let rpc_request = methods::query::RpcQueryRequest { block_reference: BlockReference::latest(), request: near_primitives::views::QueryRequest::ViewAccessKey { - account_id: signer.account_id.clone(), - public_key: signer.public_key.clone(), + account_id: change_request.signer.account_id.clone(), + public_key: change_request.signer.public_key.clone(), }, }; let access_key_query_response = client.call(rpc_request).await?; @@ -124,60 +131,49 @@ pub async fn change( _ => Err(NearRpcError::NonceError)?, }; let transaction = Transaction { - signer_id: signer.account_id.clone(), - public_key: signer.public_key.clone(), + signer_id: change_request.signer.account_id.clone(), + public_key: change_request.signer.public_key.clone(), nonce: current_nonce + 1, - receiver_id: receiver_id.parse().unwrap(), + receiver_id: change_request.receiver_id.parse().unwrap(), block_hash: access_key_query_response.block_hash, actions: vec![Action::FunctionCall(Box::new(FunctionCallAction { - method_name, - args, - gas, - deposit, + method_name: change_request.method_name, + args: change_request.args, + gas: change_request.gas, + deposit: change_request.deposit, }))], }; let request = methods::broadcast_tx_async::RpcBroadcastTxAsyncRequest { - signed_transaction: transaction.sign(&signer), + signed_transaction: transaction.sign(&change_request.signer), }; Ok(client.call(request).await?) } -pub async fn change_and_wait_for_outcome( +pub async fn change_and_wait( server_addr: &str, - signer: near_crypto::InMemorySigner, - receiver_id: String, - method_name: String, - args: Vec, - gas: u64, - deposit: u128, -) -> Result { - let tx_hash = change( - server_addr, - signer.clone(), - receiver_id, - method_name, - args, - gas, - deposit, - ) - .await?; + change_request: ChangeRequest, + wait_until: near_primitives::views::TxExecutionStatus, +) -> Result { + let tx_hash = change(server_addr, change_request.clone()).await?; - wait_for_tx_final_outcome( - tx_hash, - signer.account_id, + wait_for_tx( server_addr, + tx_hash, + change_request.signer.account_id, + wait_until, DEFAULT_WAIT_FINAL_OUTCOME_TIMEOUT_SEC, ) .await } -pub async fn wait_for_tx_final_outcome( +pub async fn wait_for_tx( + server_addr: &str, hash: CryptoHash, account_id: AccountId, - server_addr: &str, + wait_until: near_primitives::views::TxExecutionStatus, timeout_sec: u64, -) -> Result { +) -> Result { let client = DEFAULT_CONNECTOR.connect(server_addr); let sent_at = time::Instant::now(); let tx_info = TransactionInfo::TransactionId { @@ -189,7 +185,7 @@ pub async fn wait_for_tx_final_outcome( let response = client .call(methods::tx::RpcTransactionStatusRequest { transaction_info: tx_info.clone(), - wait_until: near_primitives::views::TxExecutionStatus::Executed, + wait_until: wait_until.clone(), }) .await; @@ -199,6 +195,7 @@ pub async fn wait_for_tx_final_outcome( } match response { + Ok(_) => return Ok(hash), Err(err) => match err.handler_error() { Some(_err) => { time::sleep(time::Duration::from_secs(2)).await; @@ -206,13 +203,40 @@ pub async fn wait_for_tx_final_outcome( } _ => Err(NearRpcError::RpcTransactionError(err))?, }, - Ok(response) => match response.final_execution_outcome { - None => { - time::sleep(time::Duration::from_secs(2)).await; - continue; - } - Some(outcome) => return Ok(outcome.into_outcome()), - }, } } } + +pub async fn get_tx_final_outcome( + server_addr: &str, + hash: CryptoHash, + account_id: AccountId, +) -> Result { + let client = DEFAULT_CONNECTOR.connect(server_addr); + + let tx_info = TransactionInfo::TransactionId { + tx_hash: hash, + sender_account_id: account_id, + }; + + let response = client + .call(methods::tx::RpcTransactionStatusRequest { + transaction_info: tx_info.clone(), + wait_until: near_primitives::views::TxExecutionStatus::Executed, + }) + .await; + + match response { + Ok(optional_outcome) => { + if let Some(outcome) = optional_outcome.final_execution_outcome { + Ok(outcome.into_outcome()) + } else { + Err(NearRpcError::FinalizationError) + } + } + Err(err) => match err.handler_error() { + Some(_err) => Err(NearRpcError::FinalizationError), + _ => Err(NearRpcError::RpcTransactionError(err)), + }, + } +}