Compare commits

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

* CHANGELOG

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

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

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

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

* Some current and validator retrieval opts

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

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

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

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

* Chain defs

* Allow stakers queries with exclude filter

* Generate interfaces

* Return all exposures

* Rework exposures

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

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

* Updated

* debug logs

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

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

* Fix call encoding (stepped into that one)

* Event struct order

* Update with missing tuple type (getTypeDef type)
2020-04-01 22:44:34 +02:00
Github Actions 7d3464ae2c [CI Skip] 1.9.1
skip-checks: true
2020-04-01 10:26:10 +00:00
Jaco Greeff 295cd2a7e0 1.9 (#2124) 2020-04-01 12:14:00 +02:00
Github Actions 5a66ce5a87 [CI Skip] 1.9.0-beta.27
skip-checks: true
2020-04-01 08:01:14 +00:00
Jaco Greeff d8d008108d CI scripts (#2123) 2020-04-01 09:49:16 +02:00
Github Actions 491518405d [CI Skip] 1.9.0-beta.26
skip-checks: true
2020-03-31 13:18:37 +00:00
Jaco Greeff 7290b3d296 sanitize options (allowNamespaces) (#2122)
* sanitize options (allowNamespaces)

* Pass actual option to test
2020-03-31 15:07:35 +02:00
Github Actions b6162a316f [CI Skip] 1.9.0-beta.25
skip-checks: true
2020-03-31 13:06:05 +00:00
Jaco Greeff 71c1d16dc4 Bump @polkadot/util (#2121) 2020-03-31 14:54:49 +02:00
Github Actions 204f592bea [CI Skip] 1.9.0-beta.24
skip-checks: true
2020-03-31 11:52:59 +00:00
Jaco Greeff 39c44bb5aa Split @polkadot/types/known into @polkadot/types-known (#2120)
* Split @polkadot/types/known into @polkadot/types-known

* Rreadme link

* tsconfig typo

* script aliasses
2020-03-31 13:40:59 +02:00
Github Actions df0de49a67 [CI Skip] 1.9.0-beta.23
skip-checks: true
2020-03-31 07:28:28 +00:00
Jaco Greeff 0bdbf4b7a7 Use querystorageAt for map entries (optional) (#2119) 2020-03-31 09:17:36 +02:00
Github Actions ef9cd6fc4b [CI Skip] 1.9.0-beta.22
skip-checks: true
2020-03-30 16:33:11 +00:00
Jaco Greeff 5ab0bf3998 Aplit derive session.{info, progress} (#2117) 2020-03-30 18:20:34 +02:00
Github Actions e69d97619e [CI Skip] 1.9.0-beta.21
skip-checks: true
2020-03-30 12:04:00 +00:00
Jaco Greeff 6aa0d90fc0 Add childstate_* RPCs (#2065)
* Add childstate_* RPCs

* childstate into rpc-core

* PrefixedStorageKey
2020-03-30 13:53:33 +02:00
Jaco Greeff d338fcb58c Add derive for council voting info (#2115)
* Add derive for council voting info

* Update packages/api-derive/src/council/votes.ts
2020-03-30 13:48:14 +02:00
Github Actions b9a60a2519 [CI Skip] 1.9.0-beta.20
skip-checks: true
2020-03-28 21:06:18 +00:00
Jaco Greeff 7b8b4e8078 BTreeSet only has single sub (#2114) 2020-03-28 21:55:49 +01:00
Github Actions 50b551e4fc [CI Skip] 1.9.0-beta.19
skip-checks: true
2020-03-28 20:06:12 +00:00
Jaco Greeff a4ea4d648a Handle double-encoded Bytes in fallback/constants (#2113)
* Handle double-encoded Bytes in fallback/constants

* Fix import, bypass for tests
2020-03-28 20:55:39 +01:00
Github Actions 146360a454 [CI Skip] 1.9.0-beta.18
skip-checks: true
2020-03-27 20:00:32 +00:00
Jaco Greeff 2e83d92adc Derive for deomcracy nextExternal (#2108) 2020-03-27 20:49:18 +01:00
Github Actions b77e5d079c [CI Skip] 1.9.0-beta.17
skip-checks: true
2020-03-27 17:10:21 +00:00
Jaco Greeff 0d067c9484 Add api.derive.democracy.dispatchQueue (#2107) 2020-03-27 17:59:22 +01:00
Github Actions 88519eff3f [CI Skip] 1.9.0-beta.16
skip-checks: true
2020-03-27 14:44:07 +00:00
Jaco Greeff bb14471e60 Consistency in Derive* type names (#2106) 2020-03-27 15:34:41 +01:00
Github Actions 97ab7fcf2f [CI Skip] 1.9.0-beta.15
skip-checks: true
2020-03-27 13:18:21 +00:00
Jaco Greeff 922cfb8759 FAQ entry for node-template addresses (#2105) 2020-03-27 14:07:51 +01:00
Github Actions 717f33ca02 [CI Skip] 1.9.0-beta.14
skip-checks: true
2020-03-27 12:36:19 +00:00
Jaco Greeff 21a2b5f0b7 signAndSend with finalized hash (depending on lag) (#2104)
* signAndSend with finalized hash (depending on drift)

* Extract lag calc

* mock update

* getSigningHeader

* api.derive.tx (with submittable cleanups)

* Adjust mortal calculations

* Cleanup new tx derives

* Optimize calcs

* Comment cleanups, next-up testing

* Adjust mocks

* Adjust sig (period is now based on metadata)

* Remove extra fn, tested and it works
2020-03-27 13:26:12 +01:00
Github Actions 54efead9d7 [CI Skip] 1.9.0-beta.13
skip-checks: true
2020-03-27 09:29:42 +00:00
Jaco Greeff c472a451a4 Bump dev (#2103)
* Bump dev

* Rewrite yarn.lock
2020-03-27 10:20:02 +01:00
Github Actions 6ed2de43fc [CI Skip] 1.9.0-beta.12
skip-checks: true
2020-03-26 20:20:55 +00:00
Jaco Greeff 8976ded37f Add state_queryStorageAt RPC (#2082)
* Add state_queryStorageAt RPC

* Add queryStorageAt rpc

* Clanup merge
2020-03-26 21:08:34 +01:00
Github Actions 169a374544 [CI Skip] 1.9.0-beta.11
skip-checks: true
2020-03-26 15:52:15 +00:00
Jaco Greeff 6476d88e19 Update .123trigger 2020-03-26 16:40:34 +01:00
Github Actions 75de454619 [CI Skip] 1.9.0-beta.10
skip-checks: true
2020-03-26 15:35:59 +00:00
Jaco Greeff 851428aef9 Merge branch 'master' of github.com:polkadot-js/api 2020-03-26 16:25:50 +01:00
Jaco Greeff dfc51ad300 Adjust toCallsOnly typing 2020-03-26 16:25:45 +01:00
Github Actions e16d288644 [CI Skip] 1.9.0-beta.9
skip-checks: true
2020-03-26 15:18:52 +00:00
Jaco Greeff a19928fef9 Add additional types for offchain Phragmen (#2097)
* Add additional types for offchain Phragmen

* Trim down metadata toCallsOnly
2020-03-26 16:07:54 +01:00
Github Actions 0906c7837a [CI Skip] 1.9.0-beta.8
skip-checks: true
2020-03-26 14:27:21 +00:00
Jaco Greeff cb9831c4f8 Bump metadata (#2096)
* Bump metadata

* Update staking types

* Enum updates
2020-03-26 15:17:20 +01:00
Github Actions 620d3757ba [CI Skip] 1.9.0-beta.7
skip-checks: true
2020-03-25 13:14:24 +00:00
Jaco Greeff 601288b3ec Handle <module>::<Type> in sanitize (#2094)
* Handle <module>::<Type> in santize

* Sanitize all ::'s

* Additional cleanups
2020-03-25 14:01:24 +01:00
Github Actions efbeecc8f6 [CI Skip] 1.9.0-beta.6
skip-checks: true
2020-03-25 10:18:50 +00:00
Jaco Greeff 852e0d4f0b Additional referendum derive cleanups (#2093) 2020-03-25 11:06:16 +01:00
Github Actions 5c7f9f1c8a [CI Skip] 1.9.0-beta.5
skip-checks: true
2020-03-25 08:54:57 +00:00
Jaco Greeff 64f64c1001 Add referensumsActive (#2091) 2020-03-25 09:43:05 +01:00
Github Actions 15c3085511 [CI Skip] 1.9.0-beta.4
skip-checks: true
2020-03-25 08:34:25 +00:00
Jaco Greeff 27cd9b1ca4 Cleanup interfaces/rpc, types to correct locations (#2084)
* Cleanup interfaces/rcp, types to correct locations

* Update import locations
2020-03-25 09:23:03 +01:00
Github Actions 1c2a95f820 [CI Skip] 1.9.0-beta.3
skip-checks: true
2020-03-25 07:52:42 +00:00
Jaco Greeff 8bf5e51725 Return Observable when no referendums (#2090)
* Return Observable when no referendums

* Small ordering cleanups
2020-03-25 08:41:26 +01:00
Github Actions 493225aa9d [CI Skip] 1.9.0-beta.2
skip-checks: true
2020-03-25 07:12:03 +00:00
Jaco Greeff a0979a9ce3 Only format error log, upstream error from core (#2089)
* Only format error log, upstream error from core

* Remove (now unused) wrapping info
2020-03-25 08:00:14 +01:00
Github Actions 02849ae49b [CI Skip] 1.9.0-beta.1
skip-checks: true
2020-03-24 16:50:32 +00:00
Jaco Greeff 602bb1406b derive.referendum extended info (#2086)
* derive.referendum extended info

* update

* util bump
2020-03-24 17:39:37 +01:00
Github Actions d70930587c [CI Skip] 1.9.0-beta.0
skip-checks: true
2020-03-23 10:37:30 +00:00
Jaco Greeff 8c011cdc86 Adjust new vote retrieval with entries (#2080)
* Adjust new vote retrieval with entries

* testing
2020-03-23 11:24:06 +01:00
320 changed files with 6412 additions and 3542 deletions
+2 -2
View File
@@ -1,3 +1,3 @@
20 21
1.4.2 1.4.2
1.6.2 1.6.2
-3
View File
@@ -10,9 +10,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: '12.x'
- name: ${{ matrix.step }} - name: ${{ matrix.step }}
run: | run: |
yarn install --immutable | grep -v 'YN0013' yarn install --immutable | grep -v 'YN0013'
+1 -4
View File
@@ -10,15 +10,12 @@ jobs:
matrix: matrix:
step: ['build:release', 'docs:release'] step: ['build:release', 'docs:release']
name: ${{ matrix.step }} name: ${{ matrix.step }}
if: "! contains(github.event.head_commit.message, '[CI Skip]')" if: "! contains(github.event.head_commit.message, '[CI Skip]') && github.repository == 'polkadot-js/api'"
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
with: with:
token: ${{ secrets.GH_PAT }} token: ${{ secrets.GH_PAT }}
- uses: actions/setup-node@v1
with:
node-version: '12.x'
- name: ${{ matrix.step }} - name: ${{ matrix.step }}
env: env:
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }} CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
+30 -1
View File
@@ -1,6 +1,34 @@
# 1.10.1 Apr 13, 2020
- **Important** Substrate master has updated staking, on older chains apply `StakingLedger: 'StakingLedgerTo240'`
- Add `rpc.system.chainType` to retrieve the chain type (Development. Local, Live & Custom)
- Adjust types for Westend after the reset
- Adjust democracy derives, including the support of the frame-scheduler for scheduled deployments
- Allow staking derives to work with new staking payouts, specifically `tx.staking.payoutStakers`
- Cleanups to derives for democracy & staking to be more performant
- Add Centrifuge base types to `@polkadot/types-known`
- Adjust with all the latest substrate master types
- Internally all private/protected methods/variables are now `_` prefixed (Aligning with the `private/protected` indicators in the TS definitions)
- Update metadata/docs-from-metadata to the latest Substrate
# 1.9.1 Apr 1, 2020
- **Breaking change** (TypeScript with derives only) The return type names for `api.derive.*` have been adjusted for consistency, all starting with `Derive*` (previously a mixture of `Derived*` and `Derive*`)
- **Breaking change** (derives only) Additional cleanups of democracy proposal & referenda derives, including support for new Polkadot/Substrate vote retrievals
- Tx signing via `signAndSend` & `signAsync` now tries to use the last finalized block (depending on finalized drift)
- Add support for `api.rpc.childstate.*` Substrate RPCs, older nodes with still populate `api.rpc.state.*` with the child methods
- Adjust `Error.message` on RPC failures to not include the (already known) method signature
- Split `@polkadot/types/known` into `@polkadot/types-known`, allowing for base API overrides
- Extended `api.derive.democracy` to cater for dispatchQueue and externals
- Extended `api.derive.council` to cater for new phragmen elections
- Use new `queryStorageAt` for query `.entries`, removing unneeded subscriptions (use as available)
- Fix `BTreeSet` initialization when it forms part of query interfaces
- Fix encoding for `Vec<u8>`-related types as part of constants
- Internal adjustment of interface type locations (no impact on imports via `@polkadot/types/interfaces`)
# 1.8.1 Mar 22, 2020 # 1.8.1 Mar 22, 2020
- **Breaking change** The format for any custom RPCs have been changed alongside API-internal changes to allow for better RPC management. If you are currently using custom RPCs (or planning to do so), look at the [updated documentation](https://polkadot.js.org/api/start/rpc.custom.html) - **Breaking change** The format for any custom RPCs have been changed (alongside API-internal changes) to allow for better RPC management. If you are currently using custom RPCs (or planning to do so), look at the [updated documentation](https://polkadot.js.org/api/start/rpc.custom.html)
- **Breaking change** Alongside API RPC changes, the `@polkadot/jsonrpc` package has been removed. Since it was never documented and only used internally, this should not have adverse impacts. All RPC definitions itself has now been moved to the relevant modules inside `@polkadot/types/interfaces` - **Breaking change** Alongside API RPC changes, the `@polkadot/jsonrpc` package has been removed. Since it was never documented and only used internally, this should not have adverse impacts. All RPC definitions itself has now been moved to the relevant modules inside `@polkadot/types/interfaces`
- **Important** Substrate has an updated democracy module. If using an older chain add the `ReferendumInfo: 'ReferendumInfoTo239'` type when using referendums - **Important** Substrate has an updated democracy module. If using an older chain add the `ReferendumInfo: 'ReferendumInfoTo239'` type when using referendums
- The `isRetracted` Extrinsic status is now a warning, not a fatal error, correctly aligning with Polkadot/Substrate - The `isRetracted` Extrinsic status is now a warning, not a fatal error, correctly aligning with Polkadot/Substrate
@@ -8,6 +36,7 @@
- Add support for all known substrate RPC methods - Add support for all known substrate RPC methods
- Extend account derives to include status flags, e.g. `isCouncil`, `isSudo`, ... - Extend account derives to include status flags, e.g. `isCouncil`, `isSudo`, ...
- Adjusted referendum derives to cater for bot new/old democracy. Derived `referendumInfo` now includes `status` field, not `info` - Adjusted referendum derives to cater for bot new/old democracy. Derived `referendumInfo` now includes `status` field, not `info`
- Add `initWasm` flag to API options. When set to `false` does not init the WASM portion (leaving it to the user elsewhere)
# 1.7.1 Mar 17, 2020 # 1.7.1 Mar 17, 2020
+4
View File
@@ -1 +1,5 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
module.exports = require('@polkadot/dev/config/babel'); module.exports = require('@polkadot/dev/config/babel');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Required imports // Required imports
const { ApiPromise, WsProvider } = require('@polkadot/api'); const { ApiPromise, WsProvider } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API // Import the API
const { ApiPromise } = require('@polkadot/api'); const { ApiPromise } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API // Import the API
const { ApiPromise } = require('@polkadot/api'); const { ApiPromise } = require('@polkadot/api');
@@ -13,13 +14,13 @@ async function main () {
// Retrieve the initial balance. Since the call has no callback, it is simply a promise // Retrieve the initial balance. Since the call has no callback, it is simply a promise
// that resolves to the current on-chain value // that resolves to the current on-chain value
let { nonce: previousNonce, data: { free: previousFree } } = await api.query.system.account(Alice); let { data: { free: previousFree }, nonce: previousNonce } = await api.query.system.account(Alice);
console.log(`${Alice} has a balance of ${previousFree}, nonce ${previousNonce}`); console.log(`${Alice} has a balance of ${previousFree}, nonce ${previousNonce}`);
console.log(`You may leave this example running and start example 06 or transfer any value to ${Alice}`); console.log(`You may leave this example running and start example 06 or transfer any value to ${Alice}`);
// Here we subscribe to any balance changes and update the on-screen value // Here we subscribe to any balance changes and update the on-screen value
api.query.system.account(Alice, ({ nonce: currentNonce, data: { free: currentFree } }) => { api.query.system.account(Alice, ({ data: { free: currentFree }, nonce: currentNonce }) => {
// Calculate the delta // Calculate the delta
const change = currentFree.sub(previousFree); const change = currentFree.sub(previousFree);
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API // Import the API
const { ApiPromise } = require('@polkadot/api'); const { ApiPromise } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API // Import the API
const { ApiPromise } = require('@polkadot/api'); const { ApiPromise } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API // Import the API
const { ApiPromise } = require('@polkadot/api'); const { ApiPromise } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API // Import the API
const { ApiPromise } = require('@polkadot/api'); const { ApiPromise } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API, Keyring and some utility functions // Import the API, Keyring and some utility functions
const { ApiPromise } = require('@polkadot/api'); const { ApiPromise } = require('@polkadot/api');
const { Keyring } = require('@polkadot/keyring'); const { Keyring } = require('@polkadot/keyring');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API, Keyring and some utility functions // Import the API, Keyring and some utility functions
const { ApiPromise } = require('@polkadot/api'); const { ApiPromise } = require('@polkadot/api');
const { Keyring } = require('@polkadot/keyring'); const { Keyring } = require('@polkadot/keyring');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API // Import the API
const { ApiPromise } = require('@polkadot/api'); const { ApiPromise } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable @typescript-eslint/no-var-requires */
// Import the API & Provider and some utility functions // Import the API & Provider and some utility functions
const { ApiPromise } = require('@polkadot/api'); const { ApiPromise } = require('@polkadot/api');
@@ -44,7 +45,7 @@ async function main () {
console.log('Included at block hash', status.asInBlock.toHex()); console.log('Included at block hash', status.asInBlock.toHex());
console.log('Events:'); console.log('Events:');
events.forEach(({ phase, event: { data, method, section } }) => { events.forEach(({ event: { data, method, section }, phase }) => {
console.log('\t', phase.toString(), `: ${section}.${method}`, data.toString()); console.log('\t', phase.toString(), `: ${section}.${method}`, data.toString());
}); });
} else if (status.isFinalized) { } else if (status.isFinalized) {
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API & Provider and some utility functions // Import the API & Provider and some utility functions
const { ApiPromise, WsProvider } = require('@polkadot/api'); const { ApiPromise, WsProvider } = require('@polkadot/api');
+2 -1
View File
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Required imports // Required imports
const { zip } = require('rxjs'); const { zip } = require('rxjs');
const { ApiRx } = require('@polkadot/api'); const { ApiRx } = require('@polkadot/api');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API // Import the API
const { ApiRx } = require('@polkadot/api'); const { ApiRx } = require('@polkadot/api');
const { switchMap } = require('rxjs/operators'); const { switchMap } = require('rxjs/operators');
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API and operators from RxJs // Import the API and operators from RxJs
const { ApiRx } = require('@polkadot/api'); const { ApiRx } = require('@polkadot/api');
const { pairwise, startWith } = require('rxjs/operators'); const { pairwise, startWith } = require('rxjs/operators');
@@ -27,6 +28,7 @@ async function main () {
// then balance[1] is the initial value of Alice account. // then balance[1] is the initial value of Alice account.
console.log(`Alice ${Alice} has a balance of ${balance[1].data.free}`); console.log(`Alice ${Alice} has a balance of ${balance[1].data.free}`);
console.log('You may leave this example running and start the "Make a transfer" example or transfer any value to Alice address'); console.log('You may leave this example running and start the "Make a transfer" example or transfer any value to Alice address');
return; return;
} }
+2 -1
View File
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API // Import the API
const { ApiRx } = require('@polkadot/api'); const { ApiRx } = require('@polkadot/api');
const { switchMap } = require('rxjs/operators'); const { switchMap } = require('rxjs/operators');
+2 -1
View File
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API // Import the API
const { ApiRx } = require('@polkadot/api'); const { ApiRx } = require('@polkadot/api');
const { combineLatest, of } = require('rxjs'); const { combineLatest, of } = require('rxjs');
+3 -1
View File
@@ -1,6 +1,8 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API, Keyring and some utility functions // Import the API, Keyring and some utility functions
const { ApiRx } = require('@polkadot/api'); const { ApiRx } = require('@polkadot/api');
const { Keyring } = require('@polkadot/keyring'); const { Keyring } = require('@polkadot/keyring');
+2 -1
View File
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API and selected RxJs operators // Import the API and selected RxJs operators
const { switchMap } = require('rxjs/operators'); const { switchMap } = require('rxjs/operators');
const { ApiRx } = require('@polkadot/api'); const { ApiRx } = require('@polkadot/api');
+3 -2
View File
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API and some utility functions // Import the API and some utility functions
const { ApiRx } = require('@polkadot/api'); const { ApiRx } = require('@polkadot/api');
@@ -48,7 +49,7 @@ async function main () {
console.log('Included at block hash', status.asInBlock.toHex()); console.log('Included at block hash', status.asInBlock.toHex());
console.log('Events:'); console.log('Events:');
events.forEach(({ phase, event: { data, method, section } }) => { events.forEach(({ event: { data, method, section }, phase }) => {
console.log('\t', phase.toString(), `: ${section}.${method}`, data.toString()); console.log('\t', phase.toString(), `: ${section}.${method}`, data.toString());
}); });
} else if (status.isFinalized) { } else if (status.isFinalized) {
+2 -1
View File
@@ -1,6 +1,7 @@
/* eslint-disable header/header */
/* eslint-disable @typescript-eslint/require-await */ /* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable @typescript-eslint/unbound-method */
/* eslint-disable @typescript-eslint/no-var-requires */
// Import the API & Provider and some utility functions // Import the API & Provider and some utility functions
const { ApiRx, WsProvider } = require('@polkadot/api'); const { ApiRx, WsProvider } = require('@polkadot/api');
// Import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie) // Import the test keyring (already has dev keys for Alice, Bob, Charlie, Eve & Ferdie)
+9 -1
View File
@@ -40,7 +40,7 @@ Tuples, as defined in the Polkadot/Substrate types appear as `(TypeA, TypeB)`. F
Polkadot/Substrate supports both immortal and mortal transactions. For immortal, this means that the transaction has an infinite lifetime, for mortals, the transactions expire after a defined period. By default the API sends mortal transactions when no explicit extrinsic era has been specified. This means that all transaction has a limited lifetime and will expire if not included in the period set. Polkadot/Substrate supports both immortal and mortal transactions. For immortal, this means that the transaction has an infinite lifetime, for mortals, the transactions expire after a defined period. By default the API sends mortal transactions when no explicit extrinsic era has been specified. This means that all transaction has a limited lifetime and will expire if not included in the period set.
The length for this transaction validity is set to 50 blocks, which translates to 5 minutes assuming a default of 6 second blocktimes. (10 blocks per minute in this default configuration). The length for this transaction validity is set to 5 minutes, calculated based on the blocktime for the chain. (10 blocks per minute in this default 6s Substrate configuration).
## My chain does not support system.account queries ## My chain does not support system.account queries
@@ -49,3 +49,11 @@ The API always tracks the latest Substrate master in terms of examples. This mea
It is possible that you are connecting to an older chain that has not been upgraded yet. For these chains, this storage entry won't be available (yet). To query the nonce on older chains, you can do a query to `api.query.system.accountNonce(<account>)` and balances can be retrieved via `api.query.balances.freeBalance(<account>)`. It is possible that you are connecting to an older chain that has not been upgraded yet. For these chains, this storage entry won't be available (yet). To query the nonce on older chains, you can do a query to `api.query.system.accountNonce(<account>)` and balances can be retrieved via `api.query.balances.freeBalance(<account>)`.
Likewise, if your chain has been upgraded recently and you are still using the old `system.accountNonce` or `balances.freeBalance` queries in your code (which is now not available in the chain metadata), you need to update it to query the new location. Likewise, if your chain has been upgraded recently and you are still using the old `system.accountNonce` or `balances.freeBalance` queries in your code (which is now not available in the chain metadata), you need to update it to query the new location.
## I cannot send transactions from my node-template-based chain
The API always injects the default type definitions as specified by the Substrate master fully-featured node. This means that any customizations to chains needs needs to be applied as types, should there be differences in specific user-implementations.
The Substrate node-template has added customizations for some types in the default template, specifically around the `Address` and `Lookup` types, removing any lookups based on indices. This means that the transaction payload saves 2 bytes for a transfer and is an approach followed by other chains as well, notably Polkadot & Kusama.
Due to these customizations and differences that bleed through to the transaction formats, out-of-the-box chains based on the node-template will have issues when sending transactions. To fix this, you would need to add [the customized Address types into your API](types.extend.md#impact-on-extrinsics) instances (or UIs), allowing the API to have the information required to adjust the encoding.
+12 -2
View File
@@ -62,7 +62,7 @@ When working maps and double-maps, it is possible to retrieve a list of all the
// Retrieve the active era // Retrieve the active era
const activeEra = await api.query.staking.activeEra(); const activeEra = await api.query.staking.activeEra();
// retrieve all exposures int the active era // retrieve all exposures for the active era
const exposures = await api.query.staking.erasStakers.entries(activeEra.index); const exposures = await api.query.staking.erasStakers.entries(activeEra.index);
exposures.forEach(([key, exposure]) => { exposures.forEach(([key, exposure]) => {
@@ -73,7 +73,17 @@ exposures.forEach(([key, exposure]) => {
Here we are querying a double-map, so we supply 1 argument. No arguments on double-maps will be very costly, retrieving all the eras and associated entries. Additionally when `twox64_concat` & `blake2_concat` is used, the key `.args` will contain decoded values of the params, in this case it will contain the actual `AccountId` of the staker. (Since that was not supplied) Here we are querying a double-map, so we supply 1 argument. No arguments on double-maps will be very costly, retrieving all the eras and associated entries. Additionally when `twox64_concat` & `blake2_concat` is used, the key `.args` will contain decoded values of the params, in this case it will contain the actual `AccountId` of the staker. (Since that was not supplied)
In the same way as above we can simply do `.keys(activeEra.index): StorageKey[]` to retrieve all the keys here, including the individual keys args decoding, as available on maps with decodable hashing functions. In the same way as above we can simply do `.keys(activeEra.index): StorageKey[]` to retrieve all the keys here, including the individual keys args (available on maps with decodable hashing functions) -
```js
// retrieve all the nominator keys
const keys = await api.query.staking.nominators.keys();
// extract the first key argument (AccountId) as string
const nominatorIds = keys.map((key) => key.args[0].toString());
console.log('all nominators:', nminatorIds.join(', '));
```
## State entries ## State entries
+2 -1
View File
@@ -57,7 +57,7 @@ Be aware that in the JS version naming defaults to `camelCase` where names of fi
Each enum has additional getters which are injected based on the fields wrapped. These take the form of `.is<Name>` and `.as<Name>` to allow you to check is the enum is a certain value or to retrieve the underlying value as a specific type. Each enum has additional getters which are injected based on the fields wrapped. These take the form of `.is<Name>` and `.as<Name>` to allow you to check is the enum is a certain value or to retrieve the underlying value as a specific type.
As a real-world example, when an extrinsic is applied, the `Phase` enum has one of two states, `ApplyExtrinsic(u32)` or `Finalization`. In this case `.isApplyExtrinsic` would be `true` when an extrinsic is being applied, and `.asApplyExtrinsic` would return the value as a `u32` (which is the index of the extrinsic in the block, as it is being applied). When `isisApplyExtrinsic` is `false` and `asApplyExtrinsic` is called, the getter will throw. As a real-world example, when an extrinsic is applied, the `Phase` enum has one of two states, `ApplyExtrinsic(u32)` or `Finalization`. In this case `.isApplyExtrinsic` would be `true` when an extrinsic is being applied, and `.asApplyExtrinsic` would return the value as a `u32` (which is the index of the extrinsic in the block, as it is being applied). When `isApplyExtrinsic` is `false` and `asApplyExtrinsic` is called, the getter will throw.
## Working with Option&lt;Type&gt; ## Working with Option&lt;Type&gt;
@@ -67,6 +67,7 @@ An `Option<Type>` attempts to mimic the Rust approach of having `None` and `Some
- `.isSome` - this is `true` is a value is wrapped, i.e. if a `Option<u32>` has an actual underlying `u32` - `.isSome` - this is `true` is a value is wrapped, i.e. if a `Option<u32>` has an actual underlying `u32`
- `.unwrap()` - when `isSome`, this will return the wrapped value, i.e. for `Option<u32>`, this would return the `u32`. When the value is `isNone`, this call will throw an exception. - `.unwrap()` - when `isSome`, this will return the wrapped value, i.e. for `Option<u32>`, this would return the `u32`. When the value is `isNone`, this call will throw an exception.
- `.unwrapOr(<default value>)` - this extends `unwrap()`, returning the wrapped value when `isSome` and in the case of `isNone` it will return the `<default value>` passed. - `.unwrapOr(<default value>)` - this extends `unwrap()`, returning the wrapped value when `isSome` and in the case of `isNone` it will return the `<default value>` passed.
- `.unwrapOrDefault()` - returns either the rapped value when `isSome`, or the default for the type when `isNone`
## Working with Tuples ## Working with Tuples
+9 -3
View File
@@ -1,14 +1,19 @@
/* eslint-disable @typescript-eslint/camelcase */ // Copyright 2017-2020 @polkadot/api authors & contributors
/* eslint-disable @typescript-eslint/no-var-requires */ // This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
const config = require('@polkadot/dev/config/jest'); const config = require('@polkadot/dev/config/jest');
module.exports = Object.assign({}, config, { module.exports = Object.assign({}, config, {
moduleNameMapper: { moduleNameMapper: {
'@polkadot/api-contract(.*)$': '<rootDir>/packages/api-contract/src/$1', '@polkadot/api-contract(.*)$': '<rootDir>/packages/api-contract/src/$1',
'@polkadot/api-derive(.*)$': '<rootDir>/packages/api-derive/src/$1', '@polkadot/api-derive(.*)$': '<rootDir>/packages/api-derive/src/$1',
// eslint-disable-next-line sort-keys
'@polkadot/api(.*)$': '<rootDir>/packages/api/src/$1', '@polkadot/api(.*)$': '<rootDir>/packages/api/src/$1',
'@polkadot/metadata(.*)$': '<rootDir>/packages/metadata/src/$1', '@polkadot/metadata(.*)$': '<rootDir>/packages/metadata/src/$1',
'@polkadot/rpc-(core|provider)(.*)$': '<rootDir>/packages/rpc-$1/src/$2', '@polkadot/rpc-(core|provider)(.*)$': '<rootDir>/packages/rpc-$1/src/$2',
'@polkadot/types-known(.*)$': '<rootDir>/packages/types-known/src/$1',
// eslint-disable-next-line sort-keys
'@polkadot/types(.*)$': '<rootDir>/packages/types/src/$1' '@polkadot/types(.*)$': '<rootDir>/packages/types/src/$1'
}, },
modulePathIgnorePatterns: [ modulePathIgnorePatterns: [
@@ -18,7 +23,8 @@ module.exports = Object.assign({}, config, {
'<rootDir>/packages/metadata/build', '<rootDir>/packages/metadata/build',
'<rootDir>/packages/rpc-core/build', '<rootDir>/packages/rpc-core/build',
'<rootDir>/packages/rpc-provider/build', '<rootDir>/packages/rpc-provider/build',
'<rootDir>/packages/types/build' '<rootDir>/packages/types/build',
'<rootDir>/packages/types-known/build'
], ],
resolver: './jest.resolver.js' resolver: './jest.resolver.js'
}); });
+1 -2
View File
@@ -1,8 +1,7 @@
// Copyright 2017-2020 @polkadot/util authors & contributors // Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms // This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details. // of the Apache-2.0 license. See the LICENSE file for details.
// eslint-disable-next-line @typescript-eslint/no-var-requires
const path = require('path'); const path = require('path');
module.exports = function resolver (file, config) { module.exports = function resolver (file, config) {
+1 -1
View File
@@ -9,5 +9,5 @@
"packages": [ "packages": [
"packages/*" "packages/*"
], ],
"version": "1.8.1" "version": "1.10.1"
} }
+3 -3
View File
@@ -27,10 +27,10 @@
"@babel/core": "^7.9.0", "@babel/core": "^7.9.0",
"@babel/register": "^7.9.0", "@babel/register": "^7.9.0",
"@babel/runtime": "^7.9.2", "@babel/runtime": "^7.9.2",
"@polkadot/dev": "^0.51.7", "@polkadot/dev": "^0.52.9",
"@polkadot/ts": "^0.3.14", "@polkadot/ts": "^0.3.18",
"@polkadot/typegen": "workspace:packages/typegen", "@polkadot/typegen": "workspace:packages/typegen",
"@types/jest": "^25.1.4", "@types/jest": "^25.2.1",
"copyfiles": "^2.2.0" "copyfiles": "^2.2.0"
} }
} }
+6 -6
View File
@@ -1,6 +1,6 @@
{ {
"name": "@polkadot/api-contract", "name": "@polkadot/api-contract",
"version": "1.8.1", "version": "1.10.1",
"description": "Interfaces for interacting with contracts and contract ABIs", "description": "Interfaces for interacting with contracts and contract ABIs",
"main": "index.js", "main": "index.js",
"keywords": [ "keywords": [
@@ -27,11 +27,11 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-contract#readme", "homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-contract#readme",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.9.2", "@babel/runtime": "^7.9.2",
"@polkadot/api": "1.8.1", "@polkadot/api": "1.10.1",
"@polkadot/rpc-core": "1.8.1", "@polkadot/rpc-core": "1.10.1",
"@polkadot/types": "1.8.1", "@polkadot/types": "1.10.1",
"@polkadot/util": "^2.6.2", "@polkadot/util": "^2.8.1",
"bn.js": "^5.1.1", "bn.js": "^5.1.1",
"rxjs": "^6.5.4" "rxjs": "^6.5.5"
} }
} }
+2 -2
View File
@@ -18,10 +18,10 @@ export default class ContractAbi extends ContractRegistry implements InterfaceAb
constructor (registry: Registry, abi: ContractABIPre) { constructor (registry: Registry, abi: ContractABIPre) {
super(registry, abi); super(registry, abi);
[this.abi, this.constructors, this.messages] = this.decodeAbi(abi); [this.abi, this.constructors, this.messages] = this._decodeAbi(abi);
} }
private decodeAbi (abiPre: ContractABIPre): [ContractABI, ContractABIFn[], AbiMessages] { private _decodeAbi (abiPre: ContractABIPre): [ContractABI, ContractABIFn[], AbiMessages] {
this.validateAbi(abiPre); this.validateAbi(abiPre);
const abi = this.convertAbi(abiPre); const abi = this.convertAbi(abiPre);
+20 -15
View File
@@ -61,7 +61,7 @@ export default class ContractRegistry extends MetaRegistry {
const unknownKeys = Object.keys(arg).filter((key): boolean => !['name', 'type'].includes(key)); const unknownKeys = Object.keys(arg).filter((key): boolean => !['name', 'type'].includes(key));
assert(unknownKeys.length === 0, `Unknown keys ${unknownKeys.join(', ')} found in ABI args for ${name}`); assert(unknownKeys.length === 0, `Unknown keys ${unknownKeys.join(', ')} found in ABI args for ${name}`);
assert(isNumber(arg.name) && isString(this.stringAt(arg.name)), `${name} args should have valid name `); assert(isNumber(arg.name) && isString(this._stringAt(arg.name)), `${name} args should have valid name `);
assert(isNumber(arg.type.ty) && isObject(this.typeDefAt(arg.type.ty)), `${name} args should have valid type`); assert(isNumber(arg.type.ty) && isObject(this.typeDefAt(arg.type.ty)), `${name} args should have valid type`);
}); });
} }
@@ -83,9 +83,9 @@ export default class ContractRegistry extends MetaRegistry {
assert(unknownKeys.length === 0, `Unknown keys ${unknownKeys.join(', ')} found in ABI args for messages.${message.name}`); assert(unknownKeys.length === 0, `Unknown keys ${unknownKeys.join(', ')} found in ABI args for messages.${message.name}`);
const { name, selector, return_type: returnType } = message; const { name, return_type: returnType, selector } = message;
assert(isNumber(name) && isString(this.stringAt(name)), `Expected name for ${fnname}`); assert(isNumber(name) && isString(this._stringAt(name)), `Expected name for ${fnname}`);
assert(isNull(returnType) || (isNumber(returnType.ty) && isObject(this.typeDefAt(returnType.ty))), `Expected return_type for ${fnname}`); assert(isNull(returnType) || (isNumber(returnType.ty) && isObject(this.typeDefAt(returnType.ty))), `Expected return_type for ${fnname}`);
parseSelector(this.registry, fnname, selector); parseSelector(this.registry, fnname, selector);
@@ -100,7 +100,7 @@ export default class ContractRegistry extends MetaRegistry {
const { contract: { constructors, messages, name } } = abi; const { contract: { constructors, messages, name } } = abi;
assert(constructors && messages && isString(this.stringAt(name)), 'ABI should have constructors, messages & name sections'); assert(constructors && messages && isString(this._stringAt(name)), 'ABI should have constructors, messages & name sections');
this.validateConstructors(abi); this.validateConstructors(abi);
this.validateMessages(abi); this.validateMessages(abi);
@@ -109,13 +109,16 @@ export default class ContractRegistry extends MetaRegistry {
public createMessage (name: string, message: Partial<ContractABIMessage> & ContractABIMessageBase): ContractABIFn { public createMessage (name: string, message: Partial<ContractABIMessage> & ContractABIMessageBase): ContractABIFn {
const args = message.args.map(({ name, type }): ContractABIFnArg => { const args = message.args.map(({ name, type }): ContractABIFnArg => {
assert(isObject(type), `Invalid type at index ${type}`); assert(isObject(type), `Invalid type at index ${type}`);
return { return {
name: stringCamelCase(name), name: stringCamelCase(name),
type type
}; };
}); });
const Clazz = createArgClass(this.registry, args, isUndefined(message.selector) ? {} : { __selector: 'u32' }); const Clazz = createArgClass(this.registry, args, isUndefined(message.selector) ? {} : { __selector: 'u32' });
const baseStruct: { [index: string]: any } = { __selector: isUndefined(message.selector) ? undefined : parseSelector(this.registry, name, message.selector) }; const baseStruct: { [index: string]: any } = { __selector: isUndefined(message.selector) ? undefined : parseSelector(this.registry, name, message.selector) };
const encoder = (...params: CodecArg[]): Uint8Array => { const encoder = (...params: CodecArg[]): Uint8Array => {
assert(params.length === args.length, `Expected ${args.length} arguments to contract ${name}, found ${params.length}`); assert(params.length === args.length, `Expected ${args.length} arguments to contract ${name}, found ${params.length}`);
@@ -136,6 +139,7 @@ export default class ContractRegistry extends MetaRegistry {
fn.args = args; fn.args = args;
fn.isConstant = !(message.mutates || false); fn.isConstant = !(message.mutates || false);
fn.type = message.returnType || null; fn.type = message.returnType || null;
return fn; return fn;
} }
@@ -147,19 +151,20 @@ export default class ContractRegistry extends MetaRegistry {
} }
public convertArgs (args: ContractABIArgBasePre[]): any[] { public convertArgs (args: ContractABIArgBasePre[]): any[] {
return args.map(({ name, type, ...arg }) => ({ ...arg, name: this.stringAt(name), type: this.convertType(type) })); return args.map(({ name, type, ...arg }) => ({ ...arg, name: this._stringAt(name), type: this.convertType(type) }));
} }
public convertType ({ ty, display_name: displayNameIndices }: ContractABITypePre): TypeDef { public convertType ({ display_name: displayNameIndices, ty }: ContractABITypePre): TypeDef {
const displayName = this.stringsAt(displayNameIndices).join('::'); const displayName = this.stringsAt(displayNameIndices).join('::');
return this.typeDefAt(ty, { displayName }); return this.typeDefAt(ty, { displayName });
} }
public convertContract ({ constructors, messages, name, events, ...contract }: ContractABIContractPre): ContractABIContract { public convertContract ({ constructors, events, messages, name, ...contract }: ContractABIContractPre): ContractABIContract {
return { return {
constructors: this.convertConstructors(constructors), constructors: this.convertConstructors(constructors),
messages: messages.map((message) => this.convertMessage(message)), messages: messages.map((message) => this.convertMessage(message)),
name: this.stringAt(name), name: this._stringAt(name),
...(events ...(events
? { events: events.map((event) => this.convertEvent(event)) } ? { events: events.map((event) => this.convertEvent(event)) }
: {}), : {}),
@@ -179,7 +184,7 @@ export default class ContractRegistry extends MetaRegistry {
return { return {
...message, ...message,
args: this.convertArgs(args), args: this.convertArgs(args),
name: this.stringAt(name), name: this._stringAt(name),
returnType: returnType ? this.convertType(returnType) : null returnType: returnType ? this.convertType(returnType) : null
}; };
} }
@@ -202,13 +207,13 @@ export default class ContractRegistry extends MetaRegistry {
} }
} }
public convertStorageStruct ({ 'struct.type': structType, 'struct.fields': structFields }: ContractABIStorageStructPre): ContractABIStorageStruct { public convertStorageStruct ({ 'struct.fields': structFields, 'struct.type': structType }: ContractABIStorageStructPre): ContractABIStorageStruct {
return { return {
'struct.type': this.typeDefAt(structType), 'struct.fields': structFields.map(({ layout, name }) => ({
'struct.fields': structFields.map(({ name, layout }) => ({ layout: this.convertStorageLayout(layout),
name: this.stringAt(name), name: this._stringAt(name)
layout: this.convertStorageLayout(layout) })),
})) 'struct.type': this.typeDefAt(structType)
}; };
} }
+50 -46
View File
@@ -48,7 +48,7 @@ class MetadataRegistryLookup {
this._types = types; this._types = types;
} }
protected hasItemAt (index: number, variant: MetaRegistryItem): boolean { protected _hasItemAt (index: number, variant: MetaRegistryItem): boolean {
switch (variant) { switch (variant) {
case MetaRegistryItem.String: case MetaRegistryItem.String:
return this._strings && !!this._strings[index - 1]; return this._strings && !!this._strings[index - 1];
@@ -59,8 +59,8 @@ class MetadataRegistryLookup {
} }
} }
protected itemAt (index: number, variant: MetaRegistryItem): any { protected _itemAt (index: number, variant: MetaRegistryItem): any {
assert(this.hasItemAt(index, variant), `MetaRegistry: Invalid ${variant} index ${index} found in metadata`); assert(this._hasItemAt(index, variant), `MetaRegistry: Invalid ${variant} index ${index} found in metadata`);
switch (variant) { switch (variant) {
case MetaRegistryItem.String: case MetaRegistryItem.String:
@@ -72,33 +72,33 @@ class MetadataRegistryLookup {
} }
} }
protected itemsAt (indices: number[], variant: MetaRegistryItem): any[] { protected _itemsAt (indices: number[], variant: MetaRegistryItem): any[] {
return indices.map((index: number): string => this.itemAt(index, variant)); return indices.map((index: number): string => this._itemAt(index, variant));
} }
protected stringAt (index: StringIndex): string { protected _stringAt (index: StringIndex): string {
return this.itemAt(index, MetaRegistryItem.String); return this._itemAt(index, MetaRegistryItem.String);
} }
public stringsAt (indices: StringIndex[]): string[] { public stringsAt (indices: StringIndex[]): string[] {
return this.itemsAt(indices, MetaRegistryItem.String); return this._itemsAt(indices, MetaRegistryItem.String);
} }
public typeAt (index: TypeIndex): MetaType { public typeAt (index: TypeIndex): MetaType {
return this.itemAt(index, MetaRegistryItem.Type); return this._itemAt(index, MetaRegistryItem.Type);
} }
public typesAt (indices: TypeIndex[]): MetaType[] { public typesAt (indices: TypeIndex[]): MetaType[] {
return this.itemsAt(indices, MetaRegistryItem.Type); return this._itemsAt(indices, MetaRegistryItem.Type);
} }
public hasTypeDefAt (index: TypeIndex): boolean { public hasTypeDefAt (index: TypeIndex): boolean {
return this.hasItemAt(index, MetaRegistryItem.TypeDef); return this._hasItemAt(index, MetaRegistryItem.TypeDef);
} }
public typeDefAt (index: TypeIndex, extra: Pick<TypeDef, never> = {}): TypeDef { public typeDefAt (index: TypeIndex, extra: Pick<TypeDef, never> = {}): TypeDef {
return { return {
...this.itemAt(index, MetaRegistryItem.TypeDef), ...this._itemAt(index, MetaRegistryItem.TypeDef),
...extra ...extra
}; };
} }
@@ -116,7 +116,7 @@ export default class MetaRegistry extends MetadataRegistryLookup {
this.typeDefs[typeIndex - 1] = this.typeDefFromMetaType(this.typeAt(typeIndex), typeIndex); this.typeDefs[typeIndex - 1] = this.typeDefFromMetaType(this.typeAt(typeIndex), typeIndex);
} }
private typeDefIdFields ({ id }: MetaType): Pick<TypeDef, never> { private _typeDefIdFields ({ id }: MetaType): Pick<TypeDef, never> {
const { 'custom.name': nameIndex, 'custom.namespace': namespaceIndices, 'custom.params': paramsIndices } = id as MetaTypeIdCustom; const { 'custom.name': nameIndex, 'custom.namespace': namespaceIndices, 'custom.params': paramsIndices } = id as MetaTypeIdCustom;
if (!nameIndex) { if (!nameIndex) {
@@ -124,7 +124,7 @@ export default class MetaRegistry extends MetadataRegistryLookup {
} }
return { return {
name: this.stringAt(nameIndex), name: this._stringAt(nameIndex),
...(namespaceIndices && namespaceIndices.length ...(namespaceIndices && namespaceIndices.length
? { namespace: this.stringsAt(namespaceIndices).join('::') } ? { namespace: this.stringsAt(namespaceIndices).join('::') }
: {} : {}
@@ -136,33 +136,33 @@ export default class MetaRegistry extends MetadataRegistryLookup {
}; };
} }
private typeDefDefFields (metaType: MetaType, typeIndex?: TypeIndex): Pick<TypeDef, never> { private _typeDefDefFields (metaType: MetaType, typeIndex?: TypeIndex): Pick<TypeDef, never> {
let typeDef; let typeDef;
switch (detectedType(metaType)) { switch (detectedType(metaType)) {
case MetaTypeInfo.BuiltinPlain: case MetaTypeInfo.BuiltinPlain:
typeDef = this.typeDefForBuiltinPlain(metaType.id as string); typeDef = this._typeDefForBuiltinPlain(metaType.id as string);
break; break;
case MetaTypeInfo.BuiltinTuple: case MetaTypeInfo.BuiltinTuple:
typeDef = this.typeDefForBuiltinTuple(metaType.id as TypeIndex[]); typeDef = this._typeDefForBuiltinTuple(metaType.id as TypeIndex[]);
break; break;
case MetaTypeInfo.BuiltinVec: case MetaTypeInfo.BuiltinVec:
typeDef = this.typeDefForBuiltinVec(metaType.id as MetaTypeIdVec, typeIndex); typeDef = this._typeDefForBuiltinVec(metaType.id as MetaTypeIdVec, typeIndex);
break; break;
case MetaTypeInfo.BuiltinVecFixed: case MetaTypeInfo.BuiltinVecFixed:
typeDef = this.typeDefForBuiltinVecFixed(metaType.id as MetaTypeIdVecFixed, typeIndex); typeDef = this._typeDefForBuiltinVecFixed(metaType.id as MetaTypeIdVecFixed, typeIndex);
break; break;
case MetaTypeInfo.Enum: case MetaTypeInfo.Enum:
typeDef = this.typeDefForEnum(metaType.def as MetaTypeDefEnum, metaType.id as MetaTypeIdCustom, typeIndex); typeDef = this._typeDefForEnum(metaType.def as MetaTypeDefEnum, metaType.id as MetaTypeIdCustom, typeIndex);
break; break;
case MetaTypeInfo.ClikeEnum: case MetaTypeInfo.ClikeEnum:
typeDef = this.typeDefForClikeEnum(metaType.def as MetaTypeDefClikeEnum); typeDef = this._typeDefForClikeEnum(metaType.def as MetaTypeDefClikeEnum);
break; break;
case MetaTypeInfo.Struct: case MetaTypeInfo.Struct:
typeDef = this.typeDefForStruct(metaType.def as MetaTypeDefStruct); typeDef = this.typeDefForStruct(metaType.def as MetaTypeDefStruct);
break; break;
case MetaTypeInfo.TupleStruct: case MetaTypeInfo.TupleStruct:
typeDef = this.typeDefForTupleStruct(metaType.def as MetaTypeDefTupleStruct); typeDef = this._typeDefForTupleStruct(metaType.def as MetaTypeDefTupleStruct);
break; break;
case MetaTypeInfo.Null: case MetaTypeInfo.Null:
default: default:
@@ -176,8 +176,8 @@ export default class MetaRegistry extends MetadataRegistryLookup {
return withTypeString({ return withTypeString({
info: TypeDefInfo.Null, info: TypeDefInfo.Null,
type: '', type: '',
...this.typeDefDefFields(metaType, typeIndex), ...this._typeDefDefFields(metaType, typeIndex),
...this.typeDefIdFields(metaType) ...this._typeDefIdFields(metaType)
}) as TypeDef; }) as TypeDef;
} }
@@ -189,13 +189,13 @@ export default class MetaRegistry extends MetadataRegistryLookup {
return this.typeDefAt(typeIndex); return this.typeDefAt(typeIndex);
} }
private typeDefForEnumVariant (variant: MetaTypeDefEnumVariant): Pick<TypeDef, any> { private _typeDefForEnumVariant (variant: MetaTypeDefEnumVariant): Pick<TypeDef, any> {
const { 'unit_variant.name': unitNameIndex } = variant as MetaTypeDefEnumVariantUnit; const { 'unit_variant.name': unitNameIndex } = variant as MetaTypeDefEnumVariantUnit;
if (unitNameIndex) { if (unitNameIndex) {
return { return {
info: TypeDefInfo.Plain, info: TypeDefInfo.Plain,
name: this.stringAt(unitNameIndex), name: this._stringAt(unitNameIndex),
type: 'Null' type: 'Null'
}; };
} }
@@ -203,7 +203,7 @@ export default class MetaRegistry extends MetadataRegistryLookup {
const { 'tuple_struct_variant.name': tupleStructVariantNameIndex } = variant as MetaTypeDefEnumVariantTupleStruct; const { 'tuple_struct_variant.name': tupleStructVariantNameIndex } = variant as MetaTypeDefEnumVariantTupleStruct;
if (tupleStructVariantNameIndex) { if (tupleStructVariantNameIndex) {
return this.typeDefForTupleStruct(variant as MetaTypeDefEnumVariantTupleStruct); return this._typeDefForTupleStruct(variant as MetaTypeDefEnumVariantTupleStruct);
} }
const { 'struct_variant.name': structVariantNameIndex } = variant as MetaTypeDefEnumVariantStruct; const { 'struct_variant.name': structVariantNameIndex } = variant as MetaTypeDefEnumVariantStruct;
@@ -218,14 +218,14 @@ export default class MetaRegistry extends MetadataRegistryLookup {
}; };
} }
private typeDefForBuiltinPlain (id: string): Pick<TypeDef, never> { private _typeDefForBuiltinPlain (id: string): Pick<TypeDef, never> {
return { return {
info: TypeDefInfo.Plain, info: TypeDefInfo.Plain,
type: id type: id
}; };
} }
private typeDefForBuiltinTuple (id: TypeIndex[]): Pick<TypeDef, never> { private _typeDefForBuiltinTuple (id: TypeIndex[]): Pick<TypeDef, never> {
const sub = id.map((tupleTypeIndex: number): TypeDef => this.typeDefFromMetaTypeAt(tupleTypeIndex)); const sub = id.map((tupleTypeIndex: number): TypeDef => this.typeDefFromMetaTypeAt(tupleTypeIndex));
return { return {
@@ -234,48 +234,52 @@ export default class MetaRegistry extends MetadataRegistryLookup {
}; };
} }
private typeDefForBuiltinVec (id: MetaTypeIdVec, typeIndex?: TypeIndex): Pick<TypeDef, never> { private _typeDefForBuiltinVec (id: MetaTypeIdVec, typeIndex?: TypeIndex): Pick<TypeDef, never> {
const { 'slice.type': vecTypeIndex } = id; const { 'slice.type': vecTypeIndex } = id;
assert(!typeIndex || vecTypeIndex !== typeIndex, `MetaRegistry: self-referencing registry type at index ${typeIndex}`); assert(!typeIndex || vecTypeIndex !== typeIndex, `MetaRegistry: self-referencing registry type at index ${typeIndex}`);
const type = displayType(this.typeDefFromMetaTypeAt(vecTypeIndex)); const type = displayType(this.typeDefFromMetaTypeAt(vecTypeIndex));
assert(type && type.length > 0, `MetaRegistry: Invalid builtin Vec type found at index ${typeIndex}`); assert(type && type.length > 0, `MetaRegistry: Invalid builtin Vec type found at index ${typeIndex}`);
return { return {
info: TypeDefInfo.Vec, info: TypeDefInfo.Vec,
type: `Vec<${type}>`, sub: this.typeDefFromMetaTypeAt(vecTypeIndex),
sub: this.typeDefFromMetaTypeAt(vecTypeIndex) type: `Vec<${type}>`
}; };
} }
private typeDefForBuiltinVecFixed (id: MetaTypeIdVecFixed, typeIndex?: TypeIndex): Pick<TypeDef, never> { private _typeDefForBuiltinVecFixed (id: MetaTypeIdVecFixed, typeIndex?: TypeIndex): Pick<TypeDef, never> {
const { 'array.type': vecTypeIndex, 'array.len': vecLength } = id; const { 'array.len': vecLength, 'array.type': vecTypeIndex } = id;
assert(!vecLength || vecLength <= 256, 'MetaRegistry: Only support for [Type; <length>], where length <= 256'); assert(!vecLength || vecLength <= 256, 'MetaRegistry: Only support for [Type; <length>], where length <= 256');
assert(!typeIndex || vecTypeIndex !== typeIndex, `MetaRegistry: self-referencing registry type at index ${typeIndex}`); assert(!typeIndex || vecTypeIndex !== typeIndex, `MetaRegistry: self-referencing registry type at index ${typeIndex}`);
const type = displayType(this.typeDefFromMetaTypeAt(vecTypeIndex)); const type = displayType(this.typeDefFromMetaTypeAt(vecTypeIndex));
assert(type && type.length > 0, `MetaRegistry: Invalid vector type found at index ${typeIndex}`); assert(type && type.length > 0, `MetaRegistry: Invalid vector type found at index ${typeIndex}`);
return { return {
info: TypeDefInfo.VecFixed, info: TypeDefInfo.VecFixed,
length: vecLength, // ex: { type: type } length: vecLength, // ex: { type: type }
type: `[${type};${vecLength}]`, sub: this.typeDefFromMetaTypeAt(vecTypeIndex),
sub: this.typeDefFromMetaTypeAt(vecTypeIndex) type: `[${type};${vecLength}]`
}; };
} }
private typeDefForEnum (def: MetaTypeDefEnum, id: MetaTypeIdCustom, typeIndex?: TypeIndex): Pick<TypeDef, any> { private _typeDefForEnum (def: MetaTypeDefEnum, id: MetaTypeIdCustom, typeIndex?: TypeIndex): Pick<TypeDef, any> {
const name = id && this.stringAt(id['custom.name']); const name = id && this._stringAt(id['custom.name']);
switch (name) { switch (name) {
case 'Option': case 'Option':
return this.typeDefForOption(id, typeIndex); return this.typeDefForOption(id, typeIndex);
case 'Result': case 'Result':
return this.typeDefForResult(id, typeIndex); return this.typeDefForResult(id, typeIndex);
default: { default: {
const sub = def['enum.variants'].map((variant) => this.typeDefForEnumVariant(variant)); const sub = def['enum.variants'].map((variant) => this._typeDefForEnumVariant(variant));
return { return {
info: TypeDefInfo.Enum, info: TypeDefInfo.Enum,
@@ -285,13 +289,13 @@ export default class MetaRegistry extends MetadataRegistryLookup {
} }
} }
private typeDefForClikeEnum (def: MetaTypeDefClikeEnum): Pick<TypeDef, never> { private _typeDefForClikeEnum (def: MetaTypeDefClikeEnum): Pick<TypeDef, never> {
return { return {
info: TypeDefInfo.Enum, info: TypeDefInfo.Enum,
sub: def['clike_enum.variants'].map(({ name: nameIndex, discriminant }): TypeDef => ({ sub: def['clike_enum.variants'].map(({ discriminant, name: nameIndex }): TypeDef => ({
ext: { discriminant }, ext: { discriminant },
info: TypeDefInfo.Plain, info: TypeDefInfo.Plain,
name: this.stringAt(nameIndex), name: this._stringAt(nameIndex),
type: 'Null' type: 'Null'
})) }))
}; };
@@ -322,24 +326,24 @@ export default class MetaRegistry extends MetadataRegistryLookup {
return withTypeString({ return withTypeString({
info: TypeDefInfo.Struct, info: TypeDefInfo.Struct,
...(structNameIndex ...(structNameIndex
? { name: this.stringAt(structNameIndex) } ? { name: this._stringAt(structNameIndex) }
: {} : {}
), ),
sub: structFields.map((field: MetaTypeDefStructField): TypeDef => ({ sub: structFields.map((field: MetaTypeDefStructField): TypeDef => ({
...this.typeDefFromMetaTypeAt(field.type), ...this.typeDefFromMetaTypeAt(field.type),
name: this.stringAt(field.name) name: this._stringAt(field.name)
})) }))
}); });
} }
private typeDefForTupleStruct (def: MetaTypeDefTupleStruct | MetaTypeDefEnumVariantTupleStruct): Pick<TypeDef, any> { private _typeDefForTupleStruct (def: MetaTypeDefTupleStruct | MetaTypeDefEnumVariantTupleStruct): Pick<TypeDef, any> {
const tupleStructTypes = (def as MetaTypeDefTupleStruct)['tuple_struct.types'] || (def as MetaTypeDefEnumVariantTupleStruct)['tuple_struct_variant.types']; const tupleStructTypes = (def as MetaTypeDefTupleStruct)['tuple_struct.types'] || (def as MetaTypeDefEnumVariantTupleStruct)['tuple_struct_variant.types'];
const tupleStructNameIndex = (def as MetaTypeDefEnumVariantTupleStruct)['tuple_struct_variant.name']; const tupleStructNameIndex = (def as MetaTypeDefEnumVariantTupleStruct)['tuple_struct_variant.name'];
return withTypeString({ return withTypeString({
info: TypeDefInfo.Tuple, info: TypeDefInfo.Tuple,
...(tupleStructNameIndex ...(tupleStructNameIndex
? { name: this.stringAt(tupleStructNameIndex) } ? { name: this._stringAt(tupleStructNameIndex) }
: {} : {}
), ),
sub: tupleStructTypes.map((fieldIndex: number, index: number): TypeDef => ({ sub: tupleStructTypes.map((fieldIndex: number, index: number): TypeDef => ({
+3 -3
View File
@@ -49,16 +49,16 @@ export default class Blueprint<ApiType extends ApiTypes> extends BaseWithTx<ApiT
return { return {
signAndSend: this.decorateMethod( signAndSend: this.decorateMethod(
(account: IKeyringPair | string | AccountId | Address): BlueprintCreateResultSubscription<ApiType> => { (account: IKeyringPair | string | AccountId | Address): BlueprintCreateResultSubscription<ApiType> => {
return this.apiContracts return this._apiContracts
.create(endowment, maxGas, this.codeHash, this.abi.constructors[constructorIndex](...params)) .create(endowment, maxGas, this.codeHash, this.abi.constructors[constructorIndex](...params))
.signAndSend(account) .signAndSend(account)
.pipe(map(this.createResult)); .pipe(map(this._createResult));
} }
) )
}; };
} }
private createResult = (result: SubmittableResult): BlueprintCreateResult<ApiType> => { private _createResult = (result: SubmittableResult): BlueprintCreateResult<ApiType> => {
let contract: Contract<ApiType> | undefined; let contract: Contract<ApiType> | undefined;
if (result.isInBlock) { if (result.isInBlock) {
+3 -3
View File
@@ -48,15 +48,15 @@ export default class Code<ApiType extends ApiTypes> extends BaseWithTx<ApiType>
return { return {
signAndSend: this.decorateMethod( signAndSend: this.decorateMethod(
(account: IKeyringPair | string | AccountId | Address): CodePutCodeResultSubscription<ApiType> => (account: IKeyringPair | string | AccountId | Address): CodePutCodeResultSubscription<ApiType> =>
this.apiContracts this._apiContracts
.putCode(maxGas, compactAddLength(this.code)) .putCode(maxGas, compactAddLength(this.code))
.signAndSend(account) .signAndSend(account)
.pipe(map(this.createResult)) .pipe(map(this._createResult))
) )
}; };
} }
private createResult = (result: ISubmittableResult): CodePutCodeResult<ApiType> => { private _createResult = (result: ISubmittableResult): CodePutCodeResult<ApiType> => {
let blueprint: Blueprint<ApiType> | undefined; let blueprint: Blueprint<ApiType> | undefined;
if (result.isInBlock) { if (result.isInBlock) {
+17 -17
View File
@@ -33,35 +33,41 @@ export type ContractCallResult<CallType extends ContractCallTypes> = CallType ex
export default class Contract<ApiType extends ApiTypes> extends BaseWithTxAndRpcCall<ApiType> { export default class Contract<ApiType extends ApiTypes> extends BaseWithTxAndRpcCall<ApiType> {
public readonly address: Address; public readonly address: Address;
constructor (api: ApiObject<ApiType>, abi: ContractABIPre | Abi, decorateMethod: DecorateMethod<ApiType>, address: string | AccountId | Address) {
super(api, abi, decorateMethod);
this.address = this.registry.createType('Address', address);
}
public call (as: 'rpc', message: string, value: BN | number, gasLimit: BN | number, ...params: any[]): ContractCall<ApiType, 'rpc'>; public call (as: 'rpc', message: string, value: BN | number, gasLimit: BN | number, ...params: any[]): ContractCall<ApiType, 'rpc'>;
public call (as: 'tx', message: string, value: BN | number, gasLimit: BN | number, ...params: any[]): ContractCall<ApiType, 'tx'>; public call (as: 'tx', message: string, value: BN | number, gasLimit: BN | number, ...params: any[]): ContractCall<ApiType, 'tx'>;
public call<CallType extends ContractCallTypes> (as: CallType, message: string, value: BN | number, gasLimit: BN | number, ...params: any[]): ContractCall<ApiType, CallType> { public call<CallType extends ContractCallTypes> (as: CallType, message: string, value: BN | number, gasLimit: BN | number, ...params: any[]): ContractCall<ApiType, CallType> {
const { fn, def } = this.getMessage(message); const { def, fn } = this.getMessage(message);
return { return {
send: this.decorateMethod( send: this.decorateMethod(
as === 'rpc' && this.hasRpcContractsCall as === 'rpc' && this.hasRpcContractsCall
? (account: IKeyringPair | string | AccountId | Address): ContractCallResult<'rpc'> => ? (account: IKeyringPair | string | AccountId | Address): ContractCallResult<'rpc'> =>
this.rpcContractsCall( this._rpcContractsCall(
this.registry.createType('ContractCallRequest', { this.registry.createType('ContractCallRequest', {
origin: account,
dest: this.address.toString(), dest: this.address.toString(),
value,
gasLimit, gasLimit,
inputData: fn(...params) inputData: fn(...params),
origin: account,
value
}) })
).pipe(map((result: ContractExecResult): ContractCallOutcome => ).pipe(map((result: ContractExecResult): ContractCallOutcome =>
this.createOutcome(result, this.registry.createType('AccountId', account), def, params) this._createOutcome(result, this.registry.createType('AccountId', account), def, params)
)) ))
: (account: IKeyringPair | string | AccountId | Address): ContractCallResult<'tx'> => : (account: IKeyringPair | string | AccountId | Address): ContractCallResult<'tx'> =>
this.apiContracts this._apiContracts
.call(this.address, value, gasLimit, fn(...params)) .call(this.address, value, gasLimit, fn(...params))
.signAndSend(account) .signAndSend(account)
) )
}; };
} }
private createOutcome (result: ContractExecResult, origin: AccountId, message: ContractABIMessage, params: any[]): ContractCallOutcome { private _createOutcome (result: ContractExecResult, origin: AccountId, message: ContractABIMessage, params: any[]): ContractCallOutcome {
let output: Codec | null = null; let output: Codec | null = null;
if (result.isSuccess) { if (result.isSuccess) {
@@ -73,19 +79,13 @@ export default class Contract<ApiType extends ApiTypes> extends BaseWithTxAndRpc
} }
return { return {
time: Date.now(), isSuccess: result.isSuccess,
message, message,
origin, origin,
output,
params, params,
result, result,
isSuccess: result.isSuccess, time: Date.now()
output
}; };
} }
constructor (api: ApiObject<ApiType>, abi: ContractABIPre | Abi, decorateMethod: DecorateMethod<ApiType>, address: string | AccountId | Address) {
super(api, abi, decorateMethod);
this.address = this.registry.createType('Address', address);
}
} }
+6 -5
View File
@@ -31,9 +31,9 @@ export abstract class Base<ApiType extends ApiTypes> implements ContractBase<Api
public get messages (): ContractMessage[] { public get messages (): ContractMessage[] {
return this.abi.abi.contract.messages.map( return this.abi.abi.contract.messages.map(
(def: ContractABIMessage, index): ContractMessage => ({ (def: ContractABIMessage, index): ContractMessage => ({
index,
def, def,
fn: this.abi.messages[def.name] || this.abi.messages[stringCamelCase(name)] fn: this.abi.messages[def.name] || this.abi.messages[stringCamelCase(name)],
index
}) })
); );
} }
@@ -49,12 +49,13 @@ export abstract class Base<ApiType extends ApiTypes> implements ContractBase<Api
assert(!!def, `Attempted to access a contract message that does not exist: ${typeof nameOrIndex === 'number' ? `index ${nameOrIndex}` : nameOrIndex}`); assert(!!def, `Attempted to access a contract message that does not exist: ${typeof nameOrIndex === 'number' ? `index ${nameOrIndex}` : nameOrIndex}`);
const fn = this.abi.messages[def.name] || this.abi.messages[stringCamelCase(def.name)]; const fn = this.abi.messages[def.name] || this.abi.messages[stringCamelCase(def.name)];
return { index, def, fn };
return { def, fn, index };
} }
} }
export abstract class BaseWithTx<ApiType extends ApiTypes> extends Base<ApiType> { export abstract class BaseWithTx<ApiType extends ApiTypes> extends Base<ApiType> {
protected get apiContracts (): SubmittableModuleExtrinsics<'rxjs'> { protected get _apiContracts (): SubmittableModuleExtrinsics<'rxjs'> {
return this.api.rx.tx.contracts; return this.api.rx.tx.contracts;
} }
@@ -70,7 +71,7 @@ export abstract class BaseWithTxAndRpcCall<ApiType extends ApiTypes> extends Bas
return isFunction(this.api.rx.rpc.contracts?.call); return isFunction(this.api.rx.rpc.contracts?.call);
} }
protected get rpcContractsCall (): DecoratedRpc<'rxjs', RpcInterface>['contracts']['call'] { protected get _rpcContractsCall (): DecoratedRpc<'rxjs', RpcInterface>['contracts']['call'] {
assert(this.hasRpcContractsCall, 'You need to connect to a node with the contracts.call RPC method.'); assert(this.hasRpcContractsCall, 'You need to connect to a node with the contracts.call RPC method.');
return this.api.rx.rpc.contracts.call; return this.api.rx.rpc.contracts.call;
+9 -9
View File
@@ -1,6 +1,6 @@
{ {
"name": "@polkadot/api-derive", "name": "@polkadot/api-derive",
"version": "1.8.1", "version": "1.10.1",
"description": "Common functions used across Polkadot, derived from RPC calls and storage queries.", "description": "Common functions used across Polkadot, derived from RPC calls and storage queries.",
"main": "index.js", "main": "index.js",
"keywords": [ "keywords": [
@@ -28,17 +28,17 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme", "homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.9.2", "@babel/runtime": "^7.9.2",
"@polkadot/api": "1.8.1", "@polkadot/api": "1.10.1",
"@polkadot/rpc-core": "1.8.1", "@polkadot/rpc-core": "1.10.1",
"@polkadot/rpc-provider": "1.8.1", "@polkadot/rpc-provider": "1.10.1",
"@polkadot/types": "1.8.1", "@polkadot/types": "1.10.1",
"@polkadot/util": "^2.6.2", "@polkadot/util": "^2.8.1",
"@polkadot/util-crypto": "^2.6.2", "@polkadot/util-crypto": "^2.8.1",
"bn.js": "^5.1.1", "bn.js": "^5.1.1",
"memoizee": "^0.4.14", "memoizee": "^0.4.14",
"rxjs": "^6.5.4" "rxjs": "^6.5.5"
}, },
"devDependencies": { "devDependencies": {
"@polkadot/keyring": "^2.6.2" "@polkadot/keyring": "^2.8.1"
} }
} }
+4 -4
View File
@@ -59,6 +59,7 @@ function extractIdentity (identityOfOpt?: Option<Registration>, superOf?: [Accou
: undefined, : undefined,
email: dataAsString(info.email), email: dataAsString(info.email),
image: dataAsString(info.image), image: dataAsString(info.image),
judgements,
legal: dataAsString(info.legal), legal: dataAsString(info.legal),
other: info.additional.reduce((other: Record<string, string>, [_key, _value]): Record<string, string> => { other: info.additional.reduce((other: Record<string, string>, [_key, _value]): Record<string, string> => {
const key = dataAsString(_key); const key = dataAsString(_key);
@@ -78,8 +79,7 @@ function extractIdentity (identityOfOpt?: Option<Registration>, superOf?: [Accou
: undefined, : undefined,
riot: dataAsString(info.riot), riot: dataAsString(info.riot),
twitter: dataAsString(info.twitter), twitter: dataAsString(info.twitter),
web: dataAsString(info.web), web: dataAsString(info.web)
judgements
}; };
} }
@@ -140,9 +140,9 @@ function retrieveFlags (api: ApiInterfaceRx, accountId?: AccountId): Observable<
return { return {
isCouncil: (electionsMembers?.map(([id]) => id) || councilMembers || []).some(checkIncluded), isCouncil: (electionsMembers?.map(([id]) => id) || councilMembers || []).some(checkIncluded),
isTechCommittee: technicalCommitteeMembers.some(checkIncluded),
isSociety: societyMembers.some(checkIncluded), isSociety: societyMembers.some(checkIncluded),
isSudo: !!sudoKey && sudoKey.eq(accountId) isSudo: !!sudoKey && sudoKey.eq(accountId),
isTechCommittee: technicalCommitteeMembers.some(checkIncluded)
}; };
}) })
); );
+7 -7
View File
@@ -4,7 +4,7 @@
import { AccountId, AccountData, AccountIndex, AccountInfo, Address, Balance, Index } from '@polkadot/types/interfaces'; import { AccountId, AccountData, AccountIndex, AccountInfo, Address, Balance, Index } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types'; import { ITuple } from '@polkadot/types/types';
import { DerivedBalancesAccount } from '../types'; import { DeriveBalancesAccount } from '../types';
import { Observable, combineLatest, of } from 'rxjs'; import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
@@ -14,7 +14,7 @@ import { memo } from '../util';
type Result = [Balance, Balance, Balance, Balance, Index]; type Result = [Balance, Balance, Balance, Balance, Index];
function calcBalances (api: ApiInterfaceRx, [accountId, [freeBalance, reservedBalance, frozenFee, frozenMisc, accountNonce]]: [AccountId, Result]): DerivedBalancesAccount { function calcBalances (api: ApiInterfaceRx, [accountId, [freeBalance, reservedBalance, frozenFee, frozenMisc, accountNonce]]: [AccountId, Result]): DeriveBalancesAccount {
return { return {
accountId, accountId,
accountNonce, accountNonce,
@@ -44,7 +44,7 @@ function queryBalancesAccount (api: ApiInterfaceRx, accountId: AccountId): Obser
[api.query.balances.account, accountId], [api.query.balances.account, accountId],
[api.query.system.accountNonce, accountId] [api.query.system.accountNonce, accountId]
]).pipe( ]).pipe(
map(([{ free, reserved, miscFrozen, feeFrozen }, accountNonce]): Result => map(([{ feeFrozen, free, miscFrozen, reserved }, accountNonce]): Result =>
[free, reserved, feeFrozen, miscFrozen, accountNonce] [free, reserved, feeFrozen, miscFrozen, accountNonce]
) )
); );
@@ -54,7 +54,7 @@ function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<Re
// AccountInfo is current, support old, eg. Edgeware // AccountInfo is current, support old, eg. Edgeware
return api.query.system.account<AccountInfo | ITuple<[Index, AccountData]>>(accountId).pipe( return api.query.system.account<AccountInfo | ITuple<[Index, AccountData]>>(accountId).pipe(
map((infoOrTuple): Result => { map((infoOrTuple): Result => {
const { free, reserved, miscFrozen, feeFrozen } = (infoOrTuple as AccountInfo).nonce const { feeFrozen, free, miscFrozen, reserved } = (infoOrTuple as AccountInfo).nonce
? (infoOrTuple as AccountInfo).data ? (infoOrTuple as AccountInfo).data
: (infoOrTuple as [Index, AccountData])[1]; : (infoOrTuple as [Index, AccountData])[1];
const accountNonce = (infoOrTuple as AccountInfo).nonce || (infoOrTuple as [Index, AccountData])[0]; const accountNonce = (infoOrTuple as AccountInfo).nonce || (infoOrTuple as [Index, AccountData])[0];
@@ -79,8 +79,8 @@ function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<Re
* }); * });
* ``` * ```
*/ */
export function account (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DerivedBalancesAccount> { export function account (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DeriveBalancesAccount> {
return memo((address: AccountIndex | AccountId | Address | string): Observable<DerivedBalancesAccount> => return memo((address: AccountIndex | AccountId | Address | string): Observable<DeriveBalancesAccount> =>
api.derive.accounts.info(address).pipe( api.derive.accounts.info(address).pipe(
switchMap(({ accountId }): Observable<[AccountId, Result]> => switchMap(({ accountId }): Observable<[AccountId, Result]> =>
(accountId (accountId
@@ -95,6 +95,6 @@ export function account (api: ApiInterfaceRx): (address: AccountIndex | AccountI
: of([api.registry.createType('AccountId'), [api.registry.createType('Balance'), api.registry.createType('Balance'), api.registry.createType('Balance'), api.registry.createType('Balance'), api.registry.createType('Index')]]) : of([api.registry.createType('AccountId'), [api.registry.createType('Balance'), api.registry.createType('Balance'), api.registry.createType('Balance'), api.registry.createType('Balance'), api.registry.createType('Index')]])
) )
), ),
map((result): DerivedBalancesAccount => calcBalances(api, result)) map((result): DeriveBalancesAccount => calcBalances(api, result))
)); ));
} }
+6 -6
View File
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details. // of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, AccountIndex, Address, Balance, BalanceLock, BalanceLockTo212, BlockNumber, VestingInfo, VestingSchedule } from '@polkadot/types/interfaces'; import { AccountId, AccountIndex, Address, Balance, BalanceLock, BalanceLockTo212, BlockNumber, VestingInfo, VestingSchedule } from '@polkadot/types/interfaces';
import { DerivedBalancesAccount, DerivedBalancesAll } from '../types'; import { DeriveBalancesAccount, DeriveBalancesAll } from '../types';
import BN from 'bn.js'; import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs'; import { Observable, combineLatest, of } from 'rxjs';
@@ -15,9 +15,9 @@ import { bnMax } from '@polkadot/util';
import { memo } from '../util'; import { memo } from '../util';
type ResultBalance = [VestingInfo | null, (BalanceLock | BalanceLockTo212)[]]; type ResultBalance = [VestingInfo | null, (BalanceLock | BalanceLockTo212)[]];
type Result = [DerivedBalancesAccount, BlockNumber, ResultBalance]; type Result = [DeriveBalancesAccount, BlockNumber, ResultBalance];
function calcBalances (api: ApiInterfaceRx, [{ accountId, accountNonce, freeBalance, frozenFee, frozenMisc, reservedBalance, votingBalance }, bestNumber, [vesting, locks]]: Result): DerivedBalancesAll { function calcBalances (api: ApiInterfaceRx, [{ accountId, accountNonce, freeBalance, frozenFee, frozenMisc, reservedBalance, votingBalance }, bestNumber, [vesting, locks]]: Result): DeriveBalancesAll {
let lockedBalance = api.registry.createType('Balance'); let lockedBalance = api.registry.createType('Balance');
let lockedBreakdown: (BalanceLock | BalanceLockTo212)[] = []; let lockedBreakdown: (BalanceLock | BalanceLockTo212)[] = [];
let allLocked = false; let allLocked = false;
@@ -127,8 +127,8 @@ function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<Re
* }); * });
* ``` * ```
*/ */
export function all (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DerivedBalancesAll> { export function all (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DeriveBalancesAll> {
return memo((address: AccountIndex | AccountId | Address | string): Observable<DerivedBalancesAll> => return memo((address: AccountIndex | AccountId | Address | string): Observable<DeriveBalancesAll> =>
api.derive.balances.account(address).pipe( api.derive.balances.account(address).pipe(
switchMap((account): Observable<Result> => switchMap((account): Observable<Result> =>
(!account.accountId.isEmpty (!account.accountId.isEmpty
@@ -142,6 +142,6 @@ export function all (api: ApiInterfaceRx): (address: AccountIndex | AccountId |
: of([account, api.registry.createType('BlockNumber'), [null, api.registry.createType('Vec<BalanceLock>')]]) : of([account, api.registry.createType('BlockNumber'), [null, api.registry.createType('Vec<BalanceLock>')]])
) )
), ),
map((result): DerivedBalancesAll => calcBalances(api, result)) map((result): DeriveBalancesAll => calcBalances(api, result))
)); ));
} }
+4 -4
View File
@@ -4,7 +4,7 @@
import { ApiInterfaceRx } from '@polkadot/api/types'; import { ApiInterfaceRx } from '@polkadot/api/types';
import { Balance } from '@polkadot/types/interfaces'; import { Balance } from '@polkadot/types/interfaces';
import { DerivedFees } from '../types'; import { DeriveFees } from '../types';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
@@ -24,8 +24,8 @@ import { memo } from '../util';
* }); * });
* ``` * ```
*/ */
export function fees (api: ApiInterfaceRx): () => Observable<DerivedFees> { export function fees (api: ApiInterfaceRx): () => Observable<DeriveFees> {
return memo((): Observable<DerivedFees> => return memo((): Observable<DeriveFees> =>
of([ of([
// deprecated - remove // deprecated - remove
(api.consts.balances?.creationFee as Balance) || api.registry.createType('Balance'), (api.consts.balances?.creationFee as Balance) || api.registry.createType('Balance'),
@@ -36,7 +36,7 @@ export function fees (api: ApiInterfaceRx): () => Observable<DerivedFees> {
(api.consts.transactionPayment?.transactionBaseFee as Balance) || api.registry.createType('Balance'), (api.consts.transactionPayment?.transactionBaseFee as Balance) || api.registry.createType('Balance'),
(api.consts.transactionPayment?.transactionByteFee as Balance) || api.registry.createType('Balance') (api.consts.transactionPayment?.transactionByteFee as Balance) || api.registry.createType('Balance')
]).pipe( ]).pipe(
map(([creationFee, transferFee, existentialDeposit, transactionBaseFee, transactionByteFee]): DerivedFees => ({ map(([creationFee, transferFee, existentialDeposit, transactionBaseFee, transactionByteFee]): DeriveFees => ({
creationFee, creationFee,
existentialDeposit, existentialDeposit,
transactionBaseFee, transactionBaseFee,
@@ -3,19 +3,19 @@
// of the Apache-2.0 license. See the LICENSE file for details. // of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces'; import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces';
import { DerivedBalancesAccount } from '../types'; import { DeriveBalancesAccount } from '../types';
import { Observable, combineLatest, of } from 'rxjs'; import { Observable, combineLatest, of } from 'rxjs';
import { ApiInterfaceRx } from '@polkadot/api/types'; import { ApiInterfaceRx } from '@polkadot/api/types';
import { memo } from '../util'; import { memo } from '../util';
export function votingBalances (api: ApiInterfaceRx): (addresses?: (AccountId | AccountIndex | Address | string)[]) => Observable<DerivedBalancesAccount[]> { export function votingBalances (api: ApiInterfaceRx): (addresses?: (AccountId | AccountIndex | Address | string)[]) => Observable<DeriveBalancesAccount[]> {
return memo((addresses?: (AccountId | AccountIndex | Address | string)[]): Observable<DerivedBalancesAccount[]> => return memo((addresses?: (AccountId | AccountIndex | Address | string)[]): Observable<DeriveBalancesAccount[]> =>
!addresses || !addresses.length !addresses || !addresses.length
? of([] as DerivedBalancesAccount[]) ? of([] as DeriveBalancesAccount[])
: combineLatest( : combineLatest(
addresses.map((accountId): Observable<DerivedBalancesAccount> => addresses.map((accountId): Observable<DeriveBalancesAccount> =>
api.derive.balances.account(accountId) api.derive.balances.account(accountId)
) )
) )
@@ -4,17 +4,19 @@
import { ApiInterfaceRx } from '@polkadot/api/types'; import { ApiInterfaceRx } from '@polkadot/api/types';
import { Hash, Proposal, Votes } from '@polkadot/types/interfaces'; import { Hash, Proposal, Votes } from '@polkadot/types/interfaces';
import { DerivedCollectiveProposal } from '../types'; import { DeriveCollectiveProposal } from '../types';
import { Observable, combineLatest, of } from 'rxjs'; import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
import { Option } from '@polkadot/types'; import { Option } from '@polkadot/types';
import { memo } from '../util';
type Result = [Hash[], Option<Proposal>[], Option<Votes>[]]; type Result = [Hash[], Option<Proposal>[], Option<Votes>[]];
function parse ([hashes, proposals, votes]: Result): DerivedCollectiveProposal[] { function parse ([hashes, proposals, votes]: Result): DeriveCollectiveProposal[] {
return proposals return proposals
.map((proposalOpt, index): DerivedCollectiveProposal | null => .map((proposalOpt, index): DeriveCollectiveProposal | null =>
proposalOpt.isSome proposalOpt.isSome
? { ? {
hash: hashes[index], hash: hashes[index],
@@ -23,11 +25,11 @@ function parse ([hashes, proposals, votes]: Result): DerivedCollectiveProposal[]
} }
: null : null
) )
.filter((proposal): proposal is DerivedCollectiveProposal => !!proposal); .filter((proposal): proposal is DeriveCollectiveProposal => !!proposal);
} }
export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalCommittee'): () => Observable<DerivedCollectiveProposal[]> { export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalCommittee'): () => Observable<DeriveCollectiveProposal[]> {
return (): Observable<DerivedCollectiveProposal[]> => return memo((): Observable<DeriveCollectiveProposal[]> =>
api.query[section]?.proposals api.query[section]?.proposals
? api.query[section].proposals().pipe( ? api.query[section].proposals().pipe(
switchMap((hashes: Hash[]): Observable<Result> => switchMap((hashes: Hash[]): Observable<Result> =>
@@ -41,5 +43,6 @@ export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalC
), ),
map(parse) map(parse)
) )
: of([] as DerivedCollectiveProposal[]); : of([] as DeriveCollectiveProposal[])
);
} }
+4 -4
View File
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details. // of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types'; import { ApiInterfaceRx } from '@polkadot/api/types';
import { DerivedContractFees } from '../types'; import { DeriveContractFees } from '../types';
import BN from 'bn.js'; import BN from 'bn.js';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
@@ -44,10 +44,10 @@ function queryConstants (api: ApiInterfaceRx): Observable<ResultV2> {
* }); * });
* ``` * ```
*/ */
export function fees (api: ApiInterfaceRx): () => Observable<DerivedContractFees> { export function fees (api: ApiInterfaceRx): () => Observable<DeriveContractFees> {
return memo((): Observable<DerivedContractFees> => { return memo((): Observable<DeriveContractFees> => {
return queryConstants(api).pipe( return queryConstants(api).pipe(
map(([creationFee, transferFee, callBaseFee, contractFee, rentByteFee, rentDepositOffset, tombstoneDeposit, transactionBaseFee, transactionByteFee]): DerivedContractFees => ({ map(([creationFee, transferFee, callBaseFee, contractFee, rentByteFee, rentDepositOffset, tombstoneDeposit, transactionBaseFee, transactionByteFee]): DeriveContractFees => ({
callBaseFee, callBaseFee,
contractFee, contractFee,
creationFee, creationFee,
+2
View File
@@ -3,3 +3,5 @@
// of the Apache-2.0 license. See the LICENSE file for details. // of the Apache-2.0 license. See the LICENSE file for details.
export * from './proposals'; export * from './proposals';
export * from './votes';
export * from './votesOf';
+2 -2
View File
@@ -3,12 +3,12 @@
// of the Apache-2.0 license. See the LICENSE file for details. // of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types'; import { ApiInterfaceRx } from '@polkadot/api/types';
import { DerivedCollectiveProposals } from '../types'; import { DeriveCollectiveProposals } from '../types';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { proposals as collectiveProposals } from '../collective'; import { proposals as collectiveProposals } from '../collective';
import { memo } from '../util'; import { memo } from '../util';
export function proposals (api: ApiInterfaceRx): () => Observable<DerivedCollectiveProposals> { export function proposals (api: ApiInterfaceRx): () => Observable<DeriveCollectiveProposals> {
return memo(collectiveProposals(api, 'council')); return memo(collectiveProposals(api, 'council'));
} }
+12
View File
@@ -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][];
+90
View File
@@ -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([])
);
}
+9 -3
View File
@@ -2,8 +2,14 @@
// This software may be modified and distributed under the terms // This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details. // of the Apache-2.0 license. See the LICENSE file for details.
export * from './dispatchQueue';
export * from './nextExternal';
export * from './preimage';
export * from './preimages';
export * from './proposals'; export * from './proposals';
export * from './referendumInfos'; export * from './referendumIds';
export * from './referendums'; export * from './referendums';
export * from './referendumVotesFor'; export * from './referendumsActive';
export * from './votes'; export * from './referendumsFinished';
export * from './referendumsInfo';
export * from './sqrtElectorate';
@@ -0,0 +1,40 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Hash, VoteThreshold } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DeriveProposalExternal } from '../types';
import { Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Option } from '@polkadot/types';
import { memo } from '../util';
function withImage (api: ApiInterfaceRx, nextOpt: Option<ITuple<[Hash, VoteThreshold]>>): Observable<DeriveProposalExternal | null> {
if (nextOpt.isNone) {
return of(null);
}
const [imageHash, threshold] = nextOpt.unwrap();
return api.derive.democracy.preimage(imageHash).pipe(
map((image): DeriveProposalExternal => ({
image,
imageHash,
threshold
}))
);
}
export function nextExternal (api: ApiInterfaceRx): () => Observable<DeriveProposalExternal | null> {
return memo((): Observable<DeriveProposalExternal | null> =>
api.query.democracy?.nextExternal
? api.query.democracy.nextExternal<Option<ITuple<[Hash, VoteThreshold]>>>().pipe(
switchMap((nextOpt) => withImage(api, nextOpt))
)
: of(null)
);
}
@@ -0,0 +1,25 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, Balance, BlockNumber, Hash } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveProposalImage } from '../types';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Bytes, Option } from '@polkadot/types';
import { memo } from '../util';
import { parseImage } from './util';
type PreImage = Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>;
export function preimage (api: ApiInterfaceRx): (hash: Hash) => Observable<DeriveProposalImage | undefined> {
return memo((hashes: Hash[]): Observable<DeriveProposalImage | undefined> =>
api.query.democracy.preimages<PreImage>(hashes).pipe(
map((imageOpt) => parseImage(api, imageOpt))
)
);
}
@@ -0,0 +1,29 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, Balance, BlockNumber, Hash } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveProposalImage } from '../types';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Bytes, Option } from '@polkadot/types';
import { memo } from '../util';
import { parseImage } from './util';
type PreImage = Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>;
export function preimages (api: ApiInterfaceRx): (hashes: Hash[]) => Observable<(DeriveProposalImage | undefined)[]> {
return memo((hashes: Hash[]): Observable<(DeriveProposalImage | undefined)[]> =>
api.query.democracy.preimages.multi<PreImage>(hashes).pipe(
map((images): (DeriveProposalImage | undefined)[] =>
images.map((imageOpt) =>
parseImage(api, imageOpt)
)
)
)
);
}
+14 -42
View File
@@ -2,61 +2,35 @@
// This software may be modified and distributed under the terms // This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details. // of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, Balance, BlockNumber, Hash, PropIndex, Proposal } from '@polkadot/types/interfaces'; import { AccountId, Balance, Hash, PropIndex } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types'; import { ITuple } from '@polkadot/types/types';
import { DeriveProposal } from '../types'; import { DeriveProposalImage, DeriveProposal } from '../types';
import { Observable, combineLatest, of } from 'rxjs'; import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types'; import { ApiInterfaceRx } from '@polkadot/api/types';
import { Bytes, Option, Vec } from '@polkadot/types'; import { Option, Vec } from '@polkadot/types';
import { memo } from '../util'; import { memo } from '../util';
export type PreImage = Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>;
type Depositors = Option<ITuple<[Balance, Vec<AccountId>]>>; type Depositors = Option<ITuple<[Balance, Vec<AccountId>]>>;
type Proposals = Vec<ITuple<[PropIndex, Hash, AccountId]>>; type Proposals = Vec<ITuple<[PropIndex, Hash, AccountId]>>;
interface Result { function parse ([proposals, images, depositors]: [Proposals, (DeriveProposalImage | undefined)[], Depositors[]]): DeriveProposal[] {
depositors: Depositors[];
preimages: PreImage[];
proposals: Proposals;
}
function parse (api: ApiInterfaceRx, { depositors, proposals, preimages }: Result): DeriveProposal[] {
return proposals return proposals
.filter(([, , proposer], index): boolean => .filter(([, , proposer], index): boolean =>
!!(depositors[index]?.isSome) && !proposer.isEmpty !!(depositors[index]?.isSome) && !proposer.isEmpty
) )
.map(([propIndex, hash, proposer], index): DeriveProposal => { .map(([index, imageHash, proposer], proposalIndex): DeriveProposal => {
const preimage = preimages[index].unwrapOr(null); const [balance, seconds] = depositors[proposalIndex].unwrap();
const depositor = depositors[index].unwrap();
let proposal: undefined | Proposal;
// we could end up in a situation where the proposal is non-decodable, e.g. after an upgrade
if (preimage) {
try {
proposal = api.registry.createType('Proposal', preimage[0].toU8a(true));
} catch (error) {
console.error(error);
}
}
return { return {
balance: depositor[0], balance,
hash, image: images[proposalIndex],
index: propIndex, imageHash,
preimage: preimage index,
? {
at: preimage[3],
balance: preimage[2],
proposer: preimage[1]
}
: undefined,
proposal,
proposer, proposer,
seconds: depositor[1] seconds
}; };
}); });
} }
@@ -68,16 +42,14 @@ export function proposals (api: ApiInterfaceRx): () => Observable<DeriveProposal
switchMap((proposals) => switchMap((proposals) =>
combineLatest([ combineLatest([
of(proposals), of(proposals),
api.query.democracy.preimages.multi<PreImage>( api.derive.democracy.preimages(
proposals.map(([, hash]): Hash => hash)), proposals.map(([, hash]): Hash => hash)),
api.query.democracy.depositOf.multi<Depositors>( api.query.democracy.depositOf.multi<Depositors>(
proposals.map(([index]): PropIndex => index)) proposals.map(([index]): PropIndex => index))
]) ])
), ),
map(([proposals, preimages, depositors]): DeriveProposal[] => map(parse)
parse(api, { depositors, proposals, preimages })
)
) )
: of([] as DeriveProposal[]) : of([])
); );
} }
@@ -0,0 +1,29 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { ReferendumIndex } from '@polkadot/types/interfaces';
import BN from 'bn.js';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { memo } from '../util';
export function referendumIds (api: ApiInterfaceRx): () => Observable<BN[]> {
return memo((): Observable<BN[]> =>
api.query.democracy?.lowestUnbaked
? api.queryMulti<[ReferendumIndex, ReferendumIndex]>([
api.query.democracy.lowestUnbaked,
api.query.democracy.referendumCount
]).pipe(
map(([first, total]): BN[] =>
total.gt(first)
? [...Array(total.sub(first).toNumber())].map((_, i): BN => first.addn(i))
: []
)
)
: of([])
);
}
@@ -1,80 +0,0 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ReferendumInfo, ReferendumInfoTo239, ReferendumStatus } from '@polkadot/types/interfaces';
import { DerivedReferendum } from '../types';
import { PreImage } from './proposals';
import BN from 'bn.js';
import { Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Option } from '@polkadot/types';
import { memo } from '../util';
function isOld (info: ReferendumInfo | ReferendumInfoTo239): info is ReferendumInfoTo239 {
return !!(info as ReferendumInfoTo239).proposalHash;
}
function getStatus (info: Option<ReferendumInfo | ReferendumInfoTo239>): ReferendumStatus | ReferendumInfoTo239 | null {
if (info.isNone) {
return null;
}
const unwrapped = info.unwrap();
if (isOld(unwrapped)) {
return unwrapped;
} else if (unwrapped.isOngoing) {
return unwrapped.asOngoing;
}
// done, we don't include it here... only currently active
return null;
}
function constructInfo (api: ApiInterfaceRx, index: BN | number, status: ReferendumStatus | ReferendumInfoTo239, _preimage?: PreImage): DerivedReferendum | null {
const preImage = _preimage?.isSome
? _preimage.unwrap()
: null;
return {
index: api.registry.createType('PropIndex', index),
hash: status.proposalHash,
proposal: preImage
? api.registry.createType('Proposal', preImage[0].toU8a(true))
: undefined,
preimage: preImage
? {
at: preImage[3],
balance: preImage[2],
proposer: preImage[1]
}
: undefined,
status
};
}
export function retrieveInfo (api: ApiInterfaceRx, index: BN | number, info: Option<ReferendumInfo | ReferendumInfoTo239>): Observable<DerivedReferendum | null> {
const status = getStatus(info);
return status
? api.query.democracy.preimages(status.proposalHash).pipe(
map((preimage?: PreImage): DerivedReferendum | null =>
constructInfo(api, index, status, preimage)
)
)
: of(null);
}
export function referendumInfo (api: ApiInterfaceRx): (index: BN | number) => Observable<DerivedReferendum | null> {
return memo((index: BN | number): Observable<DerivedReferendum | null> =>
api.query.democracy.referendumInfoOf<Option<ReferendumInfo | ReferendumInfoTo239>>(index).pipe(
switchMap((info): Observable<DerivedReferendum | null> =>
retrieveInfo(api, index, info)
)
)
);
}
@@ -1,35 +0,0 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ReferendumInfo } from '@polkadot/types/interfaces/democracy';
import { DerivedReferendum } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Option } from '@polkadot/types';
import { memo } from '../util';
import { retrieveInfo } from './referendumInfo';
export function referendumInfos (api: ApiInterfaceRx): (ids?: (BN | number)[]) => Observable<DerivedReferendum[]> {
return memo((ids: (BN | number)[] = []): Observable<DerivedReferendum[]> =>
(
!ids?.length
? of([] as Option<ReferendumInfo>[])
: api.query.democracy.referendumInfoOf.multi<Option<ReferendumInfo>>(ids)
).pipe(
switchMap((infos): Observable<(DerivedReferendum | null)[]> =>
combineLatest(
ids.map((id, index): Observable<DerivedReferendum | null> =>
retrieveInfo(api, id, infos[index])
)
)
),
map((infos): DerivedReferendum[] =>
infos.filter((referendum): referendum is DerivedReferendum => !!referendum)
)
));
}
@@ -1,34 +0,0 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, Vote } from '@polkadot/types/interfaces';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Vec } from '@polkadot/types';
import { DerivedBalancesAccount, DerivedReferendumVote } from '../types';
import { memo } from '../util';
export function referendumVotesFor (api: ApiInterfaceRx): (referendumId: BN | number) => Observable<DerivedReferendumVote[]> {
return memo((referendumId: BN | number): Observable<DerivedReferendumVote[]> =>
api.query.democracy.votersFor<Vec<AccountId>>(referendumId).pipe(
switchMap((votersFor): Observable<[Vec<AccountId>, Vote[], DerivedBalancesAccount[]]> =>
combineLatest([
of(votersFor),
api.derive.democracy.votes(referendumId, votersFor),
api.derive.balances.votingBalances(votersFor)
])
),
map(([votersFor, votes, balances]): DerivedReferendumVote[] =>
votersFor.map((accountId, index): DerivedReferendumVote => ({
accountId,
balance: balances[index].votingBalance || api.registry.createType('Balance'),
vote: votes[index] || api.registry.createType('Vote')
} as DerivedReferendumVote))
)
));
}
@@ -2,33 +2,29 @@
// This software may be modified and distributed under the terms // This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details. // of the Apache-2.0 license. See the LICENSE file for details.
import { ReferendumIndex } from '@polkadot/types/interfaces/democracy';
import { DerivedReferendum } from '../types';
import BN from 'bn.js';
import { Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types'; import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveReferendumExt } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util'; import { memo } from '../util';
export function referendums (api: ApiInterfaceRx): () => Observable<DerivedReferendum[]> { export function referendums (api: ApiInterfaceRx): () => Observable<DeriveReferendumExt[]> {
return memo((): Observable<DerivedReferendum[]> => return memo((): Observable<DeriveReferendumExt[]> =>
api.query.democracy?.lowestUnbaked api.derive.democracy.referendumsActive().pipe(
? api.queryMulti<[ReferendumIndex, ReferendumIndex]>([ switchMap((referendums) =>
api.query.democracy.lowestUnbaked, combineLatest([
api.query.democracy.referendumCount of(referendums),
]).pipe( api.derive.democracy._referendumsVotes(referendums)
switchMap(([earliest, referendumCount]): Observable<DerivedReferendum[]> => ])
referendumCount?.gt(earliest) && referendumCount?.gtn(0) ),
? api.derive.democracy.referendumInfos( map(([referendums, votes]) =>
[...Array(referendumCount.sub(earliest).toNumber())].map((_, i): BN => referendums.map((referendum, index): DeriveReferendumExt => ({
earliest.addn(i) ...referendum,
) ...votes[index]
) }))
: of([])
)
) )
: of([] as DerivedReferendum[]) )
); );
} }
@@ -0,0 +1,23 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveReferendum } from '../types';
import { Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { memo } from '../util';
export function referendumsActive (api: ApiInterfaceRx): () => Observable<DeriveReferendum[]> {
return memo((): Observable<DeriveReferendum[]> =>
api.derive.democracy.referendumIds().pipe(
switchMap((ids): Observable<DeriveReferendum[]> =>
ids.length
? api.derive.democracy.referendumsInfo(ids)
: of([])
)
)
);
}
@@ -0,0 +1,27 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { ReferendumInfo, ReferendumInfoFinished } from '@polkadot/types/interfaces';
import { Observable } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option } from '@polkadot/types';
import { memo } from '../util';
export function referendumsFinished (api: ApiInterfaceRx): () => Observable<ReferendumInfoFinished[]> {
return memo((): Observable<ReferendumInfoFinished[]> =>
api.derive.democracy.referendumIds().pipe(
switchMap((ids) => api.query.democracy.referendumInfoOf.multi<Option<ReferendumInfo>>(ids)),
map((infos): ReferendumInfoFinished[] =>
infos
.filter((optInfo) => optInfo.isSome)
.map((optInfo) => optInfo.unwrap())
.filter((info) => info.isFinished)
.map((info) => info.asFinished)
)
)
);
}
@@ -0,0 +1,132 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId, ReferendumInfo, ReferendumInfoTo239, Vote, Voting, VotingDirectVote } from '@polkadot/types/interfaces';
import { DeriveBalancesAccount, DeriveReferendum, DeriveReferendumVote, DeriveReferendumVotes } from '../types';
import BN from 'bn.js';
import { Observable, of, combineLatest } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option, Vec } from '@polkadot/types';
import { memo } from '../util';
import { calcVotes, getStatus, parseImage } from './util';
function votesPrev (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveReferendumVote[]> {
return api.query.democracy.votersFor<Vec<AccountId>>(referendumId).pipe(
switchMap((votersFor): Observable<[Vec<AccountId>, Vote[], DeriveBalancesAccount[]]> =>
combineLatest([
of(votersFor),
votersFor.length
? api.query.democracy.voteOf.multi<Vote>(
votersFor.map((accountId): [BN | number, AccountId] =>
[referendumId, accountId]
)
)
: of([]),
api.derive.balances.votingBalances(votersFor)
])
),
map(([votersFor, votes, balances]): DeriveReferendumVote[] =>
votersFor.map((accountId, index): DeriveReferendumVote => ({
accountId,
balance: balances[index].votingBalance || api.registry.createType('Balance'),
vote: votes[index] || api.registry.createType('Vote')
}))
)
);
}
function votesCurr (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveReferendumVote[]> {
return api.query.democracy.votingOf.entries<Voting>().pipe(
map((allVoting): DeriveReferendumVote[] =>
allVoting
.map(([key, voting]): [AccountId, Voting] => [key.args[0] as AccountId, voting])
// FIXME We are ignoring delegated votes
.filter(([, voting]) => voting.isDirect)
.map(([accountId, voting]): [AccountId, VotingDirectVote[]] => [
accountId,
voting.asDirect.votes.filter(([idx]) => idx.eq(referendumId))
])
.filter(([, directVotes]) => !!directVotes.length)
.reduce((result: DeriveReferendumVote[], [accountId, votes]) =>
// FIXME We are ignoring split votes
votes.reduce((result: DeriveReferendumVote[], [, vote]): DeriveReferendumVote[] => {
if (vote.isStandard) {
result.push({
accountId,
...vote.asStandard
});
}
return result;
}, result), []
)
)
);
}
export function _referendumVotes (api: ApiInterfaceRx): (referendum: DeriveReferendum) => Observable<DeriveReferendumVotes> {
return memo((referendum: DeriveReferendum): Observable<DeriveReferendumVotes> =>
combineLatest([
api.derive.democracy.sqrtElectorate(),
api.query.democracy.votingOf
? votesCurr(api, referendum.index)
: votesPrev(api, referendum.index)
]).pipe(
map(([sqrtElectorate, votes]) =>
calcVotes(sqrtElectorate, referendum, votes)
)
)
);
}
export function _referendumsVotes (api: ApiInterfaceRx): (referendums: DeriveReferendum[]) => Observable<DeriveReferendumVotes[]> {
return memo((referendums: DeriveReferendum[]): Observable<DeriveReferendumVotes[]> =>
referendums.length
? combineLatest(
referendums.map((referendum): Observable<DeriveReferendumVotes> =>
api.derive.democracy._referendumVotes(referendum)
)
)
: of([])
);
}
export function _referendumInfo (api: ApiInterfaceRx): (index: BN, info: Option<ReferendumInfo | ReferendumInfoTo239>) => Observable<DeriveReferendum | null> {
return memo((index: BN, info: Option<ReferendumInfo | ReferendumInfoTo239>): Observable<DeriveReferendum | null> => {
const status = getStatus(info);
return status
? api.query.democracy.preimages(status.proposalHash).pipe(
map((preimage): DeriveReferendum => ({
image: parseImage(api, preimage),
imageHash: status.proposalHash,
index: api.registry.createType('ReferendumIndex', index),
status
}))
)
: of(null);
});
}
export function referendumsInfo (api: ApiInterfaceRx): (ids: BN[]) => Observable<DeriveReferendum[]> {
return memo((ids: BN[]): Observable<DeriveReferendum[]> =>
ids.length
? api.query.democracy.referendumInfoOf.multi<Option<ReferendumInfo>>(ids).pipe(
switchMap((infos): Observable<(DeriveReferendum | null)[]> =>
combineLatest(
ids.map((id, index): Observable<DeriveReferendum | null> =>
api.derive.democracy._referendumInfo(id, infos[index])
)
)
),
map((infos) =>
infos.filter((referendum): referendum is DeriveReferendum => !!referendum)
)
)
: of([])
);
}
@@ -0,0 +1,22 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import BN from 'bn.js';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { bnSqrt } from '@polkadot/util';
import { memo } from '../util';
export function sqrtElectorate (api: ApiInterfaceRx): () => Observable<BN> {
return memo((): Observable<BN> =>
api.query.balances.totalIssuance().pipe(
map((totalIssuance) =>
bnSqrt(totalIssuance)
)
)
);
}
@@ -0,0 +1,69 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, Balance, BlockNumber, Hash, Proposal, PropIndex, ReferendumInfoTo239, ReferendumStatus, Vote, ReferendumIndex, VoteThreshold } from '@polkadot/types/interfaces';
import BN from 'bn.js';
import { Vec } from '@polkadot/types';
export interface DeriveDispatch {
at: BlockNumber;
index: ReferendumIndex;
imageHash: Hash;
image?: DeriveProposalImage;
}
export interface DeriveProposalImage {
at: BlockNumber;
balance: Balance;
proposal?: Proposal;
proposer: AccountId;
}
export interface DeriveProposal {
balance?: Balance;
index: PropIndex;
image?: DeriveProposalImage;
imageHash: Hash;
proposer: AccountId;
seconds: Vec<AccountId>;
}
export interface DeriveProposalExternal {
image?: DeriveProposalImage;
imageHash: Hash;
threshold: VoteThreshold;
}
export interface DeriveReferendum {
index: ReferendumIndex;
image?: DeriveProposalImage;
imageHash: Hash;
status: ReferendumStatus | ReferendumInfoTo239;
}
export interface DeriveReferendumVote {
accountId: AccountId;
balance: Balance;
vote: Vote;
}
export interface DeriveReferendumVoteState {
allAye: DeriveReferendumVote[];
allNay: DeriveReferendumVote[];
voteCount: number;
voteCountAye: number;
voteCountNay: number;
votedAye: BN;
votedNay: BN;
votedTotal: BN;
}
export interface DeriveReferendumVotes extends DeriveReferendumVoteState {
isPassing: boolean;
votes: DeriveReferendumVote[];
}
export interface DeriveReferendumExt extends DeriveReferendum, DeriveReferendumVotes {
}
+191
View File
@@ -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]
)
)
);
}
+7 -7
View File
@@ -10,14 +10,14 @@ import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types'; import { ApiInterfaceRx } from '@polkadot/api/types';
import { Vec, u32 } from '@polkadot/types'; import { Vec, u32 } from '@polkadot/types';
import { DerivedElectionsInfo } from '../types'; import { DeriveElectionsInfo } from '../types';
import { memo } from '../util'; import { memo } from '../util';
function sortAccounts ([, balanceA]: ITuple<[AccountId, Balance]>, [, balanceB]: ITuple<[AccountId, Balance]>): number { function sortAccounts ([, balanceA]: ITuple<[AccountId, Balance]>, [, balanceB]: ITuple<[AccountId, Balance]>): number {
return balanceB.cmp(balanceA); return balanceB.cmp(balanceA);
} }
function queryElections (api: ApiInterfaceRx): Observable<DerivedElectionsInfo> { function queryElections (api: ApiInterfaceRx): Observable<DeriveElectionsInfo> {
const section = api.query.electionsPhragmen ? 'electionsPhragmen' : 'elections'; const section = api.query.electionsPhragmen ? 'electionsPhragmen' : 'elections';
return api.queryMulti<[Vec<AccountId>, Vec<AccountId>, Vec<ITuple<[AccountId, Balance]>>, Vec<ITuple<[AccountId, Balance]>>]>([ return api.queryMulti<[Vec<AccountId>, Vec<AccountId>, Vec<ITuple<[AccountId, Balance]>>, Vec<ITuple<[AccountId, Balance]>>]>([
@@ -26,10 +26,10 @@ function queryElections (api: ApiInterfaceRx): Observable<DerivedElectionsInfo>
api.query[section].members, api.query[section].members,
api.query[section].runnersUp api.query[section].runnersUp
]).pipe( ]).pipe(
map(([councilMembers, candidates, members, runnersUp]): DerivedElectionsInfo => ({ map(([councilMembers, candidates, members, runnersUp]): DeriveElectionsInfo => ({
candidates,
candidateCount: api.registry.createType('u32', candidates.length),
candidacyBond: api.consts[section].candidacyBond as Balance, candidacyBond: api.consts[section].candidacyBond as Balance,
candidateCount: api.registry.createType('u32', candidates.length),
candidates,
desiredSeats: api.consts[section].desiredMembers as u32, desiredSeats: api.consts[section].desiredMembers as u32,
members: members.length members: members.length
? members.sort(sortAccounts) ? members.sort(sortAccounts)
@@ -54,6 +54,6 @@ function queryElections (api: ApiInterfaceRx): Observable<DerivedElectionsInfo>
* }); * });
* ``` * ```
*/ */
export function info (api: ApiInterfaceRx): () => Observable<DerivedElectionsInfo> { export function info (api: ApiInterfaceRx): () => Observable<DeriveElectionsInfo> {
return memo((): Observable<DerivedElectionsInfo> => queryElections(api)); return memo((): Observable<DeriveElectionsInfo> => queryElections(api));
} }
@@ -3,7 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details. // of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId } from '@polkadot/types/interfaces'; import { AccountId } from '@polkadot/types/interfaces';
import { DerivedHeartbeats } from '../types'; import { DeriveHeartbeats } from '../types';
import { Observable, of, combineLatest } from 'rxjs'; import { Observable, of, combineLatest } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
@@ -15,8 +15,8 @@ import { memo } from '../util';
/** /**
* @description Return a boolean array indicating whether the passed accounts had received heartbeats in the current session * @description Return a boolean array indicating whether the passed accounts had received heartbeats in the current session
*/ */
export function receivedHeartbeats (api: ApiInterfaceRx): () => Observable<DerivedHeartbeats> { export function receivedHeartbeats (api: ApiInterfaceRx): () => Observable<DeriveHeartbeats> {
return memo((): Observable<DerivedHeartbeats> => return memo((): Observable<DeriveHeartbeats> =>
api.query.imOnline?.receivedHeartbeats api.query.imOnline?.receivedHeartbeats
? api.derive.staking.overview().pipe( ? api.derive.staking.overview().pipe(
switchMap(({ currentIndex, validators }): Observable<[AccountId[], Option<Bytes>[], u32[]]> => switchMap(({ currentIndex, validators }): Observable<[AccountId[], Option<Bytes>[], u32[]]> =>
@@ -28,8 +28,8 @@ export function receivedHeartbeats (api: ApiInterfaceRx): () => Observable<Deriv
validators.map((address) => [currentIndex, address])) validators.map((address) => [currentIndex, address]))
]) ])
), ),
map(([validators, heartbeats, numBlocks]): DerivedHeartbeats => map(([validators, heartbeats, numBlocks]): DeriveHeartbeats =>
validators.reduce((result: DerivedHeartbeats, validator, index): DerivedHeartbeats => ({ validators.reduce((result: DeriveHeartbeats, validator, index): DeriveHeartbeats => ({
...result, ...result,
[validator.toString()]: { [validator.toString()]: {
blockCount: numBlocks[index], blockCount: numBlocks[index],
+1 -3
View File
@@ -49,10 +49,8 @@ describe('derive', (): void => {
testFunction(api)('chain', 'bestNumber', []); testFunction(api)('chain', 'bestNumber', []);
testFunction(api)('chain', 'bestNumberFinalized', []); testFunction(api)('chain', 'bestNumberFinalized', []);
testFunction(api)('democracy', 'referendumInfos', []); testFunction(api)('democracy', 'proposals', []);
testFunction(api)('democracy', 'referendums', []); testFunction(api)('democracy', 'referendums', []);
testFunction(api)('democracy', 'referendumVotesFor', []);
testFunction(api)('democracy', 'votes', []);
testFunction(api)('elections', 'info', []); testFunction(api)('elections', 'info', []);
+3 -1
View File
@@ -21,10 +21,11 @@ import * as society from './society';
import * as staking from './staking'; import * as staking from './staking';
import * as technicalCommittee from './technicalCommittee'; import * as technicalCommittee from './technicalCommittee';
import * as treasury from './treasury'; import * as treasury from './treasury';
import * as tx from './tx';
export * from './type'; export * from './type';
export const derive = { accounts, balances, chain, contracts, council, democracy, elections, imOnline, parachains, session, society, staking, technicalCommittee, treasury }; export const derive = { accounts, balances, chain, contracts, council, democracy, elections, imOnline, parachains, session, society, staking, technicalCommittee, treasury, tx };
type DeriveSection<Section> = { type DeriveSection<Section> = {
[Method in keyof Section]: Section[Method] extends AnyFunction [Method in keyof Section]: Section[Method] extends AnyFunction
@@ -76,6 +77,7 @@ function injectFunctions<AllSections> (api: ApiInterfaceRx, allSections: AllSect
const methodName = _methodName as keyof typeof section; const methodName = _methodName as keyof typeof section;
// Not sure what to do here, casting as any. Though the final types are good // Not sure what to do here, casting as any. Though the final types are good
const method = (section[methodName] as any)(api); const method = (section[methodName] as any)(api);
// idem // idem
(sectionAcc as any)[methodName] = method; (sectionAcc as any)[methodName] = method;
@@ -44,6 +44,7 @@ function parseActive (id: ParaId, active: Active): DeriveParachainActive | null
) )
}; };
} }
return null; return null;
} }
@@ -12,7 +12,7 @@ import { memo } from '../util';
export function eraProgress (api: ApiInterfaceRx): () => Observable<BlockNumber> { export function eraProgress (api: ApiInterfaceRx): () => Observable<BlockNumber> {
return memo((): Observable<BlockNumber> => return memo((): Observable<BlockNumber> =>
api.derive.session.info().pipe( api.derive.session.progress().pipe(
map((info) => info.eraProgress) map((info) => info.eraProgress)
)); ));
} }
+1
View File
@@ -6,4 +6,5 @@ export * from './eraLength';
export * from './eraProgress'; export * from './eraProgress';
export * from './indexes'; export * from './indexes';
export * from './info'; export * from './info';
export * from './progress';
export * from './sessionProgress'; export * from './sessionProgress';
+23 -64
View File
@@ -3,110 +3,69 @@
// of the Apache-2.0 license. See the LICENSE file for details. // of the Apache-2.0 license. See the LICENSE file for details.
import { SessionIndex } from '@polkadot/types/interfaces'; import { SessionIndex } from '@polkadot/types/interfaces';
import { DerivedSessionInfo, DeriveSessionIndexes } from '../types'; import { DeriveSessionInfo, DeriveSessionIndexes } from '../types';
import { Observable, combineLatest, of } from 'rxjs'; import { Observable } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types'; import { ApiInterfaceRx } from '@polkadot/api/types';
import { Option, u64 } from '@polkadot/types'; import { u64 } from '@polkadot/types';
import { memo } from '../util'; import { memo } from '../util';
type ResultSlots = [u64, u64, u64, Option<SessionIndex>];
type ResultSlotsFlat = [u64, u64, u64, SessionIndex];
type ResultType = [boolean, u64, SessionIndex]; type ResultType = [boolean, u64, SessionIndex];
type Result = [ResultType, DeriveSessionIndexes, ResultSlotsFlat]; type Result = [ResultType, DeriveSessionIndexes];
function createDerived (api: ApiInterfaceRx, [[hasBabe, epochDuration, sessionsPerEra], { activeEra, activeEraStart, currentEra, currentIndex, validatorCount }, [currentSlot, epochIndex, epochOrGenesisStartSlot, activeEraStartSessionIndex]]: Result): DerivedSessionInfo {
const epochStartSlot = epochIndex.mul(epochDuration).add(epochOrGenesisStartSlot);
const sessionProgress = currentSlot.sub(epochStartSlot);
const eraProgress = currentIndex.sub(activeEraStartSessionIndex).mul(epochDuration).add(sessionProgress);
function createDerive (api: ApiInterfaceRx, [[hasBabe, epochDuration, sessionsPerEra], { activeEra, activeEraStart, currentEra, currentIndex, validatorCount }]: Result): DeriveSessionInfo {
return { return {
activeEra, activeEra,
activeEraStart, activeEraStart,
currentEra, currentEra,
currentIndex, currentIndex,
eraLength: api.registry.createType('BlockNumber', sessionsPerEra.mul(epochDuration)), eraLength: api.registry.createType('BlockNumber', sessionsPerEra.mul(epochDuration)),
eraProgress: api.registry.createType('BlockNumber', eraProgress),
isEpoch: hasBabe, isEpoch: hasBabe,
sessionLength: epochDuration, sessionLength: epochDuration,
sessionsPerEra, sessionsPerEra,
sessionProgress: api.registry.createType('BlockNumber', sessionProgress),
validatorCount validatorCount
}; };
} }
function queryAura (api: ApiInterfaceRx): Observable<DerivedSessionInfo> { function queryAura (api: ApiInterfaceRx): Observable<DeriveSessionInfo> {
return api.derive.session.indexes().pipe( return api.derive.session.indexes().pipe(
map((indexes): DerivedSessionInfo => map((indexes): DeriveSessionInfo =>
createDerived(api, [ createDerive(api, [
[ [
false, false,
api.registry.createType('u64', 1), api.registry.createType('u64', 1),
api.consts.staking?.sessionsPerEra || api.registry.createType('SessionIndex', 1) api.consts.staking?.sessionsPerEra || api.registry.createType('SessionIndex', 1)
], ],
indexes, indexes
[
api.registry.createType('u64', 1),
api.registry.createType('u64', 1),
api.registry.createType('u64', 1),
api.registry.createType('SessionIndex', 1)
]
]) ])
) )
); );
} }
function queryBabe (api: ApiInterfaceRx): Observable<[DeriveSessionIndexes, ResultSlotsFlat]> { function queryBabe (api: ApiInterfaceRx): Observable<DeriveSessionInfo> {
return api.derive.session.indexes().pipe( return api.derive.session.indexes().pipe(
switchMap((indexes): Observable<[DeriveSessionIndexes, ResultSlots]> => map((indexes) =>
combineLatest([ createDerive(api, [
of(indexes), [
api.queryMulti<ResultSlots>([ true,
api.query.babe.currentSlot, api.consts.babe.epochDuration,
api.query.babe.epochIndex, api.consts.staking.sessionsPerEra
api.query.babe.genesisSlot, ],
[api.query.staking.erasStartSessionIndex, indexes.activeEra] indexes
])
]) ])
), )
map(([indexes, [currentSlot, epochIndex, genesisSlot, optStartIndex]]): [DeriveSessionIndexes, ResultSlotsFlat] => [
indexes, [currentSlot, epochIndex, genesisSlot, optStartIndex.unwrapOr(api.registry.createType('SessionIndex', 1))]
])
); );
} }
function queryBabeNoHistory (api: ApiInterfaceRx): Observable<[DeriveSessionIndexes, ResultSlotsFlat]> {
return combineLatest([
api.derive.session.indexes(),
api.queryMulti<ResultSlotsFlat>([
api.query.babe.currentSlot,
api.query.babe.epochIndex,
api.query.babe.genesisSlot,
api.query.staking.currentEraStartSessionIndex
])
]);
}
/** /**
* @description Retrieves all the session and era query and calculates specific values on it as the length of the session and eras * @description Retrieves all the session and era query and calculates specific values on it as the length of the session and eras
*/ */
export function info (api: ApiInterfaceRx): () => Observable<DerivedSessionInfo> { export function info (api: ApiInterfaceRx): () => Observable<DeriveSessionInfo> {
return memo((): Observable<DerivedSessionInfo> => return memo((): Observable<DeriveSessionInfo> =>
api.consts.babe api.consts.babe
? (api.query.staking.erasStartSessionIndex ? queryBabe(api)
? queryBabe(api) // 2.x with Babe
: queryBabeNoHistory(api)
).pipe(
map(([indexes, slots]: [DeriveSessionIndexes, ResultSlotsFlat]): DerivedSessionInfo =>
createDerived(api, [
[true, api.consts.babe.epochDuration, api.consts.staking.sessionsPerEra],
indexes,
slots
])
)
)
: queryAura(api) : queryAura(api)
); );
} }
@@ -0,0 +1,90 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { SessionIndex } from '@polkadot/types/interfaces';
import { DeriveSessionInfo, DeriveSessionProgress } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Option, u64 } from '@polkadot/types';
import { memo } from '../util';
type ResultSlots = [u64, u64, u64, Option<SessionIndex>];
type ResultSlotsFlat = [u64, u64, u64, SessionIndex];
function createDerive (api: ApiInterfaceRx, info: DeriveSessionInfo, [currentSlot, epochIndex, epochOrGenesisStartSlot, activeEraStartSessionIndex]: ResultSlotsFlat): DeriveSessionProgress {
const epochStartSlot = epochIndex.mul(info.sessionLength).add(epochOrGenesisStartSlot);
const sessionProgress = currentSlot.sub(epochStartSlot);
const eraProgress = info.currentIndex.sub(activeEraStartSessionIndex).mul(info.sessionLength).add(sessionProgress);
return {
...info,
eraProgress: api.registry.createType('BlockNumber', eraProgress),
sessionProgress: api.registry.createType('BlockNumber', sessionProgress)
};
}
function queryAura (api: ApiInterfaceRx): Observable<DeriveSessionProgress> {
return api.derive.session.info().pipe(
map((info): DeriveSessionProgress =>
createDerive(api, info, [
api.registry.createType('u64', 1),
api.registry.createType('u64', 1),
api.registry.createType('u64', 1),
api.registry.createType('SessionIndex', 1)
])
)
);
}
function queryBabe (api: ApiInterfaceRx): Observable<[DeriveSessionInfo, ResultSlotsFlat]> {
return api.derive.session.info().pipe(
switchMap((info): Observable<[DeriveSessionInfo, ResultSlots]> =>
combineLatest([
of(info),
api.queryMulti<ResultSlots>([
api.query.babe.currentSlot,
api.query.babe.epochIndex,
api.query.babe.genesisSlot,
[api.query.staking.erasStartSessionIndex, info.activeEra]
])
])
),
map(([info, [currentSlot, epochIndex, genesisSlot, optStartIndex]]): [DeriveSessionInfo, ResultSlotsFlat] => [
info, [currentSlot, epochIndex, genesisSlot, optStartIndex.unwrapOr(api.registry.createType('SessionIndex', 1))]
])
);
}
function queryBabeNoHistory (api: ApiInterfaceRx): Observable<[DeriveSessionInfo, ResultSlotsFlat]> {
return combineLatest([
api.derive.session.info(),
api.queryMulti<ResultSlotsFlat>([
api.query.babe.currentSlot,
api.query.babe.epochIndex,
api.query.babe.genesisSlot,
api.query.staking.currentEraStartSessionIndex
])
]);
}
/**
* @description Retrieves all the session and era query and calculates specific values on it as the length of the session and eras
*/
export function progress (api: ApiInterfaceRx): () => Observable<DeriveSessionProgress> {
return memo((): Observable<DeriveSessionProgress> =>
api.consts.babe
? (api.query.staking.erasStartSessionIndex
? queryBabe(api) // 2.x with Babe
: queryBabeNoHistory(api)
).pipe(
map(([info, slots]: [DeriveSessionInfo, ResultSlotsFlat]): DeriveSessionProgress =>
createDerive(api, info, slots)
)
)
: queryAura(api)
);
}
@@ -12,7 +12,7 @@ import { memo } from '../util';
export function sessionProgress (api: ApiInterfaceRx): () => Observable<BlockNumber> { export function sessionProgress (api: ApiInterfaceRx): () => Observable<BlockNumber> {
return memo((): Observable<BlockNumber> => return memo((): Observable<BlockNumber> =>
api.derive.session.info().pipe( api.derive.session.progress().pipe(
map((info) => info.sessionProgress) map((info) => info.sessionProgress)
)); ));
} }
+5 -2
View File
@@ -14,11 +14,14 @@ export interface DeriveSessionIndexes {
validatorCount: u32; validatorCount: u32;
} }
export interface DerivedSessionInfo extends DeriveSessionIndexes { export interface DeriveSessionInfo extends DeriveSessionIndexes {
eraLength: BlockNumber; eraLength: BlockNumber;
eraProgress: BlockNumber;
isEpoch: boolean; isEpoch: boolean;
sessionLength: BlockNumber; sessionLength: BlockNumber;
sessionsPerEra: SessionIndex; sessionsPerEra: SessionIndex;
}
export interface DeriveSessionProgress extends DeriveSessionInfo {
eraProgress: BlockNumber;
sessionProgress: BlockNumber; sessionProgress: BlockNumber;
} }
@@ -30,7 +30,7 @@ export function candidates (api: ApiInterfaceRx): () => Observable<DeriveSociety
]) ])
), ),
map(([candidates, suspended]: Result): DeriveSocietyCandidate[] => map(([candidates, suspended]: Result): DeriveSocietyCandidate[] =>
candidates.map(({ who, kind, value }, index) => ({ candidates.map(({ kind, value, who }, index) => ({
accountId: who, accountId: who,
isSuspended: suspended[index].isSome, isSuspended: suspended[index].isSome,
kind, kind,
+1 -1
View File
@@ -30,9 +30,9 @@ export function info (api: ApiInterfaceRx): () => Observable<DeriveSociety> {
map(([bids, defender, founder, head, maxMembers, pot]: Result): DeriveSociety => ({ map(([bids, defender, founder, head, maxMembers, pot]: Result): DeriveSociety => ({
bids, bids,
defender: defender.unwrapOr(undefined), defender: defender.unwrapOr(undefined),
founder: founder.unwrapOr(undefined),
hasDefender: (defender.isSome && head.isSome && !head.eq(defender)) || false, hasDefender: (defender.isSome && head.isSome && !head.eq(defender)) || false,
head: head.unwrapOr(undefined), head: head.unwrapOr(undefined),
founder: founder.unwrapOr(undefined),
maxMembers, maxMembers,
pot pot
})) }))
+1 -1
View File
@@ -29,8 +29,8 @@ export function member (api: ApiInterfaceRx): (accountId: AccountId) => Observab
]).pipe( ]).pipe(
map(([payouts, strikes, defenderVotes, suspended, vouching]: Result): DeriveSocietyMember => ({ map(([payouts, strikes, defenderVotes, suspended, vouching]: Result): DeriveSocietyMember => ({
accountId, accountId,
payouts,
isSuspended: suspended.isTrue, isSuspended: suspended.isTrue,
payouts,
strikes, strikes,
vote: defenderVotes.unwrapOr(undefined), vote: defenderVotes.unwrapOr(undefined),
vouching: vouching.unwrapOr(undefined) vouching: vouching.unwrapOr(undefined)
+13 -27
View File
@@ -3,8 +3,8 @@
// of the Apache-2.0 license. See the LICENSE file for details. // of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types'; import { ApiInterfaceRx } from '@polkadot/api/types';
import { Balance, BlockNumber, StakingLedger, UnlockChunk } from '@polkadot/types/interfaces'; import { Balance, StakingLedger, UnlockChunk } from '@polkadot/types/interfaces';
import { DerivedSessionInfo, DerivedStakingAccount, DerivedStakingQuery, DerivedUnlocking } from '../types'; import { DeriveSessionInfo, DeriveStakingAccount, DeriveStakingQuery, DeriveUnlocking } from '../types';
import BN from 'bn.js'; import BN from 'bn.js';
import { Observable, combineLatest } from 'rxjs'; import { Observable, combineLatest } from 'rxjs';
@@ -27,27 +27,13 @@ function groupByEra (list: UnlockChunk[]): Record<string, BN> {
}, {}); }, {});
} }
// calculate the remaining blocks in a specific unlock era function calculateUnlocking (api: ApiInterfaceRx, stakingLedger: StakingLedger | undefined, sessionInfo: DeriveSessionInfo): DeriveUnlocking[] | undefined {
function remainingBlocks (api: ApiInterfaceRx, era: BN, sessionInfo: DerivedSessionInfo): BlockNumber {
const remaining = era.sub(sessionInfo.currentEra);
// on the Rust side the current-era >= era-for-unlock (removal done on >)
return api.registry.createType('BlockNumber', remaining.gtn(0)
? remaining
.subn(1)
.mul(sessionInfo.eraLength)
.add(sessionInfo.eraLength.sub(sessionInfo.eraProgress))
: 0
);
}
function calculateUnlocking (api: ApiInterfaceRx, stakingLedger: StakingLedger | undefined, sessionInfo: DerivedSessionInfo): DerivedUnlocking[] | undefined {
if (isUndefined(stakingLedger)) { if (isUndefined(stakingLedger)) {
return undefined; return undefined;
} }
const unlockingChunks = stakingLedger.unlocking.filter(({ era }): boolean => const unlockingChunks = stakingLedger.unlocking.filter(({ era }): boolean =>
remainingBlocks(api, era.unwrap(), sessionInfo).gtn(0) era.unwrap().sub(sessionInfo.activeEra).gtn(0)
); );
if (!unlockingChunks.length) { if (!unlockingChunks.length) {
@@ -56,27 +42,27 @@ function calculateUnlocking (api: ApiInterfaceRx, stakingLedger: StakingLedger |
// group the unlock chunks that have the same era and sum their values // group the unlock chunks that have the same era and sum their values
const groupedResult = groupByEra(unlockingChunks); const groupedResult = groupByEra(unlockingChunks);
const results = Object.entries(groupedResult).map(([eraString, value]): DerivedUnlocking => ({ const results = Object.entries(groupedResult).map(([eraString, value]): DeriveUnlocking => ({
value: api.registry.createType('Balance', value), remainingEras: new BN(eraString).sub(sessionInfo.activeEra),
remainingBlocks: remainingBlocks(api, new BN(eraString), sessionInfo) value: api.registry.createType('Balance', value)
})); }));
return results.length ? results : undefined; return results.length ? results : undefined;
} }
function redeemableSum (api: ApiInterfaceRx, stakingLedger: StakingLedger | undefined, sessionInfo: DerivedSessionInfo): Balance { function redeemableSum (api: ApiInterfaceRx, stakingLedger: StakingLedger | undefined, sessionInfo: DeriveSessionInfo): Balance {
if (isUndefined(stakingLedger)) { if (isUndefined(stakingLedger)) {
return api.registry.createType('Balance'); return api.registry.createType('Balance');
} }
return api.registry.createType('Balance', stakingLedger.unlocking.reduce((total, { era, value }): BN => { return api.registry.createType('Balance', stakingLedger.unlocking.reduce((total, { era, value }): BN => {
return remainingBlocks(api, era.unwrap(), sessionInfo).eqn(0) return sessionInfo.activeEra.gte(era.unwrap())
? total.add(value.unwrap()) ? total.add(value.unwrap())
: total; : total;
}, new BN(0))); }, new BN(0)));
} }
function parseResult (api: ApiInterfaceRx, sessionInfo: DerivedSessionInfo, query: DerivedStakingQuery): DerivedStakingAccount { function parseResult (api: ApiInterfaceRx, sessionInfo: DeriveSessionInfo, query: DeriveStakingQuery): DeriveStakingAccount {
return { return {
...query, ...query,
redeemable: redeemableSum(api, query.stakingLedger, sessionInfo), redeemable: redeemableSum(api, query.stakingLedger, sessionInfo),
@@ -87,13 +73,13 @@ function parseResult (api: ApiInterfaceRx, sessionInfo: DerivedSessionInfo, quer
/** /**
* @description From a stash, retrieve the controllerId and fill in all the relevant staking details * @description From a stash, retrieve the controllerId and fill in all the relevant staking details
*/ */
export function account (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DerivedStakingAccount> { export function account (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DeriveStakingAccount> {
return memo((accountId: Uint8Array | string): Observable<DerivedStakingAccount> => return memo((accountId: Uint8Array | string): Observable<DeriveStakingAccount> =>
combineLatest([ combineLatest([
api.derive.session.info(), api.derive.session.info(),
api.derive.staking.query(accountId) api.derive.staking.query(accountId)
]).pipe( ]).pipe(
map(([sessionInfo, query]: [DerivedSessionInfo, DerivedStakingQuery]) => map(([sessionInfo, query]: [DeriveSessionInfo, DeriveStakingQuery]) =>
parseResult(api, sessionInfo, query)) parseResult(api, sessionInfo, query))
)); ));
} }
@@ -0,0 +1,42 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, EraPoints, EraRewardPoints, RewardPoint } from '@polkadot/types/interfaces';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
function retrievePointsPrev (api: ApiInterfaceRx, currentElected: AccountId[]): Observable<EraRewardPoints> {
return api.query.staking.currentEraPointsEarned<EraPoints>().pipe(
map(({ individual, total }): EraRewardPoints =>
api.registry.createType('EraRewardPoints', {
individual: new Map<AccountId, RewardPoint>(
individual
.map((points) => api.registry.createType('RewardPoint', points))
.map((points, index): [AccountId, RewardPoint] => [currentElected[index], points])
),
total
})
)
);
}
/**
* @description Retrieve the staking overview, including elected and points earned
*/
export function currentPoints (api: ApiInterfaceRx): () => Observable<EraRewardPoints> {
return memo((): Observable<EraRewardPoints> =>
api.derive.staking.overview().pipe(
switchMap(({ activeEra, nextElected }) =>
api.query.staking.erasRewardPoints
? api.query.staking.erasRewardPoints<EraRewardPoints>(activeEra)
: api.query.staking.currentEraPointsEarned
? retrievePointsPrev(api, nextElected)
: of(api.registry.createType('EraRewardPoints'))
)
));
}
@@ -4,27 +4,25 @@
import { ApiInterfaceRx } from '@polkadot/api/types'; import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId } from '@polkadot/types/interfaces'; import { AccountId } from '@polkadot/types/interfaces';
import { DerivedStakingQuery, DerivedStakingElected } from '../types'; import { DeriveStakingQuery, DeriveStakingElected } from '../types';
import { Observable, combineLatest, of } from 'rxjs'; import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util'; import { memo } from '../util';
export function electedInfo (api: ApiInterfaceRx): () => Observable<DerivedStakingElected> { export function electedInfo (api: ApiInterfaceRx): () => Observable<DeriveStakingElected> {
return memo((): Observable<DerivedStakingElected> => return memo((): Observable<DeriveStakingElected> =>
api.derive.staking.validators().pipe( api.derive.staking.validators().pipe(
switchMap(({ nextElected }): Observable<[AccountId[], DerivedStakingQuery[]]> => switchMap(({ nextElected }): Observable<[AccountId[], DeriveStakingQuery[]]> =>
combineLatest([ combineLatest([
of(nextElected), of(nextElected),
combineLatest( combineLatest(
nextElected.map((accountId): Observable<DerivedStakingQuery> => nextElected.map((accountId) => api.derive.staking.query(accountId))
api.derive.staking.query(accountId)
)
) )
]) ])
), ),
map(([nextElected, info]): DerivedStakingElected => ({ map(([nextElected, info]): DeriveStakingElected => ({
info, info,
nextElected nextElected
})) }))
+13 -12
View File
@@ -6,7 +6,6 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
import { EraIndex, Exposure } from '@polkadot/types/interfaces'; import { EraIndex, Exposure } from '@polkadot/types/interfaces';
import { DeriveEraExposure, DeriveEraNominatorExposure, DeriveEraValidatorExposure } from '../types'; import { DeriveEraExposure, DeriveEraNominatorExposure, DeriveEraValidatorExposure } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs'; import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
import { StorageKey } from '@polkadot/types'; import { StorageKey } from '@polkadot/types';
@@ -24,11 +23,11 @@ function mapStakers (era: EraIndex, stakers: KeysAndExposures): DeriveEraExposur
validators[validatorId] = exposure; validators[validatorId] = exposure;
exposure.others.forEach(({ who }, index): void => { exposure.others.forEach(({ who }, validatorIndex): void => {
const nominatorId = who.toString(); const nominatorId = who.toString();
nominators[nominatorId] = nominators[nominatorId] || []; nominators[nominatorId] = nominators[nominatorId] || [];
nominators[nominatorId].push([validatorId, index]); nominators[nominatorId].push({ validatorId, validatorIndex });
}); });
}); });
@@ -43,16 +42,18 @@ export function eraExposure (api: ApiInterfaceRx): (era: EraIndex) => Observable
); );
} }
export function erasExposure (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraExposure[]> { export function _erasExposure (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraExposure[]> {
return memo((withActive?: boolean | BN | number): Observable<DeriveEraExposure[]> => return memo((eras: EraIndex[]): Observable<DeriveEraExposure[]> =>
eras.length
? combineLatest(eras.map((era) => api.derive.staking.eraExposure(era)))
: of([])
);
}
export function erasExposure (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraExposure[]> {
return memo((withActive?: boolean): Observable<DeriveEraExposure[]> =>
api.derive.staking.erasHistoric(withActive).pipe( api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras): Observable<DeriveEraExposure[]> => switchMap((eras) => api.derive.staking._erasExposure(eras))
eras.length
? combineLatest(
eras.map((era) => api.derive.staking.eraExposure(era))
)
: of([])
)
) )
); );
} }
@@ -9,45 +9,32 @@ import BN from 'bn.js';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { Option, u32 } from '@polkadot/types'; import { Option, u32 } from '@polkadot/types';
import { isBoolean, isUndefined, bnToBn } from '@polkadot/util';
import { memo } from '../util'; import { memo } from '../util';
export function erasHistoric (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<EraIndex[]> { export function erasHistoric (api: ApiInterfaceRx): (withActive?: boolean) => Observable<EraIndex[]> {
return memo((withActive?: boolean | BN | number): Observable<EraIndex[]> => return memo((withActive?: boolean): Observable<EraIndex[]> =>
api.query.staking?.activeEra api.query.staking?.activeEra
? api.queryMulti<[Option<ActiveEraInfo>, u32]>([ ? api.queryMulti<[Option<ActiveEraInfo>, u32]>([
api.query.staking.activeEra, api.query.staking.activeEra,
api.query.staking.historyDepth api.query.staking.historyDepth
]).pipe( ]).pipe(
map(([activeEraOpt, historyDepth]): EraIndex[] => { map(([activeEraOpt, historyDepth]): EraIndex[] => {
const result: (EraIndex | null)[] = []; const result: EraIndex[] = [];
const max = historyDepth.toNumber(); const max = historyDepth.toNumber();
const activeEra = activeEraOpt.unwrapOrDefault().index.toBn(); const activeEra: BN = activeEraOpt.unwrapOrDefault().index;
let lastEra = activeEra; let lastEra = activeEra;
while (lastEra.gten(0) && (result.length < max)) { while (lastEra.gten(0) && (result.length < max)) {
result.push( if ((lastEra !== activeEra) || (withActive === true)) {
((lastEra !== activeEra) || (withActive === true)) result.push(api.registry.createType('EraIndex', lastEra));
? api.registry.createType('EraIndex', lastEra) }
: null
);
lastEra = lastEra.subn(1); lastEra = lastEra.subn(1);
} }
const startEra = isUndefined(withActive) || isBoolean(withActive)
? new BN(0)
: bnToBn(withActive);
// go from oldest to newest // go from oldest to newest
return result return result.reverse();
.filter((era): era is EraIndex =>
era
? era.gte(startEra)
: false
)
.reverse();
}) })
) )
: of([]) : of([])
+20 -19
View File
@@ -6,8 +6,7 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
import { EraIndex, EraRewardPoints } from '@polkadot/types/interfaces'; import { EraIndex, EraRewardPoints } from '@polkadot/types/interfaces';
import { DeriveEraPoints, DeriveEraValPoints } from '../types'; import { DeriveEraPoints, DeriveEraValPoints } from '../types';
import BN from 'bn.js'; import { Observable, of } from 'rxjs';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util'; import { memo } from '../util';
@@ -22,24 +21,26 @@ function mapValidators ({ individual }: EraRewardPoints): DeriveEraValPoints {
}, {}); }, {});
} }
export function erasPoints (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraPoints[]> { export function _erasPoints (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraPoints[]> {
return memo((withActive?: boolean | number): Observable<DeriveEraPoints[]> => return memo((eras: EraIndex[]): Observable<DeriveEraPoints[]> =>
api.derive.staking.erasHistoric(withActive).pipe( eras.length
switchMap((eras): Observable<[EraIndex[], EraRewardPoints[]]> => ? api.query.staking.erasRewardPoints.multi<EraRewardPoints>(eras).pipe(
combineLatest([ map((points) =>
of(eras), eras.map((era, index): DeriveEraPoints => ({
eras.length era,
? api.query.staking.erasRewardPoints.multi<EraRewardPoints>(eras) eraPoints: points[index].total,
: of([]) validators: mapValidators(points[index])
]) }))
), )
map(([eras, points]): DeriveEraPoints[] =>
eras.map((era, index): DeriveEraPoints => ({
era,
eraPoints: points[index].total,
validators: mapValidators(points[index])
}))
) )
: of([])
);
}
export function erasPoints (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraPoints[]> {
return memo((withActive?: boolean): Observable<DeriveEraPoints[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking._erasPoints(eras))
) )
); );
} }
+11 -10
View File
@@ -6,7 +6,6 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
import { EraIndex, ValidatorPrefs } from '@polkadot/types/interfaces'; import { EraIndex, ValidatorPrefs } from '@polkadot/types/interfaces';
import { DeriveEraPrefs, DeriveEraValPrefs } from '../types'; import { DeriveEraPrefs, DeriveEraValPrefs } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs'; import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
import { StorageKey } from '@polkadot/types'; import { StorageKey } from '@polkadot/types';
@@ -31,16 +30,18 @@ export function eraPrefs (api: ApiInterfaceRx): (era: EraIndex) => Observable<De
); );
} }
export function erasPrefs (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraPrefs[]> { export function _erasPrefs (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraPrefs[]> {
return memo((withActive?: boolean | BN | number): Observable<DeriveEraPrefs[]> => return memo((eras: EraIndex[]): Observable<DeriveEraPrefs[]> =>
eras.length
? combineLatest(eras.map((era) => api.derive.staking.eraPrefs(era)))
: of([])
);
}
export function erasPrefs (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraPrefs[]> {
return memo((withActive?: boolean): Observable<DeriveEraPrefs[]> =>
api.derive.staking.erasHistoric(withActive).pipe( api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras): Observable<DeriveEraPrefs[]> => switchMap((eras) => api.derive.staking._erasPrefs(eras))
eras.length
? combineLatest(
eras.map((era) => api.derive.staking.eraPrefs(era))
)
: of([])
)
) )
); );
} }
+15 -16
View File
@@ -6,30 +6,29 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
import { Balance, EraIndex } from '@polkadot/types/interfaces'; import { Balance, EraIndex } from '@polkadot/types/interfaces';
import { DeriveEraRewards } from '../types'; import { DeriveEraRewards } from '../types';
import BN from 'bn.js'; import { Observable, of } from 'rxjs';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
import { Option } from '@polkadot/types'; import { Option } from '@polkadot/types';
import { memo } from '../util'; import { memo } from '../util';
export function erasRewards (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraRewards[]> { export function _erasRewards (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraRewards[]> {
return memo((withActive?: boolean | BN | number): Observable<DeriveEraRewards[]> => return memo((eras: EraIndex[]): Observable<DeriveEraRewards[]> =>
api.derive.staking.erasHistoric(withActive).pipe( eras.length
switchMap((eras): Observable<[EraIndex[], Option<Balance>[]]> => ? api.query.staking.erasValidatorReward.multi<Option<Balance>>(eras).pipe(
combineLatest([ map((rewards) => eras.map((era, index): DeriveEraRewards => ({
of(eras),
eras.length
? api.query.staking.erasValidatorReward.multi<Option<Balance>>(eras)
: of([])
])
),
map(([eras, rewards]): DeriveEraRewards[] =>
eras.map((era, index): DeriveEraRewards => ({
era, era,
eraReward: rewards[index].unwrapOrDefault() eraReward: rewards[index].unwrapOrDefault()
})) })))
) )
: of([])
);
}
export function erasRewards (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraRewards[]> {
return memo((withActive?: boolean): Observable<DeriveEraRewards[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking._erasRewards(eras))
) )
); );
} }
+13 -10
View File
@@ -7,7 +7,6 @@ import { BalanceOf, EraIndex, Perbill } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types'; import { ITuple } from '@polkadot/types/types';
import { DeriveEraSlashes, DeriveEraValSlash } from '../types'; import { DeriveEraSlashes, DeriveEraValSlash } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs'; import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
import { Option, StorageKey } from '@polkadot/types'; import { Option, StorageKey } from '@polkadot/types';
@@ -40,16 +39,20 @@ export function eraSlashes (api: ApiInterfaceRx): (era: EraIndex) => Observable<
); );
} }
export function erasSlashes (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraSlashes[]> { export function _erasSlashes (api: ApiInterfaceRx): (eras: EraIndex[]) => Observable<DeriveEraSlashes[]> {
return memo((withActive?: boolean | BN | number): Observable<DeriveEraSlashes[]> => return memo((eras: EraIndex[]): Observable<DeriveEraSlashes[]> =>
api.derive.staking.erasHistoric(withActive).pipe( eras.length
switchMap((eras): Observable<DeriveEraSlashes[]> => ? combineLatest(
eras.length eras.map((era) => api.derive.staking.eraSlashes(era))
? combineLatest(
eras.map((era) => api.derive.staking.eraSlashes(era))
)
: of([])
) )
: of([])
);
}
export function erasSlashes (api: ApiInterfaceRx): (withActive?: boolean) => Observable<DeriveEraSlashes[]> {
return memo((withActive?: boolean): Observable<DeriveEraSlashes[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => api.derive.staking._erasSlashes(eras))
) )
); );
} }
+1
View File
@@ -3,6 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details. // of the Apache-2.0 license. See the LICENSE file for details.
export * from './account'; export * from './account';
export * from './currentPoints';
export * from './erasExposure'; export * from './erasExposure';
export * from './erasHistoric'; export * from './erasHistoric';
export * from './erasPoints'; export * from './erasPoints';
+9 -33
View File
@@ -2,51 +2,27 @@
// This software may be modified and distributed under the terms // This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details. // of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, EraPoints, EraRewardPoints, RewardPoint } from '@polkadot/types/interfaces';
import { ApiInterfaceRx } from '@polkadot/api/types'; import { ApiInterfaceRx } from '@polkadot/api/types';
import { DerivedStakingOverview } from '../types'; import { DeriveStakingOverview } from '../types';
import { Observable, combineLatest, of } from 'rxjs'; import { Observable, combineLatest } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { memo } from '../util'; import { memo } from '../util';
function retrievePointsPrev (api: ApiInterfaceRx, currentElected: AccountId[]): Observable<EraRewardPoints> {
return api.query.staking.currentEraPointsEarned<EraPoints>().pipe(
map(({ individual, total }): EraRewardPoints =>
api.registry.createType('EraRewardPoints', {
total,
individual: new Map<AccountId, RewardPoint>(
individual
.map((points): RewardPoint => api.registry.createType('RewardPoint', points))
.map((points, index): [AccountId, RewardPoint] => [currentElected[index], points])
)
})
)
);
}
/** /**
* @description Retrieve the staking overview, including elected and points earned * @description Retrieve the staking overview, including elected and points earned
*/ */
export function overview (api: ApiInterfaceRx): () => Observable<DerivedStakingOverview> { export function overview (api: ApiInterfaceRx): () => Observable<DeriveStakingOverview> {
return memo((): Observable<DerivedStakingOverview> => return memo((): Observable<DeriveStakingOverview> =>
combineLatest([ combineLatest([
api.derive.session.indexes(), api.derive.session.indexes(),
api.derive.staking.validators() api.derive.staking.validators()
]).pipe( ]).pipe(
switchMap(([indexes, { nextElected, validators }]) => map(([indexes, { nextElected, validators }]): DeriveStakingOverview => ({
combineLatest([ ...indexes,
of({ ...indexes, nextElected, validators }), nextElected,
api.query.staking.erasRewardPoints validators
? api.query.staking.erasRewardPoints<EraRewardPoints>(indexes.activeEra)
: api.query.staking.currentEraPointsEarned
? retrievePointsPrev(api, nextElected)
: of(api.registry.createType('EraRewardPoints'))
])
),
map(([info, eraPoints]): DerivedStakingOverview => ({
...info, eraPoints
})) }))
)); ));
} }
@@ -5,14 +5,13 @@
import { ApiInterfaceRx } from '@polkadot/api/types'; import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveOwnExposure } from '../types'; import { DeriveOwnExposure } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs'; import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util'; import { memo } from '../util';
export function ownExposure (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean | BN | number) => Observable<DeriveOwnExposure[]> { export function ownExposure (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveOwnExposure[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean | BN | number): Observable<DeriveOwnExposure[]> => { return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveOwnExposure[]> => {
return api.derive.staking.erasHistoric(withActive).pipe( return api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => switchMap((eras) =>
eras.length eras.length
@@ -5,14 +5,13 @@
import { ApiInterfaceRx } from '@polkadot/api/types'; import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveStakerSlashes } from '../types'; import { DeriveStakerSlashes } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs'; import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util'; import { memo } from '../util';
export function ownSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean | BN | number) => Observable<DeriveStakerSlashes[]> { export function ownSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean) => Observable<DeriveStakerSlashes[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean | BN | number): Observable<DeriveStakerSlashes[]> => { return memo((accountId: Uint8Array | string, withActive?: boolean): Observable<DeriveStakerSlashes[]> => {
return api.derive.staking.erasHistoric(withActive).pipe( return api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) => switchMap((eras) =>
eras.length eras.length
@@ -30,9 +29,7 @@ export function ownSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | strin
era, era,
total: optVal.isSome total: optVal.isSome
? optVal.unwrap()[1] ? optVal.unwrap()[1]
: optNom.isSome : optNom.unwrapOrDefault()
? optNom.unwrap()
: api.registry.createType('Balance')
})) }))
) )
); );
+28 -17
View File
@@ -5,7 +5,7 @@
import { ApiInterfaceRx } from '@polkadot/api/types'; import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId, Exposure, Keys, Nominations, RewardDestination, ValidatorPrefs } from '@polkadot/types/interfaces'; import { AccountId, Exposure, Keys, Nominations, RewardDestination, ValidatorPrefs } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types'; import { ITuple } from '@polkadot/types/types';
import { DerivedStakingQuery } from '../types'; import { DeriveStakingQuery } from '../types';
import { Observable, combineLatest, of } from 'rxjs'; import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators'; import { map, switchMap } from 'rxjs/operators';
@@ -55,13 +55,13 @@ function retrieveCurr (api: ApiInterfaceRx, stashId: AccountId): Observable<Mult
); );
} }
function retrieveController (api: ApiInterfaceRx, stashId: AccountId, [queuedKeys, [controllerIdOpt, nominatorsOpt, rewardDestination, validatorPrefs, nextKeys, exposure]]: [Vec<ITuple<[AccountId, Keys]>>, MultiResult]): Observable<DerivedStakingQuery> { function retrieveController (api: ApiInterfaceRx, stashId: AccountId, queuedKeys: Vec<ITuple<[AccountId, Keys]>>, [controllerIdOpt, nominatorsOpt, rewardDestination, validatorPrefs, nextKeys, exposure]: MultiResult): Observable<DeriveStakingQuery> {
const controllerId = controllerIdOpt.unwrapOr(null); const controllerId = controllerIdOpt.unwrapOr(null);
const nominators = nominatorsOpt.unwrapOr(null); const nominators = nominatorsOpt.unwrapOr(null);
return controllerId return controllerId
? api.query.staking.ledger(controllerId).pipe( ? api.query.staking.ledger(controllerId).pipe(
map((stakingLedgerOpt): DerivedStakingQuery => ({ map((stakingLedgerOpt): DeriveStakingQuery => ({
accountId: stashId, accountId: stashId,
controllerId, controllerId,
exposure, exposure,
@@ -82,30 +82,41 @@ function retrieveController (api: ApiInterfaceRx, stashId: AccountId, [queuedKey
: of({ accountId: stashId, nextSessionIds: [], sessionIds: [] }); : of({ accountId: stashId, nextSessionIds: [], sessionIds: [] });
} }
/** export function queryWithQueued (api: ApiInterfaceRx): (accountId: Uint8Array | string, queuedKeys: Vec<ITuple<[AccountId, Keys]>>) => Observable<DeriveStakingQuery> {
* @description From a stash, retrieve the controllerId and all relevant details return memo((accountId: Uint8Array | string, queuedKeys: Vec<ITuple<[AccountId, Keys]>>): Observable<DeriveStakingQuery> => {
*/
export function query (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DerivedStakingQuery> {
return memo((accountId: Uint8Array | string): Observable<DerivedStakingQuery> => {
const stashId = api.registry.createType('AccountId', accountId); const stashId = api.registry.createType('AccountId', accountId);
return combineLatest([ return (
api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>(),
api.query.staking.erasStakers api.query.staking.erasStakers
? retrieveCurr(api, stashId) ? retrieveCurr(api, stashId)
: retrievePrev(api, stashId) : retrievePrev(api, stashId)
]).pipe( ).pipe(
switchMap((result): Observable<DerivedStakingQuery> => switchMap((result): Observable<DeriveStakingQuery> =>
retrieveController(api, stashId, result) retrieveController(api, stashId, queuedKeys, result)
) )
); );
}); });
} }
export function queryMulti (api: ApiInterfaceRx): (...accountIds: (Uint8Array | string)[]) => Observable<DerivedStakingQuery[]> { /**
return memo((...accountIds: (Uint8Array | string)[]): Observable<DerivedStakingQuery[]> => * @description From a stash, retrieve the controllerId and all relevant details
combineLatest( */
accountIds.map((accountId) => api.derive.staking.query(accountId)) export function query (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DeriveStakingQuery> {
return memo((accountId: Uint8Array | string): Observable<DeriveStakingQuery> =>
api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>().pipe(
switchMap((queuedKeys) => api.derive.staking.queryWithQueued(accountId, queuedKeys))
) )
); );
} }
export function queryMulti (api: ApiInterfaceRx): (accountIds: (Uint8Array | string)[]) => Observable<DeriveStakingQuery[]> {
return memo((accountIds: (Uint8Array | string)[]): Observable<DeriveStakingQuery[]> =>
accountIds.length
? api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>().pipe(
switchMap((queuedKeys) => combineLatest(
accountIds.map((acc) => api.derive.staking.queryWithQueued(acc, queuedKeys))
))
)
: of([])
);
}

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