{"id":15434236,"url":"https://github.com/danforbes/dots","last_synced_at":"2026-04-18T15:38:43.277Z","repository":{"id":175032838,"uuid":"539735770","full_name":"danforbes/dots","owner":"danforbes","description":"Demonstrational \u0026 educational project to showcase interactions with Substrate- and FRAME-based blockchains","archived":false,"fork":false,"pushed_at":"2022-10-23T18:00:29.000Z","size":179,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-07T14:49:06.608Z","etag":null,"topics":["polkadot","substrate","wasm","web-components"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danforbes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-22T00:34:47.000Z","updated_at":"2023-06-13T15:48:58.000Z","dependencies_parsed_at":"2023-06-26T04:16:39.240Z","dependency_job_id":null,"html_url":"https://github.com/danforbes/dots","commit_stats":{"total_commits":1,"total_committers":1,"mean_commits":1.0,"dds":0.0,"last_synced_commit":"ab4debb51e0afd1ea2e771f09c7df8893cc0415b"},"previous_names":["danforbes/dots"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/danforbes/dots","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danforbes%2Fdots","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danforbes%2Fdots/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danforbes%2Fdots/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danforbes%2Fdots/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danforbes","download_url":"https://codeload.github.com/danforbes/dots/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danforbes%2Fdots/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31974951,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T00:39:45.007Z","status":"online","status_checked_at":"2026-04-18T02:00:07.018Z","response_time":103,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["polkadot","substrate","wasm","web-components"],"created_at":"2024-10-01T18:38:19.804Z","updated_at":"2026-04-18T15:38:43.238Z","avatar_url":"https://github.com/danforbes.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dots\n\nThe purpose of this project is to elucidate the details of interacting with\nSubstrate- and FRAME-based blockchains via front-end JavaScript and\n[WebAssembly (Wasm)](https://webassembly.org/). The code in this repository is\nfor educational and demonstrational purposes only - it is not intended for\nproduction. This project demonstrates the following capabilities:\n\n- [SCALE](https://docs.substrate.io/reference/scale-codec/) encoding and\n  decoding\n- Parsing\n  [FRAME metadata](https://docs.substrate.io/build/application-development/#metadata-system)\n- Account (i.e.\n  [public/private key](https://docs.substrate.io/fundamentals/accounts-addresses-keys/#public-and-private-keys))\n  generation or recovery\n- WebSocket interaction with the\n  [Substrate JSON-RPC](https://docs.substrate.io/build/application-development/#rpc-apis)\n  server\n- [Signed extrinsic](https://docs.substrate.io/reference/transaction-format/)\n  construction and submission\n\nThose who are familiar with the above concepts may wish to skip ahead to the\n[Usage](#usage) section.\n\n## Background\n\n[Substrate](https://substrate.io/) is a [Rust](https://www.rust-lang.org/)\nframework for building blockchains;\n[FRAME](https://docs.substrate.io/fundamentals/runtime-development/#frame) is\nSubstrate's framework for building blockchain _runtimes_. A \"runtime\" is the\ncomponent of a blockchain system that represents end-user, application\ncapabilities. Blockchains that are built with Substrate and FRAME are\nself-describing systems that expose\n[metadata](https://docs.substrate.io/build/application-development/#metadata-system),\nwhich enables the dynamic, programmatic creation of interfaces that allow users\nto interact with the blockchain runtime.\n\n## Project Components\n\nThe following sections give a brief overview of the components of this project.\n\n### SCALE Codec\n\nSCALE is Substrate's lightweight and efficient codec (i.e. data serialization\nalgorithm). The SCALE encoding omits contextual information in pursuit of\nefficiency, which means that in order to decode SCALE data, it's necessary to\nindependently posses a type registry that defines the structures/schemas of the\nobjects in the data that is to be decoded. Further\n[details of the SCALE codec](doc/scale-codec.md) are outlined in a separate\ndocument. Although it may have been possible to reuse existing Rust code and\ncompile it to Wasm, fighting the Rust type system proved too challenging for an\ninitial implementation - this is potentially an opportunity to improve this\nproject. For now, this project uses a [simple JavaScript SCALE](lib/scale.js)\nimplementation.\n\n### FRAME Metadata\n\nThe metadata exposed by FRAME runtimes consists of three components: 1) a type\nregistry to enable the SCALE-encoding and -decoding of messages to and from the\nruntime, 2) a list that describes the data that must be included with\n[signed extrinsics](#signed-extrinsics), and 3) an exhaustive description of the\nruntime's public interface. Since Substrate and FRAME are Rust-based frameworks,\nthe metadata that is exposed by FRAME runtimes is defined as a Rust `struct`, in\nparticular the\n[`frame_metadata::v14::RuntimeMetadataV14`](https://docs.rs/frame-metadata/latest/frame_metadata/v14/struct.RuntimeMetadataV14.html)\ntype has been used by FRAME since around the end of 2021. When a user requests\nthe metadata from a FRAME-based runtime, the runtime returns a hexadecimal\nstring that represents the SCALE-encoding of its\n`frame_metadata::v14::RuntimeMetadataV14` instance. Although it would be\npossible to decode the hex string and parse the metadata in JavaScript (as in\n[this older code](https://github.com/danforbes/decode-substrate-metadata/blob/master/index.js)\nthat does so for version 11 of FRAME metadata), doing so in Rust and making the\nresulting code available as Wasm has two primary benefits: 1) it relies on\nexisting, unit- and battle-tested libraries that are provided by the maintainers\nof Substrate, 2) it allows for reliable, efficient transformation of the\nmetadata into a structure that is better suited for front-end/client-side use.\nThe Rust code that decodes and transforms the metadata can be found in\n[rs/metadata/src/lib.rs](rs/metadata/src/lib.rs).\n[Further details](doc/frame-metadata.md) about the\n`frame_metadata::v14::RuntimeMetadataV14` format and the transformations that\nare applied to it are documented in a separate file.\n\n### Accounts\n\nLike the decoding and transformation of metadata, most of this project's account\ncapabilities are implemented in Rust and made available to the front-end as\nWasm. The code, which is located in the\n[rs/account/src/lib.rs](rs/account/src/lib.rs) file, was more or less copied\ndirectly from\n[Polkadot-JS](https://github.com/polkadot-js/wasm/tree/v6.3.1/packages/wasm-crypto/src/rs)\nand is fairly self-explanatory. This project supports importing an existing,\nknown account from its 32-byte\n[sr25519](https://wiki.polkadot.network/docs/learn-cryptography#keypairs-and-signing)\nprivate seed, or generating a new\n[BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) seed\nphrase and using that to derive an sr25519 keypair. An sr25519 account can be\nused to sign a message, and a 32-byte sr25519 public key and an\n[Ss58 network identifier](https://github.com/paritytech/ss58-registry/) can be\nused to derive an\n[Ss58 address](https://wiki.polkadot.network/docs/learn-account-advanced#address-format)\nfor that account.\n\n### JSON-RPC\n\nSubstrate uses a [JSON-RPC](https://en.wikipedia.org/wiki/JSON-RPC) server as\nits primary mechanism for interacting with end-users. This project defines a\nJavaScript class named `Context` as an abstraction on top of a\n[WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)\nconnection to a Substrate node's JSON-RPC server. Substrate implements a\nspecification called\n[PSP-6](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md) in order\nto define its JSON-RPC interface; this project relies on a small subset of the\nendpoints defined by this specification. The `Context` class, which can be found\nin the [lib/context.js](lib/context.js) file, makes use of the following PSP-6\nendpoints:\n\n- [`state_subscribeRuntimeVersion`](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md#11113-state_subscriberuntimeversion-pubsub)\n  is used to watch the node for\n  [runtime upgrades](https://docs.substrate.io/build/upgrade-the-runtime/)\n- [`state_getMetadata`](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md#1119-state_getmetadata)\n  is used to retrieve the runtime's [metadata](#metadata), which will only\n  change when the runtime version changes by way of a runtime upgrade\n- The following endpoints are used to track various properties of the node\n  itself (as opposed to the runtime); these properties can be updated on-demand\n  by using the `update` method of the `Context` class\n  - [`system_name`](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md#152-system_name)\n  - [`system_version`](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md#153-system_version)\n  - [`system_chain`](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md#154-system_chain)\n  - [`system_properties`](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md#156-system_properties)\n  - [`system_health`](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md#157-system_health)\n- [`state_getStorage`](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md#1116-state_getstorage)\n  for querying\n  [runtime storage](https://docs.substrate.io/build/runtime-storage/) items\n- [`author_submitAndWatchExtrinsic`](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md#189-author_submitandwatchextrinsic-pubsub)\n  for submitting and tracking [signed extrinsics](#signed-extrinsics)\n- [`system_accountNextIndex`](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md#1516-system_accountnextindex)\n  is used to retrieve the\n  [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) for an account\n  before submitting an extrinsic that is signed by that account\n\n### Signed Extrinsics\n\nThe term \"[extrinsic](https://docs.substrate.io/reference/glossary/#extrinsic)\"\nis native to Substrate and is used to refer to any external data that is\nincluded in a block of a blockchain. The most straightforward usage of this term\napplies to\n\"[signed extrinsics](https://docs.substrate.io/reference/transaction-format/)\",\nwhich are colloquially referred to as \"transactions\". Signed extrinsics allow\nblockchain end-users to interact with the blockchain runtime; as the name\nimplies, requests of this type must be signed by the private key that is\nassociated with a blockchain [account](#accounts), which allows the blockchain\nnetwork to debit that user's account in order to pay the\n[fees](https://docs.substrate.io/build/tx-weights-fees/) associated with that\nrequest. Other types of extrinsics, like\n[unsigned extrinsics](https://docs.substrate.io/fundamentals/transaction-types/#unsigned-transactions)\nor\n[inherents](https://docs.substrate.io/fundamentals/transaction-types/#inherent-transactions),\nare out of the scope of this project at this time. Extrinsic encoding is\nimplemented in the `submitExtrinsic` method of the\n[`Context` class](lib/context.js). [More details](doc/extrinsic-encoding.md)\nabout the encoding of signed extrinsics are documented in a separate file.\n\n## Usage\n\nThis project includes a simple browser front-end that is built with standard\n[Web Components](https://developer.mozilla.org/en-US/docs/Web/Web_Components).\nThe front-end uses the metadata from a Substrate- and FRAME-based blockchain to\nenumerate the modules (\"pallets\") that inform the blockchain runtime. Pallets\nmay expose [storage items](docs/frame-metadata.md#storage-items) or\n[dispatchable calls](docs/frame-metadata.md#dispatchable-calls), and the\nfront-end can be used to query storage items and submit dispatchable calls in\nthe form of signed extrinsics.\n\n### Requirements\n\nOther than a browser and an HTTP server, the only requirement for building and\nusing this project is [`wasm-pack`](https://rustwasm.github.io/docs/wasm-pack/)\nand its associated dependencies for building the Wasm libraries. First,\n[install Rust](https://www.rust-lang.org/tools/install), then\n[install `wasm-pack`](https://rustwasm.github.io/wasm-pack/installer/). This\nproject includes a `package.json` file that provides a command for launching a\nsimple HTTP server, which requires [Node.js](https://nodejs.org/en/).\n\n### Installation\n\nTo build the Wasm libraries and their bindings, and install them in the expected\ndirectory (`lib/wasm`), execute the `build:wasm` NPM script:\n\n```\nnpm run build:wasm\n```\n\n### Web UI\n\nLaunch the web UI by executing the `start` NPM script:\n\n```\nnpm start\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanforbes%2Fdots","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanforbes%2Fdots","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanforbes%2Fdots/lists"}