diff --git a/avail-rust/src/lib.rs b/avail-rust/src/lib.rs index e549bb576..5df9c98fc 100644 --- a/avail-rust/src/lib.rs +++ b/avail-rust/src/lib.rs @@ -32,5 +32,6 @@ pub use primitives::block::{ pub use primitives::kate::{Cell, GDataProof, GRow}; pub use subxt; pub use subxt::config::polkadot::U256; +pub use subxt_signer; pub use utils::utils_raw; pub use utils::FetchTransactionError; diff --git a/avail-rust/src/primitives/block/extrinsics.rs b/avail-rust/src/primitives/block/extrinsics.rs index 107c63a04..c72e90fcf 100644 --- a/avail-rust/src/primitives/block/extrinsics.rs +++ b/avail-rust/src/primitives/block/extrinsics.rs @@ -1,8 +1,9 @@ use super::extrinsics_params::OnlyCodecExtra; use crate::{avail::runtime_types::da_runtime::RuntimeCall, Address, Signature}; -use codec::{Compact, Decode, Error, Input}; -use serde::Deserialize; +use codec::{Compact, Decode, Encode, EncodeLike, Error, Input}; +use serde::{Deserialize, Serialize}; +use std::mem::size_of; use subxt::backend::legacy::rpc_methods::Bytes; pub type SignaturePayload = (Address, Signature, OnlyCodecExtra); @@ -14,7 +15,7 @@ pub type SignaturePayload = (Address, Signature, OnlyCodecExtra); /// the decoding fails. const EXTRINSIC_FORMAT_VERSION: u8 = 4; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct AppUncheckedExtrinsic { /// The signature, address, number of extrinsics have come before from /// the same signer and an era describing the longevity of this transaction, @@ -25,6 +26,18 @@ pub struct AppUncheckedExtrinsic { } impl AppUncheckedExtrinsic { + fn encode_vec_compatible(inner: &[u8]) -> Vec { + let compact_len = codec::Compact::(inner.len() as u32); + + // Allocate the output buffer with the correct length + let mut output = Vec::with_capacity(compact_len.size_hint() + inner.len()); + + compact_len.encode_to(&mut output); + output.extend(inner); + + output + } + pub fn app_id(&self) -> crate::AppId { self.signature .as_ref() @@ -34,6 +47,38 @@ impl AppUncheckedExtrinsic { } } +impl Encode for AppUncheckedExtrinsic { + fn encode(&self) -> Vec { + let mut tmp = Vec::with_capacity(size_of::()); + + // 1 byte version id. + match self.signature.as_ref() { + Some(s) => { + tmp.push(EXTRINSIC_FORMAT_VERSION | 0b1000_0000); + s.encode_to(&mut tmp); + }, + None => { + tmp.push(EXTRINSIC_FORMAT_VERSION & 0b0111_1111); + }, + } + self.function.encode_to(&mut tmp); + + Self::encode_vec_compatible(&tmp) + } +} + +impl EncodeLike for AppUncheckedExtrinsic {} + +impl Serialize for AppUncheckedExtrinsic { + fn serialize(&self, s: S) -> Result + where + S: ::serde::Serializer, + { + let encoded = self.encode(); + sp_core::bytes::serialize(&encoded, s) + } +} + impl Decode for AppUncheckedExtrinsic { fn decode(input: &mut I) -> Result { // This is a little more complicated than usual since the binary format must be compatible diff --git a/avail-rust/src/rpcs.rs b/avail-rust/src/rpcs.rs index aa8f3c737..fd334d6c4 100644 --- a/avail-rust/src/rpcs.rs +++ b/avail-rust/src/rpcs.rs @@ -13,6 +13,7 @@ use subxt::rpc_params; /// Arbitrary properties defined in chain spec as a JSON object pub type Properties = serde_json::map::Map; +#[derive(Clone)] pub struct Rpc { pub client: RpcClient, pub legacy_methods: LegacyRpcMethods, @@ -45,6 +46,7 @@ impl Rpc { } } +#[derive(Clone)] pub struct Payment { client: RpcClient, } @@ -111,6 +113,7 @@ mod tests { } } +#[derive(Clone)] pub struct System { client: RpcClient, } @@ -202,6 +205,7 @@ impl System { } } +#[derive(Clone)] pub struct Chain { client: RpcClient, } @@ -250,6 +254,7 @@ impl Chain { } } +#[derive(Clone)] pub struct Author { client: RpcClient, } @@ -268,6 +273,7 @@ impl Author { } } +#[derive(Clone)] pub struct Kate { client: RpcClient, } diff --git a/avail-rust/src/sdk.rs b/avail-rust/src/sdk.rs index 3181e91f3..756c69432 100644 --- a/avail-rust/src/sdk.rs +++ b/avail-rust/src/sdk.rs @@ -1,5 +1,6 @@ use crate::{rpcs::Rpc, transactions::Transactions, utils::Util, Api}; +#[derive(Clone)] pub struct SDK { pub api: Api, pub tx: Transactions, diff --git a/avail-rust/src/transactions.rs b/avail-rust/src/transactions.rs index b8cc2eb6e..836a5ce51 100644 --- a/avail-rust/src/transactions.rs +++ b/avail-rust/src/transactions.rs @@ -32,7 +32,9 @@ pub struct TransferAllTxSuccess { pub event2: Option, pub events: ExtrinsicEvents, pub tx_hash: BlockHash, + pub tx_index: u32, pub block_hash: BlockHash, + pub block_number: u32, } pub struct TransferAllowDeathTxSuccess { @@ -40,63 +42,81 @@ pub struct TransferAllowDeathTxSuccess { pub event2: Option, pub events: ExtrinsicEvents, pub tx_hash: BlockHash, + pub tx_index: u32, pub block_hash: BlockHash, + pub block_number: u32, } pub struct TransferKeepAliveTxSuccess { pub event: BalancesEvents::Transfer, pub events: ExtrinsicEvents, pub tx_hash: BlockHash, + pub tx_index: u32, pub block_hash: BlockHash, + pub block_number: u32, } pub struct BondTxSuccess { pub event: StakingEvents::Bonded, pub events: ExtrinsicEvents, pub tx_hash: BlockHash, + pub tx_index: u32, pub block_hash: BlockHash, + pub block_number: u32, } pub struct BondExtraTxSuccess { pub event: StakingEvents::Bonded, pub events: ExtrinsicEvents, pub tx_hash: BlockHash, + pub tx_index: u32, pub block_hash: BlockHash, + pub block_number: u32, } pub struct ChillTxSuccess { pub event: Option, pub events: ExtrinsicEvents, pub tx_hash: BlockHash, + pub tx_index: u32, pub block_hash: BlockHash, + pub block_number: u32, } pub struct ChillOtherTxSuccess { pub event: StakingEvents::Chilled, pub events: ExtrinsicEvents, pub tx_hash: BlockHash, + pub tx_index: u32, pub block_hash: BlockHash, + pub block_number: u32, } pub struct NominateTxSuccess { pub events: ExtrinsicEvents, pub tx_data: transaction_data::staking::Nominate, pub tx_hash: BlockHash, + pub tx_index: u32, pub block_hash: BlockHash, + pub block_number: u32, } pub struct UnbondTxSuccess { pub event: StakingEvents::Unbonded, pub events: ExtrinsicEvents, pub tx_hash: BlockHash, + pub tx_index: u32, pub block_hash: BlockHash, + pub block_number: u32, } pub struct ValidateTxSuccess { pub event: StakingEvents::ValidatorPrefsSet, pub events: ExtrinsicEvents, pub tx_hash: BlockHash, + pub tx_index: u32, pub block_hash: BlockHash, + pub block_number: u32, } pub struct SubmitDataTxSuccess { @@ -104,37 +124,48 @@ pub struct SubmitDataTxSuccess { pub events: ExtrinsicEvents, pub tx_data: transaction_data::data_availability::SubmitData, pub tx_hash: BlockHash, + pub tx_index: u32, pub block_hash: BlockHash, + pub block_number: u32, } pub struct CreateApplicationKeyTxSuccess { pub event: DataAvailabilityEvents::ApplicationKeyCreated, pub events: ExtrinsicEvents, pub tx_hash: BlockHash, + pub tx_index: u32, pub block_hash: BlockHash, + pub block_number: u32, } pub struct SetApplicationKeyTxSuccess { pub event: DataAvailabilityEvents::ApplicationKeySet, pub events: ExtrinsicEvents, pub tx_hash: BlockHash, + pub tx_index: u32, pub block_hash: BlockHash, + pub block_number: u32, } pub struct SubmitBlockLengthProposalTxSuccess { pub event: DataAvailabilityEvents::BlockLengthProposalSubmitted, pub events: ExtrinsicEvents, pub tx_hash: BlockHash, + pub tx_index: u32, pub block_hash: BlockHash, + pub block_number: u32, } pub struct SetSubmitDataFeeModifierTxSuccess { pub event: DataAvailabilityEvents::SubmitDataFeeModifierSet, pub events: ExtrinsicEvents, pub tx_hash: BlockHash, + pub tx_index: u32, pub block_hash: BlockHash, + pub block_number: u32, } +#[derive(Clone)] pub struct Transactions { pub balances: Balances, pub staking: Staking, @@ -147,20 +178,22 @@ impl Transactions { let blocks = api.blocks(); Self { - balances: Balances::new(tx.clone()), + balances: Balances::new(tx.clone(), blocks.clone()), staking: Staking::new(tx.clone(), blocks.clone()), data_availability: DataAvailability::new(tx.clone(), blocks), } } } +#[derive(Clone)] pub struct Balances { api: TxApi, + blocks: AvailBlocksClient, } impl Balances { - pub fn new(api: TxApi) -> Self { - Self { api } + pub fn new(api: TxApi, blocks: AvailBlocksClient) -> Self { + Self { api, blocks } } pub async fn transfer_all( @@ -203,12 +236,24 @@ impl Balances { let event2 = events.find_first::(); let event2 = event2.ok().flatten(); + let tx_hash = tx_in_block.extrinsic_hash(); + let tx_index = events.extrinsic_index(); + let block_hash = tx_in_block.block_hash(); + let block_number = self + .blocks + .at(block_hash) + .await + .map_err(|e| e.to_string())? + .number(); + Ok(TransferAllTxSuccess { event, event2, events, - tx_hash: tx_in_block.extrinsic_hash(), - block_hash: tx_in_block.block_hash(), + tx_hash, + tx_index, + block_hash, + block_number, }) } @@ -254,12 +299,24 @@ impl Balances { let event2 = events.find_first::(); let event2 = event2.ok().flatten(); + let tx_hash = tx_in_block.extrinsic_hash(); + let tx_index = events.extrinsic_index(); + let block_hash = tx_in_block.block_hash(); + let block_number = self + .blocks + .at(block_hash) + .await + .map_err(|e| e.to_string())? + .number(); + Ok(TransferAllowDeathTxSuccess { event, event2, events, - tx_hash: tx_in_block.extrinsic_hash(), - block_hash: tx_in_block.block_hash(), + tx_hash, + tx_index, + block_hash, + block_number, }) } @@ -302,15 +359,28 @@ impl Balances { return Err(String::from("Failed to find Transfer event")); }; + let tx_hash = tx_in_block.extrinsic_hash(); + let tx_index = events.extrinsic_index(); + let block_hash = tx_in_block.block_hash(); + let block_number = self + .blocks + .at(block_hash) + .await + .map_err(|e| e.to_string())? + .number(); + Ok(TransferKeepAliveTxSuccess { event, events, - tx_hash: tx_in_block.extrinsic_hash(), - block_hash: tx_in_block.block_hash(), + tx_hash, + tx_index, + block_hash, + block_number, }) } } +#[derive(Clone)] pub struct Staking { api: TxApi, blocks: AvailBlocksClient, @@ -353,11 +423,23 @@ impl Staking { return Err(String::from("Failed to find Bonded event")); }; + let tx_hash = tx_in_block.extrinsic_hash(); + let tx_index = events.extrinsic_index(); + let block_hash = tx_in_block.block_hash(); + let block_number = self + .blocks + .at(block_hash) + .await + .map_err(|e| e.to_string())? + .number(); + Ok(BondTxSuccess { event, events, - tx_hash: tx_in_block.extrinsic_hash(), - block_hash: tx_in_block.block_hash(), + tx_hash, + tx_index, + block_hash, + block_number, }) } @@ -392,11 +474,23 @@ impl Staking { return Err(String::from("Failed to find Bonded event")); }; + let tx_hash = tx_in_block.extrinsic_hash(); + let tx_index = events.extrinsic_index(); + let block_hash = tx_in_block.block_hash(); + let block_number = self + .blocks + .at(block_hash) + .await + .map_err(|e| e.to_string())? + .number(); + Ok(BondExtraTxSuccess { event, events, - tx_hash: tx_in_block.extrinsic_hash(), - block_hash: tx_in_block.block_hash(), + tx_hash, + tx_index, + block_hash, + block_number, }) } @@ -427,11 +521,23 @@ impl Staking { let event = events.find_first::().ok().flatten(); + let tx_hash = tx_in_block.extrinsic_hash(); + let tx_index = events.extrinsic_index(); + let block_hash = tx_in_block.block_hash(); + let block_number = self + .blocks + .at(block_hash) + .await + .map_err(|e| e.to_string())? + .number(); + Ok(ChillTxSuccess { event, events, - tx_hash: tx_in_block.extrinsic_hash(), - block_hash: tx_in_block.block_hash(), + tx_hash, + tx_index, + block_hash, + block_number, }) } @@ -471,11 +577,23 @@ impl Staking { return Err(String::from("Failed to find Chilled event")); }; + let tx_hash = tx_in_block.extrinsic_hash(); + let tx_index = events.extrinsic_index(); + let block_hash = tx_in_block.block_hash(); + let block_number = self + .blocks + .at(block_hash) + .await + .map_err(|e| e.to_string())? + .number(); + Ok(ChillOtherTxSuccess { event, events, - tx_hash: tx_in_block.extrinsic_hash(), - block_hash: tx_in_block.block_hash(), + tx_hash, + tx_index, + block_hash, + block_number, }) } @@ -517,11 +635,23 @@ impl Staking { let tx_data = transaction_data::staking::Nominate::new(block_hash, tx_hash, &self.blocks).await?; + let tx_hash = tx_in_block.extrinsic_hash(); + let tx_index = events.extrinsic_index(); + let block_hash = tx_in_block.block_hash(); + let block_number = self + .blocks + .at(block_hash) + .await + .map_err(|e| e.to_string())? + .number(); + Ok(NominateTxSuccess { events, tx_data, tx_hash, + tx_index, block_hash, + block_number, }) } @@ -556,11 +686,23 @@ impl Staking { return Err(String::from("Failed to find Unbonded event")); }; + let tx_hash = tx_in_block.extrinsic_hash(); + let tx_index = events.extrinsic_index(); + let block_hash = tx_in_block.block_hash(); + let block_number = self + .blocks + .at(block_hash) + .await + .map_err(|e| e.to_string())? + .number(); + Ok(UnbondTxSuccess { event, events, - tx_hash: tx_in_block.extrinsic_hash(), - block_hash: tx_in_block.block_hash(), + tx_hash, + tx_index, + block_hash, + block_number, }) } @@ -606,15 +748,28 @@ impl Staking { return Err(String::from("Failed to find ValidatorPrefsSet event")); }; + let tx_hash = tx_in_block.extrinsic_hash(); + let tx_index = events.extrinsic_index(); + let block_hash = tx_in_block.block_hash(); + let block_number = self + .blocks + .at(block_hash) + .await + .map_err(|e| e.to_string())? + .number(); + Ok(ValidateTxSuccess { event, events, - tx_hash: tx_in_block.extrinsic_hash(), - block_hash: tx_in_block.block_hash(), + tx_hash, + tx_index, + block_hash, + block_number, }) } } +#[derive(Clone)] pub struct DataAvailability { api: TxApi, blocks: AvailBlocksClient, @@ -662,12 +817,24 @@ impl DataAvailability { transaction_data::data_availability::SubmitData::new(block_hash, tx_hash, &self.blocks) .await?; + let tx_hash = tx_in_block.extrinsic_hash(); + let tx_index = events.extrinsic_index(); + let block_hash = tx_in_block.block_hash(); + let block_number = self + .blocks + .at(block_hash) + .await + .map_err(|e| e.to_string())? + .number(); + Ok(SubmitDataTxSuccess { event, events, tx_data, tx_hash, + tx_index, block_hash, + block_number, }) } @@ -702,11 +869,23 @@ impl DataAvailability { return Err(String::from("Failed to find ApplicationKeyCreated event")); }; + let tx_hash = tx_in_block.extrinsic_hash(); + let tx_index = events.extrinsic_index(); + let block_hash = tx_in_block.block_hash(); + let block_number = self + .blocks + .at(block_hash) + .await + .map_err(|e| e.to_string())? + .number(); + Ok(CreateApplicationKeyTxSuccess { event, events, - tx_hash: tx_in_block.extrinsic_hash(), - block_hash: tx_in_block.block_hash(), + tx_hash, + tx_index, + block_hash, + block_number, }) } @@ -757,11 +936,23 @@ impl DataAvailability { return Err(String::from("Failed to find ApplicationKeySet event")); }; + let tx_hash = tx_in_block.extrinsic_hash(); + let tx_index = events.extrinsic_index(); + let block_hash = tx_in_block.block_hash(); + let block_number = self + .blocks + .at(block_hash) + .await + .map_err(|e| e.to_string())? + .number(); + Ok(SetApplicationKeyTxSuccess { event, events, - tx_hash: tx_in_block.extrinsic_hash(), - block_hash: tx_in_block.block_hash(), + tx_hash, + tx_index, + block_hash, + block_number, }) } @@ -814,11 +1005,23 @@ impl DataAvailability { )); }; + let tx_hash = tx_in_block.extrinsic_hash(); + let tx_index = events.extrinsic_index(); + let block_hash = tx_in_block.block_hash(); + let block_number = self + .blocks + .at(block_hash) + .await + .map_err(|e| e.to_string())? + .number(); + Ok(SubmitBlockLengthProposalTxSuccess { event, events, - tx_hash: tx_in_block.extrinsic_hash(), - block_hash: tx_in_block.block_hash(), + tx_hash, + tx_index, + block_hash, + block_number, }) } @@ -869,11 +1072,23 @@ impl DataAvailability { )); }; + let tx_hash = tx_in_block.extrinsic_hash(); + let tx_index = events.extrinsic_index(); + let block_hash = tx_in_block.block_hash(); + let block_number = self + .blocks + .at(block_hash) + .await + .map_err(|e| e.to_string())? + .number(); + Ok(SetSubmitDataFeeModifierTxSuccess { event, events, - tx_hash: tx_in_block.extrinsic_hash(), - block_hash: tx_in_block.block_hash(), + tx_hash, + tx_index, + block_hash, + block_number, }) } } diff --git a/avail-rust/src/utils.rs b/avail-rust/src/utils.rs index 74f1795a2..2d96d90d0 100644 --- a/avail-rust/src/utils.rs +++ b/avail-rust/src/utils.rs @@ -31,6 +31,7 @@ impl FetchTransactionError { } } +#[derive(Clone)] pub struct Util { blocks_api: AvailBlocksClient, }