Skip to content

Commit

Permalink
Configurable Config and Extra types (#373)
Browse files Browse the repository at this point in the history
* WIP config

* WIP separate default config

* Separate trait impls on client

* WIP introduce new ApiConfig (to be renamed) trait

* Update generated polkadot codegen

* Allow configuring Config and Extra types independently

* Add extra default configuration

* Revert ir parsing of config attr

* Add default-features = false to substrate deps

* Revert "Add default-features = false to substrate deps"

This reverts commit 099d20c.
  • Loading branch information
ascjones authored Jan 6, 2022
1 parent 30665bf commit ca5345c
Show file tree
Hide file tree
Showing 22 changed files with 18,841 additions and 12,811 deletions.
13 changes: 8 additions & 5 deletions codegen/src/api/calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub fn generate_calls(
pub fn #fn_name(
&self,
#( #call_fn_args, )*
) -> ::subxt::SubmittableExtrinsic<'a, T, #call_struct_name> {
) -> ::subxt::SubmittableExtrinsic<'a, T, E, A, #call_struct_name> {
let call = #call_struct_name { #( #call_args, )* };
::subxt::SubmittableExtrinsic::new(self.client, call)
}
Expand All @@ -82,16 +82,19 @@ pub fn generate_calls(
use super::#types_mod_ident;
#( #call_structs )*

pub struct TransactionApi<'a, T: ::subxt::Config + ::subxt::ExtrinsicExtraData<T>> {
pub struct TransactionApi<'a, T: ::subxt::Config, E, A> {
client: &'a ::subxt::Client<T>,
marker: ::core::marker::PhantomData<(E, A)>,
}

impl<'a, T: ::subxt::Config> TransactionApi<'a, T>
impl<'a, T, E, A> TransactionApi<'a, T, E, A>
where
T: ::subxt::Config + ::subxt::ExtrinsicExtraData<T>,
T: ::subxt::Config,
E: ::subxt::SignedExtra<T>,
A: ::subxt::AccountData<T>,
{
pub fn new(client: &'a ::subxt::Client<T>) -> Self {
Self { client }
Self { client, marker: ::core::marker::PhantomData }
}

#( #call_fns )*
Expand Down
71 changes: 27 additions & 44 deletions codegen/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ impl RuntimeGenerator {
)
})
.collect::<Vec<_>>();

let modules = pallets_with_mod_names.iter().map(|(pallet, mod_name)| {
let calls = if let Some(ref calls) = pallet.calls {
calls::generate_calls(&type_gen, pallet, calls, types_mod_ident)
Expand Down Expand Up @@ -222,76 +223,55 @@ impl RuntimeGenerator {
#( #modules )*
#types_mod

/// Default configuration of common types for a target Substrate runtime.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct DefaultConfig;

impl ::subxt::Config for DefaultConfig {
type Index = u32;
type BlockNumber = u32;
type Hash = ::subxt::sp_core::H256;
type Hashing = ::subxt::sp_runtime::traits::BlakeTwo256;
type AccountId = ::subxt::sp_runtime::AccountId32;
type Address = ::subxt::sp_runtime::MultiAddress<Self::AccountId, u32>;
type Header = ::subxt::sp_runtime::generic::Header<
Self::BlockNumber, ::subxt::sp_runtime::traits::BlakeTwo256
>;
type Signature = ::subxt::sp_runtime::MultiSignature;
type Extrinsic = ::subxt::sp_runtime::OpaqueExtrinsic;
}

impl ::subxt::ExtrinsicExtraData<DefaultConfig> for DefaultConfig {
type AccountData = AccountData;
type Extra = ::subxt::DefaultExtra<DefaultConfig>;
}
/// The default storage entry from which to fetch an account nonce, required for
/// constructing a transaction.
pub type DefaultAccountData = self::system::storage::Account;

pub type AccountData = self::system::storage::Account;

impl ::subxt::AccountData<DefaultConfig> for AccountData {
fn nonce(result: &<Self as ::subxt::StorageEntry>::Value) -> <DefaultConfig as ::subxt::Config>::Index {
impl ::subxt::AccountData<::subxt::DefaultConfig> for DefaultAccountData {
fn nonce(result: &<Self as ::subxt::StorageEntry>::Value) -> <::subxt::DefaultConfig as ::subxt::Config>::Index {
result.nonce
}
fn storage_entry(account_id: <DefaultConfig as ::subxt::Config>::AccountId) -> Self {
fn storage_entry(account_id: <::subxt::DefaultConfig as ::subxt::Config>::AccountId) -> Self {
Self(account_id)
}
}

pub struct RuntimeApi<T: ::subxt::Config + ::subxt::ExtrinsicExtraData<T>> {
pub struct RuntimeApi<T: ::subxt::Config, E> {
pub client: ::subxt::Client<T>,
marker: ::core::marker::PhantomData<E>,
}

impl<T> ::core::convert::From<::subxt::Client<T>> for RuntimeApi<T>
impl<T, E> ::core::convert::From<::subxt::Client<T>> for RuntimeApi<T, E>
where
T: ::subxt::Config + ::subxt::ExtrinsicExtraData<T>,
T: ::subxt::Config,
E: ::subxt::SignedExtra<T>,
{
fn from(client: ::subxt::Client<T>) -> Self {
Self { client }
Self { client, marker: ::core::marker::PhantomData }
}
}

impl<'a, T> RuntimeApi<T>
impl<'a, T, E> RuntimeApi<T, E>
where
T: ::subxt::Config + ::subxt::ExtrinsicExtraData<T>,
T: ::subxt::Config,
E: ::subxt::SignedExtra<T>,
{
pub fn storage(&'a self) -> StorageApi<'a, T> {
StorageApi { client: &self.client }
}

pub fn tx(&'a self) -> TransactionApi<'a, T> {
TransactionApi { client: &self.client }
pub fn tx(&'a self) -> TransactionApi<'a, T, E, DefaultAccountData> {
TransactionApi { client: &self.client, marker: ::core::marker::PhantomData }
}
}

pub struct StorageApi<'a, T>
where
T: ::subxt::Config + ::subxt::ExtrinsicExtraData<T>,
{
pub struct StorageApi<'a, T: ::subxt::Config> {
client: &'a ::subxt::Client<T>,
}

impl<'a, T> StorageApi<'a, T>
where
T: ::subxt::Config + ::subxt::ExtrinsicExtraData<T>,
T: ::subxt::Config,
{
#(
pub fn #pallets_with_storage(&self) -> #pallets_with_storage::storage::StorageApi<'a, T> {
Expand All @@ -300,16 +280,19 @@ impl RuntimeGenerator {
)*
}

pub struct TransactionApi<'a, T: ::subxt::Config + ::subxt::ExtrinsicExtraData<T>> {
pub struct TransactionApi<'a, T: ::subxt::Config, E, A> {
client: &'a ::subxt::Client<T>,
marker: ::core::marker::PhantomData<(E, A)>,
}

impl<'a, T> TransactionApi<'a, T>
impl<'a, T, E, A> TransactionApi<'a, T, E, A>
where
T: ::subxt::Config + ::subxt::ExtrinsicExtraData<T>,
T: ::subxt::Config,
E: ::subxt::SignedExtra<T>,
A: ::subxt::AccountData<T>,
{
#(
pub fn #pallets_with_calls(&self) -> #pallets_with_calls::calls::TransactionApi<'a, T> {
pub fn #pallets_with_calls(&self) -> #pallets_with_calls::calls::TransactionApi<'a, T, E, A> {
#pallets_with_calls::calls::TransactionApi::new(self.client)
}
)*
Expand Down
1 change: 0 additions & 1 deletion codegen/src/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ impl ItemMod {

#[allow(clippy::large_enum_variant)]
#[derive(Debug, PartialEq, Eq)]
#[allow(clippy::large_enum_variant)]
pub enum Item {
Rust(syn::Item),
Subxt(SubxtItem),
Expand Down
8 changes: 6 additions & 2 deletions examples/fetch_all_accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@
//! polkadot --dev --tmp
//! ```

use subxt::ClientBuilder;
use subxt::{
ClientBuilder,
DefaultConfig,
DefaultExtra,
};

#[subxt::subxt(runtime_metadata_path = "examples/polkadot_metadata.scale")]
pub mod polkadot {}
Expand All @@ -34,7 +38,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api = ClientBuilder::new()
.build()
.await?
.to_runtime_api::<polkadot::RuntimeApi<polkadot::DefaultConfig>>();
.to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, DefaultExtra<DefaultConfig>>>();

let mut iter = api.storage().system().account_iter(None).await?;

Expand Down
8 changes: 6 additions & 2 deletions examples/fetch_remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with subxt. If not, see <http://www.gnu.org/licenses/>.

use subxt::ClientBuilder;
use subxt::{
ClientBuilder,
DefaultConfig,
DefaultExtra,
};

#[subxt::subxt(runtime_metadata_path = "examples/polkadot_metadata.scale")]
pub mod polkadot {}
Expand All @@ -27,7 +31,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.set_url("wss://rpc.polkadot.io:443")
.build()
.await?
.to_runtime_api::<polkadot::RuntimeApi<polkadot::DefaultConfig>>();
.to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, DefaultExtra<DefaultConfig>>>();

let block_number = 1;

Expand Down
4 changes: 3 additions & 1 deletion examples/polkadot_balance_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
use sp_keyring::AccountKeyring;
use subxt::{
ClientBuilder,
DefaultConfig,
DefaultExtra,
PairSigner,
};

Expand All @@ -41,7 +43,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api = ClientBuilder::new()
.build()
.await?
.to_runtime_api::<polkadot::RuntimeApi<polkadot::DefaultConfig>>();
.to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, DefaultExtra<DefaultConfig>>>();
let hash = api
.tx()
.balances()
Expand Down
8 changes: 5 additions & 3 deletions examples/submit_and_watch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ use futures::StreamExt;
use sp_keyring::AccountKeyring;
use subxt::{
ClientBuilder,
DefaultConfig,
DefaultExtra,
PairSigner,
};

Expand Down Expand Up @@ -53,7 +55,7 @@ async fn simple_transfer() -> Result<(), Box<dyn std::error::Error>> {
let api = ClientBuilder::new()
.build()
.await?
.to_runtime_api::<polkadot::RuntimeApi<polkadot::DefaultConfig>>();
.to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, DefaultExtra<_>>>();

let balance_transfer = api
.tx()
Expand Down Expand Up @@ -85,7 +87,7 @@ async fn simple_transfer_separate_events() -> Result<(), Box<dyn std::error::Err
let api = ClientBuilder::new()
.build()
.await?
.to_runtime_api::<polkadot::RuntimeApi<polkadot::DefaultConfig>>();
.to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, DefaultExtra<_>>>();

let balance_transfer = api
.tx()
Expand Down Expand Up @@ -136,7 +138,7 @@ async fn handle_transfer_events() -> Result<(), Box<dyn std::error::Error>> {
let api = ClientBuilder::new()
.build()
.await?
.to_runtime_api::<polkadot::RuntimeApi<polkadot::DefaultConfig>>();
.to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, DefaultExtra<_>>>();

let mut balance_transfer_progress = api
.tx()
Expand Down
6 changes: 4 additions & 2 deletions examples/transfer_subscribe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
use sp_keyring::AccountKeyring;
use subxt::{
ClientBuilder,
DefaultConfig,
DefaultExtra,
EventSubscription,
PairSigner,
};
Expand All @@ -42,11 +44,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api = ClientBuilder::new()
.build()
.await?
.to_runtime_api::<polkadot::RuntimeApi<polkadot::DefaultConfig>>();
.to_runtime_api::<polkadot::RuntimeApi<DefaultConfig, DefaultExtra<DefaultConfig>>>();

let sub = api.client.rpc().subscribe_events().await?;
let decoder = api.client.events_decoder();
let mut sub = EventSubscription::<polkadot::DefaultConfig>::new(sub, decoder);
let mut sub = EventSubscription::<DefaultConfig>::new(sub, decoder);
sub.filter_event::<polkadot::balances::events::Transfer>();

api.tx()
Expand Down
42 changes: 24 additions & 18 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ use crate::{
AccountData,
Call,
Config,
ExtrinsicExtraData,
Metadata,
};
use std::sync::Arc;
Expand Down Expand Up @@ -185,19 +184,26 @@ impl<T: Config> Client<T> {
}

/// A constructed call ready to be signed and submitted.
pub struct SubmittableExtrinsic<'client, T: Config, C> {
pub struct SubmittableExtrinsic<'client, T: Config, E, A, C> {
client: &'client Client<T>,
call: C,
marker: std::marker::PhantomData<(E, A)>,
}

impl<'client, T, C> SubmittableExtrinsic<'client, T, C>
impl<'client, T, E, A, C> SubmittableExtrinsic<'client, T, E, A, C>
where
T: Config + ExtrinsicExtraData<T>,
T: Config,
E: SignedExtra<T>,
A: AccountData<T>,
C: Call + Send + Sync,
{
/// Create a new [`SubmittableExtrinsic`].
pub fn new(client: &'client Client<T>, call: C) -> Self {
Self { client, call }
Self {
client,
call,
marker: Default::default(),
}
}

/// Creates and signs an extrinsic and submits it to the chain.
Expand All @@ -206,10 +212,11 @@ where
/// and obtain details about it, once it has made it into a block.
pub async fn sign_and_submit_then_watch(
self,
signer: &(dyn Signer<T> + Send + Sync),
signer: &(dyn Signer<T, E> + Send + Sync),
) -> Result<TransactionProgress<'client, T>, Error>
where
<<<T as ExtrinsicExtraData<T>>::Extra as SignedExtra<T>>::Extra as SignedExtension>::AdditionalSigned: Send + Sync + 'static
<<E as SignedExtra<T>>::Extra as SignedExtension>::AdditionalSigned:
Send + Sync + 'static,
{
// Sign the call data to create our extrinsic.
let extrinsic = self.create_signed(signer, Default::default()).await?;
Expand All @@ -231,10 +238,11 @@ where
/// and has been included in the transaction pool.
pub async fn sign_and_submit(
self,
signer: &(dyn Signer<T> + Send + Sync),
signer: &(dyn Signer<T, E> + Send + Sync),
) -> Result<T::Hash, Error>
where
<<<T as ExtrinsicExtraData<T>>::Extra as SignedExtra<T>>::Extra as SignedExtension>::AdditionalSigned: Send + Sync + 'static
<<E as SignedExtra<T>>::Extra as SignedExtension>::AdditionalSigned:
Send + Sync + 'static,
{
let extrinsic = self.create_signed(signer, Default::default()).await?;
self.client.rpc().submit_extrinsic(extrinsic).await
Expand All @@ -243,25 +251,23 @@ where
/// Creates a signed extrinsic.
pub async fn create_signed(
&self,
signer: &(dyn Signer<T> + Send + Sync),
additional_params: <T::Extra as SignedExtra<T>>::Parameters,
) -> Result<UncheckedExtrinsic<T>, Error>
signer: &(dyn Signer<T, E> + Send + Sync),
additional_params: E::Parameters,
) -> Result<UncheckedExtrinsic<T, E>, Error>
where
<<<T as ExtrinsicExtraData<T>>::Extra as SignedExtra<T>>::Extra as SignedExtension>::AdditionalSigned: Send + Sync + 'static
<<E as SignedExtra<T>>::Extra as SignedExtension>::AdditionalSigned:
Send + Sync + 'static,
{
let account_nonce = if let Some(nonce) = signer.nonce() {
nonce
} else {
let account_storage_entry =
<<T as ExtrinsicExtraData<T>>::AccountData as AccountData<T>>::storage_entry(signer.account_id().clone());
let account_storage_entry = A::storage_entry(signer.account_id().clone());
let account_data = self
.client
.storage()
.fetch_or_default(&account_storage_entry, None)
.await?;
<<T as ExtrinsicExtraData<T>>::AccountData as AccountData<T>>::nonce(
&account_data,
)
A::nonce(&account_data)
};
let call = self
.client
Expand Down
Loading

0 comments on commit ca5345c

Please sign in to comment.