|
|
|
@@ -14,12 +14,14 @@
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
|
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
use crate::rpc::Ethereum;
|
|
|
|
|
use crate::types::{
|
|
|
|
|
Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SignedRawTx, SyncState, Transaction,
|
|
|
|
|
TransactionHash, H256, U256,
|
|
|
|
|
use crate::{
|
|
|
|
|
rpc::Ethereum,
|
|
|
|
|
types::{
|
|
|
|
|
Address, Bytes, CallRequest, Header, HeaderWithTransactions, Receipt, SignedRawTx,
|
|
|
|
|
SyncState, Transaction, TransactionHash, H256, U256,
|
|
|
|
|
},
|
|
|
|
|
ConnectionParams, Error, Result,
|
|
|
|
|
};
|
|
|
|
|
use crate::{ConnectionParams, Error, Result};
|
|
|
|
|
|
|
|
|
|
use jsonrpsee_ws_client::{WsClient as RpcClient, WsClientBuilder as RpcClientBuilder};
|
|
|
|
|
use relay_utils::relay_loop::RECONNECT_DELAY;
|
|
|
|
@@ -57,15 +59,17 @@ impl Client {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Try to connect to Ethereum node. Returns Ethereum RPC client if connection has been established
|
|
|
|
|
/// or error otherwise.
|
|
|
|
|
/// Try to connect to Ethereum node. Returns Ethereum RPC client if connection has been
|
|
|
|
|
/// established or error otherwise.
|
|
|
|
|
pub async fn try_connect(params: ConnectionParams) -> Result<Self> {
|
|
|
|
|
let (tokio, client) = Self::build_client(¶ms).await?;
|
|
|
|
|
Ok(Self { tokio, client, params })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Build client to use in connection.
|
|
|
|
|
async fn build_client(params: &ConnectionParams) -> Result<(Arc<tokio::runtime::Runtime>, Arc<RpcClient>)> {
|
|
|
|
|
async fn build_client(
|
|
|
|
|
params: &ConnectionParams,
|
|
|
|
|
) -> Result<(Arc<tokio::runtime::Runtime>, Arc<RpcClient>)> {
|
|
|
|
|
let tokio = tokio::runtime::Runtime::new()?;
|
|
|
|
|
let uri = format!("ws://{}:{}", params.host, params.port);
|
|
|
|
|
let client = tokio
|
|
|
|
@@ -90,13 +94,14 @@ impl Client {
|
|
|
|
|
match Ethereum::syncing(&*client).await? {
|
|
|
|
|
SyncState::NotSyncing => Ok(()),
|
|
|
|
|
SyncState::Syncing(syncing) => {
|
|
|
|
|
let missing_headers = syncing.highest_block.saturating_sub(syncing.current_block);
|
|
|
|
|
let missing_headers =
|
|
|
|
|
syncing.highest_block.saturating_sub(syncing.current_block);
|
|
|
|
|
if missing_headers > MAJOR_SYNC_BLOCKS.into() {
|
|
|
|
|
return Err(Error::ClientNotSynced(missing_headers));
|
|
|
|
|
return Err(Error::ClientNotSynced(missing_headers))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.await
|
|
|
|
@@ -104,21 +109,26 @@ impl Client {
|
|
|
|
|
|
|
|
|
|
/// Estimate gas usage for the given call.
|
|
|
|
|
pub async fn estimate_gas(&self, call_request: CallRequest) -> Result<U256> {
|
|
|
|
|
self.jsonrpsee_execute(move |client| async move { Ok(Ethereum::estimate_gas(&*client, call_request).await?) })
|
|
|
|
|
.await
|
|
|
|
|
self.jsonrpsee_execute(move |client| async move {
|
|
|
|
|
Ok(Ethereum::estimate_gas(&*client, call_request).await?)
|
|
|
|
|
})
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Retrieve number of the best known block from the Ethereum node.
|
|
|
|
|
pub async fn best_block_number(&self) -> Result<u64> {
|
|
|
|
|
self.jsonrpsee_execute(move |client| async move { Ok(Ethereum::block_number(&*client).await?.as_u64()) })
|
|
|
|
|
.await
|
|
|
|
|
self.jsonrpsee_execute(move |client| async move {
|
|
|
|
|
Ok(Ethereum::block_number(&*client).await?.as_u64())
|
|
|
|
|
})
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Retrieve number of the best known block from the Ethereum node.
|
|
|
|
|
pub async fn header_by_number(&self, block_number: u64) -> Result<Header> {
|
|
|
|
|
self.jsonrpsee_execute(move |client| async move {
|
|
|
|
|
let get_full_tx_objects = false;
|
|
|
|
|
let header = Ethereum::get_block_by_number(&*client, block_number, get_full_tx_objects).await?;
|
|
|
|
|
let header =
|
|
|
|
|
Ethereum::get_block_by_number(&*client, block_number, get_full_tx_objects).await?;
|
|
|
|
|
match header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some() {
|
|
|
|
|
true => Ok(header),
|
|
|
|
|
false => Err(Error::IncompleteHeader),
|
|
|
|
@@ -141,19 +151,28 @@ impl Client {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Retrieve block header and its transactions by its number from Ethereum node.
|
|
|
|
|
pub async fn header_by_number_with_transactions(&self, number: u64) -> Result<HeaderWithTransactions> {
|
|
|
|
|
pub async fn header_by_number_with_transactions(
|
|
|
|
|
&self,
|
|
|
|
|
number: u64,
|
|
|
|
|
) -> Result<HeaderWithTransactions> {
|
|
|
|
|
self.jsonrpsee_execute(move |client| async move {
|
|
|
|
|
let get_full_tx_objects = true;
|
|
|
|
|
let header = Ethereum::get_block_by_number_with_transactions(&*client, number, get_full_tx_objects).await?;
|
|
|
|
|
let header = Ethereum::get_block_by_number_with_transactions(
|
|
|
|
|
&*client,
|
|
|
|
|
number,
|
|
|
|
|
get_full_tx_objects,
|
|
|
|
|
)
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some();
|
|
|
|
|
let is_complete_header =
|
|
|
|
|
header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some();
|
|
|
|
|
if !is_complete_header {
|
|
|
|
|
return Err(Error::IncompleteHeader);
|
|
|
|
|
return Err(Error::IncompleteHeader)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some());
|
|
|
|
|
if !is_complete_transactions {
|
|
|
|
|
return Err(Error::IncompleteTransaction);
|
|
|
|
|
return Err(Error::IncompleteTransaction)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(header)
|
|
|
|
@@ -162,19 +181,25 @@ impl Client {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Retrieve block header and its transactions by its hash from Ethereum node.
|
|
|
|
|
pub async fn header_by_hash_with_transactions(&self, hash: H256) -> Result<HeaderWithTransactions> {
|
|
|
|
|
pub async fn header_by_hash_with_transactions(
|
|
|
|
|
&self,
|
|
|
|
|
hash: H256,
|
|
|
|
|
) -> Result<HeaderWithTransactions> {
|
|
|
|
|
self.jsonrpsee_execute(move |client| async move {
|
|
|
|
|
let get_full_tx_objects = true;
|
|
|
|
|
let header = Ethereum::get_block_by_hash_with_transactions(&*client, hash, get_full_tx_objects).await?;
|
|
|
|
|
let header =
|
|
|
|
|
Ethereum::get_block_by_hash_with_transactions(&*client, hash, get_full_tx_objects)
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
let is_complete_header = header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some();
|
|
|
|
|
let is_complete_header =
|
|
|
|
|
header.number.is_some() && header.hash.is_some() && header.logs_bloom.is_some();
|
|
|
|
|
if !is_complete_header {
|
|
|
|
|
return Err(Error::IncompleteHeader);
|
|
|
|
|
return Err(Error::IncompleteHeader)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let is_complete_transactions = header.transactions.iter().all(|tx| tx.raw.is_some());
|
|
|
|
|
if !is_complete_transactions {
|
|
|
|
|
return Err(Error::IncompleteTransaction);
|
|
|
|
|
return Err(Error::IncompleteTransaction)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(header)
|
|
|
|
@@ -184,8 +209,10 @@ impl Client {
|
|
|
|
|
|
|
|
|
|
/// Retrieve transaction by its hash from Ethereum node.
|
|
|
|
|
pub async fn transaction_by_hash(&self, hash: H256) -> Result<Option<Transaction>> {
|
|
|
|
|
self.jsonrpsee_execute(move |client| async move { Ok(Ethereum::transaction_by_hash(&*client, hash).await?) })
|
|
|
|
|
.await
|
|
|
|
|
self.jsonrpsee_execute(move |client| async move {
|
|
|
|
|
Ok(Ethereum::transaction_by_hash(&*client, hash).await?)
|
|
|
|
|
})
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Retrieve transaction receipt by transaction hash.
|
|
|
|
@@ -198,9 +225,9 @@ impl Client {
|
|
|
|
|
|
|
|
|
|
/// Get the nonce of the given account.
|
|
|
|
|
pub async fn account_nonce(&self, address: Address) -> Result<U256> {
|
|
|
|
|
self.jsonrpsee_execute(
|
|
|
|
|
move |client| async move { Ok(Ethereum::get_transaction_count(&*client, address).await?) },
|
|
|
|
|
)
|
|
|
|
|
self.jsonrpsee_execute(move |client| async move {
|
|
|
|
|
Ok(Ethereum::get_transaction_count(&*client, address).await?)
|
|
|
|
|
})
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -219,8 +246,10 @@ impl Client {
|
|
|
|
|
|
|
|
|
|
/// Call Ethereum smart contract.
|
|
|
|
|
pub async fn eth_call(&self, call_transaction: CallRequest) -> Result<Bytes> {
|
|
|
|
|
self.jsonrpsee_execute(move |client| async move { Ok(Ethereum::call(&*client, call_transaction).await?) })
|
|
|
|
|
.await
|
|
|
|
|
self.jsonrpsee_execute(move |client| async move {
|
|
|
|
|
Ok(Ethereum::call(&*client, call_transaction).await?)
|
|
|
|
|
})
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Execute jsonrpsee future in tokio context.
|
|
|
|
@@ -231,8 +260,6 @@ impl Client {
|
|
|
|
|
T: Send + 'static,
|
|
|
|
|
{
|
|
|
|
|
let client = self.client.clone();
|
|
|
|
|
self.tokio
|
|
|
|
|
.spawn(async move { make_jsonrpsee_future(client).await })
|
|
|
|
|
.await?
|
|
|
|
|
self.tokio.spawn(async move { make_jsonrpsee_future(client).await }).await?
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|