Use RPC call to get account nonce (#476)

* remove code related to getting nonce from storage and use RPC call instead

* cargo fmt

* move nonce fetching into Rpc, since it's just an RPC call

* clippy
This commit is contained in:
James Wilson
2022-03-14 15:39:40 +00:00
committed by GitHub
parent 798a1d0b88
commit 8b19549560
10 changed files with 460 additions and 1086 deletions
+7 -29
View File
@@ -37,7 +37,6 @@ use crate::{
},
storage::StorageClient,
transaction::TransactionProgress,
AccountData,
Call,
Config,
Metadata,
@@ -170,23 +169,6 @@ impl<T: Config> Client<T> {
StorageClient::new(&self.rpc, &self.metadata, self.iter_page_size)
}
/// Fetch the current nonce for the given account id.
pub async fn fetch_nonce<A: AccountData>(
&self,
account: &T::AccountId,
) -> Result<T::Index, BasicError>
where
<A as AccountData>::AccountId: From<<T as Config>::AccountId>,
<A as AccountData>::Index: Into<<T as Config>::Index>,
{
let account_storage_entry = A::storage_entry(account.clone().into());
let account_data = self
.storage()
.fetch_or_default(&account_storage_entry, None)
.await?;
Ok(A::nonce(&account_data).into())
}
/// Convert the client to a runtime api wrapper for custom runtime access.
///
/// The `subxt` proc macro will provide methods to submit extrinsics and read storage specific
@@ -197,17 +179,16 @@ impl<T: Config> Client<T> {
}
/// A constructed call ready to be signed and submitted.
pub struct SubmittableExtrinsic<'client, T: Config, X, A, C, E: Decode, Evs: Decode> {
pub struct SubmittableExtrinsic<'client, T: Config, X, C, E: Decode, Evs: Decode> {
client: &'client Client<T>,
call: C,
marker: std::marker::PhantomData<(X, A, E, Evs)>,
marker: std::marker::PhantomData<(X, E, Evs)>,
}
impl<'client, T, X, A, C, E, Evs> SubmittableExtrinsic<'client, T, X, A, C, E, Evs>
impl<'client, T, X, C, E, Evs> SubmittableExtrinsic<'client, T, X, C, E, Evs>
where
T: Config,
X: SignedExtra<T>,
A: AccountData,
C: Call + Send + Sync,
E: Decode + HasModuleError,
Evs: Decode,
@@ -232,8 +213,6 @@ where
where
<<X as SignedExtra<T>>::Extra as SignedExtension>::AdditionalSigned:
Send + Sync + 'static,
<A as AccountData>::AccountId: From<<T as Config>::AccountId>,
<A as AccountData>::Index: Into<<T as Config>::Index>,
{
// Sign the call data to create our extrinsic.
let extrinsic = self.create_signed(signer, Default::default()).await?;
@@ -262,8 +241,6 @@ where
where
<<X as SignedExtra<T>>::Extra as SignedExtension>::AdditionalSigned:
Send + Sync + 'static,
<A as AccountData>::AccountId: From<<T as Config>::AccountId>,
<A as AccountData>::Index: Into<<T as Config>::Index>,
{
let extrinsic = self.create_signed(signer, Default::default()).await?;
self.client.rpc().submit_extrinsic(extrinsic).await
@@ -278,13 +255,14 @@ where
where
<<X as SignedExtra<T>>::Extra as SignedExtension>::AdditionalSigned:
Send + Sync + 'static,
<A as AccountData>::AccountId: From<<T as Config>::AccountId>,
<A as AccountData>::Index: Into<<T as Config>::Index>,
{
let account_nonce = if let Some(nonce) = signer.nonce() {
nonce
} else {
self.client.fetch_nonce::<A>(signer.account_id()).await?
self.client
.rpc()
.system_account_next_index(signer.account_id())
.await?
};
let call = self
.client
+8 -22
View File
@@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with subxt. If not, see <http://www.gnu.org/licenses/>.
use crate::StorageEntry;
use codec::{
Codec,
Encode,
@@ -38,7 +37,13 @@ use sp_runtime::traits::{
pub trait Config: 'static {
/// Account index (aka nonce) type. This stores the number of previous
/// transactions associated with a sender account.
type Index: Parameter + Member + Default + AtLeast32Bit + Copy + scale_info::TypeInfo;
type Index: Parameter
+ Member
+ serde::de::DeserializeOwned
+ Default
+ AtLeast32Bit
+ Copy
+ scale_info::TypeInfo;
/// The block number type used by the runtime.
type BlockNumber: Parameter
@@ -65,7 +70,7 @@ pub trait Config: 'static {
type Hashing: Hash<Output = Self::Hash>;
/// The user account identifier type for the runtime.
type AccountId: Parameter + Member;
type AccountId: Parameter + Member + serde::Serialize;
/// The address type. This instead of `<frame_system::Trait::Lookup as StaticLookup>::Source`.
type Address: Codec + Clone + PartialEq;
@@ -103,22 +108,3 @@ impl Config for DefaultConfig {
type Signature = sp_runtime::MultiSignature;
type Extrinsic = sp_runtime::OpaqueExtrinsic;
}
/// Trait to fetch data about an account.
pub trait AccountData {
/// The runtime storage entry from which the account data can be fetched.
/// Usually generated by the `subxt` macro.
type StorageEntry: StorageEntry;
/// The type of the account id to fetch the account data for.
type AccountId;
/// The type of the account nonce returned from storage.
type Index;
/// Create a new storage entry key from the account id.
fn storage_entry(account_id: Self::AccountId) -> Self::StorageEntry;
/// Get the nonce from the storage entry value.
fn nonce(result: &<Self::StorageEntry as StorageEntry>::Value) -> Self::Index;
}
-1
View File
@@ -73,7 +73,6 @@ pub use crate::{
SubmittableExtrinsic,
},
config::{
AccountData,
Config,
DefaultConfig,
},
+11
View File
@@ -324,6 +324,17 @@ impl<T: Config> Rpc<T> {
Ok(self.client.request("system_version", rpc_params![]).await?)
}
/// Fetch the current nonce for the given account ID.
pub async fn system_account_next_index(
&self,
account: &T::AccountId,
) -> Result<T::Index, BasicError> {
Ok(self
.client
.request("system_accountNextIndex", rpc_params![account])
.await?)
}
/// Get a header
pub async fn header(
&self,