Skip to content
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

aleph-client: Get tx events #860

Merged
merged 15 commits into from
Jan 13, 2023
2 changes: 1 addition & 1 deletion aleph-client/Cargo.lock

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

2 changes: 1 addition & 1 deletion aleph-client/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "aleph_client"
# TODO bump major version when API stablize
version = "2.7.0"
version = "2.8.0"
edition = "2021"
license = "Apache 2.0"

Expand Down
73 changes: 51 additions & 22 deletions aleph-client/src/connections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use std::{thread::sleep, time::Duration};
use anyhow::anyhow;
use codec::Decode;
use log::info;
use serde::{Deserialize, Serialize};
use subxt::{
blocks::ExtrinsicEvents,
ext::sp_core::Bytes,
metadata::DecodeWithMetadata,
rpc::RpcParams,
Expand All @@ -13,7 +15,8 @@ use subxt::{
};

use crate::{
api, sp_weights::weight_v2::Weight, AccountId, BlockHash, Call, KeyPair, SubxtClient, TxStatus,
api, sp_weights::weight_v2::Weight, AccountId, AlephConfig, BlockHash, Call, KeyPair,
SubxtClient, TxHash, TxStatus,
};

/// Capable of communicating with a live Aleph chain.
Expand Down Expand Up @@ -105,39 +108,55 @@ pub trait ConnectionApi: Sync {
async fn rpc_call<R: Decode>(&self, func_name: String, params: RpcParams) -> anyhow::Result<R>;
}

/// Data regarding submitted transaction.
#[derive(Copy, Clone, Eq, PartialEq, Debug, Deserialize, Serialize)]
pub struct TxInfo {
pub block_hash: BlockHash,
pub tx_hash: TxHash,
}

impl From<ExtrinsicEvents<AlephConfig>> for TxInfo {
fn from(ee: ExtrinsicEvents<AlephConfig>) -> Self {
Self {
block_hash: ee.block_hash(),
tx_hash: ee.extrinsic_hash(),
}
}
}

/// Signed connection should be able to sends transactions to chain
#[async_trait::async_trait]
pub trait SignedConnectionApi: ConnectionApi {
/// Send a transaction to a chain. It waits for a given tx `status`.
/// * `tx` - encoded transaction payload
/// * `status` - a [`TxStatus`] for a tx to wait for
/// # Returns
/// Block hash of block where transaction was put or error
/// Block hash of block where transaction was put together with transaction hash, or error.
/// # Examples
/// ```ignore
/// let tx = api::tx()
/// .balances()
/// .transfer(MultiAddress::Id(dest), amount);
/// send_tx(tx, status).await
/// let tx = api::tx()
/// .balances()
/// .transfer(MultiAddress::Id(dest), amount);
/// send_tx(tx, status).await
/// ```
async fn send_tx<Call: TxPayload + Send + Sync>(
&self,
tx: Call,
status: TxStatus,
) -> anyhow::Result<BlockHash>;
) -> anyhow::Result<TxInfo>;

/// Send a transaction to a chain. It waits for a given tx `status`.
/// * `tx` - encoded transaction payload
/// * `params` - optional tx params e.g. tip
/// * `status` - a [`TxStatus`] of a tx to wait for
/// # Returns
/// Block hash of block where transaction was put or error
/// Block hash of block where transaction was put together with transaction hash, or error.
async fn send_tx_with_params<Call: TxPayload + Send + Sync>(
&self,
tx: Call,
params: BaseExtrinsicParamsBuilder<SubstrateConfig, PlainTip>,
status: TxStatus,
) -> anyhow::Result<BlockHash>;
) -> anyhow::Result<TxInfo>;

/// Returns account id which signs this connection
fn account_id(&self) -> &AccountId;
Expand All @@ -153,14 +172,14 @@ pub trait SignedConnectionApi: ConnectionApi {
#[async_trait::async_trait]
pub trait SudoCall {
/// API for [`sudo_unchecked_weight`](https://paritytech.github.io/substrate/master/pallet_sudo/pallet/enum.Call.html#variant.sudo_unchecked_weight) call.
async fn sudo_unchecked(&self, call: Call, status: TxStatus) -> anyhow::Result<BlockHash>;
async fn sudo_unchecked(&self, call: Call, status: TxStatus) -> anyhow::Result<TxInfo>;
/// API for [`sudo`](https://paritytech.github.io/substrate/master/pallet_sudo/pallet/enum.Call.html#variant.sudo) call.
async fn sudo(&self, call: Call, status: TxStatus) -> anyhow::Result<BlockHash>;
async fn sudo(&self, call: Call, status: TxStatus) -> anyhow::Result<TxInfo>;
}

#[async_trait::async_trait]
impl SudoCall for RootConnection {
async fn sudo_unchecked(&self, call: Call, status: TxStatus) -> anyhow::Result<BlockHash> {
async fn sudo_unchecked(&self, call: Call, status: TxStatus) -> anyhow::Result<TxInfo> {
info!(target: "aleph-client", "sending call as sudo_unchecked {:?}", call);
let sudo = api::tx().sudo().sudo_unchecked_weight(
call,
Expand All @@ -173,7 +192,7 @@ impl SudoCall for RootConnection {
self.as_signed().send_tx(sudo, status).await
}

async fn sudo(&self, call: Call, status: TxStatus) -> anyhow::Result<BlockHash> {
async fn sudo(&self, call: Call, status: TxStatus) -> anyhow::Result<TxInfo> {
info!(target: "aleph-client", "sending call as sudo {:?}", call);
let sudo = api::tx().sudo().sudo(call);

Expand Down Expand Up @@ -263,7 +282,7 @@ impl<S: AsSigned + Sync> SignedConnectionApi for S {
&self,
tx: Call,
status: TxStatus,
) -> anyhow::Result<BlockHash> {
) -> anyhow::Result<TxInfo> {
self.send_tx_with_params(tx, Default::default(), status)
.await
}
Expand All @@ -273,7 +292,7 @@ impl<S: AsSigned + Sync> SignedConnectionApi for S {
tx: Call,
params: BaseExtrinsicParamsBuilder<SubstrateConfig, PlainTip>,
status: TxStatus,
) -> anyhow::Result<BlockHash> {
) -> anyhow::Result<TxInfo> {
if let Some(details) = tx.validation_details() {
info!(target:"aleph-client", "Sending extrinsic {}.{} with params: {:?}", details.pallet_name, details.call_name, params);
}
Expand All @@ -286,15 +305,25 @@ impl<S: AsSigned + Sync> SignedConnectionApi for S {
.await
.map_err(|e| anyhow!("Failed to submit transaction: {:?}", e))?;

// In case of Submitted hash does not mean anything
let hash = match status {
TxStatus::InBlock => progress.wait_for_in_block().await?.block_hash(),
TxStatus::Finalized => progress.wait_for_finalized_success().await?.block_hash(),
TxStatus::Submitted => return Ok(BlockHash::from_low_u64_be(0)),
let info: TxInfo = match status {
TxStatus::InBlock => progress
.wait_for_in_block()
.await?
.wait_for_success()
.await?
.into(),
TxStatus::Finalized => progress.wait_for_finalized_success().await?.into(),
// In case of Submitted block hash does not mean anything
TxStatus::Submitted => {
return Ok(TxInfo {
block_hash: Default::default(),
tx_hash: progress.extrinsic_hash(),
})
}
};
info!(target: "aleph-client", "tx included in block {:?}", hash);
info!(target: "aleph-client", "tx with hash {:?} included in block {:?}", info.tx_hash, info.block_hash);

Ok(hash)
Ok(info)
}

fn account_id(&self) -> &AccountId {
Expand Down
6 changes: 4 additions & 2 deletions aleph-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
extern crate core;

pub use contract_transcode;
pub use subxt::ext::sp_core::Pair;
pub use subxt::{blocks::ExtrinsicEvents, ext::sp_core::Pair};
use subxt::{
ext::sp_core::{ed25519, sr25519, H256},
tx::PairSigner,
Expand Down Expand Up @@ -49,8 +49,10 @@ pub type KeyPair = PairSigner<AlephConfig, sr25519::Pair>;
pub type AccountId = subxt::ext::sp_core::crypto::AccountId32;
/// An alias for a client type.
pub type Client = OnlineClient<AlephConfig>;
/// An alias for a hash type.
/// An alias for a block hash type.
pub type BlockHash = H256;
/// An alias for a transaction hash type.
pub type TxHash = H256;

/// An alias for an RPC client type.
pub type SubxtClient = OnlineClient<AlephConfig>;
Expand Down
9 changes: 5 additions & 4 deletions aleph-client/src/pallets/aleph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
pallet_aleph::pallet::Call::set_emergency_finalizer, primitives::app::Public,
sp_core::ed25519::Public as EdPublic,
},
connections::TxInfo,
pallet_aleph::pallet::Call::schedule_finality_version_change,
AccountId, AlephKeyPair, BlockHash,
Call::Aleph,
Expand All @@ -26,7 +27,7 @@ pub trait AlephSudoApi {
&self,
finalizer: AccountId,
status: TxStatus,
) -> anyhow::Result<BlockHash>;
) -> anyhow::Result<TxInfo>;

/// Schedules a finality version change for a future session.
/// * `version` - next version of the finalizer
Expand All @@ -39,7 +40,7 @@ pub trait AlephSudoApi {
version: u32,
session: SessionIndex,
status: TxStatus,
) -> anyhow::Result<BlockHash>;
) -> anyhow::Result<TxInfo>;
}

/// Pallet aleph RPC api.
Expand All @@ -62,7 +63,7 @@ impl AlephSudoApi for RootConnection {
&self,
finalizer: AccountId,
status: TxStatus,
) -> anyhow::Result<BlockHash> {
) -> anyhow::Result<TxInfo> {
let call = Aleph(set_emergency_finalizer {
emergency_finalizer: Public(EdPublic(finalizer.into())),
});
Expand All @@ -74,7 +75,7 @@ impl AlephSudoApi for RootConnection {
version: u32,
session: SessionIndex,
status: TxStatus,
) -> anyhow::Result<BlockHash> {
) -> anyhow::Result<TxInfo> {
let call = Aleph(schedule_finality_version_change {
version_incoming: version,
session,
Expand Down
13 changes: 7 additions & 6 deletions aleph-client/src/pallets/balances.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use subxt::{ext::sp_runtime::MultiAddress, tx::PolkadotExtrinsicParamsBuilder};

use crate::{
aleph_zero::{self, api, api::runtime_types::pallet_balances::BalanceLock},
connections::TxInfo,
pallet_balances::pallet::Call::transfer,
pallets::utility::UtilityApi,
AccountId, BlockHash,
Expand Down Expand Up @@ -44,7 +45,7 @@ pub trait BalanceUserApi {
dest: AccountId,
amount: Balance,
status: TxStatus,
) -> anyhow::Result<BlockHash>;
) -> anyhow::Result<TxInfo>;

/// API for [`transfer`](https://paritytech.github.io/substrate/master/pallet_balances/pallet/struct.Pallet.html#method.transfer) call.
/// Include tip in the tx.
Expand All @@ -54,7 +55,7 @@ pub trait BalanceUserApi {
amount: Balance,
tip: Balance,
status: TxStatus,
) -> anyhow::Result<BlockHash>;
) -> anyhow::Result<TxInfo>;
}

/// Pallet balances logic not directly related to any pallet call.
Expand All @@ -79,7 +80,7 @@ pub trait BalanceUserBatchExtApi {
dest: &[AccountId],
amount: Balance,
status: TxStatus,
) -> anyhow::Result<BlockHash>;
) -> anyhow::Result<TxInfo>;
}

#[async_trait::async_trait]
Expand Down Expand Up @@ -122,7 +123,7 @@ impl<S: SignedConnectionApi> BalanceUserApi for S {
dest: AccountId,
amount: Balance,
status: TxStatus,
) -> anyhow::Result<BlockHash> {
) -> anyhow::Result<TxInfo> {
let tx = api::tx()
.balances()
.transfer(MultiAddress::Id(dest), amount);
Expand All @@ -135,7 +136,7 @@ impl<S: SignedConnectionApi> BalanceUserApi for S {
amount: Balance,
tip: Balance,
status: TxStatus,
) -> anyhow::Result<BlockHash> {
) -> anyhow::Result<TxInfo> {
let tx = api::tx()
.balances()
.transfer(MultiAddress::Id(dest), amount);
Expand All @@ -152,7 +153,7 @@ impl<S: SignedConnectionApi> BalanceUserBatchExtApi for S {
dests: &[AccountId],
amount: Balance,
status: TxStatus,
) -> anyhow::Result<BlockHash> {
) -> anyhow::Result<TxInfo> {
let calls = dests
.iter()
.map(|dest| {
Expand Down
Loading