WIP: Sd 569 docs add and fix apirx examples (#600)
* Docs: Fixed keyring examples * Docs: Added Rx examples * [Docs] Added timeout to showcase unsubscribe method in ApiPromise * [Docs] Added timeout to showcase unsubscribe method in ApiPromise * [Docs] Added comments to read_storage example * [Docs] Renamed "transfer_dots' to a more generic 'make_transfer' since it's not only DOT's * [Docs] ApiRx examples for simple_connect, listen_to_blocks (incl. unsubscribe), listen_to_balance_change and read_storage * [Docs] changed back keyring import syntax to require * [Docs] Removed provider from read storage example * [Docs] ApiRx "make transfer" example * [Docs] ApiRx "system events" example * [Docs] ApiRx "transfer events" example * [Docs] Removed unused utility functions import * [Docs] ApiRx 'upgrade chain' example * [Docs] removed generated html files * [Docs] Ficed wrong Readme of listen to blocks example * [Docs added missing import] * [Docs] Removed unsubscribe() example from 'listen to blocks' * [Docs] Added Unsubscribe example for ApiPromise and ApiRx * [Docs] Added links to summary * [Docs] Removed duplicate info/comment from 04_unsubscribe * [Docs] Fixed wording * [Docs] Log actual transaction status in "make_transfer" * [Docs] Changed author name * [Docs] Log actual transaction status in "make_transfer" * [Docs] changed headline of make_transfer example README's * [Docs] changed status.value to status.asFinalised * [Docs] Removed auto-generated html * [Docs] Changed all occurances of status.value.toHex() to status.asFinalised.toHex() * [Docs] Remove call to nonce observable from signAndSend examples * [Docs] Use RxJs' zip() operator instead of 'await Promise.all()' * [Docs] Remove call to nonce observable from 'upgrade_chain' example * [Docs] Changed author * [Docs] Changed wording of balance change example * [Docs] smaller code-review fixes * [Docs] Fix Rx read_storage example * [Docs] use pairwise together with startWith in the Rx balance_change example * [Docs] Wording & little less code * [Docs] Added whitespace * [Docs] Use switchMap instead fo subscribe inside subscribe syntax * [Docs] Fixed import syntax for RxJs examples * [Docs] removed provider * [Docs] WIP read storage make-over * [Docs] update Rx read_storage * [Docs] Read storage example with piped switchMap() * [Docs] Turn null into observable * [Docs] Read storage example added 2nd version using tap() * [Docs] fixed name typo * [Docs] removed tap() example
This commit is contained in:
committed by
Amaury Martiny
parent
187eae8c81
commit
2433d8d1fc
+12
-2
@@ -16,16 +16,26 @@
|
||||
- [Events (runtime)](METHODS_EVENTS.md)
|
||||
|
||||
## Examples
|
||||
|
||||
- [ApiPromise](examples/promise/README.md)
|
||||
- [Simple connect](examples/promise/01_simple_connect/README.md)
|
||||
- [Listen to blocks](examples/promise/02_listen_to_blocks/README.md)
|
||||
- [Listen to balance change](examples/promise/03_listen_to_balance_change/README.md)
|
||||
- [Unsubscribe from listening](examples/promise/04_unsubscribe/README.md)
|
||||
- [Read chain state](examples/promise/05_read_storage/README.md)
|
||||
- [Make a transfer](examples/promise/07_transfer_dots/README.md)
|
||||
- [Make a transfer](examples/promise/06_make_transfer/README.md)
|
||||
- [Display system events](examples/promise/08_system_events/README.md)(
|
||||
- [Transaction with events](examples/promise/09_transfer_events/README.md)
|
||||
- [Upgrade via sudo](examples/promise/10_upgrade_chain/README.md)
|
||||
- [ApiRx](examples/rx/README.md)
|
||||
- [Simple connect](examples/rx/01_simple_connect/README.md)
|
||||
- [Listen to blocks](examples/rx/02_listen_to_blocks/README.md)
|
||||
- [Listen to balance change](examples/rx/03_listen_to_balance_change/README.md)
|
||||
- [Unsubscribe from listening](examples/rx/04_unsubscribe/README.md)
|
||||
- [Read chain state](examples/rx/05_read_storage/README.md)
|
||||
- [Make a transfer](examples/rx/06_make_transfer/README.md)
|
||||
- [Display system events](examples/rx/08_system_events/README.md)(
|
||||
- [Transaction with events](examples/rx/09_transfer_events/README.md)
|
||||
- [Upgrade via sudo](examples/rx/10_upgrade_chain/README.md)
|
||||
|
||||
<!-- These are hidden, allowing HTML generation but does not appear in the sidebar -->
|
||||
|
||||
|
||||
@@ -30,12 +30,12 @@ api.rpc.chain.subscribeNewHead().subscribe((header) => {
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
Subscribing to chain state -
|
||||
|
||||
```javascript
|
||||
import { combineLatest } from 'rxjs';
|
||||
import { combineLatest, switchMap } from 'rxjs';
|
||||
import { ApiRx } from '@polkadot/api';
|
||||
import { WsProvider } from '@polkadot/rpc-provider';
|
||||
|
||||
@@ -54,18 +54,18 @@ new ApiRx(provider)
|
||||
api.query.timestamp.blockPeriod(),
|
||||
api.query.timestamp.now()
|
||||
])
|
||||
)
|
||||
.subscribe(([blockPeriod, timestamp]) => {
|
||||
const elapsed = last
|
||||
? `, ${timestamp.toNumber() - last}s since last`
|
||||
: '';
|
||||
)
|
||||
.subscribe(([blockPeriod, timestamp]) => {
|
||||
const elapsed = last
|
||||
? `, ${timestamp.toNumber() - last}s since last`
|
||||
: '';
|
||||
|
||||
last = timestamp.toNumber();
|
||||
console.log(`timestamp ${timestamp}${elapsed} (${blockPeriod}s target)`);
|
||||
});
|
||||
last = timestamp.toNumber();
|
||||
console.log(`timestamp ${timestamp}${elapsed} (${blockPeriod}s target)`);
|
||||
}));
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
Submitting a transaction -
|
||||
|
||||
@@ -432,4 +432,3 @@ Api.create().subscribe((api) => {
|
||||
**Returns:** `Observable`<[ApiRx](_rx_index_.apirx.md)>
|
||||
|
||||
___
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Simple Connect
|
||||
|
||||
The following example shows how to instantiate a Polkadot API object and use it to connect to a node.
|
||||
The following example shows how to instantiate a Polkadot API object and use it to connect to a node using ApiPromise.
|
||||
|
||||
[include](index.js)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# Listen to new blocks
|
||||
|
||||
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.
|
||||
|
||||
@@ -10,13 +10,9 @@ async function main () {
|
||||
// Subscribe to the new headers on-chain. The callback is fired when new headers
|
||||
// are found, the call itself returns a promise with a subscription that can be
|
||||
// used to unsubscribe from the newHead subscription
|
||||
const subscriptionId = await api.rpc.chain.subscribeNewHead((header) => {
|
||||
console.log(`best #${header.blockNumber}`);
|
||||
const unsubscribe = await api.rpc.chain.subscribeNewHead((header) => {
|
||||
console.log(`Chain is at block: #${header.blockNumber}`);
|
||||
});
|
||||
|
||||
// Id for the subscription, we can cleanup and unsubscribe via
|
||||
// `api.chain.newHead.unsubscribe(subscriptionId)`
|
||||
console.log(`subsciptionId: ${subscriptionId}`);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Import the Api
|
||||
// Import the API
|
||||
const { ApiPromise } = require('@polkadot/api');
|
||||
|
||||
// Known account we want to use (available on dev chain, with funds)
|
||||
@@ -12,7 +12,7 @@ async function main () {
|
||||
// that resolves to the current on-chain value
|
||||
let previous = await api.query.balances.freeBalance(Alice);
|
||||
|
||||
console.log(`${Alice} has a ${previous} balance`);
|
||||
console.log(`${Alice} has a balance of ${previous}`);
|
||||
console.log(`You may leave this example running and start example 06 or transfer any value to ${Alice}`);
|
||||
|
||||
// Here we subscribe to any balance changes and update the on-screen value
|
||||
@@ -22,13 +22,10 @@ async function main () {
|
||||
|
||||
// Only display positive value changes (Since we are pulling `previous` above already,
|
||||
// the initial balance change will also be zero)
|
||||
if (change.isZero()) {
|
||||
return;
|
||||
if (!change.isZero()) {
|
||||
previous = current;
|
||||
console.log(`New balance change of: ${change}`);
|
||||
}
|
||||
|
||||
previous = current;
|
||||
|
||||
console.log(`Balance of ${Alice}: ${current}, ${change} change`);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# Unsubscribe from listening to updates
|
||||
|
||||
This example shows how to subscribe to and later unsubscribe from listening to block updates.
|
||||
|
||||
In this example we're calling the built-in unsubscribe() function after a timeOut of 20s to cleanup and unsubscribe from listening to updates.
|
||||
|
||||
[include](index.js)
|
||||
@@ -0,0 +1,22 @@
|
||||
// Import the API
|
||||
const { ApiPromise } = require('@polkadot/api');
|
||||
|
||||
async function main () {
|
||||
|
||||
// Create a new instance of the api
|
||||
const api = await ApiPromise.create();
|
||||
|
||||
// Subscribe to chain updates and log the current block number on update.
|
||||
const unsubscribe = await api.rpc.chain.subscribeNewHead((header) => {
|
||||
console.log(`Chain is at block: #${header.blockNumber}`);
|
||||
});
|
||||
|
||||
// In this example we're calling the unsubscribe() function that is being
|
||||
// returned by the api call function after 20s.
|
||||
setTimeout(() => {
|
||||
unsubscribe();
|
||||
console.log('Unsubscribed')
|
||||
}, 20000);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "02_listen_to_blocks",
|
||||
"version": "0.2.0",
|
||||
"description": "Example showing how to use subscriptions",
|
||||
"main": "index.js",
|
||||
"author": "chevdor",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"clean": "rimraf node_modules",
|
||||
"start": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polkadot/api": "^0.38.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "^2.6.2"
|
||||
}
|
||||
}
|
||||
@@ -18,17 +18,20 @@ async function main () {
|
||||
console.log(`accountNonce(${Alice}) ${accountNonce}`);
|
||||
console.log(`blockPeriod ${blockPeriod.toNumber()} seconds`);
|
||||
|
||||
// Retrieve the balances for all validators
|
||||
const validatorBalances = await Promise.all(
|
||||
validators.map((authorityId) =>
|
||||
api.query.balances.freeBalance(authorityId)
|
||||
)
|
||||
);
|
||||
if (validators && validators.length > 0) {
|
||||
// Retrieve the balances for all validators
|
||||
const validatorBalances = await Promise.all(
|
||||
validators.map(authorityId =>
|
||||
api.query.balances.freeBalance(authorityId)
|
||||
)
|
||||
);
|
||||
|
||||
console.log('validators', validators.map((authorityId, index) => ({
|
||||
address: authorityId.toString(),
|
||||
balance: validatorBalances[index].toString()
|
||||
})));
|
||||
// Print out the authorityIds and balances of all validators
|
||||
console.log('validators', validators.map((authorityId, index) => ({
|
||||
address: authorityId.toString(),
|
||||
balance: validatorBalances[index].toString()
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error).finally(_ => process.exit());
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# Tranfer DOTs
|
||||
# Make a simple transfer
|
||||
|
||||
This sample shows how to create a transaction to make a transfer from one an account to another.
|
||||
|
||||
+8
-7
@@ -24,13 +24,14 @@ async function main () {
|
||||
// here we split it out for the sake of readability
|
||||
const transfer = api.tx.balances.transfer(BOB_ADDR, 12345);
|
||||
|
||||
// Sign the transaction using our account
|
||||
transfer.sign(alice, aliceNonce);
|
||||
|
||||
// Send the transaction and retrieve the resulting Hash
|
||||
const hash = await transfer.send();
|
||||
|
||||
console.log(`transfer 12345 to Bob with hash ${hash}`);
|
||||
// Sign and send the transaction using our account. Send the transaction and retrieve the resulting Hash
|
||||
transfer.signAndSend(alice, ({ status, type }) => {
|
||||
if (type === 'Finalised') {
|
||||
console.log(`Successful transfer of 12345 from Alice to Bob with hash ${status.asFinalised.toHex()}`);
|
||||
} else {
|
||||
console.log(`Transaction status: ${type}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
main().catch(console.error).finally(_ => process.exit());
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "07_transfer_dots",
|
||||
"name": "06_make_transfer",
|
||||
"version": "0.2.0",
|
||||
"description": "Example showing how to transfer DOTs",
|
||||
"main": "index.js",
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,8 @@ const AMOUNT = 10000;
|
||||
|
||||
async function main () {
|
||||
// create an instance of our testign keyring
|
||||
// If you're using ES6 module imports instead of require, just change this line to:
|
||||
// const keyring = testKeyring();
|
||||
const keyring = testKeyring.default();
|
||||
|
||||
// Create the API and wait until ready
|
||||
@@ -37,7 +39,7 @@ async function main () {
|
||||
console.log('Transaction status:', type);
|
||||
|
||||
if (type === 'Finalised') {
|
||||
console.log('Completed at block hash', status.value.toHex());
|
||||
console.log('Completed at block hash', status.asFinalised.toHex());
|
||||
console.log('Events:');
|
||||
|
||||
events.forEach(({ phase, event: { data, method, section } }) => {
|
||||
|
||||
@@ -5,9 +5,6 @@ const { WsProvider } = require('@polkadot/rpc-provider');
|
||||
// import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie)
|
||||
const testKeyring = require('@polkadot/keyring/testing');
|
||||
|
||||
// utility functions
|
||||
const { compactAddLength, hexToU8a } = require('@polkadot/util');
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
async function main () {
|
||||
@@ -38,14 +35,13 @@ async function main () {
|
||||
// preform the actual chain upgrade via the sudo module
|
||||
api.tx.sudo
|
||||
.sudo(proposal)
|
||||
.sign(adminPair, adminNonce)
|
||||
.send(({ events = [], status, type }) => {
|
||||
console.log('Transaction status:', type);
|
||||
.signAndSend(adminPair, ({ events = [], status, type }) => {
|
||||
console.log('Proposal status:', type);
|
||||
|
||||
if (type === 'Finalised') {
|
||||
console.error('You have just upgraded your chain');
|
||||
|
||||
console.log('Completed at block hash', status.value.toHex());
|
||||
console.log('Completed at block hash', status.asFinalised.toHex());
|
||||
console.log('Events:');
|
||||
|
||||
events.forEach(({ phase, event: { data, method, section } }) => {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Simple Connect
|
||||
|
||||
The following example shows how to instantiate a Polkadot API object and use it to connect to a node using ApiRx.
|
||||
|
||||
[include](index.js)
|
||||
@@ -0,0 +1,26 @@
|
||||
// Required imports
|
||||
const { zip } = require('rxjs');
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
const { WsProvider } = require('@polkadot/rpc-provider');
|
||||
|
||||
function main () {
|
||||
// Initialise the provider to connect to the local node
|
||||
const provider = new WsProvider('ws://127.0.0.1:9944');
|
||||
|
||||
// Create the API and wait until ready
|
||||
const api = await ApiRx.create(provider).toPromise();
|
||||
|
||||
// We're using RxJs 'zip()' combination operator to get the emitted values
|
||||
// of multiple observables as an array
|
||||
zip(
|
||||
api.rpc.system.chain(),
|
||||
api.rpc.system.name(),
|
||||
api.rpc.system.version()
|
||||
)
|
||||
// Then we subscribe to the result
|
||||
.subscribe(([chain, nodeName, nodeVersion]) => {
|
||||
console.log(`You are connected to chain ${chain} using ${nodeName} v${nodeVersion}`);
|
||||
});
|
||||
}
|
||||
|
||||
main().catch(console.error).finally(() => process.exit());
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "01_simple_connect",
|
||||
"version": "0.2.0",
|
||||
"description": "Example showing how to connect using a WebSocket",
|
||||
"main": "index.js",
|
||||
"author": "Stefie",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"clean": "rimraf node_modules",
|
||||
"start": "node index.js"
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"@polkadot/api": "^0.38.6",
|
||||
"@polkadot/rpc-provider": "^0.38.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "^2.6.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
# Listen to new blocks
|
||||
|
||||
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 with CTRL+C
|
||||
|
||||
[include](index.js)
|
||||
@@ -0,0 +1,19 @@
|
||||
// Import the API
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
const { switchMap } = require('rxjs/operators');
|
||||
|
||||
async function main () {
|
||||
// Here we don't pass the (optional) provider, connecting directly to the default
|
||||
// node/port, i.e. `ws://127.0.0.1:9944`. Await for the isReady promise to ensure
|
||||
// the API has connected to the node and completed the initialisation process
|
||||
new ApiRx().isReady
|
||||
.pipe(
|
||||
switchMap((api) =>
|
||||
api.rpc.chain.subscribeNewHead()
|
||||
))
|
||||
.subscribe((header) => {
|
||||
console.log(`Chain is at block: #${header.blockNumber}`);
|
||||
});
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "02_listen_to_blocks",
|
||||
"version": "0.2.0",
|
||||
"description": "Example showing how to use subscriptions",
|
||||
"main": "index.js",
|
||||
"author": "Stefie",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"clean": "rimraf node_modules",
|
||||
"start": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polkadot/api": "^0.38.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "^2.6.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# Listen to balance changes
|
||||
|
||||
This example shows how to instantiate a Polkadot API object and use it to connect to a node and retrieve balance updates.
|
||||
|
||||
[include](index.js)
|
||||
@@ -0,0 +1,38 @@
|
||||
// Import the API and operators from RxJs
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
const { pairwise, startWith } = require('rxjs/operators');
|
||||
|
||||
// Known account we want to use (available on dev chain, with funds)
|
||||
const Alice = '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDtZ';
|
||||
|
||||
async function main () {
|
||||
// Create an await for the API
|
||||
const api = await ApiRx.create().toPromise();
|
||||
|
||||
// Here we subscribe to any balance changes and update the on-screen value.
|
||||
// We're using RxJs pairwise() operator to get the previous and current values as an array.
|
||||
api.query.balances.freeBalance(Alice)
|
||||
.pipe(
|
||||
// since pairwise only starts emitting values on the second emission, we prepend an
|
||||
// initial value with the startWith() operator to be able to also receive the first value
|
||||
startWith('first'),
|
||||
pairwise()
|
||||
)
|
||||
.subscribe((balance) => {
|
||||
if (balance[0] === 'first') {
|
||||
// Now we know that if the previous value emitted as balance[0] is `first`,
|
||||
// then balance[1] is the initial value of Alice account.
|
||||
console.log(`<b>Alice</b> ${Alice} has a balance of ${balance[1]}`);
|
||||
console.log('You may leave this example running and start the "Make a transfer" example or transfer any value to Alice address');
|
||||
return;
|
||||
}
|
||||
|
||||
const change = balance[1].sub(balance[0]);
|
||||
// Only display value changes
|
||||
if (!change.isZero()) {
|
||||
console.log(`New balance change of: ${change}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "03_listen_to_balance_change",
|
||||
"version": "0.2.0",
|
||||
"description": "Example showing how to subscribe to balance change",
|
||||
"main": "index.js",
|
||||
"author": "Stefie",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"clean": "rimraf node_modules",
|
||||
"start": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polkadot/api": "^0.38.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "^2.6.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# Unsubscribe from listening to updates
|
||||
|
||||
This example shows how to subscribe to and later unsubscribe from listening to block updates.
|
||||
|
||||
In this example we're calling the built-in unsubscribe() function after a timeOut of 20s to cleanup and unsubscribe from listening to updates.
|
||||
|
||||
[include](index.js)
|
||||
@@ -0,0 +1,25 @@
|
||||
// Import the API
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
const { switchMap } = require('rxjs/operators');
|
||||
|
||||
async function main () {
|
||||
// Create a new instance of the api
|
||||
// Subscribe to chain updates and log the current block number on update.
|
||||
const subscription = new ApiRx().isReady
|
||||
.pipe(
|
||||
switchMap((api) =>
|
||||
api.rpc.chain.subscribeNewHead()
|
||||
))
|
||||
.subscribe((header) => {
|
||||
console.log(`Chain is at block: #${header.blockNumber}`);
|
||||
});
|
||||
|
||||
// In this example we're calling the Overvables unsubscribe() //
|
||||
// function after 20s.
|
||||
setTimeout(() => {
|
||||
subscription.unsubscribe();
|
||||
console.log('Unsubscribed');
|
||||
}, 20000);
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "02_listen_to_blocks",
|
||||
"version": "0.2.0",
|
||||
"description": "Example showing how to use subscriptions",
|
||||
"main": "index.js",
|
||||
"author": "Stefie",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"clean": "rimraf node_modules",
|
||||
"start": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polkadot/api": "^0.38.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "^2.6.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# Read storage
|
||||
|
||||
Many important variables are available through the storage API. This example shows how to call a few of those APIs.
|
||||
|
||||
[include](index.js)
|
||||
@@ -0,0 +1,51 @@
|
||||
// Import the API
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
// Import dependencies from RxJs
|
||||
const { combineLatest, of, tap } = require('rxjs');
|
||||
const { first, switchMap } = require('rxjs/operators');
|
||||
|
||||
// Our address for Alice on the dev chain
|
||||
const Alice = '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDtZ';
|
||||
|
||||
function main () {
|
||||
// Create our API with a default connection to the local node
|
||||
new ApiRx(provider).isReady
|
||||
.pipe(
|
||||
// Here we ake our basic chain state/storage queries
|
||||
switchMap((api) => combineLatest(
|
||||
of(api),
|
||||
api.query.session.validators().pipe(first())
|
||||
)),
|
||||
switchMap(([api, validators]) => {
|
||||
// In the next step, we're checking if the node has active validators.
|
||||
// If it does, we're making another call to the api to get the balances for all validators
|
||||
const balances = (validators && validators.length > 0)
|
||||
? combineLatest(validators.map(authorityId => api.query.balances.freeBalance(authorityId).pipe(first())))
|
||||
: of(null);
|
||||
|
||||
// We're combining the results together with the emitted value 'validators',
|
||||
// which we're turning back into an observable using of()
|
||||
return combineLatest(
|
||||
api.query.system.accountNonce(Alice).pipe(first()),
|
||||
api.query.timestamp.blockPeriod().pipe(first()),
|
||||
of(validators),
|
||||
balances
|
||||
);
|
||||
})
|
||||
)
|
||||
// Then we're subscribing to the emitted results
|
||||
.subscribe(([accountNonce, blockPeriod, validators, validatorBalances]) => {
|
||||
console.log(`accountNonce(${Alice}) ${accountNonce}`);
|
||||
console.log(`blockPeriod ${blockPeriod.toNumber()} seconds`);
|
||||
|
||||
if (validatorBalances) {
|
||||
// And lastly we print out the authorityIds and balances of all validators
|
||||
console.log('validators', validators.map((authorityId, index) => ({
|
||||
address: authorityId.toString(),
|
||||
balance: validatorBalances[index].toString()
|
||||
})));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
main().catch(console.error).finally(_ => process.exit());
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "05_read_storage",
|
||||
"version": "0.2.0",
|
||||
"description": "Example showing how to query storage",
|
||||
"main": "index.js",
|
||||
"author": "Stefie",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"clean": "rimraf node_modules",
|
||||
"start": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polkadot/api": "^0.38.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "^2.6.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# Make a simple transfer
|
||||
|
||||
This sample shows how to create a transaction to make a transfer from one an account to another.
|
||||
|
||||
[include](index.js)
|
||||
@@ -0,0 +1,35 @@
|
||||
// Import the API, Keyring and some utility functions
|
||||
const { ApiPromise } = require('@polkadot/api');
|
||||
const { Keyring } = require('@polkadot/keyring');
|
||||
const { stringToU8a } = require('@polkadot/util');
|
||||
|
||||
const ALICE_SEED = 'Alice'.padEnd(32, ' ');
|
||||
const BOB_ADDR = '5Gw3s7q4QLkSWwknsiPtjujPv3XM4Trxi5d4PgKMMk3gfGTE';
|
||||
|
||||
async function main () {
|
||||
// Create an instance of the keyring
|
||||
const keyring = new Keyring();
|
||||
|
||||
// Add Alice to our keyring (with the known seed for the account)
|
||||
const alice = keyring.addFromSeed(stringToU8a(ALICE_SEED));
|
||||
|
||||
// Instantiate the API
|
||||
const api = await ApiRx.create().toPromise();
|
||||
|
||||
// Create a extrinsic, transferring 12345 units to Bob.
|
||||
api.tx.balances
|
||||
// create transfer
|
||||
.transfer(BOB, randomAmount)
|
||||
// Sign and send the transcation
|
||||
.signAndSend(alice)
|
||||
// Subscribe to the status updates of the transfer
|
||||
.subscribe(({ status, type }) => {
|
||||
if (type === 'Finalised') {
|
||||
console.log(`Successful transfer of 12345 from Alice to Bob with hash ${status.asFinalised.toHex()}`);
|
||||
} else {
|
||||
console.log(`Staus of transfer: ${type}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
main().catch(console.error).finally(_ => process.exit());
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "06_make_transfer",
|
||||
"version": "0.2.0",
|
||||
"description": "Example showing how to transfer DOTs",
|
||||
"main": "index.js",
|
||||
"author": "Stefie",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"clean": "rimraf node_modules",
|
||||
"start": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polkadot/api": "^0.38.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "^2.6.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# Traverse events
|
||||
|
||||
Query the system events and extract information from them. This example runs until exited via Ctrl-C
|
||||
|
||||
[include](index.js)
|
||||
@@ -0,0 +1,37 @@
|
||||
// Import the API and selected RxJs operators
|
||||
const { switchMap } = require('rxjs/operators');
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
|
||||
async function main () {
|
||||
// Create our API with a default connection to the local node
|
||||
ApiRx.create()
|
||||
.pipe(
|
||||
switchMap((api) =>
|
||||
// subscribe to system events via storage
|
||||
api.query.system.events()
|
||||
))
|
||||
// Then we're subscribing to the emitted results
|
||||
.subscribe((events) => {
|
||||
console.log(`\nReceived ${events.length} events:`);
|
||||
// loop through the Vec<EventRecord>
|
||||
events.forEach((record) => {
|
||||
// extract the phase, event and the event types
|
||||
const { event, phase } = record;
|
||||
const types = event.typeDef;
|
||||
|
||||
// show what we are busy with
|
||||
console.log(`\t${event.section}:${event.method}:: (phase=${phase.toString()})`);
|
||||
console.log(`\t\t${event.meta.documentation.toString()}`);
|
||||
|
||||
// loop through each of the parameters, displaying the type and data
|
||||
event.data.forEach((data, index) => {
|
||||
console.log(`\t\t\t${types[index].type}: ${data.toString()}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(-1);
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "08_system_events",
|
||||
"version": "0.1.0",
|
||||
"description": "Example showing how to query and parse events",
|
||||
"main": "index.js",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"clean": "rimraf node_modules",
|
||||
"start": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polkadot/api": "^0.38.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "^2.6.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# Transfer events
|
||||
|
||||
Display the events that occur during a transfer by sending a value to a random account
|
||||
|
||||
[include](index.js)
|
||||
@@ -0,0 +1,54 @@
|
||||
// Import the API and some utility functions
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
|
||||
// import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie)
|
||||
const testKeyring = require('@polkadot/keyring/testing');
|
||||
|
||||
// utility function for random values
|
||||
const { randomAsU8a } = require('@polkadot/util-crypto');
|
||||
|
||||
// some constants we are using in this sample
|
||||
const ALICE = '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDtZ';
|
||||
const AMOUNT = 10000;
|
||||
|
||||
async function main () {
|
||||
// create an instance of our testign keyring
|
||||
// If you're using ES6 module imports instead of require, just change this line to:
|
||||
// const keyring = testKeyring();
|
||||
const keyring = testKeyring.default();
|
||||
|
||||
// Create our API with a connection to the node
|
||||
const api = await ApiRx.create().toPromise();
|
||||
|
||||
// find the actual keypair in the keyring
|
||||
const alicePair = keyring.getPair(ALICE);
|
||||
|
||||
// create a new random recipient
|
||||
const recipient = keyring.addFromSeed(randomAsU8a(32)).address();
|
||||
|
||||
console.log('Sending', AMOUNT, 'from', alicePair.address(), 'to', recipient);
|
||||
|
||||
// get the nonce for the admin key
|
||||
// Create a extrinsic, transferring 12345 units to Bob.
|
||||
api.tx.balances
|
||||
// Do the transfer
|
||||
.transfer(recipient, AMOUNT)
|
||||
// Sign and send it
|
||||
.signAndSend(alicePair)
|
||||
// And subscribe to the actual status
|
||||
.subscribe(({ events = [], status, type }) => {
|
||||
// Log transfer events
|
||||
console.log('Transfer status:', type);
|
||||
// Log system events once the transfer is finalised
|
||||
if (type === 'Finalised') {
|
||||
console.log('Completed at block hash', status.asFinalised.toHex());
|
||||
console.log('Events:');
|
||||
|
||||
events.forEach(({ phase, event: { data, method, section } }) => {
|
||||
console.log('\t', phase.toString(), `: ${section}.${method}`, data.toString());
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "09_transfer_events",
|
||||
"version": "0.1.0",
|
||||
"description": "Example showing how to transfer DOTs (with events)",
|
||||
"main": "index.js",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"clean": "rimraf node_modules",
|
||||
"start": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polkadot/api": "^0.38.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "^2.6.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# Chain upgrade
|
||||
|
||||
Performs a chain upgrade using the `sudo` module. This may brick your chain, so us it as an educational sample. (use `substrate --dev purge-chain` to remove DB and recover).
|
||||
|
||||
[include](index.js)
|
||||
@@ -0,0 +1,59 @@
|
||||
// Import the API & Provider and some utility functions
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
const { WsProvider } = require('@polkadot/rpc-provider');
|
||||
// import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie)
|
||||
const testKeyring = require('@polkadot/keyring/testing');
|
||||
const fs = require('fs');
|
||||
|
||||
async function main () {
|
||||
// Initialise the provider to connect to the local node
|
||||
const provider = new WsProvider('ws://127.0.0.1:9944');
|
||||
|
||||
// Create the API and wait until ready (optional provider passed through)
|
||||
const api = await ApiRx.create(provider).toPromise();
|
||||
|
||||
// retrieve the upgrade key from the chain state
|
||||
const adminId = await api.query.sudo.key().toPromise();
|
||||
|
||||
// find the actual keypair in the keyring (if this is an changed value, the key
|
||||
// needs to be added to the keyring before - this assumes we have defaults, i.e.
|
||||
// Alice as the key - and this already exists on the test keyring)
|
||||
const keyring = testKeyring.default();
|
||||
const adminPair = keyring.getPair(adminId.toString());
|
||||
|
||||
// retrieve the runtime to upgrade to
|
||||
const code = fs.readFileSync('./test.wasm').toString('hex');
|
||||
const proposal = api.tx.consensus.setCode(`0x${code}`);
|
||||
|
||||
console.log(`Upgrading chain runtime from ${adminId}`);
|
||||
|
||||
api.tx.sudo
|
||||
// preform the actual chain upgrade via the sudo module
|
||||
.sudo(proposal)
|
||||
// sign and send the proposal
|
||||
.signAndSend(adminPair)
|
||||
// subscribe to overall result
|
||||
.subscribe(({ events = [], status, type }) => {
|
||||
// Log transfer events
|
||||
console.log('Proposal status:', type);
|
||||
|
||||
if (type === 'Finalised') {
|
||||
console.error('You have just upgraded your chain');
|
||||
|
||||
console.log('Completed at block hash', status.asFinalised.toHex());
|
||||
console.log('Events:');
|
||||
|
||||
// Log system events once the chain update is finalised
|
||||
events.forEach(({ phase, event: { data, method, section } }) => {
|
||||
console.log('\t', phase.toString(), `: ${section}.${method}`, data.toString());
|
||||
});
|
||||
|
||||
process.exit(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(-1);
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "10_upgrade_chain",
|
||||
"version": "0.2.0",
|
||||
"description": "Example showing how to upgrade via upgradeKey",
|
||||
"main": "index.js",
|
||||
"author": "Stefie",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"clean": "rimraf node_modules",
|
||||
"start": "node index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polkadot/api": "^0.38.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"rimraf": "^2.6.2"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,26 @@
|
||||
# ApiPromise Examples
|
||||
|
||||
Here you will find a list of examples that takes you through the basics of connecting to a local node, retrieving data from the Node and chain and execute transactions on the chain. It uses the [[ApiRx]] interface.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
For the following examples, you need a local node. It is usually convenient testing with:
|
||||
|
||||
```
|
||||
substrate --dev
|
||||
```
|
||||
|
||||
## Running the examples
|
||||
|
||||
From each folder, run `yarn` to install the required dependencies and then run `yarn start` to execute the example against the running node.
|
||||
|
||||
## Development accounts
|
||||
|
||||
Some of the examples use the following accounts:
|
||||
|
||||
- Alice: `5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaDtZ`
|
||||
- Bob: `5Gw3s7q4QLkSWwknsiPtjujPv3XM4Trxi5d4PgKMMk3gfGTE`
|
||||
|
||||
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.
|
||||
Reference in New Issue
Block a user