From a4ac88021b6f68ac8c93a8a832c0f4b7314aa3f4 Mon Sep 17 00:00:00 2001 From: Erin Shaben Date: Mon, 30 Sep 2024 11:49:06 -0400 Subject: [PATCH] Merge remote-tracking branch 'origin/master' into nhussein11/tutorials-substrate-acquire-a-testnet-slot --- .CONTRIBUTING.md | 38 ++- .gitignore | 1 + .husky/pre-commit | 11 + .../overview/localParachainTx.md | 24 ++ .../overview/localParachainTx.ts | 37 +++ .../asset-transfer-api/overview/paraToPara.md | 87 ++++++ .../asset-transfer-api/overview/paraToPara.ts | 36 +++ .../overview/relayToSystem.md | 62 ++++ .../overview/relayToSystem.ts | 36 +++ .../asset-transfer-api/overview/setup.ts | 16 ++ .../reference/asset-transfer-type.md | 10 + .../reference/ca-example-request.ts | 35 +++ .../reference/ca-example-response.md | 12 + .../reference/ca-fn-signature.ts | 6 + .../reference/constructed-format.md | 15 + .../reference/ctt-example-request.ts | 34 +++ .../reference/ctt-example-response.md | 12 + .../reference/ctt-fn-signature.ts | 7 + .../reference/de-example-request.ts | 27 ++ .../reference/de-example-response.md | 11 + .../reference/de-fn-signature.ts | 4 + .../reference/ffi-example-request.ts | 25 ++ .../reference/ffi-example-response.md | 11 + .../reference/ffi-fn-signature.ts | 4 + .../asset-transfer-api/reference/format.ts | 1 + .../reference/transfer-arg-opts.md | 94 +++++++ .../asset-transfer-api/reference/tx-result.md | 148 ++++++++++ .../hrmp-channels/hrmp-query-output.json | 66 ++--- .../build-a-local-blockchain/node-output.html | 54 ++-- .../simulate-a-network/node-output-1.html | 38 +-- .../simulate-a-network/node-output.html | 50 ++-- .../testnet-slot-1.json | 2 +- .../testnet-slot-2.html | 12 +- .../connect-a-parachain-2.json | 2 +- .../connect-a-parachain-3.html | 8 +- .../connect-a-parachain-4.html | 4 +- .../connect-a-parachain-5.html | 20 +- .../connect-a-parachain-6.html | 48 ++-- .../prepare-relay-chain/relay-chain-1.html | 40 +-- .../prepare-relay-chain/relay-chain-2.html | 16 +- .../zombienet/overview/base-example.json | 4 +- .../zombienet/overview/base-example.toml | 4 +- .../zombienet/overview/collator-example.json | 30 +- .../zombienet/overview/collator-example.toml | 2 +- .../overview/collator-groups-example.json | 10 +- .../overview/collator-groups-example.toml | 2 +- .../zombienet/overview/parachain-example.json | 16 +- .../zombienet/overview/parachain-example.toml | 2 +- .../relaychain-example-node-groups.json | 7 +- .../relaychain-example-node-groups.toml | 2 +- .../overview/relaychain-example-nodes.toml | 2 +- develop/application-devs/interact/.pages | 1 + .../interact/light-clients.md | 50 ++++ develop/application-devs/tooling/.pages | 1 + .../tooling/asset-transfer-api/.pages | 6 + .../tooling/asset-transfer-api/index.md | 7 + .../tooling/asset-transfer-api/overview.md | 130 +++++++++ .../tooling/asset-transfer-api/reference.md | 266 ++++++++++++++++++ images/contributing/vale-output-01.webp | Bin 0 -> 36504 bytes package-lock.json | 43 +++ package.json | 17 ++ 61 files changed, 1534 insertions(+), 232 deletions(-) create mode 100644 .gitignore create mode 100755 .husky/pre-commit create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/localParachainTx.md create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/localParachainTx.ts create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/paraToPara.md create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/paraToPara.ts create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/relayToSystem.md create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/relayToSystem.ts create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/setup.ts create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/asset-transfer-type.md create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ca-example-request.ts create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ca-example-response.md create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ca-fn-signature.ts create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/constructed-format.md create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ctt-example-request.ts create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ctt-example-response.md create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ctt-fn-signature.ts create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/de-example-request.ts create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/de-example-response.md create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/de-fn-signature.ts create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ffi-example-request.ts create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ffi-example-response.md create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ffi-fn-signature.ts create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/format.ts create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/transfer-arg-opts.md create mode 100644 .snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/tx-result.md create mode 100644 develop/application-devs/interact/light-clients.md create mode 100644 develop/application-devs/tooling/asset-transfer-api/.pages create mode 100644 develop/application-devs/tooling/asset-transfer-api/index.md create mode 100644 develop/application-devs/tooling/asset-transfer-api/overview.md create mode 100644 develop/application-devs/tooling/asset-transfer-api/reference.md create mode 100644 images/contributing/vale-output-01.webp create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.CONTRIBUTING.md b/.CONTRIBUTING.md index 3fc113043..e5d820f55 100644 --- a/.CONTRIBUTING.md +++ b/.CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contribute to the Polkadot Developer Docs -The documentation source files are written in [Markdown](https://daringfireball.net/projects/markdown) and generally follow the [PaperMoon style guide](https://github.com/papermoonio/documentation-style-guide/blob/main/style-guide.md). If the PaperMoon style guide does not provide explicit guidance on a particular subject, please default to the [Google developer documentation style guide](https://developers.google.com/style). +The documentation source files are written in [Markdown](https://daringfireball.net/projects/markdown) and generally follow the [PaperMoon style guide](https://github.com/papermoonio/documentation-style-guide/blob/main/style-guide.md). If the PaperMoon style guide doesn't provide explicit guidance on a particular subject, please default to the [Google developer documentation style guide](https://developers.google.com/style). This guide covers how to contribute to the documentation, including serving a local version of the site, adding new pages and directories, managing images and code snippets, and a few SEO tips. @@ -18,6 +18,7 @@ This guide covers how to contribute to the documentation, including serving a lo - [Adding Code and Text Snippets](#adding-code-and-text-snippets) - [Adding Images](#adding-images) - [Optimizing for SEO](#search-enging-optimization-seo) +- [Tools for Editing](#tools-for-editing) ## Viewing Site Locally @@ -27,9 +28,9 @@ You may want to spin up a local version of the documentation site to preview you Building and serving the site requires cloning two repositories: -- **[Polkadot MkDocs](https://github.com/papermoonio/polkadot-mkdocs)** - contains the MkDocs config files, theme overrides, and custom CSS for the Polkadot documentation site +- **[Polkadot MkDocs](https://github.com/papermoonio/polkadot-mkdocs)** - contains the MkDocs configuration files, theme overrides, and custom CSS for the Polkadot documentation site -- **[Polkadot Docs](https://github.com/polkadot-developers/polkadot-docs)** - the actual content is stored in the polkadot-docs repo and pulled into the polkadot-mkdocs directory during build +- **[Polkadot Docs](https://github.com/polkadot-developers/polkadot-docs)** - the actual content is stored in the `polkadot-docs` repository and pulled into the `polkadot-mkdocs` directory during build For everything to work correctly, the file structure needs to be as follows: @@ -65,7 +66,7 @@ To set up the structure, follow these steps: This command will install all dependencies listed in the `requirements.txt` file. -2. In the polkadot-mkdocs folder (which should be the current one), you can build the site by running: +2. In the `polkadot-mkdocs` folder (which should be the current one), you can build the site by running: ```bash mkdocs serve @@ -127,7 +128,7 @@ If you are adding pages to an existing section, the steps are simplified. Howeve - Add the new markdown page to the appropriate section. Note that the filename becomes part of the URL for this page. See the [style guide](https://github.com/papermoonio/documentation-style-guide/blob/main/style-guide.md#naming-conventions) for additional guidance on naming conventions. - Ensure the new content page includes the following: - **`title`** - represents the `` tag and is used for SEO purposes (not displayed on the published site) Titles have a maximum length of 45 characters. - - **`description`** - represents the meta-description and is also used for SEO purposes (not displayed on the published site). Descriptions should be between 120-160 characters and should provide a preview into the page topic. + - **`description`** - represents the meta-description and is also used for SEO purposes (not displayed on the published site). Descriptions should be 120-160 characters and should provide a preview into the page topic. - **Page title** - an H1 heading title to be displayed at the top of the page - **`## Checking Prerequisites` section** - if the guide requires the user to have specific developer tools installed, for example, Docker or MetaMask, it should be listed here @@ -168,7 +169,7 @@ More resources for [SEO Optimization](#search-engine-optimization-seo) of titles 3. Once you commit and push all of your changes, open a pull request for the new content branch against the `main` branch 4. Monitor notifications and pull requests for feedback from code owners. At least one approval is required before merging content -If your additions or modifications are limited to content on an existing page, there is no need to worry about the [`.pages`](#example-pages-file) or [`index.md`](#example-indexmd-file) files, as changes to page content do not affect these files. +If your additions or modifications are limited to content on an existing page, there is no need to worry about the [`.pages`](#example-pages-file) or [`index.md`](#example-indexmd-file) files, as changes to page content don't affect these files. ## Adding Code and Text Snippets @@ -208,3 +209,28 @@ Here are some resources to help you create good titles and descriptions for SEO: - [Google's recommendation on good descriptions](https://developers.google.com/search/docs/advanced/appearance/snippet?hl=en) In general, titles should be between 50 and 60 characters and descriptions should be between 120 and 160 characters. + +## Tools for Editing + +There are a few tools you may find useful for proofreading and editing your contributions: + +- **[Vale](https://vale.sh/)** - the `polkadot-mkdocs` repository contains configuration for Vale, an open source NLP-powered linter for text. The configuration is a work in progress with a growing custom dictionary tailored toward software engineering, blockchain, and Polkadot terms. Running Vale against your files locally can serve as a first round of feedback to speed up the review process + +To use Vale locally to screen your work: + +1. Visit the Vale site and follow the [installation instructions](https://vale.sh/docs/vale-cli/installation/) +2. From the `polkadot-mkdocs` directory, run the following in your terminal: + + ```bash + vale INSERT_PATH_TO_FILE + ``` + + The output will look something like: + + ![Vale sample terminal output](images/contributing/vale-output-01.webp) + +3. You can use CMD+click to open the file with the flagged items. This is especially helpful if you run Vale against a directory with multiple files + +4. Each flag tells you the line and location of the flagged item, the level of the flag (error, warning, or suggestion), and a suggestion for how to resolve the flag + +5. Once you have addressed the flagged items and made edits as needed, you can complete the normal steps to commit your changes and open a pull request to review for merge \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..b512c09d4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 000000000..a07e2a6aa --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,11 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +echo "Running Prettier on .snippets/code/**/*.{js,json,html}" +npx prettier --write .snippets/code/**/*.{js,json,html} + +echo "Running Taplo to format TOML files" +npx taplo fmt .snippets/code/**/*.toml + +echo "Adding formatted files back to the commit..." +git add .snippets/code/**/*.{js,json,html,toml} diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/localParachainTx.md b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/localParachainTx.md new file mode 100644 index 000000000..58667b413 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/localParachainTx.md @@ -0,0 +1,24 @@ +<div id="termynal" data-termynal> + <span data-ty="input"><span class="file-path"></span>ts-node localParachainTx.ts</span> + <br> + <span data-ty>Call data:</span> + <span data-ty>{</span> + <span data-ty> "origin": "moonbeam",</span> + <span data-ty> "dest": "moonbeam",</span> + <span data-ty> "direction": "local",</span> + <span data-ty> "xcmVersion": null,</span> + <span data-ty> "method": "balances::transferKeepAlive",</span> + <span data-ty> "format": "call",</span> + <span data-ty> "tx": "0x0a03f977814e90da44bfa03b6295a0616a897441acec821a0600"</span> + <span data-ty>}</span> + <span data-ty></span> + <span data-ty>Decoded tx:</span> + <span data-ty>{</span> + <span data-ty> "args": {</span> + <span data-ty> "dest": "0xF977814e90dA44bFA03b6295A0616a897441aceC",</span> + <span data-ty> "value": "1,000,000,000,000,000,000"</span> + <span data-ty> },</span> + <span data-ty> "method": "transferKeepAlive",</span> + <span data-ty> "section": "balances"</span> + <span data-ty>}</span> +</div> \ No newline at end of file diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/localParachainTx.ts b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/localParachainTx.ts new file mode 100644 index 000000000..a2a6453b6 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/localParachainTx.ts @@ -0,0 +1,37 @@ +import { + AssetTransferApi, + constructApiPromise, +} from "@substrate/asset-transfer-api"; + +async function main() { + const { api, specName, safeXcmVersion } = await constructApiPromise( + "wss://wss.api.moonbeam.network" + ); + const assetApi = new AssetTransferApi(api, specName, safeXcmVersion); + + let callInfo; + try { + callInfo = await assetApi.createTransferTransaction( + "2004", + "0xF977814e90dA44bFA03b6295A0616a897441aceC", + [], + ["1000000000000000000"], + { + format: "call", + keepAlive: true, + } + ); + + console.log(`Call data:\n${JSON.stringify(callInfo, null, 4)}`); + } catch (e) { + console.error(e); + throw Error(e as string); + } + + const decoded = assetApi.decodeExtrinsic(callInfo.tx, "call"); + console.log(`\nDecoded tx:\n${JSON.stringify(JSON.parse(decoded), null, 4)}`); +} + +main() + .catch((err) => console.error(err)) + .finally(() => process.exit()); diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/paraToPara.md b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/paraToPara.md new file mode 100644 index 000000000..ff1535601 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/paraToPara.md @@ -0,0 +1,87 @@ +<div id='termynal' data-termynal> + <span data-ty='input'><span class='file-path'></span>ts-node paraToPara.ts</span> + + <br> + <span data-ty>Call data:</span> + <span data-ty>{</span> + <span data-ty> "origin": "moonriver",</span> + <span data-ty> "dest": "bifrost",</span> + <span data-ty> "direction": "ParaToPara",</span> + <span data-ty> "xcmVersion": 2,</span> + <span data-ty> "method": "transferMultiassets",</span> + <span data-ty> "format": "call",</span> + <span data-ty> "tx": "0x6a05010800010200451f06080101000700e40b540200010200451f0608010a0002093d000000000001010200451f0100c4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a06300"</span> + <span data-ty>}</span> + <span data-ty></span> + <span data-ty>Decoded tx:</span> + <span data-ty>{</span> + <span data-ty> "args": {</span> + <span data-ty> "assets": {</span> + <span data-ty> "V2": [</span> + <span data-ty> {</span> + <span data-ty> "id": {</span> + <span data-ty> "Concrete": {</span> + <span data-ty> "parents": "1",</span> + <span data-ty> "interior": {</span> + <span data-ty> "X2": [</span> + <span data-ty> {</span> + <span data-ty> "Parachain": "2,001"</span> + <span data-ty> },</span> + <span data-ty> {</span> + <span data-ty> "GeneralKey": "0x0101"</span> + <span data-ty> }</span> + <span data-ty> ]</span> + <span data-ty> }</span> + <span data-ty> }</span> + <span data-ty> },</span> + <span data-ty> "fun": {</span> + <span data-ty> "Fungible": "10,000,000,000"</span> + <span data-ty> }</span> + <span data-ty> },</span> + <span data-ty> {</span> + <span data-ty> "id": {</span> + <span data-ty> "Concrete": {</span> + <span data-ty> "parents": "1",</span> + <span data-ty> "interior": {</span> + <span data-ty> "X2": [</span> + <span data-ty> {</span> + <span data-ty> "Parachain": "2,001"</span> + <span data-ty> },</span> + <span data-ty> {</span> + <span data-ty> "GeneralKey": "0x010a"</span> + <span data-ty> }</span> + <span data-ty> ]</span> + <span data-ty> }</span> + <span data-ty> }</span> + <span data-ty> },</span> + <span data-ty> "fun": {</span> + <span data-ty> "Fungible": "1,000,000"</span> + <span data-ty> }</span> + <span data-ty> }</span> + <span data-ty> ]</span> + <span data-ty> },</span> + <span data-ty> "fee_item": "0",</span> + <span data-ty> "dest": {</span> + <span data-ty> "V2": {</span> + <span data-ty> "parents": "1",</span> + <span data-ty> "interior": {</span> + <span data-ty> "X2": [</span> + <span data-ty> {</span> + <span data-ty> "Parachain": "2,001"</span> + <span data-ty> },</span> + <span data-ty> {</span> + <span data-ty> "AccountId32": {</span> + <span data-ty> "network": "Any",</span> + <span data-ty> "id": "0xc4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a063"</span> + <span data-ty> }</span> + <span data-ty> }</span> + <span data-ty> ]</span> + <span data-ty> }</span> + <span data-ty> }</span> + <span data-ty> },</span> + <span data-ty> "dest_weight_limit": "Unlimited"</span> + <span data-ty> },</span> + <span data-ty> "method": "transferMultiassets",</span> + <span data-ty> "section": "xTokens"</span> + <span data-ty>}</span> +</div> \ No newline at end of file diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/paraToPara.ts b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/paraToPara.ts new file mode 100644 index 000000000..c5dbd7809 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/paraToPara.ts @@ -0,0 +1,36 @@ +import { + AssetTransferApi, + constructApiPromise, +} from "@substrate/asset-transfer-api"; + +async function main() { + const { api, specName, safeXcmVersion } = await constructApiPromise( + "wss://moonriver.public.blastapi.io" + ); + const assetApi = new AssetTransferApi(api, specName, safeXcmVersion); + let callInfo; + try { + callInfo = await assetApi.createTransferTransaction( + "2001", + "0xc4db7bcb733e117c0b34ac96354b10d47e84a006b9e7e66a229d174e8ff2a063", + ["vMOVR", "72145018963825376852137222787619937732"], + ["1000000", "10000000000"], + { + format: "call", + xcmVersion: safeXcmVersion, + } + ); + + console.log(`Call data:\n${JSON.stringify(callInfo, null, 4)}`); + } catch (e) { + console.error(e); + throw Error(e as string); + } + + const decoded = assetApi.decodeExtrinsic(callInfo.tx, "call"); + console.log(`\nDecoded tx:\n${JSON.stringify(JSON.parse(decoded), null, 4)}`); +} + +main() + .catch((err) => console.error(err)) + .finally(() => process.exit()); diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/relayToSystem.md b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/relayToSystem.md new file mode 100644 index 000000000..dea06e3b5 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/relayToSystem.md @@ -0,0 +1,62 @@ +<div id="termynal" data-termynal> + <span data-ty="input"><span class="file-path"></span>ts-node relayToSystem.ts</span> + <br> + <span data-ty>Call data:</span> + <span data-ty>{</span> + <span data-ty> "origin": "westend",</span> + <span data-ty> "dest": "westmint",</span> + <span data-ty> "direction": "RelayToSystem",</span> + <span data-ty> "xcmVersion": 3,</span> + <span data-ty> "method": "transferAssets",</span> + <span data-ty> "format": "call",</span> + <span data-ty> "tx": "0x630b03000100a10f03000101006c0c32faf970eacb2d4d8e538ac0dab3642492561a1be6f241c645876c056c1d030400000000070010a5d4e80000000000"</span> + <span data-ty>}</span> + <span data-ty></span> + <span data-ty>Decoded tx:</span> + <span data-ty>{</span> + <span data-ty> "args": {</span> + <span data-ty> "dest": {</span> + <span data-ty> "V3": {</span> + <span data-ty> "parents": "0",</span> + <span data-ty> "interior": {</span> + <span data-ty> "X1": {</span> + <span data-ty> "Parachain": "1,000"</span> + <span data-ty> }</span> + <span data-ty> }</span> + <span data-ty> }</span> + <span data-ty> },</span> + <span data-ty> "beneficiary": {</span> + <span data-ty> "V3": {</span> + <span data-ty> "parents": "0",</span> + <span data-ty> "interior": {</span> + <span data-ty> "X1": {</span> + <span data-ty> "AccountId32": {</span> + <span data-ty> "network": null,</span> + <span data-ty> "id": "0x6c0c32faf970eacb2d4d8e538ac0dab3642492561a1be6f241c645876c056c1d"</span> + <span data-ty> }</span> + <span data-ty> }</span> + <span data-ty> }</span> + <span data-ty> }</span> + <span data-ty> },</span> + <span data-ty> "assets": {</span> + <span data-ty> "V3": [</span> + <span data-ty> {</span> + <span data-ty> "id": {</span> + <span data-ty> "Concrete": {</span> + <span data-ty> "parents": "0",</span> + <span data-ty> "interior": "Here"</span> + <span data-ty> }</span> + <span data-ty> },</span> + <span data-ty> "fun": {</span> + <span data-ty> "Fungible": "1,000,000,000,000"</span> + <span data-ty> }</span> + <span data-ty> }</span> + <span data-ty> ]</span> + <span data-ty> },</span> + <span data-ty> "fee_asset_item": "0",</span> + <span data-ty> "weight_limit": "Unlimited"</span> + <span data-ty> },</span> + <span data-ty> "method": "transferAssets",</span> + <span data-ty> "section": "xcmPallet"</span> + <span data-ty>}</span> +</div> \ No newline at end of file diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/relayToSystem.ts b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/relayToSystem.ts new file mode 100644 index 000000000..ead3c4be5 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/relayToSystem.ts @@ -0,0 +1,36 @@ +import { + AssetTransferApi, + constructApiPromise, +} from "@substrate/asset-transfer-api"; + +async function main() { + const { api, specName, safeXcmVersion } = await constructApiPromise( + "wss://westend-rpc.polkadot.io" + ); + const assetApi = new AssetTransferApi(api, specName, safeXcmVersion); + let callInfo; + try { + callInfo = await assetApi.createTransferTransaction( + "1000", + "5EWNeodpcQ6iYibJ3jmWVe85nsok1EDG8Kk3aFg8ZzpfY1qX", + ["WND"], + ["1000000000000"], + { + format: "call", + xcmVersion: safeXcmVersion, + } + ); + + console.log(`Call data:\n${JSON.stringify(callInfo, null, 4)}`); + } catch (e) { + console.error(e); + throw Error(e as string); + } + + const decoded = assetApi.decodeExtrinsic(callInfo.tx, "call"); + console.log(`\nDecoded tx:\n${JSON.stringify(JSON.parse(decoded), null, 4)}`); +} + +main() + .catch((err) => console.error(err)) + .finally(() => process.exit()); diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/setup.ts b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/setup.ts new file mode 100644 index 000000000..24f32ef24 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/overview/setup.ts @@ -0,0 +1,16 @@ +import { + AssetTransferApi, + constructApiPromise, +} from "@substrate/asset-transfer-api"; + +async function main() { + const { api, specName, safeXcmVersion } = await constructApiPromise( + "INSERT_WEBSOCKET_URL" + ); + + const assetsApi = new AssetTransferApi(api, specName, safeXcmVersion); + + // Your code using assetsApi goes here +} + +main(); diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/asset-transfer-type.md b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/asset-transfer-type.md new file mode 100644 index 000000000..b9029d958 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/asset-transfer-type.md @@ -0,0 +1,10 @@ +```ts +export type AssetTransferType = + | LocalReserve + | DestinationReserve + | Teleport + | RemoteReserve; +``` + +!!! note + To use the `assetTransferType` parameter, which is a string, you should use the `AssetTransferType` type as if each of its variants are strings. For example: `assetTransferType = 'LocalReserve'`. \ No newline at end of file diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ca-example-request.ts b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ca-example-request.ts new file mode 100644 index 000000000..d35427a2d --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ca-example-request.ts @@ -0,0 +1,35 @@ +import { + AssetTransferApi, + constructApiPromise, +} from "@substrate/asset-transfer-api"; + +async function main() { + const { api, specName, safeXcmVersion } = await constructApiPromise( + "wss://westend-rpc.polkadot.io" + ); + const assetsApi = new AssetTransferApi(api, specName, safeXcmVersion); + + let callInfo; + try { + callInfo = await assetsApi.claimAssets( + [ + `{"parents":"0","interior":{"X2":[{"PalletInstance":"50"},{"GeneralIndex":"1984"}]}}`, + ], + ["1000000000000"], + "0xf5d5714c084c112843aca74f8c498da06cc5a2d63153b825189baa51043b1f0b", + { + format: "call", + xcmVersion: 2, + } + ); + + console.log(`Call data:\n${JSON.stringify(callInfo, null, 4)}`); + } catch (e) { + console.error(e); + throw Error(e as string); + } +} + +main() + .catch((err) => console.error(err)) + .finally(() => process.exit()); diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ca-example-response.md b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ca-example-response.md new file mode 100644 index 000000000..cea34c61c --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ca-example-response.md @@ -0,0 +1,12 @@ +<div id="termynal" data-termynal> + <span data-ty>Call data:</span> + <span data-ty>{</span> + <span data-ty> "origin": "0",</span> + <span data-ty> "dest": "westend",</span> + <span data-ty> "direction": "local",</span> + <span data-ty> "xcmVersion": 2,</span> + <span data-ty> "method": "claimAssets",</span> + <span data-ty> "format": "call",</span> + <span data-ty> "tx": "0x630c0104000002043205011f00070010a5d4e80100010100f5d5714c084c112843aca74f8c498da06cc5a2d63153b825189baa51043b1f0b"</span> + <span data-ty>}</span> +<div> \ No newline at end of file diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ca-fn-signature.ts b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ca-fn-signature.ts new file mode 100644 index 000000000..4303c60d1 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ca-fn-signature.ts @@ -0,0 +1,6 @@ +public async claimAssets<T extends Format>( + assetIds: string[], + amounts: string[], + beneficiary: string, + opts: TransferArgsOpts<T> +): Promise<TxResult<T>>; diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/constructed-format.md b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/constructed-format.md new file mode 100644 index 000000000..7b610adf8 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/constructed-format.md @@ -0,0 +1,15 @@ +```ts +export type ConstructedFormat<T> = T extends 'payload' + ? GenericExtrinsicPayload + : T extends 'call' + ? `0x${string}` + : T extends 'submittable' + ? SubmittableExtrinsic<'promise', ISubmittableResult> + : never; +``` + +The `ConstructedFormat` type is a conditional type that returns a specific type based on the value of the TxResult `format` field. + +- Payload format - if the format field is set to `'payload'`, the `ConstructedFormat` type will return a [`GenericExtrinsicPayload`](https://github.com/polkadot-js/api/blob/3b7b44f048ff515579dd233ea6964acec39c0589/packages/types/src/extrinsic/ExtrinsicPayload.ts#L48){target=_blank} +- Call format - if the format field is set to `'call'`, the `ConstructedFormat` type will return a hexadecimal string (`0x${string}`). This is the encoded representation of the extrinsic call +- Submittable format - if the format field is set to `'submittable'`, the `ConstructedFormat` type will return a [`SubmittableExtrinsic`](https://github.com/polkadot-js/api/blob/3b7b44f048ff515579dd233ea6964acec39c0589/packages/api-base/src/types/submittable.ts#L56){target=_blank}. This is a Polkadot.js type that represents a transaction that can be submitted to the blockchain \ No newline at end of file diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ctt-example-request.ts b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ctt-example-request.ts new file mode 100644 index 000000000..4cfca7993 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ctt-example-request.ts @@ -0,0 +1,34 @@ +import { + AssetTransferApi, + constructApiPromise, +} from "@substrate/asset-transfer-api"; + +async function main() { + const { api, specName, safeXcmVersion } = await constructApiPromise( + "wss://wss.api.moonbeam.network" + ); + const assetsApi = new AssetTransferApi(api, specName, safeXcmVersion); + + let callInfo; + try { + callInfo = await assetsApi.createTransferTransaction( + "2004", + "0xF977814e90dA44bFA03b6295A0616a897441aceC", + [], + ["1000000000000000000"], + { + format: "call", + keepAlive: true, + } + ); + + console.log(`Call data:\n${JSON.stringify(callInfo, null, 4)}`); + } catch (e) { + console.error(e); + throw Error(e as string); + } +} + +main() + .catch((err) => console.error(err)) + .finally(() => process.exit()); diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ctt-example-response.md b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ctt-example-response.md new file mode 100644 index 000000000..a1bb01f6a --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ctt-example-response.md @@ -0,0 +1,12 @@ +<div id="termynal" data-termynal> + <span data-ty>Call data:</span> + <span data-ty>{</span> + <span data-ty> "origin": "moonbeam",</span> + <span data-ty> "dest": "moonbeam",</span> + <span data-ty> "direction": "local",</span> + <span data-ty> "xcmVersion": null,</span> + <span data-ty> "method": "balances::transferKeepAlive",</span> + <span data-ty> "format": "call",</span> + <span data-ty> "tx": "0x0a03f977814e90da44bfa03b6295a0616a897441acec821a0600"</span> + <span data-ty>}</span> +<div> \ No newline at end of file diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ctt-fn-signature.ts b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ctt-fn-signature.ts new file mode 100644 index 000000000..0af1ef38c --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ctt-fn-signature.ts @@ -0,0 +1,7 @@ +public async createTransferTransaction<T extends Format>( + destChainId: string, + destAddr: string, + assetIds: string[], + amounts: string[], + opts: TransferArgsOpts<T> = {} +): Promise<TxResult<T>>; diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/de-example-request.ts b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/de-example-request.ts new file mode 100644 index 000000000..903714021 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/de-example-request.ts @@ -0,0 +1,27 @@ +import { + AssetTransferApi, + constructApiPromise, +} from "@substrate/asset-transfer-api"; + +async function main() { + const { api, specName, safeXcmVersion } = await constructApiPromise( + "wss://wss.api.moonbeam.network" + ); + const assetsApi = new AssetTransferApi(api, specName, safeXcmVersion); + + const encodedExt = "0x0a03f977814e90da44bfa03b6295a0616a897441acec821a0600"; + + try { + const decodedExt = assetsApi.decodeExtrinsic(encodedExt, "call"); + console.log( + `Decoded tx:\n ${JSON.stringify(JSON.parse(decodedExt), null, 4)}` + ); + } catch (e) { + console.error(e); + throw Error(e as string); + } +} + +main() + .catch((err) => console.error(err)) + .finally(() => process.exit()); diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/de-example-response.md b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/de-example-response.md new file mode 100644 index 000000000..3bc83e19d --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/de-example-response.md @@ -0,0 +1,11 @@ +<div id='termynal' data-termynal> + <span data-ty>Decoded tx:</span> + <span data-ty> {</span> + <span data-ty> "args": {</span> + <span data-ty> "dest": "0xF977814e90dA44bFA03b6295A0616a897441aceC",</span> + <span data-ty> "value": "100,000"</span> + <span data-ty> },</span> + <span data-ty> "method": "transferKeepAlive",</span> + <span data-ty> "section": "balances"</span> + <span data-ty>}</span> +</div> \ No newline at end of file diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/de-fn-signature.ts b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/de-fn-signature.ts new file mode 100644 index 000000000..197d817df --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/de-fn-signature.ts @@ -0,0 +1,4 @@ +public decodeExtrinsic<T extends Format>( + encodedTransaction: string, + format: T +): string; diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ffi-example-request.ts b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ffi-example-request.ts new file mode 100644 index 000000000..6fc39c42e --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ffi-example-request.ts @@ -0,0 +1,25 @@ +import { + AssetTransferApi, + constructApiPromise, +} from "@substrate/asset-transfer-api"; + +async function main() { + const { api, specName, safeXcmVersion } = await constructApiPromise( + "wss://wss.api.moonbeam.network" + ); + const assetsApi = new AssetTransferApi(api, specName, safeXcmVersion); + + const encodedExt = "0x0a03f977814e90da44bfa03b6295a0616a897441acec821a0600"; + + try { + const decodedExt = await assetsApi.fetchFeeInfo(encodedExt, "call"); + console.log(`Fee info:\n${JSON.stringify(decodedExt, null, 4)}`); + } catch (e) { + console.error(e); + throw Error(e as string); + } +} + +main() + .catch((err) => console.error(err)) + .finally(() => process.exit()); \ No newline at end of file diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ffi-example-response.md b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ffi-example-response.md new file mode 100644 index 000000000..3f90dea38 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ffi-example-response.md @@ -0,0 +1,11 @@ +<div id='termynal' data-termynal> + <span data-ty>Fee info:</span> + <span data-ty>{</span> + <span data-ty> "weight": {</span> + <span data-ty> "refTime": 163777000,</span> + <span data-ty> "proofSize": 3581</span> + <span data-ty> },</span> + <span data-ty> "class": "Normal",</span> + <span data-ty> "partialFee": 0</span> + <span data-ty>}</span> +</div> \ No newline at end of file diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ffi-fn-signature.ts b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ffi-fn-signature.ts new file mode 100644 index 000000000..7f87e9aa8 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/ffi-fn-signature.ts @@ -0,0 +1,4 @@ +public async fetchFeeInfo<T extends Format>( + tx: ConstructedFormat<T>, + format: T +): Promise<RuntimeDispatchInfo | RuntimeDispatchInfoV1 | null>; diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/format.ts b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/format.ts new file mode 100644 index 000000000..7e20a0012 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/format.ts @@ -0,0 +1 @@ +export type Format = "payload" | "call" | "submittable"; diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/transfer-arg-opts.md b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/transfer-arg-opts.md new file mode 100644 index 000000000..e244fecbc --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/transfer-arg-opts.md @@ -0,0 +1,94 @@ +Options for customizing the claim assets transaction. These options allow you to specify the transaction format, fee payment details, weight limits, XCM versions, and more. + +??? child "Show more" + + `format` ++"T extends Format"++ + + Specifies the format for returning a transaction. + + ??? child "Type `Format`" + + ```ts + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/format.ts' + ``` + + --- + + `paysWithFeeOrigin` ++"string"++ + + The Asset ID to pay fees on the current common good parachain. The defaults are as follows: + + - Polkadot Asset Hub - `'DOT'` + - Kusama Asset Hub - `'KSM'` + + --- + + `paysWithFeeDest` ++"string"++ + + Asset ID to pay fees on the destination parachain. + + --- + + `weightLimit` ++"{ refTime?: string, proofSize?: string }"++ + + Custom weight limit option. If not provided, it will default to unlimited. + + --- + + `xcmVersion` ++"number"++ + + Sets the XCM version for message construction. If this is not present a supported version will be queried, and if there is no supported version a safe version will be queried. + + --- + + `keepAlive` ++"boolean"++ + + Enables `transferKeepAlive` for local asset transfers. For creating local asset transfers, if `true` this will allow for a `transferKeepAlive` as opposed to a `transfer`. + + --- + + `transferLiquidToken` ++"boolean"++ + + Declares if this will transfer liquidity tokens. Default is `false`. + + --- + + `assetTransferType` ++"string"++ + + The XCM transfer type used to transfer assets. The `AssetTransferType` type defines the possible values for this parameter. + + ??? child "Type `AssetTransferType`" + + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/asset-transfer-type.md' + + --- + + `remoteReserveAssetTransferTypeLocation` ++"string"++ + + The remove reserve location for the XCM transfer. Should be provided when specifying an `assetTransferType` of `RemoteReserve`. + + --- + + `feesTransferType` ++"string"++ + + XCM TransferType used to pay fees for XCM transfer. The `AssetTransferType` type defines the possible values for this parameter. + + ??? child "Type `AssetTransferType`" + + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/asset-transfer-type.md' + + --- + + `remoteReserveFeesTransferTypeLocation` ++"string"++ + + The remote reserve location for the XCM transfer fees. Should be provided when specifying a `feesTransferType` of `RemoteReserve`. + + --- + + `customXcmOnDest` ++"string"++ + + A custom XCM message to be executed on the destination chain. Should be provided if a custom XCM message is needed after transferring assets. Defaults to: + + ```bash + Xcm(vec![DepositAsset { assets: Wild(AllCounted(assets.len())), beneficiary }]) + ``` \ No newline at end of file diff --git a/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/tx-result.md b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/tx-result.md new file mode 100644 index 000000000..389d58391 --- /dev/null +++ b/.snippets/code/develop/application-devs/tooling/asset-transfer-api/reference/tx-result.md @@ -0,0 +1,148 @@ +A promise containing the result of constructing the transaction. + +??? child "Show more" + + `dest` ++"string"++ + + The destination `specName` of the transaction. + + --- + + `origin` ++"string"++ + + The origin `specName` of the transaction. + + --- + + `format` ++"Format | 'local'"++ + + The format type the transaction is outputted in. + + ??? child "Type `Format`" + + ```ts + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/format.ts' + ``` + + --- + + `xcmVersion` ++"number | null"++ + + The XCM version that was used to construct the transaction. + + --- + + `direction` ++"Direction | 'local'"++ + + The direction of the cross-chain transfer. + + ??? child "Enum `Direction` values" + + `Local` + + Local transaction. + + --- + + `SystemToPara` + + System parachain to parachain. + + --- + + `SystemToRelay` + + System paracahin to system relay chain. + + --- + + `SystemToSystem` + + System parachain to System parachain chain. + + --- + + `SystemToBridge` + + System parachain to an external `GlobalConsensus` chain. + + --- + + `ParaToPara` + + Parachain to Parachain. + + --- + + `ParaToRelay` + + Parachain to Relay chain. + + --- + + `ParaToSystem` + + Parachain to System parachain. + + --- + + `RelayToSystem` + + Relay to System Parachain. + + --- + + `RelayToPara` + + Relay chain to Parachain. + + --- + + `RelayToBridge` + + Relay chain to an external `GlobalConsensus` chain. + + `method` ++"Methods"++ + + The method used in the transaction. + + ??? child "Type `Methods`" + + ```ts + type Methods = + | LocalTransferTypes + | 'transferAssets' + | 'transferAssetsUsingTypeAndThen' + | 'limitedReserveTransferAssets' + | 'limitedTeleportAssets' + | 'transferMultiasset' + | 'transferMultiassets' + | 'transferMultiassetWithFee' + | 'claimAssets'; + ``` + + ??? child "Type `LocalTransferTypes`" + + ```ts + type LocalTransferTypes = + | 'assets::transfer' + | 'assets::transferKeepAlive' + | 'foreignAssets::transfer' + | 'foreignAssets::transferKeepAlive' + | 'balances::transfer' + | 'balances::transferKeepAlive' + | 'poolAssets::transfer' + | 'poolAssets::transferKeepAlive' + | 'tokens::transfer' + | 'tokens::transferKeepAlive'; + ``` + + --- + + `tx` ++"ConstructedFormat<T>"++ + + The constructed transaction. + + ??? child "Type `ConstructedFormat<T>`" + + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/constructed-format.md' diff --git a/.snippets/code/develop/parachain-devs/interoperability/hrmp-channels/hrmp-query-output.json b/.snippets/code/develop/parachain-devs/interoperability/hrmp-channels/hrmp-query-output.json index 8165c394f..3c8189e6f 100644 --- a/.snippets/code/develop/parachain-devs/interoperability/hrmp-channels/hrmp-query-output.json +++ b/.snippets/code/develop/parachain-devs/interoperability/hrmp-channels/hrmp-query-output.json @@ -1,38 +1,38 @@ [ - [ [ - { - "sender": 1000, - "recipient": 2500 - } + [ + { + "sender": 1000, + "recipient": 2500 + } + ], + { + "maxCapacity": 8, + "maxTotalSize": 8192, + "maxMessageSize": 1048576, + "msgCount": 0, + "totalSize": 0, + "mqcHead": null, + "senderDeposit": 0, + "recipientDeposit": 0 + } ], - { - "maxCapacity": 8, - "maxTotalSize": 8192, - "maxMessageSize": 1048576, - "msgCount": 0, - "totalSize": 0, - "mqcHead": null, - "senderDeposit": 0, - "recipientDeposit": 0 - } - ], - [ [ - { - "sender": 2500, - "recipient": 1000 - } - ], - { - "maxCapacity": 8, - "maxTotalSize": 8192, - "maxMessageSize": 1048576, - "msgCount": 0, - "totalSize": 0, - "mqcHead": null, - "senderDeposit": 0, - "recipientDeposit": 0 - } - ] + [ + { + "sender": 2500, + "recipient": 1000 + } + ], + { + "maxCapacity": 8, + "maxTotalSize": 8192, + "maxMessageSize": 1048576, + "msgCount": 0, + "totalSize": 0, + "mqcHead": null, + "senderDeposit": 0, + "recipientDeposit": 0 + } + ] ] diff --git a/.snippets/code/tutorials/polkadot-sdk/build-a-blockchain/build-a-local-blockchain/node-output.html b/.snippets/code/tutorials/polkadot-sdk/build-a-blockchain/build-a-local-blockchain/node-output.html index e7f2189ae..e0819b6a5 100644 --- a/.snippets/code/tutorials/polkadot-sdk/build-a-blockchain/build-a-local-blockchain/node-output.html +++ b/.snippets/code/tutorials/polkadot-sdk/build-a-blockchain/build-a-local-blockchain/node-output.html @@ -1,27 +1,27 @@ -<div id='termynal' data-termynal> - <span data-ty='input'><span class='file-path'></span>./target/release/solochain-template-node --dev</span> - <br> - <span data-ty>2024-09-09 08:32:42 Substrate Node</span> - <span data-ty>2024-09-09 08:32:42 ✌️ version 0.1.0-8599efc46ae</span> - <span data-ty>2024-09-09 08:32:42 ❤️ by Parity Technologies <admin@parity.io>, 2017-2024</span> - <span data-ty>2024-09-09 08:32:42 📋 Chain specification: Development</span> - <span data-ty>2024-09-09 08:32:42 🏷 Node name: light-boundary-7850</span> - <span data-ty>2024-09-09 08:32:42 👤 Role: AUTHORITY</span> - <span data-ty>2024-09-09 08:32:42 💾 Database: RocksDb at /var/folders/x0/xl_kjddj3ql3bx7752yr09hc0000gn/T/substrate0QH9va/chains/dev/db/full</span> - <span data-ty>2024-09-09 08:32:42 🔨 Initializing Genesis block/state (state: 0xc2a0…16ba, header-hash: 0x0eef…935d)</span> - <span data-ty>2024-09-09 08:32:42 👴 Loading GRANDPA authority set from genesis on what appears to be first startup.</span> - <span data-ty>2024-09-09 08:32:42 Using default protocol ID "sup" because none is configured in the chain specs</span> - <span data-ty>2024-09-09 08:32:42 🏷 Local node identity is: 12D3KooWPhdUzf66di1SuuRFgjkFs6X8jm3Uj2ss5ri31WuVAbgt</span> - <span data-ty>2024-09-09 08:32:42 Running libp2p network backend</span> - <span data-ty>2024-09-09 08:32:42 💻 Operating system: macos</span> - <span data-ty>2024-09-09 08:32:42 💻 CPU architecture: aarch64</span> - <span data-ty>2024-09-09 08:32:42 📦 Highest known block at #0</span> - <span data-ty>2024-09-09 08:32:42 〽️ Prometheus exporter started at 127.0.0.1:9615</span> - <span data-ty>2024-09-09 08:32:42 Running JSON-RPC server: addr=127.0.0.1:9944, allowed origins=["*"]</span> - <span data-ty>2024-09-09 08:32:47 💤 Idle (0 peers), best: #0 (0x0eef…935d), finalized #0 (0x0eef…935d), ⬇ 0 ⬆ 0</span> - <span data-ty>2024-09-09 08:32:48 🙌 Starting consensus session on top of parent 0x0eef4a08ef90cc04d01864514dc5cb2bd822314309b770b49b0177f920ed935d (#0)</span> - <span data-ty>2024-09-09 08:32:48 🎁 Prepared block for proposing at 1 (1 ms) [hash: 0xc14630b76907550bef9037dcbfafa2b25c8dc763495f30d9e36ad4b93b673b36; parent_hash: 0x0eef…935d; extrinsics (1): [0xbcd8…5132]</span> - <span data-ty>2024-09-09 08:32:48 🔖 Pre-sealed block for proposal at 1. Hash now 0xcb3d2f28bc73807dac5cf19fcfb2ac6d7e922756da9d41ca0c9dadbd0e45265b, previously 0xc14630b76907550bef9037dcbfafa2b25c8dc763495f30d9e36ad4b93b673b36.</span> - <span data-ty>2024-09-09 08:32:48 🏆 Imported #1 (0x0eef…935d → 0xcb3d…265b)</span> - <span data-ty>...</span> -</div> \ No newline at end of file +<div id="termynal" data-termynal> + <span data-ty="input"><span class="file-path"></span>./target/release/solochain-template-node --dev</span> + <br /> + <span data-ty>2024-09-09 08:32:42 Substrate Node</span> + <span data-ty>2024-09-09 08:32:42 ✌️ version 0.1.0-8599efc46ae</span> + <span data-ty>2024-09-09 08:32:42 ❤️ by Parity Technologies <admin@parity.io>, 2017-2024</span> + <span data-ty>2024-09-09 08:32:42 📋 Chain specification: Development</span> + <span data-ty>2024-09-09 08:32:42 🏷 Node name: light-boundary-7850</span> + <span data-ty>2024-09-09 08:32:42 👤 Role: AUTHORITY</span> + <span data-ty>2024-09-09 08:32:42 💾 Database: RocksDb at /var/folders/x0/xl_kjddj3ql3bx7752yr09hc0000gn/T/substrate0QH9va/chains/dev/db/full</span> + <span data-ty>2024-09-09 08:32:42 🔨 Initializing Genesis block/state (state: 0xc2a0…16ba, header-hash: 0x0eef…935d)</span> + <span data-ty>2024-09-09 08:32:42 👴 Loading GRANDPA authority set from genesis on what appears to be first startup.</span> + <span data-ty>2024-09-09 08:32:42 Using default protocol ID "sup" because none is configured in the chain specs</span> + <span data-ty>2024-09-09 08:32:42 🏷 Local node identity is: 12D3KooWPhdUzf66di1SuuRFgjkFs6X8jm3Uj2ss5ri31WuVAbgt</span> + <span data-ty>2024-09-09 08:32:42 Running libp2p network backend</span> + <span data-ty>2024-09-09 08:32:42 💻 Operating system: macos</span> + <span data-ty>2024-09-09 08:32:42 💻 CPU architecture: aarch64</span> + <span data-ty>2024-09-09 08:32:42 📦 Highest known block at #0</span> + <span data-ty>2024-09-09 08:32:42 〽️ Prometheus exporter started at 127.0.0.1:9615</span> + <span data-ty>2024-09-09 08:32:42 Running JSON-RPC server: addr=127.0.0.1:9944, allowed origins=["*"]</span> + <span data-ty>2024-09-09 08:32:47 💤 Idle (0 peers), best: #0 (0x0eef…935d), finalized #0 (0x0eef…935d), ⬇ 0 ⬆ 0</span> + <span data-ty>2024-09-09 08:32:48 🙌 Starting consensus session on top of parent 0x0eef4a08ef90cc04d01864514dc5cb2bd822314309b770b49b0177f920ed935d (#0)</span> + <span data-ty>2024-09-09 08:32:48 🎁 Prepared block for proposing at 1 (1 ms) [hash: 0xc14630b76907550bef9037dcbfafa2b25c8dc763495f30d9e36ad4b93b673b36; parent_hash: 0x0eef…935d; extrinsics (1): [0xbcd8…5132]</span> + <span data-ty>2024-09-09 08:32:48 🔖 Pre-sealed block for proposal at 1. Hash now 0xcb3d2f28bc73807dac5cf19fcfb2ac6d7e922756da9d41ca0c9dadbd0e45265b, previously 0xc14630b76907550bef9037dcbfafa2b25c8dc763495f30d9e36ad4b93b673b36.</span> + <span data-ty>2024-09-09 08:32:48 🏆 Imported #1 (0x0eef…935d → 0xcb3d…265b)</span> + <span data-ty>...</span> +</div> diff --git a/.snippets/code/tutorials/polkadot-sdk/build-a-blockchain/simulate-a-network/node-output-1.html b/.snippets/code/tutorials/polkadot-sdk/build-a-blockchain/simulate-a-network/node-output-1.html index 52441a04e..bb4550546 100644 --- a/.snippets/code/tutorials/polkadot-sdk/build-a-blockchain/simulate-a-network/node-output-1.html +++ b/.snippets/code/tutorials/polkadot-sdk/build-a-blockchain/simulate-a-network/node-output-1.html @@ -1,19 +1,19 @@ -<div id='termynal' data-termynal> - <data-ty>...</span> - <span data-ty>2024-09-10 09:04:57 discovered: 12D3KooWHdiAxVd8uMQR1hGWXccidmfCwLqcMpGwR6QcTP6QRMuD /ip4/192.168.1.4/tcp/30334</span> - <span data-ty>2024-09-10 09:04:58 💤 Idle (0 peers), best: #0 (0x850f…951f), finalized #0 (0x850f…951f), ⬇ 0.3kiB/s ⬆ 0.3kiB/s</span> - <span data-ty>2024-09-10 09:05:00 🙌 Starting consensus session on top of parent 0x850ffab4827cb0297316cbf01fc7c2afb954c5124f366f25ea88bfd19ede951f (#0)</span> - <span data-ty>2024-09-10 09:05:00 🎁 Prepared block for proposing at 1 (2 ms) [hash: 0xe21a305e6647b0b0c6c73ba31a49ae422809611387fadb7785f68d0a1db0b52d; parent_hash: 0x850f…951f; extrinsics (1): [0x0c18…08d8]</span> - <span data-ty>2024-09-10 09:05:00 🔖 Pre-sealed block for proposal at 1. Hash now 0x75bbb026db82a4d6ff88b96f952a29e15dac2b7df24d4cb95510945e2bede82d, previously 0xe21a305e6647b0b0c6c73ba31a49ae422809611387fadb7785f68d0a1db0b52d.</span> - <span data-ty>2024-09-10 09:05:00 🏆 Imported #1 (0x850f…951f → 0x75bb…e82d)</span> - <span data-ty>2024-09-10 09:05:03 💤 Idle (1 peers), best: #1 (0x75bb…e82d), finalized #0 (0x850f…951f), ⬇ 0.7kiB/s ⬆ 0.8kiB/s</span> - <span data-ty>2024-09-10 09:05:06 🏆 Imported #2 (0x75bb…e82d → 0x774d…a176)</span> - <span data-ty>2024-09-10 09:05:08 💤 Idle (1 peers), best: #2 (0x774d…a176), finalized #0 (0x850f…951f), ⬇ 0.6kiB/s ⬆ 0.5kiB/s</span> - <span data-ty>2024-09-10 09:05:12 🙌 Starting consensus session on top of parent 0x774dec6bff7a27c38e21106a5a7428ae5d50b991f39cda7c0aa3c0c9322da176 (#2)</span> - <span data-ty>2024-09-10 09:05:12 🎁 Prepared block for proposing at 3 (0 ms) [hash: 0x10bb4589a7a13bac657219a9ff06dcef8d55e46a4275aa287a966b5648a6d486; parent_hash: 0x774d…a176; extrinsics (1): [0xdcd4…b5ec]</span> - <span data-ty>2024-09-10 09:05:12 🔖 Pre-sealed block for proposal at 3. Hash now 0x01e080f4b8421c95d0033aac7310b36972fdeef7c6025f8a153c436c1bb214ee, previously 0x10bb4589a7a13bac657219a9ff06dcef8d55e46a4275aa287a966b5648a6d486.</span> - <span data-ty>2024-09-10 09:05:12 🏆 Imported #3 (0x774d…a176 → 0x01e0…14ee)</span> - <span data-ty>2024-09-10 09:05:13 💤 Idle (1 peers), best: #3 (0x01e0…14ee), finalized #0 (0x850f…951f), ⬇ 0.6kiB/s ⬆ 0.6kiB/s</span> - <span data-ty>2024-09-10 09:05:18 🏆 Imported #4 (0x01e0…14ee → 0xe176…0430)</span> - <span data-ty>2024-09-10 09:05:18 💤 Idle (1 peers), best: #4 (0xe176…0430), finalized #1 (0x75bb…e82d), ⬇ 0.6kiB/s ⬆ 0.6kiB/s</span> -</div> \ No newline at end of file +<div id="termynal" data-termynal> + <span data-ty>...</span> + <span data-ty>2024-09-10 09:04:57 discovered: 12D3KooWHdiAxVd8uMQR1hGWXccidmfCwLqcMpGwR6QcTP6QRMuD /ip4/192.168.1.4/tcp/30334</span> + <span data-ty>2024-09-10 09:04:58 💤 Idle (0 peers), best: #0 (0x850f…951f), finalized #0 (0x850f…951f), ⬇ 0.3kiB/s ⬆ 0.3kiB/s</span> + <span data-ty>2024-09-10 09:05:00 🙌 Starting consensus session on top of parent 0x850ffab4827cb0297316cbf01fc7c2afb954c5124f366f25ea88bfd19ede951f (#0)</span> + <span data-ty>2024-09-10 09:05:00 🎁 Prepared block for proposing at 1 (2 ms) [hash: 0xe21a305e6647b0b0c6c73ba31a49ae422809611387fadb7785f68d0a1db0b52d; parent_hash: 0x850f…951f; extrinsics (1): [0x0c18…08d8]</span> + <span data-ty>2024-09-10 09:05:00 🔖 Pre-sealed block for proposal at 1. Hash now 0x75bbb026db82a4d6ff88b96f952a29e15dac2b7df24d4cb95510945e2bede82d, previously 0xe21a305e6647b0b0c6c73ba31a49ae422809611387fadb7785f68d0a1db0b52d.</span> + <span data-ty>2024-09-10 09:05:00 🏆 Imported #1 (0x850f…951f → 0x75bb…e82d)</span> + <span data-ty>2024-09-10 09:05:03 💤 Idle (1 peers), best: #1 (0x75bb…e82d), finalized #0 (0x850f…951f), ⬇ 0.7kiB/s ⬆ 0.8kiB/s</span> + <span data-ty>2024-09-10 09:05:06 🏆 Imported #2 (0x75bb…e82d → 0x774d…a176)</span> + <span data-ty>2024-09-10 09:05:08 💤 Idle (1 peers), best: #2 (0x774d…a176), finalized #0 (0x850f…951f), ⬇ 0.6kiB/s ⬆ 0.5kiB/s</span> + <span data-ty>2024-09-10 09:05:12 🙌 Starting consensus session on top of parent 0x774dec6bff7a27c38e21106a5a7428ae5d50b991f39cda7c0aa3c0c9322da176 (#2)</span> + <span data-ty>2024-09-10 09:05:12 🎁 Prepared block for proposing at 3 (0 ms) [hash: 0x10bb4589a7a13bac657219a9ff06dcef8d55e46a4275aa287a966b5648a6d486; parent_hash: 0x774d…a176; extrinsics (1): [0xdcd4…b5ec]</span> + <span data-ty>2024-09-10 09:05:12 🔖 Pre-sealed block for proposal at 3. Hash now 0x01e080f4b8421c95d0033aac7310b36972fdeef7c6025f8a153c436c1bb214ee, previously 0x10bb4589a7a13bac657219a9ff06dcef8d55e46a4275aa287a966b5648a6d486.</span> + <span data-ty>2024-09-10 09:05:12 🏆 Imported #3 (0x774d…a176 → 0x01e0…14ee)</span> + <span data-ty>2024-09-10 09:05:13 💤 Idle (1 peers), best: #3 (0x01e0…14ee), finalized #0 (0x850f…951f), ⬇ 0.6kiB/s ⬆ 0.6kiB/s</span> + <span data-ty>2024-09-10 09:05:18 🏆 Imported #4 (0x01e0…14ee → 0xe176…0430)</span> + <span data-ty>2024-09-10 09:05:18 💤 Idle (1 peers), best: #4 (0xe176…0430), finalized #1 (0x75bb…e82d), ⬇ 0.6kiB/s ⬆ 0.6kiB/s</span> +</div> diff --git a/.snippets/code/tutorials/polkadot-sdk/build-a-blockchain/simulate-a-network/node-output.html b/.snippets/code/tutorials/polkadot-sdk/build-a-blockchain/simulate-a-network/node-output.html index 3015ba3fe..4307d2c07 100644 --- a/.snippets/code/tutorials/polkadot-sdk/build-a-blockchain/simulate-a-network/node-output.html +++ b/.snippets/code/tutorials/polkadot-sdk/build-a-blockchain/simulate-a-network/node-output.html @@ -1,29 +1,21 @@ -<div id='termynal' data-termynal> - <span data-ty="input"><span class="file-path"></span>./target/release/solochain-template-node \ ---base-path /tmp/alice \ ---chain local \ ---alice \ ---port 30333 \ ---rpc-port 9945 \ ---node-key 0000000000000000000000000000000000000000000000000000000000000001 \ ---validator - </span> - <span data-ty>2024-09-10 08:35:43 Substrate Node</span> - <span data-ty>2024-09-10 08:35:43 ✌️ version 0.1.0-8599efc46ae</span> - <span data-ty>2024-09-10 08:35:43 ❤️ by Parity Technologies <admin@parity.io>, 2017-2024</span> - <span data-ty>2024-09-10 08:35:43 📋 Chain specification: Local Testnet</span> - <span data-ty>2024-09-10 08:35:43 🏷 Node name: Alice</span> - <span data-ty>2024-09-10 08:35:43 👤 Role: AUTHORITY</span> - <span data-ty>2024-09-10 08:35:43 💾 Database: RocksDb at /tmp/alice/chains/local_testnet/db/full</span> - <span data-ty>2024-09-10 08:35:43 🔨 Initializing Genesis block/state (state: 0x074c…27bd, header-hash: 0x850f…951f)</span> - <span data-ty>2024-09-10 08:35:43 👴 Loading GRANDPA authority set from genesis on what appears to be first startup.</span> - <span data-ty>2024-09-10 08:35:43 Using default protocol ID "sup" because none is configured in the chain specs</span> - <span data-ty>2024-09-10 08:35:43 🏷 Local node identity is: 12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp</span> - <span data-ty>2024-09-10 08:35:43 Running libp2p network backend</span> - <span data-ty>2024-09-10 08:35:43 💻 Operating system: macos</span> - <span data-ty>2024-09-10 08:35:43 💻 CPU architecture: aarch64</span> - <span data-ty>2024-09-10 08:35:43 📦 Highest known block at #0</span> - <span data-ty>2024-09-10 08:35:43 〽️ Prometheus exporter started at 127.0.0.1:9615</span> - <span data-ty>2024-09-10 08:35:43 Running JSON-RPC server: addr=127.0.0.1:9945, allowed origins=["http://localhost:*", "http://127.0.0.1:*", "https://localhost:*", "https://127.0.0.1:*", "https://polkadot.js.org"]</span> - <span data-ty>2024-09-10 08:35:48 💤 Idle (0 peers), best: #0 (0x850f…951f), finalized #0 (0x850f…951f), ⬇ 0 ⬆ 0</span> -</div> \ No newline at end of file +<div id="termynal" data-termynal> + <span data-ty="input"><span class="file-path"></span>./target/release/solochain-template-node \ --base-path /tmp/alice \ --chain local \ --alice \ --port 30333 \ --rpc-port 9945 \ --node-key 0000000000000000000000000000000000000000000000000000000000000001 \ --validator </span> + <span data-ty>2024-09-10 08:35:43 Substrate Node</span> + <span data-ty>2024-09-10 08:35:43 ✌️ version 0.1.0-8599efc46ae</span> + <span data-ty>2024-09-10 08:35:43 ❤️ by Parity Technologies <admin@parity.io>, 2017-2024</span> + <span data-ty>2024-09-10 08:35:43 📋 Chain specification: Local Testnet</span> + <span data-ty>2024-09-10 08:35:43 🏷 Node name: Alice</span> + <span data-ty>2024-09-10 08:35:43 👤 Role: AUTHORITY</span> + <span data-ty>2024-09-10 08:35:43 💾 Database: RocksDb at /tmp/alice/chains/local_testnet/db/full</span> + <span data-ty>2024-09-10 08:35:43 🔨 Initializing Genesis block/state (state: 0x074c…27bd, header-hash: 0x850f…951f)</span> + <span data-ty>2024-09-10 08:35:43 👴 Loading GRANDPA authority set from genesis on what appears to be first startup.</span> + <span data-ty>2024-09-10 08:35:43 Using default protocol ID "sup" because none is configured in the chain specs</span> + <span data-ty>2024-09-10 08:35:43 🏷 Local node identity is: 12D3KooWEyoppNCUx8Yx66oV9fJnriXwCcXwDDUA2kj6vnc6iDEp</span> + <span data-ty>2024-09-10 08:35:43 Running libp2p network backend</span> + <span data-ty>2024-09-10 08:35:43 💻 Operating system: macos</span> + <span data-ty>2024-09-10 08:35:43 💻 CPU architecture: aarch64</span> + <span data-ty>2024-09-10 08:35:43 📦 Highest known block at #0</span> + <span data-ty>2024-09-10 08:35:43 〽️ Prometheus exporter started at 127.0.0.1:9615</span> + <span data-ty>2024-09-10 08:35:43 Running JSON-RPC server: addr=127.0.0.1:9945, allowed origins=["http://localhost:*", "http://127.0.0.1:*", "https://localhost:*", "https://127.0.0.1:*", "https://polkadot.js.org"]</span> + <span data-ty>2024-09-10 08:35:48 💤 Idle (0 peers), best: #0 (0x850f…951f), finalized #0 (0x850f…951f), ⬇ 0 ⬆ 0</span> +</div> diff --git a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/acquire-a-testnet-slot/testnet-slot-1.json b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/acquire-a-testnet-slot/testnet-slot-1.json index 139e8274b..b6ff2c407 100644 --- a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/acquire-a-testnet-slot/testnet-slot-1.json +++ b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/acquire-a-testnet-slot/testnet-slot-1.json @@ -22,4 +22,4 @@ }, "...": {} } -} \ No newline at end of file +} diff --git a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/acquire-a-testnet-slot/testnet-slot-2.html b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/acquire-a-testnet-slot/testnet-slot-2.html index d23815709..19e9bba40 100644 --- a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/acquire-a-testnet-slot/testnet-slot-2.html +++ b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/acquire-a-testnet-slot/testnet-slot-2.html @@ -1,7 +1,7 @@ <div id="termynal" data-termynal> -<span data-ty="input"><span class="file-path"></span>./target/release/parachain-template-node build-spec --chain plain-parachain-chainspec.json --disable-default-bootnode --raw > raw-parachain-chainspec.json</span> -<br> -<span data-ty="progress">2024-09-11 09:48:15 Building chain spec</span> -<span data-ty="progress">2024-09-11 09:48:15 assembling new collators for new session 0 at #0</span> -<span data-ty="progress">2024-09-11 09:48:15 assembling new collators for new session 1 at #0</span> -</div> \ No newline at end of file + <span data-ty="input"><span class="file-path"></span>./target/release/parachain-template-node build-spec --chain plain-parachain-chainspec.json --disable-default-bootnode --raw > raw-parachain-chainspec.json</span> + <br /> + <span data-ty="progress">2024-09-11 09:48:15 Building chain spec</span> + <span data-ty="progress">2024-09-11 09:48:15 assembling new collators for new session 0 at #0</span> + <span data-ty="progress">2024-09-11 09:48:15 assembling new collators for new session 1 at #0</span> +</div> diff --git a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-2.json b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-2.json index 5026fe951..b0ac0211a 100644 --- a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-2.json +++ b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-2.json @@ -12,4 +12,4 @@ }, "...": {} } -} \ No newline at end of file +} diff --git a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-3.html b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-3.html index b8edd994d..f58a0792a 100644 --- a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-3.html +++ b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-3.html @@ -1,5 +1,5 @@ <div id="termynal" data-termynal> - <span data-ty="progress">2024-09-10 14:34:58 Building chain spec</span> - <span data-ty="progress">2024-09-10 14:34:59 assembling new collators for new session 0 at #0</span> - <span data-ty="progress">2024-09-10 14:34:59 assembling new collators for new session 1 at #0</span> -</div> \ No newline at end of file + <span data-ty="progress">2024-09-10 14:34:58 Building chain spec</span> + <span data-ty="progress">2024-09-10 14:34:59 assembling new collators for new session 0 at #0</span> + <span data-ty="progress">2024-09-10 14:34:59 assembling new collators for new session 1 at #0</span> +</div> diff --git a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-4.html b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-4.html index c5fadcff6..3f882595b 100644 --- a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-4.html +++ b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-4.html @@ -1,3 +1,3 @@ <div id="termynal" data-termynal> - <span data-ty="progress">2024-09-10 14:41:13 🔨 Initializing Genesis block/state (state: 0xb089…1830, header-hash: 0x6b0b…bd69)</span> - </div> \ No newline at end of file + <span data-ty="progress">2024-09-10 14:41:13 🔨 Initializing Genesis block/state (state: 0xb089…1830, header-hash: 0x6b0b…bd69)</span> +</div> diff --git a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-5.html b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-5.html index fecc8ef1c..64e01e649 100644 --- a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-5.html +++ b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-5.html @@ -1,11 +1,11 @@ <div id="termynal" data-termynal> - <span>...</span> - <br> - <span>2024-09-10 16:26:30 [Parachain] PoV size { header: 0.21875kb, extrinsics: 3.6103515625kb, storage_proof: 3.150390625kb }</span> - <br> - <span>2024-09-10 16:26:30 [Parachain] Compressed PoV size: 6.150390625kb</span> - <br> - <span>2024-09-10 16:26:33 [Relaychain] 💤 Idle (2 peers), best: #1729 (0x3aa4…cb6b), finalized #1726 (0xff7a…4352), ⬇ 9.1kiB/s ⬆ 3.8kiB/s</span> - <br> - <span>...</span> -</div> \ No newline at end of file + <span>...</span> + <br /> + <span>2024-09-10 16:26:30 [Parachain] PoV size { header: 0.21875kb, extrinsics: 3.6103515625kb, storage_proof: 3.150390625kb }</span> + <br /> + <span>2024-09-10 16:26:30 [Parachain] Compressed PoV size: 6.150390625kb</span> + <br /> + <span>2024-09-10 16:26:33 [Relaychain] 💤 Idle (2 peers), best: #1729 (0x3aa4…cb6b), finalized #1726 (0xff7a…4352), ⬇ 9.1kiB/s ⬆ 3.8kiB/s</span> + <br /> + <span>...</span> +</div> diff --git a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-6.html b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-6.html index cdc9e12f9..9ed121a02 100644 --- a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-6.html +++ b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/connect-a-parachain/connect-a-parachain-6.html @@ -1,25 +1,25 @@ <div id="termynal" data-termynal> - <span>...</span> - <br/> - <span>[Relaychain] 💤 Idle (2 peers), best: #90 (0x5f73…1ccf), finalized #87 (0xeb50…68ea), ⬇ 1.4kiB/s ⬆ 1.1kiB/s</span> - <br/> - <span>[Parachain] 💤 Idle (0 peers), best: #0 (0x3626…fef3), finalized #0 (0x3626…fef3), ⬇ 1.2kiB/s ⬆ 0.7kiB/s</span> - <br/> - <span>[Relaychain] 💤 Idle (2 peers), best: #90 (0x5f73…1ccf), finalized #88 (0xd43c…c3e6), ⬇ 0.7kiB/s ⬆ 0.5kiB/s</span> - <br/> - <span>[Parachain] 💤 Idle (0 peers), best: #0 (0x3626…fef3), finalized #0 (0x3626…fef3), ⬇ 1.0kiB/s ⬆ 0.6kiB/s</span> - <br/> - <span>[Relaychain] 👶 New epoch 9 launching at block 0x1c93…4aa9 (block slot 281848325 >= start slot 281848325)</span> - <br/> - <span>[Relaychain] 👶 Next epoch starts at slot 281848335</span> - <br/> - <span>[Relaychain] ✨ Imported #91 (0x1c93…4aa9)</span> - <br/> - <span>[Parachain] Starting collation. relay_parent=0x1c936289cfe15fabaa369f7ae5d73050581cb12b75209c11976afcf07f6a4aa9 at=0x36261113c31019d4b2a1e27d062e186f46da0e8f6786177dc7b35959688ffef3</span> - <br/> - <span>[Relaychain] 💤 Idle (2 peers), best: #91 (0x1c93…4aa9), finalized #88 (0xd43c…c3e6), ⬇ 1.2kiB/s ⬆ 0.7kiB/s</span> - <br/> - <span>[Parachain] 💤 Idle (0 peers), best: #0 (0x3626…fef3), finalized #0 (0x3626…fef3), ⬇ 0.2kiB/s ⬆ 37 B/s</span> - <br/> - <span>...</span> -</div> \ No newline at end of file + <span>...</span> + <br /> + <span>[Relaychain] 💤 Idle (2 peers), best: #90 (0x5f73…1ccf), finalized #87 (0xeb50…68ea), ⬇ 1.4kiB/s ⬆ 1.1kiB/s</span> + <br /> + <span>[Parachain] 💤 Idle (0 peers), best: #0 (0x3626…fef3), finalized #0 (0x3626…fef3), ⬇ 1.2kiB/s ⬆ 0.7kiB/s</span> + <br /> + <span>[Relaychain] 💤 Idle (2 peers), best: #90 (0x5f73…1ccf), finalized #88 (0xd43c…c3e6), ⬇ 0.7kiB/s ⬆ 0.5kiB/s</span> + <br /> + <span>[Parachain] 💤 Idle (0 peers), best: #0 (0x3626…fef3), finalized #0 (0x3626…fef3), ⬇ 1.0kiB/s ⬆ 0.6kiB/s</span> + <br /> + <span>[Relaychain] 👶 New epoch 9 launching at block 0x1c93…4aa9 (block slot 281848325 >= start slot 281848325)</span> + <br /> + <span>[Relaychain] 👶 Next epoch starts at slot 281848335</span> + <br /> + <span>[Relaychain] ✨ Imported #91 (0x1c93…4aa9)</span> + <br /> + <span>[Parachain] Starting collation. relay_parent=0x1c936289cfe15fabaa369f7ae5d73050581cb12b75209c11976afcf07f6a4aa9 at=0x36261113c31019d4b2a1e27d062e186f46da0e8f6786177dc7b35959688ffef3</span> + <br /> + <span>[Relaychain] 💤 Idle (2 peers), best: #91 (0x1c93…4aa9), finalized #88 (0xd43c…c3e6), ⬇ 1.2kiB/s ⬆ 0.7kiB/s</span> + <br /> + <span>[Parachain] 💤 Idle (0 peers), best: #0 (0x3626…fef3), finalized #0 (0x3626…fef3), ⬇ 0.2kiB/s ⬆ 37 B/s</span> + <br /> + <span>...</span> +</div> diff --git a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/prepare-relay-chain/relay-chain-1.html b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/prepare-relay-chain/relay-chain-1.html index eb473f32f..601dd4443 100644 --- a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/prepare-relay-chain/relay-chain-1.html +++ b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/prepare-relay-chain/relay-chain-1.html @@ -1,21 +1,21 @@ <div id="termynal" data-termynal> - <span>2024-09-09 13:49:58 Parity Polkadot</span> - <br> - <span>2024-09-09 13:49:58 ✌️ version 1.15.2-d6f482d5593</span> - <br> - <span>2024-09-09 13:49:58 ❤️ by Parity Technologies <admin@parity.io>, 2017-2024</span> - <br> - <span>2024-09-09 13:49:58 📋 Chain specification: Rococo Local Testnet</span> - <br> - <span>2024-09-09 13:49:58 🏷 Node name: Alice</span> - <br> - <span>2024-09-09 13:49:58 👤 Role: AUTHORITY</span> - <br> - <span>2024-09-09 13:49:58 💾 Database: RocksDb at /tmp/relay/alice/chains/rococo_local_testnet/db/full</span> - <br> - <span>2024-09-09 13:49:59 🏷 Local node identity is: 12D3KooWG393uX82rR3QgDkZpb7U8StzuRx9BQUXCvWsP1ctgygp</span> - <br> - <span>2024-09-09 13:49:59 Running libp2p network backend</span> - <br> - <span>...</span> -</div> \ No newline at end of file + <span>2024-09-09 13:49:58 Parity Polkadot</span> + <br /> + <span>2024-09-09 13:49:58 ✌️ version 1.15.2-d6f482d5593</span> + <br /> + <span>2024-09-09 13:49:58 ❤️ by Parity Technologies <admin@parity.io>, 2017-2024</span> + <br /> + <span>2024-09-09 13:49:58 📋 Chain specification: Rococo Local Testnet</span> + <br /> + <span>2024-09-09 13:49:58 🏷 Node name: Alice</span> + <br /> + <span>2024-09-09 13:49:58 👤 Role: AUTHORITY</span> + <br /> + <span>2024-09-09 13:49:58 💾 Database: RocksDb at /tmp/relay/alice/chains/rococo_local_testnet/db/full</span> + <br /> + <span>2024-09-09 13:49:59 🏷 Local node identity is: 12D3KooWG393uX82rR3QgDkZpb7U8StzuRx9BQUXCvWsP1ctgygp</span> + <br /> + <span>2024-09-09 13:49:59 Running libp2p network backend</span> + <br /> + <span>...</span> +</div> diff --git a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/prepare-relay-chain/relay-chain-2.html b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/prepare-relay-chain/relay-chain-2.html index 8fc3c7268..982b8b333 100644 --- a/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/prepare-relay-chain/relay-chain-2.html +++ b/.snippets/code/tutorials/polkadot-sdk/build-a-parachain/prepare-relay-chain/relay-chain-2.html @@ -1,9 +1,9 @@ <div id="termynal" data-termynal> - <span>...</span> - <br> - <span>2024-09-10 13:29:38 🏆 Imported #55 (0xad6a…567c → 0xecae…ad12)<span> - <br> - <span>2024-09-10 13:29:38 💤 Idle (1 peers), best: #55 (0xecae…ad12), finalized #0 (0x1cac…618d), ⬇ 2.0kiB/s ⬆ 1.6kiB/s</span> - <br> - <span>...</span> -</div> \ No newline at end of file + <span>...</span> + <br /> + <span>2024-09-10 13:29:38 🏆 Imported #55 (0xad6a…567c → 0xecae…ad12)</span> + <br /> + <span>2024-09-10 13:29:38 💤 Idle (1 peers), best: #55 (0xecae…ad12), finalized #0 (0x1cac…618d), ⬇ 2.0kiB/s ⬆ 1.6kiB/s</span> + <br /> + <span>...</span> +</div> diff --git a/.snippets/code/tutorials/tooling/zombienet/overview/base-example.json b/.snippets/code/tutorials/tooling/zombienet/overview/base-example.json index ca336a2c1..306fb2162 100644 --- a/.snippets/code/tutorials/tooling/zombienet/overview/base-example.json +++ b/.snippets/code/tutorials/tooling/zombienet/overview/base-example.json @@ -4,7 +4,7 @@ "bootnode": false, "provider": "kubernetes", "backchannel": false, - ... + "...": {} }, - ... + "...": {} } diff --git a/.snippets/code/tutorials/tooling/zombienet/overview/base-example.toml b/.snippets/code/tutorials/tooling/zombienet/overview/base-example.toml index fff1b657a..b9d669a28 100644 --- a/.snippets/code/tutorials/tooling/zombienet/overview/base-example.toml +++ b/.snippets/code/tutorials/tooling/zombienet/overview/base-example.toml @@ -3,6 +3,4 @@ timeout = 1000 bootnode = false provider = "kubernetes" backchannel = false -... - - +# ... diff --git a/.snippets/code/tutorials/tooling/zombienet/overview/collator-example.json b/.snippets/code/tutorials/tooling/zombienet/overview/collator-example.json index 1547a6791..a0baec8e7 100644 --- a/.snippets/code/tutorials/tooling/zombienet/overview/collator-example.json +++ b/.snippets/code/tutorials/tooling/zombienet/overview/collator-example.json @@ -1,18 +1,18 @@ { "parachain": { - "id": 100, - "add_to_genesis": true, - "cumulus_based": true, - "genesis_wasm_path": "/path/to/wasm", - "genesis_state_path": "/path/to/state", - "collators": [ - { - "name": "alice", - "image": "polkadot-parachain", - "command": "polkadot-parachain", - ... - }, - ], + "id": 100, + "add_to_genesis": true, + "cumulus_based": true, + "genesis_wasm_path": "/path/to/wasm", + "genesis_state_path": "/path/to/state", + "collators": [ + { + "name": "alice", + "image": "polkadot-parachain", + "command": "polkadot-parachain", + "...": {} + } + ] }, - ... - } \ No newline at end of file + "...": {} +} diff --git a/.snippets/code/tutorials/tooling/zombienet/overview/collator-example.toml b/.snippets/code/tutorials/tooling/zombienet/overview/collator-example.toml index 6da7fdc67..efdf82897 100644 --- a/.snippets/code/tutorials/tooling/zombienet/overview/collator-example.toml +++ b/.snippets/code/tutorials/tooling/zombienet/overview/collator-example.toml @@ -9,4 +9,4 @@ genesis_state_path = "/path/to/state" name = "alice" image = "polkadot-parachain" command = "polkadot-parachain" -... \ No newline at end of file +# ... diff --git a/.snippets/code/tutorials/tooling/zombienet/overview/collator-groups-example.json b/.snippets/code/tutorials/tooling/zombienet/overview/collator-groups-example.json index 48aef41b6..598487102 100644 --- a/.snippets/code/tutorials/tooling/zombienet/overview/collator-groups-example.json +++ b/.snippets/code/tutorials/tooling/zombienet/overview/collator-groups-example.json @@ -11,9 +11,9 @@ "count": 2, "image": "polkadot-parachain", "command": "polkadot-parachain", - ... - }, - ], + "...": {} + } + ] }, - ... -} \ No newline at end of file + "...": {} +} diff --git a/.snippets/code/tutorials/tooling/zombienet/overview/collator-groups-example.toml b/.snippets/code/tutorials/tooling/zombienet/overview/collator-groups-example.toml index 01965c726..09a27e87d 100644 --- a/.snippets/code/tutorials/tooling/zombienet/overview/collator-groups-example.toml +++ b/.snippets/code/tutorials/tooling/zombienet/overview/collator-groups-example.toml @@ -10,4 +10,4 @@ name = "group-1" count = 2 image = "polkadot-parachain" command = "polkadot-parachain" -... \ No newline at end of file +# ... diff --git a/.snippets/code/tutorials/tooling/zombienet/overview/parachain-example.json b/.snippets/code/tutorials/tooling/zombienet/overview/parachain-example.json index 156cc1626..8f7510400 100644 --- a/.snippets/code/tutorials/tooling/zombienet/overview/parachain-example.json +++ b/.snippets/code/tutorials/tooling/zombienet/overview/parachain-example.json @@ -1,11 +1,11 @@ { "parachain": { - "id": 100, - "add_to_genesis": true, - "cumulus_based": true, - "genesis_wasm_path": "/path/to/wasm", - "genesis_state_path": "/path/to/state", - ... + "id": 100, + "add_to_genesis": true, + "cumulus_based": true, + "genesis_wasm_path": "/path/to/wasm", + "genesis_state_path": "/path/to/state", + "...": {} }, - ... -} \ No newline at end of file + "...": {} +} diff --git a/.snippets/code/tutorials/tooling/zombienet/overview/parachain-example.toml b/.snippets/code/tutorials/tooling/zombienet/overview/parachain-example.toml index cb96b3579..7858c54c4 100644 --- a/.snippets/code/tutorials/tooling/zombienet/overview/parachain-example.toml +++ b/.snippets/code/tutorials/tooling/zombienet/overview/parachain-example.toml @@ -4,4 +4,4 @@ add_to_genesis = true cumulus_based = true genesis_wasm_path = "/path/to/wasm" genesis_state_path = "/path/to/state" -... \ No newline at end of file +# ... diff --git a/.snippets/code/tutorials/tooling/zombienet/overview/relaychain-example-node-groups.json b/.snippets/code/tutorials/tooling/zombienet/overview/relaychain-example-node-groups.json index b9921be50..5b6f5e928 100644 --- a/.snippets/code/tutorials/tooling/zombienet/overview/relaychain-example-node-groups.json +++ b/.snippets/code/tutorials/tooling/zombienet/overview/relaychain-example-node-groups.json @@ -1,5 +1,4 @@ { - ..., "relaychain": { "default_command": "polkadot", "default_image": "polkadot-debug:master", @@ -15,7 +14,7 @@ "args": ["--chain", "rococo-local"] } ], - ... + "...": {} }, - ... -} \ No newline at end of file + "...": {} +} diff --git a/.snippets/code/tutorials/tooling/zombienet/overview/relaychain-example-node-groups.toml b/.snippets/code/tutorials/tooling/zombienet/overview/relaychain-example-node-groups.toml index 04169f5e0..03dd7a9f3 100644 --- a/.snippets/code/tutorials/tooling/zombienet/overview/relaychain-example-node-groups.toml +++ b/.snippets/code/tutorials/tooling/zombienet/overview/relaychain-example-node-groups.toml @@ -11,4 +11,4 @@ count = 2 image = "polkadot-debug:master" command = "polkadot" args = ["--chain", "rococo-local"] -... \ No newline at end of file +# ... diff --git a/.snippets/code/tutorials/tooling/zombienet/overview/relaychain-example-nodes.toml b/.snippets/code/tutorials/tooling/zombienet/overview/relaychain-example-nodes.toml index 396668a6a..30e19d435 100644 --- a/.snippets/code/tutorials/tooling/zombienet/overview/relaychain-example-nodes.toml +++ b/.snippets/code/tutorials/tooling/zombienet/overview/relaychain-example-nodes.toml @@ -14,4 +14,4 @@ balance = 1000000000000 name = "bob" validator = true balance = 1000000000000 -... \ No newline at end of file +# ... diff --git a/develop/application-devs/interact/.pages b/develop/application-devs/interact/.pages index 0dbe45da2..b0d6c6ac4 100644 --- a/develop/application-devs/interact/.pages +++ b/develop/application-devs/interact/.pages @@ -1,3 +1,4 @@ title: Interact with the Network nav: - index.md + - 'Using Light Clients': 'light-clients.md' diff --git a/develop/application-devs/interact/light-clients.md b/develop/application-devs/interact/light-clients.md new file mode 100644 index 000000000..5fb24c053 --- /dev/null +++ b/develop/application-devs/interact/light-clients.md @@ -0,0 +1,50 @@ +--- +title: Using Light Clients +description: Information about light client options available in the Polkadot ecosystem and how they simplify interactions with the network. +--- +# Using Light Clients + +## Introduction + +Conventionally, applications use a JSON-RPC protocol for communication between a user interface (UI) and a Polkadot SDK-built node with one of the following approaches: + +- **User controlled nodes** - the UI connects to a node client the user has installed on their machine. These nodes are secure, but installation and maintenance of these nodes tend to be an inconvenience + +- **Publicly accessible nodes** - the UI connects to a third-party-owned publicly accessible node client. While these nodes are more prevalent in their usage as they are convenient to use, they are centralized and insecure + +With the advent of light clients, applications no longer have to rely on RPC nodes. Light clients don't sync entire blocks. Instead, they merely verify the finalized network headers. This option provides a cryptographically robust and less resource-intensive way to interact with and ensure the state of the network. Light clients are also available locally and embedded as part of the application, enabling a trustless solution versus running an RPC node. + +<!-- TODO: add link to chain specification when glossary is merged --> +You can use a light client implementation to connect to a Polkadot SDK-based network, both in and outside the browser, as long as a [chain specification]() for that network is available. + +## Light Client Options + +Popular options for Polkadot ecosystem light clients include: + +- The [Polkadot API (PAPI)](https://papi.how/){target=\_blank} integrates [`smoldot`](https://github.com/smol-dot/smoldot){target=\_blank} as a choice of light client for both browser and server-based implementations + +- [Substrate Connect](https://github.com/paritytech/substrate-connect){target=\_blank} is a browser extension and JavaScript library that enables developers to build application-specific light clients for Polkadot SDK chains + +## Light Client Benefits + +A light client allows for all essential features of the chain, such as fetching data and transferring tokens, but it doesn't store a copy of the entire blockchain or require the trust of remote peers. Light clients fetch the needed data from a node with an associated proof to validate the data. + +=== "Full RPC Node" + + - Complete verification of all blocks of the chain + - Holds all the previous block data and the chain's storage in database + - Installation, maintenance, and execution tend to be exhaustive and require system administration expertise + + +=== "Light Client" + + - Only verifies the authenticity of blocks of the chain + - No database + - No need to provision servers or other DevOps-related maintenance, singificantly reducing initialization time from startup + + +## Resources + +Learn more about light clients and how they help you develop on Polkadot: + +- [What is a light client and why you should care?](https://medium.com/paritytech/what-is-a-light-client-and-why-you-should-care-75f813ae2670){target=\_blank} \ No newline at end of file diff --git a/develop/application-devs/tooling/.pages b/develop/application-devs/tooling/.pages index 19e5de2ad..873708359 100644 --- a/develop/application-devs/tooling/.pages +++ b/develop/application-devs/tooling/.pages @@ -3,3 +3,4 @@ nav: - index.md - chopsticks - zombienet + - asset-transfer-api diff --git a/develop/application-devs/tooling/asset-transfer-api/.pages b/develop/application-devs/tooling/asset-transfer-api/.pages new file mode 100644 index 000000000..cb23f4fbd --- /dev/null +++ b/develop/application-devs/tooling/asset-transfer-api/.pages @@ -0,0 +1,6 @@ +title: Asset Transfer API +hide: false +nav: + - index.md + - 'Overview': 'overview.md' + - 'API Reference': 'reference.md' diff --git a/develop/application-devs/tooling/asset-transfer-api/index.md b/develop/application-devs/tooling/asset-transfer-api/index.md new file mode 100644 index 000000000..836f37f56 --- /dev/null +++ b/develop/application-devs/tooling/asset-transfer-api/index.md @@ -0,0 +1,7 @@ +--- +title: Asset Transfer API +description: Asset Transfer API is a library that simplifies the transfer of assets for Substrate based chains. It provides methods for cross-chain and local transfers. +template: subsection-index-page.html +hide: + - feedback +--- diff --git a/develop/application-devs/tooling/asset-transfer-api/overview.md b/develop/application-devs/tooling/asset-transfer-api/overview.md new file mode 100644 index 000000000..9f0d54667 --- /dev/null +++ b/develop/application-devs/tooling/asset-transfer-api/overview.md @@ -0,0 +1,130 @@ +--- +title: Asset Transfer API +description: Asset Transfer API is a library that simplifies the transfer of assets for Substrate-based chains. It provides methods for cross-chain and local transfers. +--- + +# Asset Transfer API + +## Introduction + +[Asset Transfer API](https://github.com/paritytech/asset-transfer-api){target=_blank}, a tool developed and maintained by [Parity](https://www.parity.io/){target=_blank}, is a specialized library designed to streamline asset transfers for Substrate-based blockchains. This API provides a simplified set of methods for users to: + +- Execute asset transfers to other parachains or locally within the same chain +- Facilitate transactions involving system parachains like Asset Hub (Polkadot and Kusama) + +Using this API, developers can manage asset transfers more efficiently, reducing the complexity of cross-chain transactions and enabling smoother operations within the ecosystem. + +For additional support and information, please reach out through [GitHub Issues](https://github.com/paritytech/asset-transfer-api/issues){target=_blank}. + +## Prerequisites + +Before you begin, ensure you have the following installed: + +- [Node.js](https://nodejs.org/en/){target=_blank} (recommended version 21 or greater) +- Package manager - [npm](https://www.npmjs.com/){target=_blank} should be installed with Node.js by default. Alternatively, you can use other package managers like [Yarn](https://yarnpkg.com/){target=_blank} + +## Install Asset Transfer API + +To use `asset-transfer-api`, you need a TypeScript project. If you don't have one, you can create a new one: + +1. Create a new directory for your project: + + ```bash + mkdir my-asset-transfer-project \ + && cd my-asset-transfer-project + ``` + +2. Initialize a new TypeScript project: + + ```bash + npm init -y \ + && npm install typescript ts-node @types/node --save-dev \ + && npx tsc --init + ``` + +Once you have a project set up, you can install the `asset-transfer-api` package: + +```bash +npm install @substrate/asset-transfer-api@{{dependencies.asset_transfer_api.version}} +``` + +!!!note + This documentation covers version `{{dependencies.asset_transfer_api.version}}` of Asset Transfer API. + +## Set Up Asset Transfer API + +To initialize the Asset Transfer API, you need three key components: + +- A Polkadot.js API instance +- The `specName` of the chain +- The XCM version to use + +<!-- You can set up the API in two ways. Choose the option that best fits your project's structure and requirements. Both methods will result in a fully initialized AssetTransferApi instance ready for use: + +### Using an Existing Polkadot.js API + +If you already have an initialized Polkadot.js API instance, you can use it to set up the Asset Transfer API: + +```ts +// Assuming 'api' is your initialized Polkadot.js API instance +const { specName } = await api.rpc.state.getRuntimeVersion(); +const safeXcmVersion = await fetchSafeXcmVersion(api); + +const assetsApi = new AssetTransferApi(api, specName, safeXcmVersion); +``` +--> + +### Using Helper Function from Library + +For a simpler setup process, you can leverage the `constructApiPromise` helper function provided by the library. It not only constructs a Polkadot.js `ApiPromise` but also automatically retrieves the chain's `specName` and fetches a safe XCM version. By using this function, developers can significantly reduce boilerplate code and potential configuration errors, making the initial setup both quicker and more robust. + +<!-- This method automatically initializes the Polkadot.js API, retrieves the specName, and determines the safe XCM version. --> + +```ts +--8<-- 'code/develop/application-devs/tooling/asset-transfer-api/overview/setup.ts' +``` + +!!!note + The code examples are enclosed in an async main function to provide the necessary asynchronous context. However, you can use the code directly if you're already working within an async environment. The key is to ensure you're in an async context when working with these asynchronous operations, regardless of your specific setup. + +## Asset Transfer API Reference + +For detailed information on the Asset Transfer API, including available methods, data types, and functionalities, refer to the [Asset Transfer API Reference](/develop/application-devs/tooling/asset-transfer-api/reference) section. This resource provides in-depth explanations and technical specifications to help you integrate and utilize the API effectively. + +## Examples + +### Relay to System Parachain Transfer + +This example demonstrates how to initiate a cross-chain token transfer from a relay chain to a system parachain. Specifically, 1 WND will be transferred from a Westend (relay chain) account to a Westmint (system parachain) account. + +```ts +--8<-- 'code/develop/application-devs/tooling/asset-transfer-api/overview/relayToSystem.ts' +``` + +After running the script, you'll see the following output in the terminal, which shows the call data for the cross-chain transfer and its decoded extrinsic details: + +--8<-- 'code/develop/application-devs/tooling/asset-transfer-api/overview/relayToSystem.md' + +### Local Parachain Transfer + +The following example demonstrates a local GLMR transfer within Moonbeam, using the `balances` pallet. It transfers 1 GLMR token from one account to another account, where both the sender and recipient accounts are located on the same parachain. + +```ts +--8<-- 'code/develop/application-devs/tooling/asset-transfer-api/overview/localParachainTx.ts' +``` + +Upon executing this script, the terminal will display the following output, illustrating the encoded extrinsic for the cross-chain message and its corresponding decoded format: + +--8<-- 'code/develop/application-devs/tooling/asset-transfer-api/overview/localParachainTx.md' + +### Parachain to Parachain Transfer + +This example demonstrates creating a cross-chain asset transfer between two parachains. It shows how to send vMOVR and vBNC from a Moonriver account to a Bifrost Kusama account using the safe XCM version. It connects to Moonriver, initializes the API, and uses the `createTransferTransaction` method to prepare a transaction. + +```ts +--8<-- 'code/develop/application-devs/tooling/asset-transfer-api/overview/paraToPara.ts' +``` + +After running this script, you'll see the following output in your terminal. This output presents the encoded extrinsic for the cross-chain message, along with its decoded format, providing a clear view of the transaction details. + +--8<-- 'code/develop/application-devs/tooling/asset-transfer-api/overview/paraToPara.md' \ No newline at end of file diff --git a/develop/application-devs/tooling/asset-transfer-api/reference.md b/develop/application-devs/tooling/asset-transfer-api/reference.md new file mode 100644 index 000000000..5ba57557c --- /dev/null +++ b/develop/application-devs/tooling/asset-transfer-api/reference.md @@ -0,0 +1,266 @@ +--- +title: Asset Transfer API Reference +description: Explore the Asset Transfer API Reference for comprehensive details on methods, data types, and functionalities. Essential for cross-chain asset transfers. +--- + +# Asset Transfer API Reference + +<br> +<div class="grid cards" markdown> +- :octicons-download-16:{ .lg .middle } __Install the Asset Transfer API__ + + --- + + Learn how to install [`asset-transfer-api`](https://github.com/paritytech/asset-transfer-api){target=\_blank} into a new or existing project. + + <br> + [:octicons-arrow-right-24: Get started](../asset-transfer-api/overview.md) + +- :octicons-code-16:{ .lg .middle } __Dive in with a tutorial__ + + --- + + Ready to start coding? Follow along with a step-by-step tutorial. + + <br> + [:octicons-arrow-right-24: How to use the Asset Transfer API](../asset-transfer-api/overview.md/#examples) +</div> +<br> + + +## Asset Transfer API Class + +Holds open an API connection to a specified chain within the `ApiPromise` to help construct transactions for assets and estimate fees. + +For a more in-depth explanation of the Asset Transfer API class structure, check the [source code](https://github.com/paritytech/asset-transfer-api/blob/f2aa50db83882f23492f975221dd5501c35a26d5/src/AssetTransferApi.ts#L106){target=_blank}. + +### Methods + +#### Create Transfer Transaction + +Generates an XCM transaction for transferring assets between chains. It simplifies the process by inferring what type of transaction is required given the inputs, ensuring that the assets are valid, and that the transaction details are correctly formatted. + +After obtaining the transaction, you must handle the signing and submission process separately. + +```ts +--8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/ctt-fn-signature.ts' +``` + +??? interface "Request parameters" + + `destChainId` ++"string"++ <span class="required" markdown>++"required"++</span> + + ID of the destination chain (`'0'` for relay chain, other values for parachains). + + --- + + `destAddr` ++"string"++ <span class="required" markdown>++"required"++</span> + + Address of the recipient account on the destination chain. + + --- + + `assetIds` ++"string[]"++ <span class="required" markdown>++"required"++</span> + + Array of asset IDs to be transferred. + + When asset IDs are provided, the API dynamically selects the appropriate pallet for the current chain to handle these specific assets. If the array is empty, the API defaults to using the `balances` pallet. + + --- + + `amounts` ++"string[]"++ <span class="required" markdown>++"required"++</span> + + Array of amounts corresponding to each asset in `assetIds`. + + --- + + `opts` ++"TransferArgsOpts<T>"++ + + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/transfer-arg-opts.md' + +??? interface "Response parameters" + + ++"Promise<TxResult<T>>"++ + + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/tx-result.md' + +??? interface "Example" + + ***Request*** + + ```ts + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/ctt-example-request.ts' + ``` + + ***Response*** + + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/ctt-example-response.md' + +#### Claim Assets + +Creates a local XCM transaction to retrieve trapped assets. This function can be used to claim assets either locally on a system parachain, on the relay chain, or on any chain that supports the `claimAssets` runtime call. + + +```ts +--8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/ca-fn-signature.ts' +``` + +??? interface "Request parameters" + + `assetIds` ++"string[]"++ <span class="required" markdown>++"required"++</span> + + Array of asset IDs to be claimed from the `AssetTrap`. + + --- + + `amounts` ++"string[]"++ <span class="required" markdown>++"required"++</span> + + Array of amounts corresponding to each asset in `assetIds`. + + --- + + `beneficiary` ++"string"++ <span class="required" markdown>++"required"++</span> + + Address of the account to receive the trapped assets. + + --- + + `opts` ++"TransferArgsOpts<T>"++ + + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/transfer-arg-opts.md' + +??? interface "Response parameters" + + ++"Promise<TxResult<T>>"++ + + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/tx-result.md' + +??? interface "Example" + + ***Request*** + + ```ts + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/ca-example-request.ts' + ``` + + ***Response*** + + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/ca-example-response.md' + + +#### Decode Extrinsic + +Decodes the hex of an extrinsic into a string readable format. + +```ts +--8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/de-fn-signature.ts' +``` + +??? interface "Request parameters" + + `encodedTransaction` ++"string"++ <span class="required" markdown>++"required"++</span> + + A hex encoded extrinsic. + + --- + + `format` ++"T extends Format"++ <span class="required" markdown>++"required"++</span> + + Specifies the format for returning a transaction. + + ??? child "Type `Format`" + + ```ts + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/format.ts' + ``` + +??? interface "Response parameters" + + ++"string"++ + + Decoded extrinsic in string readable format. + +??? interface "Example" + + ***Request*** + + ```ts + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/de-example-request.ts' + ``` + + ***Response*** + + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/de-example-response.md' + +#### Fetch Fee Info + +Fetch estimated fee information for an extrinsic. + +```ts +--8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/ffi-fn-signature.ts' +``` + +??? interface "Request parameters" + + `tx` ++"ConstructedFormat<T>"++ <span class="required" markdown>++"required"++</span> + + The constructed transaction. + + ??? child "Type `ConstructedFormat<T>`" + + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/constructed-format.md' + + --- + + `format` ++"T extends Format"++ <span class="required" markdown>++"required"++</span> + + Specifies the format for returning a transaction. + + ??? child "Type `Format`" + + ```ts + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/format.ts' + ``` + +??? interface "Response parameters" + + ++"Promise<RuntimeDispatchInfo | RuntimeDispatchInfoV1 | null>"++ + + A promise containing the estimated fee information for the provided extrinsic. + + ??? child "Type `RuntimeDispatchInfo`" + + ```ts + export interface RuntimeDispatchInfo extends Struct { + readonly weight: Weight; + readonly class: DispatchClass; + readonly partialFee: Balance; + } + ``` + + For more information on the underlying types and fields of `RuntimeDispatchInfo`, check the [RuntimeDispatchInfo](https://github.com/polkadot-js/api/blob/2329af239eaf194696daeaa58ebf89f0080a5e0d/packages/types/src/interfaces/payment/types.ts#L21){target=_blank} source code. + + + ??? child "Type `RuntimeDispatchInfoV1`" + + ```ts + export interface RuntimeDispatchInfoV1 extends Struct { + readonly weight: WeightV1; + readonly class: DispatchClass; + readonly partialFee: Balance; + } + ``` + + For more information on the underlying types and fields of `RuntimeDispatchInfoV1`, check the [RuntimeDispatchInfoV1](https://github.com/polkadot-js/api/blob/2329af239eaf194696daeaa58ebf89f0080a5e0d/packages/types/src/interfaces/payment/types.ts#L28){target=_blank} source code. + +??? interface "Example" + + ***Request*** + + ```ts + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/ffi-example-request.ts' + ``` + + ***Response*** + + --8<-- 'code/develop/application-devs/tooling/asset-transfer-api/reference/ffi-example-response.md' \ No newline at end of file diff --git a/images/contributing/vale-output-01.webp b/images/contributing/vale-output-01.webp new file mode 100644 index 0000000000000000000000000000000000000000..16e9790e154c8760b0177c3f85d73c7122cc34f2 GIT binary patch literal 36504 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 Xg>Hulca0$JaPihu+xK1700000Co}WI literal 0 HcmV?d00001 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..65b7775ac --- /dev/null +++ b/package-lock.json @@ -0,0 +1,43 @@ +{ + "name": "polkadot-docs", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "polkadot-docs", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "@taplo/cli": "^0.7.0", + "husky": "^8.0.0" + } + }, + "node_modules/@taplo/cli": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@taplo/cli/-/cli-0.7.0.tgz", + "integrity": "sha512-Ck3zFhQhIhi02Hl6T4ZmJsXdnJE+wXcJz5f8klxd4keRYgenMnip3JDPMGDRLbnC/2iGd8P0sBIQqI3KxfVjBg==", + "dev": true, + "license": "MIT", + "bin": { + "taplo": "dist/cli.js" + } + }, + "node_modules/husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..0abdd3630 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "polkadot-docs", + "version": "1.0.0", + "description": "This package contains tools to support the development and maintenance of the polkadot-docs repository.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "prepare": "husky install" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@taplo/cli": "^0.7.0", + "husky": "^8.0.0" + } +}