Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add subxt documentation #546

Merged
merged 62 commits into from
Jun 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
555e5ae
Documentation for cli crate
lexnv May 12, 2022
f746ebe
codegen: Add documentation and simplify calls generation
lexnv May 12, 2022
aa644af
codegen: Add documentation and simplify events generation
lexnv May 12, 2022
ddc41e7
codegen: Add documentation and simplify constants generation
lexnv May 12, 2022
4371c3d
codegen: Add documentation and simplify storage generation
lexnv May 13, 2022
0aaffcf
codegen: Add lib documentation
lexnv May 17, 2022
99e8fc6
macro: Remove `-f bytes` as this is the default
lexnv May 17, 2022
2330789
subxt/client: Add examples
lexnv May 17, 2022
ddff5f6
lib_doc: Add documentation to dedicated file
lexnv May 17, 2022
05e5fc0
Link documentation from file
lexnv May 17, 2022
687de56
subxt: Add more documentation
lexnv May 18, 2022
d8238fd
subxt: Add Storage example
lexnv May 19, 2022
9fc2e76
Add rpc documentation
lexnv May 19, 2022
1273177
metadata: Add documentation for errors
lexnv May 19, 2022
7336388
Add documentation for the `extrinsic` module
lexnv May 19, 2022
c622cc7
Add documentation for `events` module
lexnv May 19, 2022
c18b7ae
subxt: Add `Static Metadata Validation` section
lexnv May 19, 2022
6ccc6d5
subxt: Add `Runtime Updates` section
lexnv May 19, 2022
4985f8a
Fix link to documentation
lexnv May 19, 2022
b01cc32
readme: Remove hardcoded versions
lexnv May 19, 2022
2737234
Merge remote-tracking branch 'origin/master' into add_documentation
lexnv May 19, 2022
0e4bf20
Move documentation to dedicated folder
lexnv May 23, 2022
2990736
Spaces between examples
lexnv May 23, 2022
84e868a
More details for `types_mod_ident`
lexnv May 23, 2022
b1c8de4
Add note for RuntimeGenerator
lexnv May 23, 2022
0ab9457
Address feedback
lexnv May 23, 2022
6f99876
Update codegen/src/api/constants.rs
lexnv May 23, 2022
7691c13
Update subxt/src/lib.rs
lexnv May 23, 2022
713622e
Update subxt/src/metadata/metadata_type.rs
lexnv May 23, 2022
3bcea02
Update subxt/src/storage.rs
lexnv May 23, 2022
095b538
Address feedback
lexnv May 23, 2022
86ea6e5
Merge remote-tracking branch 'origin/542_add_documentation' into 542_…
lexnv May 24, 2022
9481741
Fix cargo clippy
lexnv May 24, 2022
1c7d957
Update call example
lexnv May 24, 2022
6c0a938
Add example for fetching constants
lexnv May 24, 2022
5ca15f7
Link to examples in subxt.md
lexnv May 24, 2022
0f94d73
Update codegen/src/api/calls.rs
lexnv Jun 14, 2022
dec55ee
Update codegen/src/api/calls.rs
lexnv Jun 14, 2022
ce04e6f
Update codegen/src/api/calls.rs
lexnv Jun 14, 2022
89a08bc
Update codegen/src/api/constants.rs
lexnv Jun 14, 2022
bd7263b
Update codegen/src/api/constants.rs
lexnv Jun 14, 2022
9754939
Update codegen/src/api/storage.rs
lexnv Jun 14, 2022
60ef08e
Update codegen/src/api/storage.rs
lexnv Jun 14, 2022
4819012
Update codegen/src/api/storage.rs
lexnv Jun 14, 2022
5dccd1a
Update docs/subxt.md
lexnv Jun 14, 2022
611c691
Update docs/subxt.md
lexnv Jun 14, 2022
ef4ea2a
Update docs/subxt.md
lexnv Jun 14, 2022
3a2163a
Update docs/subxt.md
lexnv Jun 14, 2022
2565211
Update docs/subxt.md
lexnv Jun 14, 2022
ced6ba0
Update subxt/src/extrinsic/mod.rs
lexnv Jun 14, 2022
2764069
Update subxt/src/storage.rs
lexnv Jun 14, 2022
b5b9795
Update documentation
lexnv Jun 14, 2022
913ec84
Merge remote-tracking branch 'origin/master' into 542_add_documentation
lexnv Jun 14, 2022
561ddfc
Update examples/examples/balance_transfer.rs
lexnv Jun 14, 2022
b907a72
Update subxt/src/extrinsic/mod.rs
lexnv Jun 14, 2022
2add050
Update subxt/src/rpc.rs
lexnv Jun 14, 2022
0443467
Update subxt/src/updates.rs
lexnv Jun 14, 2022
74d7234
Update docs example with `PolkadotExtrinsicParams`
lexnv Jun 14, 2022
85ba207
subxt: Remove extrinsic extra documentation
lexnv Jun 14, 2022
0be0dde
Merge remote-tracking branch 'origin/542_add_documentation' into 542_…
lexnv Jun 14, 2022
4a0da2e
examples: Remove similar transfer example
lexnv Jun 14, 2022
aa90ae7
Apply cargo fmt
lexnv Jun 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 4 additions & 66 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,81 +22,19 @@ subxt metadata -f bytes > metadata.scale
This defaults to querying the metadata of a locally running node on the default `http://localhost:9933/`. If querying
a different node then the `metadata` command accepts a `--url` argument.

### Generating the runtime API from the downloaded metadata
## Subxt Documentation

Declare a module and decorate it with the `subxt` attribute which points at the downloaded metadata for the
target runtime:

```rust
#[subxt::subxt(runtime_metadata_path = "metadata.scale")]
pub mod node_runtime { }
```

**Important:** `runtime_metadata_path` resolves to a path relative to the directory where your crate's `Cargo.toml`
resides ([`CARGO_MANIFEST_DIR`](https://doc.rust-lang.org/cargo/reference/environment-variables.html)), *not* relative to the source file.

### Initializing the API client

```rust
use subxt::{ClientBuilder, DefaultConfig, SubstrateExtrinsicParams};

let api = ClientBuilder::new()
.set_url("wss://rpc.polkadot.io:443")
.build()
.await?
.to_runtime_api::<node_runtime::RuntimeApi<DefaultConfig, SubstrateExtrinsicParams<DefaultConfig>>>();
```

The `RuntimeApi` type is generated by the `subxt` macro from the supplied metadata. This can be parameterized with user
supplied implementations for the `Config` and `Extra` types, if the default implementations differ from the target
chain.

### Querying Storage

Call the generated `RuntimeApi::storage()` method, followed by the `pallet_name()` and then the `storage_item_name()`.

So in order to query `Balances::TotalIssuance`:

```rust
let total_issuance = api
.storage()
.balances()
.total_issuance(None)
.await
.unwrap()
```

### Submitting Extrinsics

Submit an extrinsic, returning success once the transaction is validated and accepted into the pool:

```rust
use sp_keyring::AccountKeyring;
use subxt::PairSigner;

let signer = PairSigner::new(AccountKeyring::Alice.pair());
let dest = AccountKeyring::Bob.to_account_id().into();

let tx_hash = api
.tx()
.balances()
.transfer(dest, 10_000)
.sign_and_submit(&signer)
.await?;
```

For more advanced usage, which can wait for block inclusion and return any events triggered by the extrinsic, see the
[balance transfer example](./examples/examples/balance_transfer.rs).
For more details regarding utilizing subxt, please visit the [documentation](docs/subxt.md).

## Integration Testing

Most tests require a running substrate node to communicate with. This is done by spawning an instance of the
substrate node per test. It requires an executable binary `substrate` at [`polkadot-v0.9.10`](https://github.com/paritytech/substrate/releases/tag/polkadot-v0.9.10) on your path.
substrate node per test. It requires an up-to-date `substrate` executable on your path.

This can be installed from source via cargo:

```bash
cargo install --git https://github.com/paritytech/substrate node-cli --tag=polkadot-v0.9.10 --force
cargo install --git https://github.com/paritytech/substrate node-cli --force
```

## Real world usage
Expand Down
8 changes: 4 additions & 4 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ enum Command {
/// Download metadata from a substrate node, for use with `subxt` codegen.
#[structopt(name = "metadata")]
Metadata {
/// the url of the substrate node to query for metadata
/// The url of the substrate node to query for metadata.
#[structopt(
name = "url",
long,
parse(try_from_str),
default_value = "http://localhost:9933"
)]
url: url::Url,
/// the format of the metadata to display: `json`, `hex` or `bytes`
/// The format of the metadata to display: `json`, `hex` or `bytes`.
#[structopt(long, short, default_value = "bytes")]
format: String,
},
Expand All @@ -81,10 +81,10 @@ enum Command {
///
/// `subxt codegen | rustfmt --edition=2018 --emit=stdout`
Codegen {
/// the url of the substrate node to query for metadata for codegen.
/// The url of the substrate node to query for metadata for codegen.
#[structopt(name = "url", long, parse(try_from_str))]
url: Option<url::Url>,
/// the path to the encoded metadata file.
/// The path to the encoded metadata file.
#[structopt(short, long, parse(from_os_str))]
file: Option<PathBuf>,
/// Additional derives
Expand Down
41 changes: 39 additions & 2 deletions codegen/src/api/calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ use crate::types::{
};
use frame_metadata::{
v14::RuntimeMetadataV14,
PalletCallMetadata,
PalletMetadata,
};
use heck::{
Expand All @@ -35,13 +34,51 @@ use quote::{
};
use scale_info::form::PortableForm;

/// Generate calls from the provided pallet's metadata.
///
/// The function creates a new module named `calls` under the pallet's module.
/// ```ignore
/// pub mod PalletName {
/// pub mod calls {
/// ...
/// }
/// }
/// ```
///
/// The function generates the calls as rust structs that implement the `subxt::Call` trait
/// to uniquely identify the call's identity when creating the extrinsic.
///
/// ```ignore
/// pub struct CallName {
/// pub call_param: type,
/// }
/// impl ::subxt::Call for CallName {
/// ...
/// }
/// ```
///
/// Calls are extracted from the API and wrapped into the generated `TransactionApi` of
/// each module.
///
/// # Arguments
///
/// - `metadata` - Runtime metadata from which the calls are generated.
/// - `type_gen` - The type generator containing all types defined by metadata.
/// - `pallet` - Pallet metadata from which the calls are generated.
/// - `types_mod_ident` - The ident of the base module that we can use to access the generated types from.
pub fn generate_calls(
metadata: &RuntimeMetadataV14,
type_gen: &TypeGenerator,
pallet: &PalletMetadata<PortableForm>,
call: &PalletCallMetadata<PortableForm>,
types_mod_ident: &syn::Ident,
) -> TokenStream2 {
// Early return if the pallet has no calls.
let call = if let Some(ref calls) = pallet.calls {
calls
} else {
return quote!()
};

let mut struct_defs = super::generate_structs_from_variants(
type_gen,
call.ty.id(),
Expand Down
31 changes: 29 additions & 2 deletions codegen/src/api/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
use crate::types::TypeGenerator;
use frame_metadata::{
v14::RuntimeMetadataV14,
PalletConstantMetadata,
PalletMetadata,
};
use heck::ToSnakeCase as _;
Expand All @@ -29,13 +28,41 @@ use quote::{
};
use scale_info::form::PortableForm;

/// Generate constants from the provided pallet's metadata.
///
/// The function creates a new module named `constants` under the pallet's module.
/// ```ignore
/// pub mod PalletName {
/// pub mod constants {
/// ...
/// }
/// }
/// ```
///
/// The constants are exposed via the `ConstantsApi` wrapper.
///
/// Although the constants are defined in the provided static metadata, the API
/// ensures that the constants are returned from the runtime metadata of the node.
/// This ensures that if the node's constants change value, we'll always see the latest values.
///
/// # Arguments
///
/// - `metadata` - Runtime metadata from which the calls are generated.
/// - `type_gen` - The type generator containing all types defined by metadata
/// - `pallet` - Pallet metadata from which the calls are generated.
/// - `types_mod_ident` - The ident of the base module that we can use to access the generated types from.
pub fn generate_constants(
metadata: &RuntimeMetadataV14,
type_gen: &TypeGenerator,
pallet: &PalletMetadata<PortableForm>,
constants: &[PalletConstantMetadata<PortableForm>],
types_mod_ident: &syn::Ident,
) -> TokenStream2 {
// Early return if the pallet has no constants.
if pallet.constants.is_empty() {
return quote!()
}
let constants = &pallet.constants;

let constant_fns = constants.iter().map(|constant| {
let fn_name = format_ident!("{}", constant.name.to_snake_case());
let pallet_name = &pallet.name;
Expand Down
41 changes: 36 additions & 5 deletions codegen/src/api/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,51 @@
// along with subxt. If not, see <http://www.gnu.org/licenses/>.

use crate::types::TypeGenerator;
use frame_metadata::{
PalletEventMetadata,
PalletMetadata,
};
use frame_metadata::PalletMetadata;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use scale_info::form::PortableForm;

/// Generate events from the provided pallet metadata.
///
/// The function creates a new module named `events` under the pallet's module.
/// ```ignore
/// pub mod PalletName {
/// pub mod events {
/// ...
/// }
/// }
/// ```
///
/// The function generates the events as rust structs that implement the `subxt::Event` trait
/// to uniquely identify the event's identity when creating the extrinsic.
///
/// ```ignore
/// pub struct EventName {
/// pub event_param: type,
/// }
/// impl ::subxt::Event for EventName {
/// ...
/// }
/// ```
///
/// # Arguments
///
/// - `type_gen` - The type generator containing all types defined by metadata.
/// - `pallet` - Pallet metadata from which the events are generated.
/// - `types_mod_ident` - The ident of the base module that we can use to access the generated types from.
pub fn generate_events(
type_gen: &TypeGenerator,
pallet: &PalletMetadata<PortableForm>,
event: &PalletEventMetadata<PortableForm>,
types_mod_ident: &syn::Ident,
) -> TokenStream2 {
// Early return if the pallet has no events.
let event = if let Some(ref event) = pallet.event {
event
} else {
return quote!()
};

let struct_defs = super::generate_structs_from_variants(
type_gen,
event.ty.id(),
Expand Down
Loading