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.6.2
|
||||
1.6.2
|
||||
|
||||
@@ -10,9 +10,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '12.x'
|
||||
- name: ${{ matrix.step }}
|
||||
run: |
|
||||
yarn install --immutable | grep -v 'YN0013'
|
||||
|
||||
@@ -10,15 +10,12 @@ jobs:
|
||||
matrix:
|
||||
step: ['build:release', 'docs:release']
|
||||
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
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
token: ${{ secrets.GH_PAT }}
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '12.x'
|
||||
- name: ${{ matrix.step }}
|
||||
env:
|
||||
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
||||
|
||||
+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
|
||||
|
||||
- **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`
|
||||
- **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
|
||||
@@ -8,6 +36,7 @@
|
||||
- Add support for all known substrate RPC methods
|
||||
- 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`
|
||||
- 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 +1,5 @@
|
||||
// Copyright 2017-2020 @polkadot/api authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
module.exports = require('@polkadot/dev/config/babel');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Required imports
|
||||
const { ApiPromise, WsProvider } = require('@polkadot/api');
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API
|
||||
const { ApiPromise } = require('@polkadot/api');
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API
|
||||
const { ApiPromise } = require('@polkadot/api');
|
||||
|
||||
@@ -13,13 +14,13 @@ async function main () {
|
||||
|
||||
// Retrieve the initial balance. Since the call has no callback, it is simply a promise
|
||||
// that resolves to the current on-chain value
|
||||
let { nonce: previousNonce, data: { free: previousFree } } = await api.query.system.account(Alice);
|
||||
let { data: { free: previousFree }, nonce: previousNonce } = await api.query.system.account(Alice);
|
||||
|
||||
console.log(`${Alice} has a balance of ${previousFree}, nonce ${previousNonce}`);
|
||||
console.log(`You may leave this example running and start example 06 or transfer any value to ${Alice}`);
|
||||
|
||||
// Here we subscribe to any balance changes and update the on-screen value
|
||||
api.query.system.account(Alice, ({ nonce: currentNonce, data: { free: currentFree } }) => {
|
||||
api.query.system.account(Alice, ({ data: { free: currentFree }, nonce: currentNonce }) => {
|
||||
// Calculate the delta
|
||||
const change = currentFree.sub(previousFree);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API
|
||||
const { ApiPromise } = require('@polkadot/api');
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API
|
||||
const { ApiPromise } = require('@polkadot/api');
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API
|
||||
const { ApiPromise } = require('@polkadot/api');
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API
|
||||
const { ApiPromise } = require('@polkadot/api');
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API, Keyring and some utility functions
|
||||
const { ApiPromise } = require('@polkadot/api');
|
||||
const { Keyring } = require('@polkadot/keyring');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API, Keyring and some utility functions
|
||||
const { ApiPromise } = require('@polkadot/api');
|
||||
const { Keyring } = require('@polkadot/keyring');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API
|
||||
const { ApiPromise } = require('@polkadot/api');
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API & Provider and some utility functions
|
||||
const { ApiPromise } = require('@polkadot/api');
|
||||
|
||||
@@ -44,7 +45,7 @@ async function main () {
|
||||
console.log('Included at block hash', status.asInBlock.toHex());
|
||||
console.log('Events:');
|
||||
|
||||
events.forEach(({ phase, event: { data, method, section } }) => {
|
||||
events.forEach(({ event: { data, method, section }, phase }) => {
|
||||
console.log('\t', phase.toString(), `: ${section}.${method}`, data.toString());
|
||||
});
|
||||
} else if (status.isFinalized) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API & Provider and some utility functions
|
||||
const { ApiPromise, WsProvider } = require('@polkadot/api');
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Required imports
|
||||
const { zip } = require('rxjs');
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
const { switchMap } = require('rxjs/operators');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API and operators from RxJs
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
const { pairwise, startWith } = require('rxjs/operators');
|
||||
@@ -27,6 +28,7 @@ async function main () {
|
||||
// then balance[1] is the initial value of Alice account.
|
||||
console.log(`Alice ${Alice} has a balance of ${balance[1].data.free}`);
|
||||
console.log('You may leave this example running and start the "Make a transfer" example or transfer any value to Alice address');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
const { switchMap } = require('rxjs/operators');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
const { combineLatest, of } = require('rxjs');
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API, Keyring and some utility functions
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
const { Keyring } = require('@polkadot/keyring');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API and selected RxJs operators
|
||||
const { switchMap } = require('rxjs/operators');
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API and some utility functions
|
||||
const { ApiRx } = require('@polkadot/api');
|
||||
|
||||
@@ -48,7 +49,7 @@ async function main () {
|
||||
console.log('Included at block hash', status.asInBlock.toHex());
|
||||
console.log('Events:');
|
||||
|
||||
events.forEach(({ phase, event: { data, method, section } }) => {
|
||||
events.forEach(({ event: { data, method, section }, phase }) => {
|
||||
console.log('\t', phase.toString(), `: ${section}.${method}`, data.toString());
|
||||
});
|
||||
} else if (status.isFinalized) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable header/header */
|
||||
/* eslint-disable @typescript-eslint/require-await */
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
|
||||
// Import the API & Provider and some utility functions
|
||||
const { ApiRx, WsProvider } = require('@polkadot/api');
|
||||
// Import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie)
|
||||
|
||||
+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.
|
||||
|
||||
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
|
||||
|
||||
@@ -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>)`.
|
||||
|
||||
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
|
||||
const activeEra = await api.query.staking.activeEra();
|
||||
|
||||
// retrieve all exposures int the active era
|
||||
// retrieve all exposures for the active era
|
||||
const exposures = await api.query.staking.erasStakers.entries(activeEra.index);
|
||||
|
||||
exposures.forEach(([key, exposure]) => {
|
||||
@@ -73,7 +73,17 @@ exposures.forEach(([key, exposure]) => {
|
||||
|
||||
Here we are querying a double-map, so we supply 1 argument. No arguments on double-maps will be very costly, retrieving all the eras and associated entries. Additionally when `twox64_concat` & `blake2_concat` is used, the key `.args` will contain decoded values of the params, in this case it will contain the actual `AccountId` of the staker. (Since that was not supplied)
|
||||
|
||||
In the same way as above we can simply do `.keys(activeEra.index): StorageKey[]` to retrieve all the keys here, including the individual keys args decoding, as available on maps with decodable hashing functions.
|
||||
In the same way as above we can simply do `.keys(activeEra.index): StorageKey[]` to retrieve all the keys here, including the individual keys args (available on maps with decodable hashing functions) -
|
||||
|
||||
```js
|
||||
// retrieve all the nominator keys
|
||||
const keys = await api.query.staking.nominators.keys();
|
||||
|
||||
// extract the first key argument (AccountId) as string
|
||||
const nominatorIds = keys.map((key) => key.args[0].toString());
|
||||
|
||||
console.log('all nominators:', nminatorIds.join(', '));
|
||||
```
|
||||
|
||||
## State entries
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ Be aware that in the JS version naming defaults to `camelCase` where names of fi
|
||||
|
||||
Each enum has additional getters which are injected based on the fields wrapped. These take the form of `.is<Name>` and `.as<Name>` to allow you to check is the enum is a certain value or to retrieve the underlying value as a specific type.
|
||||
|
||||
As a real-world example, when an extrinsic is applied, the `Phase` enum has one of two states, `ApplyExtrinsic(u32)` or `Finalization`. In this case `.isApplyExtrinsic` would be `true` when an extrinsic is being applied, and `.asApplyExtrinsic` would return the value as a `u32` (which is the index of the extrinsic in the block, as it is being applied). When `isisApplyExtrinsic` is `false` and `asApplyExtrinsic` is called, the getter will throw.
|
||||
As a real-world example, when an extrinsic is applied, the `Phase` enum has one of two states, `ApplyExtrinsic(u32)` or `Finalization`. In this case `.isApplyExtrinsic` would be `true` when an extrinsic is being applied, and `.asApplyExtrinsic` would return the value as a `u32` (which is the index of the extrinsic in the block, as it is being applied). When `isApplyExtrinsic` is `false` and `asApplyExtrinsic` is called, the getter will throw.
|
||||
|
||||
## Working with Option<Type>
|
||||
|
||||
@@ -67,6 +67,7 @@ An `Option<Type>` attempts to mimic the Rust approach of having `None` and `Some
|
||||
- `.isSome` - this is `true` is a value is wrapped, i.e. if a `Option<u32>` has an actual underlying `u32`
|
||||
- `.unwrap()` - when `isSome`, this will return the wrapped value, i.e. for `Option<u32>`, this would return the `u32`. When the value is `isNone`, this call will throw an exception.
|
||||
- `.unwrapOr(<default value>)` - this extends `unwrap()`, returning the wrapped value when `isSome` and in the case of `isNone` it will return the `<default value>` passed.
|
||||
- `.unwrapOrDefault()` - returns either the rapped value when `isSome`, or the default for the type when `isNone`
|
||||
|
||||
## Working with Tuples
|
||||
|
||||
|
||||
+9
-3
@@ -1,14 +1,19 @@
|
||||
/* eslint-disable @typescript-eslint/camelcase */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
// Copyright 2017-2020 @polkadot/api authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
const config = require('@polkadot/dev/config/jest');
|
||||
|
||||
module.exports = Object.assign({}, config, {
|
||||
moduleNameMapper: {
|
||||
'@polkadot/api-contract(.*)$': '<rootDir>/packages/api-contract/src/$1',
|
||||
'@polkadot/api-derive(.*)$': '<rootDir>/packages/api-derive/src/$1',
|
||||
// eslint-disable-next-line sort-keys
|
||||
'@polkadot/api(.*)$': '<rootDir>/packages/api/src/$1',
|
||||
'@polkadot/metadata(.*)$': '<rootDir>/packages/metadata/src/$1',
|
||||
'@polkadot/rpc-(core|provider)(.*)$': '<rootDir>/packages/rpc-$1/src/$2',
|
||||
'@polkadot/types-known(.*)$': '<rootDir>/packages/types-known/src/$1',
|
||||
// eslint-disable-next-line sort-keys
|
||||
'@polkadot/types(.*)$': '<rootDir>/packages/types/src/$1'
|
||||
},
|
||||
modulePathIgnorePatterns: [
|
||||
@@ -18,7 +23,8 @@ module.exports = Object.assign({}, config, {
|
||||
'<rootDir>/packages/metadata/build',
|
||||
'<rootDir>/packages/rpc-core/build',
|
||||
'<rootDir>/packages/rpc-provider/build',
|
||||
'<rootDir>/packages/types/build'
|
||||
'<rootDir>/packages/types/build',
|
||||
'<rootDir>/packages/types-known/build'
|
||||
],
|
||||
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
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const path = require('path');
|
||||
|
||||
module.exports = function resolver (file, config) {
|
||||
|
||||
+1
-1
@@ -9,5 +9,5 @@
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "1.8.1"
|
||||
"version": "1.10.1"
|
||||
}
|
||||
|
||||
+3
-3
@@ -27,10 +27,10 @@
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/register": "^7.9.0",
|
||||
"@babel/runtime": "^7.9.2",
|
||||
"@polkadot/dev": "^0.51.7",
|
||||
"@polkadot/ts": "^0.3.14",
|
||||
"@polkadot/dev": "^0.52.9",
|
||||
"@polkadot/ts": "^0.3.18",
|
||||
"@polkadot/typegen": "workspace:packages/typegen",
|
||||
"@types/jest": "^25.1.4",
|
||||
"@types/jest": "^25.2.1",
|
||||
"copyfiles": "^2.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/api-contract",
|
||||
"version": "1.8.1",
|
||||
"version": "1.10.1",
|
||||
"description": "Interfaces for interacting with contracts and contract ABIs",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
@@ -27,11 +27,11 @@
|
||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-contract#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.9.2",
|
||||
"@polkadot/api": "1.8.1",
|
||||
"@polkadot/rpc-core": "1.8.1",
|
||||
"@polkadot/types": "1.8.1",
|
||||
"@polkadot/util": "^2.6.2",
|
||||
"@polkadot/api": "1.10.1",
|
||||
"@polkadot/rpc-core": "1.10.1",
|
||||
"@polkadot/types": "1.10.1",
|
||||
"@polkadot/util": "^2.8.1",
|
||||
"bn.js": "^5.1.1",
|
||||
"rxjs": "^6.5.4"
|
||||
"rxjs": "^6.5.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@ export default class ContractAbi extends ContractRegistry implements InterfaceAb
|
||||
|
||||
constructor (registry: Registry, abi: ContractABIPre) {
|
||||
super(registry, abi);
|
||||
[this.abi, this.constructors, this.messages] = this.decodeAbi(abi);
|
||||
[this.abi, this.constructors, this.messages] = this._decodeAbi(abi);
|
||||
}
|
||||
|
||||
private decodeAbi (abiPre: ContractABIPre): [ContractABI, ContractABIFn[], AbiMessages] {
|
||||
private _decodeAbi (abiPre: ContractABIPre): [ContractABI, ContractABIFn[], AbiMessages] {
|
||||
this.validateAbi(abiPre);
|
||||
|
||||
const abi = this.convertAbi(abiPre);
|
||||
|
||||
@@ -61,7 +61,7 @@ export default class ContractRegistry extends MetaRegistry {
|
||||
const unknownKeys = Object.keys(arg).filter((key): boolean => !['name', 'type'].includes(key));
|
||||
|
||||
assert(unknownKeys.length === 0, `Unknown keys ${unknownKeys.join(', ')} found in ABI args for ${name}`);
|
||||
assert(isNumber(arg.name) && isString(this.stringAt(arg.name)), `${name} args should have valid name `);
|
||||
assert(isNumber(arg.name) && isString(this._stringAt(arg.name)), `${name} args should have valid name `);
|
||||
assert(isNumber(arg.type.ty) && isObject(this.typeDefAt(arg.type.ty)), `${name} args should have valid type`);
|
||||
});
|
||||
}
|
||||
@@ -83,9 +83,9 @@ export default class ContractRegistry extends MetaRegistry {
|
||||
|
||||
assert(unknownKeys.length === 0, `Unknown keys ${unknownKeys.join(', ')} found in ABI args for messages.${message.name}`);
|
||||
|
||||
const { name, selector, return_type: returnType } = message;
|
||||
const { name, return_type: returnType, selector } = message;
|
||||
|
||||
assert(isNumber(name) && isString(this.stringAt(name)), `Expected name for ${fnname}`);
|
||||
assert(isNumber(name) && isString(this._stringAt(name)), `Expected name for ${fnname}`);
|
||||
assert(isNull(returnType) || (isNumber(returnType.ty) && isObject(this.typeDefAt(returnType.ty))), `Expected return_type for ${fnname}`);
|
||||
|
||||
parseSelector(this.registry, fnname, selector);
|
||||
@@ -100,7 +100,7 @@ export default class ContractRegistry extends MetaRegistry {
|
||||
|
||||
const { contract: { constructors, messages, name } } = abi;
|
||||
|
||||
assert(constructors && messages && isString(this.stringAt(name)), 'ABI should have constructors, messages & name sections');
|
||||
assert(constructors && messages && isString(this._stringAt(name)), 'ABI should have constructors, messages & name sections');
|
||||
|
||||
this.validateConstructors(abi);
|
||||
this.validateMessages(abi);
|
||||
@@ -109,13 +109,16 @@ export default class ContractRegistry extends MetaRegistry {
|
||||
public createMessage (name: string, message: Partial<ContractABIMessage> & ContractABIMessageBase): ContractABIFn {
|
||||
const args = message.args.map(({ name, type }): ContractABIFnArg => {
|
||||
assert(isObject(type), `Invalid type at index ${type}`);
|
||||
|
||||
return {
|
||||
name: stringCamelCase(name),
|
||||
type
|
||||
};
|
||||
});
|
||||
|
||||
const Clazz = createArgClass(this.registry, args, isUndefined(message.selector) ? {} : { __selector: 'u32' });
|
||||
const baseStruct: { [index: string]: any } = { __selector: isUndefined(message.selector) ? undefined : parseSelector(this.registry, name, message.selector) };
|
||||
|
||||
const encoder = (...params: CodecArg[]): Uint8Array => {
|
||||
assert(params.length === args.length, `Expected ${args.length} arguments to contract ${name}, found ${params.length}`);
|
||||
|
||||
@@ -136,6 +139,7 @@ export default class ContractRegistry extends MetaRegistry {
|
||||
fn.args = args;
|
||||
fn.isConstant = !(message.mutates || false);
|
||||
fn.type = message.returnType || null;
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
@@ -147,19 +151,20 @@ export default class ContractRegistry extends MetaRegistry {
|
||||
}
|
||||
|
||||
public convertArgs (args: ContractABIArgBasePre[]): any[] {
|
||||
return args.map(({ name, type, ...arg }) => ({ ...arg, name: this.stringAt(name), type: this.convertType(type) }));
|
||||
return args.map(({ name, type, ...arg }) => ({ ...arg, name: this._stringAt(name), type: this.convertType(type) }));
|
||||
}
|
||||
|
||||
public convertType ({ ty, display_name: displayNameIndices }: ContractABITypePre): TypeDef {
|
||||
public convertType ({ display_name: displayNameIndices, ty }: ContractABITypePre): TypeDef {
|
||||
const displayName = this.stringsAt(displayNameIndices).join('::');
|
||||
|
||||
return this.typeDefAt(ty, { displayName });
|
||||
}
|
||||
|
||||
public convertContract ({ constructors, messages, name, events, ...contract }: ContractABIContractPre): ContractABIContract {
|
||||
public convertContract ({ constructors, events, messages, name, ...contract }: ContractABIContractPre): ContractABIContract {
|
||||
return {
|
||||
constructors: this.convertConstructors(constructors),
|
||||
messages: messages.map((message) => this.convertMessage(message)),
|
||||
name: this.stringAt(name),
|
||||
name: this._stringAt(name),
|
||||
...(events
|
||||
? { events: events.map((event) => this.convertEvent(event)) }
|
||||
: {}),
|
||||
@@ -179,7 +184,7 @@ export default class ContractRegistry extends MetaRegistry {
|
||||
return {
|
||||
...message,
|
||||
args: this.convertArgs(args),
|
||||
name: this.stringAt(name),
|
||||
name: this._stringAt(name),
|
||||
returnType: returnType ? this.convertType(returnType) : null
|
||||
};
|
||||
}
|
||||
@@ -202,13 +207,13 @@ export default class ContractRegistry extends MetaRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
public convertStorageStruct ({ 'struct.type': structType, 'struct.fields': structFields }: ContractABIStorageStructPre): ContractABIStorageStruct {
|
||||
public convertStorageStruct ({ 'struct.fields': structFields, 'struct.type': structType }: ContractABIStorageStructPre): ContractABIStorageStruct {
|
||||
return {
|
||||
'struct.type': this.typeDefAt(structType),
|
||||
'struct.fields': structFields.map(({ name, layout }) => ({
|
||||
name: this.stringAt(name),
|
||||
layout: this.convertStorageLayout(layout)
|
||||
}))
|
||||
'struct.fields': structFields.map(({ layout, name }) => ({
|
||||
layout: this.convertStorageLayout(layout),
|
||||
name: this._stringAt(name)
|
||||
})),
|
||||
'struct.type': this.typeDefAt(structType)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class MetadataRegistryLookup {
|
||||
this._types = types;
|
||||
}
|
||||
|
||||
protected hasItemAt (index: number, variant: MetaRegistryItem): boolean {
|
||||
protected _hasItemAt (index: number, variant: MetaRegistryItem): boolean {
|
||||
switch (variant) {
|
||||
case MetaRegistryItem.String:
|
||||
return this._strings && !!this._strings[index - 1];
|
||||
@@ -59,8 +59,8 @@ class MetadataRegistryLookup {
|
||||
}
|
||||
}
|
||||
|
||||
protected itemAt (index: number, variant: MetaRegistryItem): any {
|
||||
assert(this.hasItemAt(index, variant), `MetaRegistry: Invalid ${variant} index ${index} found in metadata`);
|
||||
protected _itemAt (index: number, variant: MetaRegistryItem): any {
|
||||
assert(this._hasItemAt(index, variant), `MetaRegistry: Invalid ${variant} index ${index} found in metadata`);
|
||||
|
||||
switch (variant) {
|
||||
case MetaRegistryItem.String:
|
||||
@@ -72,33 +72,33 @@ class MetadataRegistryLookup {
|
||||
}
|
||||
}
|
||||
|
||||
protected itemsAt (indices: number[], variant: MetaRegistryItem): any[] {
|
||||
return indices.map((index: number): string => this.itemAt(index, variant));
|
||||
protected _itemsAt (indices: number[], variant: MetaRegistryItem): any[] {
|
||||
return indices.map((index: number): string => this._itemAt(index, variant));
|
||||
}
|
||||
|
||||
protected stringAt (index: StringIndex): string {
|
||||
return this.itemAt(index, MetaRegistryItem.String);
|
||||
protected _stringAt (index: StringIndex): string {
|
||||
return this._itemAt(index, MetaRegistryItem.String);
|
||||
}
|
||||
|
||||
public stringsAt (indices: StringIndex[]): string[] {
|
||||
return this.itemsAt(indices, MetaRegistryItem.String);
|
||||
return this._itemsAt(indices, MetaRegistryItem.String);
|
||||
}
|
||||
|
||||
public typeAt (index: TypeIndex): MetaType {
|
||||
return this.itemAt(index, MetaRegistryItem.Type);
|
||||
return this._itemAt(index, MetaRegistryItem.Type);
|
||||
}
|
||||
|
||||
public typesAt (indices: TypeIndex[]): MetaType[] {
|
||||
return this.itemsAt(indices, MetaRegistryItem.Type);
|
||||
return this._itemsAt(indices, MetaRegistryItem.Type);
|
||||
}
|
||||
|
||||
public hasTypeDefAt (index: TypeIndex): boolean {
|
||||
return this.hasItemAt(index, MetaRegistryItem.TypeDef);
|
||||
return this._hasItemAt(index, MetaRegistryItem.TypeDef);
|
||||
}
|
||||
|
||||
public typeDefAt (index: TypeIndex, extra: Pick<TypeDef, never> = {}): TypeDef {
|
||||
return {
|
||||
...this.itemAt(index, MetaRegistryItem.TypeDef),
|
||||
...this._itemAt(index, MetaRegistryItem.TypeDef),
|
||||
...extra
|
||||
};
|
||||
}
|
||||
@@ -116,7 +116,7 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
||||
this.typeDefs[typeIndex - 1] = this.typeDefFromMetaType(this.typeAt(typeIndex), typeIndex);
|
||||
}
|
||||
|
||||
private typeDefIdFields ({ id }: MetaType): Pick<TypeDef, never> {
|
||||
private _typeDefIdFields ({ id }: MetaType): Pick<TypeDef, never> {
|
||||
const { 'custom.name': nameIndex, 'custom.namespace': namespaceIndices, 'custom.params': paramsIndices } = id as MetaTypeIdCustom;
|
||||
|
||||
if (!nameIndex) {
|
||||
@@ -124,7 +124,7 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
||||
}
|
||||
|
||||
return {
|
||||
name: this.stringAt(nameIndex),
|
||||
name: this._stringAt(nameIndex),
|
||||
...(namespaceIndices && namespaceIndices.length
|
||||
? { namespace: this.stringsAt(namespaceIndices).join('::') }
|
||||
: {}
|
||||
@@ -136,33 +136,33 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
||||
};
|
||||
}
|
||||
|
||||
private typeDefDefFields (metaType: MetaType, typeIndex?: TypeIndex): Pick<TypeDef, never> {
|
||||
private _typeDefDefFields (metaType: MetaType, typeIndex?: TypeIndex): Pick<TypeDef, never> {
|
||||
let typeDef;
|
||||
|
||||
switch (detectedType(metaType)) {
|
||||
case MetaTypeInfo.BuiltinPlain:
|
||||
typeDef = this.typeDefForBuiltinPlain(metaType.id as string);
|
||||
typeDef = this._typeDefForBuiltinPlain(metaType.id as string);
|
||||
break;
|
||||
case MetaTypeInfo.BuiltinTuple:
|
||||
typeDef = this.typeDefForBuiltinTuple(metaType.id as TypeIndex[]);
|
||||
typeDef = this._typeDefForBuiltinTuple(metaType.id as TypeIndex[]);
|
||||
break;
|
||||
case MetaTypeInfo.BuiltinVec:
|
||||
typeDef = this.typeDefForBuiltinVec(metaType.id as MetaTypeIdVec, typeIndex);
|
||||
typeDef = this._typeDefForBuiltinVec(metaType.id as MetaTypeIdVec, typeIndex);
|
||||
break;
|
||||
case MetaTypeInfo.BuiltinVecFixed:
|
||||
typeDef = this.typeDefForBuiltinVecFixed(metaType.id as MetaTypeIdVecFixed, typeIndex);
|
||||
typeDef = this._typeDefForBuiltinVecFixed(metaType.id as MetaTypeIdVecFixed, typeIndex);
|
||||
break;
|
||||
case MetaTypeInfo.Enum:
|
||||
typeDef = this.typeDefForEnum(metaType.def as MetaTypeDefEnum, metaType.id as MetaTypeIdCustom, typeIndex);
|
||||
typeDef = this._typeDefForEnum(metaType.def as MetaTypeDefEnum, metaType.id as MetaTypeIdCustom, typeIndex);
|
||||
break;
|
||||
case MetaTypeInfo.ClikeEnum:
|
||||
typeDef = this.typeDefForClikeEnum(metaType.def as MetaTypeDefClikeEnum);
|
||||
typeDef = this._typeDefForClikeEnum(metaType.def as MetaTypeDefClikeEnum);
|
||||
break;
|
||||
case MetaTypeInfo.Struct:
|
||||
typeDef = this.typeDefForStruct(metaType.def as MetaTypeDefStruct);
|
||||
break;
|
||||
case MetaTypeInfo.TupleStruct:
|
||||
typeDef = this.typeDefForTupleStruct(metaType.def as MetaTypeDefTupleStruct);
|
||||
typeDef = this._typeDefForTupleStruct(metaType.def as MetaTypeDefTupleStruct);
|
||||
break;
|
||||
case MetaTypeInfo.Null:
|
||||
default:
|
||||
@@ -176,8 +176,8 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
||||
return withTypeString({
|
||||
info: TypeDefInfo.Null,
|
||||
type: '',
|
||||
...this.typeDefDefFields(metaType, typeIndex),
|
||||
...this.typeDefIdFields(metaType)
|
||||
...this._typeDefDefFields(metaType, typeIndex),
|
||||
...this._typeDefIdFields(metaType)
|
||||
}) as TypeDef;
|
||||
}
|
||||
|
||||
@@ -189,13 +189,13 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
||||
return this.typeDefAt(typeIndex);
|
||||
}
|
||||
|
||||
private typeDefForEnumVariant (variant: MetaTypeDefEnumVariant): Pick<TypeDef, any> {
|
||||
private _typeDefForEnumVariant (variant: MetaTypeDefEnumVariant): Pick<TypeDef, any> {
|
||||
const { 'unit_variant.name': unitNameIndex } = variant as MetaTypeDefEnumVariantUnit;
|
||||
|
||||
if (unitNameIndex) {
|
||||
return {
|
||||
info: TypeDefInfo.Plain,
|
||||
name: this.stringAt(unitNameIndex),
|
||||
name: this._stringAt(unitNameIndex),
|
||||
type: 'Null'
|
||||
};
|
||||
}
|
||||
@@ -203,7 +203,7 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
||||
const { 'tuple_struct_variant.name': tupleStructVariantNameIndex } = variant as MetaTypeDefEnumVariantTupleStruct;
|
||||
|
||||
if (tupleStructVariantNameIndex) {
|
||||
return this.typeDefForTupleStruct(variant as MetaTypeDefEnumVariantTupleStruct);
|
||||
return this._typeDefForTupleStruct(variant as MetaTypeDefEnumVariantTupleStruct);
|
||||
}
|
||||
|
||||
const { 'struct_variant.name': structVariantNameIndex } = variant as MetaTypeDefEnumVariantStruct;
|
||||
@@ -218,14 +218,14 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
||||
};
|
||||
}
|
||||
|
||||
private typeDefForBuiltinPlain (id: string): Pick<TypeDef, never> {
|
||||
private _typeDefForBuiltinPlain (id: string): Pick<TypeDef, never> {
|
||||
return {
|
||||
info: TypeDefInfo.Plain,
|
||||
type: id
|
||||
};
|
||||
}
|
||||
|
||||
private typeDefForBuiltinTuple (id: TypeIndex[]): Pick<TypeDef, never> {
|
||||
private _typeDefForBuiltinTuple (id: TypeIndex[]): Pick<TypeDef, never> {
|
||||
const sub = id.map((tupleTypeIndex: number): TypeDef => this.typeDefFromMetaTypeAt(tupleTypeIndex));
|
||||
|
||||
return {
|
||||
@@ -234,48 +234,52 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
||||
};
|
||||
}
|
||||
|
||||
private typeDefForBuiltinVec (id: MetaTypeIdVec, typeIndex?: TypeIndex): Pick<TypeDef, never> {
|
||||
private _typeDefForBuiltinVec (id: MetaTypeIdVec, typeIndex?: TypeIndex): Pick<TypeDef, never> {
|
||||
const { 'slice.type': vecTypeIndex } = id;
|
||||
|
||||
assert(!typeIndex || vecTypeIndex !== typeIndex, `MetaRegistry: self-referencing registry type at index ${typeIndex}`);
|
||||
|
||||
const type = displayType(this.typeDefFromMetaTypeAt(vecTypeIndex));
|
||||
|
||||
assert(type && type.length > 0, `MetaRegistry: Invalid builtin Vec type found at index ${typeIndex}`);
|
||||
|
||||
return {
|
||||
info: TypeDefInfo.Vec,
|
||||
type: `Vec<${type}>`,
|
||||
sub: this.typeDefFromMetaTypeAt(vecTypeIndex)
|
||||
sub: this.typeDefFromMetaTypeAt(vecTypeIndex),
|
||||
type: `Vec<${type}>`
|
||||
};
|
||||
}
|
||||
|
||||
private typeDefForBuiltinVecFixed (id: MetaTypeIdVecFixed, typeIndex?: TypeIndex): Pick<TypeDef, never> {
|
||||
const { 'array.type': vecTypeIndex, 'array.len': vecLength } = id;
|
||||
private _typeDefForBuiltinVecFixed (id: MetaTypeIdVecFixed, typeIndex?: TypeIndex): Pick<TypeDef, never> {
|
||||
const { 'array.len': vecLength, 'array.type': vecTypeIndex } = id;
|
||||
|
||||
assert(!vecLength || vecLength <= 256, 'MetaRegistry: Only support for [Type; <length>], where length <= 256');
|
||||
assert(!typeIndex || vecTypeIndex !== typeIndex, `MetaRegistry: self-referencing registry type at index ${typeIndex}`);
|
||||
|
||||
const type = displayType(this.typeDefFromMetaTypeAt(vecTypeIndex));
|
||||
|
||||
assert(type && type.length > 0, `MetaRegistry: Invalid vector type found at index ${typeIndex}`);
|
||||
|
||||
return {
|
||||
info: TypeDefInfo.VecFixed,
|
||||
length: vecLength, // ex: { type: type }
|
||||
type: `[${type};${vecLength}]`,
|
||||
sub: this.typeDefFromMetaTypeAt(vecTypeIndex)
|
||||
sub: this.typeDefFromMetaTypeAt(vecTypeIndex),
|
||||
type: `[${type};${vecLength}]`
|
||||
};
|
||||
}
|
||||
|
||||
private typeDefForEnum (def: MetaTypeDefEnum, id: MetaTypeIdCustom, typeIndex?: TypeIndex): Pick<TypeDef, any> {
|
||||
const name = id && this.stringAt(id['custom.name']);
|
||||
private _typeDefForEnum (def: MetaTypeDefEnum, id: MetaTypeIdCustom, typeIndex?: TypeIndex): Pick<TypeDef, any> {
|
||||
const name = id && this._stringAt(id['custom.name']);
|
||||
|
||||
switch (name) {
|
||||
case 'Option':
|
||||
return this.typeDefForOption(id, typeIndex);
|
||||
|
||||
case 'Result':
|
||||
return this.typeDefForResult(id, typeIndex);
|
||||
|
||||
default: {
|
||||
const sub = def['enum.variants'].map((variant) => this.typeDefForEnumVariant(variant));
|
||||
const sub = def['enum.variants'].map((variant) => this._typeDefForEnumVariant(variant));
|
||||
|
||||
return {
|
||||
info: TypeDefInfo.Enum,
|
||||
@@ -285,13 +289,13 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
||||
}
|
||||
}
|
||||
|
||||
private typeDefForClikeEnum (def: MetaTypeDefClikeEnum): Pick<TypeDef, never> {
|
||||
private _typeDefForClikeEnum (def: MetaTypeDefClikeEnum): Pick<TypeDef, never> {
|
||||
return {
|
||||
info: TypeDefInfo.Enum,
|
||||
sub: def['clike_enum.variants'].map(({ name: nameIndex, discriminant }): TypeDef => ({
|
||||
sub: def['clike_enum.variants'].map(({ discriminant, name: nameIndex }): TypeDef => ({
|
||||
ext: { discriminant },
|
||||
info: TypeDefInfo.Plain,
|
||||
name: this.stringAt(nameIndex),
|
||||
name: this._stringAt(nameIndex),
|
||||
type: 'Null'
|
||||
}))
|
||||
};
|
||||
@@ -322,24 +326,24 @@ export default class MetaRegistry extends MetadataRegistryLookup {
|
||||
return withTypeString({
|
||||
info: TypeDefInfo.Struct,
|
||||
...(structNameIndex
|
||||
? { name: this.stringAt(structNameIndex) }
|
||||
? { name: this._stringAt(structNameIndex) }
|
||||
: {}
|
||||
),
|
||||
sub: structFields.map((field: MetaTypeDefStructField): TypeDef => ({
|
||||
...this.typeDefFromMetaTypeAt(field.type),
|
||||
name: this.stringAt(field.name)
|
||||
name: this._stringAt(field.name)
|
||||
}))
|
||||
});
|
||||
}
|
||||
|
||||
private typeDefForTupleStruct (def: MetaTypeDefTupleStruct | MetaTypeDefEnumVariantTupleStruct): Pick<TypeDef, any> {
|
||||
private _typeDefForTupleStruct (def: MetaTypeDefTupleStruct | MetaTypeDefEnumVariantTupleStruct): Pick<TypeDef, any> {
|
||||
const tupleStructTypes = (def as MetaTypeDefTupleStruct)['tuple_struct.types'] || (def as MetaTypeDefEnumVariantTupleStruct)['tuple_struct_variant.types'];
|
||||
const tupleStructNameIndex = (def as MetaTypeDefEnumVariantTupleStruct)['tuple_struct_variant.name'];
|
||||
|
||||
return withTypeString({
|
||||
info: TypeDefInfo.Tuple,
|
||||
...(tupleStructNameIndex
|
||||
? { name: this.stringAt(tupleStructNameIndex) }
|
||||
? { name: this._stringAt(tupleStructNameIndex) }
|
||||
: {}
|
||||
),
|
||||
sub: tupleStructTypes.map((fieldIndex: number, index: number): TypeDef => ({
|
||||
|
||||
@@ -49,16 +49,16 @@ export default class Blueprint<ApiType extends ApiTypes> extends BaseWithTx<ApiT
|
||||
return {
|
||||
signAndSend: this.decorateMethod(
|
||||
(account: IKeyringPair | string | AccountId | Address): BlueprintCreateResultSubscription<ApiType> => {
|
||||
return this.apiContracts
|
||||
return this._apiContracts
|
||||
.create(endowment, maxGas, this.codeHash, this.abi.constructors[constructorIndex](...params))
|
||||
.signAndSend(account)
|
||||
.pipe(map(this.createResult));
|
||||
.pipe(map(this._createResult));
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
private createResult = (result: SubmittableResult): BlueprintCreateResult<ApiType> => {
|
||||
private _createResult = (result: SubmittableResult): BlueprintCreateResult<ApiType> => {
|
||||
let contract: Contract<ApiType> | undefined;
|
||||
|
||||
if (result.isInBlock) {
|
||||
|
||||
@@ -48,15 +48,15 @@ export default class Code<ApiType extends ApiTypes> extends BaseWithTx<ApiType>
|
||||
return {
|
||||
signAndSend: this.decorateMethod(
|
||||
(account: IKeyringPair | string | AccountId | Address): CodePutCodeResultSubscription<ApiType> =>
|
||||
this.apiContracts
|
||||
this._apiContracts
|
||||
.putCode(maxGas, compactAddLength(this.code))
|
||||
.signAndSend(account)
|
||||
.pipe(map(this.createResult))
|
||||
.pipe(map(this._createResult))
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
private createResult = (result: ISubmittableResult): CodePutCodeResult<ApiType> => {
|
||||
private _createResult = (result: ISubmittableResult): CodePutCodeResult<ApiType> => {
|
||||
let blueprint: Blueprint<ApiType> | undefined;
|
||||
|
||||
if (result.isInBlock) {
|
||||
|
||||
@@ -33,35 +33,41 @@ export type ContractCallResult<CallType extends ContractCallTypes> = CallType ex
|
||||
export default class Contract<ApiType extends ApiTypes> extends BaseWithTxAndRpcCall<ApiType> {
|
||||
public readonly address: Address;
|
||||
|
||||
constructor (api: ApiObject<ApiType>, abi: ContractABIPre | Abi, decorateMethod: DecorateMethod<ApiType>, address: string | AccountId | Address) {
|
||||
super(api, abi, decorateMethod);
|
||||
|
||||
this.address = this.registry.createType('Address', address);
|
||||
}
|
||||
|
||||
public call (as: 'rpc', message: string, value: BN | number, gasLimit: BN | number, ...params: any[]): ContractCall<ApiType, 'rpc'>;
|
||||
public call (as: 'tx', message: string, value: BN | number, gasLimit: BN | number, ...params: any[]): ContractCall<ApiType, 'tx'>;
|
||||
public call<CallType extends ContractCallTypes> (as: CallType, message: string, value: BN | number, gasLimit: BN | number, ...params: any[]): ContractCall<ApiType, CallType> {
|
||||
const { fn, def } = this.getMessage(message);
|
||||
const { def, fn } = this.getMessage(message);
|
||||
|
||||
return {
|
||||
send: this.decorateMethod(
|
||||
as === 'rpc' && this.hasRpcContractsCall
|
||||
? (account: IKeyringPair | string | AccountId | Address): ContractCallResult<'rpc'> =>
|
||||
this.rpcContractsCall(
|
||||
this._rpcContractsCall(
|
||||
this.registry.createType('ContractCallRequest', {
|
||||
origin: account,
|
||||
dest: this.address.toString(),
|
||||
value,
|
||||
gasLimit,
|
||||
inputData: fn(...params)
|
||||
inputData: fn(...params),
|
||||
origin: account,
|
||||
value
|
||||
})
|
||||
).pipe(map((result: ContractExecResult): ContractCallOutcome =>
|
||||
this.createOutcome(result, this.registry.createType('AccountId', account), def, params)
|
||||
this._createOutcome(result, this.registry.createType('AccountId', account), def, params)
|
||||
))
|
||||
: (account: IKeyringPair | string | AccountId | Address): ContractCallResult<'tx'> =>
|
||||
this.apiContracts
|
||||
this._apiContracts
|
||||
.call(this.address, value, gasLimit, fn(...params))
|
||||
.signAndSend(account)
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
private createOutcome (result: ContractExecResult, origin: AccountId, message: ContractABIMessage, params: any[]): ContractCallOutcome {
|
||||
private _createOutcome (result: ContractExecResult, origin: AccountId, message: ContractABIMessage, params: any[]): ContractCallOutcome {
|
||||
let output: Codec | null = null;
|
||||
|
||||
if (result.isSuccess) {
|
||||
@@ -73,19 +79,13 @@ export default class Contract<ApiType extends ApiTypes> extends BaseWithTxAndRpc
|
||||
}
|
||||
|
||||
return {
|
||||
time: Date.now(),
|
||||
isSuccess: result.isSuccess,
|
||||
message,
|
||||
origin,
|
||||
output,
|
||||
params,
|
||||
result,
|
||||
isSuccess: result.isSuccess,
|
||||
output
|
||||
time: Date.now()
|
||||
};
|
||||
}
|
||||
|
||||
constructor (api: ApiObject<ApiType>, abi: ContractABIPre | Abi, decorateMethod: DecorateMethod<ApiType>, address: string | AccountId | Address) {
|
||||
super(api, abi, decorateMethod);
|
||||
|
||||
this.address = this.registry.createType('Address', address);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@ export abstract class Base<ApiType extends ApiTypes> implements ContractBase<Api
|
||||
public get messages (): ContractMessage[] {
|
||||
return this.abi.abi.contract.messages.map(
|
||||
(def: ContractABIMessage, index): ContractMessage => ({
|
||||
index,
|
||||
def,
|
||||
fn: this.abi.messages[def.name] || this.abi.messages[stringCamelCase(name)]
|
||||
fn: this.abi.messages[def.name] || this.abi.messages[stringCamelCase(name)],
|
||||
index
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -49,12 +49,13 @@ export abstract class Base<ApiType extends ApiTypes> implements ContractBase<Api
|
||||
assert(!!def, `Attempted to access a contract message that does not exist: ${typeof nameOrIndex === 'number' ? `index ${nameOrIndex}` : nameOrIndex}`);
|
||||
|
||||
const fn = this.abi.messages[def.name] || this.abi.messages[stringCamelCase(def.name)];
|
||||
return { index, def, fn };
|
||||
|
||||
return { def, fn, index };
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class BaseWithTx<ApiType extends ApiTypes> extends Base<ApiType> {
|
||||
protected get apiContracts (): SubmittableModuleExtrinsics<'rxjs'> {
|
||||
protected get _apiContracts (): SubmittableModuleExtrinsics<'rxjs'> {
|
||||
return this.api.rx.tx.contracts;
|
||||
}
|
||||
|
||||
@@ -70,7 +71,7 @@ export abstract class BaseWithTxAndRpcCall<ApiType extends ApiTypes> extends Bas
|
||||
return isFunction(this.api.rx.rpc.contracts?.call);
|
||||
}
|
||||
|
||||
protected get rpcContractsCall (): DecoratedRpc<'rxjs', RpcInterface>['contracts']['call'] {
|
||||
protected get _rpcContractsCall (): DecoratedRpc<'rxjs', RpcInterface>['contracts']['call'] {
|
||||
assert(this.hasRpcContractsCall, 'You need to connect to a node with the contracts.call RPC method.');
|
||||
|
||||
return this.api.rx.rpc.contracts.call;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/api-derive",
|
||||
"version": "1.8.1",
|
||||
"version": "1.10.1",
|
||||
"description": "Common functions used across Polkadot, derived from RPC calls and storage queries.",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
@@ -28,17 +28,17 @@
|
||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.9.2",
|
||||
"@polkadot/api": "1.8.1",
|
||||
"@polkadot/rpc-core": "1.8.1",
|
||||
"@polkadot/rpc-provider": "1.8.1",
|
||||
"@polkadot/types": "1.8.1",
|
||||
"@polkadot/util": "^2.6.2",
|
||||
"@polkadot/util-crypto": "^2.6.2",
|
||||
"@polkadot/api": "1.10.1",
|
||||
"@polkadot/rpc-core": "1.10.1",
|
||||
"@polkadot/rpc-provider": "1.10.1",
|
||||
"@polkadot/types": "1.10.1",
|
||||
"@polkadot/util": "^2.8.1",
|
||||
"@polkadot/util-crypto": "^2.8.1",
|
||||
"bn.js": "^5.1.1",
|
||||
"memoizee": "^0.4.14",
|
||||
"rxjs": "^6.5.4"
|
||||
"rxjs": "^6.5.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/keyring": "^2.6.2"
|
||||
"@polkadot/keyring": "^2.8.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ function extractIdentity (identityOfOpt?: Option<Registration>, superOf?: [Accou
|
||||
: undefined,
|
||||
email: dataAsString(info.email),
|
||||
image: dataAsString(info.image),
|
||||
judgements,
|
||||
legal: dataAsString(info.legal),
|
||||
other: info.additional.reduce((other: Record<string, string>, [_key, _value]): Record<string, string> => {
|
||||
const key = dataAsString(_key);
|
||||
@@ -78,8 +79,7 @@ function extractIdentity (identityOfOpt?: Option<Registration>, superOf?: [Accou
|
||||
: undefined,
|
||||
riot: dataAsString(info.riot),
|
||||
twitter: dataAsString(info.twitter),
|
||||
web: dataAsString(info.web),
|
||||
judgements
|
||||
web: dataAsString(info.web)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -140,9 +140,9 @@ function retrieveFlags (api: ApiInterfaceRx, accountId?: AccountId): Observable<
|
||||
|
||||
return {
|
||||
isCouncil: (electionsMembers?.map(([id]) => id) || councilMembers || []).some(checkIncluded),
|
||||
isTechCommittee: technicalCommitteeMembers.some(checkIncluded),
|
||||
isSociety: societyMembers.some(checkIncluded),
|
||||
isSudo: !!sudoKey && sudoKey.eq(accountId)
|
||||
isSudo: !!sudoKey && sudoKey.eq(accountId),
|
||||
isTechCommittee: technicalCommitteeMembers.some(checkIncluded)
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import { AccountId, AccountData, AccountIndex, AccountInfo, Address, Balance, Index } from '@polkadot/types/interfaces';
|
||||
import { ITuple } from '@polkadot/types/types';
|
||||
import { DerivedBalancesAccount } from '../types';
|
||||
import { DeriveBalancesAccount } from '../types';
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
@@ -14,7 +14,7 @@ import { memo } from '../util';
|
||||
|
||||
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 {
|
||||
accountId,
|
||||
accountNonce,
|
||||
@@ -44,7 +44,7 @@ function queryBalancesAccount (api: ApiInterfaceRx, accountId: AccountId): Obser
|
||||
[api.query.balances.account, accountId],
|
||||
[api.query.system.accountNonce, accountId]
|
||||
]).pipe(
|
||||
map(([{ free, reserved, miscFrozen, feeFrozen }, accountNonce]): Result =>
|
||||
map(([{ feeFrozen, free, miscFrozen, reserved }, accountNonce]): Result =>
|
||||
[free, reserved, feeFrozen, miscFrozen, accountNonce]
|
||||
)
|
||||
);
|
||||
@@ -54,7 +54,7 @@ function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<Re
|
||||
// AccountInfo is current, support old, eg. Edgeware
|
||||
return api.query.system.account<AccountInfo | ITuple<[Index, AccountData]>>(accountId).pipe(
|
||||
map((infoOrTuple): Result => {
|
||||
const { free, reserved, miscFrozen, feeFrozen } = (infoOrTuple as AccountInfo).nonce
|
||||
const { feeFrozen, free, miscFrozen, reserved } = (infoOrTuple as AccountInfo).nonce
|
||||
? (infoOrTuple as AccountInfo).data
|
||||
: (infoOrTuple as [Index, AccountData])[1];
|
||||
const accountNonce = (infoOrTuple as AccountInfo).nonce || (infoOrTuple as [Index, AccountData])[0];
|
||||
@@ -79,8 +79,8 @@ function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<Re
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function account (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DerivedBalancesAccount> {
|
||||
return memo((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<DeriveBalancesAccount> =>
|
||||
api.derive.accounts.info(address).pipe(
|
||||
switchMap(({ accountId }): Observable<[AccountId, Result]> =>
|
||||
(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')]])
|
||||
)
|
||||
),
|
||||
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.
|
||||
|
||||
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 { Observable, combineLatest, of } from 'rxjs';
|
||||
@@ -15,9 +15,9 @@ import { bnMax } from '@polkadot/util';
|
||||
import { memo } from '../util';
|
||||
|
||||
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 lockedBreakdown: (BalanceLock | BalanceLockTo212)[] = [];
|
||||
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> {
|
||||
return memo((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<DeriveBalancesAll> =>
|
||||
api.derive.balances.account(address).pipe(
|
||||
switchMap((account): Observable<Result> =>
|
||||
(!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>')]])
|
||||
)
|
||||
),
|
||||
map((result): DerivedBalancesAll => calcBalances(api, result))
|
||||
map((result): DeriveBalancesAll => calcBalances(api, result))
|
||||
));
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Balance } from '@polkadot/types/interfaces';
|
||||
import { DerivedFees } from '../types';
|
||||
import { DeriveFees } from '../types';
|
||||
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
@@ -24,8 +24,8 @@ import { memo } from '../util';
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function fees (api: ApiInterfaceRx): () => Observable<DerivedFees> {
|
||||
return memo((): Observable<DerivedFees> =>
|
||||
export function fees (api: ApiInterfaceRx): () => Observable<DeriveFees> {
|
||||
return memo((): Observable<DeriveFees> =>
|
||||
of([
|
||||
// deprecated - remove
|
||||
(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?.transactionByteFee as Balance) || api.registry.createType('Balance')
|
||||
]).pipe(
|
||||
map(([creationFee, transferFee, existentialDeposit, transactionBaseFee, transactionByteFee]): DerivedFees => ({
|
||||
map(([creationFee, transferFee, existentialDeposit, transactionBaseFee, transactionByteFee]): DeriveFees => ({
|
||||
creationFee,
|
||||
existentialDeposit,
|
||||
transactionBaseFee,
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces';
|
||||
import { DerivedBalancesAccount } from '../types';
|
||||
import { DeriveBalancesAccount } from '../types';
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
export function votingBalances (api: ApiInterfaceRx): (addresses?: (AccountId | AccountIndex | Address | string)[]) => Observable<DerivedBalancesAccount[]> {
|
||||
return memo((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<DeriveBalancesAccount[]> =>
|
||||
!addresses || !addresses.length
|
||||
? of([] as DerivedBalancesAccount[])
|
||||
? of([] as DeriveBalancesAccount[])
|
||||
: combineLatest(
|
||||
addresses.map((accountId): Observable<DerivedBalancesAccount> =>
|
||||
addresses.map((accountId): Observable<DeriveBalancesAccount> =>
|
||||
api.derive.balances.account(accountId)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -4,17 +4,19 @@
|
||||
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Hash, Proposal, Votes } from '@polkadot/types/interfaces';
|
||||
import { DerivedCollectiveProposal } from '../types';
|
||||
import { DeriveCollectiveProposal } from '../types';
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { Option } from '@polkadot/types';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
type Result = [Hash[], Option<Proposal>[], Option<Votes>[]];
|
||||
|
||||
function parse ([hashes, proposals, votes]: Result): DerivedCollectiveProposal[] {
|
||||
function parse ([hashes, proposals, votes]: Result): DeriveCollectiveProposal[] {
|
||||
return proposals
|
||||
.map((proposalOpt, index): DerivedCollectiveProposal | null =>
|
||||
.map((proposalOpt, index): DeriveCollectiveProposal | null =>
|
||||
proposalOpt.isSome
|
||||
? {
|
||||
hash: hashes[index],
|
||||
@@ -23,11 +25,11 @@ function parse ([hashes, proposals, votes]: Result): DerivedCollectiveProposal[]
|
||||
}
|
||||
: null
|
||||
)
|
||||
.filter((proposal): proposal is DerivedCollectiveProposal => !!proposal);
|
||||
.filter((proposal): proposal is DeriveCollectiveProposal => !!proposal);
|
||||
}
|
||||
|
||||
export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalCommittee'): () => Observable<DerivedCollectiveProposal[]> {
|
||||
return (): Observable<DerivedCollectiveProposal[]> =>
|
||||
export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalCommittee'): () => Observable<DeriveCollectiveProposal[]> {
|
||||
return memo((): Observable<DeriveCollectiveProposal[]> =>
|
||||
api.query[section]?.proposals
|
||||
? api.query[section].proposals().pipe(
|
||||
switchMap((hashes: Hash[]): Observable<Result> =>
|
||||
@@ -41,5 +43,6 @@ export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalC
|
||||
),
|
||||
map(parse)
|
||||
)
|
||||
: of([] as DerivedCollectiveProposal[]);
|
||||
: of([] as DeriveCollectiveProposal[])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { DerivedContractFees } from '../types';
|
||||
import { DeriveContractFees } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable, of } from 'rxjs';
|
||||
@@ -44,10 +44,10 @@ function queryConstants (api: ApiInterfaceRx): Observable<ResultV2> {
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function fees (api: ApiInterfaceRx): () => Observable<DerivedContractFees> {
|
||||
return memo((): Observable<DerivedContractFees> => {
|
||||
export function fees (api: ApiInterfaceRx): () => Observable<DeriveContractFees> {
|
||||
return memo((): Observable<DeriveContractFees> => {
|
||||
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,
|
||||
contractFee,
|
||||
creationFee,
|
||||
|
||||
@@ -3,3 +3,5 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
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.
|
||||
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { DerivedCollectiveProposals } from '../types';
|
||||
import { DeriveCollectiveProposals } from '../types';
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import { proposals as collectiveProposals } from '../collective';
|
||||
import { memo } from '../util';
|
||||
|
||||
export function proposals (api: ApiInterfaceRx): () => Observable<DerivedCollectiveProposals> {
|
||||
export function proposals (api: ApiInterfaceRx): () => Observable<DeriveCollectiveProposals> {
|
||||
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
|
||||
// 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 './referendumInfos';
|
||||
export * from './referendumIds';
|
||||
export * from './referendums';
|
||||
export * from './referendumVotesFor';
|
||||
export * from './votes';
|
||||
export * from './referendumsActive';
|
||||
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
|
||||
// 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 { DeriveProposal } from '../types';
|
||||
import { DeriveProposalImage, DeriveProposal } from '../types';
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Bytes, Option, Vec } from '@polkadot/types';
|
||||
import { Option, Vec } from '@polkadot/types';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
export type PreImage = Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>;
|
||||
|
||||
type Depositors = Option<ITuple<[Balance, Vec<AccountId>]>>;
|
||||
type Proposals = Vec<ITuple<[PropIndex, Hash, AccountId]>>;
|
||||
|
||||
interface Result {
|
||||
depositors: Depositors[];
|
||||
preimages: PreImage[];
|
||||
proposals: Proposals;
|
||||
}
|
||||
|
||||
function parse (api: ApiInterfaceRx, { depositors, proposals, preimages }: Result): DeriveProposal[] {
|
||||
function parse ([proposals, images, depositors]: [Proposals, (DeriveProposalImage | undefined)[], Depositors[]]): DeriveProposal[] {
|
||||
return proposals
|
||||
.filter(([, , proposer], index): boolean =>
|
||||
!!(depositors[index]?.isSome) && !proposer.isEmpty
|
||||
)
|
||||
.map(([propIndex, hash, proposer], index): DeriveProposal => {
|
||||
const preimage = preimages[index].unwrapOr(null);
|
||||
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);
|
||||
}
|
||||
}
|
||||
.map(([index, imageHash, proposer], proposalIndex): DeriveProposal => {
|
||||
const [balance, seconds] = depositors[proposalIndex].unwrap();
|
||||
|
||||
return {
|
||||
balance: depositor[0],
|
||||
hash,
|
||||
index: propIndex,
|
||||
preimage: preimage
|
||||
? {
|
||||
at: preimage[3],
|
||||
balance: preimage[2],
|
||||
proposer: preimage[1]
|
||||
}
|
||||
: undefined,
|
||||
proposal,
|
||||
balance,
|
||||
image: images[proposalIndex],
|
||||
imageHash,
|
||||
index,
|
||||
proposer,
|
||||
seconds: depositor[1]
|
||||
seconds
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -68,16 +42,14 @@ export function proposals (api: ApiInterfaceRx): () => Observable<DeriveProposal
|
||||
switchMap((proposals) =>
|
||||
combineLatest([
|
||||
of(proposals),
|
||||
api.query.democracy.preimages.multi<PreImage>(
|
||||
api.derive.democracy.preimages(
|
||||
proposals.map(([, hash]): Hash => hash)),
|
||||
api.query.democracy.depositOf.multi<Depositors>(
|
||||
proposals.map(([index]): PropIndex => index))
|
||||
])
|
||||
),
|
||||
map(([proposals, preimages, depositors]): DeriveProposal[] =>
|
||||
parse(api, { depositors, proposals, preimages })
|
||||
)
|
||||
map(parse)
|
||||
)
|
||||
: 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
|
||||
// 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 { DeriveReferendumExt } from '../types';
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
export function referendums (api: ApiInterfaceRx): () => Observable<DerivedReferendum[]> {
|
||||
return memo((): Observable<DerivedReferendum[]> =>
|
||||
api.query.democracy?.lowestUnbaked
|
||||
? api.queryMulti<[ReferendumIndex, ReferendumIndex]>([
|
||||
api.query.democracy.lowestUnbaked,
|
||||
api.query.democracy.referendumCount
|
||||
]).pipe(
|
||||
switchMap(([earliest, referendumCount]): Observable<DerivedReferendum[]> =>
|
||||
referendumCount?.gt(earliest) && referendumCount?.gtn(0)
|
||||
? api.derive.democracy.referendumInfos(
|
||||
[...Array(referendumCount.sub(earliest).toNumber())].map((_, i): BN =>
|
||||
earliest.addn(i)
|
||||
)
|
||||
)
|
||||
: of([])
|
||||
)
|
||||
export function referendums (api: ApiInterfaceRx): () => Observable<DeriveReferendumExt[]> {
|
||||
return memo((): Observable<DeriveReferendumExt[]> =>
|
||||
api.derive.democracy.referendumsActive().pipe(
|
||||
switchMap((referendums) =>
|
||||
combineLatest([
|
||||
of(referendums),
|
||||
api.derive.democracy._referendumsVotes(referendums)
|
||||
])
|
||||
),
|
||||
map(([referendums, votes]) =>
|
||||
referendums.map((referendum, index): DeriveReferendumExt => ({
|
||||
...referendum,
|
||||
...votes[index]
|
||||
}))
|
||||
)
|
||||
: 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 { Vec, u32 } from '@polkadot/types';
|
||||
|
||||
import { DerivedElectionsInfo } from '../types';
|
||||
import { DeriveElectionsInfo } from '../types';
|
||||
import { memo } from '../util';
|
||||
|
||||
function sortAccounts ([, balanceA]: ITuple<[AccountId, Balance]>, [, balanceB]: ITuple<[AccountId, Balance]>): number {
|
||||
return balanceB.cmp(balanceA);
|
||||
}
|
||||
|
||||
function queryElections (api: ApiInterfaceRx): Observable<DerivedElectionsInfo> {
|
||||
function queryElections (api: ApiInterfaceRx): Observable<DeriveElectionsInfo> {
|
||||
const section = api.query.electionsPhragmen ? 'electionsPhragmen' : 'elections';
|
||||
|
||||
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].runnersUp
|
||||
]).pipe(
|
||||
map(([councilMembers, candidates, members, runnersUp]): DerivedElectionsInfo => ({
|
||||
candidates,
|
||||
candidateCount: api.registry.createType('u32', candidates.length),
|
||||
map(([councilMembers, candidates, members, runnersUp]): DeriveElectionsInfo => ({
|
||||
candidacyBond: api.consts[section].candidacyBond as Balance,
|
||||
candidateCount: api.registry.createType('u32', candidates.length),
|
||||
candidates,
|
||||
desiredSeats: api.consts[section].desiredMembers as u32,
|
||||
members: members.length
|
||||
? members.sort(sortAccounts)
|
||||
@@ -54,6 +54,6 @@ function queryElections (api: ApiInterfaceRx): Observable<DerivedElectionsInfo>
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function info (api: ApiInterfaceRx): () => Observable<DerivedElectionsInfo> {
|
||||
return memo((): Observable<DerivedElectionsInfo> => queryElections(api));
|
||||
export function info (api: ApiInterfaceRx): () => Observable<DeriveElectionsInfo> {
|
||||
return memo((): Observable<DeriveElectionsInfo> => queryElections(api));
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId } from '@polkadot/types/interfaces';
|
||||
import { DerivedHeartbeats } from '../types';
|
||||
import { DeriveHeartbeats } from '../types';
|
||||
|
||||
import { Observable, of, combineLatest } from 'rxjs';
|
||||
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
|
||||
*/
|
||||
export function receivedHeartbeats (api: ApiInterfaceRx): () => Observable<DerivedHeartbeats> {
|
||||
return memo((): Observable<DerivedHeartbeats> =>
|
||||
export function receivedHeartbeats (api: ApiInterfaceRx): () => Observable<DeriveHeartbeats> {
|
||||
return memo((): Observable<DeriveHeartbeats> =>
|
||||
api.query.imOnline?.receivedHeartbeats
|
||||
? api.derive.staking.overview().pipe(
|
||||
switchMap(({ currentIndex, validators }): Observable<[AccountId[], Option<Bytes>[], u32[]]> =>
|
||||
@@ -28,8 +28,8 @@ export function receivedHeartbeats (api: ApiInterfaceRx): () => Observable<Deriv
|
||||
validators.map((address) => [currentIndex, address]))
|
||||
])
|
||||
),
|
||||
map(([validators, heartbeats, numBlocks]): DerivedHeartbeats =>
|
||||
validators.reduce((result: DerivedHeartbeats, validator, index): DerivedHeartbeats => ({
|
||||
map(([validators, heartbeats, numBlocks]): DeriveHeartbeats =>
|
||||
validators.reduce((result: DeriveHeartbeats, validator, index): DeriveHeartbeats => ({
|
||||
...result,
|
||||
[validator.toString()]: {
|
||||
blockCount: numBlocks[index],
|
||||
|
||||
@@ -49,10 +49,8 @@ describe('derive', (): void => {
|
||||
testFunction(api)('chain', 'bestNumber', []);
|
||||
testFunction(api)('chain', 'bestNumberFinalized', []);
|
||||
|
||||
testFunction(api)('democracy', 'referendumInfos', []);
|
||||
testFunction(api)('democracy', 'proposals', []);
|
||||
testFunction(api)('democracy', 'referendums', []);
|
||||
testFunction(api)('democracy', 'referendumVotesFor', []);
|
||||
testFunction(api)('democracy', 'votes', []);
|
||||
|
||||
testFunction(api)('elections', 'info', []);
|
||||
|
||||
|
||||
@@ -21,10 +21,11 @@ import * as society from './society';
|
||||
import * as staking from './staking';
|
||||
import * as technicalCommittee from './technicalCommittee';
|
||||
import * as treasury from './treasury';
|
||||
import * as tx from './tx';
|
||||
|
||||
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> = {
|
||||
[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;
|
||||
// Not sure what to do here, casting as any. Though the final types are good
|
||||
const method = (section[methodName] as any)(api);
|
||||
|
||||
// idem
|
||||
(sectionAcc as any)[methodName] = method;
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ function parseActive (id: ParaId, active: Active): DeriveParachainActive | null
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import { memo } from '../util';
|
||||
|
||||
export function eraProgress (api: ApiInterfaceRx): () => Observable<BlockNumber> {
|
||||
return memo((): Observable<BlockNumber> =>
|
||||
api.derive.session.info().pipe(
|
||||
api.derive.session.progress().pipe(
|
||||
map((info) => info.eraProgress)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -6,4 +6,5 @@ export * from './eraLength';
|
||||
export * from './eraProgress';
|
||||
export * from './indexes';
|
||||
export * from './info';
|
||||
export * from './progress';
|
||||
export * from './sessionProgress';
|
||||
|
||||
@@ -3,110 +3,69 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { SessionIndex } from '@polkadot/types/interfaces';
|
||||
import { DerivedSessionInfo, DeriveSessionIndexes } from '../types';
|
||||
import { DeriveSessionInfo, DeriveSessionIndexes } from '../types';
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Option, u64 } from '@polkadot/types';
|
||||
import { u64 } from '@polkadot/types';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
type ResultSlots = [u64, u64, u64, Option<SessionIndex>];
|
||||
type ResultSlotsFlat = [u64, u64, u64, SessionIndex];
|
||||
type ResultType = [boolean, u64, SessionIndex];
|
||||
type Result = [ResultType, DeriveSessionIndexes, ResultSlotsFlat];
|
||||
|
||||
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);
|
||||
type Result = [ResultType, DeriveSessionIndexes];
|
||||
|
||||
function createDerive (api: ApiInterfaceRx, [[hasBabe, epochDuration, sessionsPerEra], { activeEra, activeEraStart, currentEra, currentIndex, validatorCount }]: Result): DeriveSessionInfo {
|
||||
return {
|
||||
activeEra,
|
||||
activeEraStart,
|
||||
currentEra,
|
||||
currentIndex,
|
||||
eraLength: api.registry.createType('BlockNumber', sessionsPerEra.mul(epochDuration)),
|
||||
eraProgress: api.registry.createType('BlockNumber', eraProgress),
|
||||
isEpoch: hasBabe,
|
||||
sessionLength: epochDuration,
|
||||
sessionsPerEra,
|
||||
sessionProgress: api.registry.createType('BlockNumber', sessionProgress),
|
||||
validatorCount
|
||||
};
|
||||
}
|
||||
|
||||
function queryAura (api: ApiInterfaceRx): Observable<DerivedSessionInfo> {
|
||||
function queryAura (api: ApiInterfaceRx): Observable<DeriveSessionInfo> {
|
||||
return api.derive.session.indexes().pipe(
|
||||
map((indexes): DerivedSessionInfo =>
|
||||
createDerived(api, [
|
||||
map((indexes): DeriveSessionInfo =>
|
||||
createDerive(api, [
|
||||
[
|
||||
false,
|
||||
api.registry.createType('u64', 1),
|
||||
api.consts.staking?.sessionsPerEra || api.registry.createType('SessionIndex', 1)
|
||||
],
|
||||
indexes,
|
||||
[
|
||||
api.registry.createType('u64', 1),
|
||||
api.registry.createType('u64', 1),
|
||||
api.registry.createType('u64', 1),
|
||||
api.registry.createType('SessionIndex', 1)
|
||||
]
|
||||
indexes
|
||||
])
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function queryBabe (api: ApiInterfaceRx): Observable<[DeriveSessionIndexes, ResultSlotsFlat]> {
|
||||
function queryBabe (api: ApiInterfaceRx): Observable<DeriveSessionInfo> {
|
||||
return api.derive.session.indexes().pipe(
|
||||
switchMap((indexes): Observable<[DeriveSessionIndexes, ResultSlots]> =>
|
||||
combineLatest([
|
||||
of(indexes),
|
||||
api.queryMulti<ResultSlots>([
|
||||
api.query.babe.currentSlot,
|
||||
api.query.babe.epochIndex,
|
||||
api.query.babe.genesisSlot,
|
||||
[api.query.staking.erasStartSessionIndex, indexes.activeEra]
|
||||
])
|
||||
map((indexes) =>
|
||||
createDerive(api, [
|
||||
[
|
||||
true,
|
||||
api.consts.babe.epochDuration,
|
||||
api.consts.staking.sessionsPerEra
|
||||
],
|
||||
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
|
||||
*/
|
||||
export function info (api: ApiInterfaceRx): () => Observable<DerivedSessionInfo> {
|
||||
return memo((): Observable<DerivedSessionInfo> =>
|
||||
export function info (api: ApiInterfaceRx): () => Observable<DeriveSessionInfo> {
|
||||
return memo((): Observable<DeriveSessionInfo> =>
|
||||
api.consts.babe
|
||||
? (api.query.staking.erasStartSessionIndex
|
||||
? 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
|
||||
])
|
||||
)
|
||||
)
|
||||
? queryBabe(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> {
|
||||
return memo((): Observable<BlockNumber> =>
|
||||
api.derive.session.info().pipe(
|
||||
api.derive.session.progress().pipe(
|
||||
map((info) => info.sessionProgress)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -14,11 +14,14 @@ export interface DeriveSessionIndexes {
|
||||
validatorCount: u32;
|
||||
}
|
||||
|
||||
export interface DerivedSessionInfo extends DeriveSessionIndexes {
|
||||
export interface DeriveSessionInfo extends DeriveSessionIndexes {
|
||||
eraLength: BlockNumber;
|
||||
eraProgress: BlockNumber;
|
||||
isEpoch: boolean;
|
||||
sessionLength: BlockNumber;
|
||||
sessionsPerEra: SessionIndex;
|
||||
}
|
||||
|
||||
export interface DeriveSessionProgress extends DeriveSessionInfo {
|
||||
eraProgress: BlockNumber;
|
||||
sessionProgress: BlockNumber;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ export function candidates (api: ApiInterfaceRx): () => Observable<DeriveSociety
|
||||
])
|
||||
),
|
||||
map(([candidates, suspended]: Result): DeriveSocietyCandidate[] =>
|
||||
candidates.map(({ who, kind, value }, index) => ({
|
||||
candidates.map(({ kind, value, who }, index) => ({
|
||||
accountId: who,
|
||||
isSuspended: suspended[index].isSome,
|
||||
kind,
|
||||
|
||||
@@ -30,9 +30,9 @@ export function info (api: ApiInterfaceRx): () => Observable<DeriveSociety> {
|
||||
map(([bids, defender, founder, head, maxMembers, pot]: Result): DeriveSociety => ({
|
||||
bids,
|
||||
defender: defender.unwrapOr(undefined),
|
||||
founder: founder.unwrapOr(undefined),
|
||||
hasDefender: (defender.isSome && head.isSome && !head.eq(defender)) || false,
|
||||
head: head.unwrapOr(undefined),
|
||||
founder: founder.unwrapOr(undefined),
|
||||
maxMembers,
|
||||
pot
|
||||
}))
|
||||
|
||||
@@ -29,8 +29,8 @@ export function member (api: ApiInterfaceRx): (accountId: AccountId) => Observab
|
||||
]).pipe(
|
||||
map(([payouts, strikes, defenderVotes, suspended, vouching]: Result): DeriveSocietyMember => ({
|
||||
accountId,
|
||||
payouts,
|
||||
isSuspended: suspended.isTrue,
|
||||
payouts,
|
||||
strikes,
|
||||
vote: defenderVotes.unwrapOr(undefined),
|
||||
vouching: vouching.unwrapOr(undefined)
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Balance, BlockNumber, StakingLedger, UnlockChunk } from '@polkadot/types/interfaces';
|
||||
import { DerivedSessionInfo, DerivedStakingAccount, DerivedStakingQuery, DerivedUnlocking } from '../types';
|
||||
import { Balance, StakingLedger, UnlockChunk } from '@polkadot/types/interfaces';
|
||||
import { DeriveSessionInfo, DeriveStakingAccount, DeriveStakingQuery, DeriveUnlocking } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
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 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 {
|
||||
function calculateUnlocking (api: ApiInterfaceRx, stakingLedger: StakingLedger | undefined, sessionInfo: DeriveSessionInfo): DeriveUnlocking[] | undefined {
|
||||
if (isUndefined(stakingLedger)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const unlockingChunks = stakingLedger.unlocking.filter(({ era }): boolean =>
|
||||
remainingBlocks(api, era.unwrap(), sessionInfo).gtn(0)
|
||||
era.unwrap().sub(sessionInfo.activeEra).gtn(0)
|
||||
);
|
||||
|
||||
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
|
||||
const groupedResult = groupByEra(unlockingChunks);
|
||||
const results = Object.entries(groupedResult).map(([eraString, value]): DerivedUnlocking => ({
|
||||
value: api.registry.createType('Balance', value),
|
||||
remainingBlocks: remainingBlocks(api, new BN(eraString), sessionInfo)
|
||||
const results = Object.entries(groupedResult).map(([eraString, value]): DeriveUnlocking => ({
|
||||
remainingEras: new BN(eraString).sub(sessionInfo.activeEra),
|
||||
value: api.registry.createType('Balance', value)
|
||||
}));
|
||||
|
||||
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)) {
|
||||
return api.registry.createType('Balance');
|
||||
}
|
||||
|
||||
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;
|
||||
}, new BN(0)));
|
||||
}
|
||||
|
||||
function parseResult (api: ApiInterfaceRx, sessionInfo: DerivedSessionInfo, query: DerivedStakingQuery): DerivedStakingAccount {
|
||||
function parseResult (api: ApiInterfaceRx, sessionInfo: DeriveSessionInfo, query: DeriveStakingQuery): DeriveStakingAccount {
|
||||
return {
|
||||
...query,
|
||||
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
|
||||
*/
|
||||
export function account (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DerivedStakingAccount> {
|
||||
return memo((accountId: Uint8Array | string): Observable<DerivedStakingAccount> =>
|
||||
export function account (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DeriveStakingAccount> {
|
||||
return memo((accountId: Uint8Array | string): Observable<DeriveStakingAccount> =>
|
||||
combineLatest([
|
||||
api.derive.session.info(),
|
||||
api.derive.staking.query(accountId)
|
||||
]).pipe(
|
||||
map(([sessionInfo, query]: [DerivedSessionInfo, DerivedStakingQuery]) =>
|
||||
map(([sessionInfo, query]: [DeriveSessionInfo, DeriveStakingQuery]) =>
|
||||
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 { AccountId } from '@polkadot/types/interfaces';
|
||||
import { DerivedStakingQuery, DerivedStakingElected } from '../types';
|
||||
import { DeriveStakingQuery, DeriveStakingElected } from '../types';
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
export function electedInfo (api: ApiInterfaceRx): () => Observable<DerivedStakingElected> {
|
||||
return memo((): Observable<DerivedStakingElected> =>
|
||||
export function electedInfo (api: ApiInterfaceRx): () => Observable<DeriveStakingElected> {
|
||||
return memo((): Observable<DeriveStakingElected> =>
|
||||
api.derive.staking.validators().pipe(
|
||||
switchMap(({ nextElected }): Observable<[AccountId[], DerivedStakingQuery[]]> =>
|
||||
switchMap(({ nextElected }): Observable<[AccountId[], DeriveStakingQuery[]]> =>
|
||||
combineLatest([
|
||||
of(nextElected),
|
||||
combineLatest(
|
||||
nextElected.map((accountId): Observable<DerivedStakingQuery> =>
|
||||
api.derive.staking.query(accountId)
|
||||
)
|
||||
nextElected.map((accountId) => api.derive.staking.query(accountId))
|
||||
)
|
||||
])
|
||||
),
|
||||
map(([nextElected, info]): DerivedStakingElected => ({
|
||||
map(([nextElected, info]): DeriveStakingElected => ({
|
||||
info,
|
||||
nextElected
|
||||
}))
|
||||
|
||||
@@ -6,7 +6,6 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { EraIndex, Exposure } from '@polkadot/types/interfaces';
|
||||
import { DeriveEraExposure, DeriveEraNominatorExposure, DeriveEraValidatorExposure } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { StorageKey } from '@polkadot/types';
|
||||
@@ -24,11 +23,11 @@ function mapStakers (era: EraIndex, stakers: KeysAndExposures): DeriveEraExposur
|
||||
|
||||
validators[validatorId] = exposure;
|
||||
|
||||
exposure.others.forEach(({ who }, index): void => {
|
||||
exposure.others.forEach(({ who }, validatorIndex): void => {
|
||||
const nominatorId = who.toString();
|
||||
|
||||
nominators[nominatorId] = nominators[nominatorId] || [];
|
||||
nominators[nominatorId].push([validatorId, index]);
|
||||
nominators[nominatorId].push({ validatorId, validatorIndex });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,16 +42,18 @@ export function eraExposure (api: ApiInterfaceRx): (era: EraIndex) => Observable
|
||||
);
|
||||
}
|
||||
|
||||
export function erasExposure (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraExposure[]> {
|
||||
return memo((withActive?: boolean | BN | number): Observable<DeriveEraExposure[]> =>
|
||||
export function _erasExposure (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraExposure[]> {
|
||||
return memo((eras: EraIndex[]): Observable<DeriveEraExposure[]> =>
|
||||
eras.length
|
||||
? combineLatest(eras.map((era) => api.derive.staking.eraExposure(era)))
|
||||
: of([])
|
||||
);
|
||||
}
|
||||
|
||||
export function erasExposure (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraExposure[]> {
|
||||
return memo((withActive?: boolean): Observable<DeriveEraExposure[]> =>
|
||||
api.derive.staking.erasHistoric(withActive).pipe(
|
||||
switchMap((eras): Observable<DeriveEraExposure[]> =>
|
||||
eras.length
|
||||
? combineLatest(
|
||||
eras.map((era) => api.derive.staking.eraExposure(era))
|
||||
)
|
||||
: of([])
|
||||
)
|
||||
switchMap((eras) => api.derive.staking._erasExposure(eras))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,45 +9,32 @@ import BN from 'bn.js';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Option, u32 } from '@polkadot/types';
|
||||
import { isBoolean, isUndefined, bnToBn } from '@polkadot/util';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
export function erasHistoric (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<EraIndex[]> {
|
||||
return memo((withActive?: boolean | BN | number): Observable<EraIndex[]> =>
|
||||
export function erasHistoric (api: ApiInterfaceRx): (withActive?: boolean) => Observable<EraIndex[]> {
|
||||
return memo((withActive?: boolean): Observable<EraIndex[]> =>
|
||||
api.query.staking?.activeEra
|
||||
? api.queryMulti<[Option<ActiveEraInfo>, u32]>([
|
||||
api.query.staking.activeEra,
|
||||
api.query.staking.historyDepth
|
||||
]).pipe(
|
||||
map(([activeEraOpt, historyDepth]): EraIndex[] => {
|
||||
const result: (EraIndex | null)[] = [];
|
||||
const result: EraIndex[] = [];
|
||||
const max = historyDepth.toNumber();
|
||||
const activeEra = activeEraOpt.unwrapOrDefault().index.toBn();
|
||||
const activeEra: BN = activeEraOpt.unwrapOrDefault().index;
|
||||
let lastEra = activeEra;
|
||||
|
||||
while (lastEra.gten(0) && (result.length < max)) {
|
||||
result.push(
|
||||
((lastEra !== activeEra) || (withActive === true))
|
||||
? api.registry.createType('EraIndex', lastEra)
|
||||
: null
|
||||
);
|
||||
if ((lastEra !== activeEra) || (withActive === true)) {
|
||||
result.push(api.registry.createType('EraIndex', lastEra));
|
||||
}
|
||||
|
||||
lastEra = lastEra.subn(1);
|
||||
}
|
||||
|
||||
const startEra = isUndefined(withActive) || isBoolean(withActive)
|
||||
? new BN(0)
|
||||
: bnToBn(withActive);
|
||||
|
||||
// go from oldest to newest
|
||||
return result
|
||||
.filter((era): era is EraIndex =>
|
||||
era
|
||||
? era.gte(startEra)
|
||||
: false
|
||||
)
|
||||
.reverse();
|
||||
return result.reverse();
|
||||
})
|
||||
)
|
||||
: of([])
|
||||
|
||||
@@ -6,8 +6,7 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { EraIndex, EraRewardPoints } from '@polkadot/types/interfaces';
|
||||
import { DeriveEraPoints, DeriveEraValPoints } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
|
||||
import { memo } from '../util';
|
||||
@@ -22,24 +21,26 @@ function mapValidators ({ individual }: EraRewardPoints): DeriveEraValPoints {
|
||||
}, {});
|
||||
}
|
||||
|
||||
export function erasPoints (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraPoints[]> {
|
||||
return memo((withActive?: boolean | number): Observable<DeriveEraPoints[]> =>
|
||||
api.derive.staking.erasHistoric(withActive).pipe(
|
||||
switchMap((eras): Observable<[EraIndex[], EraRewardPoints[]]> =>
|
||||
combineLatest([
|
||||
of(eras),
|
||||
eras.length
|
||||
? api.query.staking.erasRewardPoints.multi<EraRewardPoints>(eras)
|
||||
: of([])
|
||||
])
|
||||
),
|
||||
map(([eras, points]): DeriveEraPoints[] =>
|
||||
eras.map((era, index): DeriveEraPoints => ({
|
||||
era,
|
||||
eraPoints: points[index].total,
|
||||
validators: mapValidators(points[index])
|
||||
}))
|
||||
export function _erasPoints (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraPoints[]> {
|
||||
return memo((eras: EraIndex[]): Observable<DeriveEraPoints[]> =>
|
||||
eras.length
|
||||
? api.query.staking.erasRewardPoints.multi<EraRewardPoints>(eras).pipe(
|
||||
map((points) =>
|
||||
eras.map((era, index): DeriveEraPoints => ({
|
||||
era,
|
||||
eraPoints: points[index].total,
|
||||
validators: mapValidators(points[index])
|
||||
}))
|
||||
)
|
||||
)
|
||||
: of([])
|
||||
);
|
||||
}
|
||||
|
||||
export function erasPoints (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraPoints[]> {
|
||||
return memo((withActive?: boolean): Observable<DeriveEraPoints[]> =>
|
||||
api.derive.staking.erasHistoric(withActive).pipe(
|
||||
switchMap((eras) => api.derive.staking._erasPoints(eras))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { EraIndex, ValidatorPrefs } from '@polkadot/types/interfaces';
|
||||
import { DeriveEraPrefs, DeriveEraValPrefs } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { StorageKey } from '@polkadot/types';
|
||||
@@ -31,16 +30,18 @@ export function eraPrefs (api: ApiInterfaceRx): (era: EraIndex) => Observable<De
|
||||
);
|
||||
}
|
||||
|
||||
export function erasPrefs (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraPrefs[]> {
|
||||
return memo((withActive?: boolean | BN | number): Observable<DeriveEraPrefs[]> =>
|
||||
export function _erasPrefs (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraPrefs[]> {
|
||||
return memo((eras: EraIndex[]): Observable<DeriveEraPrefs[]> =>
|
||||
eras.length
|
||||
? combineLatest(eras.map((era) => api.derive.staking.eraPrefs(era)))
|
||||
: of([])
|
||||
);
|
||||
}
|
||||
|
||||
export function erasPrefs (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraPrefs[]> {
|
||||
return memo((withActive?: boolean): Observable<DeriveEraPrefs[]> =>
|
||||
api.derive.staking.erasHistoric(withActive).pipe(
|
||||
switchMap((eras): Observable<DeriveEraPrefs[]> =>
|
||||
eras.length
|
||||
? combineLatest(
|
||||
eras.map((era) => api.derive.staking.eraPrefs(era))
|
||||
)
|
||||
: of([])
|
||||
)
|
||||
switchMap((eras) => api.derive.staking._erasPrefs(eras))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,30 +6,29 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Balance, EraIndex } from '@polkadot/types/interfaces';
|
||||
import { DeriveEraRewards } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { Option } from '@polkadot/types';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
export function erasRewards (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraRewards[]> {
|
||||
return memo((withActive?: boolean | BN | number): Observable<DeriveEraRewards[]> =>
|
||||
api.derive.staking.erasHistoric(withActive).pipe(
|
||||
switchMap((eras): Observable<[EraIndex[], Option<Balance>[]]> =>
|
||||
combineLatest([
|
||||
of(eras),
|
||||
eras.length
|
||||
? api.query.staking.erasValidatorReward.multi<Option<Balance>>(eras)
|
||||
: of([])
|
||||
])
|
||||
),
|
||||
map(([eras, rewards]): DeriveEraRewards[] =>
|
||||
eras.map((era, index): DeriveEraRewards => ({
|
||||
export function _erasRewards (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraRewards[]> {
|
||||
return memo((eras: EraIndex[]): Observable<DeriveEraRewards[]> =>
|
||||
eras.length
|
||||
? api.query.staking.erasValidatorReward.multi<Option<Balance>>(eras).pipe(
|
||||
map((rewards) => eras.map((era, index): DeriveEraRewards => ({
|
||||
era,
|
||||
eraReward: rewards[index].unwrapOrDefault()
|
||||
}))
|
||||
})))
|
||||
)
|
||||
: of([])
|
||||
);
|
||||
}
|
||||
|
||||
export function erasRewards (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraRewards[]> {
|
||||
return memo((withActive?: boolean): Observable<DeriveEraRewards[]> =>
|
||||
api.derive.staking.erasHistoric(withActive).pipe(
|
||||
switchMap((eras) => api.derive.staking._erasRewards(eras))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import { BalanceOf, EraIndex, Perbill } from '@polkadot/types/interfaces';
|
||||
import { ITuple } from '@polkadot/types/types';
|
||||
import { DeriveEraSlashes, DeriveEraValSlash } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { Option, StorageKey } from '@polkadot/types';
|
||||
@@ -40,16 +39,20 @@ export function eraSlashes (api: ApiInterfaceRx): (era: EraIndex) => Observable<
|
||||
);
|
||||
}
|
||||
|
||||
export function erasSlashes (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraSlashes[]> {
|
||||
return memo((withActive?: boolean | BN | number): Observable<DeriveEraSlashes[]> =>
|
||||
api.derive.staking.erasHistoric(withActive).pipe(
|
||||
switchMap((eras): Observable<DeriveEraSlashes[]> =>
|
||||
eras.length
|
||||
? combineLatest(
|
||||
eras.map((era) => api.derive.staking.eraSlashes(era))
|
||||
)
|
||||
: of([])
|
||||
export function _erasSlashes (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraSlashes[]> {
|
||||
return memo((eras: EraIndex[]): Observable<DeriveEraSlashes[]> =>
|
||||
eras.length
|
||||
? combineLatest(
|
||||
eras.map((era) => api.derive.staking.eraSlashes(era))
|
||||
)
|
||||
: of([])
|
||||
);
|
||||
}
|
||||
|
||||
export function erasSlashes (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraSlashes[]> {
|
||||
return memo((withActive?: boolean): Observable<DeriveEraSlashes[]> =>
|
||||
api.derive.staking.erasHistoric(withActive).pipe(
|
||||
switchMap((eras) => api.derive.staking._erasSlashes(eras))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
export * from './account';
|
||||
export * from './currentPoints';
|
||||
export * from './erasExposure';
|
||||
export * from './erasHistoric';
|
||||
export * from './erasPoints';
|
||||
|
||||
@@ -2,51 +2,27 @@
|
||||
// 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 { DerivedStakingOverview } from '../types';
|
||||
import { DeriveStakingOverview } from '../types';
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { Observable, combineLatest } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
function retrievePointsPrev (api: ApiInterfaceRx, currentElected: AccountId[]): Observable<EraRewardPoints> {
|
||||
return api.query.staking.currentEraPointsEarned<EraPoints>().pipe(
|
||||
map(({ individual, total }): EraRewardPoints =>
|
||||
api.registry.createType('EraRewardPoints', {
|
||||
total,
|
||||
individual: new Map<AccountId, RewardPoint>(
|
||||
individual
|
||||
.map((points): RewardPoint => api.registry.createType('RewardPoint', points))
|
||||
.map((points, index): [AccountId, RewardPoint] => [currentElected[index], points])
|
||||
)
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Retrieve the staking overview, including elected and points earned
|
||||
*/
|
||||
export function overview (api: ApiInterfaceRx): () => Observable<DerivedStakingOverview> {
|
||||
return memo((): Observable<DerivedStakingOverview> =>
|
||||
export function overview (api: ApiInterfaceRx): () => Observable<DeriveStakingOverview> {
|
||||
return memo((): Observable<DeriveStakingOverview> =>
|
||||
combineLatest([
|
||||
api.derive.session.indexes(),
|
||||
api.derive.staking.validators()
|
||||
]).pipe(
|
||||
switchMap(([indexes, { nextElected, validators }]) =>
|
||||
combineLatest([
|
||||
of({ ...indexes, nextElected, validators }),
|
||||
api.query.staking.erasRewardPoints
|
||||
? api.query.staking.erasRewardPoints<EraRewardPoints>(indexes.activeEra)
|
||||
: api.query.staking.currentEraPointsEarned
|
||||
? retrievePointsPrev(api, nextElected)
|
||||
: of(api.registry.createType('EraRewardPoints'))
|
||||
])
|
||||
),
|
||||
map(([info, eraPoints]): DerivedStakingOverview => ({
|
||||
...info, eraPoints
|
||||
map(([indexes, { nextElected, validators }]): DeriveStakingOverview => ({
|
||||
...indexes,
|
||||
nextElected,
|
||||
validators
|
||||
}))
|
||||
));
|
||||
}
|
||||
|
||||
@@ -5,14 +5,13 @@
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { DeriveOwnExposure } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
export function ownExposure (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean | BN | number) => Observable<DeriveOwnExposure[]> {
|
||||
return memo((accountId: Uint8Array | string, withActive?: boolean | BN | number): Observable<DeriveOwnExposure[]> => {
|
||||
export function ownExposure (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveOwnExposure[]> {
|
||||
return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveOwnExposure[]> => {
|
||||
return api.derive.staking.erasHistoric(withActive).pipe(
|
||||
switchMap((eras) =>
|
||||
eras.length
|
||||
|
||||
@@ -5,14 +5,13 @@
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { DeriveStakerSlashes } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
export function ownSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean | BN | number) => Observable<DeriveStakerSlashes[]> {
|
||||
return memo((accountId: Uint8Array | string, withActive?: boolean | BN | number): Observable<DeriveStakerSlashes[]> => {
|
||||
export function ownSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveStakerSlashes[]> {
|
||||
return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveStakerSlashes[]> => {
|
||||
return api.derive.staking.erasHistoric(withActive).pipe(
|
||||
switchMap((eras) =>
|
||||
eras.length
|
||||
@@ -30,9 +29,7 @@ export function ownSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | strin
|
||||
era,
|
||||
total: optVal.isSome
|
||||
? optVal.unwrap()[1]
|
||||
: optNom.isSome
|
||||
? optNom.unwrap()
|
||||
: api.registry.createType('Balance')
|
||||
: optNom.unwrapOrDefault()
|
||||
}))
|
||||
)
|
||||
);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { AccountId, Exposure, Keys, Nominations, RewardDestination, ValidatorPrefs } from '@polkadot/types/interfaces';
|
||||
import { ITuple } from '@polkadot/types/types';
|
||||
import { DerivedStakingQuery } from '../types';
|
||||
import { DeriveStakingQuery } from '../types';
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
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 nominators = nominatorsOpt.unwrapOr(null);
|
||||
|
||||
return controllerId
|
||||
? api.query.staking.ledger(controllerId).pipe(
|
||||
map((stakingLedgerOpt): DerivedStakingQuery => ({
|
||||
map((stakingLedgerOpt): DeriveStakingQuery => ({
|
||||
accountId: stashId,
|
||||
controllerId,
|
||||
exposure,
|
||||
@@ -82,30 +82,41 @@ function retrieveController (api: ApiInterfaceRx, stashId: AccountId, [queuedKey
|
||||
: of({ accountId: stashId, nextSessionIds: [], sessionIds: [] });
|
||||
}
|
||||
|
||||
/**
|
||||
* @description From a stash, retrieve the controllerId and all relevant details
|
||||
*/
|
||||
export function query (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DerivedStakingQuery> {
|
||||
return memo((accountId: Uint8Array | string): Observable<DerivedStakingQuery> => {
|
||||
export function queryWithQueued (api: ApiInterfaceRx): (accountId: Uint8Array | string, queuedKeys: Vec<ITuple<[AccountId, Keys]>>) => Observable<DeriveStakingQuery> {
|
||||
return memo((accountId: Uint8Array | string, queuedKeys: Vec<ITuple<[AccountId, Keys]>>): Observable<DeriveStakingQuery> => {
|
||||
const stashId = api.registry.createType('AccountId', accountId);
|
||||
|
||||
return combineLatest([
|
||||
api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>(),
|
||||
return (
|
||||
api.query.staking.erasStakers
|
||||
? retrieveCurr(api, stashId)
|
||||
: retrievePrev(api, stashId)
|
||||
]).pipe(
|
||||
switchMap((result): Observable<DerivedStakingQuery> =>
|
||||
retrieveController(api, stashId, result)
|
||||
).pipe(
|
||||
switchMap((result): Observable<DeriveStakingQuery> =>
|
||||
retrieveController(api, stashId, queuedKeys, result)
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function queryMulti (api: ApiInterfaceRx): (...accountIds: (Uint8Array | string)[]) => Observable<DerivedStakingQuery[]> {
|
||||
return memo((...accountIds: (Uint8Array | string)[]): Observable<DerivedStakingQuery[]> =>
|
||||
combineLatest(
|
||||
accountIds.map((accountId) => api.derive.staking.query(accountId))
|
||||
/**
|
||||
* @description From a stash, retrieve the controllerId and all relevant details
|
||||
*/
|
||||
export function query (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DeriveStakingQuery> {
|
||||
return memo((accountId: Uint8Array | string): Observable<DeriveStakingQuery> =>
|
||||
api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>().pipe(
|
||||
switchMap((queuedKeys) => api.derive.staking.queryWithQueued(accountId, queuedKeys))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export function queryMulti (api: ApiInterfaceRx): (accountIds: (Uint8Array | string)[]) => Observable<DeriveStakingQuery[]> {
|
||||
return memo((accountIds: (Uint8Array | string)[]): Observable<DeriveStakingQuery[]> =>
|
||||
accountIds.length
|
||||
? api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>().pipe(
|
||||
switchMap((queuedKeys) => combineLatest(
|
||||
accountIds.map((acc) => api.derive.staking.queryWithQueued(acc, queuedKeys))
|
||||
))
|
||||
)
|
||||
: of([])
|
||||
);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user