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 | ||
|
|
7d3464ae2c | ||
|
|
295cd2a7e0 | ||
|
|
5a66ce5a87 | ||
|
|
d8d008108d | ||
|
|
491518405d | ||
|
|
7290b3d296 | ||
|
|
b6162a316f | ||
|
|
71c1d16dc4 | ||
|
|
204f592bea | ||
|
|
39c44bb5aa | ||
|
|
df0de49a67 | ||
|
|
0bdbf4b7a7 | ||
|
|
ef9cd6fc4b | ||
|
|
5ab0bf3998 | ||
|
|
e69d97619e | ||
|
|
6aa0d90fc0 | ||
|
|
d338fcb58c | ||
|
|
b9a60a2519 | ||
|
|
7b8b4e8078 | ||
|
|
50b551e4fc | ||
|
|
a4ea4d648a | ||
|
|
146360a454 | ||
|
|
2e83d92adc | ||
|
|
b77e5d079c | ||
|
|
0d067c9484 | ||
|
|
88519eff3f | ||
|
|
bb14471e60 | ||
|
|
97ab7fcf2f | ||
|
|
922cfb8759 | ||
|
|
717f33ca02 | ||
|
|
21a2b5f0b7 | ||
|
|
54efead9d7 | ||
|
|
c472a451a4 | ||
|
|
6ed2de43fc | ||
|
|
8976ded37f | ||
|
|
169a374544 | ||
|
|
6476d88e19 | ||
|
|
75de454619 | ||
|
|
851428aef9 | ||
|
|
dfc51ad300 | ||
|
|
e16d288644 | ||
|
|
a19928fef9 | ||
|
|
0906c7837a | ||
|
|
cb9831c4f8 | ||
|
|
620d3757ba | ||
|
|
601288b3ec | ||
|
|
efbeecc8f6 | ||
|
|
852e0d4f0b | ||
|
|
5c7f9f1c8a | ||
|
|
64f64c1001 | ||
|
|
15c3085511 | ||
|
|
27cd9b1ca4 | ||
|
|
1c2a95f820 | ||
|
|
8bf5e51725 | ||
|
|
493225aa9d | ||
|
|
a0979a9ce3 | ||
|
|
02849ae49b | ||
|
|
602bb1406b | ||
|
|
d70930587c | ||
|
|
8c011cdc86 |
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
20
|
21
|
||||||
1.4.2
|
1.4.2
|
||||||
1.6.2
|
1.6.2
|
||||||
|
|||||||
@@ -10,9 +10,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
- uses: actions/setup-node@v1
|
|
||||||
with:
|
|
||||||
node-version: '12.x'
|
|
||||||
- name: ${{ matrix.step }}
|
- name: ${{ matrix.step }}
|
||||||
run: |
|
run: |
|
||||||
yarn install --immutable | grep -v 'YN0013'
|
yarn install --immutable | grep -v 'YN0013'
|
||||||
|
|||||||
@@ -10,15 +10,12 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
step: ['build:release', 'docs:release']
|
step: ['build:release', 'docs:release']
|
||||||
name: ${{ matrix.step }}
|
name: ${{ matrix.step }}
|
||||||
if: "! contains(github.event.head_commit.message, '[CI Skip]')"
|
if: "! contains(github.event.head_commit.message, '[CI Skip]') && github.repository == 'polkadot-js/api'"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GH_PAT }}
|
token: ${{ secrets.GH_PAT }}
|
||||||
- uses: actions/setup-node@v1
|
|
||||||
with:
|
|
||||||
node-version: '12.x'
|
|
||||||
- name: ${{ matrix.step }}
|
- name: ${{ matrix.step }}
|
||||||
env:
|
env:
|
||||||
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
||||||
|
|||||||
+30
-1
@@ -1,6 +1,34 @@
|
|||||||
|
# 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
|
||||||
|
- 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
|
||||||
|
- Split `@polkadot/types/known` into `@polkadot/types-known`, allowing for base API overrides
|
||||||
|
- Extended `api.derive.democracy` to cater for dispatchQueue and externals
|
||||||
|
- Extended `api.derive.council` to cater for new phragmen elections
|
||||||
|
- Use new `queryStorageAt` for query `.entries`, removing unneeded subscriptions (use as available)
|
||||||
|
- Fix `BTreeSet` initialization when it forms part of query interfaces
|
||||||
|
- Fix encoding for `Vec<u8>`-related types as part of constants
|
||||||
|
- Internal adjustment of interface type locations (no impact on imports via `@polkadot/types/interfaces`)
|
||||||
|
|
||||||
# 1.8.1 Mar 22, 2020
|
# 1.8.1 Mar 22, 2020
|
||||||
|
|
||||||
- **Breaking change** The format for any custom RPCs have been changed alongside API-internal changes to allow for better RPC management. If you are currently using custom RPCs (or planning to do so), look at the [updated documentation](https://polkadot.js.org/api/start/rpc.custom.html)
|
- **Breaking change** The format for any custom RPCs have been changed (alongside API-internal changes) to allow for better RPC management. If you are currently using custom RPCs (or planning to do so), look at the [updated documentation](https://polkadot.js.org/api/start/rpc.custom.html)
|
||||||
- **Breaking change** Alongside API RPC changes, the `@polkadot/jsonrpc` package has been removed. Since it was never documented and only used internally, this should not have adverse impacts. All RPC definitions itself has now been moved to the relevant modules inside `@polkadot/types/interfaces`
|
- **Breaking change** Alongside API RPC changes, the `@polkadot/jsonrpc` package has been removed. Since it was never documented and only used internally, this should not have adverse impacts. All RPC definitions itself has now been moved to the relevant modules inside `@polkadot/types/interfaces`
|
||||||
- **Important** Substrate has an updated democracy module. If using an older chain add the `ReferendumInfo: 'ReferendumInfoTo239'` type when using referendums
|
- **Important** Substrate has an updated democracy module. If using an older chain add the `ReferendumInfo: 'ReferendumInfoTo239'` type when using referendums
|
||||||
- The `isRetracted` Extrinsic status is now a warning, not a fatal error, correctly aligning with Polkadot/Substrate
|
- The `isRetracted` Extrinsic status is now a warning, not a fatal error, correctly aligning with Polkadot/Substrate
|
||||||
@@ -8,6 +36,7 @@
|
|||||||
- Add support for all known substrate RPC methods
|
- Add support for all known substrate RPC methods
|
||||||
- Extend account derives to include status flags, e.g. `isCouncil`, `isSudo`, ...
|
- Extend account derives to include status flags, e.g. `isCouncil`, `isSudo`, ...
|
||||||
- Adjusted referendum derives to cater for bot new/old democracy. Derived `referendumInfo` now includes `status` field, not `info`
|
- Adjusted referendum derives to cater for bot new/old democracy. Derived `referendumInfo` now includes `status` field, not `info`
|
||||||
|
- Add `initWasm` flag to API options. When set to `false` does not init the WASM portion (leaving it to the user elsewhere)
|
||||||
|
|
||||||
# 1.7.1 Mar 17, 2020
|
# 1.7.1 Mar 17, 2020
|
||||||
|
|
||||||
|
|||||||
@@ -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');
|
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/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Required imports
|
// Required imports
|
||||||
const { ApiPromise, WsProvider } = require('@polkadot/api');
|
const { ApiPromise, WsProvider } = require('@polkadot/api');
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API
|
// Import the API
|
||||||
const { ApiPromise } = require('@polkadot/api');
|
const { ApiPromise } = require('@polkadot/api');
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API
|
// Import the API
|
||||||
const { ApiPromise } = require('@polkadot/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
|
// Retrieve the initial balance. Since the call has no callback, it is simply a promise
|
||||||
// that resolves to the current on-chain value
|
// 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(`${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}`);
|
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
|
// 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
|
// Calculate the delta
|
||||||
const change = currentFree.sub(previousFree);
|
const change = currentFree.sub(previousFree);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API
|
// Import the API
|
||||||
const { ApiPromise } = require('@polkadot/api');
|
const { ApiPromise } = require('@polkadot/api');
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API
|
// Import the API
|
||||||
const { ApiPromise } = require('@polkadot/api');
|
const { ApiPromise } = require('@polkadot/api');
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API
|
// Import the API
|
||||||
const { ApiPromise } = require('@polkadot/api');
|
const { ApiPromise } = require('@polkadot/api');
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API
|
// Import the API
|
||||||
const { ApiPromise } = require('@polkadot/api');
|
const { ApiPromise } = require('@polkadot/api');
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API, Keyring and some utility functions
|
// Import the API, Keyring and some utility functions
|
||||||
const { ApiPromise } = require('@polkadot/api');
|
const { ApiPromise } = require('@polkadot/api');
|
||||||
const { Keyring } = require('@polkadot/keyring');
|
const { Keyring } = require('@polkadot/keyring');
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API, Keyring and some utility functions
|
// Import the API, Keyring and some utility functions
|
||||||
const { ApiPromise } = require('@polkadot/api');
|
const { ApiPromise } = require('@polkadot/api');
|
||||||
const { Keyring } = require('@polkadot/keyring');
|
const { Keyring } = require('@polkadot/keyring');
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API
|
// Import the API
|
||||||
const { ApiPromise } = require('@polkadot/api');
|
const { ApiPromise } = require('@polkadot/api');
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
|
|
||||||
// Import the API & Provider and some utility functions
|
// Import the API & Provider and some utility functions
|
||||||
const { ApiPromise } = require('@polkadot/api');
|
const { ApiPromise } = require('@polkadot/api');
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ async function main () {
|
|||||||
console.log('Included at block hash', status.asInBlock.toHex());
|
console.log('Included at block hash', status.asInBlock.toHex());
|
||||||
console.log('Events:');
|
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());
|
console.log('\t', phase.toString(), `: ${section}.${method}`, data.toString());
|
||||||
});
|
});
|
||||||
} else if (status.isFinalized) {
|
} else if (status.isFinalized) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API & Provider and some utility functions
|
// Import the API & Provider and some utility functions
|
||||||
const { ApiPromise, WsProvider } = require('@polkadot/api');
|
const { ApiPromise, WsProvider } = require('@polkadot/api');
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Required imports
|
// Required imports
|
||||||
const { zip } = require('rxjs');
|
const { zip } = require('rxjs');
|
||||||
const { ApiRx } = require('@polkadot/api');
|
const { ApiRx } = require('@polkadot/api');
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API
|
// Import the API
|
||||||
const { ApiRx } = require('@polkadot/api');
|
const { ApiRx } = require('@polkadot/api');
|
||||||
const { switchMap } = require('rxjs/operators');
|
const { switchMap } = require('rxjs/operators');
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API and operators from RxJs
|
// Import the API and operators from RxJs
|
||||||
const { ApiRx } = require('@polkadot/api');
|
const { ApiRx } = require('@polkadot/api');
|
||||||
const { pairwise, startWith } = require('rxjs/operators');
|
const { pairwise, startWith } = require('rxjs/operators');
|
||||||
@@ -27,6 +28,7 @@ async function main () {
|
|||||||
// then balance[1] is the initial value of Alice account.
|
// then balance[1] is the initial value of Alice account.
|
||||||
console.log(`Alice ${Alice} has a balance of ${balance[1].data.free}`);
|
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');
|
console.log('You may leave this example running and start the "Make a transfer" example or transfer any value to Alice address');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API
|
// Import the API
|
||||||
const { ApiRx } = require('@polkadot/api');
|
const { ApiRx } = require('@polkadot/api');
|
||||||
const { switchMap } = require('rxjs/operators');
|
const { switchMap } = require('rxjs/operators');
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API
|
// Import the API
|
||||||
const { ApiRx } = require('@polkadot/api');
|
const { ApiRx } = require('@polkadot/api');
|
||||||
const { combineLatest, of } = require('rxjs');
|
const { combineLatest, of } = require('rxjs');
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API, Keyring and some utility functions
|
// Import the API, Keyring and some utility functions
|
||||||
const { ApiRx } = require('@polkadot/api');
|
const { ApiRx } = require('@polkadot/api');
|
||||||
const { Keyring } = require('@polkadot/keyring');
|
const { Keyring } = require('@polkadot/keyring');
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API and selected RxJs operators
|
// Import the API and selected RxJs operators
|
||||||
const { switchMap } = require('rxjs/operators');
|
const { switchMap } = require('rxjs/operators');
|
||||||
const { ApiRx } = require('@polkadot/api');
|
const { ApiRx } = require('@polkadot/api');
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API and some utility functions
|
// Import the API and some utility functions
|
||||||
const { ApiRx } = require('@polkadot/api');
|
const { ApiRx } = require('@polkadot/api');
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ async function main () {
|
|||||||
console.log('Included at block hash', status.asInBlock.toHex());
|
console.log('Included at block hash', status.asInBlock.toHex());
|
||||||
console.log('Events:');
|
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());
|
console.log('\t', phase.toString(), `: ${section}.${method}`, data.toString());
|
||||||
});
|
});
|
||||||
} else if (status.isFinalized) {
|
} else if (status.isFinalized) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
/* eslint-disable header/header */
|
||||||
/* eslint-disable @typescript-eslint/require-await */
|
/* eslint-disable @typescript-eslint/require-await */
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
// Import the API & Provider and some utility functions
|
// Import the API & Provider and some utility functions
|
||||||
const { ApiRx, WsProvider } = require('@polkadot/api');
|
const { ApiRx, WsProvider } = require('@polkadot/api');
|
||||||
// Import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie)
|
// Import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie)
|
||||||
|
|||||||
+9
-1
@@ -40,7 +40,7 @@ Tuples, as defined in the Polkadot/Substrate types appear as `(TypeA, TypeB)`. F
|
|||||||
|
|
||||||
Polkadot/Substrate supports both immortal and mortal transactions. For immortal, this means that the transaction has an infinite lifetime, for mortals, the transactions expire after a defined period. By default the API sends mortal transactions when no explicit extrinsic era has been specified. This means that all transaction has a limited lifetime and will expire if not included in the period set.
|
Polkadot/Substrate supports both immortal and mortal transactions. For immortal, this means that the transaction has an infinite lifetime, for mortals, the transactions expire after a defined period. By default the API sends mortal transactions when no explicit extrinsic era has been specified. This means that all transaction has a limited lifetime and will expire if not included in the period set.
|
||||||
|
|
||||||
The length for this transaction validity is set to 50 blocks, which translates to 5 minutes assuming a default of 6 second blocktimes. (10 blocks per minute in this default configuration).
|
The length for this transaction validity is set to 5 minutes, calculated based on the blocktime for the chain. (10 blocks per minute in this default 6s Substrate configuration).
|
||||||
|
|
||||||
## My chain does not support system.account queries
|
## My chain does not support system.account queries
|
||||||
|
|
||||||
@@ -49,3 +49,11 @@ The API always tracks the latest Substrate master in terms of examples. This mea
|
|||||||
It is possible that you are connecting to an older chain that has not been upgraded yet. For these chains, this storage entry won't be available (yet). To query the nonce on older chains, you can do a query to `api.query.system.accountNonce(<account>)` and balances can be retrieved via `api.query.balances.freeBalance(<account>)`.
|
It is possible that you are connecting to an older chain that has not been upgraded yet. For these chains, this storage entry won't be available (yet). To query the nonce on older chains, you can do a query to `api.query.system.accountNonce(<account>)` and balances can be retrieved via `api.query.balances.freeBalance(<account>)`.
|
||||||
|
|
||||||
Likewise, if your chain has been upgraded recently and you are still using the old `system.accountNonce` or `balances.freeBalance` queries in your code (which is now not available in the chain metadata), you need to update it to query the new location.
|
Likewise, if your chain has been upgraded recently and you are still using the old `system.accountNonce` or `balances.freeBalance` queries in your code (which is now not available in the chain metadata), you need to update it to query the new location.
|
||||||
|
|
||||||
|
## I cannot send transactions from my node-template-based chain
|
||||||
|
|
||||||
|
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 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 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
|
// Retrieve the active era
|
||||||
const activeEra = await api.query.staking.activeEra();
|
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);
|
const exposures = await api.query.staking.erasStakers.entries(activeEra.index);
|
||||||
|
|
||||||
exposures.forEach(([key, exposure]) => {
|
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)
|
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
|
## 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.
|
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>
|
## 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`
|
- `.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.
|
- `.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.
|
- `.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
|
## Working with Tuples
|
||||||
|
|
||||||
|
|||||||
+9
-3
@@ -1,14 +1,19 @@
|
|||||||
/* eslint-disable @typescript-eslint/camelcase */
|
// Copyright 2017-2020 @polkadot/api authors & contributors
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
// 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');
|
const config = require('@polkadot/dev/config/jest');
|
||||||
|
|
||||||
module.exports = Object.assign({}, config, {
|
module.exports = Object.assign({}, config, {
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'@polkadot/api-contract(.*)$': '<rootDir>/packages/api-contract/src/$1',
|
'@polkadot/api-contract(.*)$': '<rootDir>/packages/api-contract/src/$1',
|
||||||
'@polkadot/api-derive(.*)$': '<rootDir>/packages/api-derive/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/api(.*)$': '<rootDir>/packages/api/src/$1',
|
||||||
'@polkadot/metadata(.*)$': '<rootDir>/packages/metadata/src/$1',
|
'@polkadot/metadata(.*)$': '<rootDir>/packages/metadata/src/$1',
|
||||||
'@polkadot/rpc-(core|provider)(.*)$': '<rootDir>/packages/rpc-$1/src/$2',
|
'@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'
|
'@polkadot/types(.*)$': '<rootDir>/packages/types/src/$1'
|
||||||
},
|
},
|
||||||
modulePathIgnorePatterns: [
|
modulePathIgnorePatterns: [
|
||||||
@@ -18,7 +23,8 @@ module.exports = Object.assign({}, config, {
|
|||||||
'<rootDir>/packages/metadata/build',
|
'<rootDir>/packages/metadata/build',
|
||||||
'<rootDir>/packages/rpc-core/build',
|
'<rootDir>/packages/rpc-core/build',
|
||||||
'<rootDir>/packages/rpc-provider/build',
|
'<rootDir>/packages/rpc-provider/build',
|
||||||
'<rootDir>/packages/types/build'
|
'<rootDir>/packages/types/build',
|
||||||
|
'<rootDir>/packages/types-known/build'
|
||||||
],
|
],
|
||||||
resolver: './jest.resolver.js'
|
resolver: './jest.resolver.js'
|
||||||
});
|
});
|
||||||
|
|||||||
+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
|
// This software may be modified and distributed under the terms
|
||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// 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');
|
const path = require('path');
|
||||||
|
|
||||||
module.exports = function resolver (file, config) {
|
module.exports = function resolver (file, config) {
|
||||||
|
|||||||
+1
-1
@@ -9,5 +9,5 @@
|
|||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"version": "1.8.1"
|
"version": "1.10.1"
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -27,10 +27,10 @@
|
|||||||
"@babel/core": "^7.9.0",
|
"@babel/core": "^7.9.0",
|
||||||
"@babel/register": "^7.9.0",
|
"@babel/register": "^7.9.0",
|
||||||
"@babel/runtime": "^7.9.2",
|
"@babel/runtime": "^7.9.2",
|
||||||
"@polkadot/dev": "^0.51.7",
|
"@polkadot/dev": "^0.52.9",
|
||||||
"@polkadot/ts": "^0.3.14",
|
"@polkadot/ts": "^0.3.18",
|
||||||
"@polkadot/typegen": "workspace:packages/typegen",
|
"@polkadot/typegen": "workspace:packages/typegen",
|
||||||
"@types/jest": "^25.1.4",
|
"@types/jest": "^25.2.1",
|
||||||
"copyfiles": "^2.2.0"
|
"copyfiles": "^2.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@polkadot/api-contract",
|
"name": "@polkadot/api-contract",
|
||||||
"version": "1.8.1",
|
"version": "1.10.1",
|
||||||
"description": "Interfaces for interacting with contracts and contract ABIs",
|
"description": "Interfaces for interacting with contracts and contract ABIs",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -27,11 +27,11 @@
|
|||||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-contract#readme",
|
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-contract#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.9.2",
|
"@babel/runtime": "^7.9.2",
|
||||||
"@polkadot/api": "1.8.1",
|
"@polkadot/api": "1.10.1",
|
||||||
"@polkadot/rpc-core": "1.8.1",
|
"@polkadot/rpc-core": "1.10.1",
|
||||||
"@polkadot/types": "1.8.1",
|
"@polkadot/types": "1.10.1",
|
||||||
"@polkadot/util": "^2.6.2",
|
"@polkadot/util": "^2.8.1",
|
||||||
"bn.js": "^5.1.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) {
|
constructor (registry: Registry, abi: ContractABIPre) {
|
||||||
super(registry, abi);
|
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);
|
this.validateAbi(abiPre);
|
||||||
|
|
||||||
const abi = this.convertAbi(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));
|
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(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`);
|
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}`);
|
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}`);
|
assert(isNull(returnType) || (isNumber(returnType.ty) && isObject(this.typeDefAt(returnType.ty))), `Expected return_type for ${fnname}`);
|
||||||
|
|
||||||
parseSelector(this.registry, fnname, selector);
|
parseSelector(this.registry, fnname, selector);
|
||||||
@@ -100,7 +100,7 @@ export default class ContractRegistry extends MetaRegistry {
|
|||||||
|
|
||||||
const { contract: { constructors, messages, name } } = abi;
|
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.validateConstructors(abi);
|
||||||
this.validateMessages(abi);
|
this.validateMessages(abi);
|
||||||
@@ -109,13 +109,16 @@ export default class ContractRegistry extends MetaRegistry {
|
|||||||
public createMessage (name: string, message: Partial<ContractABIMessage> & ContractABIMessageBase): ContractABIFn {
|
public createMessage (name: string, message: Partial<ContractABIMessage> & ContractABIMessageBase): ContractABIFn {
|
||||||
const args = message.args.map(({ name, type }): ContractABIFnArg => {
|
const args = message.args.map(({ name, type }): ContractABIFnArg => {
|
||||||
assert(isObject(type), `Invalid type at index ${type}`);
|
assert(isObject(type), `Invalid type at index ${type}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: stringCamelCase(name),
|
name: stringCamelCase(name),
|
||||||
type
|
type
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const Clazz = createArgClass(this.registry, args, isUndefined(message.selector) ? {} : { __selector: 'u32' });
|
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 baseStruct: { [index: string]: any } = { __selector: isUndefined(message.selector) ? undefined : parseSelector(this.registry, name, message.selector) };
|
||||||
|
|
||||||
const encoder = (...params: CodecArg[]): Uint8Array => {
|
const encoder = (...params: CodecArg[]): Uint8Array => {
|
||||||
assert(params.length === args.length, `Expected ${args.length} arguments to contract ${name}, found ${params.length}`);
|
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.args = args;
|
||||||
fn.isConstant = !(message.mutates || false);
|
fn.isConstant = !(message.mutates || false);
|
||||||
fn.type = message.returnType || null;
|
fn.type = message.returnType || null;
|
||||||
|
|
||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,19 +151,20 @@ export default class ContractRegistry extends MetaRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public convertArgs (args: ContractABIArgBasePre[]): any[] {
|
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('::');
|
const displayName = this.stringsAt(displayNameIndices).join('::');
|
||||||
|
|
||||||
return this.typeDefAt(ty, { displayName });
|
return this.typeDefAt(ty, { displayName });
|
||||||
}
|
}
|
||||||
|
|
||||||
public convertContract ({ constructors, messages, name, events, ...contract }: ContractABIContractPre): ContractABIContract {
|
public convertContract ({ constructors, events, messages, name, ...contract }: ContractABIContractPre): ContractABIContract {
|
||||||
return {
|
return {
|
||||||
constructors: this.convertConstructors(constructors),
|
constructors: this.convertConstructors(constructors),
|
||||||
messages: messages.map((message) => this.convertMessage(message)),
|
messages: messages.map((message) => this.convertMessage(message)),
|
||||||
name: this.stringAt(name),
|
name: this._stringAt(name),
|
||||||
...(events
|
...(events
|
||||||
? { events: events.map((event) => this.convertEvent(event)) }
|
? { events: events.map((event) => this.convertEvent(event)) }
|
||||||
: {}),
|
: {}),
|
||||||
@@ -179,7 +184,7 @@ export default class ContractRegistry extends MetaRegistry {
|
|||||||
return {
|
return {
|
||||||
...message,
|
...message,
|
||||||
args: this.convertArgs(args),
|
args: this.convertArgs(args),
|
||||||
name: this.stringAt(name),
|
name: this._stringAt(name),
|
||||||
returnType: returnType ? this.convertType(returnType) : null
|
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 {
|
return {
|
||||||
'struct.type': this.typeDefAt(structType),
|
'struct.fields': structFields.map(({ layout, name }) => ({
|
||||||
'struct.fields': structFields.map(({ name, layout }) => ({
|
layout: this.convertStorageLayout(layout),
|
||||||
name: this.stringAt(name),
|
name: this._stringAt(name)
|
||||||
layout: this.convertStorageLayout(layout)
|
})),
|
||||||
}))
|
'struct.type': this.typeDefAt(structType)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class MetadataRegistryLookup {
|
|||||||
this._types = types;
|
this._types = types;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected hasItemAt (index: number, variant: MetaRegistryItem): boolean {
|
protected _hasItemAt (index: number, variant: MetaRegistryItem): boolean {
|
||||||
switch (variant) {
|
switch (variant) {
|
||||||
case MetaRegistryItem.String:
|
case MetaRegistryItem.String:
|
||||||
return this._strings && !!this._strings[index - 1];
|
return this._strings && !!this._strings[index - 1];
|
||||||
@@ -59,8 +59,8 @@ class MetadataRegistryLookup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected itemAt (index: number, variant: MetaRegistryItem): any {
|
protected _itemAt (index: number, variant: MetaRegistryItem): any {
|
||||||
assert(this.hasItemAt(index, variant), `MetaRegistry: Invalid ${variant} index ${index} found in metadata`);
|
assert(this._hasItemAt(index, variant), `MetaRegistry: Invalid ${variant} index ${index} found in metadata`);
|
||||||
|
|
||||||
switch (variant) {
|
switch (variant) {
|
||||||
case MetaRegistryItem.String:
|
case MetaRegistryItem.String:
|
||||||
@@ -72,33 +72,33 @@ class MetadataRegistryLookup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected itemsAt (indices: number[], variant: MetaRegistryItem): any[] {
|
protected _itemsAt (indices: number[], variant: MetaRegistryItem): any[] {
|
||||||
return indices.map((index: number): string => this.itemAt(index, variant));
|
return indices.map((index: number): string => this._itemAt(index, variant));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected stringAt (index: StringIndex): string {
|
protected _stringAt (index: StringIndex): string {
|
||||||
return this.itemAt(index, MetaRegistryItem.String);
|
return this._itemAt(index, MetaRegistryItem.String);
|
||||||
}
|
}
|
||||||
|
|
||||||
public stringsAt (indices: StringIndex[]): string[] {
|
public stringsAt (indices: StringIndex[]): string[] {
|
||||||
return this.itemsAt(indices, MetaRegistryItem.String);
|
return this._itemsAt(indices, MetaRegistryItem.String);
|
||||||
}
|
}
|
||||||
|
|
||||||
public typeAt (index: TypeIndex): MetaType {
|
public typeAt (index: TypeIndex): MetaType {
|
||||||
return this.itemAt(index, MetaRegistryItem.Type);
|
return this._itemAt(index, MetaRegistryItem.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public typesAt (indices: TypeIndex[]): MetaType[] {
|
public typesAt (indices: TypeIndex[]): MetaType[] {
|
||||||
return this.itemsAt(indices, MetaRegistryItem.Type);
|
return this._itemsAt(indices, MetaRegistryItem.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public hasTypeDefAt (index: TypeIndex): boolean {
|
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 {
|
public typeDefAt (index: TypeIndex, extra: Pick<TypeDef, never> = {}): TypeDef {
|
||||||
return {
|
return {
|
||||||
...this.itemAt(index, MetaRegistryItem.TypeDef),
|
...this._itemAt(index, MetaRegistryItem.TypeDef),
|
||||||
...extra
|
...extra
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -116,7 +116,7 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
|||||||
this.typeDefs[typeIndex - 1] = this.typeDefFromMetaType(this.typeAt(typeIndex), typeIndex);
|
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;
|
const { 'custom.name': nameIndex, 'custom.namespace': namespaceIndices, 'custom.params': paramsIndices } = id as MetaTypeIdCustom;
|
||||||
|
|
||||||
if (!nameIndex) {
|
if (!nameIndex) {
|
||||||
@@ -124,7 +124,7 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: this.stringAt(nameIndex),
|
name: this._stringAt(nameIndex),
|
||||||
...(namespaceIndices && namespaceIndices.length
|
...(namespaceIndices && namespaceIndices.length
|
||||||
? { namespace: this.stringsAt(namespaceIndices).join('::') }
|
? { 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;
|
let typeDef;
|
||||||
|
|
||||||
switch (detectedType(metaType)) {
|
switch (detectedType(metaType)) {
|
||||||
case MetaTypeInfo.BuiltinPlain:
|
case MetaTypeInfo.BuiltinPlain:
|
||||||
typeDef = this.typeDefForBuiltinPlain(metaType.id as string);
|
typeDef = this._typeDefForBuiltinPlain(metaType.id as string);
|
||||||
break;
|
break;
|
||||||
case MetaTypeInfo.BuiltinTuple:
|
case MetaTypeInfo.BuiltinTuple:
|
||||||
typeDef = this.typeDefForBuiltinTuple(metaType.id as TypeIndex[]);
|
typeDef = this._typeDefForBuiltinTuple(metaType.id as TypeIndex[]);
|
||||||
break;
|
break;
|
||||||
case MetaTypeInfo.BuiltinVec:
|
case MetaTypeInfo.BuiltinVec:
|
||||||
typeDef = this.typeDefForBuiltinVec(metaType.id as MetaTypeIdVec, typeIndex);
|
typeDef = this._typeDefForBuiltinVec(metaType.id as MetaTypeIdVec, typeIndex);
|
||||||
break;
|
break;
|
||||||
case MetaTypeInfo.BuiltinVecFixed:
|
case MetaTypeInfo.BuiltinVecFixed:
|
||||||
typeDef = this.typeDefForBuiltinVecFixed(metaType.id as MetaTypeIdVecFixed, typeIndex);
|
typeDef = this._typeDefForBuiltinVecFixed(metaType.id as MetaTypeIdVecFixed, typeIndex);
|
||||||
break;
|
break;
|
||||||
case MetaTypeInfo.Enum:
|
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;
|
break;
|
||||||
case MetaTypeInfo.ClikeEnum:
|
case MetaTypeInfo.ClikeEnum:
|
||||||
typeDef = this.typeDefForClikeEnum(metaType.def as MetaTypeDefClikeEnum);
|
typeDef = this._typeDefForClikeEnum(metaType.def as MetaTypeDefClikeEnum);
|
||||||
break;
|
break;
|
||||||
case MetaTypeInfo.Struct:
|
case MetaTypeInfo.Struct:
|
||||||
typeDef = this.typeDefForStruct(metaType.def as MetaTypeDefStruct);
|
typeDef = this.typeDefForStruct(metaType.def as MetaTypeDefStruct);
|
||||||
break;
|
break;
|
||||||
case MetaTypeInfo.TupleStruct:
|
case MetaTypeInfo.TupleStruct:
|
||||||
typeDef = this.typeDefForTupleStruct(metaType.def as MetaTypeDefTupleStruct);
|
typeDef = this._typeDefForTupleStruct(metaType.def as MetaTypeDefTupleStruct);
|
||||||
break;
|
break;
|
||||||
case MetaTypeInfo.Null:
|
case MetaTypeInfo.Null:
|
||||||
default:
|
default:
|
||||||
@@ -176,8 +176,8 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
|||||||
return withTypeString({
|
return withTypeString({
|
||||||
info: TypeDefInfo.Null,
|
info: TypeDefInfo.Null,
|
||||||
type: '',
|
type: '',
|
||||||
...this.typeDefDefFields(metaType, typeIndex),
|
...this._typeDefDefFields(metaType, typeIndex),
|
||||||
...this.typeDefIdFields(metaType)
|
...this._typeDefIdFields(metaType)
|
||||||
}) as TypeDef;
|
}) as TypeDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,13 +189,13 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
|||||||
return this.typeDefAt(typeIndex);
|
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;
|
const { 'unit_variant.name': unitNameIndex } = variant as MetaTypeDefEnumVariantUnit;
|
||||||
|
|
||||||
if (unitNameIndex) {
|
if (unitNameIndex) {
|
||||||
return {
|
return {
|
||||||
info: TypeDefInfo.Plain,
|
info: TypeDefInfo.Plain,
|
||||||
name: this.stringAt(unitNameIndex),
|
name: this._stringAt(unitNameIndex),
|
||||||
type: 'Null'
|
type: 'Null'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -203,7 +203,7 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
|||||||
const { 'tuple_struct_variant.name': tupleStructVariantNameIndex } = variant as MetaTypeDefEnumVariantTupleStruct;
|
const { 'tuple_struct_variant.name': tupleStructVariantNameIndex } = variant as MetaTypeDefEnumVariantTupleStruct;
|
||||||
|
|
||||||
if (tupleStructVariantNameIndex) {
|
if (tupleStructVariantNameIndex) {
|
||||||
return this.typeDefForTupleStruct(variant as MetaTypeDefEnumVariantTupleStruct);
|
return this._typeDefForTupleStruct(variant as MetaTypeDefEnumVariantTupleStruct);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { 'struct_variant.name': structVariantNameIndex } = variant as MetaTypeDefEnumVariantStruct;
|
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 {
|
return {
|
||||||
info: TypeDefInfo.Plain,
|
info: TypeDefInfo.Plain,
|
||||||
type: id
|
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));
|
const sub = id.map((tupleTypeIndex: number): TypeDef => this.typeDefFromMetaTypeAt(tupleTypeIndex));
|
||||||
|
|
||||||
return {
|
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;
|
const { 'slice.type': vecTypeIndex } = id;
|
||||||
|
|
||||||
assert(!typeIndex || vecTypeIndex !== typeIndex, `MetaRegistry: self-referencing registry type at index ${typeIndex}`);
|
assert(!typeIndex || vecTypeIndex !== typeIndex, `MetaRegistry: self-referencing registry type at index ${typeIndex}`);
|
||||||
|
|
||||||
const type = displayType(this.typeDefFromMetaTypeAt(vecTypeIndex));
|
const type = displayType(this.typeDefFromMetaTypeAt(vecTypeIndex));
|
||||||
|
|
||||||
assert(type && type.length > 0, `MetaRegistry: Invalid builtin Vec type found at index ${typeIndex}`);
|
assert(type && type.length > 0, `MetaRegistry: Invalid builtin Vec type found at index ${typeIndex}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
info: TypeDefInfo.Vec,
|
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> {
|
private _typeDefForBuiltinVecFixed (id: MetaTypeIdVecFixed, typeIndex?: TypeIndex): Pick<TypeDef, never> {
|
||||||
const { 'array.type': vecTypeIndex, 'array.len': vecLength } = id;
|
const { 'array.len': vecLength, 'array.type': vecTypeIndex } = id;
|
||||||
|
|
||||||
assert(!vecLength || vecLength <= 256, 'MetaRegistry: Only support for [Type; <length>], where length <= 256');
|
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}`);
|
assert(!typeIndex || vecTypeIndex !== typeIndex, `MetaRegistry: self-referencing registry type at index ${typeIndex}`);
|
||||||
|
|
||||||
const type = displayType(this.typeDefFromMetaTypeAt(vecTypeIndex));
|
const type = displayType(this.typeDefFromMetaTypeAt(vecTypeIndex));
|
||||||
|
|
||||||
assert(type && type.length > 0, `MetaRegistry: Invalid vector type found at index ${typeIndex}`);
|
assert(type && type.length > 0, `MetaRegistry: Invalid vector type found at index ${typeIndex}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
info: TypeDefInfo.VecFixed,
|
info: TypeDefInfo.VecFixed,
|
||||||
length: vecLength, // ex: { type: type }
|
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> {
|
private _typeDefForEnum (def: MetaTypeDefEnum, id: MetaTypeIdCustom, typeIndex?: TypeIndex): Pick<TypeDef, any> {
|
||||||
const name = id && this.stringAt(id['custom.name']);
|
const name = id && this._stringAt(id['custom.name']);
|
||||||
|
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'Option':
|
case 'Option':
|
||||||
return this.typeDefForOption(id, typeIndex);
|
return this.typeDefForOption(id, typeIndex);
|
||||||
|
|
||||||
case 'Result':
|
case 'Result':
|
||||||
return this.typeDefForResult(id, typeIndex);
|
return this.typeDefForResult(id, typeIndex);
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
const sub = def['enum.variants'].map((variant) => this.typeDefForEnumVariant(variant));
|
const sub = def['enum.variants'].map((variant) => this._typeDefForEnumVariant(variant));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
info: TypeDefInfo.Enum,
|
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 {
|
return {
|
||||||
info: TypeDefInfo.Enum,
|
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 },
|
ext: { discriminant },
|
||||||
info: TypeDefInfo.Plain,
|
info: TypeDefInfo.Plain,
|
||||||
name: this.stringAt(nameIndex),
|
name: this._stringAt(nameIndex),
|
||||||
type: 'Null'
|
type: 'Null'
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
@@ -322,24 +326,24 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
|||||||
return withTypeString({
|
return withTypeString({
|
||||||
info: TypeDefInfo.Struct,
|
info: TypeDefInfo.Struct,
|
||||||
...(structNameIndex
|
...(structNameIndex
|
||||||
? { name: this.stringAt(structNameIndex) }
|
? { name: this._stringAt(structNameIndex) }
|
||||||
: {}
|
: {}
|
||||||
),
|
),
|
||||||
sub: structFields.map((field: MetaTypeDefStructField): TypeDef => ({
|
sub: structFields.map((field: MetaTypeDefStructField): TypeDef => ({
|
||||||
...this.typeDefFromMetaTypeAt(field.type),
|
...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 tupleStructTypes = (def as MetaTypeDefTupleStruct)['tuple_struct.types'] || (def as MetaTypeDefEnumVariantTupleStruct)['tuple_struct_variant.types'];
|
||||||
const tupleStructNameIndex = (def as MetaTypeDefEnumVariantTupleStruct)['tuple_struct_variant.name'];
|
const tupleStructNameIndex = (def as MetaTypeDefEnumVariantTupleStruct)['tuple_struct_variant.name'];
|
||||||
|
|
||||||
return withTypeString({
|
return withTypeString({
|
||||||
info: TypeDefInfo.Tuple,
|
info: TypeDefInfo.Tuple,
|
||||||
...(tupleStructNameIndex
|
...(tupleStructNameIndex
|
||||||
? { name: this.stringAt(tupleStructNameIndex) }
|
? { name: this._stringAt(tupleStructNameIndex) }
|
||||||
: {}
|
: {}
|
||||||
),
|
),
|
||||||
sub: tupleStructTypes.map((fieldIndex: number, index: number): TypeDef => ({
|
sub: tupleStructTypes.map((fieldIndex: number, index: number): TypeDef => ({
|
||||||
|
|||||||
@@ -49,16 +49,16 @@ export default class Blueprint<ApiType extends ApiTypes> extends BaseWithTx<ApiT
|
|||||||
return {
|
return {
|
||||||
signAndSend: this.decorateMethod(
|
signAndSend: this.decorateMethod(
|
||||||
(account: IKeyringPair | string | AccountId | Address): BlueprintCreateResultSubscription<ApiType> => {
|
(account: IKeyringPair | string | AccountId | Address): BlueprintCreateResultSubscription<ApiType> => {
|
||||||
return this.apiContracts
|
return this._apiContracts
|
||||||
.create(endowment, maxGas, this.codeHash, this.abi.constructors[constructorIndex](...params))
|
.create(endowment, maxGas, this.codeHash, this.abi.constructors[constructorIndex](...params))
|
||||||
.signAndSend(account)
|
.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;
|
let contract: Contract<ApiType> | undefined;
|
||||||
|
|
||||||
if (result.isInBlock) {
|
if (result.isInBlock) {
|
||||||
|
|||||||
@@ -48,15 +48,15 @@ export default class Code<ApiType extends ApiTypes> extends BaseWithTx<ApiType>
|
|||||||
return {
|
return {
|
||||||
signAndSend: this.decorateMethod(
|
signAndSend: this.decorateMethod(
|
||||||
(account: IKeyringPair | string | AccountId | Address): CodePutCodeResultSubscription<ApiType> =>
|
(account: IKeyringPair | string | AccountId | Address): CodePutCodeResultSubscription<ApiType> =>
|
||||||
this.apiContracts
|
this._apiContracts
|
||||||
.putCode(maxGas, compactAddLength(this.code))
|
.putCode(maxGas, compactAddLength(this.code))
|
||||||
.signAndSend(account)
|
.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;
|
let blueprint: Blueprint<ApiType> | undefined;
|
||||||
|
|
||||||
if (result.isInBlock) {
|
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> {
|
export default class Contract<ApiType extends ApiTypes> extends BaseWithTxAndRpcCall<ApiType> {
|
||||||
public readonly address: Address;
|
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: '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 (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> {
|
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 {
|
return {
|
||||||
send: this.decorateMethod(
|
send: this.decorateMethod(
|
||||||
as === 'rpc' && this.hasRpcContractsCall
|
as === 'rpc' && this.hasRpcContractsCall
|
||||||
? (account: IKeyringPair | string | AccountId | Address): ContractCallResult<'rpc'> =>
|
? (account: IKeyringPair | string | AccountId | Address): ContractCallResult<'rpc'> =>
|
||||||
this.rpcContractsCall(
|
this._rpcContractsCall(
|
||||||
this.registry.createType('ContractCallRequest', {
|
this.registry.createType('ContractCallRequest', {
|
||||||
origin: account,
|
|
||||||
dest: this.address.toString(),
|
dest: this.address.toString(),
|
||||||
value,
|
|
||||||
gasLimit,
|
gasLimit,
|
||||||
inputData: fn(...params)
|
inputData: fn(...params),
|
||||||
|
origin: account,
|
||||||
|
value
|
||||||
})
|
})
|
||||||
).pipe(map((result: ContractExecResult): ContractCallOutcome =>
|
).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'> =>
|
: (account: IKeyringPair | string | AccountId | Address): ContractCallResult<'tx'> =>
|
||||||
this.apiContracts
|
this._apiContracts
|
||||||
.call(this.address, value, gasLimit, fn(...params))
|
.call(this.address, value, gasLimit, fn(...params))
|
||||||
.signAndSend(account)
|
.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;
|
let output: Codec | null = null;
|
||||||
|
|
||||||
if (result.isSuccess) {
|
if (result.isSuccess) {
|
||||||
@@ -73,19 +79,13 @@ export default class Contract<ApiType extends ApiTypes> extends BaseWithTxAndRpc
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
time: Date.now(),
|
isSuccess: result.isSuccess,
|
||||||
message,
|
message,
|
||||||
origin,
|
origin,
|
||||||
|
output,
|
||||||
params,
|
params,
|
||||||
result,
|
result,
|
||||||
isSuccess: result.isSuccess,
|
time: Date.now()
|
||||||
output
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
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[] {
|
public get messages (): ContractMessage[] {
|
||||||
return this.abi.abi.contract.messages.map(
|
return this.abi.abi.contract.messages.map(
|
||||||
(def: ContractABIMessage, index): ContractMessage => ({
|
(def: ContractABIMessage, index): ContractMessage => ({
|
||||||
index,
|
|
||||||
def,
|
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}`);
|
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)];
|
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> {
|
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;
|
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);
|
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.');
|
assert(this.hasRpcContractsCall, 'You need to connect to a node with the contracts.call RPC method.');
|
||||||
|
|
||||||
return this.api.rx.rpc.contracts.call;
|
return this.api.rx.rpc.contracts.call;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@polkadot/api-derive",
|
"name": "@polkadot/api-derive",
|
||||||
"version": "1.8.1",
|
"version": "1.10.1",
|
||||||
"description": "Common functions used across Polkadot, derived from RPC calls and storage queries.",
|
"description": "Common functions used across Polkadot, derived from RPC calls and storage queries.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -28,17 +28,17 @@
|
|||||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme",
|
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.9.2",
|
"@babel/runtime": "^7.9.2",
|
||||||
"@polkadot/api": "1.8.1",
|
"@polkadot/api": "1.10.1",
|
||||||
"@polkadot/rpc-core": "1.8.1",
|
"@polkadot/rpc-core": "1.10.1",
|
||||||
"@polkadot/rpc-provider": "1.8.1",
|
"@polkadot/rpc-provider": "1.10.1",
|
||||||
"@polkadot/types": "1.8.1",
|
"@polkadot/types": "1.10.1",
|
||||||
"@polkadot/util": "^2.6.2",
|
"@polkadot/util": "^2.8.1",
|
||||||
"@polkadot/util-crypto": "^2.6.2",
|
"@polkadot/util-crypto": "^2.8.1",
|
||||||
"bn.js": "^5.1.1",
|
"bn.js": "^5.1.1",
|
||||||
"memoizee": "^0.4.14",
|
"memoizee": "^0.4.14",
|
||||||
"rxjs": "^6.5.4"
|
"rxjs": "^6.5.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@polkadot/keyring": "^2.6.2"
|
"@polkadot/keyring": "^2.8.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ function extractIdentity (identityOfOpt?: Option<Registration>, superOf?: [Accou
|
|||||||
: undefined,
|
: undefined,
|
||||||
email: dataAsString(info.email),
|
email: dataAsString(info.email),
|
||||||
image: dataAsString(info.image),
|
image: dataAsString(info.image),
|
||||||
|
judgements,
|
||||||
legal: dataAsString(info.legal),
|
legal: dataAsString(info.legal),
|
||||||
other: info.additional.reduce((other: Record<string, string>, [_key, _value]): Record<string, string> => {
|
other: info.additional.reduce((other: Record<string, string>, [_key, _value]): Record<string, string> => {
|
||||||
const key = dataAsString(_key);
|
const key = dataAsString(_key);
|
||||||
@@ -78,8 +79,7 @@ function extractIdentity (identityOfOpt?: Option<Registration>, superOf?: [Accou
|
|||||||
: undefined,
|
: undefined,
|
||||||
riot: dataAsString(info.riot),
|
riot: dataAsString(info.riot),
|
||||||
twitter: dataAsString(info.twitter),
|
twitter: dataAsString(info.twitter),
|
||||||
web: dataAsString(info.web),
|
web: dataAsString(info.web)
|
||||||
judgements
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,9 +140,9 @@ function retrieveFlags (api: ApiInterfaceRx, accountId?: AccountId): Observable<
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
isCouncil: (electionsMembers?.map(([id]) => id) || councilMembers || []).some(checkIncluded),
|
isCouncil: (electionsMembers?.map(([id]) => id) || councilMembers || []).some(checkIncluded),
|
||||||
isTechCommittee: technicalCommitteeMembers.some(checkIncluded),
|
|
||||||
isSociety: societyMembers.some(checkIncluded),
|
isSociety: societyMembers.some(checkIncluded),
|
||||||
isSudo: !!sudoKey && sudoKey.eq(accountId)
|
isSudo: !!sudoKey && sudoKey.eq(accountId),
|
||||||
|
isTechCommittee: technicalCommitteeMembers.some(checkIncluded)
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
import { AccountId, AccountData, AccountIndex, AccountInfo, Address, Balance, Index } from '@polkadot/types/interfaces';
|
import { AccountId, AccountData, AccountIndex, AccountInfo, Address, Balance, Index } from '@polkadot/types/interfaces';
|
||||||
import { ITuple } from '@polkadot/types/types';
|
import { ITuple } from '@polkadot/types/types';
|
||||||
import { DerivedBalancesAccount } from '../types';
|
import { DeriveBalancesAccount } from '../types';
|
||||||
|
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
import { Observable, combineLatest, of } from 'rxjs';
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
@@ -14,7 +14,7 @@ import { memo } from '../util';
|
|||||||
|
|
||||||
type Result = [Balance, Balance, Balance, Balance, Index];
|
type Result = [Balance, Balance, Balance, Balance, Index];
|
||||||
|
|
||||||
function calcBalances (api: ApiInterfaceRx, [accountId, [freeBalance, reservedBalance, frozenFee, frozenMisc, accountNonce]]: [AccountId, Result]): DerivedBalancesAccount {
|
function calcBalances (api: ApiInterfaceRx, [accountId, [freeBalance, reservedBalance, frozenFee, frozenMisc, accountNonce]]: [AccountId, Result]): DeriveBalancesAccount {
|
||||||
return {
|
return {
|
||||||
accountId,
|
accountId,
|
||||||
accountNonce,
|
accountNonce,
|
||||||
@@ -44,7 +44,7 @@ function queryBalancesAccount (api: ApiInterfaceRx, accountId: AccountId): Obser
|
|||||||
[api.query.balances.account, accountId],
|
[api.query.balances.account, accountId],
|
||||||
[api.query.system.accountNonce, accountId]
|
[api.query.system.accountNonce, accountId]
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([{ free, reserved, miscFrozen, feeFrozen }, accountNonce]): Result =>
|
map(([{ feeFrozen, free, miscFrozen, reserved }, accountNonce]): Result =>
|
||||||
[free, reserved, feeFrozen, miscFrozen, accountNonce]
|
[free, reserved, feeFrozen, miscFrozen, accountNonce]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -54,7 +54,7 @@ function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<Re
|
|||||||
// AccountInfo is current, support old, eg. Edgeware
|
// AccountInfo is current, support old, eg. Edgeware
|
||||||
return api.query.system.account<AccountInfo | ITuple<[Index, AccountData]>>(accountId).pipe(
|
return api.query.system.account<AccountInfo | ITuple<[Index, AccountData]>>(accountId).pipe(
|
||||||
map((infoOrTuple): Result => {
|
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 AccountInfo).data
|
||||||
: (infoOrTuple as [Index, AccountData])[1];
|
: (infoOrTuple as [Index, AccountData])[1];
|
||||||
const accountNonce = (infoOrTuple as AccountInfo).nonce || (infoOrTuple as [Index, AccountData])[0];
|
const accountNonce = (infoOrTuple as AccountInfo).nonce || (infoOrTuple as [Index, AccountData])[0];
|
||||||
@@ -79,8 +79,8 @@ function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<Re
|
|||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function account (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DerivedBalancesAccount> {
|
export function account (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DeriveBalancesAccount> {
|
||||||
return memo((address: AccountIndex | AccountId | Address | string): Observable<DerivedBalancesAccount> =>
|
return memo((address: AccountIndex | AccountId | Address | string): Observable<DeriveBalancesAccount> =>
|
||||||
api.derive.accounts.info(address).pipe(
|
api.derive.accounts.info(address).pipe(
|
||||||
switchMap(({ accountId }): Observable<[AccountId, Result]> =>
|
switchMap(({ accountId }): Observable<[AccountId, Result]> =>
|
||||||
(accountId
|
(accountId
|
||||||
@@ -95,6 +95,6 @@ export function account (api: ApiInterfaceRx): (address: AccountIndex | AccountI
|
|||||||
: of([api.registry.createType('AccountId'), [api.registry.createType('Balance'), api.registry.createType('Balance'), api.registry.createType('Balance'), api.registry.createType('Balance'), api.registry.createType('Index')]])
|
: of([api.registry.createType('AccountId'), [api.registry.createType('Balance'), api.registry.createType('Balance'), api.registry.createType('Balance'), api.registry.createType('Balance'), api.registry.createType('Index')]])
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
map((result): DerivedBalancesAccount => calcBalances(api, result))
|
map((result): DeriveBalancesAccount => calcBalances(api, result))
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
import { AccountId, AccountIndex, Address, Balance, BalanceLock, BalanceLockTo212, BlockNumber, VestingInfo, VestingSchedule } from '@polkadot/types/interfaces';
|
import { AccountId, AccountIndex, Address, Balance, BalanceLock, BalanceLockTo212, BlockNumber, VestingInfo, VestingSchedule } from '@polkadot/types/interfaces';
|
||||||
import { DerivedBalancesAccount, DerivedBalancesAll } from '../types';
|
import { DeriveBalancesAccount, DeriveBalancesAll } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
import BN from 'bn.js';
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
import { Observable, combineLatest, of } from 'rxjs';
|
||||||
@@ -15,9 +15,9 @@ import { bnMax } from '@polkadot/util';
|
|||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
type ResultBalance = [VestingInfo | null, (BalanceLock | BalanceLockTo212)[]];
|
type ResultBalance = [VestingInfo | null, (BalanceLock | BalanceLockTo212)[]];
|
||||||
type Result = [DerivedBalancesAccount, BlockNumber, ResultBalance];
|
type Result = [DeriveBalancesAccount, BlockNumber, ResultBalance];
|
||||||
|
|
||||||
function calcBalances (api: ApiInterfaceRx, [{ accountId, accountNonce, freeBalance, frozenFee, frozenMisc, reservedBalance, votingBalance }, bestNumber, [vesting, locks]]: Result): DerivedBalancesAll {
|
function calcBalances (api: ApiInterfaceRx, [{ accountId, accountNonce, freeBalance, frozenFee, frozenMisc, reservedBalance, votingBalance }, bestNumber, [vesting, locks]]: Result): DeriveBalancesAll {
|
||||||
let lockedBalance = api.registry.createType('Balance');
|
let lockedBalance = api.registry.createType('Balance');
|
||||||
let lockedBreakdown: (BalanceLock | BalanceLockTo212)[] = [];
|
let lockedBreakdown: (BalanceLock | BalanceLockTo212)[] = [];
|
||||||
let allLocked = false;
|
let allLocked = false;
|
||||||
@@ -127,8 +127,8 @@ function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<Re
|
|||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function all (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DerivedBalancesAll> {
|
export function all (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DeriveBalancesAll> {
|
||||||
return memo((address: AccountIndex | AccountId | Address | string): Observable<DerivedBalancesAll> =>
|
return memo((address: AccountIndex | AccountId | Address | string): Observable<DeriveBalancesAll> =>
|
||||||
api.derive.balances.account(address).pipe(
|
api.derive.balances.account(address).pipe(
|
||||||
switchMap((account): Observable<Result> =>
|
switchMap((account): Observable<Result> =>
|
||||||
(!account.accountId.isEmpty
|
(!account.accountId.isEmpty
|
||||||
@@ -142,6 +142,6 @@ export function all (api: ApiInterfaceRx): (address: AccountIndex | AccountId |
|
|||||||
: of([account, api.registry.createType('BlockNumber'), [null, api.registry.createType('Vec<BalanceLock>')]])
|
: of([account, api.registry.createType('BlockNumber'), [null, api.registry.createType('Vec<BalanceLock>')]])
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
map((result): DerivedBalancesAll => calcBalances(api, result))
|
map((result): DeriveBalancesAll => calcBalances(api, result))
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import { Balance } from '@polkadot/types/interfaces';
|
import { Balance } from '@polkadot/types/interfaces';
|
||||||
import { DerivedFees } from '../types';
|
import { DeriveFees } from '../types';
|
||||||
|
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
@@ -24,8 +24,8 @@ import { memo } from '../util';
|
|||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function fees (api: ApiInterfaceRx): () => Observable<DerivedFees> {
|
export function fees (api: ApiInterfaceRx): () => Observable<DeriveFees> {
|
||||||
return memo((): Observable<DerivedFees> =>
|
return memo((): Observable<DeriveFees> =>
|
||||||
of([
|
of([
|
||||||
// deprecated - remove
|
// deprecated - remove
|
||||||
(api.consts.balances?.creationFee as Balance) || api.registry.createType('Balance'),
|
(api.consts.balances?.creationFee as Balance) || api.registry.createType('Balance'),
|
||||||
@@ -36,7 +36,7 @@ export function fees (api: ApiInterfaceRx): () => Observable<DerivedFees> {
|
|||||||
(api.consts.transactionPayment?.transactionBaseFee as Balance) || api.registry.createType('Balance'),
|
(api.consts.transactionPayment?.transactionBaseFee as Balance) || api.registry.createType('Balance'),
|
||||||
(api.consts.transactionPayment?.transactionByteFee as Balance) || api.registry.createType('Balance')
|
(api.consts.transactionPayment?.transactionByteFee as Balance) || api.registry.createType('Balance')
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([creationFee, transferFee, existentialDeposit, transactionBaseFee, transactionByteFee]): DerivedFees => ({
|
map(([creationFee, transferFee, existentialDeposit, transactionBaseFee, transactionByteFee]): DeriveFees => ({
|
||||||
creationFee,
|
creationFee,
|
||||||
existentialDeposit,
|
existentialDeposit,
|
||||||
transactionBaseFee,
|
transactionBaseFee,
|
||||||
|
|||||||
@@ -3,19 +3,19 @@
|
|||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces';
|
import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces';
|
||||||
import { DerivedBalancesAccount } from '../types';
|
import { DeriveBalancesAccount } from '../types';
|
||||||
|
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
import { Observable, combineLatest, of } from 'rxjs';
|
||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
export function votingBalances (api: ApiInterfaceRx): (addresses?: (AccountId | AccountIndex | Address | string)[]) => Observable<DerivedBalancesAccount[]> {
|
export function votingBalances (api: ApiInterfaceRx): (addresses?: (AccountId | AccountIndex | Address | string)[]) => Observable<DeriveBalancesAccount[]> {
|
||||||
return memo((addresses?: (AccountId | AccountIndex | Address | string)[]): Observable<DerivedBalancesAccount[]> =>
|
return memo((addresses?: (AccountId | AccountIndex | Address | string)[]): Observable<DeriveBalancesAccount[]> =>
|
||||||
!addresses || !addresses.length
|
!addresses || !addresses.length
|
||||||
? of([] as DerivedBalancesAccount[])
|
? of([] as DeriveBalancesAccount[])
|
||||||
: combineLatest(
|
: combineLatest(
|
||||||
addresses.map((accountId): Observable<DerivedBalancesAccount> =>
|
addresses.map((accountId): Observable<DeriveBalancesAccount> =>
|
||||||
api.derive.balances.account(accountId)
|
api.derive.balances.account(accountId)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,17 +4,19 @@
|
|||||||
|
|
||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import { Hash, Proposal, Votes } from '@polkadot/types/interfaces';
|
import { Hash, Proposal, Votes } from '@polkadot/types/interfaces';
|
||||||
import { DerivedCollectiveProposal } from '../types';
|
import { DeriveCollectiveProposal } from '../types';
|
||||||
|
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
import { Observable, combineLatest, of } from 'rxjs';
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
import { Option } from '@polkadot/types';
|
import { Option } from '@polkadot/types';
|
||||||
|
|
||||||
|
import { memo } from '../util';
|
||||||
|
|
||||||
type Result = [Hash[], Option<Proposal>[], Option<Votes>[]];
|
type Result = [Hash[], Option<Proposal>[], Option<Votes>[]];
|
||||||
|
|
||||||
function parse ([hashes, proposals, votes]: Result): DerivedCollectiveProposal[] {
|
function parse ([hashes, proposals, votes]: Result): DeriveCollectiveProposal[] {
|
||||||
return proposals
|
return proposals
|
||||||
.map((proposalOpt, index): DerivedCollectiveProposal | null =>
|
.map((proposalOpt, index): DeriveCollectiveProposal | null =>
|
||||||
proposalOpt.isSome
|
proposalOpt.isSome
|
||||||
? {
|
? {
|
||||||
hash: hashes[index],
|
hash: hashes[index],
|
||||||
@@ -23,11 +25,11 @@ function parse ([hashes, proposals, votes]: Result): DerivedCollectiveProposal[]
|
|||||||
}
|
}
|
||||||
: null
|
: null
|
||||||
)
|
)
|
||||||
.filter((proposal): proposal is DerivedCollectiveProposal => !!proposal);
|
.filter((proposal): proposal is DeriveCollectiveProposal => !!proposal);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalCommittee'): () => Observable<DerivedCollectiveProposal[]> {
|
export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalCommittee'): () => Observable<DeriveCollectiveProposal[]> {
|
||||||
return (): Observable<DerivedCollectiveProposal[]> =>
|
return memo((): Observable<DeriveCollectiveProposal[]> =>
|
||||||
api.query[section]?.proposals
|
api.query[section]?.proposals
|
||||||
? api.query[section].proposals().pipe(
|
? api.query[section].proposals().pipe(
|
||||||
switchMap((hashes: Hash[]): Observable<Result> =>
|
switchMap((hashes: Hash[]): Observable<Result> =>
|
||||||
@@ -41,5 +43,6 @@ export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalC
|
|||||||
),
|
),
|
||||||
map(parse)
|
map(parse)
|
||||||
)
|
)
|
||||||
: of([] as DerivedCollectiveProposal[]);
|
: of([] as DeriveCollectiveProposal[])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import { DerivedContractFees } from '../types';
|
import { DeriveContractFees } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
import BN from 'bn.js';
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
@@ -44,10 +44,10 @@ function queryConstants (api: ApiInterfaceRx): Observable<ResultV2> {
|
|||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function fees (api: ApiInterfaceRx): () => Observable<DerivedContractFees> {
|
export function fees (api: ApiInterfaceRx): () => Observable<DeriveContractFees> {
|
||||||
return memo((): Observable<DerivedContractFees> => {
|
return memo((): Observable<DeriveContractFees> => {
|
||||||
return queryConstants(api).pipe(
|
return queryConstants(api).pipe(
|
||||||
map(([creationFee, transferFee, callBaseFee, contractFee, rentByteFee, rentDepositOffset, tombstoneDeposit, transactionBaseFee, transactionByteFee]): DerivedContractFees => ({
|
map(([creationFee, transferFee, callBaseFee, contractFee, rentByteFee, rentDepositOffset, tombstoneDeposit, transactionBaseFee, transactionByteFee]): DeriveContractFees => ({
|
||||||
callBaseFee,
|
callBaseFee,
|
||||||
contractFee,
|
contractFee,
|
||||||
creationFee,
|
creationFee,
|
||||||
|
|||||||
@@ -3,3 +3,5 @@
|
|||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
export * from './proposals';
|
export * from './proposals';
|
||||||
|
export * from './votes';
|
||||||
|
export * from './votesOf';
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import { DerivedCollectiveProposals } from '../types';
|
import { DeriveCollectiveProposals } from '../types';
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { proposals as collectiveProposals } from '../collective';
|
import { proposals as collectiveProposals } from '../collective';
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
export function proposals (api: ApiInterfaceRx): () => Observable<DerivedCollectiveProposals> {
|
export function proposals (api: ApiInterfaceRx): () => Observable<DeriveCollectiveProposals> {
|
||||||
return memo(collectiveProposals(api, 'council'));
|
return memo(collectiveProposals(api, 'council'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// 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, Balance } from '@polkadot/types/interfaces';
|
||||||
|
|
||||||
|
export interface DeriveCouncilVote {
|
||||||
|
stake: Balance;
|
||||||
|
votes: AccountId[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DeriveCouncilVotes = [AccountId, DeriveCouncilVote][];
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
// 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, Balance } from '@polkadot/types/interfaces';
|
||||||
|
import { ITuple } from '@polkadot/types/types';
|
||||||
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import { DeriveCouncilVote, DeriveCouncilVotes } from '../types';
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return elections.stakeOf.creator.meta.type.asMap.linked.isTrue
|
||||||
|
? elections.stakeOf<ITuple<[Vec<AccountId>, Vec<Balance>]>>().pipe(
|
||||||
|
map(([voters, stake]) =>
|
||||||
|
voters.map((voter, index): [AccountId, Balance] => [voter, stake[index]])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
: elections.stakeOf.entries<Balance>().pipe(
|
||||||
|
map((entries) =>
|
||||||
|
entries.map(([key, stake]) => [key.args[0] as AccountId, stake])
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function retrieveVoteOf (api: ApiInterfaceRx): Observable<[AccountId, AccountId[]][]> {
|
||||||
|
const elections = (api.query.electionsPhragmen || api.query.elections);
|
||||||
|
|
||||||
|
return elections.votesOf.creator.meta.type.asMap.linked.isTrue
|
||||||
|
? elections.votesOf<ITuple<[Vec<AccountId>, Vec<Vec<AccountId>>]>>().pipe(
|
||||||
|
map(([voters, votes]) =>
|
||||||
|
voters.map((voter, index) => [voter, votes[index]])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
: elections.votesOf.entries<Vec<AccountId>>().pipe(
|
||||||
|
map((entries) =>
|
||||||
|
entries.map(([key, votes]) => [key.args[0] as AccountId, votes])
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function retrievePrev (api: ApiInterfaceRx): Observable<DeriveCouncilVotes> {
|
||||||
|
return combineLatest([retrieveStakeOf(api), retrieveVoteOf(api)]).pipe(
|
||||||
|
map(([stakes, votes]): DeriveCouncilVotes => {
|
||||||
|
const result: DeriveCouncilVotes = [];
|
||||||
|
|
||||||
|
votes.forEach(([voter, votes]): void => {
|
||||||
|
result.push([voter, { stake: api.registry.createType('Balance'), votes }]);
|
||||||
|
});
|
||||||
|
|
||||||
|
stakes.forEach(([staker, stake]): void => {
|
||||||
|
const entry = result.find(([voter]) => voter.eq(staker));
|
||||||
|
|
||||||
|
if (entry) {
|
||||||
|
entry[1].stake = stake;
|
||||||
|
} else {
|
||||||
|
result.push([staker, { stake, votes: [] }]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function retrieveCurrent (api: ApiInterfaceRx): Observable<DeriveCouncilVotes> {
|
||||||
|
const elections = (api.query.electionsPhragmen || api.query.elections);
|
||||||
|
|
||||||
|
return elections.voting.entries<ITuple<[Balance, Vec<AccountId>]>>().pipe(
|
||||||
|
map((entries): DeriveCouncilVotes =>
|
||||||
|
entries.map(([key, [stake, votes]]): [AccountId, DeriveCouncilVote] =>
|
||||||
|
[key.args[0] as AccountId, { stake, votes }]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function votes (api: ApiInterfaceRx): () => Observable<DeriveCouncilVotes> {
|
||||||
|
return memo((): Observable<DeriveCouncilVotes> =>
|
||||||
|
(api.query.electionsPhragmen || api.query.elections).stakeOf
|
||||||
|
? retrievePrev(api)
|
||||||
|
: retrieveCurrent(api)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
// 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 } from '@polkadot/types/interfaces';
|
||||||
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
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> {
|
||||||
|
return memo((accountId: string | Uint8Array | AccountId): Observable<DeriveCouncilVote> =>
|
||||||
|
api.derive.council.votes().pipe(
|
||||||
|
map((votes): DeriveCouncilVote =>
|
||||||
|
(
|
||||||
|
votes.find(([from]) => from.eq(accountId)) ||
|
||||||
|
[null, { stake: api.registry.createType('Balance'), votes: [] as AccountId[] }]
|
||||||
|
)[1]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
// 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 { BlockNumber, Hash, ReferendumIndex, Scheduled } from '@polkadot/types/interfaces';
|
||||||
|
import { ITuple } from '@polkadot/types/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 { Option, Vec, u64 } from '@polkadot/types';
|
||||||
|
import { stringToHex } from '@polkadot/util';
|
||||||
|
|
||||||
|
import { memo } from '../util';
|
||||||
|
|
||||||
|
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,8 +2,14 @@
|
|||||||
// This software may be modified and distributed under the terms
|
// This software may be modified and distributed under the terms
|
||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
|
export * from './dispatchQueue';
|
||||||
|
export * from './nextExternal';
|
||||||
|
export * from './preimage';
|
||||||
|
export * from './preimages';
|
||||||
export * from './proposals';
|
export * from './proposals';
|
||||||
export * from './referendumInfos';
|
export * from './referendumIds';
|
||||||
export * from './referendums';
|
export * from './referendums';
|
||||||
export * from './referendumVotesFor';
|
export * from './referendumsActive';
|
||||||
export * from './votes';
|
export * from './referendumsFinished';
|
||||||
|
export * from './referendumsInfo';
|
||||||
|
export * from './sqrtElectorate';
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// 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 { Hash, VoteThreshold } from '@polkadot/types/interfaces';
|
||||||
|
import { ITuple } from '@polkadot/types/types';
|
||||||
|
import { DeriveProposalExternal } from '../types';
|
||||||
|
|
||||||
|
import { Observable, of } from 'rxjs';
|
||||||
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import { Option } from '@polkadot/types';
|
||||||
|
|
||||||
|
import { memo } from '../util';
|
||||||
|
|
||||||
|
function withImage (api: ApiInterfaceRx, nextOpt: Option<ITuple<[Hash, VoteThreshold]>>): Observable<DeriveProposalExternal | null> {
|
||||||
|
if (nextOpt.isNone) {
|
||||||
|
return of(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const [imageHash, threshold] = nextOpt.unwrap();
|
||||||
|
|
||||||
|
return api.derive.democracy.preimage(imageHash).pipe(
|
||||||
|
map((image): DeriveProposalExternal => ({
|
||||||
|
image,
|
||||||
|
imageHash,
|
||||||
|
threshold
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function nextExternal (api: ApiInterfaceRx): () => Observable<DeriveProposalExternal | null> {
|
||||||
|
return memo((): Observable<DeriveProposalExternal | null> =>
|
||||||
|
api.query.democracy?.nextExternal
|
||||||
|
? api.query.democracy.nextExternal<Option<ITuple<[Hash, VoteThreshold]>>>().pipe(
|
||||||
|
switchMap((nextOpt) => withImage(api, nextOpt))
|
||||||
|
)
|
||||||
|
: of(null)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// 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, Balance, BlockNumber, Hash } from '@polkadot/types/interfaces';
|
||||||
|
import { ITuple } from '@polkadot/types/types';
|
||||||
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import { DeriveProposalImage } from '../types';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
import { Bytes, Option } from '@polkadot/types';
|
||||||
|
|
||||||
|
import { memo } from '../util';
|
||||||
|
import { parseImage } from './util';
|
||||||
|
|
||||||
|
type PreImage = Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>;
|
||||||
|
|
||||||
|
export function preimage (api: ApiInterfaceRx): (hash: Hash) => Observable<DeriveProposalImage | undefined> {
|
||||||
|
return memo((hashes: Hash[]): Observable<DeriveProposalImage | undefined> =>
|
||||||
|
api.query.democracy.preimages<PreImage>(hashes).pipe(
|
||||||
|
map((imageOpt) => parseImage(api, imageOpt))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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 { AccountId, Balance, BlockNumber, Hash } from '@polkadot/types/interfaces';
|
||||||
|
import { ITuple } from '@polkadot/types/types';
|
||||||
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import { DeriveProposalImage } from '../types';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
import { Bytes, Option } from '@polkadot/types';
|
||||||
|
|
||||||
|
import { memo } from '../util';
|
||||||
|
import { parseImage } from './util';
|
||||||
|
|
||||||
|
type PreImage = Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>;
|
||||||
|
|
||||||
|
export function preimages (api: ApiInterfaceRx): (hashes: Hash[]) => Observable<(DeriveProposalImage | undefined)[]> {
|
||||||
|
return memo((hashes: Hash[]): Observable<(DeriveProposalImage | undefined)[]> =>
|
||||||
|
api.query.democracy.preimages.multi<PreImage>(hashes).pipe(
|
||||||
|
map((images): (DeriveProposalImage | undefined)[] =>
|
||||||
|
images.map((imageOpt) =>
|
||||||
|
parseImage(api, imageOpt)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,61 +2,35 @@
|
|||||||
// This software may be modified and distributed under the terms
|
// This software may be modified and distributed under the terms
|
||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
import { AccountId, Balance, BlockNumber, Hash, PropIndex, Proposal } from '@polkadot/types/interfaces';
|
import { AccountId, Balance, Hash, PropIndex } from '@polkadot/types/interfaces';
|
||||||
import { ITuple } from '@polkadot/types/types';
|
import { ITuple } from '@polkadot/types/types';
|
||||||
import { DeriveProposal } from '../types';
|
import { DeriveProposalImage, DeriveProposal } from '../types';
|
||||||
|
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
import { Observable, combineLatest, of } from 'rxjs';
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import { Bytes, Option, Vec } from '@polkadot/types';
|
import { Option, Vec } from '@polkadot/types';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
export type PreImage = Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>;
|
|
||||||
|
|
||||||
type Depositors = Option<ITuple<[Balance, Vec<AccountId>]>>;
|
type Depositors = Option<ITuple<[Balance, Vec<AccountId>]>>;
|
||||||
type Proposals = Vec<ITuple<[PropIndex, Hash, AccountId]>>;
|
type Proposals = Vec<ITuple<[PropIndex, Hash, AccountId]>>;
|
||||||
|
|
||||||
interface Result {
|
function parse ([proposals, images, depositors]: [Proposals, (DeriveProposalImage | undefined)[], Depositors[]]): DeriveProposal[] {
|
||||||
depositors: Depositors[];
|
|
||||||
preimages: PreImage[];
|
|
||||||
proposals: Proposals;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parse (api: ApiInterfaceRx, { depositors, proposals, preimages }: Result): DeriveProposal[] {
|
|
||||||
return proposals
|
return proposals
|
||||||
.filter(([, , proposer], index): boolean =>
|
.filter(([, , proposer], index): boolean =>
|
||||||
!!(depositors[index]?.isSome) && !proposer.isEmpty
|
!!(depositors[index]?.isSome) && !proposer.isEmpty
|
||||||
)
|
)
|
||||||
.map(([propIndex, hash, proposer], index): DeriveProposal => {
|
.map(([index, imageHash, proposer], proposalIndex): DeriveProposal => {
|
||||||
const preimage = preimages[index].unwrapOr(null);
|
const [balance, seconds] = depositors[proposalIndex].unwrap();
|
||||||
const depositor = depositors[index].unwrap();
|
|
||||||
let proposal: undefined | Proposal;
|
|
||||||
|
|
||||||
// we could end up in a situation where the proposal is non-decodable, e.g. after an upgrade
|
|
||||||
if (preimage) {
|
|
||||||
try {
|
|
||||||
proposal = api.registry.createType('Proposal', preimage[0].toU8a(true));
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
balance: depositor[0],
|
balance,
|
||||||
hash,
|
image: images[proposalIndex],
|
||||||
index: propIndex,
|
imageHash,
|
||||||
preimage: preimage
|
index,
|
||||||
? {
|
|
||||||
at: preimage[3],
|
|
||||||
balance: preimage[2],
|
|
||||||
proposer: preimage[1]
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
proposal,
|
|
||||||
proposer,
|
proposer,
|
||||||
seconds: depositor[1]
|
seconds
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -68,16 +42,14 @@ export function proposals (api: ApiInterfaceRx): () => Observable<DeriveProposal
|
|||||||
switchMap((proposals) =>
|
switchMap((proposals) =>
|
||||||
combineLatest([
|
combineLatest([
|
||||||
of(proposals),
|
of(proposals),
|
||||||
api.query.democracy.preimages.multi<PreImage>(
|
api.derive.democracy.preimages(
|
||||||
proposals.map(([, hash]): Hash => hash)),
|
proposals.map(([, hash]): Hash => hash)),
|
||||||
api.query.democracy.depositOf.multi<Depositors>(
|
api.query.democracy.depositOf.multi<Depositors>(
|
||||||
proposals.map(([index]): PropIndex => index))
|
proposals.map(([index]): PropIndex => index))
|
||||||
])
|
])
|
||||||
),
|
),
|
||||||
map(([proposals, preimages, depositors]): DeriveProposal[] =>
|
map(parse)
|
||||||
parse(api, { depositors, proposals, preimages })
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
: of([] as DeriveProposal[])
|
: of([])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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([])
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,80 +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 { ReferendumInfo, ReferendumInfoTo239, ReferendumStatus } from '@polkadot/types/interfaces';
|
|
||||||
import { DerivedReferendum } from '../types';
|
|
||||||
import { PreImage } from './proposals';
|
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
import { Observable, of } from 'rxjs';
|
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
|
||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
|
||||||
import { Option } from '@polkadot/types';
|
|
||||||
|
|
||||||
import { memo } from '../util';
|
|
||||||
|
|
||||||
function isOld (info: ReferendumInfo | ReferendumInfoTo239): info is ReferendumInfoTo239 {
|
|
||||||
return !!(info as ReferendumInfoTo239).proposalHash;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStatus (info: Option<ReferendumInfo | ReferendumInfoTo239>): ReferendumStatus | ReferendumInfoTo239 | null {
|
|
||||||
if (info.isNone) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unwrapped = info.unwrap();
|
|
||||||
|
|
||||||
if (isOld(unwrapped)) {
|
|
||||||
return unwrapped;
|
|
||||||
} else if (unwrapped.isOngoing) {
|
|
||||||
return unwrapped.asOngoing;
|
|
||||||
}
|
|
||||||
|
|
||||||
// done, we don't include it here... only currently active
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function constructInfo (api: ApiInterfaceRx, index: BN | number, status: ReferendumStatus | ReferendumInfoTo239, _preimage?: PreImage): DerivedReferendum | null {
|
|
||||||
const preImage = _preimage?.isSome
|
|
||||||
? _preimage.unwrap()
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return {
|
|
||||||
index: api.registry.createType('PropIndex', index),
|
|
||||||
hash: status.proposalHash,
|
|
||||||
proposal: preImage
|
|
||||||
? api.registry.createType('Proposal', preImage[0].toU8a(true))
|
|
||||||
: undefined,
|
|
||||||
preimage: preImage
|
|
||||||
? {
|
|
||||||
at: preImage[3],
|
|
||||||
balance: preImage[2],
|
|
||||||
proposer: preImage[1]
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
status
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function retrieveInfo (api: ApiInterfaceRx, index: BN | number, info: Option<ReferendumInfo | ReferendumInfoTo239>): Observable<DerivedReferendum | null> {
|
|
||||||
const status = getStatus(info);
|
|
||||||
|
|
||||||
return status
|
|
||||||
? api.query.democracy.preimages(status.proposalHash).pipe(
|
|
||||||
map((preimage?: PreImage): DerivedReferendum | null =>
|
|
||||||
constructInfo(api, index, status, preimage)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
: of(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function referendumInfo (api: ApiInterfaceRx): (index: BN | number) => Observable<DerivedReferendum | null> {
|
|
||||||
return memo((index: BN | number): Observable<DerivedReferendum | null> =>
|
|
||||||
api.query.democracy.referendumInfoOf<Option<ReferendumInfo | ReferendumInfoTo239>>(index).pipe(
|
|
||||||
switchMap((info): Observable<DerivedReferendum | null> =>
|
|
||||||
retrieveInfo(api, index, info)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,35 +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 { ReferendumInfo } from '@polkadot/types/interfaces/democracy';
|
|
||||||
import { DerivedReferendum } from '../types';
|
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
|
||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
|
||||||
import { Option } from '@polkadot/types';
|
|
||||||
|
|
||||||
import { memo } from '../util';
|
|
||||||
import { retrieveInfo } from './referendumInfo';
|
|
||||||
|
|
||||||
export function referendumInfos (api: ApiInterfaceRx): (ids?: (BN | number)[]) => Observable<DerivedReferendum[]> {
|
|
||||||
return memo((ids: (BN | number)[] = []): Observable<DerivedReferendum[]> =>
|
|
||||||
(
|
|
||||||
!ids?.length
|
|
||||||
? of([] as Option<ReferendumInfo>[])
|
|
||||||
: api.query.democracy.referendumInfoOf.multi<Option<ReferendumInfo>>(ids)
|
|
||||||
).pipe(
|
|
||||||
switchMap((infos): Observable<(DerivedReferendum | null)[]> =>
|
|
||||||
combineLatest(
|
|
||||||
ids.map((id, index): Observable<DerivedReferendum | null> =>
|
|
||||||
retrieveInfo(api, id, infos[index])
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
map((infos): DerivedReferendum[] =>
|
|
||||||
infos.filter((referendum): referendum is DerivedReferendum => !!referendum)
|
|
||||||
)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
@@ -1,34 +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 { AccountId, Vote } from '@polkadot/types/interfaces';
|
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
|
||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
|
||||||
import { Vec } from '@polkadot/types';
|
|
||||||
|
|
||||||
import { DerivedBalancesAccount, DerivedReferendumVote } from '../types';
|
|
||||||
import { memo } from '../util';
|
|
||||||
|
|
||||||
export function referendumVotesFor (api: ApiInterfaceRx): (referendumId: BN | number) => Observable<DerivedReferendumVote[]> {
|
|
||||||
return memo((referendumId: BN | number): Observable<DerivedReferendumVote[]> =>
|
|
||||||
api.query.democracy.votersFor<Vec<AccountId>>(referendumId).pipe(
|
|
||||||
switchMap((votersFor): Observable<[Vec<AccountId>, Vote[], DerivedBalancesAccount[]]> =>
|
|
||||||
combineLatest([
|
|
||||||
of(votersFor),
|
|
||||||
api.derive.democracy.votes(referendumId, votersFor),
|
|
||||||
api.derive.balances.votingBalances(votersFor)
|
|
||||||
])
|
|
||||||
),
|
|
||||||
map(([votersFor, votes, balances]): DerivedReferendumVote[] =>
|
|
||||||
votersFor.map((accountId, index): DerivedReferendumVote => ({
|
|
||||||
accountId,
|
|
||||||
balance: balances[index].votingBalance || api.registry.createType('Balance'),
|
|
||||||
vote: votes[index] || api.registry.createType('Vote')
|
|
||||||
} as DerivedReferendumVote))
|
|
||||||
)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
@@ -2,33 +2,29 @@
|
|||||||
// This software may be modified and distributed under the terms
|
// This software may be modified and distributed under the terms
|
||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
import { ReferendumIndex } from '@polkadot/types/interfaces/democracy';
|
|
||||||
import { DerivedReferendum } from '../types';
|
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
import { Observable, of } from 'rxjs';
|
|
||||||
import { switchMap } from 'rxjs/operators';
|
|
||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import { DeriveReferendumExt } from '../types';
|
||||||
|
|
||||||
|
import { Observable, combineLatest, of } from 'rxjs';
|
||||||
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
export function referendums (api: ApiInterfaceRx): () => Observable<DerivedReferendum[]> {
|
export function referendums (api: ApiInterfaceRx): () => Observable<DeriveReferendumExt[]> {
|
||||||
return memo((): Observable<DerivedReferendum[]> =>
|
return memo((): Observable<DeriveReferendumExt[]> =>
|
||||||
api.query.democracy?.lowestUnbaked
|
api.derive.democracy.referendumsActive().pipe(
|
||||||
? api.queryMulti<[ReferendumIndex, ReferendumIndex]>([
|
switchMap((referendums) =>
|
||||||
api.query.democracy.lowestUnbaked,
|
combineLatest([
|
||||||
api.query.democracy.referendumCount
|
of(referendums),
|
||||||
]).pipe(
|
api.derive.democracy._referendumsVotes(referendums)
|
||||||
switchMap(([earliest, referendumCount]): Observable<DerivedReferendum[]> =>
|
])
|
||||||
referendumCount?.gt(earliest) && referendumCount?.gtn(0)
|
),
|
||||||
? api.derive.democracy.referendumInfos(
|
map(([referendums, votes]) =>
|
||||||
[...Array(referendumCount.sub(earliest).toNumber())].map((_, i): BN =>
|
referendums.map((referendum, index): DeriveReferendumExt => ({
|
||||||
earliest.addn(i)
|
...referendum,
|
||||||
)
|
...votes[index]
|
||||||
)
|
}))
|
||||||
: of([])
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
: of([] as DerivedReferendum[])
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// 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 } from '../types';
|
||||||
|
|
||||||
|
import { Observable, of } from 'rxjs';
|
||||||
|
import { switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { memo } from '../util';
|
||||||
|
|
||||||
|
export function referendumsActive (api: ApiInterfaceRx): () => Observable<DeriveReferendum[]> {
|
||||||
|
return memo((): Observable<DeriveReferendum[]> =>
|
||||||
|
api.derive.democracy.referendumIds().pipe(
|
||||||
|
switchMap((ids): Observable<DeriveReferendum[]> =>
|
||||||
|
ids.length
|
||||||
|
? api.derive.democracy.referendumsInfo(ids)
|
||||||
|
: 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)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
// 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, 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, 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[]> =>
|
||||||
|
ids.length
|
||||||
|
? api.query.democracy.referendumInfoOf.multi<Option<ReferendumInfo>>(ids).pipe(
|
||||||
|
switchMap((infos): Observable<(DeriveReferendum | null)[]> =>
|
||||||
|
combineLatest(
|
||||||
|
ids.map((id, index): Observable<DeriveReferendum | null> =>
|
||||||
|
api.derive.democracy._referendumInfo(id, infos[index])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
map((infos) =>
|
||||||
|
infos.filter((referendum): referendum is DeriveReferendum => !!referendum)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
: of([])
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// 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 BN from 'bn.js';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
import { bnSqrt } from '@polkadot/util';
|
||||||
|
|
||||||
|
import { memo } from '../util';
|
||||||
|
|
||||||
|
export function sqrtElectorate (api: ApiInterfaceRx): () => Observable<BN> {
|
||||||
|
return memo((): Observable<BN> =>
|
||||||
|
api.query.balances.totalIssuance().pipe(
|
||||||
|
map((totalIssuance) =>
|
||||||
|
bnSqrt(totalIssuance)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
// 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, Balance, BlockNumber, Hash, Proposal, PropIndex, ReferendumInfoTo239, ReferendumStatus, Vote, ReferendumIndex, VoteThreshold } from '@polkadot/types/interfaces';
|
||||||
|
|
||||||
|
import BN from 'bn.js';
|
||||||
|
import { Vec } from '@polkadot/types';
|
||||||
|
|
||||||
|
export interface DeriveDispatch {
|
||||||
|
at: BlockNumber;
|
||||||
|
index: ReferendumIndex;
|
||||||
|
imageHash: Hash;
|
||||||
|
image?: DeriveProposalImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeriveProposalImage {
|
||||||
|
at: BlockNumber;
|
||||||
|
balance: Balance;
|
||||||
|
proposal?: Proposal;
|
||||||
|
proposer: AccountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeriveProposal {
|
||||||
|
balance?: Balance;
|
||||||
|
index: PropIndex;
|
||||||
|
image?: DeriveProposalImage;
|
||||||
|
imageHash: Hash;
|
||||||
|
proposer: AccountId;
|
||||||
|
seconds: Vec<AccountId>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeriveProposalExternal {
|
||||||
|
image?: DeriveProposalImage;
|
||||||
|
imageHash: Hash;
|
||||||
|
threshold: VoteThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeriveReferendum {
|
||||||
|
index: ReferendumIndex;
|
||||||
|
image?: DeriveProposalImage;
|
||||||
|
imageHash: Hash;
|
||||||
|
status: ReferendumStatus | ReferendumInfoTo239;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeriveReferendumVote {
|
||||||
|
accountId: AccountId;
|
||||||
|
balance: Balance;
|
||||||
|
vote: Vote;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeriveReferendumVoteState {
|
||||||
|
allAye: DeriveReferendumVote[];
|
||||||
|
allNay: DeriveReferendumVote[];
|
||||||
|
voteCount: number;
|
||||||
|
voteCountAye: number;
|
||||||
|
voteCountNay: number;
|
||||||
|
votedAye: BN;
|
||||||
|
votedNay: BN;
|
||||||
|
votedTotal: BN;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeriveReferendumVotes extends DeriveReferendumVoteState {
|
||||||
|
isPassing: boolean;
|
||||||
|
votes: DeriveReferendumVote[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeriveReferendumExt extends DeriveReferendum, DeriveReferendumVotes {
|
||||||
|
}
|
||||||
@@ -0,0 +1,191 @@
|
|||||||
|
// 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, 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';
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isCurrentStatus (status: ReferendumStatus | ReferendumInfoTo239): status is ReferendumStatus {
|
||||||
|
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);
|
||||||
|
const q2 = n2.div(d2);
|
||||||
|
|
||||||
|
if (q1.lt(q2)) {
|
||||||
|
return true;
|
||||||
|
} else if (q2.lt(q1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const r1 = n1.mod(d1);
|
||||||
|
const r2 = n2.mod(d2);
|
||||||
|
|
||||||
|
if (r2.isZero()) {
|
||||||
|
return false;
|
||||||
|
} else if (r1.isZero()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
n1 = d2;
|
||||||
|
n2 = d1;
|
||||||
|
d1 = r2;
|
||||||
|
d2 = r1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function calcPassing (threshold: VoteThreshold, sqrtElectorate: BN, { votedAye, votedNay, votedTotal }: ApproxState): boolean {
|
||||||
|
const sqrtVoters = bnSqrt(votedTotal);
|
||||||
|
|
||||||
|
return sqrtVoters.isZero()
|
||||||
|
? false
|
||||||
|
: threshold.isSimplemajority
|
||||||
|
? votedAye.gt(votedNay)
|
||||||
|
: threshold.isSupermajorityapproval
|
||||||
|
? compareRationals(votedNay, sqrtVoters, votedAye, sqrtElectorate)
|
||||||
|
: compareRationals(votedNay, sqrtElectorate, votedAye, sqrtVoters);
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcVotesPrev (votesFor: DeriveReferendumVote[]): DeriveReferendumVoteState {
|
||||||
|
return votesFor.reduce((state: DeriveReferendumVoteState, derived): DeriveReferendumVoteState => {
|
||||||
|
const { balance, vote } = derived;
|
||||||
|
const isDefault = vote.conviction.index === 0;
|
||||||
|
const counted = balance
|
||||||
|
.muln(isDefault ? 1 : vote.conviction.index)
|
||||||
|
.divn(isDefault ? 10 : 1);
|
||||||
|
|
||||||
|
if (vote.isAye) {
|
||||||
|
state.allAye.push(derived);
|
||||||
|
state.voteCountAye++;
|
||||||
|
state.votedAye = state.votedAye.add(counted);
|
||||||
|
} else {
|
||||||
|
state.allNay.push(derived);
|
||||||
|
state.voteCountNay++;
|
||||||
|
state.votedNay = state.votedNay.add(counted);
|
||||||
|
}
|
||||||
|
|
||||||
|
state.voteCount++;
|
||||||
|
state.votedTotal = state.votedTotal.add(counted);
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}, {
|
||||||
|
allAye: [],
|
||||||
|
allNay: [],
|
||||||
|
voteCount: 0,
|
||||||
|
voteCountAye: 0,
|
||||||
|
voteCountNay: 0,
|
||||||
|
votedAye: new BN(0),
|
||||||
|
votedNay: new BN(0),
|
||||||
|
votedTotal: new BN(0)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcVotesCurrent (tally: Tally, votes: DeriveReferendumVote[]): DeriveReferendumVoteState {
|
||||||
|
const allAye: DeriveReferendumVote[] = [];
|
||||||
|
const allNay: DeriveReferendumVote[] = [];
|
||||||
|
|
||||||
|
votes.forEach((derived): void => {
|
||||||
|
if (derived.vote.isAye) {
|
||||||
|
allAye.push(derived);
|
||||||
|
} else {
|
||||||
|
allNay.push(derived);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
allAye,
|
||||||
|
allNay,
|
||||||
|
voteCount: allAye.length + allNay.length,
|
||||||
|
voteCountAye: allAye.length,
|
||||||
|
voteCountNay: allNay.length,
|
||||||
|
votedAye: tally.ayes,
|
||||||
|
votedNay: tally.nays,
|
||||||
|
votedTotal: tally.turnout
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function calcVotes (sqrtElectorate: BN, referendum: DeriveReferendum, votes: DeriveReferendumVote[]): DeriveReferendumVotes {
|
||||||
|
const state = isCurrentStatus(referendum.status)
|
||||||
|
? calcVotesCurrent(referendum.status.tally, votes)
|
||||||
|
: calcVotesPrev(votes);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
isPassing: calcPassing(referendum.status.threshold, sqrtElectorate, state),
|
||||||
|
votes
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getStatus (info: Option<ReferendumInfo | ReferendumInfoTo239>): ReferendumStatus | ReferendumInfoTo239 | null {
|
||||||
|
if (info.isNone) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unwrapped = info.unwrap();
|
||||||
|
|
||||||
|
if (isOldInfo(unwrapped)) {
|
||||||
|
return unwrapped;
|
||||||
|
} else if (unwrapped.isOngoing) {
|
||||||
|
return unwrapped.asOngoing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// done, we don't include it here... only currently active
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function constructProposal (api: ApiInterfaceRx, [bytes, proposer, balance, at]: PreimageInfo): DeriveProposalImage {
|
||||||
|
let proposal: Proposal | undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
proposal = api.registry.createType('Proposal', bytes.toU8a(true));
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
@@ -1,23 +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 { AccountId, Vote } from '@polkadot/types/interfaces';
|
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
import { Observable, of } from 'rxjs';
|
|
||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
|
||||||
|
|
||||||
import { memo } from '../util';
|
|
||||||
|
|
||||||
export function votes (api: ApiInterfaceRx): (referendumId: BN | number, accountIds?: AccountId[]) => Observable<Vote[]> {
|
|
||||||
return memo((referendumId: BN | number, accountIds: AccountId[] = []): Observable<Vote[]> =>
|
|
||||||
!accountIds || !accountIds.length
|
|
||||||
? of([] as Vote[])
|
|
||||||
: api.query.democracy.voteOf.multi<Vote>(
|
|
||||||
accountIds.map((accountId): [BN | number, AccountId] =>
|
|
||||||
[referendumId, accountId]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -10,14 +10,14 @@ import { map } from 'rxjs/operators';
|
|||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import { Vec, u32 } from '@polkadot/types';
|
import { Vec, u32 } from '@polkadot/types';
|
||||||
|
|
||||||
import { DerivedElectionsInfo } from '../types';
|
import { DeriveElectionsInfo } from '../types';
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
function sortAccounts ([, balanceA]: ITuple<[AccountId, Balance]>, [, balanceB]: ITuple<[AccountId, Balance]>): number {
|
function sortAccounts ([, balanceA]: ITuple<[AccountId, Balance]>, [, balanceB]: ITuple<[AccountId, Balance]>): number {
|
||||||
return balanceB.cmp(balanceA);
|
return balanceB.cmp(balanceA);
|
||||||
}
|
}
|
||||||
|
|
||||||
function queryElections (api: ApiInterfaceRx): Observable<DerivedElectionsInfo> {
|
function queryElections (api: ApiInterfaceRx): Observable<DeriveElectionsInfo> {
|
||||||
const section = api.query.electionsPhragmen ? 'electionsPhragmen' : 'elections';
|
const section = api.query.electionsPhragmen ? 'electionsPhragmen' : 'elections';
|
||||||
|
|
||||||
return api.queryMulti<[Vec<AccountId>, Vec<AccountId>, Vec<ITuple<[AccountId, Balance]>>, Vec<ITuple<[AccountId, Balance]>>]>([
|
return api.queryMulti<[Vec<AccountId>, Vec<AccountId>, Vec<ITuple<[AccountId, Balance]>>, Vec<ITuple<[AccountId, Balance]>>]>([
|
||||||
@@ -26,10 +26,10 @@ function queryElections (api: ApiInterfaceRx): Observable<DerivedElectionsInfo>
|
|||||||
api.query[section].members,
|
api.query[section].members,
|
||||||
api.query[section].runnersUp
|
api.query[section].runnersUp
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([councilMembers, candidates, members, runnersUp]): DerivedElectionsInfo => ({
|
map(([councilMembers, candidates, members, runnersUp]): DeriveElectionsInfo => ({
|
||||||
candidates,
|
|
||||||
candidateCount: api.registry.createType('u32', candidates.length),
|
|
||||||
candidacyBond: api.consts[section].candidacyBond as Balance,
|
candidacyBond: api.consts[section].candidacyBond as Balance,
|
||||||
|
candidateCount: api.registry.createType('u32', candidates.length),
|
||||||
|
candidates,
|
||||||
desiredSeats: api.consts[section].desiredMembers as u32,
|
desiredSeats: api.consts[section].desiredMembers as u32,
|
||||||
members: members.length
|
members: members.length
|
||||||
? members.sort(sortAccounts)
|
? members.sort(sortAccounts)
|
||||||
@@ -54,6 +54,6 @@ function queryElections (api: ApiInterfaceRx): Observable<DerivedElectionsInfo>
|
|||||||
* });
|
* });
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function info (api: ApiInterfaceRx): () => Observable<DerivedElectionsInfo> {
|
export function info (api: ApiInterfaceRx): () => Observable<DeriveElectionsInfo> {
|
||||||
return memo((): Observable<DerivedElectionsInfo> => queryElections(api));
|
return memo((): Observable<DeriveElectionsInfo> => queryElections(api));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
import { AccountId } from '@polkadot/types/interfaces';
|
import { AccountId } from '@polkadot/types/interfaces';
|
||||||
import { DerivedHeartbeats } from '../types';
|
import { DeriveHeartbeats } from '../types';
|
||||||
|
|
||||||
import { Observable, of, combineLatest } from 'rxjs';
|
import { Observable, of, combineLatest } from 'rxjs';
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
@@ -15,8 +15,8 @@ import { memo } from '../util';
|
|||||||
/**
|
/**
|
||||||
* @description Return a boolean array indicating whether the passed accounts had received heartbeats in the current session
|
* @description Return a boolean array indicating whether the passed accounts had received heartbeats in the current session
|
||||||
*/
|
*/
|
||||||
export function receivedHeartbeats (api: ApiInterfaceRx): () => Observable<DerivedHeartbeats> {
|
export function receivedHeartbeats (api: ApiInterfaceRx): () => Observable<DeriveHeartbeats> {
|
||||||
return memo((): Observable<DerivedHeartbeats> =>
|
return memo((): Observable<DeriveHeartbeats> =>
|
||||||
api.query.imOnline?.receivedHeartbeats
|
api.query.imOnline?.receivedHeartbeats
|
||||||
? api.derive.staking.overview().pipe(
|
? api.derive.staking.overview().pipe(
|
||||||
switchMap(({ currentIndex, validators }): Observable<[AccountId[], Option<Bytes>[], u32[]]> =>
|
switchMap(({ currentIndex, validators }): Observable<[AccountId[], Option<Bytes>[], u32[]]> =>
|
||||||
@@ -28,8 +28,8 @@ export function receivedHeartbeats (api: ApiInterfaceRx): () => Observable<Deriv
|
|||||||
validators.map((address) => [currentIndex, address]))
|
validators.map((address) => [currentIndex, address]))
|
||||||
])
|
])
|
||||||
),
|
),
|
||||||
map(([validators, heartbeats, numBlocks]): DerivedHeartbeats =>
|
map(([validators, heartbeats, numBlocks]): DeriveHeartbeats =>
|
||||||
validators.reduce((result: DerivedHeartbeats, validator, index): DerivedHeartbeats => ({
|
validators.reduce((result: DeriveHeartbeats, validator, index): DeriveHeartbeats => ({
|
||||||
...result,
|
...result,
|
||||||
[validator.toString()]: {
|
[validator.toString()]: {
|
||||||
blockCount: numBlocks[index],
|
blockCount: numBlocks[index],
|
||||||
|
|||||||
@@ -49,10 +49,8 @@ describe('derive', (): void => {
|
|||||||
testFunction(api)('chain', 'bestNumber', []);
|
testFunction(api)('chain', 'bestNumber', []);
|
||||||
testFunction(api)('chain', 'bestNumberFinalized', []);
|
testFunction(api)('chain', 'bestNumberFinalized', []);
|
||||||
|
|
||||||
testFunction(api)('democracy', 'referendumInfos', []);
|
testFunction(api)('democracy', 'proposals', []);
|
||||||
testFunction(api)('democracy', 'referendums', []);
|
testFunction(api)('democracy', 'referendums', []);
|
||||||
testFunction(api)('democracy', 'referendumVotesFor', []);
|
|
||||||
testFunction(api)('democracy', 'votes', []);
|
|
||||||
|
|
||||||
testFunction(api)('elections', 'info', []);
|
testFunction(api)('elections', 'info', []);
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,11 @@ import * as society from './society';
|
|||||||
import * as staking from './staking';
|
import * as staking from './staking';
|
||||||
import * as technicalCommittee from './technicalCommittee';
|
import * as technicalCommittee from './technicalCommittee';
|
||||||
import * as treasury from './treasury';
|
import * as treasury from './treasury';
|
||||||
|
import * as tx from './tx';
|
||||||
|
|
||||||
export * from './type';
|
export * from './type';
|
||||||
|
|
||||||
export const derive = { accounts, balances, chain, contracts, council, democracy, elections, imOnline, parachains, session, society, staking, technicalCommittee, treasury };
|
export const derive = { accounts, balances, chain, contracts, council, democracy, elections, imOnline, parachains, session, society, staking, technicalCommittee, treasury, tx };
|
||||||
|
|
||||||
type DeriveSection<Section> = {
|
type DeriveSection<Section> = {
|
||||||
[Method in keyof Section]: Section[Method] extends AnyFunction
|
[Method in keyof Section]: Section[Method] extends AnyFunction
|
||||||
@@ -76,6 +77,7 @@ function injectFunctions<AllSections> (api: ApiInterfaceRx, allSections: AllSect
|
|||||||
const methodName = _methodName as keyof typeof section;
|
const methodName = _methodName as keyof typeof section;
|
||||||
// Not sure what to do here, casting as any. Though the final types are good
|
// Not sure what to do here, casting as any. Though the final types are good
|
||||||
const method = (section[methodName] as any)(api);
|
const method = (section[methodName] as any)(api);
|
||||||
|
|
||||||
// idem
|
// idem
|
||||||
(sectionAcc as any)[methodName] = method;
|
(sectionAcc as any)[methodName] = method;
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ function parseActive (id: ParaId, active: Active): DeriveParachainActive | null
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { memo } from '../util';
|
|||||||
|
|
||||||
export function eraProgress (api: ApiInterfaceRx): () => Observable<BlockNumber> {
|
export function eraProgress (api: ApiInterfaceRx): () => Observable<BlockNumber> {
|
||||||
return memo((): Observable<BlockNumber> =>
|
return memo((): Observable<BlockNumber> =>
|
||||||
api.derive.session.info().pipe(
|
api.derive.session.progress().pipe(
|
||||||
map((info) => info.eraProgress)
|
map((info) => info.eraProgress)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ export * from './eraLength';
|
|||||||
export * from './eraProgress';
|
export * from './eraProgress';
|
||||||
export * from './indexes';
|
export * from './indexes';
|
||||||
export * from './info';
|
export * from './info';
|
||||||
|
export * from './progress';
|
||||||
export * from './sessionProgress';
|
export * from './sessionProgress';
|
||||||
|
|||||||
@@ -3,110 +3,69 @@
|
|||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
import { SessionIndex } from '@polkadot/types/interfaces';
|
import { SessionIndex } from '@polkadot/types/interfaces';
|
||||||
import { DerivedSessionInfo, DeriveSessionIndexes } from '../types';
|
import { DeriveSessionInfo, DeriveSessionIndexes } from '../types';
|
||||||
|
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import { Option, u64 } from '@polkadot/types';
|
import { u64 } from '@polkadot/types';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
type ResultSlots = [u64, u64, u64, Option<SessionIndex>];
|
|
||||||
type ResultSlotsFlat = [u64, u64, u64, SessionIndex];
|
|
||||||
type ResultType = [boolean, u64, SessionIndex];
|
type ResultType = [boolean, u64, SessionIndex];
|
||||||
type Result = [ResultType, DeriveSessionIndexes, ResultSlotsFlat];
|
type Result = [ResultType, DeriveSessionIndexes];
|
||||||
|
|
||||||
function createDerived (api: ApiInterfaceRx, [[hasBabe, epochDuration, sessionsPerEra], { activeEra, activeEraStart, currentEra, currentIndex, validatorCount }, [currentSlot, epochIndex, epochOrGenesisStartSlot, activeEraStartSessionIndex]]: Result): DerivedSessionInfo {
|
|
||||||
const epochStartSlot = epochIndex.mul(epochDuration).add(epochOrGenesisStartSlot);
|
|
||||||
const sessionProgress = currentSlot.sub(epochStartSlot);
|
|
||||||
const eraProgress = currentIndex.sub(activeEraStartSessionIndex).mul(epochDuration).add(sessionProgress);
|
|
||||||
|
|
||||||
|
function createDerive (api: ApiInterfaceRx, [[hasBabe, epochDuration, sessionsPerEra], { activeEra, activeEraStart, currentEra, currentIndex, validatorCount }]: Result): DeriveSessionInfo {
|
||||||
return {
|
return {
|
||||||
activeEra,
|
activeEra,
|
||||||
activeEraStart,
|
activeEraStart,
|
||||||
currentEra,
|
currentEra,
|
||||||
currentIndex,
|
currentIndex,
|
||||||
eraLength: api.registry.createType('BlockNumber', sessionsPerEra.mul(epochDuration)),
|
eraLength: api.registry.createType('BlockNumber', sessionsPerEra.mul(epochDuration)),
|
||||||
eraProgress: api.registry.createType('BlockNumber', eraProgress),
|
|
||||||
isEpoch: hasBabe,
|
isEpoch: hasBabe,
|
||||||
sessionLength: epochDuration,
|
sessionLength: epochDuration,
|
||||||
sessionsPerEra,
|
sessionsPerEra,
|
||||||
sessionProgress: api.registry.createType('BlockNumber', sessionProgress),
|
|
||||||
validatorCount
|
validatorCount
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function queryAura (api: ApiInterfaceRx): Observable<DerivedSessionInfo> {
|
function queryAura (api: ApiInterfaceRx): Observable<DeriveSessionInfo> {
|
||||||
return api.derive.session.indexes().pipe(
|
return api.derive.session.indexes().pipe(
|
||||||
map((indexes): DerivedSessionInfo =>
|
map((indexes): DeriveSessionInfo =>
|
||||||
createDerived(api, [
|
createDerive(api, [
|
||||||
[
|
[
|
||||||
false,
|
false,
|
||||||
api.registry.createType('u64', 1),
|
api.registry.createType('u64', 1),
|
||||||
api.consts.staking?.sessionsPerEra || api.registry.createType('SessionIndex', 1)
|
api.consts.staking?.sessionsPerEra || api.registry.createType('SessionIndex', 1)
|
||||||
],
|
],
|
||||||
indexes,
|
indexes
|
||||||
[
|
|
||||||
api.registry.createType('u64', 1),
|
|
||||||
api.registry.createType('u64', 1),
|
|
||||||
api.registry.createType('u64', 1),
|
|
||||||
api.registry.createType('SessionIndex', 1)
|
|
||||||
]
|
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function queryBabe (api: ApiInterfaceRx): Observable<[DeriveSessionIndexes, ResultSlotsFlat]> {
|
function queryBabe (api: ApiInterfaceRx): Observable<DeriveSessionInfo> {
|
||||||
return api.derive.session.indexes().pipe(
|
return api.derive.session.indexes().pipe(
|
||||||
switchMap((indexes): Observable<[DeriveSessionIndexes, ResultSlots]> =>
|
map((indexes) =>
|
||||||
combineLatest([
|
createDerive(api, [
|
||||||
of(indexes),
|
[
|
||||||
api.queryMulti<ResultSlots>([
|
true,
|
||||||
api.query.babe.currentSlot,
|
api.consts.babe.epochDuration,
|
||||||
api.query.babe.epochIndex,
|
api.consts.staking.sessionsPerEra
|
||||||
api.query.babe.genesisSlot,
|
],
|
||||||
[api.query.staking.erasStartSessionIndex, indexes.activeEra]
|
indexes
|
||||||
])
|
|
||||||
])
|
])
|
||||||
),
|
)
|
||||||
map(([indexes, [currentSlot, epochIndex, genesisSlot, optStartIndex]]): [DeriveSessionIndexes, ResultSlotsFlat] => [
|
|
||||||
indexes, [currentSlot, epochIndex, genesisSlot, optStartIndex.unwrapOr(api.registry.createType('SessionIndex', 1))]
|
|
||||||
])
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function queryBabeNoHistory (api: ApiInterfaceRx): Observable<[DeriveSessionIndexes, ResultSlotsFlat]> {
|
|
||||||
return combineLatest([
|
|
||||||
api.derive.session.indexes(),
|
|
||||||
api.queryMulti<ResultSlotsFlat>([
|
|
||||||
api.query.babe.currentSlot,
|
|
||||||
api.query.babe.epochIndex,
|
|
||||||
api.query.babe.genesisSlot,
|
|
||||||
api.query.staking.currentEraStartSessionIndex
|
|
||||||
])
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Retrieves all the session and era query and calculates specific values on it as the length of the session and eras
|
* @description Retrieves all the session and era query and calculates specific values on it as the length of the session and eras
|
||||||
*/
|
*/
|
||||||
export function info (api: ApiInterfaceRx): () => Observable<DerivedSessionInfo> {
|
export function info (api: ApiInterfaceRx): () => Observable<DeriveSessionInfo> {
|
||||||
return memo((): Observable<DerivedSessionInfo> =>
|
return memo((): Observable<DeriveSessionInfo> =>
|
||||||
api.consts.babe
|
api.consts.babe
|
||||||
? (api.query.staking.erasStartSessionIndex
|
? queryBabe(api)
|
||||||
? queryBabe(api) // 2.x with Babe
|
|
||||||
: queryBabeNoHistory(api)
|
|
||||||
).pipe(
|
|
||||||
map(([indexes, slots]: [DeriveSessionIndexes, ResultSlotsFlat]): DerivedSessionInfo =>
|
|
||||||
createDerived(api, [
|
|
||||||
[true, api.consts.babe.epochDuration, api.consts.staking.sessionsPerEra],
|
|
||||||
indexes,
|
|
||||||
slots
|
|
||||||
])
|
|
||||||
)
|
|
||||||
)
|
|
||||||
: queryAura(api)
|
: queryAura(api)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
// 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 { SessionIndex } from '@polkadot/types/interfaces';
|
||||||
|
import { DeriveSessionInfo, DeriveSessionProgress } from '../types';
|
||||||
|
|
||||||
|
import { Observable, combineLatest, of } from 'rxjs';
|
||||||
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
|
import { Option, u64 } from '@polkadot/types';
|
||||||
|
|
||||||
|
import { memo } from '../util';
|
||||||
|
|
||||||
|
type ResultSlots = [u64, u64, u64, Option<SessionIndex>];
|
||||||
|
type ResultSlotsFlat = [u64, u64, u64, SessionIndex];
|
||||||
|
|
||||||
|
function createDerive (api: ApiInterfaceRx, info: DeriveSessionInfo, [currentSlot, epochIndex, epochOrGenesisStartSlot, activeEraStartSessionIndex]: ResultSlotsFlat): DeriveSessionProgress {
|
||||||
|
const epochStartSlot = epochIndex.mul(info.sessionLength).add(epochOrGenesisStartSlot);
|
||||||
|
const sessionProgress = currentSlot.sub(epochStartSlot);
|
||||||
|
const eraProgress = info.currentIndex.sub(activeEraStartSessionIndex).mul(info.sessionLength).add(sessionProgress);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...info,
|
||||||
|
eraProgress: api.registry.createType('BlockNumber', eraProgress),
|
||||||
|
sessionProgress: api.registry.createType('BlockNumber', sessionProgress)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function queryAura (api: ApiInterfaceRx): Observable<DeriveSessionProgress> {
|
||||||
|
return api.derive.session.info().pipe(
|
||||||
|
map((info): DeriveSessionProgress =>
|
||||||
|
createDerive(api, info, [
|
||||||
|
api.registry.createType('u64', 1),
|
||||||
|
api.registry.createType('u64', 1),
|
||||||
|
api.registry.createType('u64', 1),
|
||||||
|
api.registry.createType('SessionIndex', 1)
|
||||||
|
])
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function queryBabe (api: ApiInterfaceRx): Observable<[DeriveSessionInfo, ResultSlotsFlat]> {
|
||||||
|
return api.derive.session.info().pipe(
|
||||||
|
switchMap((info): Observable<[DeriveSessionInfo, ResultSlots]> =>
|
||||||
|
combineLatest([
|
||||||
|
of(info),
|
||||||
|
api.queryMulti<ResultSlots>([
|
||||||
|
api.query.babe.currentSlot,
|
||||||
|
api.query.babe.epochIndex,
|
||||||
|
api.query.babe.genesisSlot,
|
||||||
|
[api.query.staking.erasStartSessionIndex, info.activeEra]
|
||||||
|
])
|
||||||
|
])
|
||||||
|
),
|
||||||
|
map(([info, [currentSlot, epochIndex, genesisSlot, optStartIndex]]): [DeriveSessionInfo, ResultSlotsFlat] => [
|
||||||
|
info, [currentSlot, epochIndex, genesisSlot, optStartIndex.unwrapOr(api.registry.createType('SessionIndex', 1))]
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function queryBabeNoHistory (api: ApiInterfaceRx): Observable<[DeriveSessionInfo, ResultSlotsFlat]> {
|
||||||
|
return combineLatest([
|
||||||
|
api.derive.session.info(),
|
||||||
|
api.queryMulti<ResultSlotsFlat>([
|
||||||
|
api.query.babe.currentSlot,
|
||||||
|
api.query.babe.epochIndex,
|
||||||
|
api.query.babe.genesisSlot,
|
||||||
|
api.query.staking.currentEraStartSessionIndex
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description Retrieves all the session and era query and calculates specific values on it as the length of the session and eras
|
||||||
|
*/
|
||||||
|
export function progress (api: ApiInterfaceRx): () => Observable<DeriveSessionProgress> {
|
||||||
|
return memo((): Observable<DeriveSessionProgress> =>
|
||||||
|
api.consts.babe
|
||||||
|
? (api.query.staking.erasStartSessionIndex
|
||||||
|
? queryBabe(api) // 2.x with Babe
|
||||||
|
: queryBabeNoHistory(api)
|
||||||
|
).pipe(
|
||||||
|
map(([info, slots]: [DeriveSessionInfo, ResultSlotsFlat]): DeriveSessionProgress =>
|
||||||
|
createDerive(api, info, slots)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
: queryAura(api)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ import { memo } from '../util';
|
|||||||
|
|
||||||
export function sessionProgress (api: ApiInterfaceRx): () => Observable<BlockNumber> {
|
export function sessionProgress (api: ApiInterfaceRx): () => Observable<BlockNumber> {
|
||||||
return memo((): Observable<BlockNumber> =>
|
return memo((): Observable<BlockNumber> =>
|
||||||
api.derive.session.info().pipe(
|
api.derive.session.progress().pipe(
|
||||||
map((info) => info.sessionProgress)
|
map((info) => info.sessionProgress)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,14 @@ export interface DeriveSessionIndexes {
|
|||||||
validatorCount: u32;
|
validatorCount: u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DerivedSessionInfo extends DeriveSessionIndexes {
|
export interface DeriveSessionInfo extends DeriveSessionIndexes {
|
||||||
eraLength: BlockNumber;
|
eraLength: BlockNumber;
|
||||||
eraProgress: BlockNumber;
|
|
||||||
isEpoch: boolean;
|
isEpoch: boolean;
|
||||||
sessionLength: BlockNumber;
|
sessionLength: BlockNumber;
|
||||||
sessionsPerEra: SessionIndex;
|
sessionsPerEra: SessionIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeriveSessionProgress extends DeriveSessionInfo {
|
||||||
|
eraProgress: BlockNumber;
|
||||||
sessionProgress: BlockNumber;
|
sessionProgress: BlockNumber;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export function candidates (api: ApiInterfaceRx): () => Observable<DeriveSociety
|
|||||||
])
|
])
|
||||||
),
|
),
|
||||||
map(([candidates, suspended]: Result): DeriveSocietyCandidate[] =>
|
map(([candidates, suspended]: Result): DeriveSocietyCandidate[] =>
|
||||||
candidates.map(({ who, kind, value }, index) => ({
|
candidates.map(({ kind, value, who }, index) => ({
|
||||||
accountId: who,
|
accountId: who,
|
||||||
isSuspended: suspended[index].isSome,
|
isSuspended: suspended[index].isSome,
|
||||||
kind,
|
kind,
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ export function info (api: ApiInterfaceRx): () => Observable<DeriveSociety> {
|
|||||||
map(([bids, defender, founder, head, maxMembers, pot]: Result): DeriveSociety => ({
|
map(([bids, defender, founder, head, maxMembers, pot]: Result): DeriveSociety => ({
|
||||||
bids,
|
bids,
|
||||||
defender: defender.unwrapOr(undefined),
|
defender: defender.unwrapOr(undefined),
|
||||||
|
founder: founder.unwrapOr(undefined),
|
||||||
hasDefender: (defender.isSome && head.isSome && !head.eq(defender)) || false,
|
hasDefender: (defender.isSome && head.isSome && !head.eq(defender)) || false,
|
||||||
head: head.unwrapOr(undefined),
|
head: head.unwrapOr(undefined),
|
||||||
founder: founder.unwrapOr(undefined),
|
|
||||||
maxMembers,
|
maxMembers,
|
||||||
pot
|
pot
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ export function member (api: ApiInterfaceRx): (accountId: AccountId) => Observab
|
|||||||
]).pipe(
|
]).pipe(
|
||||||
map(([payouts, strikes, defenderVotes, suspended, vouching]: Result): DeriveSocietyMember => ({
|
map(([payouts, strikes, defenderVotes, suspended, vouching]: Result): DeriveSocietyMember => ({
|
||||||
accountId,
|
accountId,
|
||||||
payouts,
|
|
||||||
isSuspended: suspended.isTrue,
|
isSuspended: suspended.isTrue,
|
||||||
|
payouts,
|
||||||
strikes,
|
strikes,
|
||||||
vote: defenderVotes.unwrapOr(undefined),
|
vote: defenderVotes.unwrapOr(undefined),
|
||||||
vouching: vouching.unwrapOr(undefined)
|
vouching: vouching.unwrapOr(undefined)
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import { Balance, BlockNumber, StakingLedger, UnlockChunk } from '@polkadot/types/interfaces';
|
import { Balance, StakingLedger, UnlockChunk } from '@polkadot/types/interfaces';
|
||||||
import { DerivedSessionInfo, DerivedStakingAccount, DerivedStakingQuery, DerivedUnlocking } from '../types';
|
import { DeriveSessionInfo, DeriveStakingAccount, DeriveStakingQuery, DeriveUnlocking } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
import BN from 'bn.js';
|
||||||
import { Observable, combineLatest } from 'rxjs';
|
import { Observable, combineLatest } from 'rxjs';
|
||||||
@@ -27,27 +27,13 @@ function groupByEra (list: UnlockChunk[]): Record<string, BN> {
|
|||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate the remaining blocks in a specific unlock era
|
function calculateUnlocking (api: ApiInterfaceRx, stakingLedger: StakingLedger | undefined, sessionInfo: DeriveSessionInfo): DeriveUnlocking[] | undefined {
|
||||||
function remainingBlocks (api: ApiInterfaceRx, era: BN, sessionInfo: DerivedSessionInfo): BlockNumber {
|
|
||||||
const remaining = era.sub(sessionInfo.currentEra);
|
|
||||||
|
|
||||||
// on the Rust side the current-era >= era-for-unlock (removal done on >)
|
|
||||||
return api.registry.createType('BlockNumber', remaining.gtn(0)
|
|
||||||
? remaining
|
|
||||||
.subn(1)
|
|
||||||
.mul(sessionInfo.eraLength)
|
|
||||||
.add(sessionInfo.eraLength.sub(sessionInfo.eraProgress))
|
|
||||||
: 0
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function calculateUnlocking (api: ApiInterfaceRx, stakingLedger: StakingLedger | undefined, sessionInfo: DerivedSessionInfo): DerivedUnlocking[] | undefined {
|
|
||||||
if (isUndefined(stakingLedger)) {
|
if (isUndefined(stakingLedger)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unlockingChunks = stakingLedger.unlocking.filter(({ era }): boolean =>
|
const unlockingChunks = stakingLedger.unlocking.filter(({ era }): boolean =>
|
||||||
remainingBlocks(api, era.unwrap(), sessionInfo).gtn(0)
|
era.unwrap().sub(sessionInfo.activeEra).gtn(0)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!unlockingChunks.length) {
|
if (!unlockingChunks.length) {
|
||||||
@@ -56,27 +42,27 @@ function calculateUnlocking (api: ApiInterfaceRx, stakingLedger: StakingLedger |
|
|||||||
|
|
||||||
// group the unlock chunks that have the same era and sum their values
|
// group the unlock chunks that have the same era and sum their values
|
||||||
const groupedResult = groupByEra(unlockingChunks);
|
const groupedResult = groupByEra(unlockingChunks);
|
||||||
const results = Object.entries(groupedResult).map(([eraString, value]): DerivedUnlocking => ({
|
const results = Object.entries(groupedResult).map(([eraString, value]): DeriveUnlocking => ({
|
||||||
value: api.registry.createType('Balance', value),
|
remainingEras: new BN(eraString).sub(sessionInfo.activeEra),
|
||||||
remainingBlocks: remainingBlocks(api, new BN(eraString), sessionInfo)
|
value: api.registry.createType('Balance', value)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return results.length ? results : undefined;
|
return results.length ? results : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function redeemableSum (api: ApiInterfaceRx, stakingLedger: StakingLedger | undefined, sessionInfo: DerivedSessionInfo): Balance {
|
function redeemableSum (api: ApiInterfaceRx, stakingLedger: StakingLedger | undefined, sessionInfo: DeriveSessionInfo): Balance {
|
||||||
if (isUndefined(stakingLedger)) {
|
if (isUndefined(stakingLedger)) {
|
||||||
return api.registry.createType('Balance');
|
return api.registry.createType('Balance');
|
||||||
}
|
}
|
||||||
|
|
||||||
return api.registry.createType('Balance', stakingLedger.unlocking.reduce((total, { era, value }): BN => {
|
return api.registry.createType('Balance', stakingLedger.unlocking.reduce((total, { era, value }): BN => {
|
||||||
return remainingBlocks(api, era.unwrap(), sessionInfo).eqn(0)
|
return sessionInfo.activeEra.gte(era.unwrap())
|
||||||
? total.add(value.unwrap())
|
? total.add(value.unwrap())
|
||||||
: total;
|
: total;
|
||||||
}, new BN(0)));
|
}, new BN(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseResult (api: ApiInterfaceRx, sessionInfo: DerivedSessionInfo, query: DerivedStakingQuery): DerivedStakingAccount {
|
function parseResult (api: ApiInterfaceRx, sessionInfo: DeriveSessionInfo, query: DeriveStakingQuery): DeriveStakingAccount {
|
||||||
return {
|
return {
|
||||||
...query,
|
...query,
|
||||||
redeemable: redeemableSum(api, query.stakingLedger, sessionInfo),
|
redeemable: redeemableSum(api, query.stakingLedger, sessionInfo),
|
||||||
@@ -87,13 +73,13 @@ function parseResult (api: ApiInterfaceRx, sessionInfo: DerivedSessionInfo, quer
|
|||||||
/**
|
/**
|
||||||
* @description From a stash, retrieve the controllerId and fill in all the relevant staking details
|
* @description From a stash, retrieve the controllerId and fill in all the relevant staking details
|
||||||
*/
|
*/
|
||||||
export function account (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DerivedStakingAccount> {
|
export function account (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DeriveStakingAccount> {
|
||||||
return memo((accountId: Uint8Array | string): Observable<DerivedStakingAccount> =>
|
return memo((accountId: Uint8Array | string): Observable<DeriveStakingAccount> =>
|
||||||
combineLatest([
|
combineLatest([
|
||||||
api.derive.session.info(),
|
api.derive.session.info(),
|
||||||
api.derive.staking.query(accountId)
|
api.derive.staking.query(accountId)
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([sessionInfo, query]: [DerivedSessionInfo, DerivedStakingQuery]) =>
|
map(([sessionInfo, query]: [DeriveSessionInfo, DeriveStakingQuery]) =>
|
||||||
parseResult(api, sessionInfo, query))
|
parseResult(api, sessionInfo, query))
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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'))
|
||||||
|
)
|
||||||
|
));
|
||||||
|
}
|
||||||
@@ -4,27 +4,25 @@
|
|||||||
|
|
||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import { AccountId } from '@polkadot/types/interfaces';
|
import { AccountId } from '@polkadot/types/interfaces';
|
||||||
import { DerivedStakingQuery, DerivedStakingElected } from '../types';
|
import { DeriveStakingQuery, DeriveStakingElected } from '../types';
|
||||||
|
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
import { Observable, combineLatest, of } from 'rxjs';
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
export function electedInfo (api: ApiInterfaceRx): () => Observable<DerivedStakingElected> {
|
export function electedInfo (api: ApiInterfaceRx): () => Observable<DeriveStakingElected> {
|
||||||
return memo((): Observable<DerivedStakingElected> =>
|
return memo((): Observable<DeriveStakingElected> =>
|
||||||
api.derive.staking.validators().pipe(
|
api.derive.staking.validators().pipe(
|
||||||
switchMap(({ nextElected }): Observable<[AccountId[], DerivedStakingQuery[]]> =>
|
switchMap(({ nextElected }): Observable<[AccountId[], DeriveStakingQuery[]]> =>
|
||||||
combineLatest([
|
combineLatest([
|
||||||
of(nextElected),
|
of(nextElected),
|
||||||
combineLatest(
|
combineLatest(
|
||||||
nextElected.map((accountId): Observable<DerivedStakingQuery> =>
|
nextElected.map((accountId) => api.derive.staking.query(accountId))
|
||||||
api.derive.staking.query(accountId)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
),
|
),
|
||||||
map(([nextElected, info]): DerivedStakingElected => ({
|
map(([nextElected, info]): DeriveStakingElected => ({
|
||||||
info,
|
info,
|
||||||
nextElected
|
nextElected
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
|
|||||||
import { EraIndex, Exposure } from '@polkadot/types/interfaces';
|
import { EraIndex, Exposure } from '@polkadot/types/interfaces';
|
||||||
import { DeriveEraExposure, DeriveEraNominatorExposure, DeriveEraValidatorExposure } from '../types';
|
import { DeriveEraExposure, DeriveEraNominatorExposure, DeriveEraValidatorExposure } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
import { Observable, combineLatest, of } from 'rxjs';
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
import { StorageKey } from '@polkadot/types';
|
import { StorageKey } from '@polkadot/types';
|
||||||
@@ -24,11 +23,11 @@ function mapStakers (era: EraIndex, stakers: KeysAndExposures): DeriveEraExposur
|
|||||||
|
|
||||||
validators[validatorId] = exposure;
|
validators[validatorId] = exposure;
|
||||||
|
|
||||||
exposure.others.forEach(({ who }, index): void => {
|
exposure.others.forEach(({ who }, validatorIndex): void => {
|
||||||
const nominatorId = who.toString();
|
const nominatorId = who.toString();
|
||||||
|
|
||||||
nominators[nominatorId] = nominators[nominatorId] || [];
|
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[]> {
|
export function _erasExposure (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraExposure[]> {
|
||||||
return memo((withActive?: boolean | BN | number): 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(
|
api.derive.staking.erasHistoric(withActive).pipe(
|
||||||
switchMap((eras): Observable<DeriveEraExposure[]> =>
|
switchMap((eras) => api.derive.staking._erasExposure(eras))
|
||||||
eras.length
|
|
||||||
? combineLatest(
|
|
||||||
eras.map((era) => api.derive.staking.eraExposure(era))
|
|
||||||
)
|
|
||||||
: of([])
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,45 +9,32 @@ import BN from 'bn.js';
|
|||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { Option, u32 } from '@polkadot/types';
|
import { Option, u32 } from '@polkadot/types';
|
||||||
import { isBoolean, isUndefined, bnToBn } from '@polkadot/util';
|
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
export function erasHistoric (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<EraIndex[]> {
|
export function erasHistoric (api: ApiInterfaceRx): (withActive?: boolean) => Observable<EraIndex[]> {
|
||||||
return memo((withActive?: boolean | BN | number): Observable<EraIndex[]> =>
|
return memo((withActive?: boolean): Observable<EraIndex[]> =>
|
||||||
api.query.staking?.activeEra
|
api.query.staking?.activeEra
|
||||||
? api.queryMulti<[Option<ActiveEraInfo>, u32]>([
|
? api.queryMulti<[Option<ActiveEraInfo>, u32]>([
|
||||||
api.query.staking.activeEra,
|
api.query.staking.activeEra,
|
||||||
api.query.staking.historyDepth
|
api.query.staking.historyDepth
|
||||||
]).pipe(
|
]).pipe(
|
||||||
map(([activeEraOpt, historyDepth]): EraIndex[] => {
|
map(([activeEraOpt, historyDepth]): EraIndex[] => {
|
||||||
const result: (EraIndex | null)[] = [];
|
const result: EraIndex[] = [];
|
||||||
const max = historyDepth.toNumber();
|
const max = historyDepth.toNumber();
|
||||||
const activeEra = activeEraOpt.unwrapOrDefault().index.toBn();
|
const activeEra: BN = activeEraOpt.unwrapOrDefault().index;
|
||||||
let lastEra = activeEra;
|
let lastEra = activeEra;
|
||||||
|
|
||||||
while (lastEra.gten(0) && (result.length < max)) {
|
while (lastEra.gten(0) && (result.length < max)) {
|
||||||
result.push(
|
if ((lastEra !== activeEra) || (withActive === true)) {
|
||||||
((lastEra !== activeEra) || (withActive === true))
|
result.push(api.registry.createType('EraIndex', lastEra));
|
||||||
? api.registry.createType('EraIndex', lastEra)
|
}
|
||||||
: null
|
|
||||||
);
|
|
||||||
|
|
||||||
lastEra = lastEra.subn(1);
|
lastEra = lastEra.subn(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const startEra = isUndefined(withActive) || isBoolean(withActive)
|
|
||||||
? new BN(0)
|
|
||||||
: bnToBn(withActive);
|
|
||||||
|
|
||||||
// go from oldest to newest
|
// go from oldest to newest
|
||||||
return result
|
return result.reverse();
|
||||||
.filter((era): era is EraIndex =>
|
|
||||||
era
|
|
||||||
? era.gte(startEra)
|
|
||||||
: false
|
|
||||||
)
|
|
||||||
.reverse();
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
: of([])
|
: of([])
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
|
|||||||
import { EraIndex, EraRewardPoints } from '@polkadot/types/interfaces';
|
import { EraIndex, EraRewardPoints } from '@polkadot/types/interfaces';
|
||||||
import { DeriveEraPoints, DeriveEraValPoints } from '../types';
|
import { DeriveEraPoints, DeriveEraValPoints } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
import { Observable, of } from 'rxjs';
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
@@ -22,24 +21,26 @@ function mapValidators ({ individual }: EraRewardPoints): DeriveEraValPoints {
|
|||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function erasPoints (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraPoints[]> {
|
export function _erasPoints (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraPoints[]> {
|
||||||
return memo((withActive?: boolean | number): Observable<DeriveEraPoints[]> =>
|
return memo((eras: EraIndex[]): Observable<DeriveEraPoints[]> =>
|
||||||
api.derive.staking.erasHistoric(withActive).pipe(
|
eras.length
|
||||||
switchMap((eras): Observable<[EraIndex[], EraRewardPoints[]]> =>
|
? api.query.staking.erasRewardPoints.multi<EraRewardPoints>(eras).pipe(
|
||||||
combineLatest([
|
map((points) =>
|
||||||
of(eras),
|
eras.map((era, index): DeriveEraPoints => ({
|
||||||
eras.length
|
era,
|
||||||
? api.query.staking.erasRewardPoints.multi<EraRewardPoints>(eras)
|
eraPoints: points[index].total,
|
||||||
: of([])
|
validators: mapValidators(points[index])
|
||||||
])
|
}))
|
||||||
),
|
)
|
||||||
map(([eras, points]): DeriveEraPoints[] =>
|
|
||||||
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 { EraIndex, ValidatorPrefs } from '@polkadot/types/interfaces';
|
||||||
import { DeriveEraPrefs, DeriveEraValPrefs } from '../types';
|
import { DeriveEraPrefs, DeriveEraValPrefs } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
import { Observable, combineLatest, of } from 'rxjs';
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
import { StorageKey } from '@polkadot/types';
|
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[]> {
|
export function _erasPrefs (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraPrefs[]> {
|
||||||
return memo((withActive?: boolean | BN | number): 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(
|
api.derive.staking.erasHistoric(withActive).pipe(
|
||||||
switchMap((eras): Observable<DeriveEraPrefs[]> =>
|
switchMap((eras) => api.derive.staking._erasPrefs(eras))
|
||||||
eras.length
|
|
||||||
? combineLatest(
|
|
||||||
eras.map((era) => api.derive.staking.eraPrefs(era))
|
|
||||||
)
|
|
||||||
: of([])
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,30 +6,29 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
|
|||||||
import { Balance, EraIndex } from '@polkadot/types/interfaces';
|
import { Balance, EraIndex } from '@polkadot/types/interfaces';
|
||||||
import { DeriveEraRewards } from '../types';
|
import { DeriveEraRewards } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
import { Observable, of } from 'rxjs';
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
import { Option } from '@polkadot/types';
|
import { Option } from '@polkadot/types';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
export function erasRewards (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraRewards[]> {
|
export function _erasRewards (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraRewards[]> {
|
||||||
return memo((withActive?: boolean | BN | number): Observable<DeriveEraRewards[]> =>
|
return memo((eras: EraIndex[]): Observable<DeriveEraRewards[]> =>
|
||||||
api.derive.staking.erasHistoric(withActive).pipe(
|
eras.length
|
||||||
switchMap((eras): Observable<[EraIndex[], Option<Balance>[]]> =>
|
? api.query.staking.erasValidatorReward.multi<Option<Balance>>(eras).pipe(
|
||||||
combineLatest([
|
map((rewards) => eras.map((era, index): DeriveEraRewards => ({
|
||||||
of(eras),
|
|
||||||
eras.length
|
|
||||||
? api.query.staking.erasValidatorReward.multi<Option<Balance>>(eras)
|
|
||||||
: of([])
|
|
||||||
])
|
|
||||||
),
|
|
||||||
map(([eras, rewards]): DeriveEraRewards[] =>
|
|
||||||
eras.map((era, index): DeriveEraRewards => ({
|
|
||||||
era,
|
era,
|
||||||
eraReward: rewards[index].unwrapOrDefault()
|
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 { ITuple } from '@polkadot/types/types';
|
||||||
import { DeriveEraSlashes, DeriveEraValSlash } from '../types';
|
import { DeriveEraSlashes, DeriveEraValSlash } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
import { Observable, combineLatest, of } from 'rxjs';
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
import { Option, StorageKey } from '@polkadot/types';
|
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[]> {
|
export function _erasSlashes (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraSlashes[]> {
|
||||||
return memo((withActive?: boolean | BN | number): Observable<DeriveEraSlashes[]> =>
|
return memo((eras: EraIndex[]): Observable<DeriveEraSlashes[]> =>
|
||||||
api.derive.staking.erasHistoric(withActive).pipe(
|
eras.length
|
||||||
switchMap((eras): Observable<DeriveEraSlashes[]> =>
|
? combineLatest(
|
||||||
eras.length
|
eras.map((era) => api.derive.staking.eraSlashes(era))
|
||||||
? combineLatest(
|
|
||||||
eras.map((era) => api.derive.staking.eraSlashes(era))
|
|
||||||
)
|
|
||||||
: of([])
|
|
||||||
)
|
)
|
||||||
|
: 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.
|
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||||
|
|
||||||
export * from './account';
|
export * from './account';
|
||||||
|
export * from './currentPoints';
|
||||||
export * from './erasExposure';
|
export * from './erasExposure';
|
||||||
export * from './erasHistoric';
|
export * from './erasHistoric';
|
||||||
export * from './erasPoints';
|
export * from './erasPoints';
|
||||||
|
|||||||
@@ -2,51 +2,27 @@
|
|||||||
// This software may be modified and distributed under the terms
|
// This software may be modified and distributed under the terms
|
||||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
// 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 { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import { DerivedStakingOverview } from '../types';
|
import { DeriveStakingOverview } from '../types';
|
||||||
|
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
import { Observable, combineLatest } from 'rxjs';
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
import { memo } from '../util';
|
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
|
* @description Retrieve the staking overview, including elected and points earned
|
||||||
*/
|
*/
|
||||||
export function overview (api: ApiInterfaceRx): () => Observable<DerivedStakingOverview> {
|
export function overview (api: ApiInterfaceRx): () => Observable<DeriveStakingOverview> {
|
||||||
return memo((): Observable<DerivedStakingOverview> =>
|
return memo((): Observable<DeriveStakingOverview> =>
|
||||||
combineLatest([
|
combineLatest([
|
||||||
api.derive.session.indexes(),
|
api.derive.session.indexes(),
|
||||||
api.derive.staking.validators()
|
api.derive.staking.validators()
|
||||||
]).pipe(
|
]).pipe(
|
||||||
switchMap(([indexes, { nextElected, validators }]) =>
|
map(([indexes, { nextElected, validators }]): DeriveStakingOverview => ({
|
||||||
combineLatest([
|
...indexes,
|
||||||
of({ ...indexes, nextElected, validators }),
|
nextElected,
|
||||||
api.query.staking.erasRewardPoints
|
validators
|
||||||
? api.query.staking.erasRewardPoints<EraRewardPoints>(indexes.activeEra)
|
|
||||||
: api.query.staking.currentEraPointsEarned
|
|
||||||
? retrievePointsPrev(api, nextElected)
|
|
||||||
: of(api.registry.createType('EraRewardPoints'))
|
|
||||||
])
|
|
||||||
),
|
|
||||||
map(([info, eraPoints]): DerivedStakingOverview => ({
|
|
||||||
...info, eraPoints
|
|
||||||
}))
|
}))
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,13 @@
|
|||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import { DeriveOwnExposure } from '../types';
|
import { DeriveOwnExposure } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
import { Observable, combineLatest, of } from 'rxjs';
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
export function ownExposure (api: ApiInterfaceRx): (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 | BN | number): Observable<DeriveOwnExposure[]> => {
|
return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveOwnExposure[]> => {
|
||||||
return api.derive.staking.erasHistoric(withActive).pipe(
|
return api.derive.staking.erasHistoric(withActive).pipe(
|
||||||
switchMap((eras) =>
|
switchMap((eras) =>
|
||||||
eras.length
|
eras.length
|
||||||
|
|||||||
@@ -5,14 +5,13 @@
|
|||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import { DeriveStakerSlashes } from '../types';
|
import { DeriveStakerSlashes } from '../types';
|
||||||
|
|
||||||
import BN from 'bn.js';
|
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
import { Observable, combineLatest, of } from 'rxjs';
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
import { memo } from '../util';
|
import { memo } from '../util';
|
||||||
|
|
||||||
export function ownSlashes (api: ApiInterfaceRx): (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 | BN | number): Observable<DeriveStakerSlashes[]> => {
|
return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveStakerSlashes[]> => {
|
||||||
return api.derive.staking.erasHistoric(withActive).pipe(
|
return api.derive.staking.erasHistoric(withActive).pipe(
|
||||||
switchMap((eras) =>
|
switchMap((eras) =>
|
||||||
eras.length
|
eras.length
|
||||||
@@ -30,9 +29,7 @@ export function ownSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | strin
|
|||||||
era,
|
era,
|
||||||
total: optVal.isSome
|
total: optVal.isSome
|
||||||
? optVal.unwrap()[1]
|
? optVal.unwrap()[1]
|
||||||
: optNom.isSome
|
: optNom.unwrapOrDefault()
|
||||||
? optNom.unwrap()
|
|
||||||
: api.registry.createType('Balance')
|
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||||
import { AccountId, Exposure, Keys, Nominations, RewardDestination, ValidatorPrefs } from '@polkadot/types/interfaces';
|
import { AccountId, Exposure, Keys, Nominations, RewardDestination, ValidatorPrefs } from '@polkadot/types/interfaces';
|
||||||
import { ITuple } from '@polkadot/types/types';
|
import { ITuple } from '@polkadot/types/types';
|
||||||
import { DerivedStakingQuery } from '../types';
|
import { DeriveStakingQuery } from '../types';
|
||||||
|
|
||||||
import { Observable, combineLatest, of } from 'rxjs';
|
import { Observable, combineLatest, of } from 'rxjs';
|
||||||
import { map, switchMap } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
@@ -55,13 +55,13 @@ 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<DerivedStakingQuery> {
|
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 controllerId = controllerIdOpt.unwrapOr(null);
|
||||||
const nominators = nominatorsOpt.unwrapOr(null);
|
const nominators = nominatorsOpt.unwrapOr(null);
|
||||||
|
|
||||||
return controllerId
|
return controllerId
|
||||||
? api.query.staking.ledger(controllerId).pipe(
|
? api.query.staking.ledger(controllerId).pipe(
|
||||||
map((stakingLedgerOpt): DerivedStakingQuery => ({
|
map((stakingLedgerOpt): DeriveStakingQuery => ({
|
||||||
accountId: stashId,
|
accountId: stashId,
|
||||||
controllerId,
|
controllerId,
|
||||||
exposure,
|
exposure,
|
||||||
@@ -82,30 +82,41 @@ function retrieveController (api: ApiInterfaceRx, stashId: AccountId, [queuedKey
|
|||||||
: of({ accountId: stashId, nextSessionIds: [], sessionIds: [] });
|
: of({ accountId: stashId, nextSessionIds: [], sessionIds: [] });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export function queryWithQueued (api: ApiInterfaceRx): (accountId: Uint8Array | string, queuedKeys: Vec<ITuple<[AccountId, Keys]>>) => Observable<DeriveStakingQuery> {
|
||||||
* @description From a stash, retrieve the controllerId and all relevant details
|
return memo((accountId: Uint8Array | string, queuedKeys: Vec<ITuple<[AccountId, Keys]>>): Observable<DeriveStakingQuery> => {
|
||||||
*/
|
|
||||||
export function query (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DerivedStakingQuery> {
|
|
||||||
return memo((accountId: Uint8Array | string): Observable<DerivedStakingQuery> => {
|
|
||||||
const stashId = api.registry.createType('AccountId', accountId);
|
const stashId = api.registry.createType('AccountId', accountId);
|
||||||
|
|
||||||
return combineLatest([
|
return (
|
||||||
api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>(),
|
|
||||||
api.query.staking.erasStakers
|
api.query.staking.erasStakers
|
||||||
? retrieveCurr(api, stashId)
|
? retrieveCurr(api, stashId)
|
||||||
: retrievePrev(api, stashId)
|
: retrievePrev(api, stashId)
|
||||||
]).pipe(
|
).pipe(
|
||||||
switchMap((result): Observable<DerivedStakingQuery> =>
|
switchMap((result): Observable<DeriveStakingQuery> =>
|
||||||
retrieveController(api, stashId, result)
|
retrieveController(api, stashId, queuedKeys, result)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function queryMulti (api: ApiInterfaceRx): (...accountIds: (Uint8Array | string)[]) => Observable<DerivedStakingQuery[]> {
|
/**
|
||||||
return memo((...accountIds: (Uint8Array | string)[]): Observable<DerivedStakingQuery[]> =>
|
* @description From a stash, retrieve the controllerId and all relevant details
|
||||||
combineLatest(
|
*/
|
||||||
accountIds.map((accountId) => api.derive.staking.query(accountId))
|
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([])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user