diff --git a/examples/examples/storage_query.rs b/examples/examples/storage_query.rs
new file mode 100644
index 0000000000..7b41948ba4
--- /dev/null
+++ b/examples/examples/storage_query.rs
@@ -0,0 +1,165 @@
+// Copyright 2019-2022 Parity Technologies (UK) Ltd.
+// This file is part of subxt.
+//
+// subxt is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// subxt is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with subxt. If not, see .
+
+//! To run this example, a local polkadot node should be running. Example verified against polkadot 0.9.18-4542a603cc-aarch64-macos.
+//!
+//! E.g.
+//! ```bash
+//! curl "https://github.com/paritytech/polkadot/releases/download/v0.9.18/polkadot" --output /usr/local/bin/polkadot --location
+//! polkadot --dev --tmp
+//! ```
+
+use codec::Decode;
+use subxt::{
+ rpc::Rpc,
+ storage::{
+ StorageClient,
+ StorageKeyPrefix,
+ },
+ ClientBuilder,
+ DefaultConfig,
+ PolkadotExtrinsicParams,
+ StorageEntryKey,
+ StorageMapKey,
+};
+
+#[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata.scale")]
+pub mod polkadot {}
+
+#[tokio::main]
+async fn main() -> Result<(), Box> {
+ tracing_subscriber::fmt::init();
+
+ let api = ClientBuilder::new()
+ .build()
+ .await?
+ .to_runtime_api::>>();
+
+ // Obtain the storage client wrapper from the API.
+ let storage: StorageClient<_> = api.client.storage();
+
+ // The VersionNotifiers type of the XcmPallet is defined as:
+ //
+ // ```
+ // All locations that we have requested version notifications from.
+ // #[pallet::storage]
+ // pub(super) type VersionNotifiers = StorageDoubleMap<
+ // _,
+ // Twox64Concat,
+ // XcmVersion,
+ // Blake2_128Concat,
+ // VersionedMultiLocation,
+ // QueryId,
+ // OptionQuery,
+ // >;
+ // ```
+
+ // Example 1. Iterate over fetched keys manually.
+ {
+ // Fetch at most 10 keys from below the prefix XcmPallet' VersionNotifiers.
+ let keys = storage
+ .fetch_keys::(10, None, None)
+ .await?;
+
+ println!("Example 1. Obtained keys:");
+ for key in keys.iter() {
+ println!("Key: 0x{}", hex::encode(&key));
+
+ if let Some(storage_data) = storage.fetch_raw(key.clone(), None).await? {
+ // We know the return value to be `QueryId` (`u64`) from inspecting either:
+ // - polkadot code
+ // - polkadot.rs generated file under `version_notifiers()` fn
+ // - metadata in json format
+ let value = u64::decode(&mut &storage_data.0[..])?;
+ println!(" Value: {}", value);
+ }
+ }
+ }
+
+ // Example 2. Iterate over (keys, value) using the storage client.
+ {
+ let mut iter = storage
+ .iter::(None)
+ .await?;
+
+ println!("\nExample 2. Obtained keys:");
+ while let Some((key, value)) = iter.next().await? {
+ println!("Key: 0x{}", hex::encode(&key));
+ println!(" Value: {}", value);
+ }
+ }
+
+ // Example 3. Iterate over (keys, value) using the polkadot API.
+ {
+ let mut iter = api
+ .storage()
+ .xcm_pallet()
+ .version_notifiers_iter(None)
+ .await?;
+
+ println!("\nExample 3. Obtained keys:");
+ while let Some((key, value)) = iter.next().await? {
+ println!("Key: 0x{}", hex::encode(&key));
+ println!(" Value: {}", value);
+ }
+ }
+
+ // Example 4. Custom iteration over double maps.
+ {
+ // Obtain the inner RPC from the API.
+ let rpc: &Rpc<_> = api.client.rpc();
+
+ // Obtain the prefixed `twox_128("XcmPallet") ++ twox_128("VersionNotifiers")`
+ let prefix =
+ StorageKeyPrefix::new::();
+ // From the VersionNotifiers definition above, the first key is represented by
+ // ```
+ // Twox64Concat,
+ // XcmVersion,
+ // ```
+ // while `XcmVersion` is `u32`.
+ // Pass `2` as `XcmVersion` and concatenate the key to the prefix.
+ let entry_key = StorageEntryKey::Map(vec![StorageMapKey::new(
+ &2u32,
+ ::subxt::StorageHasher::Twox64Concat,
+ )]);
+
+ // The final query key is:
+ // `twox_128("XcmPallet") ++ twox_128("VersionNotifiers") ++ twox_64(2u32) ++ 2u32`
+ let query_key = entry_key.final_key(prefix);
+ println!("\nExample 4\nQuery key: 0x{}", hex::encode(&query_key));
+
+ let keys = rpc
+ .storage_keys_paged(Some(query_key), 10, None, None)
+ .await?;
+
+ println!("Obtained keys:");
+ for key in keys.iter() {
+ println!("Key: 0x{}", hex::encode(&key));
+
+ if let Some(storage_data) = storage.fetch_raw(key.clone(), None).await? {
+ // We know the return value to be `QueryId` (`u64`) from inspecting either:
+ // - polkadot code
+ // - polkadot.rs generated file under `version_notifiers()` fn
+ // - metadata in json format
+ let value = u64::decode(&mut &storage_data.0[..])?;
+ println!(" Value: {}", value);
+ }
+ }
+ }
+
+ Ok(())
+}
diff --git a/subxt/src/rpc.rs b/subxt/src/rpc.rs
index 9882367e6e..1aff88e8a9 100644
--- a/subxt/src/rpc.rs
+++ b/subxt/src/rpc.rs
@@ -28,7 +28,6 @@ use std::{
use crate::{
error::BasicError,
- storage::StorageKeyPrefix,
Config,
Metadata,
PhantomDataSendSync,
@@ -277,13 +276,12 @@ impl Rpc {
/// If `start_key` is passed, return next keys in storage in lexicographic order.
pub async fn storage_keys_paged(
&self,
- prefix: Option,
+ key: Option,
count: u32,
start_key: Option,
hash: Option,
) -> Result, BasicError> {
- let prefix = prefix.map(|p| p.to_storage_key());
- let params = rpc_params![prefix, count, start_key, hash];
+ let params = rpc_params![key, count, start_key, hash];
let data = self.client.request("state_getKeysPaged", params).await?;
Ok(data)
}
diff --git a/subxt/src/storage.rs b/subxt/src/storage.rs
index 7d41278dbb..b3e2f55657 100644
--- a/subxt/src/storage.rs
+++ b/subxt/src/storage.rs
@@ -235,10 +235,10 @@ impl<'a, T: Config> StorageClient<'a, T> {
start_key: Option,
hash: Option,
) -> Result, BasicError> {
- let prefix = StorageKeyPrefix::new::();
+ let key = StorageKeyPrefix::new::().to_storage_key();
let keys = self
.rpc
- .storage_keys_paged(Some(prefix), count, start_key, hash)
+ .storage_keys_paged(Some(key), count, start_key, hash)
.await?;
Ok(keys)
}