You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I hope that the details below is helpful to subxt.
The codegen (crate polymesh-api-codegen) that is used for polymesh-api has support for generating code for both RPC clients (std native and no_std web) & Ink!.
The generated code uses feature flag ink to support ink and not-ink clients. The type_info feature flag
is used to derive scale-info::TypeInfo for the chain types.
/// ----- Moved these top-level types here:#[derive(Clone)]pubstructApi{#[cfg(not(feature = "ink"))]client:::polymesh_api_client::Client,/// <----- `polymesh_api_client` is the backend to submit signed tx for RPC clients.}implApi{pubfncall(&self) -> CallApi{CallApi{api:self}}}#[cfg(feature = "ink")]implApi{pubfnnew() -> Self{Self{}}/// --------------------- For Ink! support Polymesh has a `ChainExtension` to provide a custom `call_runtime`/// ----- and `read_storage` support.pubfnruntime(&self) -> ::polymesh_api_ink::extension::PolymeshRuntimeInstance{::polymesh_api_ink::extension::new_instance()}/// ------------- uses the `read_storage` method of the `ChainExtension` for storage reads./// ----- this is the low-level method used by the `QueryApi` below.pubfnread_storage<T:::codec::Decode>(&self,key:::alloc::vec::Vec<u8>,) -> ::polymesh_api_ink::error::Result<Option<T>>{let runtime = self.runtime();let value = runtime
.read_storage(key.into())?
.map(|data| T::decode(&mut data.as_slice())).transpose()?;Ok(value)}pubfnquery(&self) -> QueryApi{QueryApi{api:self}}pubfnwrap_call(&self,call:::alloc::vec::Vec<u8>) -> WrappedCall{WrappedCall::new(call)}}#[cfg(not(feature = "ink"))]implApi{pubasyncfnnew(url:&str) -> ::polymesh_api_client::error::Result<Self>{Ok(Self{client:::polymesh_api_client::Client::new(url).await?,})}pubfnquery(&self) -> QueryApi{QueryApi{api:self,at:None,}}pubfnquery_at(&self,block:::polymesh_api_client::BlockHash) -> QueryApi{QueryApi{api:self,at:Some(block),}}pubfnwrap_call(&self,call: types::runtime::RuntimeCall,) -> ::polymesh_api_client::Result<WrappedCall>{Ok(WrappedCall::new(self, call))}}/// ------------------ The `ChainApi` trait from `polymesh_api_client` is used to provide some/// -- important chain types and to provide some helpers `get_nonce`, `block_events`#[async_trait::async_trait]#[cfg(not(feature = "ink"))]impl::polymesh_api_client::ChainApiforApi{typeRuntimeCall = types::runtime::RuntimeCall;typeRuntimeEvent = types::runtime::RuntimeEvent;typeDispatchInfo = types::frame_support::dispatch::DispatchInfo;typeDispatchError = types::sp_runtime::DispatchError;asyncfnget_nonce(&self,account:::polymesh_api_client::AccountId,) -> ::polymesh_api_client::Result<u32>{let info = self.query().system().account(account).await?;Ok(info.nonce)}asyncfnblock_events(&self,block:Option<::polymesh_api_client::BlockHash>,) -> ::polymesh_api_client::Result<::alloc::vec::Vec<::polymesh_api_client::EventRecord<Self::RuntimeEvent>>,>{let system = match block {Some(block) => self.query_at(block).system(),None => self.query().system(),};Ok(system.events().await?)}/// ------------------- This makes it much easier for the clients to check if their tx was successful or failed.fnevent_to_extrinsic_result(event:&::polymesh_api_client::EventRecord<Self::RuntimeEvent>,) -> Option<::polymesh_api_client::ExtrinsicResult<Self>>{match&event.event{
types::runtime::RuntimeEvent::System(
types::frame_system::pallet::SystemEvent::ExtrinsicSuccess{ dispatch_info },) => Some(::polymesh_api_client::ExtrinsicResult::Success(
dispatch_info.clone(),)),
types::runtime::RuntimeEvent::System(
types::frame_system::pallet::SystemEvent::ExtrinsicFailed{
dispatch_info,
dispatch_error,},) => Some(::polymesh_api_client::ExtrinsicResult::Failed(
dispatch_info.clone(),
dispatch_error.clone(),)),
_ => None,}}fnclient(&self) -> &::polymesh_api_client::Client{&self.client}}/// -------------------- `CallApi` is the top-level type used to construct an extrinsic call.#[derive(Clone)]pubstructCallApi<'api>{api:&'apiApi,}impl<'api>CallApi<'api>{pubfnsystem(&self) -> api::system::SystemCallApi<'api>{
api::system::SystemCallApi::from(self.api)}//// ---------------- <snipped other pallets>pubfnsudo(&self) -> api::sudo::SudoCallApi<'api>{
api::sudo::SudoCallApi::from(self.api)}}/// ---------------------- The `WrappedCall` type is returned from `api.call().pallet().extrinsic(<params)`/// ------------ it holds the encoded call and is provided by the backend (RPC client or Ink!)/// ------------ to provide methods for signing and/or submitting the call to the chain.#[cfg(not(feature = "ink"))]pubtypeWrappedCall = ::polymesh_api_client::Call<Api>;#[cfg(feature = "ink")]pubtypeWrappedCall = ::polymesh_api_ink::Call;/// -------- RPC clients get `TransactionResults` after submitting a tx to await on it's execution results./// ------- Ink! contracts get the results (Success/failed) when they submit the call.#[cfg(not(feature = "ink"))]pubtypeTransactionResults = ::polymesh_api_client::TransactionResults<Api>;/// ------------- The `From` impl is used for batching, multisig or other extrinsics that take a `RuntimeCall`./// ------------- Ink! doesn't have support for this right now.#[cfg(not(feature = "ink"))]implFrom<WrappedCall>for types::runtime::RuntimeCall{fnfrom(wrapped:WrappedCall) -> Self{
wrapped.into_runtime_call()}}/// -------------------- `QueryApi` is the top-level type used to query chain storage.#[derive(Clone)]pubstructQueryApi<'api>{api:&'apiApi,#[cfg(not(feature = "ink"))]at:Option<::polymesh_api_client::BlockHash>,/// ----- Ink! contracts are only allowed to query the current block storage.}impl<'api>QueryApi<'api>{pubfnsystem(&self) -> api::system::SystemQueryApi<'api>{
api::system::SystemQueryApi{api:self.api,#[cfg(not(feature = "ink"))]at:self.at,}}/// --------------------- <Snipped other pallets>pubfnsudo(&self) -> api::sudo::SudoQueryApi<'api>{
api::sudo::SudoQueryApi{api:self.api,#[cfg(not(feature = "ink"))]at:self.at,}}}/// ------------------- the `api` sub-module is used for per-pallet `<Pallet>CallApi` and `<Pallet>QueryApi` types./// ------ Only including the `pallet_sudo` here to keep this short.#[allow(dead_code, unused_imports, non_camel_case_types)]pubmod api {usesuper::types;usesuper::types::*;usesuper::WrappedCall;pubmod sudo {usesuper::*;/// ---------------- The per-pallet `<pallet>CallApi` provides one method for each extrinsic/// ------ and has both ink and non-ink impls.#[derive(Clone)]pubstructSudoCallApi<'api>{api:&'apisuper::super::Api,}impl<'api>SudoCallApi<'api>{#[doc = "See [`Pallet::sudo`]."]#[cfg(not(feature = "ink"))]pubfnsudo(&self,call: runtime::RuntimeCall,) -> ::polymesh_api_client::error::Result<super::super::WrappedCall>{self.api.wrap_call(runtime::RuntimeCall::Sudo(
types::pallet_sudo::pallet::SudoCall::sudo{call:::alloc::boxed::Box::new(call),},))}#[doc = "See [`Pallet::sudo`]."]#[cfg(feature = "ink")]pubfnsudo(&self,call: runtime::RuntimeCall) -> super::super::WrappedCall{use::codec::Encode;letmut buf = ::alloc::vec![6u8,0u8];
call.encode_to(&mut buf);self.api.wrap_call(buf)}/// ----------------------------------------------- <Snipped other sudo extrinsics>.}impl<'api>From<&'apisuper::super::Api>forSudoCallApi<'api>{fnfrom(api:&'apisuper::super::Api) -> Self{Self{ api }}}/// ---------------- The per-pallet `<pallet>QueryApi` provides one method for each storage item./// ------ The storage hash prefix is calculated by the generator and hard-coded./// ------ The ink impl uses the `read_storage` method from the ChainExtension.#[derive(Clone)]pubstructSudoQueryApi<'api>{pub(crate)api:&'apisuper::super::Api,#[cfg(not(feature = "ink"))]pub(crate)at:Option<::polymesh_api_client::BlockHash>,}impl<'api>SudoQueryApi<'api>{#[doc = " The `AccountId` of the sudo key."]#[cfg(not(feature = "ink"))]pubasyncfnkey(&self,) -> ::polymesh_api_client::error::Result<Option<::polymesh_api_client::AccountId>>{let key = ::polymesh_api_client::StorageKey(::alloc::vec![92u8,13u8,17u8,118u8,165u8,104u8,193u8,249u8,41u8,68u8,52u8,13u8,191u8,237u8,158u8,156u8,83u8,14u8,188u8,167u8,3u8,200u8,89u8,16u8,231u8,22u8,76u8,183u8,209u8,201u8,228u8,123u8,]);let value = self.api.client.get_storage_by_key(key,self.at).await?;Ok(value)}#[doc = " The `AccountId` of the sudo key."]#[cfg(feature = "ink")]pubfnkey(&self,) -> ::polymesh_api_ink::error::Result<Option<::polymesh_api_client::AccountId>>{let value = self.api.read_storage(::alloc::vec![92u8,13u8,17u8,118u8,165u8,104u8,193u8,249u8,41u8,68u8,52u8,13u8,191u8,237u8,158u8,156u8,83u8,14u8,188u8,167u8,3u8,200u8,89u8,16u8,231u8,22u8,76u8,183u8,209u8,201u8,228u8,123u8,])?;Ok(value)}}}}/// ------------ `mod types` holds all types generated from the chain metadata.pubmod types {usesuper::WrappedCall;pubmod sp_arithmetic {usesuper::*;#[derive(Clone,Debug,PartialEq,Eq,:: codec ::Encode,:: codec ::Decode)]#[cfg_attr( all(feature = "std", feature = "type_info"), derive(::scale_info::TypeInfo))]#[cfg_attr(feature = "serde", derive(::serde::Serialize,::serde::Deserialize))]pubenumArithmeticError{#[codec(index = 0u8)]Underflow,#[codec(index = 1u8)]Overflow,#[codec(index = 2u8)]DivisionByZero,}}/// ---------------------------------- Only including the types from `pallet_sudo`, all pallets in the metadata will have a sub-module/// ------- here with their types.pubmod pallet_sudo {usesuper::*;pubmod pallet {usesuper::*;#[doc = "The `Event` enum of this pallet"]#[derive(Clone,Debug,PartialEq,Eq,:: codec ::Encode,:: codec ::Decode)]#[cfg_attr( all(feature = "std", feature = "type_info"), derive(::scale_info::TypeInfo))]#[cfg_attr(feature = "serde", derive(::serde::Serialize,::serde::Deserialize))]pubenumSudoEvent{#[doc = "A sudo just took place. \\[result\\]"]#[codec(index = 0u8)]Sudid{sudo_result:Result<(), sp_runtime::DispatchError>,},#[doc = "The \\[sudoer\\] just switched identity; the old key is supplied if one existed."]#[codec(index = 1u8)]KeyChanged{old_sudoer:Option<::polymesh_api_client::AccountId>,},#[doc = "A sudo just took place. \\[result\\]"]#[codec(index = 2u8)]SudoAsDone{sudo_result:Result<(), sp_runtime::DispatchError>,},}implSudoEvent{pubfnas_static_str(&self) -> &'staticstr{#[allow(unreachable_patterns)]matchself{Self::Sudid{ .. } => "Sudo.Sudid",Self::KeyChanged{ .. } => "Sudo.KeyChanged",Self::SudoAsDone{ .. } => "Sudo.SudoAsDone",
_ => "Unknown",}}}#[cfg(not(feature = "ink"))]impl::polymesh_api_client::EnumInfoforSudoEvent{fnas_name(&self) -> &'staticstr{self.as_static_str()}fnas_docs(&self) -> &'static[&'staticstr]{# [allow (unreachable_patterns)]matchself{Self::Sudid{ .. } => {&["A sudo just took place. \\[result\\]",]},Self::KeyChanged{ .. } => {&["The \\[sudoer\\] just switched identity; the old key is supplied if one existed.",]},Self::SudoAsDone{ .. } => {&["A sudo just took place. \\[result\\]",]}, _ => &[""],}}}implFrom<SudoEvent>for&'staticstr{fnfrom(v:SudoEvent) -> Self{
v.as_static_str()}}implFrom<&SudoEvent>for&'staticstr{fnfrom(v:&SudoEvent) -> Self{
v.as_static_str()}}#[doc = "Contains a variant per dispatchable extrinsic that this pallet has."]#[derive(Clone,Debug,PartialEq,Eq,:: codec ::Encode,:: codec ::Decode)]#[cfg_attr( all(feature = "std", feature = "type_info"), derive(::scale_info::TypeInfo))]#[cfg_attr(feature = "serde", derive(::serde::Serialize,::serde::Deserialize))]pubenumSudoCall{#[doc = "See [`Pallet::sudo`]."]#[codec(index = 0u8)]
sudo {call:::alloc::boxed::Box<runtime::RuntimeCall>,},#[doc = "See [`Pallet::sudo_unchecked_weight`]."]#[codec(index = 1u8)]
sudo_unchecked_weight {call:::alloc::boxed::Box<runtime::RuntimeCall>,weight:::polymesh_api_client::sp_weights::Weight,},#[doc = "See [`Pallet::set_key`]."]#[codec(index = 2u8)]
set_key {new:::polymesh_api_client::MultiAddress<::polymesh_api_client::AccountId,u32>,},#[doc = "See [`Pallet::sudo_as`]."]#[codec(index = 3u8)]
sudo_as {who:::polymesh_api_client::MultiAddress<::polymesh_api_client::AccountId,u32>,call:::alloc::boxed::Box<runtime::RuntimeCall>,},}implSudoCall{pubfnas_static_str(&self) -> &'staticstr{#[allow(unreachable_patterns)]matchself{Self::sudo{ .. } => "Sudo.sudo",Self::sudo_unchecked_weight{ .. } => "Sudo.sudo_unchecked_weight",Self::set_key{ .. } => "Sudo.set_key",Self::sudo_as{ .. } => "Sudo.sudo_as",
_ => "Unknown",}}}#[cfg(not(feature = "ink"))]impl::polymesh_api_client::EnumInfoforSudoCall{fnas_name(&self) -> &'staticstr{self.as_static_str()}fnas_docs(&self) -> &'static[&'staticstr]{#[allow(unreachable_patterns)]matchself{Self::sudo{ .. } => &["See [`Pallet::sudo`]."],Self::sudo_unchecked_weight{ .. } => {&["See [`Pallet::sudo_unchecked_weight`]."]}Self::set_key{ .. } => &["See [`Pallet::set_key`]."],Self::sudo_as{ .. } => &["See [`Pallet::sudo_as`]."],
_ => &[""],}}}implFrom<SudoCall>for&'staticstr{fnfrom(v:SudoCall) -> Self{
v.as_static_str()}}implFrom<&SudoCall>for&'staticstr{fnfrom(v:&SudoCall) -> Self{
v.as_static_str()}}#[doc = "Error for the Sudo pallet"]#[derive(Clone,Debug,PartialEq,Eq,:: codec ::Encode,:: codec ::Decode)]#[cfg_attr( all(feature = "std", feature = "type_info"), derive(::scale_info::TypeInfo))]#[cfg_attr(feature = "serde", derive(::serde::Serialize,::serde::Deserialize))]pubenumSudoError{#[doc = "Sender must be the Sudo account"]#[codec(index = 0u8)]RequireSudo,}implSudoError{pubfnas_static_str(&self) -> &'staticstr{#[allow(unreachable_patterns)]matchself{Self::RequireSudo => "Sudo.RequireSudo",
_ => "Unknown",}}}#[cfg(not(feature = "ink"))]impl::polymesh_api_client::EnumInfoforSudoError{fnas_name(&self) -> &'staticstr{self.as_static_str()}fnas_docs(&self) -> &'static[&'staticstr]{#[allow(unreachable_patterns)]matchself{Self::RequireSudo => &["Sender must be the Sudo account"],
_ => &[""],}}}implFrom<SudoError>for&'staticstr{fnfrom(v:SudoError) -> Self{
v.as_static_str()}}implFrom<&SudoError>for&'staticstr{fnfrom(v:&SudoError) -> Self{
v.as_static_str()}}}}
The text was updated successfully, but these errors were encountered:
Continuing discussion from PR #1155 : #1155 (comment)
I hope that the details below is helpful to
subxt
.The codegen (crate
polymesh-api-codegen
) that is used forpolymesh-api
has support for generating code for both RPC clients (std native and no_std web) & Ink!.The generated code uses feature flag
ink
to support ink and not-ink clients. Thetype_info
feature flagis used to derive
scale-info::TypeInfo
for the chain types.Ink! also requires some other derives (
SpreadLayout
andPackedLayout
) to be able to the chain types in contract storage.I haven't come up with away to auto-detect which ink derives should be used for the generated types so for now the generator has a list of custom types which should have extra
#[derive(...)]
code:https://github.com/PolymeshAssociation/polymesh-api/blob/c444e452b0401d40694ba326042f56a5617d642f/crates/polymesh-api-codegen/src/generate.rs#L287
Here are some snips from generated code (used the Substrate
node-template
).I used the
dump_codegen.rs
example frompolymesh-api-codegen
to generator the code.https://github.com/PolymeshAssociation/polymesh-api/blob/main/crates/polymesh-api-codegen/dump_codegen.sh
I added some notes prefixed with
----
The text was updated successfully, but these errors were encountered: