diff --git a/codegen/src/api/constants.rs b/codegen/src/api/constants.rs
new file mode 100644
index 0000000000..7cbb988450
--- /dev/null
+++ b/codegen/src/api/constants.rs
@@ -0,0 +1,56 @@
+// 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 .
+
+use crate::types::TypeGenerator;
+use frame_metadata::PalletConstantMetadata;
+use heck::SnakeCase as _;
+use proc_macro2::TokenStream as TokenStream2;
+use quote::{
+ format_ident,
+ quote,
+};
+use scale_info::form::PortableForm;
+
+pub fn generate_constants(
+ type_gen: &TypeGenerator,
+ constants: &[PalletConstantMetadata],
+ types_mod_ident: &syn::Ident,
+) -> TokenStream2 {
+ let constant_fns = constants.iter().map(|constant| {
+ let fn_name = format_ident!("{}", constant.name.to_snake_case());
+ let return_ty = type_gen.resolve_type_path(constant.ty.id(), &[]);
+
+ let ref_slice = constant.value.as_slice();
+
+ quote! {
+ pub fn #fn_name(&self) -> ::core::result::Result<#return_ty, ::subxt::BasicError> {
+ Ok(::subxt::codec::Decode::decode(&mut &[#(#ref_slice,)*][..])?)
+ }
+ }
+ });
+
+ quote! {
+ pub mod constants {
+ use super::#types_mod_ident;
+
+ pub struct ConstantsApi;
+
+ impl ConstantsApi {
+ #(#constant_fns)*
+ }
+ }
+ }
+}
diff --git a/codegen/src/api/mod.rs b/codegen/src/api/mod.rs
index ea8e73c45f..3b4c4dd365 100644
--- a/codegen/src/api/mod.rs
+++ b/codegen/src/api/mod.rs
@@ -15,6 +15,7 @@
// along with subxt. If not, see .
mod calls;
+mod constants;
mod errors;
mod events;
mod storage;
@@ -173,12 +174,23 @@ impl RuntimeGenerator {
quote!()
};
+ let constants_mod = if !pallet.constants.is_empty() {
+ constants::generate_constants(
+ &type_gen,
+ &pallet.constants,
+ types_mod_ident,
+ )
+ } else {
+ quote!()
+ };
+
quote! {
pub mod #mod_name {
use super::#types_mod_ident;
#calls
#event
#storage_mod
+ #constants_mod
}
}
});
@@ -204,6 +216,12 @@ impl RuntimeGenerator {
};
let mod_ident = item_mod_ir.ident;
+ let pallets_with_constants =
+ pallets_with_mod_names
+ .iter()
+ .filter_map(|(pallet, pallet_mod_name)| {
+ (!pallet.constants.is_empty()).then(|| pallet_mod_name)
+ });
let pallets_with_storage =
pallets_with_mod_names
.iter()
@@ -270,6 +288,10 @@ impl RuntimeGenerator {
T: ::subxt::Config,
X: ::subxt::SignedExtra,
{
+ pub fn constants(&'a self) -> ConstantsApi {
+ ConstantsApi
+ }
+
pub fn storage(&'a self) -> StorageApi<'a, T> {
StorageApi { client: &self.client }
}
@@ -279,6 +301,17 @@ impl RuntimeGenerator {
}
}
+ pub struct ConstantsApi;
+
+ impl ConstantsApi
+ {
+ #(
+ pub fn #pallets_with_constants(&self) -> #pallets_with_constants::constants::ConstantsApi {
+ #pallets_with_constants::constants::ConstantsApi
+ }
+ )*
+ }
+
pub struct StorageApi<'a, T: ::subxt::Config> {
client: &'a ::subxt::Client,
}
diff --git a/tests/integration/frame/balances.rs b/tests/integration/frame/balances.rs
index 91dbcc353e..405ca90fc1 100644
--- a/tests/integration/frame/balances.rs
+++ b/tests/integration/frame/balances.rs
@@ -261,4 +261,12 @@ async fn constant_existential_deposit() {
let constant_metadata = balances_metadata.constant("ExistentialDeposit").unwrap();
let existential_deposit = u128::decode(&mut &constant_metadata.value[..]).unwrap();
assert_eq!(existential_deposit, 100_000_000_000_000);
+ assert_eq!(
+ existential_deposit,
+ cxt.api
+ .constants()
+ .balances()
+ .existential_deposit()
+ .unwrap()
+ );
}