Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f08031792 | ||
|
|
e0bde927d1 | ||
|
|
e569de520a | ||
|
|
a833dccdaf | ||
|
|
b58d772156 | ||
|
|
e5d9bbc264 | ||
|
|
3089529405 | ||
|
|
5ab24390c5 | ||
|
|
245047a41f | ||
|
|
8aa1bd5bd0 | ||
|
|
e0dde35621 | ||
|
|
9ba91a3851 | ||
|
|
351cb97667 | ||
|
|
afdb476796 | ||
|
|
3b67b65091 | ||
|
|
25580b2026 | ||
|
|
2db16e94b7 | ||
|
|
9184268c3d | ||
|
|
83a762af1e | ||
|
|
6a8e5370b6 | ||
|
|
9cd4bf7cf7 | ||
|
|
c4708dcfca | ||
|
|
041d06a6c8 | ||
|
|
2b4bd75499 | ||
|
|
c4c47a84e1 | ||
|
|
a241bd1c38 | ||
|
|
d420cede82 | ||
|
|
b869695e40 | ||
|
|
37caf4e710 | ||
|
|
134bc22463 | ||
|
|
39d142876e | ||
|
|
6d95eb418d | ||
|
|
e26a6a28ff | ||
|
|
d80d6f2a06 | ||
|
|
ff8dabb249 | ||
|
|
e7a01f9780 | ||
|
|
94938c7075 | ||
|
|
f37e729605 | ||
|
|
9cfde73ff8 | ||
|
|
f5c140d1c2 | ||
|
|
472e1022d3 | ||
|
|
f71211f5dc | ||
|
|
7e06974f1b | ||
|
|
f95384d9ff | ||
|
|
baedd5b689 | ||
|
|
9ec1cb194a | ||
|
|
d730310ea5 | ||
|
|
641fe5c380 | ||
|
|
c5a8d5e018 | ||
|
|
02d130f0a0 | ||
|
|
5554f17f05 | ||
|
|
69351ceb9e | ||
|
|
0cf9fa7405 | ||
|
|
8213fa7cb9 | ||
|
|
8ef983169f | ||
|
|
e392dd745e | ||
|
|
6b07a9c2a5 | ||
|
|
114ac59707 | ||
|
|
3c95bfe56e | ||
|
|
58de0b8b9c | ||
|
|
1f97c5e9e3 | ||
|
|
0dc46445bc |
@@ -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'
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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');
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
const { combineLatest, of } = require('rxjs');
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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<Type>
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -9,5 +9,5 @@
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "1.9.1"
|
||||
"version": "1.10.1"
|
||||
}
|
||||
|
||||
+3
-3
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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 => ({
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
@@ -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[])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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,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[]> =>
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}))
|
||||
|
||||
@@ -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))
|
||||
)
|
||||
])
|
||||
),
|
||||
|
||||
@@ -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([])
|
||||
|
||||
@@ -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))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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()
|
||||
}))
|
||||
)
|
||||
);
|
||||
|
||||
@@ -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))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
**/
|
||||
|
||||
@@ -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
|
||||
**/
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 }
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user