Compare commits

...
62 Commits
Author SHA1 Message Date
Github Actions 0f08031792 [CI Skip] 1.10.1
skip-checks: true
2020-04-13 05:28:25 +00:00
Jaco Greeff e0bde927d1 1.10 (#2158)
* 1.10

* CHANGELOG

* key extract example
2020-04-13 07:16:43 +02:00
Github Actions e569de520a [CI Skip] 1.10.0-beta.29
skip-checks: true
2020-04-11 20:32:39 +00:00
Jaco Greeff a833dccdaf All private prefixed with _ (#2157)
* All private prefixed with _

* Fix test
2020-04-11 22:21:55 +02:00
Github Actions b58d772156 [CI Skip] 1.10.0-beta.28
skip-checks: true
2020-04-10 16:17:30 +00:00
Jaco Greeff e5d9bbc264 Filter old rewards with stakingLedger (ledger can update) (#2155)
* Filter old rewards with stakingLedger (ledger can update)

* Cleanup internal functions
2020-04-10 18:06:14 +02:00
Github Actions 3089529405 [CI Skip] 1.10.0-beta.27
skip-checks: true
2020-04-10 12:41:15 +00:00
Jaco Greeff 5ab24390c5 Indicate all protected members and variables (#2154)
* Indicate all protected members and variables

* Added dropped protected
2020-04-10 14:29:58 +02:00
Github Actions 245047a41f [CI Skip] 1.10.0-beta.26
skip-checks: true
2020-04-10 12:04:49 +00:00
Jaco Greeff 8aa1bd5bd0 Indicate protected raw with _raw in Base codec (#2153) 2020-04-10 13:54:15 +02:00
Github Actions e0dde35621 [CI Skip] 1.10.0-beta.25
skip-checks: true
2020-04-10 10:23:42 +00:00
Jaco Greeff 9ba91a3851 Use forkJoin for entries() retrieval (#2152)
* Use forkJoin for entries() retrieval

* Some current and validator retrieval opts

* Remove duplicate filtering
2020-04-10 12:12:10 +02:00
Github Actions 351cb97667 [CI Skip] 1.10.0-beta.24
skip-checks: true
2020-04-09 16:44:08 +00:00
Jaco Greeff afdb476796 Small cleanups & consistency (#2151)
* Small cleanups & consistency

* Fixes
2020-04-09 18:32:30 +02:00
Github Actions 3b67b65091 [CI Skip] 1.10.0-beta.23
skip-checks: true
2020-04-09 13:55:22 +00:00
Jaco Greeff 25580b2026 Update CHANGELOG, bump deps (#2150) 2020-04-09 15:44:07 +02:00
Github Actions 2db16e94b7 [CI Skip] 1.10.0-beta.22
skip-checks: true
2020-04-09 12:57:00 +00:00
Jaco Greeff 9184268c3d Bump metadata (#2148)
* Bump metadata

* Adjust to non-customized democracy params
2020-04-09 14:46:48 +02:00
Github Actions 83a762af1e [CI Skip] 1.10.0-beta.21
skip-checks: true
2020-04-09 12:39:49 +00:00
Jaco Greeff 6a8e5370b6 Add system_chainType RPC (#2149) 2020-04-09 14:28:43 +02:00
Github Actions 9cd4bf7cf7 [CI Skip] 1.10.0-beta.20
skip-checks: true
2020-04-09 07:31:24 +00:00
Jaco Greeff c4708dcfca Cleanup isPassing (#2147) 2020-04-09 09:19:56 +02:00
Github Actions 041d06a6c8 [CI Skip] 1.10.0-beta.19
skip-checks: true
2020-04-08 19:58:30 +00:00
Jaco Greeff 2b4bd75499 Adjust calc with turnout add/sub 2020-04-08 21:47:22 +02:00
Github Actions c4c47a84e1 [CI Skip] 1.10.0-beta.18
skip-checks: true
2020-04-08 15:36:45 +00:00
Jaco Greeff a241bd1c38 Adjust change calc (#2145) 2020-04-08 17:23:59 +02:00
Github Actions d420cede82 [CI Skip] 1.10.0-beta.17
skip-checks: true
2020-04-08 14:04:37 +00:00
Jaco Greeff b869695e40 Bump util (#2144) 2020-04-08 15:55:04 +02:00
Github Actions 37caf4e710 [CI Skip] 1.10.0-beta.16
skip-checks: true
2020-04-07 19:23:34 +00:00
Jaco Greeff 134bc22463 Westend (spec) 2020-04-07 21:11:37 +02:00
Github Actions 39d142876e [CI Skip] 1.10.0-beta.15
skip-checks: true
2020-04-07 18:42:57 +00:00
Jaco Greeff 6d95eb418d Westend (again) 2020-04-07 20:31:16 +02:00
Github Actions e26a6a28ff [CI Skip] 1.10.0-beta.14
skip-checks: true
2020-04-07 18:10:26 +00:00
Jaco Greeff d80d6f2a06 Westend update (#2143) 2020-04-07 19:59:08 +02:00
Github Actions ff8dabb249 [CI Skip] 1.10.0-beta.13
skip-checks: true
2020-04-07 09:30:13 +00:00
Jaco Greeff e7a01f9780 Dump dev (incl. eslint header checks) (#2142) 2020-04-07 11:20:07 +02:00
Github Actions 94938c7075 [CI Skip] 1.10.0-beta.12
skip-checks: true
2020-04-06 10:43:28 +00:00
Jaco Greeff f37e729605 Use bumbled node (#2141) 2020-04-06 12:32:05 +02:00
Github Actions 9cfde73ff8 [CI Skip] 1.10.0-beta.11
skip-checks: true
2020-04-05 10:23:01 +00:00
Jaco Greeff f5c140d1c2 Split derive.staking.currentPoints from overview (#2140) 2020-04-05 12:12:03 +02:00
Github Actions 472e1022d3 [CI Skip] 1.10.0-beta.10
skip-checks: true
2020-04-05 08:15:44 +00:00
Jaco Greeff f71211f5dc Bump deps (#2139) 2020-04-05 10:05:50 +02:00
Github Actions 7e06974f1b [CI Skip] 1.10.0-beta.9
skip-checks: true
2020-04-04 17:16:19 +00:00
Jaco Greeff f95384d9ff Bump deps (#2138)
* Bump deps

* Add lockfile :)
2020-04-04 19:04:42 +02:00
Github Actions baedd5b689 [CI Skip] 1.10.0-beta.8
skip-checks: true
2020-04-04 16:36:28 +00:00
Jaco Greeff 9ec1cb194a Update StakingLedger (simpl payouts) (#2102)
* Update StakingLedger (simpl payouts)

* Chain defs

* Allow stakers queries with exclude filter

* Generate interfaces

* Return all exposures

* Rework exposures

* Cleanups
2020-04-04 18:25:32 +02:00
Github Actions d730310ea5 [CI Skip] 1.10.0-beta.7
skip-checks: true
2020-04-03 12:58:06 +00:00
Jaco Greeff 641fe5c380 Refresh on scheduler entries (#2135)
* Refresh on scheduler entries

* Cleanups
2020-04-03 14:47:39 +02:00
Github Actions c5a8d5e018 [CI Skip] 1.10.0-beta.6
skip-checks: true
2020-04-03 11:40:23 +00:00
Jaco Greeff 02d130f0a0 Add Mandatory to DispatchClass (#2134) 2020-04-03 13:29:07 +02:00
Github Actions 5554f17f05 [CI Skip] 1.10.0-beta.5
skip-checks: true
2020-04-02 18:55:29 +00:00
Jaco Greeff 69351ceb9e Cater for new dispatch scheduler (#2130)
* Cater for new dispatch scheduler

* Updated

* debug logs

* Update types.ts
2020-04-02 20:44:27 +02:00
Github Actions 0cf9fa7405 [CI Skip] 1.10.0-beta.4
skip-checks: true
2020-04-02 14:27:07 +00:00
Jaco Greeff 8213fa7cb9 Add validator total to staker rewards (#2129)
* Add validator total to staker rewards

* yarn rewrite
2020-04-02 16:16:10 +02:00
Github Actions 8ef983169f [CI Skip] 1.10.0-beta.3
skip-checks: true
2020-04-02 09:24:58 +00:00
Jaco Greeff e392dd745e Base centrifuge types (#2125) 2020-04-02 11:15:28 +02:00
Github Actions 6b07a9c2a5 [CI Skip] 1.10.0-beta.2
skip-checks: true
2020-04-02 07:46:55 +00:00
Jaco Greeff 114ac59707 Reword FAQ 2020-04-02 09:35:16 +02:00
Github Actions 3c95bfe56e [CI Skip] 1.10.0-beta.1
skip-checks: true
2020-04-01 22:00:58 +00:00
Jaco Greeff 58de0b8b9c Rewrite yarn.lock (#2127) 2020-04-01 23:49:56 +02:00
Github Actions 1f97c5e9e3 [CI Skip] 1.10.0-beta.0
skip-checks: true
2020-04-01 20:54:58 +00:00
Jaco Greeff 0dc46445bc Bump dev (incl. lint fixes) (#2126)
* Bump dev (incl. lint fixes)

* Fix call encoding (stepped into that one)

* Event struct order

* Update with missing tuple type (getTypeDef type)
2020-04-01 22:44:34 +02:00
258 changed files with 3113 additions and 2084 deletions
-3
View File
@@ -10,9 +10,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: '12.x'
- name: ${{ matrix.step }}
run: |
yarn install --immutable | grep -v 'YN0013'
-3
View File
@@ -16,9 +16,6 @@ jobs:
- uses: actions/checkout@v1
with:
token: ${{ secrets.GH_PAT }}
- uses: actions/setup-node@v1
with:
node-version: '12.x'
- name: ${{ matrix.step }}
env:
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
+15 -2
View File
@@ -1,7 +1,20 @@
# 1.10.1 Apr 13, 2020
- **Important** Substrate master has updated staking, on older chains apply `StakingLedger: 'StakingLedgerTo240'`
- Add `rpc.system.chainType` to retrieve the chain type (Development. Local, Live & Custom)
- Adjust types for Westend after the reset
- Adjust democracy derives, including the support of the frame-scheduler for scheduled deployments
- Allow staking derives to work with new staking payouts, specifically `tx.staking.payoutStakers`
- Cleanups to derives for democracy & staking to be more performant
- Add Centrifuge base types to `@polkadot/types-known`
- Adjust with all the latest substrate master types
- Internally all private/protected methods/variables are now `_` prefixed (Aligning with the `private/protected` indicators in the TS definitions)
- Update metadata/docs-from-metadata to the latest Substrate
# 1.9.1 Apr 1, 2020
**Breaking change** (TypeScript with derives only) The return type names for `api.derive.*` have been adjusted for consistency, all starting with `Derive*` (previously a mixture of `Derived*` and `Derive*`)
**Breaking change** (derives only) Additional cleanups of democracy proposal & referenda derives, including support for new Polkadot/Substrate vote retrievals
- **Breaking change** (TypeScript with derives only) The return type names for `api.derive.*` have been adjusted for consistency, all starting with `Derive*` (previously a mixture of `Derived*` and `Derive*`)
- **Breaking change** (derives only) Additional cleanups of democracy proposal & referenda derives, including support for new Polkadot/Substrate vote retrievals
- Tx signing via `signAndSend` & `signAsync` now tries to use the last finalized block (depending on finalized drift)
- Add support for `api.rpc.childstate.*` Substrate RPCs, older nodes with still populate `api.rpc.state.*` with the child methods
- Adjust `Error.message` on RPC failures to not include the (already known) method signature
+4
View File
@@ -1 +1,5 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
module.exports = require('@polkadot/dev/config/babel');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Required imports
const { ApiPromise, WsProvider } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API
const { ApiPromise } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API
const { ApiPromise } = require('@polkadot/api');
@@ -13,13 +14,13 @@ async function main () {
// Retrieve the initial balance. Since the call has no callback, it is simply a promise
// that resolves to the current on-chain value
let { nonce: previousNonce, data: { free: previousFree } } = await api.query.system.account(Alice);
let { data: { free: previousFree }, nonce: previousNonce } = await api.query.system.account(Alice);
console.log(`${Alice} has a balance of ${previousFree}, nonce ${previousNonce}`);
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
api.query.system.account(Alice, ({ nonce: currentNonce, data: { free: currentFree } }) => {
api.query.system.account(Alice, ({ data: { free: currentFree }, nonce: currentNonce }) => {
// Calculate the delta
const change = currentFree.sub(previousFree);
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API
const { ApiPromise } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API
const { ApiPromise } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API
const { ApiPromise } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API
const { ApiPromise } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API, Keyring and some utility functions
const { ApiPromise } = require('@polkadot/api');
const { Keyring } = require('@polkadot/keyring');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API, Keyring and some utility functions
const { ApiPromise } = require('@polkadot/api');
const { Keyring } = require('@polkadot/keyring');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API
const { ApiPromise } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API & Provider and some utility functions
const { ApiPromise } = require('@polkadot/api');
@@ -44,7 +45,7 @@ async function main () {
console.log('Included at block hash', status.asInBlock.toHex());
console.log('Events:');
events.forEach(({ phase, event: { data, method, section } }) => {
events.forEach(({ event: { data, method, section }, phase }) => {
console.log('\t', phase.toString(), `: ${section}.${method}`, data.toString());
});
} else if (status.isFinalized) {
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API & Provider and some utility functions
const { ApiPromise, WsProvider } = require('@polkadot/api');
+2 -1
View File
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Required imports
const { zip } = require('rxjs');
const { ApiRx } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API
const { ApiRx } = require('@polkadot/api');
const { switchMap } = require('rxjs/operators');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API and operators from RxJs
const { ApiRx } = require('@polkadot/api');
const { pairwise, startWith } = require('rxjs/operators');
@@ -27,6 +28,7 @@ async function main () {
// then balance[1] is the initial value of Alice account.
console.log(`Alice ${Alice} has a balance of ${balance[1].data.free}`);
console.log('You may leave this example running and start the "Make a transfer" example or transfer any value to Alice address');
return;
}
+2 -1
View File
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API
const { ApiRx } = require('@polkadot/api');
const { switchMap } = require('rxjs/operators');
+2 -1
View File
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API
const { ApiRx } = require('@polkadot/api');
const { combineLatest, of } = require('rxjs');
+3 -1
View File
@@ -1,6 +1,8 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API, Keyring and some utility functions
const { ApiRx } = require('@polkadot/api');
const { Keyring } = require('@polkadot/keyring');
+2 -1
View File
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API and selected RxJs operators
const { switchMap } = require('rxjs/operators');
const { ApiRx } = require('@polkadot/api');
+3 -2
View File
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API and some utility functions
const { ApiRx } = require('@polkadot/api');
@@ -48,7 +49,7 @@ async function main () {
console.log('Included at block hash', status.asInBlock.toHex());
console.log('Events:');
events.forEach(({ phase, event: { data, method, section } }) => {
events.forEach(({ event: { data, method, section }, phase }) => {
console.log('\t', phase.toString(), `: ${section}.${method}`, data.toString());
});
} else if (status.isFinalized) {
+2 -1
View File
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* 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)
+3 -3
View File
@@ -52,8 +52,8 @@ Likewise, if your chain has been upgraded recently and you are still using the o
## I cannot send transactions from my node-template-based chain
For the API defaults, the API always the type definitions as specified by the Substrate master fully-featured node. This means that any customizations needs to be applied as types should there be differences in specific user-implementations.
The API always injects the default type definitions as specified by the Substrate master fully-featured node. This means that any customizations to chains needs needs to be applied as types, should there be differences in specific user-implementations.
The Substrate node-template has added customizations for some types in the default template, specifically around the `Address` and `Lookup` types, removing indices lookups from addresses. This means that the transaction payload saves 2 bytes for a transfer and is an approach followed by other chains as well, notably Polkadot & Kusama.
The Substrate node-template has added customizations for some types in the default template, specifically around the `Address` and `Lookup` types, removing any lookups based on indices. This means that the transaction payload saves 2 bytes for a transfer and is an approach followed by other chains as well, notably Polkadot & Kusama.
Due to these customizations and differences that bleed through to the transaction formats, out-of-the-box the node-template will have issues when sending transactions. To fix this, you would need to add [the customized Address types into your API](types.extend.md#impact-on-extrinsics) instances (or UIs), allowing the API to have the information required to adjust the encoding.
Due to these customizations and differences that bleed through to the transaction formats, out-of-the-box chains based on the node-template will have issues when sending transactions. To fix this, you would need to add [the customized Address types into your API](types.extend.md#impact-on-extrinsics) instances (or UIs), allowing the API to have the information required to adjust the encoding.
+12 -2
View File
@@ -62,7 +62,7 @@ When working maps and double-maps, it is possible to retrieve a list of all the
// Retrieve the active era
const activeEra = await api.query.staking.activeEra();
// retrieve all exposures int the active era
// retrieve all exposures for the active era
const exposures = await api.query.staking.erasStakers.entries(activeEra.index);
exposures.forEach(([key, exposure]) => {
@@ -73,7 +73,17 @@ exposures.forEach(([key, exposure]) => {
Here we are querying a double-map, so we supply 1 argument. No arguments on double-maps will be very costly, retrieving all the eras and associated entries. Additionally when `twox64_concat` & `blake2_concat` is used, the key `.args` will contain decoded values of the params, in this case it will contain the actual `AccountId` of the staker. (Since that was not supplied)
In the same way as above we can simply do `.keys(activeEra.index): StorageKey[]` to retrieve all the keys here, including the individual keys args decoding, as available on maps with decodable hashing functions.
In the same way as above we can simply do `.keys(activeEra.index): StorageKey[]` to retrieve all the keys here, including the individual keys args (available on maps with decodable hashing functions) -
```js
// retrieve all the nominator keys
const keys = await api.query.staking.nominators.keys();
// extract the first key argument (AccountId) as string
const nominatorIds = keys.map((key) => key.args[0].toString());
console.log('all nominators:', nminatorIds.join(', '));
```
## State entries
+2 -1
View File
@@ -57,7 +57,7 @@ Be aware that in the JS version naming defaults to `camelCase` where names of fi
Each enum has additional getters which are injected based on the fields wrapped. These take the form of `.is<Name>` and `.as<Name>` to allow you to check is the enum is a certain value or to retrieve the underlying value as a specific type.
As a real-world example, when an extrinsic is applied, the `Phase` enum has one of two states, `ApplyExtrinsic(u32)` or `Finalization`. In this case `.isApplyExtrinsic` would be `true` when an extrinsic is being applied, and `.asApplyExtrinsic` would return the value as a `u32` (which is the index of the extrinsic in the block, as it is being applied). When `isisApplyExtrinsic` is `false` and `asApplyExtrinsic` is called, the getter will throw.
As a real-world example, when an extrinsic is applied, the `Phase` enum has one of two states, `ApplyExtrinsic(u32)` or `Finalization`. In this case `.isApplyExtrinsic` would be `true` when an extrinsic is being applied, and `.asApplyExtrinsic` would return the value as a `u32` (which is the index of the extrinsic in the block, as it is being applied). When `isApplyExtrinsic` is `false` and `asApplyExtrinsic` is called, the getter will throw.
## Working with Option&lt;Type&gt;
@@ -67,6 +67,7 @@ An `Option<Type>` attempts to mimic the Rust approach of having `None` and `Some
- `.isSome` - this is `true` is a value is wrapped, i.e. if a `Option<u32>` has an actual underlying `u32`
- `.unwrap()` - when `isSome`, this will return the wrapped value, i.e. for `Option<u32>`, this would return the `u32`. When the value is `isNone`, this call will throw an exception.
- `.unwrapOr(<default value>)` - this extends `unwrap()`, returning the wrapped value when `isSome` and in the case of `isNone` it will return the `<default value>` passed.
- `.unwrapOrDefault()` - returns either the rapped value when `isSome`, or the default for the type when `isNone`
## Working with Tuples
+6 -2
View File
@@ -1,15 +1,19 @@
/* eslint-disable @typescript-eslint/camelcase */
/* eslint-disable @typescript-eslint/no-var-requires */
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
const config = require('@polkadot/dev/config/jest');
module.exports = Object.assign({}, config, {
moduleNameMapper: {
'@polkadot/api-contract(.*)$': '<rootDir>/packages/api-contract/src/$1',
'@polkadot/api-derive(.*)$': '<rootDir>/packages/api-derive/src/$1',
// eslint-disable-next-line sort-keys
'@polkadot/api(.*)$': '<rootDir>/packages/api/src/$1',
'@polkadot/metadata(.*)$': '<rootDir>/packages/metadata/src/$1',
'@polkadot/rpc-(core|provider)(.*)$': '<rootDir>/packages/rpc-$1/src/$2',
'@polkadot/types-known(.*)$': '<rootDir>/packages/types-known/src/$1',
// eslint-disable-next-line sort-keys
'@polkadot/types(.*)$': '<rootDir>/packages/types/src/$1'
},
modulePathIgnorePatterns: [
+1 -2
View File
@@ -1,8 +1,7 @@
// Copyright 2017-2020 @polkadot/util authors & contributors
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
// eslint-disable-next-line @typescript-eslint/no-var-requires
const path = require('path');
module.exports = function resolver (file, config) {
+1 -1
View File
@@ -9,5 +9,5 @@
"packages": [
"packages/*"
],
"version": "1.9.1"
"version": "1.10.1"
}
+3 -3
View File
@@ -27,10 +27,10 @@
"@babel/core": "^7.9.0",
"@babel/register": "^7.9.0",
"@babel/runtime": "^7.9.2",
"@polkadot/dev": "^0.51.9",
"@polkadot/ts": "^0.3.14",
"@polkadot/dev": "^0.52.9",
"@polkadot/ts": "^0.3.18",
"@polkadot/typegen": "workspace:packages/typegen",
"@types/jest": "^25.1.4",
"@types/jest": "^25.2.1",
"copyfiles": "^2.2.0"
}
}
+6 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-contract",
"version": "1.9.1",
"version": "1.10.1",
"description": "Interfaces for interacting with contracts and contract ABIs",
"main": "index.js",
"keywords": [
@@ -27,11 +27,11 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-contract#readme",
"dependencies": {
"@babel/runtime": "^7.9.2",
"@polkadot/api": "1.9.1",
"@polkadot/rpc-core": "1.9.1",
"@polkadot/types": "1.9.1",
"@polkadot/util": "^2.7.1",
"@polkadot/api": "1.10.1",
"@polkadot/rpc-core": "1.10.1",
"@polkadot/types": "1.10.1",
"@polkadot/util": "^2.8.1",
"bn.js": "^5.1.1",
"rxjs": "^6.5.4"
"rxjs": "^6.5.5"
}
}
+2 -2
View File
@@ -18,10 +18,10 @@ export default class ContractAbi extends ContractRegistry implements InterfaceAb
constructor (registry: Registry, abi: ContractABIPre) {
super(registry, abi);
[this.abi, this.constructors, this.messages] = this.decodeAbi(abi);
[this.abi, this.constructors, this.messages] = this._decodeAbi(abi);
}
private decodeAbi (abiPre: ContractABIPre): [ContractABI, ContractABIFn[], AbiMessages] {
private _decodeAbi (abiPre: ContractABIPre): [ContractABI, ContractABIFn[], AbiMessages] {
this.validateAbi(abiPre);
const abi = this.convertAbi(abiPre);
+20 -15
View File
@@ -61,7 +61,7 @@ export default class ContractRegistry extends MetaRegistry {
const unknownKeys = Object.keys(arg).filter((key): boolean => !['name', 'type'].includes(key));
assert(unknownKeys.length === 0, `Unknown keys ${unknownKeys.join(', ')} found in ABI args for ${name}`);
assert(isNumber(arg.name) && isString(this.stringAt(arg.name)), `${name} args should have valid name `);
assert(isNumber(arg.name) && isString(this._stringAt(arg.name)), `${name} args should have valid name `);
assert(isNumber(arg.type.ty) && isObject(this.typeDefAt(arg.type.ty)), `${name} args should have valid type`);
});
}
@@ -83,9 +83,9 @@ export default class ContractRegistry extends MetaRegistry {
assert(unknownKeys.length === 0, `Unknown keys ${unknownKeys.join(', ')} found in ABI args for messages.${message.name}`);
const { name, selector, return_type: returnType } = message;
const { name, return_type: returnType, selector } = message;
assert(isNumber(name) && isString(this.stringAt(name)), `Expected name for ${fnname}`);
assert(isNumber(name) && isString(this._stringAt(name)), `Expected name for ${fnname}`);
assert(isNull(returnType) || (isNumber(returnType.ty) && isObject(this.typeDefAt(returnType.ty))), `Expected return_type for ${fnname}`);
parseSelector(this.registry, fnname, selector);
@@ -100,7 +100,7 @@ export default class ContractRegistry extends MetaRegistry {
const { contract: { constructors, messages, name } } = abi;
assert(constructors && messages && isString(this.stringAt(name)), 'ABI should have constructors, messages & name sections');
assert(constructors && messages && isString(this._stringAt(name)), 'ABI should have constructors, messages & name sections');
this.validateConstructors(abi);
this.validateMessages(abi);
@@ -109,13 +109,16 @@ export default class ContractRegistry extends MetaRegistry {
public createMessage (name: string, message: Partial<ContractABIMessage> & ContractABIMessageBase): ContractABIFn {
const args = message.args.map(({ name, type }): ContractABIFnArg => {
assert(isObject(type), `Invalid type at index ${type}`);
return {
name: stringCamelCase(name),
type
};
});
const Clazz = createArgClass(this.registry, args, isUndefined(message.selector) ? {} : { __selector: 'u32' });
const baseStruct: { [index: string]: any } = { __selector: isUndefined(message.selector) ? undefined : parseSelector(this.registry, name, message.selector) };
const encoder = (...params: CodecArg[]): Uint8Array => {
assert(params.length === args.length, `Expected ${args.length} arguments to contract ${name}, found ${params.length}`);
@@ -136,6 +139,7 @@ export default class ContractRegistry extends MetaRegistry {
fn.args = args;
fn.isConstant = !(message.mutates || false);
fn.type = message.returnType || null;
return fn;
}
@@ -147,19 +151,20 @@ export default class ContractRegistry extends MetaRegistry {
}
public convertArgs (args: ContractABIArgBasePre[]): any[] {
return args.map(({ name, type, ...arg }) => ({ ...arg, name: this.stringAt(name), type: this.convertType(type) }));
return args.map(({ name, type, ...arg }) => ({ ...arg, name: this._stringAt(name), type: this.convertType(type) }));
}
public convertType ({ ty, display_name: displayNameIndices }: ContractABITypePre): TypeDef {
public convertType ({ display_name: displayNameIndices, ty }: ContractABITypePre): TypeDef {
const displayName = this.stringsAt(displayNameIndices).join('::');
return this.typeDefAt(ty, { displayName });
}
public convertContract ({ constructors, messages, name, events, ...contract }: ContractABIContractPre): ContractABIContract {
public convertContract ({ constructors, events, messages, name, ...contract }: ContractABIContractPre): ContractABIContract {
return {
constructors: this.convertConstructors(constructors),
messages: messages.map((message) => this.convertMessage(message)),
name: this.stringAt(name),
name: this._stringAt(name),
...(events
? { events: events.map((event) => this.convertEvent(event)) }
: {}),
@@ -179,7 +184,7 @@ export default class ContractRegistry extends MetaRegistry {
return {
...message,
args: this.convertArgs(args),
name: this.stringAt(name),
name: this._stringAt(name),
returnType: returnType ? this.convertType(returnType) : null
};
}
@@ -202,13 +207,13 @@ export default class ContractRegistry extends MetaRegistry {
}
}
public convertStorageStruct ({ 'struct.type': structType, 'struct.fields': structFields }: ContractABIStorageStructPre): ContractABIStorageStruct {
public convertStorageStruct ({ 'struct.fields': structFields, 'struct.type': structType }: ContractABIStorageStructPre): ContractABIStorageStruct {
return {
'struct.type': this.typeDefAt(structType),
'struct.fields': structFields.map(({ name, layout }) => ({
name: this.stringAt(name),
layout: this.convertStorageLayout(layout)
}))
'struct.fields': structFields.map(({ layout, name }) => ({
layout: this.convertStorageLayout(layout),
name: this._stringAt(name)
})),
'struct.type': this.typeDefAt(structType)
};
}
+50 -46
View File
@@ -48,7 +48,7 @@ class MetadataRegistryLookup {
this._types = types;
}
protected hasItemAt (index: number, variant: MetaRegistryItem): boolean {
protected _hasItemAt (index: number, variant: MetaRegistryItem): boolean {
switch (variant) {
case MetaRegistryItem.String:
return this._strings && !!this._strings[index - 1];
@@ -59,8 +59,8 @@ class MetadataRegistryLookup {
}
}
protected itemAt (index: number, variant: MetaRegistryItem): any {
assert(this.hasItemAt(index, variant), `MetaRegistry: Invalid ${variant} index ${index} found in metadata`);
protected _itemAt (index: number, variant: MetaRegistryItem): any {
assert(this._hasItemAt(index, variant), `MetaRegistry: Invalid ${variant} index ${index} found in metadata`);
switch (variant) {
case MetaRegistryItem.String:
@@ -72,33 +72,33 @@ class MetadataRegistryLookup {
}
}
protected itemsAt (indices: number[], variant: MetaRegistryItem): any[] {
return indices.map((index: number): string => this.itemAt(index, variant));
protected _itemsAt (indices: number[], variant: MetaRegistryItem): any[] {
return indices.map((index: number): string => this._itemAt(index, variant));
}
protected stringAt (index: StringIndex): string {
return this.itemAt(index, MetaRegistryItem.String);
protected _stringAt (index: StringIndex): string {
return this._itemAt(index, MetaRegistryItem.String);
}
public stringsAt (indices: StringIndex[]): string[] {
return this.itemsAt(indices, MetaRegistryItem.String);
return this._itemsAt(indices, MetaRegistryItem.String);
}
public typeAt (index: TypeIndex): MetaType {
return this.itemAt(index, MetaRegistryItem.Type);
return this._itemAt(index, MetaRegistryItem.Type);
}
public typesAt (indices: TypeIndex[]): MetaType[] {
return this.itemsAt(indices, MetaRegistryItem.Type);
return this._itemsAt(indices, MetaRegistryItem.Type);
}
public hasTypeDefAt (index: TypeIndex): boolean {
return this.hasItemAt(index, MetaRegistryItem.TypeDef);
return this._hasItemAt(index, MetaRegistryItem.TypeDef);
}
public typeDefAt (index: TypeIndex, extra: Pick<TypeDef, never> = {}): TypeDef {
return {
...this.itemAt(index, MetaRegistryItem.TypeDef),
...this._itemAt(index, MetaRegistryItem.TypeDef),
...extra
};
}
@@ -116,7 +116,7 @@ export default class MetaRegistry extends MetadataRegistryLookup {
this.typeDefs[typeIndex - 1] = this.typeDefFromMetaType(this.typeAt(typeIndex), typeIndex);
}
private typeDefIdFields ({ id }: MetaType): Pick<TypeDef, never> {
private _typeDefIdFields ({ id }: MetaType): Pick<TypeDef, never> {
const { 'custom.name': nameIndex, 'custom.namespace': namespaceIndices, 'custom.params': paramsIndices } = id as MetaTypeIdCustom;
if (!nameIndex) {
@@ -124,7 +124,7 @@ export default class MetaRegistry extends MetadataRegistryLookup {
}
return {
name: this.stringAt(nameIndex),
name: this._stringAt(nameIndex),
...(namespaceIndices && namespaceIndices.length
? { namespace: this.stringsAt(namespaceIndices).join('::') }
: {}
@@ -136,33 +136,33 @@ export default class MetaRegistry extends MetadataRegistryLookup {
};
}
private typeDefDefFields (metaType: MetaType, typeIndex?: TypeIndex): Pick<TypeDef, never> {
private _typeDefDefFields (metaType: MetaType, typeIndex?: TypeIndex): Pick<TypeDef, never> {
let typeDef;
switch (detectedType(metaType)) {
case MetaTypeInfo.BuiltinPlain:
typeDef = this.typeDefForBuiltinPlain(metaType.id as string);
typeDef = this._typeDefForBuiltinPlain(metaType.id as string);
break;
case MetaTypeInfo.BuiltinTuple:
typeDef = this.typeDefForBuiltinTuple(metaType.id as TypeIndex[]);
typeDef = this._typeDefForBuiltinTuple(metaType.id as TypeIndex[]);
break;
case MetaTypeInfo.BuiltinVec:
typeDef = this.typeDefForBuiltinVec(metaType.id as MetaTypeIdVec, typeIndex);
typeDef = this._typeDefForBuiltinVec(metaType.id as MetaTypeIdVec, typeIndex);
break;
case MetaTypeInfo.BuiltinVecFixed:
typeDef = this.typeDefForBuiltinVecFixed(metaType.id as MetaTypeIdVecFixed, typeIndex);
typeDef = this._typeDefForBuiltinVecFixed(metaType.id as MetaTypeIdVecFixed, typeIndex);
break;
case MetaTypeInfo.Enum:
typeDef = this.typeDefForEnum(metaType.def as MetaTypeDefEnum, metaType.id as MetaTypeIdCustom, typeIndex);
typeDef = this._typeDefForEnum(metaType.def as MetaTypeDefEnum, metaType.id as MetaTypeIdCustom, typeIndex);
break;
case MetaTypeInfo.ClikeEnum:
typeDef = this.typeDefForClikeEnum(metaType.def as MetaTypeDefClikeEnum);
typeDef = this._typeDefForClikeEnum(metaType.def as MetaTypeDefClikeEnum);
break;
case MetaTypeInfo.Struct:
typeDef = this.typeDefForStruct(metaType.def as MetaTypeDefStruct);
break;
case MetaTypeInfo.TupleStruct:
typeDef = this.typeDefForTupleStruct(metaType.def as MetaTypeDefTupleStruct);
typeDef = this._typeDefForTupleStruct(metaType.def as MetaTypeDefTupleStruct);
break;
case MetaTypeInfo.Null:
default:
@@ -176,8 +176,8 @@ export default class MetaRegistry extends MetadataRegistryLookup {
return withTypeString({
info: TypeDefInfo.Null,
type: '',
...this.typeDefDefFields(metaType, typeIndex),
...this.typeDefIdFields(metaType)
...this._typeDefDefFields(metaType, typeIndex),
...this._typeDefIdFields(metaType)
}) as TypeDef;
}
@@ -189,13 +189,13 @@ export default class MetaRegistry extends MetadataRegistryLookup {
return this.typeDefAt(typeIndex);
}
private typeDefForEnumVariant (variant: MetaTypeDefEnumVariant): Pick<TypeDef, any> {
private _typeDefForEnumVariant (variant: MetaTypeDefEnumVariant): Pick<TypeDef, any> {
const { 'unit_variant.name': unitNameIndex } = variant as MetaTypeDefEnumVariantUnit;
if (unitNameIndex) {
return {
info: TypeDefInfo.Plain,
name: this.stringAt(unitNameIndex),
name: this._stringAt(unitNameIndex),
type: 'Null'
};
}
@@ -203,7 +203,7 @@ export default class MetaRegistry extends MetadataRegistryLookup {
const { 'tuple_struct_variant.name': tupleStructVariantNameIndex } = variant as MetaTypeDefEnumVariantTupleStruct;
if (tupleStructVariantNameIndex) {
return this.typeDefForTupleStruct(variant as MetaTypeDefEnumVariantTupleStruct);
return this._typeDefForTupleStruct(variant as MetaTypeDefEnumVariantTupleStruct);
}
const { 'struct_variant.name': structVariantNameIndex } = variant as MetaTypeDefEnumVariantStruct;
@@ -218,14 +218,14 @@ export default class MetaRegistry extends MetadataRegistryLookup {
};
}
private typeDefForBuiltinPlain (id: string): Pick<TypeDef, never> {
private _typeDefForBuiltinPlain (id: string): Pick<TypeDef, never> {
return {
info: TypeDefInfo.Plain,
type: id
};
}
private typeDefForBuiltinTuple (id: TypeIndex[]): Pick<TypeDef, never> {
private _typeDefForBuiltinTuple (id: TypeIndex[]): Pick<TypeDef, never> {
const sub = id.map((tupleTypeIndex: number): TypeDef => this.typeDefFromMetaTypeAt(tupleTypeIndex));
return {
@@ -234,48 +234,52 @@ export default class MetaRegistry extends MetadataRegistryLookup {
};
}
private typeDefForBuiltinVec (id: MetaTypeIdVec, typeIndex?: TypeIndex): Pick<TypeDef, never> {
private _typeDefForBuiltinVec (id: MetaTypeIdVec, typeIndex?: TypeIndex): Pick<TypeDef, never> {
const { 'slice.type': vecTypeIndex } = id;
assert(!typeIndex || vecTypeIndex !== typeIndex, `MetaRegistry: self-referencing registry type at index ${typeIndex}`);
const type = displayType(this.typeDefFromMetaTypeAt(vecTypeIndex));
assert(type && type.length > 0, `MetaRegistry: Invalid builtin Vec type found at index ${typeIndex}`);
return {
info: TypeDefInfo.Vec,
type: `Vec<${type}>`,
sub: this.typeDefFromMetaTypeAt(vecTypeIndex)
sub: this.typeDefFromMetaTypeAt(vecTypeIndex),
type: `Vec<${type}>`
};
}
private typeDefForBuiltinVecFixed (id: MetaTypeIdVecFixed, typeIndex?: TypeIndex): Pick<TypeDef, never> {
const { 'array.type': vecTypeIndex, 'array.len': vecLength } = id;
private _typeDefForBuiltinVecFixed (id: MetaTypeIdVecFixed, typeIndex?: TypeIndex): Pick<TypeDef, never> {
const { 'array.len': vecLength, 'array.type': vecTypeIndex } = id;
assert(!vecLength || vecLength <= 256, 'MetaRegistry: Only support for [Type; <length>], where length <= 256');
assert(!typeIndex || vecTypeIndex !== typeIndex, `MetaRegistry: self-referencing registry type at index ${typeIndex}`);
const type = displayType(this.typeDefFromMetaTypeAt(vecTypeIndex));
assert(type && type.length > 0, `MetaRegistry: Invalid vector type found at index ${typeIndex}`);
return {
info: TypeDefInfo.VecFixed,
length: vecLength, // ex: { type: type }
type: `[${type};${vecLength}]`,
sub: this.typeDefFromMetaTypeAt(vecTypeIndex)
sub: this.typeDefFromMetaTypeAt(vecTypeIndex),
type: `[${type};${vecLength}]`
};
}
private typeDefForEnum (def: MetaTypeDefEnum, id: MetaTypeIdCustom, typeIndex?: TypeIndex): Pick<TypeDef, any> {
const name = id && this.stringAt(id['custom.name']);
private _typeDefForEnum (def: MetaTypeDefEnum, id: MetaTypeIdCustom, typeIndex?: TypeIndex): Pick<TypeDef, any> {
const name = id && this._stringAt(id['custom.name']);
switch (name) {
case 'Option':
return this.typeDefForOption(id, typeIndex);
case 'Result':
return this.typeDefForResult(id, typeIndex);
default: {
const sub = def['enum.variants'].map((variant) => this.typeDefForEnumVariant(variant));
const sub = def['enum.variants'].map((variant) => this._typeDefForEnumVariant(variant));
return {
info: TypeDefInfo.Enum,
@@ -285,13 +289,13 @@ export default class MetaRegistry extends MetadataRegistryLookup {
}
}
private typeDefForClikeEnum (def: MetaTypeDefClikeEnum): Pick<TypeDef, never> {
private _typeDefForClikeEnum (def: MetaTypeDefClikeEnum): Pick<TypeDef, never> {
return {
info: TypeDefInfo.Enum,
sub: def['clike_enum.variants'].map(({ name: nameIndex, discriminant }): TypeDef => ({
sub: def['clike_enum.variants'].map(({ discriminant, name: nameIndex }): TypeDef => ({
ext: { discriminant },
info: TypeDefInfo.Plain,
name: this.stringAt(nameIndex),
name: this._stringAt(nameIndex),
type: 'Null'
}))
};
@@ -322,24 +326,24 @@ export default class MetaRegistry extends MetadataRegistryLookup {
return withTypeString({
info: TypeDefInfo.Struct,
...(structNameIndex
? { name: this.stringAt(structNameIndex) }
? { name: this._stringAt(structNameIndex) }
: {}
),
sub: structFields.map((field: MetaTypeDefStructField): TypeDef => ({
...this.typeDefFromMetaTypeAt(field.type),
name: this.stringAt(field.name)
name: this._stringAt(field.name)
}))
});
}
private typeDefForTupleStruct (def: MetaTypeDefTupleStruct | MetaTypeDefEnumVariantTupleStruct): Pick<TypeDef, any> {
private _typeDefForTupleStruct (def: MetaTypeDefTupleStruct | MetaTypeDefEnumVariantTupleStruct): Pick<TypeDef, any> {
const tupleStructTypes = (def as MetaTypeDefTupleStruct)['tuple_struct.types'] || (def as MetaTypeDefEnumVariantTupleStruct)['tuple_struct_variant.types'];
const tupleStructNameIndex = (def as MetaTypeDefEnumVariantTupleStruct)['tuple_struct_variant.name'];
return withTypeString({
info: TypeDefInfo.Tuple,
...(tupleStructNameIndex
? { name: this.stringAt(tupleStructNameIndex) }
? { name: this._stringAt(tupleStructNameIndex) }
: {}
),
sub: tupleStructTypes.map((fieldIndex: number, index: number): TypeDef => ({
+3 -3
View File
@@ -49,16 +49,16 @@ export default class Blueprint<ApiType extends ApiTypes> extends BaseWithTx<ApiT
return {
signAndSend: this.decorateMethod(
(account: IKeyringPair | string | AccountId | Address): BlueprintCreateResultSubscription<ApiType> => {
return this.apiContracts
return this._apiContracts
.create(endowment, maxGas, this.codeHash, this.abi.constructors[constructorIndex](...params))
.signAndSend(account)
.pipe(map(this.createResult));
.pipe(map(this._createResult));
}
)
};
}
private createResult = (result: SubmittableResult): BlueprintCreateResult<ApiType> => {
private _createResult = (result: SubmittableResult): BlueprintCreateResult<ApiType> => {
let contract: Contract<ApiType> | undefined;
if (result.isInBlock) {
+3 -3
View File
@@ -48,15 +48,15 @@ export default class Code<ApiType extends ApiTypes> extends BaseWithTx<ApiType>
return {
signAndSend: this.decorateMethod(
(account: IKeyringPair | string | AccountId | Address): CodePutCodeResultSubscription<ApiType> =>
this.apiContracts
this._apiContracts
.putCode(maxGas, compactAddLength(this.code))
.signAndSend(account)
.pipe(map(this.createResult))
.pipe(map(this._createResult))
)
};
}
private createResult = (result: ISubmittableResult): CodePutCodeResult<ApiType> => {
private _createResult = (result: ISubmittableResult): CodePutCodeResult<ApiType> => {
let blueprint: Blueprint<ApiType> | undefined;
if (result.isInBlock) {
+17 -17
View File
@@ -33,35 +33,41 @@ export type ContractCallResult<CallType extends ContractCallTypes> = CallType ex
export default class Contract<ApiType extends ApiTypes> extends BaseWithTxAndRpcCall<ApiType> {
public readonly address: Address;
constructor (api: ApiObject<ApiType>, abi: ContractABIPre | Abi, decorateMethod: DecorateMethod<ApiType>, address: string | AccountId | Address) {
super(api, abi, decorateMethod);
this.address = this.registry.createType('Address', address);
}
public call (as: 'rpc', message: string, value: BN | number, gasLimit: BN | number, ...params: any[]): ContractCall<ApiType, 'rpc'>;
public call (as: 'tx', message: string, value: BN | number, gasLimit: BN | number, ...params: any[]): ContractCall<ApiType, 'tx'>;
public call<CallType extends ContractCallTypes> (as: CallType, message: string, value: BN | number, gasLimit: BN | number, ...params: any[]): ContractCall<ApiType, CallType> {
const { fn, def } = this.getMessage(message);
const { def, fn } = this.getMessage(message);
return {
send: this.decorateMethod(
as === 'rpc' && this.hasRpcContractsCall
? (account: IKeyringPair | string | AccountId | Address): ContractCallResult<'rpc'> =>
this.rpcContractsCall(
this._rpcContractsCall(
this.registry.createType('ContractCallRequest', {
origin: account,
dest: this.address.toString(),
value,
gasLimit,
inputData: fn(...params)
inputData: fn(...params),
origin: account,
value
})
).pipe(map((result: ContractExecResult): ContractCallOutcome =>
this.createOutcome(result, this.registry.createType('AccountId', account), def, params)
this._createOutcome(result, this.registry.createType('AccountId', account), def, params)
))
: (account: IKeyringPair | string | AccountId | Address): ContractCallResult<'tx'> =>
this.apiContracts
this._apiContracts
.call(this.address, value, gasLimit, fn(...params))
.signAndSend(account)
)
};
}
private createOutcome (result: ContractExecResult, origin: AccountId, message: ContractABIMessage, params: any[]): ContractCallOutcome {
private _createOutcome (result: ContractExecResult, origin: AccountId, message: ContractABIMessage, params: any[]): ContractCallOutcome {
let output: Codec | null = null;
if (result.isSuccess) {
@@ -73,19 +79,13 @@ export default class Contract<ApiType extends ApiTypes> extends BaseWithTxAndRpc
}
return {
time: Date.now(),
isSuccess: result.isSuccess,
message,
origin,
output,
params,
result,
isSuccess: result.isSuccess,
output
time: Date.now()
};
}
constructor (api: ApiObject<ApiType>, abi: ContractABIPre | Abi, decorateMethod: DecorateMethod<ApiType>, address: string | AccountId | Address) {
super(api, abi, decorateMethod);
this.address = this.registry.createType('Address', address);
}
}
+6 -5
View File
@@ -31,9 +31,9 @@ export abstract class Base<ApiType extends ApiTypes> implements ContractBase<Api
public get messages (): ContractMessage[] {
return this.abi.abi.contract.messages.map(
(def: ContractABIMessage, index): ContractMessage => ({
index,
def,
fn: this.abi.messages[def.name] || this.abi.messages[stringCamelCase(name)]
fn: this.abi.messages[def.name] || this.abi.messages[stringCamelCase(name)],
index
})
);
}
@@ -49,12 +49,13 @@ export abstract class Base<ApiType extends ApiTypes> implements ContractBase<Api
assert(!!def, `Attempted to access a contract message that does not exist: ${typeof nameOrIndex === 'number' ? `index ${nameOrIndex}` : nameOrIndex}`);
const fn = this.abi.messages[def.name] || this.abi.messages[stringCamelCase(def.name)];
return { index, def, fn };
return { def, fn, index };
}
}
export abstract class BaseWithTx<ApiType extends ApiTypes> extends Base<ApiType> {
protected get apiContracts (): SubmittableModuleExtrinsics<'rxjs'> {
protected get _apiContracts (): SubmittableModuleExtrinsics<'rxjs'> {
return this.api.rx.tx.contracts;
}
@@ -70,7 +71,7 @@ export abstract class BaseWithTxAndRpcCall<ApiType extends ApiTypes> extends Bas
return isFunction(this.api.rx.rpc.contracts?.call);
}
protected get rpcContractsCall (): DecoratedRpc<'rxjs', RpcInterface>['contracts']['call'] {
protected get _rpcContractsCall (): DecoratedRpc<'rxjs', RpcInterface>['contracts']['call'] {
assert(this.hasRpcContractsCall, 'You need to connect to a node with the contracts.call RPC method.');
return this.api.rx.rpc.contracts.call;
+9 -9
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-derive",
"version": "1.9.1",
"version": "1.10.1",
"description": "Common functions used across Polkadot, derived from RPC calls and storage queries.",
"main": "index.js",
"keywords": [
@@ -28,17 +28,17 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme",
"dependencies": {
"@babel/runtime": "^7.9.2",
"@polkadot/api": "1.9.1",
"@polkadot/rpc-core": "1.9.1",
"@polkadot/rpc-provider": "1.9.1",
"@polkadot/types": "1.9.1",
"@polkadot/util": "^2.7.1",
"@polkadot/util-crypto": "^2.7.1",
"@polkadot/api": "1.10.1",
"@polkadot/rpc-core": "1.10.1",
"@polkadot/rpc-provider": "1.10.1",
"@polkadot/types": "1.10.1",
"@polkadot/util": "^2.8.1",
"@polkadot/util-crypto": "^2.8.1",
"bn.js": "^5.1.1",
"memoizee": "^0.4.14",
"rxjs": "^6.5.4"
"rxjs": "^6.5.5"
},
"devDependencies": {
"@polkadot/keyring": "^2.7.1"
"@polkadot/keyring": "^2.8.1"
}
}
+4 -4
View File
@@ -59,6 +59,7 @@ function extractIdentity (identityOfOpt?: Option<Registration>, superOf?: [Accou
: undefined,
email: dataAsString(info.email),
image: dataAsString(info.image),
judgements,
legal: dataAsString(info.legal),
other: info.additional.reduce((other: Record<string, string>, [_key, _value]): Record<string, string> => {
const key = dataAsString(_key);
@@ -78,8 +79,7 @@ function extractIdentity (identityOfOpt?: Option<Registration>, superOf?: [Accou
: undefined,
riot: dataAsString(info.riot),
twitter: dataAsString(info.twitter),
web: dataAsString(info.web),
judgements
web: dataAsString(info.web)
};
}
@@ -140,9 +140,9 @@ function retrieveFlags (api: ApiInterfaceRx, accountId?: AccountId): Observable<
return {
isCouncil: (electionsMembers?.map(([id]) => id) || councilMembers || []).some(checkIncluded),
isTechCommittee: technicalCommitteeMembers.some(checkIncluded),
isSociety: societyMembers.some(checkIncluded),
isSudo: !!sudoKey && sudoKey.eq(accountId)
isSudo: !!sudoKey && sudoKey.eq(accountId),
isTechCommittee: technicalCommitteeMembers.some(checkIncluded)
};
})
);
+2 -2
View File
@@ -44,7 +44,7 @@ function queryBalancesAccount (api: ApiInterfaceRx, accountId: AccountId): Obser
[api.query.balances.account, accountId],
[api.query.system.accountNonce, accountId]
]).pipe(
map(([{ free, reserved, miscFrozen, feeFrozen }, accountNonce]): Result =>
map(([{ feeFrozen, free, miscFrozen, reserved }, accountNonce]): Result =>
[free, reserved, feeFrozen, miscFrozen, accountNonce]
)
);
@@ -54,7 +54,7 @@ function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<Re
// AccountInfo is current, support old, eg. Edgeware
return api.query.system.account<AccountInfo | ITuple<[Index, AccountData]>>(accountId).pipe(
map((infoOrTuple): Result => {
const { free, reserved, miscFrozen, feeFrozen } = (infoOrTuple as AccountInfo).nonce
const { feeFrozen, free, miscFrozen, reserved } = (infoOrTuple as AccountInfo).nonce
? (infoOrTuple as AccountInfo).data
: (infoOrTuple as [Index, AccountData])[1];
const accountNonce = (infoOrTuple as AccountInfo).nonce || (infoOrTuple as [Index, AccountData])[0];
@@ -10,6 +10,8 @@ import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option } from '@polkadot/types';
import { memo } from '../util';
type Result = [Hash[], Option<Proposal>[], Option<Votes>[]];
function parse ([hashes, proposals, votes]: Result): DeriveCollectiveProposal[] {
@@ -27,7 +29,7 @@ function parse ([hashes, proposals, votes]: Result): DeriveCollectiveProposal[]
}
export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalCommittee'): () => Observable<DeriveCollectiveProposal[]> {
return (): Observable<DeriveCollectiveProposal[]> =>
return memo((): Observable<DeriveCollectiveProposal[]> =>
api.query[section]?.proposals
? api.query[section].proposals().pipe(
switchMap((hashes: Hash[]): Observable<Result> =>
@@ -41,5 +43,6 @@ export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalC
),
map(parse)
)
: of([] as DeriveCollectiveProposal[]);
: of([] as DeriveCollectiveProposal[])
);
}
+5 -3
View File
@@ -11,6 +11,8 @@ import { Observable, combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';
import { Vec } from '@polkadot/types';
import { memo } from '../util';
function retrieveStakeOf (api: ApiInterfaceRx): Observable<[AccountId, Balance][]> {
const elections = (api.query.electionsPhragmen || api.query.elections);
@@ -80,9 +82,9 @@ function retrieveCurrent (api: ApiInterfaceRx): Observable<DeriveCouncilVotes> {
}
export function votes (api: ApiInterfaceRx): () => Observable<DeriveCouncilVotes> {
// since we are using entries, we are not adding a memo
return (): Observable<DeriveCouncilVotes> =>
return memo((): Observable<DeriveCouncilVotes> =>
(api.query.electionsPhragmen || api.query.elections).stakeOf
? retrievePrev(api)
: retrieveCurrent(api);
: retrieveCurrent(api)
);
}
+4 -3
View File
@@ -8,10 +8,10 @@ import { DeriveCouncilVote } from '../types';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { memo } from '../util';
export function votesOf (api: ApiInterfaceRx): (accountId: string | Uint8Array | AccountId) => Observable<DeriveCouncilVote> {
// no memo, votes actually pulls the entries without a memo (using entries)
return (accountId: string | Uint8Array | AccountId): Observable<DeriveCouncilVote> =>
return memo((accountId: string | Uint8Array | AccountId): Observable<DeriveCouncilVote> =>
api.derive.council.votes().pipe(
map((votes): DeriveCouncilVote =>
(
@@ -19,5 +19,6 @@ export function votesOf (api: ApiInterfaceRx): (accountId: string | Uint8Array |
[null, { stake: api.registry.createType('Balance'), votes: [] as AccountId[] }]
)[1]
)
);
)
);
}
@@ -1,32 +0,0 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { ReferendumInfo, ReferendumInfoTo239 } from '@polkadot/types/interfaces';
import { DeriveReferendum } from '../types';
import BN from 'bn.js';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { Option } from '@polkadot/types';
import { memo } from '../util';
import { getStatus, parseImage } from './util';
export function _referendumInfo (api: ApiInterfaceRx): (index: BN, info: Option<ReferendumInfo | ReferendumInfoTo239>) => Observable<DeriveReferendum | null> {
return memo((index: BN, info: Option<ReferendumInfo | ReferendumInfoTo239>): Observable<DeriveReferendum | null> => {
const status = getStatus(info);
return status
? api.query.democracy.preimages(status.proposalHash).pipe(
map((preimage): DeriveReferendum => ({
index: api.registry.createType('ReferendumIndex', index),
image: parseImage(api, preimage),
imageHash: status.proposalHash,
status
}))
)
: of(null);
});
}
@@ -1,84 +0,0 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId, Vote, Voting, VotingDirectVote } from '@polkadot/types/interfaces';
import { DeriveBalancesAccount, DeriveReferendum, DeriveReferendumVote, DeriveReferendumVotes } from '../types';
import BN from 'bn.js';
import { Observable, of, combineLatest } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Vec } from '@polkadot/types';
import { memo } from '../util';
import { calcVotes } from './util';
function votesPrev (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveReferendumVote[]> {
return api.query.democracy.votersFor<Vec<AccountId>>(referendumId).pipe(
switchMap((votersFor): Observable<[Vec<AccountId>, Vote[], DeriveBalancesAccount[]]> =>
combineLatest([
of(votersFor),
votersFor.length
? api.query.democracy.voteOf.multi<Vote>(
votersFor.map((accountId): [BN | number, AccountId] =>
[referendumId, accountId]
)
)
: of([]),
api.derive.balances.votingBalances(votersFor)
])
),
map(([votersFor, votes, balances]): DeriveReferendumVote[] =>
votersFor.map((accountId, index): DeriveReferendumVote => ({
accountId,
balance: balances[index].votingBalance || api.registry.createType('Balance'),
vote: votes[index] || api.registry.createType('Vote')
}))
)
);
}
function votesCurr (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveReferendumVote[]> {
return api.query.democracy.votingOf.entries<Voting>().pipe(
map((allVoting): DeriveReferendumVote[] =>
allVoting
.map(([key, voting]): [AccountId, Voting] => [key.args[0] as AccountId, voting])
// FIXME We are ignoring delegated votes
.filter(([, voting]) => voting.isDirect)
.map(([accountId, voting]): [AccountId, VotingDirectVote[]] => [
accountId,
voting.asDirect.votes.filter(([idx]) => idx.eq(referendumId))
])
.filter(([, directVotes]) => !!directVotes.length)
.reduce((result: DeriveReferendumVote[], [accountId, votes]) =>
// FIXME We are ignoring split votes
votes.reduce((result: DeriveReferendumVote[], [, vote]): DeriveReferendumVote[] => {
if (vote.isStandard) {
result.push({
accountId,
...vote.asStandard
});
}
return result;
}, result), []
)
)
);
}
export function _referendumVotes (api: ApiInterfaceRx): (referendum: DeriveReferendum) => Observable<DeriveReferendumVotes> {
return memo((referendum: DeriveReferendum): Observable<DeriveReferendumVotes> =>
combineLatest([
api.derive.democracy.sqrtElectorate(),
api.query.democracy.votingOf
? votesCurr(api, referendum.index)
: votesPrev(api, referendum.index)
]).pipe(
map(([sqrtElectorate, votes]) =>
calcVotes(sqrtElectorate, referendum, votes)
)
)
);
}
@@ -1,22 +0,0 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveReferendum, DeriveReferendumVotes } from '../types';
import { Observable, of, combineLatest } from 'rxjs';
import { memo } from '../util';
export function _referendumsVotes (api: ApiInterfaceRx): (referendums: DeriveReferendum[]) => Observable<DeriveReferendumVotes[]> {
return memo((referendums: DeriveReferendum[]): Observable<DeriveReferendumVotes[]> =>
referendums.length
? combineLatest(
referendums.map((referendum): Observable<DeriveReferendumVotes> =>
api.derive.democracy._referendumVotes(referendum)
)
)
: of([])
);
}
@@ -2,37 +2,104 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { BlockNumber, Hash, ReferendumIndex } from '@polkadot/types/interfaces';
import { BlockNumber, Hash, ReferendumIndex, Scheduled } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DeriveDispatch } from '../types';
import { DeriveDispatch, DeriveProposalImage } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Vec } from '@polkadot/types';
import { Option, Vec, u64 } from '@polkadot/types';
import { stringToHex } from '@polkadot/util';
import { memo } from '../util';
export function dispatchQueue (api: ApiInterfaceRx): () => Observable<DeriveDispatch[]> {
return memo((): Observable<DeriveDispatch[]> =>
api.query.democracy?.dispatchQueue
? api.query.democracy.dispatchQueue<Vec<ITuple<[BlockNumber, Hash, ReferendumIndex]>>>().pipe(
switchMap((dispatches) =>
combineLatest([
of(dispatches),
api.derive.democracy.preimages(
dispatches.map(([, hash]) => hash))
])
),
map(([dispatches, images]) =>
dispatches.map(([at, imageHash, index], dispatchIndex): DeriveDispatch => ({
at,
index,
image: images[dispatchIndex],
imageHash
}))
)
)
: of([])
const DEMOCRACY_ID = stringToHex('democrac');
interface SchedulerInfo {
at: BlockNumber;
imageHash: Hash;
index: ReferendumIndex;
}
function queryQueue (api: ApiInterfaceRx): Observable<DeriveDispatch[]> {
return api.query.democracy.dispatchQueue<Vec<ITuple<[BlockNumber, Hash, ReferendumIndex]>>>().pipe(
switchMap((dispatches) =>
combineLatest([
of(dispatches),
api.derive.democracy.preimages(
dispatches.map(([, hash]) => hash))
])
),
map(([dispatches, images]) =>
dispatches.map(([at, imageHash, index], dispatchIndex): DeriveDispatch => ({
at,
image: images[dispatchIndex],
imageHash,
index
}))
)
);
}
function schedulerEntries (api: ApiInterfaceRx): Observable<[BlockNumber[], Option<Scheduled>[][]]> {
// We don't get entries, but rather we get the keys (triggered via finished referendums) and
// the subscribe to those keys - this means we pickup when the schedulers actually executes
// at a block, the entry for that block will become empty
return api.derive.democracy.referendumsFinished().pipe(
switchMap(() =>
api.query.scheduler.agenda.keys()
),
switchMap((keys) => {
const blockNumbers = keys.map((key) => key.args[0] as BlockNumber);
return combineLatest([
of(blockNumbers),
api.query.scheduler.agenda.multi<Vec<Option<Scheduled>>>(blockNumbers)
]);
})
);
}
function queryScheduler (api: ApiInterfaceRx): Observable<DeriveDispatch[]> {
return schedulerEntries(api).pipe(
switchMap(([blockNumbers, agendas]): Observable<[SchedulerInfo[], (DeriveProposalImage | undefined)[]]> => {
const result: SchedulerInfo[] = [];
blockNumbers.forEach((at, index): void => {
agendas[index].filter((optScheduled) => optScheduled.isSome).forEach((optScheduled): void => {
const scheduled = optScheduled.unwrap();
if (scheduled.maybeId.isSome) {
const id = scheduled.maybeId.unwrap().toHex();
if (id.startsWith(DEMOCRACY_ID)) {
const [, index] = api.registry.createType('(u64, ReferendumIndex)' as any, id) as ITuple<[u64, ReferendumIndex]>;
const imageHash = scheduled.call.args[0] as Hash;
result.push({ at, imageHash, index });
}
}
});
});
return combineLatest([
of(result),
api.derive.democracy.preimages(result.map(({ imageHash }) => imageHash))
]);
}),
map(([infos, images]): DeriveDispatch[] =>
infos.map((info, index) => ({ ...info, image: images[index] }))
)
);
}
export function dispatchQueue (api: ApiInterfaceRx): () => Observable<DeriveDispatch[]> {
return memo((): Observable<DeriveDispatch[]> =>
api.query.scheduler?.agenda
? queryScheduler(api)
: api.query.democracy.dispatchQueue
? queryQueue(api)
: of([])
);
}
+2 -3
View File
@@ -2,15 +2,14 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
export * from './_referendumsVotes';
export * from './_referendumVotes';
export * from './_referendumInfo';
export * from './dispatchQueue';
export * from './nextExternal';
export * from './preimage';
export * from './preimages';
export * from './proposals';
export * from './referendumIds';
export * from './referendums';
export * from './referendumsActive';
export * from './referendumsFinished';
export * from './referendumsInfo';
export * from './sqrtElectorate';
@@ -26,9 +26,9 @@ function parse ([proposals, images, depositors]: [Proposals, (DeriveProposalImag
return {
balance,
index,
image: images[proposalIndex],
imageHash,
index,
proposer,
seconds
};
@@ -0,0 +1,29 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { ReferendumIndex } from '@polkadot/types/interfaces';
import BN from 'bn.js';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { memo } from '../util';
export function referendumIds (api: ApiInterfaceRx): () => Observable<BN[]> {
return memo((): Observable<BN[]> =>
api.query.democracy?.lowestUnbaked
? api.queryMulti<[ReferendumIndex, ReferendumIndex]>([
api.query.democracy.lowestUnbaked,
api.query.democracy.referendumCount
]).pipe(
map(([first, total]): BN[] =>
total.gt(first)
? [...Array(total.sub(first).toNumber())].map((_, i): BN => first.addn(i))
: []
)
)
: of([])
);
}
@@ -3,10 +3,8 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { ReferendumIndex } from '@polkadot/types/interfaces';
import { DeriveReferendum } from '../types';
import BN from 'bn.js';
import { Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
@@ -14,19 +12,12 @@ import { memo } from '../util';
export function referendumsActive (api: ApiInterfaceRx): () => Observable<DeriveReferendum[]> {
return memo((): Observable<DeriveReferendum[]> =>
api.query.democracy?.lowestUnbaked
? api.queryMulti<[ReferendumIndex, ReferendumIndex]>([
api.query.democracy.lowestUnbaked,
api.query.democracy.referendumCount
]).pipe(
switchMap(([first, total]): Observable<DeriveReferendum[]> =>
total.gt(first)
? api.derive.democracy.referendumsInfo(
[...Array(total.sub(first).toNumber())].map((_, i): BN => first.addn(i))
)
: of([])
)
api.derive.democracy.referendumIds().pipe(
switchMap((ids): Observable<DeriveReferendum[]> =>
ids.length
? api.derive.democracy.referendumsInfo(ids)
: of([])
)
: of([])
)
);
}
@@ -0,0 +1,27 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { ReferendumInfo, ReferendumInfoFinished } from '@polkadot/types/interfaces';
import { Observable } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option } from '@polkadot/types';
import { memo } from '../util';
export function referendumsFinished (api: ApiInterfaceRx): () => Observable<ReferendumInfoFinished[]> {
return memo((): Observable<ReferendumInfoFinished[]> =>
api.derive.democracy.referendumIds().pipe(
switchMap((ids) => api.query.democracy.referendumInfoOf.multi<Option<ReferendumInfo>>(ids)),
map((infos): ReferendumInfoFinished[] =>
infos
.filter((optInfo) => optInfo.isSome)
.map((optInfo) => optInfo.unwrap())
.filter((info) => info.isFinished)
.map((info) => info.asFinished)
)
)
);
}
@@ -3,15 +3,114 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { ReferendumInfo } from '@polkadot/types/interfaces';
import { DeriveReferendum } from '../types';
import { AccountId, ReferendumInfo, ReferendumInfoTo239, Vote, Voting, VotingDirectVote } from '@polkadot/types/interfaces';
import { DeriveBalancesAccount, DeriveReferendum, DeriveReferendumVote, DeriveReferendumVotes } from '../types';
import BN from 'bn.js';
import { Observable, of, combineLatest } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option } from '@polkadot/types';
import { Option, Vec } from '@polkadot/types';
import { memo } from '../util';
import { calcVotes, getStatus, parseImage } from './util';
function votesPrev (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveReferendumVote[]> {
return api.query.democracy.votersFor<Vec<AccountId>>(referendumId).pipe(
switchMap((votersFor): Observable<[Vec<AccountId>, Vote[], DeriveBalancesAccount[]]> =>
combineLatest([
of(votersFor),
votersFor.length
? api.query.democracy.voteOf.multi<Vote>(
votersFor.map((accountId): [BN | number, AccountId] =>
[referendumId, accountId]
)
)
: of([]),
api.derive.balances.votingBalances(votersFor)
])
),
map(([votersFor, votes, balances]): DeriveReferendumVote[] =>
votersFor.map((accountId, index): DeriveReferendumVote => ({
accountId,
balance: balances[index].votingBalance || api.registry.createType('Balance'),
vote: votes[index] || api.registry.createType('Vote')
}))
)
);
}
function votesCurr (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveReferendumVote[]> {
return api.query.democracy.votingOf.entries<Voting>().pipe(
map((allVoting): DeriveReferendumVote[] =>
allVoting
.map(([key, voting]): [AccountId, Voting] => [key.args[0] as AccountId, voting])
// FIXME We are ignoring delegated votes
.filter(([, voting]) => voting.isDirect)
.map(([accountId, voting]): [AccountId, VotingDirectVote[]] => [
accountId,
voting.asDirect.votes.filter(([idx]) => idx.eq(referendumId))
])
.filter(([, directVotes]) => !!directVotes.length)
.reduce((result: DeriveReferendumVote[], [accountId, votes]) =>
// FIXME We are ignoring split votes
votes.reduce((result: DeriveReferendumVote[], [, vote]): DeriveReferendumVote[] => {
if (vote.isStandard) {
result.push({
accountId,
...vote.asStandard
});
}
return result;
}, result), []
)
)
);
}
export function _referendumVotes (api: ApiInterfaceRx): (referendum: DeriveReferendum) => Observable<DeriveReferendumVotes> {
return memo((referendum: DeriveReferendum): Observable<DeriveReferendumVotes> =>
combineLatest([
api.derive.democracy.sqrtElectorate(),
api.query.democracy.votingOf
? votesCurr(api, referendum.index)
: votesPrev(api, referendum.index)
]).pipe(
map(([sqrtElectorate, votes]) =>
calcVotes(sqrtElectorate, referendum, votes)
)
)
);
}
export function _referendumsVotes (api: ApiInterfaceRx): (referendums: DeriveReferendum[]) => Observable<DeriveReferendumVotes[]> {
return memo((referendums: DeriveReferendum[]): Observable<DeriveReferendumVotes[]> =>
referendums.length
? combineLatest(
referendums.map((referendum): Observable<DeriveReferendumVotes> =>
api.derive.democracy._referendumVotes(referendum)
)
)
: of([])
);
}
export function _referendumInfo (api: ApiInterfaceRx): (index: BN, info: Option<ReferendumInfo | ReferendumInfoTo239>) => Observable<DeriveReferendum | null> {
return memo((index: BN, info: Option<ReferendumInfo | ReferendumInfoTo239>): Observable<DeriveReferendum | null> => {
const status = getStatus(info);
return status
? api.query.democracy.preimages(status.proposalHash).pipe(
map((preimage): DeriveReferendum => ({
image: parseImage(api, preimage),
imageHash: status.proposalHash,
index: api.registry.createType('ReferendumIndex', index),
status
}))
)
: of(null);
});
}
export function referendumsInfo (api: ApiInterfaceRx): (ids: BN[]) => Observable<DeriveReferendum[]> {
return memo((ids: BN[]): Observable<DeriveReferendum[]> =>
+37 -9
View File
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId, Balance, BlockNumber, Proposal, ReferendumInfo, ReferendumInfoTo239, ReferendumStatus, Tally, VoteThreshold } from '@polkadot/types/interfaces';
import { AccountId, Balance, BlockNumber, PreimageStatus, Proposal, ReferendumInfo, ReferendumInfoTo239, ReferendumStatus, Tally, VoteThreshold } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DeriveProposalImage, DeriveReferendum, DeriveReferendumVote, DeriveReferendumVotes, DeriveReferendumVoteState } from '../types';
@@ -11,6 +11,15 @@ import BN from 'bn.js';
import { Bytes, Option } from '@polkadot/types';
import { bnSqrt } from '@polkadot/util';
type PreimageInfo = [Bytes, AccountId, Balance, BlockNumber];
type OldPreimage = ITuple<PreimageInfo>;
interface ApproxState {
votedAye: BN;
votedNay: BN;
votedTotal: BN;
}
function isOldInfo (info: ReferendumInfo | ReferendumInfoTo239): info is ReferendumInfoTo239 {
return !!(info as ReferendumInfoTo239).proposalHash;
}
@@ -19,6 +28,10 @@ function isCurrentStatus (status: ReferendumStatus | ReferendumInfoTo239): statu
return !!(status as ReferendumStatus).tally;
}
function isCurrentPreimage (api: ApiInterfaceRx, imageOpt: Option<OldPreimage> | Option<PreimageStatus>): imageOpt is Option<PreimageStatus> {
return !!imageOpt && !api.query.democracy.dispatchQueue;
}
export function compareRationals (n1: BN, d1: BN, n2: BN, d2: BN): boolean {
while (true) {
const q1 = n1.div(d1);
@@ -46,7 +59,7 @@ export function compareRationals (n1: BN, d1: BN, n2: BN, d2: BN): boolean {
}
}
function isPassing (threshold: VoteThreshold, sqrtElectorate: BN, { votedAye, votedNay, votedTotal }: DeriveReferendumVoteState): boolean {
export function calcPassing (threshold: VoteThreshold, sqrtElectorate: BN, { votedAye, votedNay, votedTotal }: ApproxState): boolean {
const sqrtVoters = bnSqrt(votedTotal);
return sqrtVoters.isZero()
@@ -123,7 +136,7 @@ export function calcVotes (sqrtElectorate: BN, referendum: DeriveReferendum, vot
return {
...state,
isPassing: isPassing(referendum.status.threshold, sqrtElectorate, state),
isPassing: calcPassing(referendum.status.threshold, sqrtElectorate, state),
votes
};
}
@@ -145,13 +158,8 @@ export function getStatus (info: Option<ReferendumInfo | ReferendumInfoTo239>):
return null;
}
export function parseImage (api: ApiInterfaceRx, imageOpt: Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>): DeriveProposalImage | undefined {
if (imageOpt.isNone) {
return;
}
function constructProposal (api: ApiInterfaceRx, [bytes, proposer, balance, at]: PreimageInfo): DeriveProposalImage {
let proposal: Proposal | undefined;
const [bytes, proposer, balance, at] = imageOpt.unwrap();
try {
proposal = api.registry.createType('Proposal', bytes.toU8a(true));
@@ -161,3 +169,23 @@ export function parseImage (api: ApiInterfaceRx, imageOpt: Option<ITuple<[Bytes,
return { at, balance, proposal, proposer };
}
export function parseImage (api: ApiInterfaceRx, imageOpt: Option<OldPreimage> | Option<PreimageStatus>): DeriveProposalImage | undefined {
if (imageOpt.isNone) {
return;
}
if (isCurrentPreimage(api, imageOpt)) {
const status = imageOpt.unwrap();
if (status.isMissing) {
return;
}
const { data, deposit, provider, since } = status.asAvailable;
return constructProposal(api, [data, provider, deposit, since]);
}
return constructProposal(api, imageOpt.unwrap());
}
+2 -2
View File
@@ -27,9 +27,9 @@ function queryElections (api: ApiInterfaceRx): Observable<DeriveElectionsInfo> {
api.query[section].runnersUp
]).pipe(
map(([councilMembers, candidates, members, runnersUp]): DeriveElectionsInfo => ({
candidates,
candidateCount: api.registry.createType('u32', candidates.length),
candidacyBond: api.consts[section].candidacyBond as Balance,
candidateCount: api.registry.createType('u32', candidates.length),
candidates,
desiredSeats: api.consts[section].desiredMembers as u32,
members: members.length
? members.sort(sortAccounts)
+1
View File
@@ -77,6 +77,7 @@ function injectFunctions<AllSections> (api: ApiInterfaceRx, allSections: AllSect
const methodName = _methodName as keyof typeof section;
// Not sure what to do here, casting as any. Though the final types are good
const method = (section[methodName] as any)(api);
// idem
(sectionAcc as any)[methodName] = method;
@@ -44,6 +44,7 @@ function parseActive (id: ParaId, active: Active): DeriveParachainActive | null
)
};
}
return null;
}
@@ -30,7 +30,7 @@ export function candidates (api: ApiInterfaceRx): () => Observable<DeriveSociety
])
),
map(([candidates, suspended]: Result): DeriveSocietyCandidate[] =>
candidates.map(({ who, kind, value }, index) => ({
candidates.map(({ kind, value, who }, index) => ({
accountId: who,
isSuspended: suspended[index].isSome,
kind,
+1 -1
View File
@@ -30,9 +30,9 @@ export function info (api: ApiInterfaceRx): () => Observable<DeriveSociety> {
map(([bids, defender, founder, head, maxMembers, pot]: Result): DeriveSociety => ({
bids,
defender: defender.unwrapOr(undefined),
founder: founder.unwrapOr(undefined),
hasDefender: (defender.isSome && head.isSome && !head.eq(defender)) || false,
head: head.unwrapOr(undefined),
founder: founder.unwrapOr(undefined),
maxMembers,
pot
}))
+1 -1
View File
@@ -29,8 +29,8 @@ export function member (api: ApiInterfaceRx): (accountId: AccountId) => Observab
]).pipe(
map(([payouts, strikes, defenderVotes, suspended, vouching]: Result): DeriveSocietyMember => ({
accountId,
payouts,
isSuspended: suspended.isTrue,
payouts,
strikes,
vote: defenderVotes.unwrapOr(undefined),
vouching: vouching.unwrapOr(undefined)
@@ -0,0 +1,42 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, EraPoints, EraRewardPoints, RewardPoint } from '@polkadot/types/interfaces';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
function retrievePointsPrev (api: ApiInterfaceRx, currentElected: AccountId[]): Observable<EraRewardPoints> {
return api.query.staking.currentEraPointsEarned<EraPoints>().pipe(
map(({ individual, total }): EraRewardPoints =>
api.registry.createType('EraRewardPoints', {
individual: new Map<AccountId, RewardPoint>(
individual
.map((points) => api.registry.createType('RewardPoint', points))
.map((points, index): [AccountId, RewardPoint] => [currentElected[index], points])
),
total
})
)
);
}
/**
* @description Retrieve the staking overview, including elected and points earned
*/
export function currentPoints (api: ApiInterfaceRx): () => Observable<EraRewardPoints> {
return memo((): Observable<EraRewardPoints> =>
api.derive.staking.overview().pipe(
switchMap(({ activeEra, nextElected }) =>
api.query.staking.erasRewardPoints
? api.query.staking.erasRewardPoints<EraRewardPoints>(activeEra)
: api.query.staking.currentEraPointsEarned
? retrievePointsPrev(api, nextElected)
: of(api.registry.createType('EraRewardPoints'))
)
));
}
@@ -18,9 +18,7 @@ export function electedInfo (api: ApiInterfaceRx): () => Observable<DeriveStakin
combineLatest([
of(nextElected),
combineLatest(
nextElected.map((accountId): Observable<DeriveStakingQuery> =>
api.derive.staking.query(accountId)
)
nextElected.map((accountId) => api.derive.staking.query(accountId))
)
])
),
+13 -12
View File
@@ -6,7 +6,6 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
import { EraIndex, Exposure } from '@polkadot/types/interfaces';
import { DeriveEraExposure, DeriveEraNominatorExposure, DeriveEraValidatorExposure } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { StorageKey } from '@polkadot/types';
@@ -24,11 +23,11 @@ function mapStakers (era: EraIndex, stakers: KeysAndExposures): DeriveEraExposur
validators[validatorId] = exposure;
exposure.others.forEach(({ who }, index): void => {
exposure.others.forEach(({ who }, validatorIndex): void => {
const nominatorId = who.toString();
nominators[nominatorId] = nominators[nominatorId] || [];
nominators[nominatorId].push([validatorId, index]);
nominators[nominatorId].push({ validatorId, validatorIndex });
});
});
@@ -43,16 +42,18 @@ export function eraExposure (api: ApiInterfaceRx): (era: EraIndex) => Observable
);
}
export function erasExposure (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraExposure[]> {
return memo((withActive?: boolean | BN | number): Observable<DeriveEraExposure[]> =>
export function _erasExposure (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraExposure[]> {
return memo((eras: EraIndex[]): Observable<DeriveEraExposure[]> =>
eras.length
? combineLatest(eras.map((era) => api.derive.staking.eraExposure(era)))
: of([])
);
}
export function erasExposure (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraExposure[]> {
return memo((withActive?: boolean): Observable<DeriveEraExposure[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras): Observable<DeriveEraExposure[]> =>
eras.length
? combineLatest(
eras.map((era) => api.derive.staking.eraExposure(era))
)
: of([])
)
switchMap((eras) => api.derive.staking._erasExposure(eras))
)
);
}
@@ -9,45 +9,32 @@ import BN from 'bn.js';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { Option, u32 } from '@polkadot/types';
import { isBoolean, isUndefined, bnToBn } from '@polkadot/util';
import { memo } from '../util';
export function erasHistoric (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<EraIndex[]> {
return memo((withActive?: boolean | BN | number): Observable<EraIndex[]> =>
export function erasHistoric (api: ApiInterfaceRx): (withActive?: boolean) => Observable<EraIndex[]> {
return memo((withActive?: boolean): Observable<EraIndex[]> =>
api.query.staking?.activeEra
? api.queryMulti<[Option<ActiveEraInfo>, u32]>([
api.query.staking.activeEra,
api.query.staking.historyDepth
]).pipe(
map(([activeEraOpt, historyDepth]): EraIndex[] => {
const result: (EraIndex | null)[] = [];
const result: EraIndex[] = [];
const max = historyDepth.toNumber();
const activeEra = activeEraOpt.unwrapOrDefault().index.toBn();
const activeEra: BN = activeEraOpt.unwrapOrDefault().index;
let lastEra = activeEra;
while (lastEra.gten(0) && (result.length < max)) {
result.push(
((lastEra !== activeEra) || (withActive === true))
? api.registry.createType('EraIndex', lastEra)
: null
);
if ((lastEra !== activeEra) || (withActive === true)) {
result.push(api.registry.createType('EraIndex', lastEra));
}
lastEra = lastEra.subn(1);
}
const startEra = isUndefined(withActive) || isBoolean(withActive)
? new BN(0)
: bnToBn(withActive);
// go from oldest to newest
return result
.filter((era): era is EraIndex =>
era
? era.gte(startEra)
: false
)
.reverse();
return result.reverse();
})
)
: of([])
+20 -19
View File
@@ -6,8 +6,7 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
import { EraIndex, EraRewardPoints } from '@polkadot/types/interfaces';
import { DeriveEraPoints, DeriveEraValPoints } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs';
import { Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
@@ -22,24 +21,26 @@ function mapValidators ({ individual }: EraRewardPoints): DeriveEraValPoints {
}, {});
}
export function erasPoints (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraPoints[]> {
return memo((withActive?: boolean | number): Observable<DeriveEraPoints[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras): Observable<[EraIndex[], EraRewardPoints[]]> =>
combineLatest([
of(eras),
eras.length
? api.query.staking.erasRewardPoints.multi<EraRewardPoints>(eras)
: of([])
])
),
map(([eras, points]): DeriveEraPoints[] =>
eras.map((era, index): DeriveEraPoints => ({
era,
eraPoints: points[index].total,
validators: mapValidators(points[index])
}))
export function _erasPoints (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraPoints[]> {
return memo((eras: EraIndex[]): Observable<DeriveEraPoints[]> =>
eras.length
? api.query.staking.erasRewardPoints.multi<EraRewardPoints>(eras).pipe(
map((points) =>
eras.map((era, index): DeriveEraPoints => ({
era,
eraPoints: points[index].total,
validators: mapValidators(points[index])
}))
)
)
: of([])
);
}
export function erasPoints (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraPoints[]> {
return memo((withActive?: boolean): Observable<DeriveEraPoints[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking._erasPoints(eras))
)
);
}
+11 -10
View File
@@ -6,7 +6,6 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
import { EraIndex, ValidatorPrefs } from '@polkadot/types/interfaces';
import { DeriveEraPrefs, DeriveEraValPrefs } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { StorageKey } from '@polkadot/types';
@@ -31,16 +30,18 @@ export function eraPrefs (api: ApiInterfaceRx): (era: EraIndex) => Observable<De
);
}
export function erasPrefs (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraPrefs[]> {
return memo((withActive?: boolean | BN | number): Observable<DeriveEraPrefs[]> =>
export function _erasPrefs (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraPrefs[]> {
return memo((eras: EraIndex[]): Observable<DeriveEraPrefs[]> =>
eras.length
? combineLatest(eras.map((era) => api.derive.staking.eraPrefs(era)))
: of([])
);
}
export function erasPrefs (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraPrefs[]> {
return memo((withActive?: boolean): Observable<DeriveEraPrefs[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras): Observable<DeriveEraPrefs[]> =>
eras.length
? combineLatest(
eras.map((era) => api.derive.staking.eraPrefs(era))
)
: of([])
)
switchMap((eras) => api.derive.staking._erasPrefs(eras))
)
);
}
+15 -16
View File
@@ -6,30 +6,29 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
import { Balance, EraIndex } from '@polkadot/types/interfaces';
import { DeriveEraRewards } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs';
import { Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option } from '@polkadot/types';
import { memo } from '../util';
export function erasRewards (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraRewards[]> {
return memo((withActive?: boolean | BN | number): Observable<DeriveEraRewards[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras): Observable<[EraIndex[], Option<Balance>[]]> =>
combineLatest([
of(eras),
eras.length
? api.query.staking.erasValidatorReward.multi<Option<Balance>>(eras)
: of([])
])
),
map(([eras, rewards]): DeriveEraRewards[] =>
eras.map((era, index): DeriveEraRewards => ({
export function _erasRewards (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraRewards[]> {
return memo((eras: EraIndex[]): Observable<DeriveEraRewards[]> =>
eras.length
? api.query.staking.erasValidatorReward.multi<Option<Balance>>(eras).pipe(
map((rewards) => eras.map((era, index): DeriveEraRewards => ({
era,
eraReward: rewards[index].unwrapOrDefault()
}))
})))
)
: of([])
);
}
export function erasRewards (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraRewards[]> {
return memo((withActive?: boolean): Observable<DeriveEraRewards[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking._erasRewards(eras))
)
);
}
+13 -10
View File
@@ -7,7 +7,6 @@ import { BalanceOf, EraIndex, Perbill } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DeriveEraSlashes, DeriveEraValSlash } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option, StorageKey } from '@polkadot/types';
@@ -40,16 +39,20 @@ export function eraSlashes (api: ApiInterfaceRx): (era: EraIndex) => Observable<
);
}
export function erasSlashes (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraSlashes[]> {
return memo((withActive?: boolean | BN | number): Observable<DeriveEraSlashes[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras): Observable<DeriveEraSlashes[]> =>
eras.length
? combineLatest(
eras.map((era) => api.derive.staking.eraSlashes(era))
)
: of([])
export function _erasSlashes (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraSlashes[]> {
return memo((eras: EraIndex[]): Observable<DeriveEraSlashes[]> =>
eras.length
? combineLatest(
eras.map((era) => api.derive.staking.eraSlashes(era))
)
: of([])
);
}
export function erasSlashes (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraSlashes[]> {
return memo((withActive?: boolean): Observable<DeriveEraSlashes[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking._erasSlashes(eras))
)
);
}
+1
View File
@@ -3,6 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
export * from './account';
export * from './currentPoints';
export * from './erasExposure';
export * from './erasHistoric';
export * from './erasPoints';
+6 -30
View File
@@ -2,30 +2,14 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, EraPoints, EraRewardPoints, RewardPoint } from '@polkadot/types/interfaces';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveStakingOverview } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Observable, combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';
import { memo } from '../util';
function retrievePointsPrev (api: ApiInterfaceRx, currentElected: AccountId[]): Observable<EraRewardPoints> {
return api.query.staking.currentEraPointsEarned<EraPoints>().pipe(
map(({ individual, total }): EraRewardPoints =>
api.registry.createType('EraRewardPoints', {
total,
individual: new Map<AccountId, RewardPoint>(
individual
.map((points): RewardPoint => api.registry.createType('RewardPoint', points))
.map((points, index): [AccountId, RewardPoint] => [currentElected[index], points])
)
})
)
);
}
/**
* @description Retrieve the staking overview, including elected and points earned
*/
@@ -35,18 +19,10 @@ export function overview (api: ApiInterfaceRx): () => Observable<DeriveStakingOv
api.derive.session.indexes(),
api.derive.staking.validators()
]).pipe(
switchMap(([indexes, { nextElected, validators }]) =>
combineLatest([
of({ ...indexes, nextElected, validators }),
api.query.staking.erasRewardPoints
? api.query.staking.erasRewardPoints<EraRewardPoints>(indexes.activeEra)
: api.query.staking.currentEraPointsEarned
? retrievePointsPrev(api, nextElected)
: of(api.registry.createType('EraRewardPoints'))
])
),
map(([info, eraPoints]): DeriveStakingOverview => ({
...info, eraPoints
map(([indexes, { nextElected, validators }]): DeriveStakingOverview => ({
...indexes,
nextElected,
validators
}))
));
}
@@ -5,14 +5,13 @@
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveOwnExposure } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
export function ownExposure (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean | BN | number) => Observable<DeriveOwnExposure[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean | BN | number): Observable<DeriveOwnExposure[]> => {
export function ownExposure (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveOwnExposure[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveOwnExposure[]> => {
return api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) =>
eras.length
@@ -5,14 +5,13 @@
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveStakerSlashes } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
export function ownSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean | BN | number) => Observable<DeriveStakerSlashes[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean | BN | number): Observable<DeriveStakerSlashes[]> => {
export function ownSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveStakerSlashes[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveStakerSlashes[]> => {
return api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) =>
eras.length
@@ -30,9 +29,7 @@ export function ownSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | strin
era,
total: optVal.isSome
? optVal.unwrap()[1]
: optNom.isSome
? optNom.unwrap()
: api.registry.createType('Balance')
: optNom.unwrapOrDefault()
}))
)
);
+25 -14
View File
@@ -55,7 +55,7 @@ function retrieveCurr (api: ApiInterfaceRx, stashId: AccountId): Observable<Mult
);
}
function retrieveController (api: ApiInterfaceRx, stashId: AccountId, [queuedKeys, [controllerIdOpt, nominatorsOpt, rewardDestination, validatorPrefs, nextKeys, exposure]]: [Vec<ITuple<[AccountId, Keys]>>, MultiResult]): Observable<DeriveStakingQuery> {
function retrieveController (api: ApiInterfaceRx, stashId: AccountId, queuedKeys: Vec<ITuple<[AccountId, Keys]>>, [controllerIdOpt, nominatorsOpt, rewardDestination, validatorPrefs, nextKeys, exposure]: MultiResult): Observable<DeriveStakingQuery> {
const controllerId = controllerIdOpt.unwrapOr(null);
const nominators = nominatorsOpt.unwrapOr(null);
@@ -82,30 +82,41 @@ function retrieveController (api: ApiInterfaceRx, stashId: AccountId, [queuedKey
: of({ accountId: stashId, nextSessionIds: [], sessionIds: [] });
}
/**
* @description From a stash, retrieve the controllerId and all relevant details
*/
export function query (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DeriveStakingQuery> {
return memo((accountId: Uint8Array | string): Observable<DeriveStakingQuery> => {
export function queryWithQueued (api: ApiInterfaceRx): (accountId: Uint8Array | string, queuedKeys: Vec<ITuple<[AccountId, Keys]>>) => Observable<DeriveStakingQuery> {
return memo((accountId: Uint8Array | string, queuedKeys: Vec<ITuple<[AccountId, Keys]>>): Observable<DeriveStakingQuery> => {
const stashId = api.registry.createType('AccountId', accountId);
return combineLatest([
api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>(),
return (
api.query.staking.erasStakers
? retrieveCurr(api, stashId)
: retrievePrev(api, stashId)
]).pipe(
).pipe(
switchMap((result): Observable<DeriveStakingQuery> =>
retrieveController(api, stashId, result)
retrieveController(api, stashId, queuedKeys, result)
)
);
});
}
export function queryMulti (api: ApiInterfaceRx): (...accountIds: (Uint8Array | string)[]) => Observable<DeriveStakingQuery[]> {
return memo((...accountIds: (Uint8Array | string)[]): Observable<DeriveStakingQuery[]> =>
combineLatest(
accountIds.map((accountId) => api.derive.staking.query(accountId))
/**
* @description From a stash, retrieve the controllerId and all relevant details
*/
export function query (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DeriveStakingQuery> {
return memo((accountId: Uint8Array | string): Observable<DeriveStakingQuery> =>
api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>().pipe(
switchMap((queuedKeys) => api.derive.staking.queryWithQueued(accountId, queuedKeys))
)
);
}
export function queryMulti (api: ApiInterfaceRx): (accountIds: (Uint8Array | string)[]) => Observable<DeriveStakingQuery[]> {
return memo((accountIds: (Uint8Array | string)[]): Observable<DeriveStakingQuery[]> =>
accountIds.length
? api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>().pipe(
switchMap((queuedKeys) => combineLatest(
accountIds.map((acc) => api.derive.staking.queryWithQueued(acc, queuedKeys))
))
)
: of([])
);
}
@@ -3,31 +3,29 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { EraIndex } from '@polkadot/types/interfaces';
import { DeriveStakerExposure, DeriveEraValidatorExposure } from '../types';
import BN from 'bn.js';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
export function stakerExposure (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean | BN | number) => Observable<DeriveStakerExposure[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean | BN | number): Observable<DeriveStakerExposure[]> => {
export function _stakerExposure (api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[]) => Observable<DeriveStakerExposure[]> {
return memo((accountId: Uint8Array | string, eras: EraIndex[]): Observable<DeriveStakerExposure[]> => {
const stakerId = api.registry.createType('AccountId', accountId).toString();
return api.derive.staking.erasExposure(withActive).pipe(
return api.derive.staking._erasExposure(eras).pipe(
map((exposures): DeriveStakerExposure[] =>
exposures.map(({ era, nominators: allNominators, validators: allValidators }): DeriveStakerExposure => {
const isValidator = !!allValidators[stakerId];
const validators: DeriveEraValidatorExposure = {};
let nominating: [string, number][] = [];
const nominating = allNominators[stakerId] || [];
if (isValidator) {
validators[stakerId] = allValidators[stakerId];
} else if (allNominators[stakerId]) {
nominating = allNominators[stakerId];
nominating.forEach(([validatorId]): void => {
} else if (nominating) {
nominating.forEach(({ validatorId }): void => {
validators[validatorId] = allValidators[validatorId];
});
}
@@ -38,3 +36,11 @@ export function stakerExposure (api: ApiInterfaceRx): (accountId: Uint8Array | s
);
});
}
export function stakerExposure (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveStakerExposure[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveStakerExposure[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking._stakerExposure(accountId, eras))
)
);
}
@@ -3,28 +3,34 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { EraIndex } from '@polkadot/types/interfaces';
import { DeriveStakerPoints } from '../types';
import BN from 'bn.js';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
export function stakerPoints (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean | BN | number) => Observable<DeriveStakerPoints[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean | BN | number): Observable<DeriveStakerPoints[]> => {
export function _stakerPoints (api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[]) => Observable<DeriveStakerPoints[]> {
return memo((accountId: Uint8Array | string, eras: EraIndex[]): Observable<DeriveStakerPoints[]> => {
const stakerId = api.registry.createType('AccountId', accountId).toString();
return api.derive.staking.erasPoints(withActive).pipe(
return api.derive.staking._erasPoints(eras).pipe(
map((points): DeriveStakerPoints[] =>
points.map(({ era, eraPoints, validators }): DeriveStakerPoints => ({
era,
eraPoints,
points: validators[stakerId]
? validators[stakerId]
: api.registry.createType('RewardPoint')
points: validators[stakerId] || api.registry.createType('RewardPoint')
}))
)
);
});
}
export function stakerPoints (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveStakerPoints[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveStakerPoints[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking._stakerPoints(accountId, eras))
)
);
}
+141 -31
View File
@@ -3,27 +3,30 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Balance } from '@polkadot/types/interfaces';
import { DeriveEraPoints, DeriveEraPrefs, DeriveEraRewards, DeriveEraValPrefs, DeriveStakerExposure, DeriveStakerReward } from '../types';
import { AccountId, EraIndex, StakingLedger, StakingLedgerTo240 } from '@polkadot/types/interfaces';
import { DeriveEraPoints, DeriveEraPrefs, DeriveEraRewards, DeriveEraValPrefs, DeriveStakerExposure, DeriveStakerReward, DeriveStakerRewardValidator } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option } from '@polkadot/types';
import { memo } from '../util';
type Result = [DeriveEraPoints[], DeriveEraPrefs[], DeriveEraRewards[], DeriveStakerExposure[]];
const ZERO = new BN(0);
const MIN_ONE = new BN(-1);
const COMM_DIV = new BN(1_000_000_000);
const MAX_ERAS = new BN(1_000_000_000);
function parseRewards (api: ApiInterfaceRx, stakerId: string, [erasPoints, erasPrefs, erasRewards, exposures]: Result): DeriveStakerReward[] {
function parseRewards (api: ApiInterfaceRx, stashId: AccountId, [erasPoints, erasPrefs, erasRewards, exposures]: Result): DeriveStakerReward[] {
return exposures.map(({ era, isEmpty, isValidator, nominating, validators: eraValidators }): DeriveStakerReward => {
const { eraPoints, validators: allValPoints } = erasPoints.find((p) => p.era.eq(era)) || { eraPoints: new BN(0), validators: {} };
const { eraReward } = erasRewards.find((r) => r.era.eq(era)) || { eraReward: ZERO };
const { eraPoints, validators: allValPoints } = erasPoints.find((p) => p.era.eq(era)) || { eraPoints: ZERO, validators: {} };
const { eraReward } = erasRewards.find((r) => r.era.eq(era)) || { eraReward: api.registry.createType('Balance') };
const { validators: allValPrefs } = erasPrefs.find((p) => p.era.eq(era)) || { validators: {} as DeriveEraValPrefs };
const validators: Record<string, Balance> = {};
let total = ZERO;
const validators: Record<string, DeriveStakerRewardValidator> = {};
const stakerId = stashId.toString();
Object.entries(eraValidators).forEach(([validatorId, exposure]): void => {
const valPoints = allValPoints[validatorId] || ZERO;
@@ -47,46 +50,153 @@ function parseRewards (api: ApiInterfaceRx, stakerId: string, [erasPoints, erasP
}
value = avail.sub(valCut).mul(staked).div(expTotal).add(validatorId === stakerId ? valCut : ZERO);
total = total.add(value);
}
validators[validatorId] = api.registry.createType('Balance', value);
validators[validatorId] = {
total: api.registry.createType('Balance', avail),
value: api.registry.createType('Balance', value)
};
});
return {
era,
eraReward,
isEmpty,
isValidator,
nominating,
total: api.registry.createType('Balance', total),
validators
};
});
}
export function stakerRewards (api: ApiInterfaceRx): (accountId: Uint8Array | string, startEra: BN | number) => Observable<DeriveStakerReward[]> {
return memo((accountId: Uint8Array | string, startEra: BN | number): Observable<DeriveStakerReward[]> => {
const stakerId = api.registry.createType('AccountId', accountId).toString();
function uniqValidators (rewards: DeriveStakerReward[]): string[] {
const uniq: string[] = [];
return combineLatest([
api.derive.staking.erasPoints(startEra),
api.derive.staking.erasPrefs(startEra),
api.derive.staking.erasRewards(startEra),
api.derive.staking.stakerExposure(stakerId, startEra)
]).pipe(
map((result): DeriveStakerReward[] =>
parseRewards(api, stakerId, result)
)
);
rewards.forEach(({ validators }): void => {
Object.keys(validators).forEach((validatorId): void => {
if (!uniq.includes(validatorId)) {
uniq.push(validatorId);
}
});
});
return uniq;
}
export function stakerRewardsMulti (api: ApiInterfaceRx): (...params: [Uint8Array | string, BN | number][]) => Observable<DeriveStakerReward[][]> {
return memo((...params: [Uint8Array | string, BN | number][]): Observable<DeriveStakerReward[][]> =>
combineLatest(
params.map(([accountId, startEra]) =>
api.derive.staking.stakerRewards(accountId, startEra)
)
function isOldLedger (ledger?: StakingLedger | StakingLedgerTo240): ledger is StakingLedgerTo240 {
return !!(ledger as StakingLedgerTo240)?.lastReward;
}
function filterEra (era: EraIndex, stakingLedger: StakingLedger): boolean {
return isOldLedger(stakingLedger)
? era.gt(stakingLedger.lastReward.unwrapOr(MIN_ONE))
: !stakingLedger.claimedRewards.some((e) => e.eq(era));
}
function filterEras (eras: EraIndex[], stakingLedger: StakingLedger): EraIndex[] {
return eras.filter((era) => filterEra(era, stakingLedger));
}
function filterRewards (api: ApiInterfaceRx, rewards: DeriveStakerReward[], stakingLedger: StakingLedger, withActive?: boolean): Observable<DeriveStakerReward[]> {
if (withActive) {
return of(rewards);
}
const validators = uniqValidators(rewards);
return combineLatest([
api.query.staking.migrateEra
? api.query.staking.migrateEra<Option<EraIndex>>()
: of({ unwrapOr: () => api.tx.staking.payoutStakers ? MIN_ONE : MAX_ERAS }),
api.tx.staking.payoutStakers
? api.derive.staking.queryMulti(validators)
: of([])
]).pipe(
map(([optMigrate, queryValidators]): DeriveStakerReward[] => {
const migrateEra: BN = optMigrate.unwrapOr(MIN_ONE);
return rewards
.filter(({ isEmpty }) => !isEmpty)
.filter((reward): boolean => {
if (reward.era.lte(migrateEra)) {
// we filter again here, the actual ledger may have changed, e.g. something has been claimed
return filterEra(reward.era, stakingLedger);
}
reward.isStakerPayout = true;
const rm: string[] = [];
Object.keys(reward.validators).forEach((validatorId): void => {
const index = validators.indexOf(validatorId);
if (index !== -1) {
const valLedger = queryValidators[index].stakingLedger;
if (valLedger?.claimedRewards.some((era) => reward.era.eq(era))) {
rm.push(validatorId);
}
}
});
rm.forEach((validatorId): void => {
delete reward.validators[validatorId];
});
return true;
})
.filter(({ validators }) => Object.keys(validators).length !== 0)
.map((reward) => ({
...reward,
nominators: reward.nominating.filter(({ validatorId }) => !!reward.validators[validatorId])
}));
})
);
}
export function _stakerRewards (api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[], withActive?: boolean) => Observable<DeriveStakerReward[]> {
return memo((accountId: Uint8Array | string, _eras: EraIndex[], withActive?: boolean): Observable<DeriveStakerReward[]> =>
api.derive.staking.query(accountId).pipe(
switchMap(({ stakingLedger, stashId }): Observable<DeriveStakerReward[]> => {
if (!stashId || !stakingLedger) {
return of([]);
}
const eras = withActive
? _eras
: filterEras(_eras, stakingLedger);
return combineLatest([
api.derive.staking._erasPoints(eras),
api.derive.staking._erasPrefs(eras),
api.derive.staking._erasRewards(eras),
api.derive.staking._stakerExposure(stashId, eras)
]).pipe(
switchMap((result): Observable<DeriveStakerReward[]> =>
filterRewards(api, parseRewards(api, stashId, result), stakingLedger, withActive)
)
);
})
)
);
}
export function stakerRewards (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveStakerReward[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveStakerReward[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking._stakerRewards(accountId, eras, withActive))
)
);
}
export function stakerRewardsMulti (api: ApiInterfaceRx): (accountIds: (Uint8Array | string)[], withActive?: boolean) => Observable<DeriveStakerReward[][]> {
return memo((accountIds: (Uint8Array | string)[], withActive?: boolean): Observable<DeriveStakerReward[][]> =>
accountIds.length
? api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) =>
combineLatest(accountIds.map((acc) => api.derive.staking._stakerRewards(acc, eras, withActive)))
)
)
: of([])
);
}
@@ -3,19 +3,19 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { EraIndex } from '@polkadot/types/interfaces';
import { DeriveStakerSlashes } from '../types';
import BN from 'bn.js';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
export function stakerSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean | BN | number) => Observable<DeriveStakerSlashes[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean | BN | number): Observable<DeriveStakerSlashes[]> => {
export function _stakerSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | string, eras: EraIndex[]) => Observable<DeriveStakerSlashes[]> {
return memo((accountId: Uint8Array | string, eras: EraIndex[]): Observable<DeriveStakerSlashes[]> => {
const stakerId = api.registry.createType('AccountId', accountId).toString();
return api.derive.staking.erasSlashes(withActive).pipe(
return api.derive.staking._erasSlashes(eras).pipe(
map((slashes): DeriveStakerSlashes[] =>
slashes.map(({ era, nominators, validators }): DeriveStakerSlashes => ({
era,
@@ -25,3 +25,11 @@ export function stakerSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | st
);
});
}
export function stakerSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveStakerSlashes[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveStakerSlashes[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking._stakerSlashes(accountId, eras))
)
);
}
+17 -7
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, Balance, EraIndex, EraRewardPoints, Exposure, Keys, RewardDestination, RewardPoint, StakingLedger, ValidatorPrefs } from '@polkadot/types/interfaces';
import { AccountId, Balance, EraIndex, Exposure, Keys, RewardDestination, RewardPoint, StakingLedger, ValidatorPrefs } from '@polkadot/types/interfaces';
import { DeriveSessionIndexes } from '../session/types';
import BN from 'bn.js';
@@ -41,7 +41,7 @@ export interface DeriveStakerPoints {
points: RewardPoint;
}
export type DeriveEraNominatorExposure = Record<string, [string, number][]>;
export type DeriveEraNominatorExposure = Record<string, DeriveEraExposureNominating[]>;
export type DeriveEraValidatorExposure = Record<string, Exposure>;
@@ -59,21 +59,32 @@ export interface DeriveOwnExposure {
export type DeriveOwnSlashes = DeriveStakerSlashes;
export interface DeriveEraExposureNominating {
validatorId: string;
validatorIndex: number;
}
export interface DeriveStakerExposure {
era: EraIndex;
isEmpty: boolean;
isValidator: boolean;
nominating: [string, number][];
nominating: DeriveEraExposureNominating[];
validators: DeriveEraValidatorExposure;
}
export interface DeriveStakerRewardValidator {
total: Balance;
value: Balance;
}
export interface DeriveStakerReward {
era: EraIndex;
eraReward: Balance;
isStakerPayout?: boolean;
isEmpty: boolean;
isValidator: boolean;
nominating: [string, number][];
validators: Record<string, Balance>;
total: Balance;
nominating: DeriveEraExposureNominating[];
validators: Record<string, DeriveStakerRewardValidator>;
}
export interface DeriveStakerSlashes {
@@ -115,7 +126,6 @@ export interface DeriveStakingAccount extends DeriveStakingQuery {
}
export interface DeriveStakingOverview extends DeriveSessionIndexes {
eraPoints: EraRewardPoints;
nextElected: AccountId[];
validators: AccountId[];
}
@@ -8,7 +8,6 @@ import { DeriveStakingValidators } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { StorageKey } from '@polkadot/types';
import { memo } from '../util';
@@ -18,9 +17,7 @@ export function nextElected (api: ApiInterfaceRx): () => Observable<AccountId[]>
? api.derive.session.indexes().pipe(
// only populate for next era in the last session, so track both here - entries are not
// subscriptions, so we need a trigger - currentIndex acts as that trigger to refresh
switchMap(({ currentEra }): Observable<StorageKey[]> =>
api.query.staking.erasStakers.keys(currentEra)
),
switchMap(({ currentEra }) => api.query.staking.erasStakers.keys(currentEra)),
map((keys): AccountId[] =>
keys.map((key): AccountId => key.args[1] as AccountId)
)
+2 -2
View File
@@ -59,11 +59,11 @@ export function signingInfo (api: ApiInterfaceRx): (address: string, nonce?: Any
]).pipe(
map(([nonce, header]) => ({
header,
nonce,
mortalLength: MORTAL_PERIOD
.div(api.consts.babe?.expectedBlockTime || api.consts.timestamp?.minimumPeriod.muln(2) || FALLBACK_PERIOD)
.add(MAX_FINALITY_LAG)
.toNumber()
.toNumber(),
nonce
}))
);
}
@@ -22,10 +22,10 @@ export default class HeaderExtended extends _Header {
constructor (registry: Registry, header?: Header, sessionValidators?: AccountId[]) {
super(registry, header);
this.#author = this.extractAuthor(sessionValidators);
this.#author = this._extractAuthor(sessionValidators);
}
private extractAuthor (sessionValidators: AccountId[] = []): AccountId | undefined {
private _extractAuthor (sessionValidators: AccountId[] = []): AccountId | undefined {
const [pitem] = this.digest.logsWith('PreRuntime');
// extract from the substrate 2.0 PreRuntime digest
@@ -21,5 +21,6 @@ export function approvalFlagsToBools (flags: Vec<ApprovalFlag> | ApprovalFlag[])
// slice off trailing "false" values, as in substrate
const lastApproval: number = bools.lastIndexOf(true);
return lastApproval >= 0 ? bools.slice(0, lastApproval + 1) : [];
}
+12 -12
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api",
"version": "1.9.1",
"version": "1.10.1",
"description": "Promise and RxJS wrappers around the Polkadot JS RPC",
"main": "index.js",
"keywords": [
@@ -27,20 +27,20 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api#readme",
"dependencies": {
"@babel/runtime": "^7.9.2",
"@polkadot/api-derive": "1.9.1",
"@polkadot/keyring": "^2.7.1",
"@polkadot/metadata": "1.9.1",
"@polkadot/rpc-core": "1.9.1",
"@polkadot/rpc-provider": "1.9.1",
"@polkadot/types": "1.9.1",
"@polkadot/types-known": "1.9.1",
"@polkadot/util": "^2.7.1",
"@polkadot/util-crypto": "^2.7.1",
"@polkadot/api-derive": "1.10.1",
"@polkadot/keyring": "^2.8.1",
"@polkadot/metadata": "1.10.1",
"@polkadot/rpc-core": "1.10.1",
"@polkadot/rpc-provider": "1.10.1",
"@polkadot/types": "1.10.1",
"@polkadot/types-known": "1.10.1",
"@polkadot/util": "^2.8.1",
"@polkadot/util-crypto": "^2.8.1",
"bn.js": "^5.1.1",
"eventemitter3": "^4.0.0",
"rxjs": "^6.5.4"
"rxjs": "^6.5.5"
},
"devDependencies": {
"@polkadot/keyring": "^2.7.1"
"@polkadot/keyring": "^2.8.1"
}
}
+36 -16
View File
@@ -10,7 +10,7 @@ import { AccountData, BalanceLock, ReleasesBalances } from '@polkadot/types/inte
import { ProposalIndex, Votes } from '@polkadot/types/interfaces/collective';
import { AuthorityId, RawVRFOutput } from '@polkadot/types/interfaces/consensus';
import { CodeHash, ContractInfo, Gas, PrefabWasmModule, Schedule } from '@polkadot/types/interfaces/contracts';
import { PropIndex, Proposal, ProxyState, ReferendumIndex, ReferendumInfo, Voting } from '@polkadot/types/interfaces/democracy';
import { PreimageStatus, PropIndex, Proposal, ProxyState, ReferendumIndex, ReferendumInfo, Voting } from '@polkadot/types/interfaces/democracy';
import { VoteThreshold } from '@polkadot/types/interfaces/elections';
import { SetId, StoredPendingChange, StoredState } from '@polkadot/types/interfaces/grandpa';
import { RegistrarInfo, Registration } from '@polkadot/types/interfaces/identity';
@@ -18,6 +18,7 @@ import { AuthIndex } from '@polkadot/types/interfaces/imOnline';
import { DeferredOffenceOf, Kind, OffenceDetails, OpaqueTimeSlot, ReportIdOf } from '@polkadot/types/interfaces/offences';
import { ActiveRecovery, RecoveryConfig } from '@polkadot/types/interfaces/recovery';
import { AccountId, AccountIndex, Balance, BalanceOf, BlockNumber, Hash, KeyTypeId, Moment, Perbill, ValidatorId, Weight } from '@polkadot/types/interfaces/runtime';
import { Scheduled, TaskAddress } from '@polkadot/types/interfaces/scheduler';
import { Keys, SessionIndex } from '@polkadot/types/interfaces/session';
import { Bid, BidKind, SocietyVote, StrikeCount, VouchingStatus } from '@polkadot/types/interfaces/society';
import { ActiveEraInfo, ElectionResult, ElectionStatus, EraIndex, EraRewardPoints, Exposure, Forcing, Nominations, PhragmenScore, ReleasesStaking, RewardDestination, SlashingSpans, SpanIndex, SpanRecord, StakingLedger, UnappliedSlash, ValidatorPrefs } from '@polkadot/types/interfaces/staking';
@@ -70,6 +71,13 @@ declare module '@polkadot/api/types/storage' {
* if per-block initialization has already been called for current block.
**/
initialized: AugmentedQuery<ApiType, () => Observable<Option<MaybeVrf>>> & QueryableStorageEntry<ApiType>;
/**
* How late the current block is compared to its parent.
* This entry is populated as part of block execution and is cleaned up
* on block finalization. Querying this storage entry outside of block
* execution context should always yield zero.
**/
lateness: AugmentedQuery<ApiType, () => Observable<BlockNumber>> & QueryableStorageEntry<ApiType>;
/**
* Next epoch randomness.
**/
@@ -195,10 +203,6 @@ declare module '@polkadot/api/types/storage' {
* Those who have locked a deposit.
**/
depositOf: AugmentedQuery<ApiType, (arg: PropIndex | AnyNumber | Uint8Array) => Observable<Option<ITuple<[BalanceOf, Vec<AccountId>]>>>> & QueryableStorageEntry<ApiType>;
/**
* Queue of successful referenda to be dispatched. Stored ordered by block number.
**/
dispatchQueue: AugmentedQuery<ApiType, () => Observable<Vec<ITuple<[BlockNumber, Hash, ReferendumIndex]>>>> & QueryableStorageEntry<ApiType>;
/**
* True if the last referendum tabled was submitted externally. False if it was a public
* proposal.
@@ -225,7 +229,7 @@ declare module '@polkadot/api/types/storage' {
* Map of hashes to the proposal preimage, along with who registered it and their deposit.
* The block number is the block at which it was deposited.
**/
preimages: AugmentedQuery<ApiType, (arg: Hash | string | Uint8Array) => Observable<Option<ITuple<[Bytes, AccountId, BalanceOf, BlockNumber]>>>> & QueryableStorageEntry<ApiType>;
preimages: AugmentedQuery<ApiType, (arg: Hash | string | Uint8Array) => Observable<Option<PreimageStatus>>> & QueryableStorageEntry<ApiType>;
/**
* Who is able to vote for whom. Value is the fund-holding account, key is the
* vote-transaction-sending account.
@@ -411,6 +415,17 @@ declare module '@polkadot/api/types/storage' {
**/
recoverable: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<RecoveryConfig>>> & QueryableStorageEntry<ApiType>;
};
scheduler: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* Items to be executed, indexed by the block number that they should be executed on.
**/
agenda: AugmentedQuery<ApiType, (arg: BlockNumber | AnyNumber | Uint8Array) => Observable<Vec<Option<Scheduled>>>> & QueryableStorageEntry<ApiType>;
/**
* Lookup from identity to the block number and index of the task.
**/
lookup: AugmentedQuery<ApiType, (arg: Bytes | string | Uint8Array) => Observable<Option<TaskAddress>>> & QueryableStorageEntry<ApiType>;
};
session: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
@@ -538,7 +553,7 @@ declare module '@polkadot/api/types/storage' {
canceledSlashPayout: AugmentedQuery<ApiType, () => Observable<BalanceOf>> & QueryableStorageEntry<ApiType>;
/**
* The current era index.
* This is the latest planned era, depending on how session module queues the validator
* This is the latest planned era, depending on how the Session pallet queues the validator
* set, it might be active or not.
**/
currentEra: AugmentedQuery<ApiType, () => Observable<Option<EraIndex>>> & QueryableStorageEntry<ApiType>;
@@ -565,7 +580,7 @@ declare module '@polkadot/api/types/storage' {
erasStakers: AugmentedQueryDoubleMap<ApiType, (key1: EraIndex | AnyNumber | Uint8Array, key2: AccountId | string | Uint8Array) => Observable<Exposure>> & QueryableStorageEntry<ApiType>;
/**
* Clipped Exposure of validator at era.
* This is similar to [`ErasStakers`] but number of nominators exposed is reduce to the
* This is similar to [`ErasStakers`] but number of nominators exposed is reduced to the
* `T::MaxNominatorRewardedPerValidator` biggest stakers.
* (Note: the field `total` and `own` of the exposure remains unchanged).
* This is used to limit the i/o cost for the nominator payout.
@@ -575,7 +590,7 @@ declare module '@polkadot/api/types/storage' {
**/
erasStakersClipped: AugmentedQueryDoubleMap<ApiType, (key1: EraIndex | AnyNumber | Uint8Array, key2: AccountId | string | Uint8Array) => Observable<Exposure>> & QueryableStorageEntry<ApiType>;
/**
* The session index at which the era start for the last `HISTORY_DEPTH` eras
* The session index at which the era start for the last `HISTORY_DEPTH` eras.
**/
erasStartSessionIndex: AugmentedQuery<ApiType, (arg: EraIndex | AnyNumber | Uint8Array) => Observable<Option<SessionIndex>>> & QueryableStorageEntry<ApiType>;
/**
@@ -584,7 +599,7 @@ declare module '@polkadot/api/types/storage' {
**/
erasTotalStake: AugmentedQuery<ApiType, (arg: EraIndex | AnyNumber | Uint8Array) => Observable<BalanceOf>> & QueryableStorageEntry<ApiType>;
/**
* Similarly to `ErasStakers` this holds the preferences of validators.
* Similar to `ErasStakers`, this holds the preferences of validators.
* This is keyed first by the era index to allow bulk deletion and then the stash account.
* Is it removed after `HISTORY_DEPTH` eras.
**/
@@ -599,11 +614,11 @@ declare module '@polkadot/api/types/storage' {
**/
forceEra: AugmentedQuery<ApiType, () => Observable<Forcing>> & QueryableStorageEntry<ApiType>;
/**
* Number of era to keep in history.
* Information is kept for eras in `[current_era - history_depth; current_era]
* Must be more than the number of era delayed by session otherwise.
* i.e. active era must always be in history.
* i.e. `active_era > current_era - history_depth` must be guaranteed.
* Number of eras to keep in history.
* Information is kept for eras in `[current_era - history_depth; current_era]`.
* Must be more than the number of eras delayed by session otherwise.
* I.e. active era must always be in history.
* I.e. `active_era > current_era - history_depth` must be guaranteed.
**/
historyDepth: AugmentedQuery<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
/**
@@ -613,13 +628,18 @@ declare module '@polkadot/api/types/storage' {
**/
invulnerables: AugmentedQuery<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
/**
* True if the current planned session is final.
* True if the current **planned** session is final. Note that this does not take era
* forcing into account.
**/
isCurrentSessionFinal: AugmentedQuery<ApiType, () => Observable<bool>> & QueryableStorageEntry<ApiType>;
/**
* Map from all (unlocked) "controller" accounts to the info regarding the staking.
**/
ledger: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<StakingLedger>>> & QueryableStorageEntry<ApiType>;
/**
* The era where we migrated from Lazy Payouts to Simple Payouts
**/
migrateEra: AugmentedQuery<ApiType, () => Observable<Option<EraIndex>>> & QueryableStorageEntry<ApiType>;
/**
* Minimum number of staking participants before emergency conditions are imposed.
**/
+5 -1
View File
@@ -18,7 +18,7 @@ import { RuntimeDispatchInfo } from '@polkadot/types/interfaces/payment';
import { RpcMethods } from '@polkadot/types/interfaces/rpc';
import { AccountId, BlockNumber, H256, Hash, Header, Index, Justification, KeyValue, SignedBlock, StorageData } from '@polkadot/types/interfaces/runtime';
import { RuntimeVersion } from '@polkadot/types/interfaces/state';
import { ChainProperties, Health, NetworkState, NodeRole, PeerInfo } from '@polkadot/types/interfaces/system';
import { ChainProperties, ChainType, Health, NetworkState, NodeRole, PeerInfo } from '@polkadot/types/interfaces/system';
import { Observable } from 'rxjs';
declare module '@polkadot/rpc-core/types.jsonrpc' {
@@ -242,6 +242,10 @@ declare module '@polkadot/rpc-core/types.jsonrpc' {
* Retrieves the chain
**/
chain: AugmentedRpc<() => Observable<Text>>;
/**
* Retrieves the chain type
**/
chainType: AugmentedRpc<() => Observable<ChainType>>;
/**
* Return health status of the node
**/
+35 -2
View File
@@ -248,6 +248,10 @@ declare module '@polkadot/api/types/submittable' {
* # </weight>
**/
emergencyCancel: AugmentedSubmittable<(refIndex: ReferendumIndex | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Enact a proposal from a referendum. For now we just make the weight be the maximum.
**/
enactProposal: AugmentedSubmittable<(proposalHash: Hash | string | Uint8Array, index: ReferendumIndex | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Schedule a referendum to be tabled once it is legal to schedule an external
* referendum.
@@ -1325,7 +1329,8 @@ declare module '@polkadot/api/types/submittable' {
* Use this if there are additional funds in your stash account that you wish to bond.
* Unlike [`bond`] or [`unbond`] this function does not impose any limitation on the amount
* that can be added.
* The dispatch origin for this call must be _Signed_ by the stash, not the controller.
* The dispatch origin for this call must be _Signed_ by the stash, not the controller and
* it can be only called when [`EraElectionStatus`] is `Closed`.
* Emits `Bonded`.
* # <weight>
* - Independent of the arguments. Insignificant complexity.
@@ -1347,6 +1352,7 @@ declare module '@polkadot/api/types/submittable' {
* Declare no desire to either validate or nominate.
* Effects will be felt at the beginning of the next era.
* The dispatch origin for this call must be _Signed_ by the controller, not the stash.
* And, it can be only called when [`EraElectionStatus`] is `Closed`.
* # <weight>
* - Independent of the arguments. Insignificant complexity.
* - Contains one read.
@@ -1382,8 +1388,10 @@ declare module '@polkadot/api/types/submittable' {
forceUnstake: AugmentedSubmittable<(stash: AccountId | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Declare the desire to nominate `targets` for the origin controller.
* Effects will be felt at the beginning of the next era.
* Effects will be felt at the beginning of the next era. This can only be called when
* [`EraElectionStatus`] is `Closed`.
* The dispatch origin for this call must be _Signed_ by the controller, not the stash.
* And, it can be only called when [`EraElectionStatus`] is `Closed`.
* # <weight>
* - The transaction's complexity is proportional to the size of `targets`,
* which is capped at CompactAssignments::LIMIT.
@@ -1392,6 +1400,9 @@ declare module '@polkadot/api/types/submittable' {
**/
nominate: AugmentedSubmittable<(targets: Vec<LookupSource> | (LookupSource | Address | AccountId | AccountIndex | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>>;
/**
* **This extrinsic will be removed after `MigrationEra + HistoryDepth` has passed, giving
* opportunity for users to claim all rewards before moving to Simple Payouts. After this
* time, you should use `payout_stakers` instead.**
* Make one nominator's payout for one era.
* - `who` is the controller account of the nominator to pay out.
* - `era` may not be lower than one following the most recently paid era. If it is higher,
@@ -1417,6 +1428,23 @@ declare module '@polkadot/api/types/submittable' {
**/
payoutNominator: AugmentedSubmittable<(era: EraIndex | AnyNumber | Uint8Array, validators: Vec<ITuple<[AccountId, u32]>> | ([AccountId | string | Uint8Array, u32 | AnyNumber | Uint8Array])[]) => SubmittableExtrinsic<ApiType>>;
/**
* Pay out all the stakers behind a single validator for a single era.
* - `validator_stash` is the stash account of the validator. Their nominators, up to
* `T::MaxNominatorRewardedPerValidator`, will also receive their rewards.
* - `era` may be any era between `[current_era - history_depth; current_era]`.
* The origin of this call must be _Signed_. Any account can call this function, even if
* it is not one of the stakers.
* This can only be called when [`EraElectionStatus`] is `Closed`.
* # <weight>
* - Time complexity: at most O(MaxNominatorRewardedPerValidator).
* - Contains a limited number of reads and writes.
* # </weight>
**/
payoutStakers: AugmentedSubmittable<(validatorStash: AccountId | string | Uint8Array, era: EraIndex | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* **This extrinsic will be removed after `MigrationEra + HistoryDepth` has passed, giving
* opportunity for users to claim all rewards before moving to Simple Payouts. After this
* time, you should use `payout_stakers` instead.**
* Make one validator's payout for one era.
* - `who` is the controller account of the validator to pay out.
* - `era` may not be lower than one following the most recently paid era. If it is higher,
@@ -1440,6 +1468,8 @@ declare module '@polkadot/api/types/submittable' {
reapStash: AugmentedSubmittable<(stash: AccountId | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Rebond a portion of the stash scheduled to be unlocked.
* The dispatch origin must be signed by the controller, and it can be only called when
* [`EraElectionStatus`] is `Closed`.
* # <weight>
* - Time complexity: O(1). Bounded by `MAX_UNLOCKING_CHUNKS`.
* - Storage changes: Can't increase storage, only decrease it.
@@ -1554,6 +1584,7 @@ declare module '@polkadot/api/types/submittable' {
* can co-exists at the same time. In that case, [`Call::withdraw_unbonded`] need
* to be called first to remove some of the chunks (if possible).
* The dispatch origin for this call must be _Signed_ by the controller, not the stash.
* And, it can be only called when [`EraElectionStatus`] is `Closed`.
* Emits `Unbonded`.
* See also [`Call::withdraw_unbonded`].
* # <weight>
@@ -1571,6 +1602,7 @@ declare module '@polkadot/api/types/submittable' {
* Declare the desire to validate for the origin controller.
* Effects will be felt at the beginning of the next era.
* The dispatch origin for this call must be _Signed_ by the controller, not the stash.
* And, it can be only called when [`EraElectionStatus`] is `Closed`.
* # <weight>
* - Independent of the arguments. Insignificant complexity.
* - Contains a limited number of reads.
@@ -1583,6 +1615,7 @@ declare module '@polkadot/api/types/submittable' {
* This essentially frees up that balance to be used by the stash account to do
* whatever it wants.
* The dispatch origin for this call must be _Signed_ by the controller, not the stash.
* And, it can be only called when [`EraElectionStatus`] is `Closed`.
* Emits `Withdrawn`.
* See also [`Call::unbond`].
* # <weight>
+61 -66
View File
@@ -53,7 +53,7 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
protected _consts: Constants = {} as Constants;
protected _derive?: ReturnType<Decorate<ApiType>['decorateDerive']>;
protected _derive?: ReturnType<Decorate<ApiType>['_decorateDerive']>;
protected _extrinsics?: SubmittableExtrinsics<ApiType>;
@@ -105,7 +105,7 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
* implemented by transforming the Observable to Stream/Iterator/Kefir/Bacon
* via `decorateMethod`.
*/
protected decorateMethod: DecorateMethod<ApiType>;
protected _decorateMethod: DecorateMethod<ApiType>;
/**
* @description Create an instance of the class
@@ -134,7 +134,7 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
? options.source._rpcCore.provider.clone()
: (options.provider || new WsProvider());
this.decorateMethod = decorateMethod;
this._decorateMethod = decorateMethod;
this._options = options;
this._type = type;
this._rpcCore = new RpcCore(this.registry, thisProvider, this._options.rpc);
@@ -168,23 +168,23 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
const decoratedMeta = new DecoratedMeta(this.registry, metadata);
if (fromEmpty || !this._extrinsics) {
this._extrinsics = this.decorateExtrinsics(decoratedMeta.tx, this.decorateMethod);
this._rx.tx = this.decorateExtrinsics(decoratedMeta.tx, this.rxDecorateMethod);
this._extrinsics = this._decorateExtrinsics(decoratedMeta.tx, this._decorateMethod);
this._rx.tx = this._decorateExtrinsics(decoratedMeta.tx, this._rxDecorateMethod);
} else {
augmentObject('tx', this.decorateExtrinsics(decoratedMeta.tx, this.decorateMethod), this._extrinsics, false);
augmentObject('', this.decorateExtrinsics(decoratedMeta.tx, this.rxDecorateMethod), this._rx.tx, false);
augmentObject('tx', this._decorateExtrinsics(decoratedMeta.tx, this._decorateMethod), this._extrinsics, false);
augmentObject('', this._decorateExtrinsics(decoratedMeta.tx, this._rxDecorateMethod), this._rx.tx, false);
}
// this API
augmentObject('query', this.decorateStorage(decoratedMeta.query, this.decorateMethod), this._query, fromEmpty);
augmentObject('query', this._decorateStorage(decoratedMeta.query, this._decorateMethod), this._query, fromEmpty);
augmentObject('consts', decoratedMeta.consts, this._consts, fromEmpty);
// rx
augmentObject('', this.decorateStorage(decoratedMeta.query, this.rxDecorateMethod), this._rx.query, fromEmpty);
augmentObject('', this._decorateStorage(decoratedMeta.query, this._rxDecorateMethod), this._rx.query, fromEmpty);
augmentObject('', decoratedMeta.consts, this._rx.consts, fromEmpty);
}
private decorateFunctionMeta (input: MetaDecoration, output: MetaDecoration): MetaDecoration {
private _decorateFunctionMeta (input: MetaDecoration, output: MetaDecoration): MetaDecoration {
output.meta = input.meta;
output.method = input.method;
output.section = input.section;
@@ -201,7 +201,7 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
// manner to cater for both old and new:
// - when the number of entries are 0, only remove the ones with isOptional (account & contracts)
// - when non-zero, remove anything that is not in the array (we don't do this)
protected async filterRpc (): Promise<void> {
protected async _filterRpc (): Promise<void> {
let methods: string[];
try {
@@ -212,13 +212,13 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
methods = [];
}
this.filterRpcMethods(methods);
this._filterRpcMethods(methods);
}
protected filterRpcMethods (exposed: string[]): void {
protected _filterRpcMethods (exposed: string[]): void {
const hasResults = exposed.length !== 0;
const allKnown = [...this._rpcCore.mapping.entries()];
const allKeys = allKnown.reduce((allKeys: string[], [, { alias, method, section, pubsub }]): string[] => {
const allKeys = allKnown.reduce((allKeys: string[], [, { alias, method, pubsub, section }]): string[] => {
allKeys.push(`${section}_${method}`);
if (pubsub) {
@@ -253,7 +253,7 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
});
}
protected decorateRpc<ApiType extends ApiTypes> (rpc: RpcCore, decorateMethod: DecorateMethod<ApiType>): DecoratedRpc<ApiType, RpcInterface> {
protected _decorateRpc<ApiType extends ApiTypes> (rpc: RpcCore, decorateMethod: DecorateMethod<ApiType>): DecoratedRpc<ApiType, RpcInterface> {
return rpc.sections.reduce((out, _sectionName): DecoratedRpc<ApiType, RpcInterface> => {
const sectionName = _sectionName as keyof DecoratedRpc<ApiType, RpcInterface>;
@@ -272,7 +272,7 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
}, {} as DecoratedRpc<ApiType, RpcInterface>);
}
protected decorateMulti<ApiType extends ApiTypes> (decorateMethod: DecorateMethod<ApiType>): QueryableStorageMulti<ApiType> {
protected _decorateMulti<ApiType extends ApiTypes> (decorateMethod: DecorateMethod<ApiType>): QueryableStorageMulti<ApiType> {
return decorateMethod((calls: QueryableStorageMultiArg<ApiType>[]): Observable<Codec[]> =>
this._rpcCore.state.subscribeStorage(
calls.map((arg: QueryableStorageMultiArg<ApiType>): [QueryableStorageEntry<ApiType>, ...Arg[]] =>
@@ -282,12 +282,12 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
: [arg.creator] as any)));
}
protected decorateExtrinsics<ApiType extends ApiTypes> (extrinsics: ModulesWithCalls, decorateMethod: DecorateMethod<ApiType>): SubmittableExtrinsics<ApiType> {
protected _decorateExtrinsics<ApiType extends ApiTypes> (extrinsics: ModulesWithCalls, decorateMethod: DecorateMethod<ApiType>): SubmittableExtrinsics<ApiType> {
const creator = createSubmittable(this._type, this._rx, decorateMethod);
return Object.entries(extrinsics).reduce((out, [name, section]): SubmittableExtrinsics<ApiType> => {
out[name] = Object.entries(section).reduce((out, [name, method]): SubmittableModuleExtrinsics<ApiType> => {
out[name] = this.decorateExtrinsicEntry(method, creator);
out[name] = this._decorateExtrinsicEntry(method, creator);
return out;
}, {} as SubmittableModuleExtrinsics<ApiType>);
@@ -296,17 +296,17 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
}, creator as SubmittableExtrinsics<ApiType>);
}
private decorateExtrinsicEntry<ApiType extends ApiTypes> (method: CallFunction, creator: (value: Call | Uint8Array | string) => SubmittableExtrinsic<ApiType>): SubmittableExtrinsicFunction<ApiType> {
private _decorateExtrinsicEntry<ApiType extends ApiTypes> (method: CallFunction, creator: (value: Call | Uint8Array | string) => SubmittableExtrinsic<ApiType>): SubmittableExtrinsicFunction<ApiType> {
const decorated = (...params: Arg[]): SubmittableExtrinsic<ApiType> =>
creator(method(...params));
return this.decorateFunctionMeta(method, decorated as any) as SubmittableExtrinsicFunction<ApiType>;
return this._decorateFunctionMeta(method, decorated as any) as SubmittableExtrinsicFunction<ApiType>;
}
protected decorateStorage<ApiType extends ApiTypes> (storage: Storage, decorateMethod: DecorateMethod<ApiType>): QueryableStorage<ApiType> {
protected _decorateStorage<ApiType extends ApiTypes> (storage: Storage, decorateMethod: DecorateMethod<ApiType>): QueryableStorage<ApiType> {
return Object.entries(storage).reduce((out, [name, section]): QueryableStorage<ApiType> => {
out[name] = Object.entries(section).reduce((out, [name, method]): QueryableModuleStorage<ApiType> => {
out[name] = this.decorateStorageEntry(method, decorateMethod);
out[name] = this._decorateStorageEntry(method, decorateMethod);
return out;
}, {} as QueryableModuleStorage<ApiType>);
@@ -315,13 +315,13 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
}, {} as QueryableStorage<ApiType>);
}
private decorateStorageEntry<ApiType extends ApiTypes> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>): QueryableStorageEntry<ApiType> {
private _decorateStorageEntry<ApiType extends ApiTypes> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>): QueryableStorageEntry<ApiType> {
// get the storage arguments, with DoubleMap as an array entry, otherwise spread
const getArgs = (...args: any[]): any[] => extractStorageArgs(creator, args);
// FIXME We probably want to be able to query the full list with non-subs as well
const decorated = this.hasSubscriptions && creator.iterKey && creator.meta.type.isMap && creator.meta.type.asMap.linked.isTrue
? this.decorateStorageLinked(creator, decorateMethod)
? this._decorateStorageLinked(creator, decorateMethod)
: decorateMethod((...args: any[]): Observable<Codec> => (
this.hasSubscriptions
? this._rpcCore.state
@@ -338,9 +338,6 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
decorated.at = decorateMethod((hash: Hash, arg1?: Arg, arg2?: Arg): Observable<Codec> =>
this._rpcCore.state.getStorage(getArgs(arg1, arg2), hash));
decorated.entries = decorateMethod(memo((doubleMapArg?: Arg): Observable<[StorageKey, Codec][]> =>
this.retrieveMapEntries(creator, doubleMapArg)));
decorated.hash = decorateMethod((arg1?: Arg, arg2?: Arg): Observable<Hash> =>
this._rpcCore.state.getStorageHash(getArgs(arg1, arg2)));
@@ -350,9 +347,24 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
decorated.keyPrefix = (): string =>
u8aToHex(creator.keyPrefix);
decorated.keys = decorateMethod(memo((doubleMapArg?: Arg): Observable<StorageKey[]> =>
this.retrieveMapKeys(creator, doubleMapArg)));
decorated.range = decorateMethod((range: [Hash, Hash?], arg1?: Arg, arg2?: Arg): Observable<[Hash, Codec][]> =>
this._decorateStorageRange(decorated, [arg1, arg2], range));
decorated.size = decorateMethod((arg1?: Arg, arg2?: Arg): Observable<u64> =>
this._rpcCore.state.getStorageSize(getArgs(arg1, arg2)));
// .keys() & .entries() only available on map types
if (creator.iterKey && (creator.meta.type.isMap || creator.meta.type.isDoubleMap)) {
decorated.entries = decorateMethod(
memo((doubleMapArg?: Arg): Observable<[StorageKey, Codec][]> =>
this._retrieveMapEntries(creator, doubleMapArg)));
decorated.keys = decorateMethod(
memo((doubleMapArg?: Arg): Observable<StorageKey[]> =>
this._retrieveMapKeys(creator, doubleMapArg)));
}
// only support multi where subs are available
if (this.hasSubscriptions) {
// When using double map storage function, user need to pass double map key as an array
decorated.multi = decorateMethod((args: (Arg | Arg[])[]): Observable<Codec[]> =>
@@ -360,16 +372,10 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
args.map((arg: Arg[] | Arg): [StorageEntry, Arg | Arg[]] => [creator, arg])));
}
decorated.range = decorateMethod(memo((range: [Hash, Hash?], arg1?: Arg, arg2?: Arg): Observable<[Hash, Codec][]> =>
this.decorateStorageRange(decorated, [arg1, arg2], range)));
decorated.size = decorateMethod((arg1?: Arg, arg2?: Arg): Observable<u64> =>
this._rpcCore.state.getStorageSize(getArgs(arg1, arg2)));
return this.decorateFunctionMeta(creator, decorated) as unknown as QueryableStorageEntry<ApiType>;
return this._decorateFunctionMeta(creator, decorated) as unknown as QueryableStorageEntry<ApiType>;
}
private decorateStorageRange<ApiType extends ApiTypes> (decorated: QueryableStorageEntry<ApiType>, args: [Arg?, Arg?], range: [Hash, Hash?]): Observable<[Hash, Codec][]> {
private _decorateStorageRange<ApiType extends ApiTypes> (decorated: QueryableStorageEntry<ApiType>, args: [Arg?, Arg?], range: [Hash, Hash?]): Observable<[Hash, Codec][]> {
const outputType = unwrapStorageType(decorated.creator.meta.type, decorated.creator.meta.modifier.isOptional);
return this._rpcCore.state
@@ -382,7 +388,7 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
));
}
private decorateStorageLinked<ApiType extends ApiTypes> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>): ReturnType<DecorateMethod<ApiType>> {
private _decorateStorageLinked<ApiType extends ApiTypes> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>): ReturnType<DecorateMethod<ApiType>> {
const result: Map<Codec, ITuple<[Codec, Linkage<Codec>]> | null> = new Map();
let subject: BehaviorSubject<LinkageResult>;
let head: Codec | null = null;
@@ -454,7 +460,7 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
);
}
private retrieveMapKeys ({ iterKey, meta }: StorageEntry, arg?: Arg): Observable<StorageKey[]> {
private _retrieveMapKeys ({ iterKey, meta }: StorageEntry, arg?: Arg): Observable<StorageKey[]> {
assert(iterKey && (meta.type.isMap || meta.type.isDoubleMap), 'keys can only be retrieved on maps, linked maps and double maps');
const headKey = this.createType('Raw', u8aConcat(
@@ -471,9 +477,7 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
? startSubject.pipe(
switchMap((startKey) =>
this._rpcCore.state.getKeysPaged(headKey, PAGE_SIZE_KEYS, startKey).pipe(
map((keys): StorageKey[] =>
keys.map((key) => key.decodeArgsFromMeta(meta))
)
map((keys) => keys.map((key) => key.decodeArgsFromMeta(meta)))
)
),
tap((keys): void => {
@@ -482,24 +486,18 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
: startSubject.complete();
}),
toArray(), // toArray since we want to startSubject to be completed
map((keysArr: StorageKey[][]): StorageKey[] =>
keysArr.reduce((result: StorageKey[], keys): StorageKey[] =>
result.concat(keys), []
)
)
map((keysArr: StorageKey[][]) => keysArr.reduce((result: StorageKey[], keys) => result.concat(keys), []))
)
: this._rpcCore.state.getKeys(headKey).pipe(
map((keys): StorageKey[] =>
keys.map((key) => key.decodeArgsFromMeta(meta))
)
map((keys) => keys.map((key) => key.decodeArgsFromMeta(meta)))
);
}
private retrieveMapEntries (entry: StorageEntry, arg?: Arg): Observable<[StorageKey, Codec][]> {
private _retrieveMapEntries (entry: StorageEntry, arg?: Arg): Observable<[StorageKey, Codec][]> {
const outputType = unwrapStorageType(entry.meta.type, entry.meta.modifier.isOptional);
return this.retrieveMapKeys(entry, arg).pipe(
switchMap((keys): Observable<[StorageKey[], Option<Raw>[]]> =>
return this._retrieveMapKeys(entry, arg).pipe(
switchMap((keys): Observable<[StorageKey[], Option<Raw>[][]]> =>
combineLatest([
of(keys),
from(Array(Math.ceil(keys.length / PAGE_SIZE_VALS)).fill(0)).pipe(
@@ -510,17 +508,14 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
? this._rpcCore.state.queryStorageAt<Option<Raw>[]>(keyset)
: this._rpcCore.state.subscribeStorage<Option<Raw>[]>(keyset).pipe(take(1));
}),
toArray(),
map((valsArr: Option<Raw>[][]): Option<Raw>[] =>
valsArr.reduce((result: Option<Raw>[], vals): Option<Raw>[] =>
result.concat(vals), []
)
)
toArray()
)
])
),
map(([keys, vals]): [StorageKey, Codec][] =>
keys.map((key, index): [StorageKey, Codec] => [
map(([keys, valsArr]): [StorageKey, Codec][] => {
const vals = valsArr.reduce((result: Option<Raw>[], vals) => result.concat(vals), []);
return keys.map((key, index): [StorageKey, Codec] => [
key,
this.createType(
outputType,
@@ -528,19 +523,19 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
? vals[index].unwrap().toHex()
: undefined
)
])
)
]);
})
);
}
protected decorateDeriveRx (decorateMethod: DecorateMethod<ApiType>): DeriveAllSections<'rxjs', ExactDerive> {
protected _decorateDeriveRx (decorateMethod: DecorateMethod<ApiType>): DeriveAllSections<'rxjs', ExactDerive> {
// Pull in derive from api-derive
const derive = decorateDerive(this._rx, this._options.derives);
return decorateSections<'rxjs', ExactDerive>(derive, decorateMethod);
}
protected decorateDerive (decorateMethod: DecorateMethod<ApiType>): DeriveAllSections<ApiType, ExactDerive> {
protected _decorateDerive (decorateMethod: DecorateMethod<ApiType>): DeriveAllSections<ApiType, ExactDerive> {
return decorateSections<ApiType, ExactDerive>(this._rx.derive, decorateMethod);
}
@@ -548,7 +543,7 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
* Put the `this.onCall` function of ApiRx here, because it is needed by
* `api._rx`.
*/
protected rxDecorateMethod = <Method extends AnyFunction>(method: Method): Method => {
protected _rxDecorateMethod = <Method extends AnyFunction>(method: Method): Method => {
return method;
}
}
+18 -18
View File
@@ -48,10 +48,10 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
this.registry.setKnownTypes(options.source.registry.knownTypes);
}
this._rpc = this.decorateRpc(this._rpcCore, this.decorateMethod);
this._rx.rpc = this.decorateRpc(this._rpcCore, this.rxDecorateMethod);
this._queryMulti = this.decorateMulti(this.decorateMethod);
this._rx.queryMulti = this.decorateMulti(this.rxDecorateMethod);
this._rpc = this._decorateRpc(this._rpcCore, this._decorateMethod);
this._rx.rpc = this._decorateRpc(this._rpcCore, this._rxDecorateMethod);
this._queryMulti = this._decorateMulti(this._decorateMethod);
this._rx.queryMulti = this._decorateMulti(this._rxDecorateMethod);
this._rx.signer = options.signer;
this._rpcCore.provider.on('disconnected', this.#onProviderDisconnect);
@@ -66,7 +66,7 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
}
}
protected async loadMeta (): Promise<boolean> {
protected async _loadMeta (): Promise<boolean> {
const genesisHash = await this._rpcCore.chain.getBlockHash(0).toPromise();
// on re-connection to the same chain, we don't want to re-do everything from chain again
@@ -89,14 +89,14 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
// only load from on-chain if we are not a clone (default path), alternatively
// just use the values from the source instance provided
this._runtimeMetadata = this._options.source?._isReady
? await this.metaFromSource(this._options.source)
: await this.metaFromChain(metadata);
? await this._metaFromSource(this._options.source)
: await this._metaFromChain(metadata);
return this.initFromMeta(this._runtimeMetadata);
return this._initFromMeta(this._runtimeMetadata);
}
// eslint-disable-next-line @typescript-eslint/require-await
private async metaFromSource (source: ApiBase<any>): Promise<Metadata> {
private async _metaFromSource (source: ApiBase<any>): Promise<Metadata> {
this._extrinsicType = source.extrinsicVersion;
this._runtimeVersion = source.runtimeVersion;
this._genesisHash = source.genesisHash;
@@ -112,13 +112,13 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
});
});
this.filterRpcMethods(methods);
this._filterRpcMethods(methods);
return source.runtimeMetadata;
}
// subscribe to metadata updates, inject the types on changes
private subscribeUpdates (): void {
private _subscribeUpdates (): void {
if (this.#updateSub) {
return;
}
@@ -148,7 +148,7 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
).subscribe();
}
private async metaFromChain (optMetadata: Record<string, string>): Promise<Metadata> {
private async _metaFromChain (optMetadata: Record<string, string>): Promise<Metadata> {
const [runtimeVersion, chain, chainProps] = await Promise.all([
this._rpcCore.state.getRuntimeVersion().toPromise(),
this._rpcCore.system.chain().toPromise(),
@@ -162,10 +162,10 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
// do the setup for the specific chain
this.registry.setChainProperties(chainProps);
this.registerTypes(getSpecTypes(this.registry, chain, runtimeVersion.specName, runtimeVersion.specVersion));
this.subscribeUpdates();
this._subscribeUpdates();
// filter the RPC methods (this does an rpc-methods call)
await this.filterRpc();
await this._filterRpc();
// retrieve metadata, either from chain or as pass-in via options
const metadataKey = `${this._genesisHash}-${runtimeVersion.specVersion}`;
@@ -179,7 +179,7 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
return metadata;
}
private async initFromMeta (metadata: Metadata): Promise<boolean> {
private async _initFromMeta (metadata: Metadata): Promise<boolean> {
// inject types based on metadata, if applicable
this.registerTypes(getMetadataTypes(this.registry, metadata.version));
@@ -203,8 +203,8 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
this.injectMetadata(metadata, true);
// derive is last, since it uses the decorated rx
this._rx.derive = this.decorateDeriveRx(this.rxDecorateMethod);
this._derive = this.decorateDerive(this.decorateMethod);
this._rx.derive = this._decorateDeriveRx(this._rxDecorateMethod);
this._derive = this._decorateDerive(this._decorateMethod);
return true;
}
@@ -215,7 +215,7 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
try {
const [hasMeta, cryptoReady] = await Promise.all([
this.loadMeta(),
this._loadMeta(),
this._options.initWasm === false
? Promise.resolve(true)
: cryptoWaitReady()
+1 -1
View File
@@ -93,7 +93,7 @@ export default abstract class ApiBase<ApiType extends ApiTypes> extends Init<Api
* });
* ```
*/
public get derive (): ReturnType<ApiBase<ApiType>['decorateDerive']> {
public get derive (): ReturnType<ApiBase<ApiType>['_decorateDerive']> {
return assertResult(this._derive);
}
+6 -1
View File
@@ -31,11 +31,13 @@ async function derive (api: ApiPromise): Promise<void> {
});
const fees = await api.derive.balances.fees();
console.log('fees', fees);
}
async function query (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
const intentions = await api.query.staking.bonded();
console.log('intentions:', intentions);
// api.query.*.* is well-typed
@@ -47,6 +49,7 @@ async function query (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
// It's hard to correctly type .multi. Expected: `Balance[]`, actual: Codec[].
// In the meantime, we can case with `<Balance>` (this is not available on recent chains)
const multi = await api.query.balances.freeBalance.multi<Balance>([keyring.alice.address, keyring.bob.address]);
console.log('query types:', bar, bal, bal2, override, oldBal, multi);
// check multi for unsub
@@ -71,6 +74,7 @@ async function query (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
// at queries
const events = await api.query.system.events.at('0x12345');
console.log(`Received ${events.length} events:`);
// check entries()
@@ -82,6 +86,7 @@ async function query (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
// check range types
const entries = await api.query.system.events.range(['0x12345', '0x7890']);
console.log(`Received ${entries.length} entries, ${entries.map(([hash, events]) => `${hash.toHex()}: ${events.length} events`)}`);
}
@@ -161,7 +166,7 @@ async function tx (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
});
// it handles enum inputs correctly
await api.tx.democracy.proxyVote(123, { Split: { yay: 123, nay: 456 } }).signAndSend(keyring.alice);
await api.tx.democracy.proxyVote(123, { Split: { nay: 456, yay: 123 } }).signAndSend(keyring.alice);
}
async function main (): Promise<void> {
+7 -5
View File
@@ -21,8 +21,8 @@ describe('ApiPromise', (): void => {
const aliceEd = keyring.addPair(
// eslint-disable-next-line @typescript-eslint/unbound-method
createPair({ toSS58: keyring.encodeAddress, type: 'ed25519' }, {
secretKey: hexToU8a('0xabf8e5bdbe30c65656c0a3cbd181ff8a56294a69dfedd27982aace4a7690911588dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee'),
publicKey: hexToU8a('0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee')
publicKey: hexToU8a('0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee'),
secretKey: hexToU8a('0xabf8e5bdbe30c65656c0a3cbd181ff8a56294a69dfedd27982aace4a7690911588dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee')
})
);
let provider: Mock;
@@ -56,8 +56,10 @@ describe('ApiPromise', (): void => {
const specVersion = 0;
const metadata: any = {};
const key = `${genesisHash}-${specVersion}`;
metadata[key] = rpcData;
const api = await ApiPromise.create({ provider, metadata, registry } as ApiOptions);
const api = await ApiPromise.create({ metadata, provider, registry } as ApiOptions);
expect(api.genesisHash).toBeDefined();
expect(api.runtimeMetadata).toBeDefined();
@@ -70,7 +72,7 @@ describe('ApiPromise', (): void => {
it('Create API instance without metadata and makes the runtime, rpc, state & extrinsics available', async (): Promise<void> => {
const metadata = {};
const api = await ApiPromise.create({ provider, metadata, registry });
const api = await ApiPromise.create({ metadata, provider, registry });
expect(api.genesisHash).toBeDefined();
expect(api.runtimeMetadata).toBeDefined();
@@ -87,7 +89,7 @@ describe('ApiPromise', (): void => {
super({ provider });
}
protected loadMeta (): Promise<boolean> {
protected _loadMeta (): Promise<boolean> {
throw new Error('Simulate failure to load meta');
}
}
+2 -1
View File
@@ -37,6 +37,7 @@ function extractArgs (args: any[], needsCallback: boolean): [any[], Callback<Cod
// a Promise completion tracker, wrapping an isComplete variable that ensures the promise only resolves once
function promiseTracker (resolve: (value: () => void) => void, reject: (value: Error) => void): Tracker {
let isCompleted = false;
const complete = (fn: Function, value: any): void => {
if (!isCompleted) {
isCompleted = true;
@@ -78,7 +79,7 @@ export function decorateMethod<Method extends AnyFunction> (method: Method, opti
catchError((error): Observable<never> =>
tracker.reject(error)
),
// upon the first result, resolve the with the unsub function
// upon the first result, resolve with the unsub function
tap((): void =>
tracker.resolve((): void => subscription.unsubscribe())
)
+6 -6
View File
@@ -40,11 +40,11 @@ export default class Combinator {
this.#fns.push(fn);
// Not quite 100% how to have a variable number at the front here
return (fn as Function)(...args, this.createCallback(index));
return (fn as Function)(...args, this._createCallback(index));
});
}
protected allHasFired (): boolean {
protected _allHasFired (): boolean {
if (!this.#allHasFired) {
this.#allHasFired = this.#fired.filter((hasFired): boolean => !hasFired).length === 0;
}
@@ -52,17 +52,17 @@ export default class Combinator {
return this.#allHasFired;
}
protected createCallback (index: number): (value: any) => void {
protected _createCallback (index: number): (value: any) => void {
return (value: any): void => {
this.#fired[index] = true;
this.#results[index] = value;
this.triggerUpdate();
this._triggerUpdate();
};
}
protected triggerUpdate (): void {
if (!this.#isActive || !isFunction(this.#callback) || !this.allHasFired()) {
protected _triggerUpdate (): void {
if (!this.#isActive || !isFunction(this.#callback) || !this._allHasFired()) {
return;
}
+5 -4
View File
@@ -1,8 +1,9 @@
/* eslint-disable no-dupe-class-members */
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
/* eslint-disable no-dupe-class-members */
import { Address, Call, Extrinsic, ExtrinsicEra, ExtrinsicStatus, Hash, Header, Index, RuntimeDispatchInfo } from '@polkadot/types/interfaces';
import { Callback, Codec, Constructor, IKeyringPair, Registry, SignatureOptions, ISubmittableResult } from '@polkadot/types/types';
import { ApiInterfaceRx, ApiTypes, SignerResult } from '../types';
@@ -19,7 +20,7 @@ import SubmittableResult from './Result';
interface SubmittableOptions<ApiType extends ApiTypes> {
api: ApiInterfaceRx;
apiType: ApiTypes;
decorateMethod: ApiBase<ApiType>['decorateMethod'];
decorateMethod: ApiBase<ApiType>['_decorateMethod'];
}
export default function createClass <ApiType extends ApiTypes> ({ api, apiType, decorateMethod }: SubmittableOptions<ApiType>): Constructor<SubmittableExtrinsic<ApiType>> {
@@ -237,8 +238,8 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
const payload = this.registry.createType('SignerPayload', {
...options,
address,
method: this.method,
blockNumber: header ? header.number : 0
blockNumber: header ? header.number : 0,
method: this.method
});
let result: SignerResult;
@@ -14,7 +14,7 @@ type Creator<ApiType extends ApiTypes> = (extrinsic: Call | Uint8Array | string)
let Submittable: Constructor<SubmittableExtrinsic<any>>;
export default function createSubmittable<ApiType extends ApiTypes> (apiType: ApiTypes, api: ApiInterfaceRx, decorateMethod: ApiBase<ApiType>['decorateMethod']): Creator<ApiType> {
export default function createSubmittable<ApiType extends ApiTypes> (apiType: ApiTypes, api: ApiInterfaceRx, decorateMethod: ApiBase<ApiType>['_decorateMethod']): Creator<ApiType> {
return (extrinsic: Call | Extrinsic | Uint8Array | string): SubmittableExtrinsic<ApiType> => {
// This is not great, but basically what we do here is to only require the
// class right at the point it is actually needed - delaying initialization
+7 -7
View File
@@ -18,8 +18,8 @@ describe('augmentObject', (): void => {
it('logs added/removed sections and methods', (): void => {
augmentObject(
'test',
{ foo: { f: 1, d: 1 }, bar: { b: 1 }, new: { z: 1 } },
{ foo: { f: 1, c: 1 }, bar: { a: 1, c: 1 }, baz: { a: 1 } }
{ bar: { b: 1 }, foo: { d: 1, f: 1 }, new: { z: 1 } },
{ bar: { a: 1, c: 1 }, baz: { a: 1 }, foo: { c: 1, f: 1 } }
);
expect(spy).toHaveBeenCalledWith(
@@ -35,19 +35,19 @@ describe('augmentObject', (): void => {
});
it('copies sections to the dest', (): void => {
const src = { foo: { a: 1 }, bar: { b: 1 } };
const src = { bar: { b: 1 }, foo: { a: 1 } };
expect(augmentObject('test', src, {})).toEqual(src);
});
it('adds fields to existing sections', (): void => {
const src = { foo: { a: 1 }, bar: { b: 1 } };
const dst = { foo: { b: 2 }, baz: { c: 1 } };
const src = { bar: { b: 1 }, foo: { a: 1 } };
const dst = { baz: { c: 1 }, foo: { b: 2 } };
expect(augmentObject('test', src, dst)).toEqual({
foo: { b: 2, a: 1 },
bar: { b: 1 },
baz: { c: 1 }
baz: { c: 1 },
foo: { a: 1, b: 2 }
});
});
});
+1
View File
@@ -20,6 +20,7 @@ export default function filterEvents (extHash: H256, { block: { extrinsics, head
if (status.isInBlock) {
l.warn(`block ${header.hash}: Unable to find extrinsic ${myHash} inside ${allHashes}`);
}
return;
}

Some files were not shown because too many files have changed in this diff Show More