mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 09:21:05 +00:00
Example: How to connect to parachain (#1043)
* parachain rpc lists * guide almost done * add the 3rd config * subscribe to block with configs * delete table file * spaces instead of tabs * remove original ajuna example * zombienet setup * nft minting example * include port, use different names * link the example from the book * format book * add config creation to book, simplify example structure * fix the nft creation script * fix doc ref * fixing links to foreign crates * fix table formatting * include nits * move more docs to book, and simplify parachain-example * another pass over docs and link to exampels from guide * nit: adjust comment to numbers * teeny README fix for parachain-example * fix command in readme * add CI for examples and fix parachain-example bug I left in * add target arch * cargo fmt * make CI not fail * remove index from docs --------- Co-authored-by: James Wilson <james@jsdw.me>
This commit is contained in:
Generated
+4587
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "parachain-example"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[workspace]
|
||||
|
||||
[dependencies]
|
||||
subxt = { path = "../../subxt" }
|
||||
subxt-signer = { path = "../../signer", features = ["subxt"] }
|
||||
futures = { version = "0.3.27", default-features = false, features = ["std"] }
|
||||
tokio = { version = "1.28", features = ["macros", "time", "rt-multi-thread"] }
|
||||
sp-core = "21.0.0"
|
||||
sp-runtime = "24.0.0"
|
||||
codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false }
|
||||
scale-decode = "0.7.0"
|
||||
scale-encode = "0.3.0"
|
||||
@@ -0,0 +1,78 @@
|
||||
# parachain-example
|
||||
|
||||
This example showcases working with Subxt and Zombienet to try out connecting to a locally deployed parachain, here
|
||||
["Statemint"](https://parachains.info/details/statemint), also known as "Asset Hub".
|
||||
|
||||
## Running the example
|
||||
|
||||
### 1. Install `zombienet`
|
||||
|
||||
[Zombienet](https://github.com/paritytech/zombienet) is a tool for quickly spinning up a (local) blockchain
|
||||
network. We will use it to start up a local Asset Hub for us.
|
||||
|
||||
Please follow the install guide in the [zombienet github repo](https://github.com/paritytech/zombienet) to
|
||||
install it.
|
||||
|
||||
### 2. `polkadot`
|
||||
|
||||
We need a relay chain. Build the polkadot binary from the [polkadot github repo](https://github.com/paritytech/polkadot)
|
||||
and install it in your path:
|
||||
|
||||
```txt
|
||||
git clone https://github.com/paritytech/polkadot.git
|
||||
cd polkadot
|
||||
cargo install --path .
|
||||
```
|
||||
|
||||
### 3. `polkadot-parachain`
|
||||
|
||||
The Asset Hub is part of the [cumulus github repo](https://github.com/paritytech/cumulus), an SDK for developing
|
||||
parachains. Building the cumulus workspace produces a binary called `polkadot-parachain` which can be used to run
|
||||
Asset Hub nodes.
|
||||
|
||||
```txt
|
||||
git clone https://github.com/paritytech/cumulus.git
|
||||
cd cumulus
|
||||
cargo install --path polkadot-parachain
|
||||
```
|
||||
|
||||
### 4. Run the parachain locally
|
||||
|
||||
With these binaries installed, Zombienet can now get the parachain running locally from a configuration file, `asset-hub-zombienet.toml`
|
||||
in this case. We need to have at least 2 validator nodes running via the `polkadot` binary, and an Asset Hub node running via the
|
||||
`polkadot-parachain` binary. Zombienet starts these up, and gets the parachain registered with the validator nodes for us. To do that,
|
||||
run:
|
||||
|
||||
```txt
|
||||
zombienet -p native spawn asset-hub-zombienet.toml
|
||||
```
|
||||
|
||||
Zombienet uses Kubernetes by default, but we can use it without Kubernetes by providing the `-p native` flag.
|
||||
|
||||
You might have noticed that we use `chain = "rococo-local"` in the `asset-hub-zombienet.toml` file for the relay chain. This is just to
|
||||
make the epoch time shorter and should have no effect on your interactions with the parachain. Polkadot / Kusama / Rococo have different
|
||||
epoch times of `24h` / `2h` / `2min` respectively.
|
||||
|
||||
### 5. Run the example
|
||||
|
||||
The parachain is only registered after the first epoch. So after the previous step, we need to wait 2 minutes until the parachain becomes
|
||||
interactive and produces blocks. At this point, we can run:
|
||||
|
||||
```
|
||||
cargo run --bin parachain-example
|
||||
```
|
||||
|
||||
To run our example code.
|
||||
|
||||
## Dev notes
|
||||
|
||||
We can obtain the metadata for Statemint via the [subxt cli](https://crates.io/crates/subxt-cli) tool, like so:
|
||||
|
||||
```txt
|
||||
subxt metadata --url wss://polkadot-asset-hub-rpc.polkadot.io:443 > statemint_metadata.scale
|
||||
```
|
||||
|
||||
It is important to explicitly specify the port as `443`.
|
||||
|
||||
One way to find a suitable URL to obtain this from is by looking through the sidebar on [Polkadot.js](https://polkadot.js.org/apps/)
|
||||
to find the Asset Hub entry, and seeing which RPC node URLs it uses.
|
||||
@@ -0,0 +1,26 @@
|
||||
[relaychain]
|
||||
default_image = "docker.io/parity/polkadot:latest"
|
||||
default_command = "polkadot"
|
||||
default_args = ["-lparachain=debug"]
|
||||
|
||||
chain = "rococo-local"
|
||||
|
||||
[[relaychain.nodes]]
|
||||
name = "alice"
|
||||
validator = true
|
||||
|
||||
[[relaychain.nodes]]
|
||||
name = "bob"
|
||||
validator = true
|
||||
|
||||
[[parachains]]
|
||||
id = 100
|
||||
chain = "asset-hub-polkadot-local"
|
||||
|
||||
[parachains.collator]
|
||||
name = "collator01"
|
||||
image = "docker.io/parity/polkadot-parachain:latest"
|
||||
ws_port = 42069
|
||||
command = "polkadot-parachain"
|
||||
args = ["-lparachain=debug"]
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
use subxt::{
|
||||
Config, PolkadotConfig, SubstrateConfig,
|
||||
utils::{AccountId32, MultiAddress},
|
||||
OnlineClient,
|
||||
};
|
||||
use subxt_signer::sr25519::dev::{self};
|
||||
|
||||
#[subxt::subxt(runtime_metadata_path = "statemint_metadata.scale")]
|
||||
pub mod statemint {}
|
||||
|
||||
/// Custom config that works with Statemint:
|
||||
pub enum StatemintConfig {}
|
||||
|
||||
impl Config for StatemintConfig {
|
||||
type Hash = <PolkadotConfig as Config>::Hash;
|
||||
type AccountId = <PolkadotConfig as Config>::AccountId;
|
||||
type Address = <PolkadotConfig as Config>::Address;
|
||||
type Signature = <PolkadotConfig as Config>::Signature;
|
||||
type Hasher = <PolkadotConfig as Config>::Hasher;
|
||||
type Header = <PolkadotConfig as Config>::Header;
|
||||
type ExtrinsicParams = <SubstrateConfig as Config>::ExtrinsicParams;
|
||||
}
|
||||
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() {
|
||||
if let Err(err) = run().await {
|
||||
eprintln!("{err}");
|
||||
}
|
||||
}
|
||||
|
||||
async fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// (the port 42069 is specified in the asset-hub-zombienet.toml)
|
||||
let api = OnlineClient::<StatemintConfig>::from_url("ws://127.0.0.1:42069").await?;
|
||||
println!("Connection with parachain established.");
|
||||
|
||||
let alice: MultiAddress<AccountId32, ()> = dev::alice().public_key().into();
|
||||
let alice_pair_signer = dev::alice();
|
||||
|
||||
const COLLECTION_ID: u32 = 12;
|
||||
const NTF_ID: u32 = 234;
|
||||
|
||||
// create a collection with id `12`
|
||||
let collection_creation_tx = statemint::tx()
|
||||
.uniques()
|
||||
.create(COLLECTION_ID, alice.clone());
|
||||
let _collection_creation_events = api
|
||||
.tx()
|
||||
.sign_and_submit_then_watch_default(&collection_creation_tx, &alice_pair_signer)
|
||||
.await
|
||||
.map(|e| {
|
||||
println!("Collection creation submitted, waiting for transaction to be finalized...");
|
||||
e
|
||||
})?
|
||||
.wait_for_finalized_success()
|
||||
.await?;
|
||||
println!("Collection created.");
|
||||
|
||||
// create an nft in that collection with id `234`
|
||||
let nft_creation_tx = statemint::tx()
|
||||
.uniques()
|
||||
.mint(COLLECTION_ID, NTF_ID, alice.clone());
|
||||
let _nft_creation_events = api
|
||||
.tx()
|
||||
.sign_and_submit_then_watch_default(&nft_creation_tx, &alice_pair_signer)
|
||||
.await
|
||||
.map(|e| {
|
||||
println!("NFT creation submitted, waiting for transaction to be finalized...");
|
||||
e
|
||||
})?
|
||||
.wait_for_finalized_success()
|
||||
.await?;
|
||||
println!("NFT created.");
|
||||
|
||||
// check in storage, that alice is the official owner of the NFT:
|
||||
let nft_owner_storage_query = statemint::storage().uniques().asset(COLLECTION_ID, NTF_ID);
|
||||
let nft_storage_details = api
|
||||
.storage()
|
||||
.at_latest()
|
||||
.await?
|
||||
.fetch(&nft_owner_storage_query)
|
||||
.await?
|
||||
.ok_or("The NFT should have an owner (alice)")?;
|
||||
|
||||
// make sure that alice is the owner of the NFT:
|
||||
assert_eq!(nft_storage_details.owner, dev::alice().public_key().into());
|
||||
println!("Storage Item Details: {:?}", nft_storage_details);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user