Individuals making significant and valuable contributions are given commit-access to a project to contribute as they see fit.
+A project is more like an open wiki than a standard guarded open source project.
+
+
+
+
+
Rules
+
+
+
There are a few basic ground-rules for contributors (including the maintainer(s) of the project):
+
+
+
+
+
No --force pushes or modifying the Git history in any way. If you need to rebase, ensure you do it in your own repo.
+
+
+
Non-master branches, prefixed with a short name moniker (e.g. gav-my-feature) must be used for ongoing work.
+
+
+
All modifications must be made in a pull-request to solicit feedback from other contributors.
+
+
+
A pull-request must not be merged until CI has finished successfully.
+
+
+
+
+
Merging pull requests once CI is successful:
+
+
+
+
+
A pull request with no large change to logic that is an urgent fix may be merged after a non-author contributor has reviewed it well.
+
+
+
No PR should be merged until all reviews' comments are addressed.
+
+
+
+
+
Reviewing pull requests:
+
When reviewing a pull request, the end-goal is to suggest useful changes to the author. Reviews should finish with approval unless there are issues that would result in:
+
+
+
+
+
Buggy behaviour.
+
+
+
Undue maintenance burden.
+
+
+
Breaking with house coding style.
+
+
+
Pessimisation (i.e. reduction of speed as measured in the projects benchmarks).
+
+
+
Feature reduction (i.e. it removes some aspect of functionality that a significant minority of users rely on).
+
+
+
Uselessness (i.e. it does not strictly add a feature or fix a known issue).
+
+
+
+
+
Reviews may not be used as an effective veto for a PR because:
+
+
+
There exists a somewhat cleaner/better/faster way of accomplishing the same feature/fix.
+
+
+
It does not fit well with some other contributors' longer-term vision for the project.
+
+
+
+
+
+
+
Releases
+
+
+
Declaring formal releases remains the prerogative of the project maintainer(s).
+
+
+
+
+
Changes to this arrangement
+
+
+
This is an experiment and feedback is welcome! This document may also be subject to pull-requests or changes by contributors where you believe you have something valuable to add or change.
Formatters that are used by the application API interface, taking care of transparently formatting parameters (inputs) and the results (output) for requests made over the client RPC interfaces.
Generic transport providers to handle the transport of method calls to and from Polkadot clients from applications interacting with it. Generally, unless you are operating at a low-level and taking care of encoding and decoding of parameters/results, it won't be directly used. API interfaces building on top these providers can support various transports with the same underlying interfaces.
+
Usage
+
Installation -
+
npm install --save @polkadot/api-provider
+
Initialisation -
+
import WsProvider from'@polkadot/api-provider/ws';
+
+const provider = new WsProvider('http://127.0.0.1:9944');
+const version = await provider.send('client_version', []);
+
+console.log('clientVersion', version);
+
Warning - currently this does not actually do all that much, it is an attempt to put into code some thoughts about how to maintain the endpoints. This library provides a clean wrapper around all the methods exposed by a Polkadot network client.
+
Methods are auto-generated for the JsonRPC interface definitions, containing a full list of all sections and the methods contained within.
+
Usage
+
Installation -
+
npm install --save @polkadot/api
+
Initialisation -
+
import Api from'@polkadot/api';
+import WsProvider from'@polkadot/api-provider/ws';
+
+const provider = new WsProvider('http://127.0.0.1:9944');
+const api = new Api(provider);
+
This example shows how to subscribe to new blocks.
+
+
+
It displays the block number every time a new block is seen by the node you are connected to.
+
+
+
+
+
+
Note
+
+
+The example runs until you stop it wit CTRL+C
+
+
+
+
+
+
+
const BN = require('bn.js')
+const Api = require('@polkadot/api').default
+const WsProvider = require('@polkadot/api-provider/ws').default
+const provider = new WsProvider('ws://127.0.0.1:9944')
+const api = new Api(provider)
+
+functionmain () {
+ console.log('Blocks will be shown as they come in, CTRL+C to stop:')
+ api.chain.newHead((_, header) => {
+ const bnBlockNumber = new BN(header.number, 16)
+ console.log('#' + bnBlockNumber.toString(10))
+ })
+}
+
+main()
This example shows how to instantiate a Polkadot API object and use it to connect to a node.
+
+
+
+
const Api = require('@polkadot/api').default
+const WsProvider = require('@polkadot/api-provider/ws').default
+const storage = require('@polkadot/storage').default
+const BN = require('bn.js')
+const provider = new WsProvider('ws://127.0.0.1:9944')
+const api = new Api(provider)
+const Alice = '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDtZ'
+
+console.log('You may let this example running and start the example 06 or send DOTs to ' + Alice)
+api.state.storage([[storage.staking.public.freeBalanceOf, Alice]], (_, values) => {
+ console.log(`Balance of ${Alice}: ${new BN(values[0]).toString(10)} DOTs`)
+}).then((subscriptionId) => {
+ console.log('Balance changes subscription id:', subscriptionId)
+})
If you want to develop a wallet or a program that will accept payments in DOTs, you likely will need to generate addresses. This sample shows you how to generate accounts in several ways.
+
+
+
+
const Keyring = require('@polkadot/util-keyring').default
+const u8aToHex = require('@polkadot/util/u8a/toHex').default
+const Encoder = new TextEncoder() // always utf-8
+const crypto = require('crypto')
+
+// A fixed seed from an array
+const SEED1 = newUint8Array(
+ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 0, 0])
+
+// A fixed seed from a 32 chars string
+const SEED2 = Encoder.encode('correct horse battery and staple')
+
+const keyring = new Keyring()
+const pair1 = keyring.addFromSeed(SEED1)
+const pair2 = keyring.addFromSeed(SEED2)
+
+console.log('Deterministic addresses (same for each run):')
+console.log(`Address 1\t ${pair1.address()}\t Seed: ${u8aToHex(SEED1)}`)
+console.log(`Address 2\t ${pair2.address()}\t Seed: ${u8aToHex(SEED2)}`)
+
+// A random seed
+const SEED = newUint8Array(32)
+console.log('Random Addresses (random for each run):')
+for (var i = 3; i < 13; i++) {
+ Buffer.from(crypto.randomFillSync(SEED))
+ const pair3 = keyring.addFromSeed(SEED)
+ console.log(`Address ${i}\t ${pair3.address()}\t Seed: ${u8aToHex(SEED)}`)
+}
In the current version, crafting an extrinsic is a rather cumbersome process. This sample guides you though it and shows how to tranfer DOTs from an account to another.
+
+
+
+
const Api = require('@polkadot/api').default
+const WsProvider = require('@polkadot/api-provider/ws').default
+const extrinsics = require('@polkadot/extrinsics').default
+const encodeExtrinsic = require('@polkadot/extrinsics/codec/encode').default
+const encodeLength = require('@polkadot/extrinsics/codec/encode/length').default
+const Keyring = require('@polkadot/util-keyring').default
+const storage = require('@polkadot/storage').default
+const BN = require('bn.js')
+
+const Encoder = new TextEncoder()
+const keyring = new Keyring()
+const provider = new WsProvider('ws://127.0.0.1:9944')
+const api = new Api(provider)
+
+asyncfunctiongetAccountIndex (address) {
+ return api.state.getStorage([storage.system.public.accountIndexOf, address])
+}
+
+asyncfunctiontransfer (keyRingFrom, addressTo, amount) {
+ const accountIndex = await getAccountIndex(keyRingFrom.address())
+ console.log(`Current accountIndex: ${accountIndex}`)
+
+ // encode the call for signing
+ const message = encodeExtrinsic(
+ keyRingFrom.publicKey(),
+ accountIndex,
+ extrinsics.staking.public.transfer,
+ [addressTo, amount]
+ )
+
+ // get the signature
+ const signature = keyRingFrom.sign(message)
+
+ // encode the extrinsic for submission, adding the length (prefix) and the
+ // signature (postfix)Rödl
+ const encoded = encodeLength(
+ // When working with publicKeys, the prefix is 0xff for poc-2+
+ newUint8Array([0xff]),
+ message,
+ signature
+ )
+
+ return api.author.submitExtrinsic(encoded)
+}
+
+const Alice = keyring.addFromSeed(Encoder.encode('Alice '))
+const addressBob = '5Gw3s7q4QLkSWwknsiPtjujPv3XM4Trxi5d4PgKMMk3gfGTE'
+const amount = new BN(999) // on dev chain, the fee is 1, that makes it a round 1000
+
+console.log(`Crafting and sending an extrinsic for Alice to send Bob ${amount} DOTs`)
+transfer(Alice, addressBob, amount)
+ .then(() => console.log('Sent'))
+ .catch((e) => console.log(
+ 'HINT: Make sure you wait for the storage to update before sending the next extrinsic', e))
+ .finally(_ => process.exit(0))
Those accounts are easy to add if you don´t have/see them. The seed of Alice´s account is Alice␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣ and the seed of Bob is… well you guess…
+
+
+
+
+
+
Note
+
+
+Note the spaces padding Alice´s key up to 32 chars.
+
+
+
+
+
+
+
+
Install
+
+
+
From each folder, run yarn to install the required dependencies