From 73d7a57d38d271bff493d88527aba23e2bd9373e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?James=20Lefr=C3=A8re?= Date: Thu, 19 Sep 2019 11:43:47 +0200 Subject: [PATCH] Add `.eq()` usage to docs and fix docs typos (#1405) * Use `eq` for example * Use the base `eq` function rather than `===`, so that comparisons are made in a consistent manner in docs * Add `eq` example * Add an example of using the `eq` method to the base docs * Adjust docs/examples * Fix a number of typos in the static docs and examples * Adjust various comments in docs examples such that they are written in a consistent case * Fix metadata docs spacing * Adjust the metadata documentation generation such that unnecessary spaces are trimmed --- .../promise/02_listen_to_blocks/index.js | 2 +- docs/examples/promise/04_unsubscribe/index.js | 2 +- .../promise/05_read_storage_at/index.js | 6 ++-- .../promise/06_make_transfer/index.js | 2 +- .../index.js | 6 ++-- .../promise/08_system_events/index.js | 10 +++--- .../promise/09_transfer_events/index.js | 14 ++++---- .../promise/10_upgrade_chain/index.js | 8 ++--- .../rx/03_listen_to_balance_change/index.js | 2 +- docs/examples/rx/04_unsubscribe/index.js | 2 +- docs/examples/rx/09_transfer_events/index.js | 16 +++++----- docs/examples/rx/10_upgrade_chain/index.js | 14 ++++---- docs/start/README.md | 2 +- docs/start/api.consts.md | 8 ++--- docs/start/api.query.md | 14 ++++---- docs/start/api.query.multi.md | 10 +++--- docs/start/api.query.other.md | 18 +++++------ docs/start/api.query.subs.md | 4 +-- docs/start/api.rpc.md | 12 +++---- docs/start/api.tx.md | 6 ++-- docs/start/api.tx.subs.md | 10 +++--- docs/start/api.tx.wrap.md | 8 ++--- docs/start/basics.md | 2 +- docs/start/create.md | 18 +++++------ docs/start/keyring.md | 32 +++++++++---------- docs/start/types.basics.md | 25 ++++++++++++--- docs/start/types.extend.md | 8 ++--- docs/start/typescript.md | 8 ++--- packages/types/src/scripts/MetadataMd.ts | 13 +++++--- 29 files changed, 152 insertions(+), 130 deletions(-) diff --git a/docs/examples/promise/02_listen_to_blocks/index.js b/docs/examples/promise/02_listen_to_blocks/index.js index 10a871777b..b9355c3c3a 100755 --- a/docs/examples/promise/02_listen_to_blocks/index.js +++ b/docs/examples/promise/02_listen_to_blocks/index.js @@ -10,7 +10,7 @@ async function main () { // the API has connected to the node and completed the initialisation process const api = await ApiPromise.create(); - // we only display a couple, then unsubscribe + // We only display a couple, then unsubscribe let count = 0; // Subscribe to the new headers on-chain. The callback is fired when new headers diff --git a/docs/examples/promise/04_unsubscribe/index.js b/docs/examples/promise/04_unsubscribe/index.js index 3d60a6aa66..bc049fd369 100644 --- a/docs/examples/promise/04_unsubscribe/index.js +++ b/docs/examples/promise/04_unsubscribe/index.js @@ -8,7 +8,7 @@ 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. + // 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.number}`); }); diff --git a/docs/examples/promise/05_read_storage_at/index.js b/docs/examples/promise/05_read_storage_at/index.js index 33ddfb6246..e8ee20944c 100755 --- a/docs/examples/promise/05_read_storage_at/index.js +++ b/docs/examples/promise/05_read_storage_at/index.js @@ -12,18 +12,18 @@ async function main () { // Create our API with a default connection to the local node const api = await ApiPromise.create(); - // retrieve the last block header, extracting the hash and parentHash + // Retrieve the last block header, extracting the hash and parentHash const { hash, parentHash } = await api.rpc.chain.getHeader(); console.log(`last header hash ${hash.toHex()}`); - // retrieve the balance at the preceding block for Alice. For at queries + // Retrieve the balance at the preceding block for Alice. For at queries // the format is always `.at(, ...params)` const balance = await api.query.balances.freeBalance.at(parentHash, ALICE); console.log(`Alice's balance at ${parentHash.toHex()} was ${balance}`); - // now perform a multi query, returning multiple balances at once + // Now perform a multi query, returning multiple balances at once const balances = await api.query.balances.freeBalance.multi([ALICE, BOB]); console.log(`Current balances for Alice and Bob are ${balances[0]} and ${balances[1]}`); diff --git a/docs/examples/promise/06_make_transfer/index.js b/docs/examples/promise/06_make_transfer/index.js index 01838225db..b38c313cd0 100755 --- a/docs/examples/promise/06_make_transfer/index.js +++ b/docs/examples/promise/06_make_transfer/index.js @@ -14,7 +14,7 @@ async function main () { // Constuct the keying after the API (crypto has an async init) const keyring = new Keyring({ type: 'sr25519' }); - // Add alice to our keyring with a hard-deived path (empty phrase, so uses dev) + // Add Alice to our keyring with a hard-deived path (empty phrase, so uses dev) const alice = keyring.addFromUri('//Alice'); // Create a extrinsic, transferring 12345 units to Bob diff --git a/docs/examples/promise/07_make_transfer_with_allowed_block_permissions_only/index.js b/docs/examples/promise/07_make_transfer_with_allowed_block_permissions_only/index.js index 6bb8868b00..47fc2b2b7f 100644 --- a/docs/examples/promise/07_make_transfer_with_allowed_block_permissions_only/index.js +++ b/docs/examples/promise/07_make_transfer_with_allowed_block_permissions_only/index.js @@ -15,16 +15,16 @@ async function main () { // Constuct the keying after the API (crypto has an async init) const keyring = new Keyring({ type: 'sr25519' }); - // Add alice to our keyring with a hard-derived path (empty phrase, so uses dev) + // Add Alice to our keyring with a hard-derived path (empty phrase, so uses dev) const alice = keyring.addFromUri('//Alice'); // Get nonce for account const nonce = await api.query.system.accountNonce(alice.address); - // get current block + // Get current block const signedBlock = await api.rpc.chain.getBlock(); - // get current block height and hash + // Get current block height and hash const currentHeight = signedBlock.block.header.number; const blockHash = signedBlock.block.header.hash; diff --git a/docs/examples/promise/08_system_events/index.js b/docs/examples/promise/08_system_events/index.js index a81baf7ea7..39568a4383 100755 --- a/docs/examples/promise/08_system_events/index.js +++ b/docs/examples/promise/08_system_events/index.js @@ -8,21 +8,21 @@ async function main () { // Create our API with a default connection to the local node const api = await ApiPromise.create(); - // subscribe to system events via storage + // Subscribe to system events via storage api.query.system.events((events) => { console.log(`\nReceived ${events.length} events:`); - // loop through the Vec + // Loop through the Vec events.forEach((record) => { - // extract the phase, event and the event types + // Extract the phase, event and the event types const { event, phase } = record; const types = event.typeDef; - // show what we are busy with + // 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 + // 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()}`); }); diff --git a/docs/examples/promise/09_transfer_events/index.js b/docs/examples/promise/09_transfer_events/index.js index 5a55414a7c..06d05411cc 100755 --- a/docs/examples/promise/09_transfer_events/index.js +++ b/docs/examples/promise/09_transfer_events/index.js @@ -4,13 +4,13 @@ // Import the API & Provider and some utility functions const { ApiPromise } = require('@polkadot/api'); -// import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie) +// 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 +// Utility function for random values const { randomAsU8a } = require('@polkadot/util-crypto'); -// some constants we are using in this sample +// Some constants we are using in this sample const ALICE = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'; const AMOUNT = 10000; @@ -18,18 +18,18 @@ async function main () { // Create the API and wait until ready const api = await ApiPromise.create(); - // create an instance of our testing keyring + // Create an instance of our testing keyring // If you're using ES6 module imports instead of require, just change this line to: // const keyring = testKeyring(); const keyring = testKeyring.default(); - // get the nonce for the admin key + // Get the nonce for the admin key const nonce = await api.query.system.accountNonce(ALICE); - // find the actual keypair in the keyring + // Find the actual keypair in the keyring const alicePair = keyring.getPair(ALICE); - // create a new random recipient + // Create a new random recipient const recipient = keyring.addFromSeed(randomAsU8a(32)).address; console.log('Sending', AMOUNT, 'from', alicePair.address, 'to', recipient, 'with nonce', nonce.toString()); diff --git a/docs/examples/promise/10_upgrade_chain/index.js b/docs/examples/promise/10_upgrade_chain/index.js index b216924b0e..bb6eeaf4f7 100755 --- a/docs/examples/promise/10_upgrade_chain/index.js +++ b/docs/examples/promise/10_upgrade_chain/index.js @@ -16,22 +16,22 @@ async function main () { // Create the API and wait until ready (optional provider passed through) const api = await ApiPromise.create({ provider }); - // retrieve the upgrade key from the chain state + // Retrieve the upgrade key from the chain state const adminId = await api.query.sudo.key(); - // find the actual keypair in the keyring (if this is an changed value, the key + // Find the actual keypair in the keyring (if this is a 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 + // 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 from ${adminId}, ${code.length / 2} bytes`); - // preform the actual chain upgrade via the sudo module + // Perform the actual chain upgrade via the sudo module api.tx.sudo .sudo(proposal) .signAndSend(adminPair, ({ events = [], status }) => { diff --git a/docs/examples/rx/03_listen_to_balance_change/index.js b/docs/examples/rx/03_listen_to_balance_change/index.js index 9e2acf1ee8..b9d37a4700 100644 --- a/docs/examples/rx/03_listen_to_balance_change/index.js +++ b/docs/examples/rx/03_listen_to_balance_change/index.js @@ -22,7 +22,7 @@ async function main () { pairwise() ) .subscribe((balance) => { - if (balance[0] === 'first') { + if (balance[0].eq('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(`Alice ${Alice} has a balance of ${balance[1]}`); diff --git a/docs/examples/rx/04_unsubscribe/index.js b/docs/examples/rx/04_unsubscribe/index.js index 8985d50438..e49977f758 100644 --- a/docs/examples/rx/04_unsubscribe/index.js +++ b/docs/examples/rx/04_unsubscribe/index.js @@ -7,7 +7,7 @@ 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. + // Subscribe to chain updates and log the current block number on update. const subscription = new ApiRx().isReady .pipe( switchMap((api) => diff --git a/docs/examples/rx/09_transfer_events/index.js b/docs/examples/rx/09_transfer_events/index.js index 343c9ddab2..16b8a4372d 100644 --- a/docs/examples/rx/09_transfer_events/index.js +++ b/docs/examples/rx/09_transfer_events/index.js @@ -4,13 +4,13 @@ // 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) +// 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 +// Utility function for random values const { randomAsU8a } = require('@polkadot/util-crypto'); -// some constants we are using in this sample +// Some constants we are using in this sample const ALICE = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'; const AMOUNT = 10000; @@ -18,21 +18,21 @@ async function main () { // Create our API with a connection to the node const api = await ApiRx.create().toPromise(); - // create an instance of our testign keyring + // 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(); - // find the actual keypair in the keyring + // Find the actual keypair in the keyring const alicePair = keyring.getPair(ALICE); - // create a new random recipient + // 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. + // Get the nonce for the admin key + // Create a extrinsic, transferring 12345 units to Bob. api.tx.balances // Do the transfer .transfer(recipient, AMOUNT) diff --git a/docs/examples/rx/10_upgrade_chain/index.js b/docs/examples/rx/10_upgrade_chain/index.js index d1ce751525..42d2e38522 100644 --- a/docs/examples/rx/10_upgrade_chain/index.js +++ b/docs/examples/rx/10_upgrade_chain/index.js @@ -3,7 +3,7 @@ /* eslint-disable @typescript-eslint/no-var-requires */ // Import the API & Provider and some utility functions const { ApiRx, WsProvider } = require('@polkadot/api'); -// import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie) +// Import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie) const testKeyring = require('@polkadot/keyring/testing'); const fs = require('fs'); @@ -14,27 +14,27 @@ async function main () { // 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 + // 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 + // 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 + // 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 + // Perform the actual chain upgrade via the sudo module .sudo(proposal) - // sign and send the proposal + // Sign and send the proposal .signAndSend(adminPair) - // subscribe to overall result + // Subscribe to overall result .subscribe(({ events = [], status }) => { // Log transfer events console.log('Proposal status:', status.type); diff --git a/docs/start/README.md b/docs/start/README.md index dde3c690ab..b55b8fe1b2 100644 --- a/docs/start/README.md +++ b/docs/start/README.md @@ -4,7 +4,7 @@ These sections should provide you with all the information needed to install the ## What this is not -This is not line-by-line documentation of all the extising function calls available, nor it is tied to a specific chain. (Although the examples do refer to the base Polkadot & Substrate chains). There will be some things in the API that are probably not covered, which brings us to the next point... +This is not line-by-line documentation of all the existing function calls available, nor it is tied to a specific chain. (Although the examples do refer to the base Polkadot & Substrate chains). There will be some things in the API that are probably not covered, which brings us to the next point... ## Help us help others diff --git a/docs/start/api.consts.md b/docs/start/api.consts.md index 39f81c323c..6560b6f597 100644 --- a/docs/start/api.consts.md +++ b/docs/start/api.consts.md @@ -5,16 +5,16 @@ Constant queries will introduce you to the concepts behind the types and the int For some background: constants are values that are defined in the runtime and used as part of chain operations. These constants can be changed as part of an upgrade. ```js -// initialize the API as per previous sections +// Initialize the API as per previous sections ... -// the length of an epoch (session) in Babe +// The length of an epoch (session) in Babe console.log(api.consts.babe.epochDuration.toNumber()); -// the amount required to create a new account +// The amount required to create a new account console.log(api.consts.balances.creationFee.toNumber()); -// the amount required per byte on an extrinsic +// The amount required per byte on an extrinsic console.log(api.consts.balances.transactionByteFee.toNumber()); ``` diff --git a/docs/start/api.query.md b/docs/start/api.query.md index 70bbf579c4..ed5a1aeb15 100644 --- a/docs/start/api.query.md +++ b/docs/start/api.query.md @@ -7,19 +7,19 @@ In previous sections, we initialized the API and retrieved runtime constants. Th Let's dive right in, connect to a general chain and retrieve some information on the current state. Of interest may be retrieving the nonce of a particular account as well as the current balance, this can be achieved via - ```js -// initialize the API as in previous sections +// Initialize the API as in previous sections ... -// the actual address that we will use +// The actual address that we will use const ADDR = '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE'; -// retrieve the last timestamp +// Retrieve the last timestamp const now = await api.query.timestamp.now(); -// retrieve the account nonce via the system module +// Retrieve the account nonce via the system module const nonce = await api.query.system.accountNonce(ADDR); -// retrieve the account balance via the balances module +// Retrieve the account balance via the balances module const balance = await api.query.balances.freeBalance(ADDR); console.log(`${now}: balance of ${balance} and a nonce of ${nonce}`); @@ -29,7 +29,7 @@ There have been some additions in the code above comparing with retrieving runti ```js ... -// retrieve last block timestamp, account nonce & balance +// Retrieve last block timestamp, account nonce & balance const [now, nonce, balance] = await Promise.all([ api.query.timestamp.now(), api.query.system.accountNonce(ADDR), @@ -41,7 +41,7 @@ const [now, nonce, balance] = await Promise.all([ As indicated in previous sections, any return value is always an object with a consistent interface that reflects the type being returned. In the above example, the timestamp is a `Moment` (a `u64` value), the nonce is an `Index` (a `u32` value) and the `Balance` is an underlying `u128`. -Additionally we have provided some parameters for the query calls, specifically for the retrieval of the nonce and balance. It is important to note that the API will automatically convert any parameters into the correct type for encoding and making calls, in this case the `AccountId` parameter could be specified as a ss58 address (as it was), an actual `AccountId` (retrieved via another call) or just a plain `Uint8Array` (or even hex-string representation) for a publicKey. +Additionally we have provided some parameters for the query calls, specifically for the retrieval of the nonce and balance. It is important to note that the API will automatically convert any parameters into the correct type for encoding and making calls, in this case the `AccountId` parameter could be specified as a ss58 address (as it was), an actual `AccountId` (retrieved via another call) or just a plain `Uint8Array` (or even hex-string representation) for a publicKey. ## Exploring RPCs diff --git a/docs/start/api.query.multi.md b/docs/start/api.query.multi.md index df06e344c7..de8ac41d0d 100644 --- a/docs/start/api.query.multi.md +++ b/docs/start/api.query.multi.md @@ -4,12 +4,12 @@ In a number of applications, it is useful to monitor a number of like-queries at ## Multi queries, same type -Where possible, the use of multi queries are encouraged since it tracks a number of state entries over a single RPC call, instead of making a call for each single item. In addition it allows you to have a single callback to track changes. For queries of the same type we can use `.multi`, for example to retrieve the balances of a number of accounts at once - +Where possible, the use of multi queries are encouraged since it tracks a number of state entries over a single RPC call, instead of making a call for each single item. In addition it allows you to have a single callback to track changes. For queries of the same type we can use `.multi`, for example to retrieve the balances of a number of accounts at once - ```js ... -// subscribe to balance changes for 2 accounts, ADDR1 & ADDR2 (already defined) +// Subscribe to balance changes for 2 accounts, ADDR1 & ADDR2 (already defined) const unsub = await api.query.balances.freeBalance.multi([ADDR1, ADDR2], (balances) => { const [balance1, balance2] = balances; @@ -22,10 +22,10 @@ A couple of items to note in the example above: we don't call `freeBalance` dire ```js ... -// retrieve a snapshot of the validators +// Retrieve a snapshot of the validators const validators = await api.query.session.validators(); -// subscribe to the balances for these accounts +// Subscribe to the balances for these accounts const unsub = await api.query.balances.freeBalance.multi(validators, (balances) => { console.log(`The balances are: ${balances}`); }); @@ -40,7 +40,7 @@ The previous `.multi` examples assumes that we do queries for the same types, i. ```js ... -// subscribe to the timestamp, our index and balance +// Subscribe to the timestamp, our index and balance const unsub = await api.queryMulti([ api.query.timestamp.now, [api.query.system.accountNonce, ADDR], diff --git a/docs/start/api.query.other.md b/docs/start/api.query.other.md index 5a623080d4..d210c790c2 100644 --- a/docs/start/api.query.other.md +++ b/docs/start/api.query.other.md @@ -9,16 +9,16 @@ Quite often is is useful (taking pruning into account, more on this later) to re ```js ... -// retrieve the current block header +// Retrieve the current block header const lastHdr = await api.rpc.chain.getHeader(); -// retrieve the balance at both the current and the parent hashes +// Retrieve the balance at both the current and the parent hashes const [balanceNow, balancePrev] = await Promise.all([ api.query.balances.freeBalance.at(lastHdr.hash, ADDR), api.query.balances.freeBalance.at(lastHdr.parentHash, ADDR) ]); -// display the difference +// Display the difference console.log(`The delta was ${balanceNow.sub(balancePrev)}`); ``` @@ -27,13 +27,13 @@ In the above example, we introduce the `.at([, ...params])` query. For all ```js ... -// retrieve the timestamp for the previous block +// Retrieve the timestamp for the previous block const momentPrev = await api.query.timestamp.now.at(lastHdr.parentHash); ``` The `.at` queries are all single-shot, i.e. there are no subscription option to these, since the state for a previous block should be static. (This is true to a certain extent, i.e. when blocks have been finalized). -An additional point to take care of (briefly mentioned above), is state pruning. By default a Polkadot/Substrate node will only keep state for the last 256 blocks, unless it is explicitly run in archive mode. This means that querying state further back than the pruning period will result in an error returned from the Node. (Generaly most public RPC nodes only run with default settings, which includes agressive state pruning) +An additional point to take care of (briefly mentioned above), is state pruning. By default a Polkadot/Substrate node will only keep state for the last 256 blocks, unless it is explicitly run in archive mode. This means that querying state further back than the pruning period will result in an error returned from the Node. (Generaly most public RPC nodes only run with default settings, which includes aggressive state pruning) ## State entries @@ -42,13 +42,13 @@ In addition to using `api.query` to make actual on-chain queries, it can also be ```js ... -// retrieve the hash & size of the entry as stored on-chain +// Retrieve the hash & size of the entry as stored on-chain const [entryHash, entrySize] = await Promise.all([ api.query.balances.freeBalance.hash(ADDR), api.query.balances.freeBalance.size(ADDR) ]); -// output the info +// Output the info console.log(`The current size is ${entrySize} bytes with a hash of ${entryHash}`); ``` @@ -59,10 +59,10 @@ As per the previous examples, the params here apply explicitly to the actual nee It has been explained that the `api.query` interfaces are decorated from the metadata. This also means that there is some information that we can gather from the entry, as decorated - ```js -// extract the info +// Extract the info const { meta, method, section } = api.query.balances.freeBalance; -// display some info on a specific entry +// Display some info on a specific entry console.log(`${section}.${method}: ${meta.documentation.join(' ')}`); console.log(`query key: ${api.query.balances.freeBalance.key(ADDR)}`); ``` diff --git a/docs/start/api.query.subs.md b/docs/start/api.query.subs.md index 37dcf23194..2f9fc2f205 100644 --- a/docs/start/api.query.subs.md +++ b/docs/start/api.query.subs.md @@ -9,7 +9,7 @@ As in the case with `api.rpc` subscriptions, query subscriptions follow exactly ```js ... -// retrieve the current timestamp via subscription +// Retrieve the current timestamp via subscription const unsub = await api.query.timestamp.now((moment) => { console.log(`The last block has a timestamp of ${moment}`); }); @@ -24,7 +24,7 @@ If we had a query with parameters, i.e. where we wish to perform a query for a s ```js ... -// subscribe to balance changes for our account +// Subscribe to balance changes for our account const unsub = await api.query.balances.freeBalance(ADDR, (balance) => { console.log(`Your account balance is ${balance}`); }); diff --git a/docs/start/api.rpc.md b/docs/start/api.rpc.md index a4053a69fb..76b3f2846f 100644 --- a/docs/start/api.rpc.md +++ b/docs/start/api.rpc.md @@ -7,13 +7,13 @@ Since you are already familiar with the `api.query` interface, the `api.rpc` int ```js ... -// retrieve the chain name +// Retrieve the chain name const chain = await api.rpc.system.chain(); -// retrieve the latest header +// Retrieve the latest header const lastHeader = await api.rpc.chain.getHeader(); -// log the information +// Log the information console.log(`${chain}: last block #${lastHeader.number} has hash ${lastHeader.hash}`); ``` @@ -26,13 +26,13 @@ The RPCs lend themselves to using subscriptions, for instance in the above case ```js ... -// subscribe to the new headers +// Subscribe to the new headers await api.rpc.chain.subscribeNewHeads((lastHeader) => { console.log(`${chain}: last block #${lastHeader.number} has hash ${lastHeader.hash}`); }); ``` -Since we are dealing with a subscription, we now pass a callback into the `subscribeNewHeads` function, and this will be triggered on each header, as they are imported. The same pattern would apply to each of the `api.rpc.subscribe*` functions - as a last parameter a callback is to be provided that streams the latest data, as it becomes available. +Since we are dealing with a subscription, we now pass a callback into the `subscribeNewHeads` function, and this will be triggered on each header, as they are imported. The same pattern would apply to each of the `api.rpc.subscribe*` functions - as a last parameter a callback is to be provided that streams the latest data, as it becomes available. In general, whenever we create a subscription, we would like to cleanup after ourselves and unsubscribe, so assuming we only want to log the first 10 headers, the above example can be adjusted in the following manner - @@ -40,7 +40,7 @@ In general, whenever we create a subscription, we would like to cleanup after ou ... let count = 0; -// subscribe to the new headers +// Subscribe to the new headers const unsubHeads = await api.rpc.chain.subscribeNewHeads((lastHeader) => { console.log(`${chain}: last block #${lastHeader.number} has hash ${lastHeader.hash}`); diff --git a/docs/start/api.tx.md b/docs/start/api.tx.md index 65adb7c1d5..469d7f66ec 100644 --- a/docs/start/api.tx.md +++ b/docs/start/api.tx.md @@ -9,12 +9,12 @@ To start off, let's make a balance transfer from Alice to Bob. ```js ... -// sign and send a transfer from Alice to Bob +// Sign and send a transfer from Alice to Bob const txHash = await api.tx.balances .transfer(BOB, 12345) .signAndSend(alice); -// show the hash +// Show the hash console.log(`Submitted with hash ${txHash}`); ``` @@ -26,7 +26,7 @@ The result for this call (we will deal with subscriptions in a short while), is ## Under the hood -Despite the single-line format of `signAndSend`, there is a lot hapenning under the hood (and all of this can be manually provided) - +Despite the single-line format of `signAndSend`, there is a lot happening under the hood (and all of this can be manually provided) - - Based on the sender, the API will retrieve the `system.accountNonce` to determine the next nonce to use - The API will retrieve the current block hash and use it to create a mortal transaction, i.e. the transaction will only be valid for a limited number of blocks (by default this is 5 mins at 6s blocktimes) diff --git a/docs/start/api.tx.subs.md b/docs/start/api.tx.subs.md index 11db585b34..20a2be3f9c 100644 --- a/docs/start/api.tx.subs.md +++ b/docs/start/api.tx.subs.md @@ -9,10 +9,10 @@ To send a transaction and then waiting until it has been included in a block, we ```js ... -// create alice (carry-over from the keyring section) +// Create alice (carry-over from the keyring section) const alice = keyring.addFromUri('//Alice'); -// make a transfer from Alice to BOB, waiting for inclusion +// Make a transfer from Alice to BOB, waiting for inclusion const unsub = await api.tx.balances .transfer(BOB, 12345) .signAndSend(alice, (result) => { @@ -39,7 +39,7 @@ To display or act on these events, we can do the following - ```js ... -// make a transfer from Alice to BOB, waiting for inclusion +// Make a transfer from Alice to BOB, waiting for inclusion const unsub = await api.tx.balances .transfer(BOB, 12345) .signAndSend(alice, ({ events = [], status }) => { @@ -48,7 +48,7 @@ const unsub = await api.tx.balances if (status.isFinalized) { console.log(`Transaction included at blockHash ${status.asFinalized}`); - // loop through Vec to display all events + // Loop through Vec to display all events events.forEach(({ phase, event: { data, method, section } }) => { console.log(`\t' ${phase}: ${section}.${method}:: ${data}`); }); @@ -58,7 +58,7 @@ const unsub = await api.tx.balances }); ``` -Be aware that when a transaction status is `isFinalized`, it means it is included, but it may still have failed - for instance if you try to send a larger amount that you have free, the transaction is included in a block, however from a end-user perspective the transaction failed since the transfer did not occur. In these cases a `system.ExtrinsicFailed` event will be available in the events array. +Be aware that when a transaction status is `isFinalized`, it means it is included, but it may still have failed - for instance if you try to send a larger amount that you have free, the transaction is included in a block, however from a end-user perspective the transaction failed since the transfer did not occur. In these cases a `system.ExtrinsicFailed` event will be available in the events array. ## Complex transactions diff --git a/docs/start/api.tx.wrap.md b/docs/start/api.tx.wrap.md index 54d92e5616..d69a5a8781 100644 --- a/docs/start/api.tx.wrap.md +++ b/docs/start/api.tx.wrap.md @@ -8,13 +8,13 @@ When running a development chain (Polkadot/Substrate with a `--dev` flag), or in ```js ... -// get the current sudo key in the system +// Get the current sudo key in the system const sudoKey = await api.query.sudo.key(); -// lookup from keyring (assuming we have added all, on --dev this would be `//Alice`) +// Lookup from keyring (assuming we have added all, on --dev this would be `//Alice`) const sudoPair = keyring.getPair(sudoKey); -// send the actual sudo transaction +// Send the actual sudo transaction const unsub = await api.tx.sudo .sudo( api.tx.balances.setBalance(ADDR, 12345, 678) @@ -41,4 +41,4 @@ In the above example, all we need to provide is a the fields for the `ValidatorP ## Understanding types -As has been very apparent in all the preceding sections, the management of types is what allows the API to communicate with the node. Most values are in a [binary SCALE-encoded format](https://github.com/paritytech/parity-scale-codec) and it is the reponsibility of the API is to encode and decode these. In the next section we will [take a look at what interfaces the API provides around types](types.basics.md). +As has been very apparent in all the preceding sections, the management of types is what allows the API to communicate with the node. Most values are in a [binary SCALE-encoded format](https://github.com/paritytech/parity-scale-codec) and it is the reponsibility of the API is to encode and decode these. In the next section we will [take a look at what interfaces the API provides around types](types.basics.md). diff --git a/docs/start/basics.md b/docs/start/basics.md index 2cad06d37c..b94274eea6 100644 --- a/docs/start/basics.md +++ b/docs/start/basics.md @@ -27,7 +27,7 @@ In addition to the `api.[consts | query | tx]` detailed above, the API, upon con - `api.genesisHash` - The genesisHash of the connected chain - `api.runtimeMetadata` - The metadata as retrieved from the chain - `api.runtimeVersion` - The chain runtime version (including spec/impl. versions and types) -- `api.libraryInfo` - The version of the API, i.e. `@polkadot/api v0.90.1` +- `api.libraryInfo` - The version of the API, i.e. `@polkadot/api v0.90.1` ## Let's do something! diff --git a/docs/start/create.md b/docs/start/create.md index 11f494f4d7..3688c0790e 100644 --- a/docs/start/create.md +++ b/docs/start/create.md @@ -3,15 +3,15 @@ We have the API installed, we have an understanding of what will actually be exposed and how the API knows what to expose. So down the rabbit hole we go - let's create an actual API instance, and then take it from there - ```js -// import +// Import import { ApiPromise, WsProvider } from '@polkadot/api'; ... -// construct +// Construct const wsProvider = new WsProvider('wss://poc-3.polkadot.io'); const api = await ApiPromise.create({ provider: wsProvider }); -// do something +// Do something console.log(api.genesisHash.toHex()); ``` @@ -21,12 +21,12 @@ We will have some explanation on the ES2015 syntax used next, but just a small n Before we jump into an explanation of the above example, be aware that in all cases we are using ES2015, including using things like `async`/`await`, `import` and others. Depending on your environment, this may require some adjustments. -While we are using the `await` naked in all examples (this removes boilerplate), it will need to be wrapped in an `async` block, for we could warp all samples inside a `async function main () { ... }` and then just call `main()`. +While we are using the `await` naked in all examples (this removes boilerplate), it will need to be wrapped in an `async` block, for we could warp all samples inside a `async function main () { ... }` and then just call `main()`. In the case of Node.js you would change the `import` into `require`, i.e. ```js -// import +// Import const { ApiPromise, WsProvider } = require('@polkadot/api'); ... ``` @@ -58,13 +58,13 @@ ApiPromise In most cases we would suggest using the `.create` shortcut, which really just takes care of the following boilerplate that otherwise needs to be provided - ```js -// create the instance +// Create the instance const api = new ApiPromise({ provider: wsProvider }); -// wait until we are ready and connected +// Wait until we are ready and connected await api.isReady; -// do something +// Do something console.log(api.genesisHash.toHex()); ``` @@ -76,4 +76,4 @@ In these cases, create via `new`, attach listeners and then wait for the `isRead ## Do something -Now that we have the API initialized, the next step would be to start using it to interact and extract data [starting with chain constants](api.consts.md). +Now that we have the API initialized, the next step would be to start using it to interact and extract data [starting with chain constants](api.consts.md). diff --git a/docs/start/keyring.md b/docs/start/keyring.md index cabe816f96..3525b1658e 100644 --- a/docs/start/keyring.md +++ b/docs/start/keyring.md @@ -13,13 +13,13 @@ If you do opt to install it seperately, ensure that the version of `@polkadot/ut Once installed, you can create an instance by just creating an instance of the `Keyring` class - ```js -// import the keyring as required +// Import the keyring as required import { Keyring } from '@polkadot/api'; -// initialize the API as we would normally do +// Initialize the API as we would normally do ... -// create a keyring instance +// Create a keyring instance const keyring = new Keyring({ type: 'sr25519' }); ``` @@ -27,18 +27,18 @@ In the above example, the import is self-explanatory. Upon creation we pass thro So effectively, when creating an account and not specifying a type, it will be `sr25519` by default based on the above construction params, however we can also add an `ed25519` account and use it transparently in the same keyring. -One "trick" that is done implictly in the above sample is that that keyring is only initialized after the API. In the case of `sr25519` the keyring relies on a [WASM build](https://github.com/polkadot-js/wasm) of the [schnorrkel libraries](https://github.com/w3f/schnorrkel). Since the API inlitialization is already async, it initializes the WASM libraries are part of the setup. +One "trick" that is done implictly in the above sample is that that keyring is only initialized after the API. In the case of `sr25519` the keyring relies on a [WASM build](https://github.com/polkadot-js/wasm) of the [schnorrkel libraries](https://github.com/w3f/schnorrkel). Since the API inlitialization is already async, it initializes the WASM libraries are part of the setup. However, this initialization can also be done explicitly, mostly for more advances use-cases, or in cases where the API won't be attached until much later - ```js -// crypto promise, package used by keyring internally +// Crypto promise, package used by keyring internally import { cryptoWaitReady } from '@polkadot/util-crypto'; -// wait for the promise to resolve, async WASM or `cryptoWaitReady().then(() => { ... })` +// Wait for the promise to resolve, async WASM or `cryptoWaitReady().then(() => { ... })` await cryptoWaitReady(); -// create a keyring instance +// Create a keyring instance const keyring = new Keyring({ type: 'sr25519' }); ``` @@ -49,16 +49,16 @@ The recommended catch-all approach to adding accounts is via `.addFromUri( ```js ... -// some mnemonic phrase +// Some mnemonic phrase const PHRASE = 'entire material egg meadow latin bargain dutch coral blood melt acoustic thought'; -// add an account, straight menemonic +// Add an account, straight menemonic const newPair = keyring.addFromUri(PHRASE); -// (advanced) add an account with a derivation path (hard & soft) +// (Advanced) add an account with a derivation path (hard & soft) const newDeri = keyring.addFromUri(`${PHRASE}//hard-derived/soft-derived`); -// (advanced, development-only) add with an implied dev seed and hard derivation +// (Advanced, development-only) add with an implied dev seed and hard derivation const alice = keyring.addFromUri('//Alice', { name: 'Alice default' }); ``` @@ -71,27 +71,27 @@ In the previous examples we added a pair to the keyring (and we actually immedia ```js ... -// add our Alice dev account +// Add our Alice dev account const alice = keyring.addFromUri('//Alice', { name: 'Alice default' }); -// log some info +// Log some info console.log(`${alice.meta.name}: has address ${alice.address} with publicKey [${alice.publicKey}]`); ``` Additionally you can sign and verify using the pairs. This is the same internally to the API when constructing transactions - ```js -// some helper functions used here +// Some helper functions used here import { stringToU8a, u8aToHex } from '@polkadot/util'; ... -// convert message, sign and then verify +// Convert message, sign and then verify const message = stringToU8a('this is our message'); const signature = alice.sign(message); const isValid = alice.verify(message, signature); -// log info +// Log info console.log(`The signature ${u8aToHex(signature)}, is ${isValid ? '' : 'in'}valid`); ``` diff --git a/docs/start/types.basics.md b/docs/start/types.basics.md index 298e74ec45..566382b878 100644 --- a/docs/start/types.basics.md +++ b/docs/start/types.basics.md @@ -19,9 +19,26 @@ Additionally, the following getters and utilities are available - - `.isEmpty` - `true` if the value is an all-empy value, i.e. `0` in for numbers, all-zero for Arrays (or anything `Uint8Array`), `false` is non-zero - `.hash` - a `Hash` (once again with all the methods above) that is a `blake2-256` representation of the contained value +## Comparing types + +To reiterate the above API, the `.eq` method is the preferred means of comparing base types, rather than the JavaScript equality operator (`===`). + +For example: + +```js +const { metadata } = await api.rpc.state.getMetadata(); +const modules = metadata.asV3.modules; + +// This will not work, because `name` is an instance of `Text`, not a string +// const system = modules.find(m => m.name === 'system'); + +// This will work, because `Text.eq()` can compare against a string +const system = modules.find(m => m.name.eq('system')); +``` + ## Working with numbers -All numbers wrap and extend an instance of [bn.js](https://github.com/indutny/bn.js/). This means that in addition to the interfaces defined above, they have some additional methods - +All numbers wrap and extend an instance of [bn.js](https://github.com/indutny/bn.js/). This means that in addition to the interfaces defined above, they have some additional methods - - `.toNumber()` - a JS number (limited to 2^53 - 1). This does mean that for large values, e.g. `Balance` (a `u128` extension), this can cause overflows - `.add(...)`, `.sub(...)`, ... - all the base methods available on the `BN` object @@ -30,7 +47,7 @@ In cases where a `Compact` is returned, i.e. `Compact`, the value is wr ## Working with structures -All structures, a wrapping of an object containing a number of member variables, is an implementation of a standard JS `Map` object, so all the functions available on a `Map` such as `.entries()` are available. Additionally it is decorated with actual getters for the fields. +All structures, a wrapping of an object containing a number of member variables, is an implementation of a standard JS `Map` object, so all the functions available on a `Map` such as `.entries()` are available. Additionally it is decorated with actual getters for the fields. As an example, a `Header` will have getters for the `.parentHash`, `.number`, `.stateRoot`, `.extrinsicsRoot` and `.digest` fields. The same applies for all structures, as they are returned, each member will have an associated getter. @@ -48,7 +65,7 @@ An `Option` attempts to mimic the Rust approach of having `None` and `Some - `.isNone` - is `true` if no underlying values is warpped, effectively the same as `.isEmpty` - `.isSome` - this is `true` is a value is wrapped, i.e. if a `Option` has an actual underlying `u32` -- `.unwrap()` - when `isSome`, this will return the wrapped value, i.e. for `Option`, this would return the `u32`. When the value is `isNone`, this call will throw an exception. +- `.unwrap()` - when `isSome`, this will return the wrapped value, i.e. for `Option`, this would return the `u32`. When the value is `isNone`, this call will throw an exception. - `.unwrapOr()` - this extends `unwrap()`, returning the wrapped value when `isSome` and in the case of `isNone` it will return the `` passed. ## Working with Tuples @@ -56,7 +73,7 @@ An `Option` attempts to mimic the Rust approach of having `None` and `Some A tuple is defined in the form of `(u32, AccountId)`. To access the individual values, you can access t via the index, i.e. ```js -// assuming a tuple defined as `(32, AccountId)` +// Assuming a tuple defined as `(32, AccountId)` const [count, accountId] = tuple; console.log(`${accountId} has ${count.toNumber()} values`); diff --git a/docs/start/types.extend.md b/docs/start/types.extend.md index 6609acfd20..1baa38bbb5 100644 --- a/docs/start/types.extend.md +++ b/docs/start/types.extend.md @@ -6,7 +6,7 @@ Therefore to cater for all types, a mapping in done on the [@polkadot/types libr Additionally, the API contains some logic for chain type detection, for instance in the case of Substrate 1.x based chains, it will define `BlockNumber` & `Index` (nonce) as a `u64`, while for current-generation chains, these will be defined as `u32`. Some of the work in maintaining the API for Polkadot/Substrate is the addition of types as they appear and gets used in the Rust codebases. -There is a the [recommentation](install.md#betas) to use a `@polkadot/api@beta` should you wish to track the master branches of Polkadot or Substrate, since master changes for the addition of new types do not make it into a stable release immediately. +There is a the [recommendation](install.md#betas) to use a `@polkadot/api@beta` should you wish to track the master branches of Polkadot or Substrate, since master changes for the addition of new types do not make it into a stable release immediately. ## Extension @@ -24,7 +24,7 @@ const api = await ApiPromise.create({ }); ``` -The above introduces the `types` registry, effectively allowing overrides and the definition of new types. The override above would mean that immediately the API will treat all occurences of `Balance` not as the default, but rather as the defined size. +The above introduces the `types` registry, effectively allowing overrides and the definition of new types. The override above would mean that immediately the API will treat all occurences of `Balance` not as the default, but rather as the defined size. ## User-defined types @@ -102,7 +102,7 @@ const api = await ApiPromise.create({ }); ``` -In the same way `typesChain` can be used to match on the actual chain name, i.e. for a chain such as Kusama, the following overrides can be made (as per example only - Kusama uses the Polkadot defaults, so no overrides are needed) - +In the same way `typesChain` can be used to match on the actual chain name, i.e. for a chain such as Kusama, the following overrides can be made (as per example only - Kusama uses the Polkadot defaults, so no overrides are needed) - ```js ... @@ -139,4 +139,4 @@ const api = await ApiPromise.create({ ## Using with TypeScript -The API is built with TypeScript (as are all projects in the [polkadot-js organization](https://github.com/polkadot-js/)) and as such allows developers using TS to have access to all the type interfaces defined on the chain, as well as having access to typings on interacting with the `api.*` namespaces. In the next section we will provide an overview of [what is available in terms of types and TypeScript](typescript.md). +The API is built with TypeScript (as are all projects in the [polkadot-js organization](https://github.com/polkadot-js/)) and as such allows developers using TS to have access to all the type interfaces defined on the chain, as well as having access to typings on interacting with the `api.*` namespaces. In the next section we will provide an overview of [what is available in terms of types and TypeScript](typescript.md). diff --git a/docs/start/typescript.md b/docs/start/typescript.md index c5fdda63fc..c461205974 100644 --- a/docs/start/typescript.md +++ b/docs/start/typescript.md @@ -1,6 +1,6 @@ # TypeScript interfaces -The API is written in TypeScript, and as such definitions for all actual exposed interfaces are available. In general terms, care has been taken to expose types via a `@polkadot//types` interface, for instance the `ApiOptions` type which is passed through on the `.create` interface is available under `@polkadot/api/types`. +The API is written in TypeScript, and as such definitions for all actual exposed interfaces are available. In general terms, care has been taken to expose types via a `@polkadot//types` interface, for instance the `ApiOptions` type which is passed through on the `.create` interface is available under `@polkadot/api/types`. ## RPC interfaces @@ -19,7 +19,7 @@ api.rpc.chain.subscribeNewHeads((lastHead: Header): void => { In the above example a couple of things are introduced - most of the chain definitions (the default types for both Polkadot & Substrate) can be imported as interfaces from the `@polkadot/types/interfaces` endpoint. These are not classes (since they are [generated from definitions](https://github.com/polkadot-js/api/tree/master/packages/types/src/interfaces)) but rather a combination of TypeScript `interfaces` (where structures are involved) and `type`, i.e. `type Balance = u128`. -In the subscription example, we explicitly define `lastHead: Header`, although the same definition is missing for `firstHead`. However, in both these cases the definitions for the `api.rpc` sections are such that TypeScript understands that `firstHead` and `lastHead` are of type `Header`. The `: Header` here is rather for our own understanding (and could be needed based on your eslint/tslint config). +In the subscription example, we explicitly define `lastHead: Header`, although the same definition is missing for `firstHead`. However, in both these cases the definitions for the `api.rpc` sections are such that TypeScript understands that `firstHead` and `lastHead` are of type `Header`. The `: Header` here is rather for our own understanding (and could be needed based on your eslint/tslint config). As indicated, most of the Polkadot/Substrate default types are available via `types/interfaces`. However, for primitives types where there is an actual implementation, these are made available via `@polkadot/types` directly. For instance, `import { u32 } from '@polkadot/types` is valid in this context. @@ -46,11 +46,11 @@ As of this writing, there are still some gray areas to type detection, specifica - `.at` & `.multi` on `api.query` does not (yet) have a `` interface. This means `as ` casts are presently needed for these results - `api.queryMulti` does not (yet) allow you to provide a hint to the types returned, this ties to the previous point -In additiont to expanding the type covereage, we wish to make the actual generation script for the types from `@polkadot/types/interfaces` available in 2 ways - +In addition to expanding the type coverage, we wish to make the actual generation script for the types from `@polkadot/types/interfaces` available in 2 ways - - allowing you to point to a folder of types and auto-generate the TypeScript typings from those. (Which is akin to what we do internally). This would allow a reduction in type classes explicitly written and injected. - once the metadata itself supports full type definitions, the script can be used to generate interface definitions specifically tailored for a chain -## And it is a wrap +## And that's a wrap This brings us to the end of our overview and jump through the API. While the documentation is still very much and ever evolving item, we can encourage you to try out what you have learned with some [examples](../examples). As we [indicated right at the start of this journey](README.md#help-us-help-others), if there are areas for improvement, let us know. diff --git a/packages/types/src/scripts/MetadataMd.ts b/packages/types/src/scripts/MetadataMd.ts index 2500fe338d..b9d6f93f67 100644 --- a/packages/types/src/scripts/MetadataMd.ts +++ b/packages/types/src/scripts/MetadataMd.ts @@ -90,7 +90,8 @@ function addConstants (metadata: MetadataV7): string { return orderedConstants.reduce((md, func): string => { const methodName = stringCamelCase(func.name.toString()); - const doc = func.documentation.reduce((md, doc): string => `${md} ${doc}`, ''); + const doc = func.documentation + .reduce((md, doc): string => `${md.length ? `${md} ` : ''}${doc.trim()}`, ''); const type = func.type; const renderSignature = `${md}\n▸ **${methodName}**: ` + '`' + type + '`'; const renderSummary = `${doc ? `\n- **summary**: ${doc}\n` : '\n'}`; @@ -122,7 +123,9 @@ function addEvents (metadata: MetadataV7): string { return orderedMethods.reduce((md, func): string => { const methodName = func.name.toString(); const args = func.args.map((type): string => '`' + type + '`').join(', '); - const doc = func.documentation.reduce((md, doc): string => `${md} ${doc}`, ''); + const doc = func.documentation + .reduce((md, doc): string => `${md.length ? `${md} ` : ''}${doc.trim()}`, ''); + const renderSignature = `${md}\n▸ **${methodName}**(${args})`; const renderSummary = `${doc ? `\n- **summary**: ${doc}\n` : '\n'}`; @@ -153,7 +156,8 @@ function addExtrinsics (metadata: MetadataV7): string { return orderedMethods.reduce((md, func): string => { const methodName = stringCamelCase(func.name.toString()); const args = Call.filterOrigin(func).map(({ name, type }): string => `${name}: ` + '`' + type + '`').join(', '); - const doc = func.documentation.reduce((md, doc): string => `${md} ${doc}`, ''); + const doc = func.documentation + .reduce((md, doc): string => `${md.length ? `${md} ` : ''}${doc.trim()}`, ''); const renderSignature = `${md}\n▸ **${methodName}**(${args})`; const renderSummary = `${doc ? `\n- **summary**: ${doc}\n` : '\n'}`; @@ -187,7 +191,8 @@ function addStorage (metadata: MetadataV7): string { : func.type.isDoubleMap ? ('`' + func.type.asDoubleMap.key1.toString() + ', ' + func.type.asDoubleMap.key2.toString() + '`') : ''; - const doc = func.documentation.reduce((md, doc): string => `${md} ${doc}`, ''); + const doc = func.documentation + .reduce((md, doc): string => `${md.length ? `${md} ` : ''}${doc.trim()}`, ''); let result = ( func.type.isDoubleMap ? func.type.asDoubleMap.value