Compare commits

..
133 Commits
Author SHA1 Message Date
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
Github Actions eb3e7a0740 [CI Skip] 1.8.1
skip-checks: true
2020-03-22 17:58:16 +00:00
Jaco Greeff 2071de517d 1.8 (#2079) 2020-03-22 18:47:04 +01:00
Github Actions 205ae40f20 [CI Skip] 1.8.0-beta.12
skip-checks: true
2020-03-22 17:27:07 +00:00
Keith IngramandJaco Greeff aa37e372dd Derived account info flags (#2068)
* Derived account info flags

* Update packages/api-derive/src/accounts/info.ts

Co-Authored-By: Jaco Greeff <jacogr@gmail.com>

* Apply suggestions from code review

* Cleanups

Co-authored-by: Jaco Greeff <jacogr@gmail.com>
2020-03-22 18:16:43 +01:00
Github Actions 8cdac77a8e [CI Skip] 1.8.0-beta.11
skip-checks: true
2020-03-22 10:15:48 +00:00
Jaco Greeff 7a7d6e9b8a New democracy types (#2078)
* New democracy types

* ReferendumInfo

* Adjust democracy derives

* Spring cleaning

* Remove ReferendumInfoExtended
2020-03-22 11:05:57 +01:00
Github Actions 7a1bdb18a8 [CI Skip] 1.8.0-beta.10
skip-checks: true
2020-03-22 06:57:07 +00:00
Jaco Greeff 39f22ca403 Control wasm initialization via initWasm: false flag (#2076) 2020-03-22 07:45:22 +01:00
Github Actions b3c6a5acc5 [CI Skip] 1.8.0-beta.9
skip-checks: true
2020-03-22 06:43:14 +00:00
Jaco Greeff b3a6b3dcb5 Bump dev, arrow functions (#2077) 2020-03-22 07:31:55 +01:00
Github Actions 0c0e4c4d7c [CI Skip] 1.8.0-beta.8
skip-checks: true
2020-03-21 08:51:26 +00:00
Jaco Greeff 9d67d711d4 Bump deps, type import on generated (#2075)
* Bump deps, type import on generated

* type imports in types/types

* Re-export defs

* Split imports/exports

* Additional type import

* Remove import type

* Remove dupes
2020-03-21 09:40:59 +01:00
Github Actions f45d03fa17 [CI Skip] 1.8.0-beta.7
skip-checks: true
2020-03-21 07:00:35 +00:00
Jaco Greeff af11444b72 Update RPCs (babe, contracts) (#2074)
* Update RPCs (babe, contracts)

* Babe in rpc-core
2020-03-21 07:50:56 +01:00
Github Actions f412a5ac86 [CI Skip] 1.8.0-beta.6
skip-checks: true
2020-03-20 16:50:04 +00:00
Jaco Greeff c9dcd51ba6 is isWarning to ISubmittableResult (#2073) 2020-03-20 17:40:09 +01:00
Jaco Greeff 5dca826429 Retracted status to isWarning 2020-03-20 17:27:18 +01:00
Github Actions 8dc53e6339 [CI Skip] 1.8.0-beta.5
skip-checks: true
2020-03-20 15:41:13 +00:00
Jaco Greeff 5867f8ab0c Allow unknown struct fields (i.e. on Map, non-codec) (#2071) 2020-03-20 16:30:29 +01:00
Github Actions 6d3db2fb3f [CI Skip] 1.8.0-beta.4
skip-checks: true
2020-03-20 12:52:46 +00:00
Jaco Greeff 3a1634d67f Add all missing RPC endpoints (#2070)
* Add all missing RPC endpoints

* Rework RPC return types

* rpc-core interface

* Remove crap test, checked anyway
2020-03-20 13:42:18 +01:00
Github Actions 53d18d874d [CI Skip] 1.8.0-beta.3
skip-checks: true
2020-03-19 13:51:15 +00:00
Jaco Greeff 044efbc6de Convert jsonrpc & typings to definitions (#2064)
* Convert jsonrpc & typings to definitions

* Handle empty interface generation (no types)

* Move jsonrpc/create to rpc-core/create

* Create imports

* Remove jsonrpc package, generate rpc-core from defs

* Debug :)

* Generate RPC definitions via interfaces

* Generate md docs

* Remove @polkadot/jsonrpc refs (at least packages)

* No empty types

* Add PAHNTOM "cleanup" gen

* *sigh* regex loop

* Update mock for no jsonrpc

* Add definition export types

* Cleanup linting

* Mocking 1 fix

* Mocking 2 fix

* rpc-core tests updates

* CHANGELOG & docs

* Add jsonrpc (already mapped) to interfaces

* Add aliasses for RPCs

* Fix rpc-core tests
2020-03-19 14:40:54 +01:00
Github Actions 27e3fbfd0f [CI Skip] 1.8.0-beta.2
skip-checks: true
2020-03-18 21:50:49 +00:00
Jaco Greeff b7af4781ea Add Initialization to extrinsic phases (#2063) 2020-03-18 22:40:53 +01:00
Github Actions c51e351117 [CI Skip] 1.8.0-beta.1
skip-checks: true
2020-03-17 23:18:54 +00:00
Jaco Greeff e6afed9bb1 Allow electedInfo commition with/without linked maps (#2060) 2020-03-18 00:08:49 +01:00
Github Actions 4b07d5511e [CI Skip] 1.8.0-beta.0
skip-checks: true
2020-03-17 18:46:06 +00:00
Jaco Greeff a613308bdb Update 2020-03-17 19:34:51 +01:00
Jaco Greeff a863e5eb95 Non-array nominators 2020-03-17 19:22:16 +01:00
Github Actions 623420ca3d [CI Skip] 1.7.1
skip-checks: true
2020-03-17 13:49:41 +00:00
Jaco Greeff 9ea6053a42 1.7 (#2059) 2020-03-17 14:39:20 +01:00
Github Actions 73dce6bfd1 [CI Skip] 1.7.0-beta.19
skip-checks: true
2020-03-17 09:48:02 +00:00
Jaco Greeff 5a7811c80f Bump metadata (#2058)
* Bump metadata

* Add missing @types/jest

* Update tests for new metadata

* CHANGELOG for linked map removals

* expand re-added check
2020-03-17 10:37:24 +01:00
Github Actions 1c529bdc6a [CI Skip] 1.7.0-beta.18
skip-checks: true
2020-03-16 14:47:43 +00:00
Jaco Greeff 3f4576f524 Add yarn matrix (#2057) 2020-03-16 15:37:23 +01:00
Github Actions 2619489ec3 [CI Skip] 1.7.0-beta.17
skip-checks: true
2020-03-16 13:59:34 +00:00
Jaco Greeff f165845cc3 Collapse actions matrix (#2056) 2020-03-16 14:49:31 +01:00
Github Actions 897f03e4c1 [CI Skip] 1.7.0-beta.16
skip-checks: true
2020-03-16 10:24:34 +00:00
Jaco Greeff 82c1e3f35a Cater for new non-linked map validator queries (#2055)
* Cater for new non-linked map validator queries

* Update staking tests

* stakers -> stashes
2020-03-16 11:13:46 +01:00
Github Actions c06f260d3c [CI Skip] 1.7.0-beta.15
skip-checks: true
2020-03-16 07:23:55 +00:00
Jaco Greeff 63573ca0de Add ownExposure & ownSlashes (#2054) 2020-03-16 08:15:00 +01:00
Github Actions bf1a5f0d91 [CI Skip] 1.7.0-beta.14
skip-checks: true
2020-03-15 19:39:52 +00:00
Wei Tang 1750522cb6 Use /usr/bin/env bash instead of /bin/bash (#2053) 2020-03-15 20:29:45 +01:00
Github Actions ed3b507ea6 [CI Skip] 1.7.0-beta.13
skip-checks: true
2020-03-15 17:00:01 +00:00
Jaco Greeff f942510309 Expose stakerSlahes & eraSlashes (#2052) 2020-03-15 17:49:15 +01:00
Github Actions 09a9153645 [CI Skip] 1.7.0-beta.12
skip-checks: true
2020-03-15 09:03:36 +00:00
Jaco Greeff 908d0fcf52 Add missing commission to payout calculations (#2051)
* Add missing comission to payout calcs

* yarn

* Bump dev with version update fix
2020-03-15 09:51:52 +01:00
Github Actions 707c93a557 [CI Skip] 1.7.0-beta.11
skip-checks: true
2020-03-15 07:36:51 +00:00
Jaco Greeff 82addc4f6a Remove non-working CI cache (#2050) 2020-03-15 08:26:34 +01:00
Github Actions d595eb440c [CI Skip] 1.7.0-beta.10
skip-checks: true
2020-03-14 08:49:03 +00:00
Jaco Greeff e86fe5bab0 Bump deps (#2048) 2020-03-14 09:37:28 +01:00
Github Actions 7187dca2f7 [CI Skip] 1.7.0-beta.9
skip-checks: true
2020-03-13 20:17:16 +00:00
Jaco Greeff 94a3b1f09a eraPoints args (#2047) 2020-03-13 21:05:40 +01:00
Github Actions d88b300a6d [CI Skip] 1.7.0-beta.8
skip-checks: true
2020-03-13 18:52:54 +00:00
Jaco Greeff dd217f82b2 Chunk keys & values retrievals on keys()/entries() (#2046)
* Chunk keys & values retrievals on keys()/entries()

* Bump chunk sizes

* Fix concatMap index

* Update mock
2020-03-13 19:40:57 +01:00
Github Actions 3b4cee08e2 [CI Skip] 1.7.0-beta.7
skip-checks: true
2020-03-13 17:07:31 +00:00
Joshy Orndorff 34be2399eb Couple little typo fixes (#2045) 2020-03-13 17:54:29 +01:00
Github Actions 27d879a325 [CI Skip] 1.7.0-beta.6
skip-checks: true
2020-03-13 12:51:33 +00:00
Jaco Greeff 4093ef9ffa Add Identity hasher (#2044)
* Add Identity hasher

* Expand new V11 storage types

* Cleanups, use actual enum keys

* Sort augmented output (fy-by enhancement)

* Map get

* DEFAULT_FN
2020-03-13 13:39:34 +01:00
Github Actions 261eebee03 [CI Skip] 1.7.0-beta.5
skip-checks: true
2020-03-13 11:45:14 +00:00
Jaco Greeff d9dad3566a Use asyncScheduler for all derives (#2043) 2020-03-13 12:32:42 +01:00
Github Actions 3d0fdbd6da [CI Skip] 1.7.0-beta.4
skip-checks: true
2020-03-13 07:56:43 +00:00
Jaco Greeff affa5d390c Expose derive staking.nextElected (#2042) 2020-03-13 08:45:28 +01:00
Github Actions 1659e672ae [CI Skip] 1.7.0-beta.3
skip-checks: true
2020-03-13 07:05:20 +00:00
Jaco Greeff 0fa6b99c9e Query docs with entries & keys, submittable with paymentInfo (#2041) 2020-03-13 07:52:53 +01:00
Github Actions ef9db7bf78 [CI Skip] 1.7.0-beta.2
skip-checks: true
2020-03-13 05:45:54 +00:00
Jaco Greeff 8c6505d870 Map signs directly to H512 (no indirection) (#2038) 2020-03-13 06:34:46 +01:00
Github Actions 48f83c7d5b [CI Skip] 1.7.0-beta.1
skip-checks: true
2020-03-12 21:11:11 +00:00
Jaco Greeff f3c2c5c084 Re-enable argument checks (dropped in 1.6.2) (#2035)
* Re-enable argument checks (dropped in 1.6.2)

* typo

* Bump to preminor
2020-03-12 21:58:57 +01:00
Jaco Greeff 98e1cc3f73 Add staking.eraExposure derive (#2036) 2020-03-12 21:57:17 +01:00
Github Actions 4fd74a04c8 [CI Skip] 1.6.2
skip-checks: true
2020-03-12 14:03:53 +00:00
Jaco Greeff 421594b0eb Fix .at check, disable (release 1.6.2) (#2034)
* Fix .at check, disable (release 1.6.2)

* Remove isAt (keep at revert only)

* Grrr....

* yarn installl (really need to add this to version bump script)
2020-03-12 14:53:25 +01:00
326 changed files with 9334 additions and 7163 deletions
+2 -1
View File
@@ -1,2 +1,3 @@
20
21
1.4.2
1.6.2
+7 -99
View File
@@ -2,110 +2,18 @@ name: PR
on: [pull_request]
jobs:
lint:
name: Linting
runs-on: ubuntu-latest
pr:
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Config yarn cache
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v1
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: lint
run: |
yarn install --immutable | grep -v 'YN0013'
yarn lint
test:
name: Testing
step: ['lint', 'test', 'build', 'docs']
name: ${{ matrix.step }}
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Config yarn cache
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v1
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: test
node-version: '12.x'
- name: ${{ matrix.step }}
run: |
yarn install --immutable | grep -v 'YN0013'
yarn test
build_code:
name: Build Code
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Config yarn cache
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v1
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: build
run: |
yarn install --immutable | grep -v 'YN0013'
yarn build
build_docs:
name: Build Docs
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Config yarn cache
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v1
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: build
run: |
yarn install --immutable | grep -v 'YN0013'
yarn docs
yarn ${{ matrix.step }}
+10 -56
View File
@@ -5,82 +5,36 @@ on:
- master
jobs:
build_code:
name: Build Code
if: "! contains(github.event.head_commit.message, '[CI Skip]')"
runs-on: ubuntu-latest
master:
strategy:
matrix:
node-version: [12.x]
step: ['build:release', 'docs:release']
name: ${{ matrix.step }}
if: "! contains(github.event.head_commit.message, '[CI Skip]') && github.repository == 'polkadot-js/api'"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
with:
token: ${{ secrets.GH_PAT }}
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Config yarn cache
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v1
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: build
node-version: '12.x'
- name: ${{ matrix.step }}
env:
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
GH_PAGES_SRC: build-docs
GH_PAT: ${{ secrets.GH_PAT }}
GH_TOKEN: ${{ secrets.GH_PAT }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
yarn install --immutable | grep -v 'YN0013'
yarn polkadot-ci-ghact-build
build_docs:
name: Build Docs
if: "! contains(github.event.head_commit.message, '[CI Skip]')"
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Config yarn cache
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v1
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: build
env:
GH_PAT: ${{ secrets.GH_PAT }}
GH_TOKEN: ${{ secrets.GH_PAT }}
GH_PAGES_SRC: build-docs
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
yarn install --immutable | grep -v 'YN0013'
yarn polkadot-ci-ghact-docs
yarn ${{ matrix.step }}
dummy:
name: Dummy
if: "contains(github.event.head_commit.message, '[CI Skip]')"
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
steps:
- name: dummy
run: |
-58
View File
File diff suppressed because one or more lines are too long
Vendored Executable
+50
View File
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -1,4 +1,5 @@
enableImmutableInstalls: false
enableProgressBars: false
nodeLinker: node-modules
@@ -7,4 +8,4 @@ plugins:
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.js
spec: "@yarnpkg/plugin-interactive-tools"
yarnPath: .yarn/releases/yarn-berry.js
yarnPath: .yarn/releases/yarn-rc.js
+42 -1
View File
@@ -1,6 +1,47 @@
# 1.9.1 Apr 1, 2020
**Breaking change** (TypeScript with derives only) The return type names for `api.derive.*` have been adjusted for consistency, all starting with `Derive*` (previously a mixture of `Derived*` and `Derive*`)
**Breaking change** (derives only) Additional cleanups of democracy proposal & referenda derives, including support for new Polkadot/Substrate vote retrievals
- Tx signing via `signAndSend` & `signAsync` now tries to use the last finalized block (depending on finalized drift)
- Add support for `api.rpc.childstate.*` Substrate RPCs, older nodes with still populate `api.rpc.state.*` with the child methods
- Adjust `Error.message` on RPC failures to not include the (already known) method signature
- Split `@polkadot/types/known` into `@polkadot/types-known`, allowing for base API overrides
- Extended `api.derive.democracy` to cater for dispatchQueue and externals
- Extended `api.derive.council` to cater for new phragmen elections
- Use new `queryStorageAt` for query `.entries`, removing unneeded subscriptions (use as available)
- Fix `BTreeSet` initialization when it forms part of query interfaces
- Fix encoding for `Vec<u8>`-related types as part of constants
- Internal adjustment of interface type locations (no impact on imports via `@polkadot/types/interfaces`)
# 1.8.1 Mar 22, 2020
- **Breaking change** The format for any custom RPCs have been changed (alongside API-internal changes) to allow for better RPC management. If you are currently using custom RPCs (or planning to do so), look at the [updated documentation](https://polkadot.js.org/api/start/rpc.custom.html)
- **Breaking change** Alongside API RPC changes, the `@polkadot/jsonrpc` package has been removed. Since it was never documented and only used internally, this should not have adverse impacts. All RPC definitions itself has now been moved to the relevant modules inside `@polkadot/types/interfaces`
- **Important** Substrate has an updated democracy module. If using an older chain add the `ReferendumInfo: 'ReferendumInfoTo239'` type when using referendums
- The `isRetracted` Extrinsic status is now a warning, not a fatal error, correctly aligning with Polkadot/Substrate
- The Substrate extrinsic phase definitions has been expanded with `Initialization` to align with the latest versions
- Add support for all known substrate RPC methods
- Extend account derives to include status flags, e.g. `isCouncil`, `isSudo`, ...
- Adjusted referendum derives to cater for bot new/old democracy. Derived `referendumInfo` now includes `status` field, not `info`
- Add `initWasm` flag to API options. When set to `false` does not init the WASM portion (leaving it to the user elsewhere)
# 1.7.1 Mar 17, 2020
- **Important** Current versions of Polkadot/Substrate have dropped support for linked maps on storage entries. If you are using these queries to retrieve all entries, for instance `staking.{nominators,validators}()` and using an upgraded chain, you need to swap to retrieving entries via `.entries()` or `.keys()` for the keys.
- Pull in support and types for latest Polkadot/Substrate
- Add support for the new Substrate `state_getKeysPaged` RPC, including use in storage keys
- Move `derive.staking.controllers` to `derive.staking.stashes`, reflecting actual content
- Cater for adjusted storage (non-linked mapped) for `derive.staking.stashes` queries (with old-compat)
- Expanded `derive.staking.*` derives, including addition of `derive.staking.own*`
- Re-add fixed (with tests) checks for query args, previously disabled in 1.6.2
# 1.6.2 Mar 12, 2020
- Revert checks for query args, not working on `.at()` queries (proper fix in next version)
# 1.6.1 Mar 12, 2020
- **Breaking change** `api.rpc.state.queryStorage(...)` now full decodes the `Vec<StorageChangeSet>` and returns a decoded `[Hash, Codec[]][]` when using this RPC.
- **Breaking change** `api.rpc.state.queryStorage(...)` now fully decodes the `Vec<StorageChangeSet>` and returns a decoded `[Hash, Codec[]][]` when using this RPC.
- `StorageKey` now has an `.args` property, decoded from meta where `twox64_concat` or `blake128_concat` are used on maps
- Fix `api.query.*.*.entries` type conversions to return exact types (not `Option` in some cases)
- Add `api.query.*.*.keys` to retrieve only the storage keys, similar to `.entries`
+1 -2
View File
@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
function copy_folder () {
SRC="packages/$1/build"
@@ -18,6 +18,5 @@ copy_folder "api-derive"
copy_folder "metadata"
copy_folder "rpc-core"
copy_folder "rpc-provider"
copy_folder "jsonrpc"
copy_folder "types"
copy_folder "typegen"
+1
View File
@@ -43,6 +43,7 @@ module.exports = {
['start/api.tx.wrap.md', 'Complex transactions'],
['start/types.basics.md', 'Type basics'],
['start/types.extend.md', 'Extending types'],
['start/rpc.custom.md', 'Custom RPC'],
['start/types.create.md', 'Creating types'],
['start/typescript.md', 'TypeScript interfaces'],
['start/typescript.user.md', 'TypeScript user generated'],
@@ -24,7 +24,7 @@ async function main () {
if (validators && validators.length > 0) {
// Retrieve the balances for all validators
const validatorBalances = await Promise.all(
validators.map(authorityId =>
validators.map((authorityId) =>
api.query.system.account(authorityId)
)
);
+1 -1
View File
@@ -22,7 +22,7 @@ function main () {
// In the next step, we're checking if the node has active validators.
// If it does, we're making another call to the api to get the balances for all validators
const balances = (validators && validators.length > 0)
? combineLatest(validators.map(authorityId => api.query.system.account(authorityId).pipe(first())))
? combineLatest(validators.map((authorityId) => api.query.system.account(authorityId).pipe(first())))
: of(null);
// We're combining the results together with the emitted value 'validators',
-5
View File
@@ -1,5 +0,0 @@
... somewhere also need a signer injection section, something along the lines of the singlesigner or this https://github.com/polkadot-js/tools/blob/master/packages/signer-cli/src/cmdSubmit.ts#L12
... DoubleMap & LinkedMap examples
... api.derive
+10 -2
View File
@@ -34,13 +34,13 @@ To submit these transactions, it needs to be send as a [wrapped transaction](api
## How do I call a function with a Tuple input
Tuples, as defined in the Polkadot/Substrate types appear as `(TypeA, TypeB)`. For instance we may have an `(AccountId, u64)` input as defined in the metadata or as part of the user types. To specify a Tuple as an input, wrap it is an array format, for instance to call `query.module.get((u32, u64))` where a `(u32, u64)` Tuple input is expected, you would do `query.module.get([123, 456])`
Tuples, as defined in the Polkadot/Substrate types appear as `(TypeA, TypeB)`. For instance we may have an `(AccountId, u64)` input as defined in the metadata or as part of the user types. To specify a Tuple as an input, wrap it in an array format, for instance to call `query.module.get((u32, u64))` where a `(u32, u64)` Tuple input is expected, you would do `query.module.get([123, 456])`
## How long do transactions live
Polkadot/Substrate supports both immortal and mortal transactions. For immortal, this means that the transaction has an infinite lifetime, for mortals, the transactions expire after a defined period. By default the API sends mortal transactions when no explicit extrinsic era has been specified. This means that all transaction has a limited lifetime and will expire if not included in the period set.
The length for this transaction validity is set to 50 blocks, which translates to 5 minutes assuming a default of 6 second blocktimes. (10 blocks per minute in this default configuration).
The length for this transaction validity is set to 5 minutes, calculated based on the blocktime for the chain. (10 blocks per minute in this default 6s Substrate configuration).
## My chain does not support system.account queries
@@ -49,3 +49,11 @@ The API always tracks the latest Substrate master in terms of examples. This mea
It is possible that you are connecting to an older chain that has not been upgraded yet. For these chains, this storage entry won't be available (yet). To query the nonce on older chains, you can do a query to `api.query.system.accountNonce(<account>)` and balances can be retrieved via `api.query.balances.freeBalance(<account>)`.
Likewise, if your chain has been upgraded recently and you are still using the old `system.accountNonce` or `balances.freeBalance` queries in your code (which is now not available in the chain metadata), you need to update it to query the new location.
## I cannot send transactions from my node-template-based chain
For the API defaults, the API always the type definitions as specified by the Substrate master fully-featured node. This means that any customizations needs to be applied as types should there be differences in specific user-implementations.
The Substrate node-template has added customizations for some types in the default template, specifically around the `Address` and `Lookup` types, removing indices lookups from addresses. This means that the transaction payload saves 2 bytes for a transfer and is an approach followed by other chains as well, notably Polkadot & Kusama.
Due to these customizations and differences that bleed through to the transaction formats, out-of-the-box the node-template will have issues when sending transactions. To fix this, you would need to add [the customized Address types into your API](types.extend.md#impact-on-extrinsics) instances (or UIs), allowing the API to have the information required to adjust the encoding.
+41 -1
View File
@@ -22,7 +22,7 @@ const [{ data: balanceNow }, { data: balancePrev }] = await Promise.all([
console.log(`The delta was ${balanceNow.free.sub(balancePrev.free)}`);
```
In the above example, we introduce the `.at(<hash>[, ...params])` query. For all `.at` queries, the first parameter is always the block hash at which we want to make the query, in our example we use both the last retrieved block and the parent thereof. The params are optional as per the type of query made, for instance to retrieve the timestamp for a previous block, it would be -
In the above example, we introduce the `.at(<hash>[, ...params]): Type` query. For all `.at` queries, the first parameter is always the block hash at which we want to make the query, in our example we use both the last retrieved block and the parent thereof. The params are optional as per the type of query made, for instance to retrieve the timestamp for a previous block, it would be -
```js
...
@@ -35,6 +35,46 @@ The `.at` queries are all single-shot, i.e. there are no subscription option to
An additional point to take care of (briefly mentioned above), is state pruning. By default a Polkadot/Substrate node will only keep state for the last 256 blocks, unless it is explicitly run in archive mode. This means that querying state further back than the pruning period will result in an error returned from the Node. (Generally most public RPC nodes only run with default settings, which includes aggressive state pruning)
## State for a range of blocks
In addition to the `.at` queries, you can also query state starting at a specific historic block and up to either a specified or the latest blocks. This is done via the `.range([from, to?], <...opt params>): [Hash, Type][]` query. As an example -
```js
...
// Retrieve the current block header
const lastHdr = await api.rpc.chain.getHeader();
const startHdr = await api.rpc.chain.getBlockHash(lastHdr.number.unwrap().subn(500));
// retrieve the range of changes
const changes = await api.query.system.account.range([startHdr]);
changes.forEach(([hash, value]) => {
console.log(hash.toHex(), value.toHuman());
});
```
## Map keys & entries
When working maps and double-maps, it is possible to retrieve a list of all the keys and entries for the map. For this we can use the `.entries(<args>): [StorageKey, Type][]` queries. For example we may want to know the current list of validator exposures at a current era in the staking module -
```js
...
// Retrieve the active era
const activeEra = await api.query.staking.activeEra();
// retrieve all exposures int the active era
const exposures = await api.query.staking.erasStakers.entries(activeEra.index);
exposures.forEach(([key, exposure]) => {
console.log('key arguments:', key.args.map((k) => k.toHuman()));
console.log(' exposure:', exposure.toHuman());
});
```
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.
## State entries
In addition to using `api.query` to make actual on-chain queries, it can also be used to retrieve some information on the state entries. For instance to retrieve both the hash and size of an existing entry, we can make the following calls -
+17
View File
@@ -62,6 +62,23 @@ const unsub = await api.tx.balances
Be aware that when a transaction status is `isFinalized`, it means it is included, but it may still have failed - for instance if you try to send a larger amount that you have free, the transaction is included in a block, however from a end-user perspective the transaction failed since the transfer did not occur. In these cases a `system.ExtrinsicFailed` event will be available in the events array.
## Payment information
The Polkadot/Substrate RPC endpoints exposes weight/payment information that takes an encoded extrinsic and calculates the on-chain weight fees for it. A wrapper for this is available on the tx itself, taking exactly the same parameters as you would pass to a normal `.signAndSend` operation, specifically `.paymentInfo(sender, <any options>)`. To expand on our previous example -
```js
// construct a transaction
const transfer = api.tx.balances.transfer(BOB, 12345);
// retrieve the payment info
const { partialFee, weight } = await transfer.paymentInfo(alice);
console.log(`transaction will have a weight of ${weight}, with ${partialFee.toHuman()} weight fees`);
// send the tx
transfer.signAndSend(alice, ({ events = [], status }) => { ... });
```
## Complex transactions
In many cases transactions can carry quite complex information, be it for passing objects or proposing changes. In the next section we will take a dive [into complex transactions, including those wrapped for sudo](api.tx.wrap.md).
+51
View File
@@ -0,0 +1,51 @@
# Custom RPC
In previous sections we looked at the injection of types, as in use and defined in modules from the node. Another area that can be customized is RC definitions, and like with the types, the API provides the capability to add user-defined RPCs (in addition to the Polkadot/Substrate base) to allow use of these RPCs via the API.
## Custom definitions
RPCs are exposed as a method on a specific module, this means that once available you can call any rpc via the `api.rpc.<module>.<method>(...params[])` endpoints. To extend with user-defined RPCs, the injection can happen at the time of API creation with the addition of the `rpc` key (in addition to any other params, such as `types` or `provider`) -
```js
...
const api = await ApiPromise.create({
rpc: {
firstModule: {
testMethod: {
description: 'Just a test method',
params: [
{
name: 'index',
type: 'u64'
}
],
type: 'Balance'
}
}
}
});
```
In the above example we have defined a new method, which is now available on the RPCs as `api.rpc.firstModule.testMethod(u64) => Promise<Balance>`. Do be aware that while defined, the method will only appear if it is in the list as returned by `api.rpc.rpc.methods()`, which is the list of known RPCs the node exposes. When making changes to the node, always ensure that it does expose the RPC method correctly, otherwise it will not be decorated.
## Definition breakdown
While the above example should be self-explanatory, it is important to understand teh structure. The `rpc: { ... }` definitions are keyed first and foremost by the name of the module exposing the RPC. This means that when we have 2 modules `firstModule` & `testModule`, the first-level structure would follow the following pattern,
```js
...
const api = await ApiPromise.create({
rpc: {
firstModule: { ... },
testModule: { ... }
}
});
```
Inside the specific module definitions, the key is the actual expose RPC method. As we have seen in the first example, we expose a `testMethod` on `firstModule`. For the method definitions, apart from the description, we have definitions for the params and return a single result `type`.
Params itself, as an array, contains fields for `name`, `type` and an optional flag `isOptional` that indicates that the field is not required when making the call. (And example of this use would be in cases such as `state.getStorage(key, blockHash?)` where the last param is optional)
## Type creation
While the API always converts all the inputs into the underlying type required by the operation, be it for RPC, query or transaction, in some cases you may want to [create an instance of a type](types.create.md) yourself.
+2 -2
View File
@@ -201,6 +201,6 @@ const api = await ApiPromise.create({
Always look at customization and understand the impacts, replicating these changes between the node and the API. For the above the `Address` type is used in the construction of the `UncheckedExtrinsic` type, while the lookup type is applicable on transactions such as `balances.transfer(to: LookupSource, value: Balance)`
## Type creation
## Custom RPC
While the API always converts all the inputs into the underlying type required by the operation, in some cases you may want to [create an instance of a type](types.create.md) yourself.
In addition to customizing modules and types on your node, you can also add custom RPC definitions. Like the type definitions in ths section, [these can be defined and passed to the API](rpc.custom.md) for decoration.
+1 -1
View File
@@ -1,6 +1,6 @@
# TypeScript user generated
In the previous section we looked at the TypeScript definitions that are available and is generated from both the chain and definitions. Here we will expand upon the use of the infrastructure created to define types as part of the `@polkadot/types` library and see how to use them to generate your onw definitions and chain types.
In the previous section we looked at the TypeScript definitions that are available and is generated from both the chain and definitions. Here we will expand upon the use of the infrastructure created to define types as part of the `@polkadot/types` library and see how to use them to generate your own definitions and chain types.
## Definitions
+3 -13
View File
@@ -7,30 +7,20 @@ module.exports = Object.assign({}, config, {
'@polkadot/api-contract(.*)$': '<rootDir>/packages/api-contract/src/$1',
'@polkadot/api-derive(.*)$': '<rootDir>/packages/api-derive/src/$1',
'@polkadot/api(.*)$': '<rootDir>/packages/api/src/$1',
'@polkadot/jsonrpc(.*)$': '<rootDir>/packages/jsonrpc/src/$1',
'@polkadot/metadata(.*)$': '<rootDir>/packages/metadata/src/$1',
'@polkadot/rpc-(core|provider)(.*)$': '<rootDir>/packages/rpc-$1/src/$2',
'@polkadot/types-known(.*)$': '<rootDir>/packages/types-known/src/$1',
'@polkadot/types(.*)$': '<rootDir>/packages/types/src/$1'
},
modulePathIgnorePatterns: [
'<rootDir>/packages/api/build',
'<rootDir>/packages/api-derive/build',
'<rootDir>/packages/api-contract/build',
'<rootDir>/packages/jsonrpc/build',
'<rootDir>/packages/metadata/build',
'<rootDir>/packages/rpc-core/build',
'<rootDir>/packages/rpc-provider/build',
'<rootDir>/packages/types/build'
'<rootDir>/packages/types/build',
'<rootDir>/packages/types-known/build'
],
globals: {
ws_local: 'ws://127.0.0.1:9944/',
ws_local_substrate_master: 'ws://127.0.0.1:9945/',
ws_local_substrate_1: 'ws://127.0.0.1:9946/',
ws_local_substrate_2: 'ws://127.0.0.1:9947/',
ws_local_polkadot_master: 'ws://127.0.0.1:9948/',
ws_local_polkadot_alex: 'ws://127.0.0.1:9949/',
ws_substrate_1: 'wss://substrate-rpc.parity.io/',
ws_polkadot_alex: 'wss://poc3-rpc.polkadot.io/'
},
resolver: './jest.resolver.js'
});
+1 -1
View File
@@ -9,5 +9,5 @@
"packages": [
"packages/*"
],
"version": "1.6.1"
"version": "1.9.1"
}
+8 -5
View File
@@ -12,7 +12,9 @@
"scripts": {
"build": "yarn build:interfaces && polkadot-dev-build-ts && (cd packages/typegen && copyfiles scripts/* build)",
"build:interfaces": "polkadot-types-internal-interfaces",
"build:release": "polkadot-ci-ghact-build",
"docs": "polkadot-types-internal-metadata && polkadot-dev-build-docs",
"docs:release": "polkadot-ci-ghact-docs",
"chain:info": "polkadot-types-chain-info",
"lint": "polkadot-dev-run-lint",
"clean": "polkadot-dev-clean-build",
@@ -22,12 +24,13 @@
"test:watch": "polkadot-dev-run-test --watch"
},
"devDependencies": {
"@babel/core": "^7.8.4",
"@babel/register": "^7.8.3",
"@babel/runtime": "^7.8.4",
"@polkadot/dev": "^0.50.30",
"@polkadot/ts": "^0.3.7",
"@babel/core": "^7.9.0",
"@babel/register": "^7.9.0",
"@babel/runtime": "^7.9.2",
"@polkadot/dev": "^0.51.9",
"@polkadot/ts": "^0.3.14",
"@polkadot/typegen": "workspace:packages/typegen",
"@types/jest": "^25.1.4",
"copyfiles": "^2.2.0"
}
}
+6 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-contract",
"version": "1.6.1",
"version": "1.9.1",
"description": "Interfaces for interacting with contracts and contract ABIs",
"main": "index.js",
"keywords": [
@@ -26,11 +26,11 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-contract#readme",
"dependencies": {
"@babel/runtime": "^7.8.4",
"@polkadot/api": "1.6.1",
"@polkadot/rpc-core": "1.6.1",
"@polkadot/types": "1.6.1",
"@polkadot/util": "^2.6.2",
"@babel/runtime": "^7.9.2",
"@polkadot/api": "1.9.1",
"@polkadot/rpc-core": "1.9.1",
"@polkadot/types": "1.9.1",
"@polkadot/util": "^2.7.1",
"bn.js": "^5.1.1",
"rxjs": "^6.5.4"
}
@@ -158,10 +158,10 @@ export default class ContractRegistry extends MetaRegistry {
public convertContract ({ constructors, messages, name, events, ...contract }: ContractABIContractPre): ContractABIContract {
return {
constructors: this.convertConstructors(constructors),
messages: messages.map(message => this.convertMessage(message)),
messages: messages.map((message) => this.convertMessage(message)),
name: this.stringAt(name),
...(events
? { events: events.map(event => this.convertEvent(event)) }
? { events: events.map((event) => this.convertEvent(event)) }
: {}),
...contract
};
+1 -1
View File
@@ -275,7 +275,7 @@ export default class MetaRegistry extends MetadataRegistryLookup {
case 'Result':
return this.typeDefForResult(id, typeIndex);
default: {
const sub = def['enum.variants'].map(variant => this.typeDefForEnumVariant(variant));
const sub = def['enum.variants'].map((variant) => this.typeDefForEnumVariant(variant));
return {
info: TypeDefInfo.Enum,
-1
View File
@@ -7,7 +7,6 @@ import { AccountId, Address, ContractExecResult } from '@polkadot/types/interfac
import { Codec, CodecArg } from '@polkadot/types/types';
import { MetaRegistryJson, StringIndex, TypeIndex, TypeDef } from '@polkadot/types/create/types';
// import { Observable } from 'rxjs';
import { ApiPromise, ApiRx } from '@polkadot/api';
export type ApiObject<ApiType extends ApiTypes> = ApiType extends 'rxjs'
+1 -1
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Codec, Registry, TypeDefInfo, TypeDef } from '@polkadot/types/types';
import { Codec, Registry, TypeDef, TypeDefInfo } from '@polkadot/types/types';
import { Option, Raw, createClass, createTypeUnsafe } from '@polkadot/types';
+9 -9
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-derive",
"version": "1.6.1",
"version": "1.9.1",
"description": "Common functions used across Polkadot, derived from RPC calls and storage queries.",
"main": "index.js",
"keywords": [
@@ -27,18 +27,18 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme",
"dependencies": {
"@babel/runtime": "^7.8.4",
"@polkadot/api": "1.6.1",
"@polkadot/rpc-core": "1.6.1",
"@polkadot/rpc-provider": "1.6.1",
"@polkadot/types": "1.6.1",
"@polkadot/util": "^2.6.2",
"@polkadot/util-crypto": "^2.6.2",
"@babel/runtime": "^7.9.2",
"@polkadot/api": "1.9.1",
"@polkadot/rpc-core": "1.9.1",
"@polkadot/rpc-provider": "1.9.1",
"@polkadot/types": "1.9.1",
"@polkadot/util": "^2.7.1",
"@polkadot/util-crypto": "^2.7.1",
"bn.js": "^5.1.1",
"memoizee": "^0.4.14",
"rxjs": "^6.5.4"
},
"devDependencies": {
"@polkadot/keyring": "^2.6.2"
"@polkadot/keyring": "^2.7.1"
}
}
@@ -7,7 +7,6 @@ import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { createType } from '@polkadot/types';
import { isU8a } from '@polkadot/util';
import { decodeAddress } from '@polkadot/util-crypto';
@@ -23,14 +22,14 @@ function retrieve (api: ApiInterfaceRx, address: Address | AccountId | AccountIn
: decodeAddress((address || '').toString());
if (decoded.length === 32) {
const accountId = createType(api.registry, 'AccountId', decoded);
const accountId = api.registry.createType('AccountId', decoded);
return api.derive.accounts.idToIndex(accountId).pipe(
map((accountIndex): AccountIdAndIndex => [accountId, accountIndex])
);
}
const accountIndex = createType(api.registry, 'AccountIndex', decoded);
const accountIndex = api.registry.createType('AccountIndex', decoded);
return api.derive.accounts.indexToId(accountIndex).pipe(
map((accountId): AccountIdAndIndex => [accountId, accountIndex])
@@ -9,14 +9,14 @@ import { Observable, of } from 'rxjs';
import { map, startWith } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { ENUMSET_SIZE } from '@polkadot/types/generic/AccountIndex';
import { Option, Vec, createType } from '@polkadot/types';
import { Option, Vec } from '@polkadot/types';
import { memo } from '../util';
function queryEnumSet (api: ApiInterfaceRx, _accountIndex: AccountIndex | string): Observable<AccountId | undefined> {
const accountIndex = _accountIndex instanceof api.registry.createClass('AccountIndex')
? _accountIndex
: createType(api.registry, 'AccountIndex', _accountIndex);
: api.registry.createType('AccountIndex', _accountIndex);
return api.query.indices.enumSet<Vec<AccountId>>(accountIndex.div(ENUMSET_SIZE)).pipe(
startWith([]),
+2 -2
View File
@@ -9,7 +9,7 @@ import { AccountIndexes } from '../types';
import { Observable, of } from 'rxjs';
import { map, startWith, switchMap } from 'rxjs/operators';
import { ENUMSET_SIZE } from '@polkadot/types/generic/AccountIndex';
import { Vec, createType } from '@polkadot/types';
import { Vec } from '@polkadot/types';
import { memo } from '../util';
@@ -31,7 +31,7 @@ function queryEnumSet (api: ApiInterfaceRx): Observable<AccountIndexes> {
// 64 (0..63 in first) is [1][0] (the first index value in set 2)
const index = (outerIndex * enumsetSize) + innerIndex;
indexes[accountId.toString()] = createType(api.registry, 'AccountIndex', index);
indexes[accountId.toString()] = api.registry.createType('AccountIndex', index);
});
return indexes;
+45 -5
View File
@@ -5,11 +5,11 @@
import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId, AccountIndex, Address, Balance, Registration } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DeriveAccountInfo, DeriveAccountRegistration } from '../types';
import { DeriveAccountFlags, DeriveAccountInfo, DeriveAccountRegistration } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Bytes, Data, Option, u32 } from '@polkadot/types';
import { Bytes, Data, Option, u32, Vec } from '@polkadot/types';
import { u8aToString } from '@polkadot/util';
import { memo } from '../util';
@@ -22,6 +22,12 @@ function dataAsString (data: Data): string | undefined {
: undefined;
}
function includedWrapper (accountId?: AccountId): (_: AccountId) => boolean {
return function (id: AccountId): boolean {
return id.eq(accountId);
};
}
function retrieveNick (api: ApiInterfaceRx, accountId?: AccountId): Observable<string | undefined> {
return ((
accountId && api.query.nicks?.nameOf
@@ -109,6 +115,39 @@ function retrieveIdentity (api: ApiInterfaceRx, accountId?: AccountId): Observab
);
}
function retrieveFlags (api: ApiInterfaceRx, accountId?: AccountId): Observable<DeriveAccountFlags> {
const councilSection = api.query.electionsPhragmen ? 'electionsPhragmen' : 'elections';
return combineLatest([
api.query[councilSection]?.members
? api.query[councilSection].members<Vec<ITuple<[AccountId, Balance]>>>()
: of(undefined),
api.query.council?.members
? api.query.council.members()
: of([]),
api.query.technicalCommittee?.members
? api.query.technicalCommittee.members()
: of([]),
api.query.society?.members
? api.query.society.members()
: of([]),
api.query.sudo?.key
? api.query.sudo.key()
: of(undefined)
]).pipe(
map(([electionsMembers, councilMembers, technicalCommitteeMembers, societyMembers, sudoKey]): DeriveAccountFlags => {
const checkIncluded = includedWrapper(accountId);
return {
isCouncil: (electionsMembers?.map(([id]) => id) || councilMembers || []).some(checkIncluded),
isTechCommittee: technicalCommitteeMembers.some(checkIncluded),
isSociety: societyMembers.some(checkIncluded),
isSudo: !!sudoKey && sudoKey.eq(accountId)
};
})
);
}
/**
* @name info
* @description Returns aux. info with regards to an account, current that includes the accountId, accountIndex and nickname
@@ -116,15 +155,16 @@ function retrieveIdentity (api: ApiInterfaceRx, accountId?: AccountId): Observab
export function info (api: ApiInterfaceRx): (address?: AccountIndex | AccountId | Address | string | null) => Observable<DeriveAccountInfo> {
return memo((address?: AccountIndex | AccountId | Address | string | null): Observable<DeriveAccountInfo> =>
api.derive.accounts.idAndIndex(address).pipe(
switchMap(([accountId, accountIndex]): Observable<[Partial<DeriveAccountInfo>, DeriveAccountRegistration, string?]> =>
switchMap(([accountId, accountIndex]): Observable<[Partial<DeriveAccountInfo>, DeriveAccountFlags, DeriveAccountRegistration, string?]> =>
combineLatest([
of({ accountId, accountIndex }),
retrieveFlags(api, accountId),
retrieveIdentity(api, accountId),
retrieveNick(api, accountId)
])
),
map(([{ accountId, accountIndex }, identity, nickname]): DeriveAccountInfo => ({
accountId, accountIndex, identity, nickname
map(([{ accountId, accountIndex }, flags, identity, nickname]): DeriveAccountInfo => ({
accountId, accountIndex, ...flags, identity, nickname
}))
));
}
+9 -10
View File
@@ -4,18 +4,17 @@
import { AccountId, AccountData, AccountIndex, AccountInfo, Address, Balance, Index } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DerivedBalancesAccount } from '../types';
import { DeriveBalancesAccount } from '../types';
import { combineLatest, of, Observable } from 'rxjs';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { createType } from '@polkadot/types';
import { memo } from '../util';
type Result = [Balance, Balance, Balance, Balance, Index];
function calcBalances (api: ApiInterfaceRx, [accountId, [freeBalance, reservedBalance, frozenFee, frozenMisc, accountNonce]]: [AccountId, Result]): DerivedBalancesAccount {
function calcBalances (api: ApiInterfaceRx, [accountId, [freeBalance, reservedBalance, frozenFee, frozenMisc, accountNonce]]: [AccountId, Result]): DeriveBalancesAccount {
return {
accountId,
accountNonce,
@@ -23,7 +22,7 @@ function calcBalances (api: ApiInterfaceRx, [accountId, [freeBalance, reservedBa
frozenFee,
frozenMisc,
reservedBalance,
votingBalance: createType(api.registry, 'Balance', freeBalance.add(reservedBalance))
votingBalance: api.registry.createType('Balance', freeBalance.add(reservedBalance))
};
}
@@ -35,7 +34,7 @@ function queryBalancesFree (api: ApiInterfaceRx, accountId: AccountId): Observab
[api.query.system.accountNonce, accountId]
]).pipe(
map(([freeBalance, reservedBalance, accountNonce]): Result =>
[freeBalance, reservedBalance, createType(api.registry, 'Balance'), createType(api.registry, 'Balance'), accountNonce]
[freeBalance, reservedBalance, api.registry.createType('Balance'), api.registry.createType('Balance'), accountNonce]
)
);
}
@@ -80,8 +79,8 @@ function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<Re
* });
* ```
*/
export function account (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DerivedBalancesAccount> {
return memo((address: AccountIndex | AccountId | Address | string): Observable<DerivedBalancesAccount> =>
export function account (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DeriveBalancesAccount> {
return memo((address: AccountIndex | AccountId | Address | string): Observable<DeriveBalancesAccount> =>
api.derive.accounts.info(address).pipe(
switchMap(({ accountId }): Observable<[AccountId, Result]> =>
(accountId
@@ -93,9 +92,9 @@ export function account (api: ApiInterfaceRx): (address: AccountIndex | AccountI
? queryBalancesAccount(api, accountId)
: queryBalancesFree(api, accountId)
])
: of([createType(api.registry, 'AccountId'), [createType(api.registry, 'Balance'), createType(api.registry, 'Balance'), createType(api.registry, 'Balance'), createType(api.registry, 'Balance'), createType(api.registry, '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))
));
}
+16 -16
View File
@@ -3,22 +3,22 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, AccountIndex, Address, Balance, BalanceLock, BalanceLockTo212, BlockNumber, VestingInfo, VestingSchedule } from '@polkadot/types/interfaces';
import { DerivedBalancesAccount, DerivedBalancesAll } from '../types';
import { DeriveBalancesAccount, DeriveBalancesAll } from '../types';
import BN from 'bn.js';
import { combineLatest, of, Observable } from 'rxjs';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Option, Vec, createType } from '@polkadot/types';
import { Option, Vec } from '@polkadot/types';
import { bnMax } from '@polkadot/util';
import { memo } from '../util';
type ResultBalance = [VestingInfo | null, (BalanceLock | BalanceLockTo212)[]];
type Result = [DerivedBalancesAccount, BlockNumber, ResultBalance];
type Result = [DeriveBalancesAccount, BlockNumber, ResultBalance];
function calcBalances (api: ApiInterfaceRx, [{ accountId, accountNonce, freeBalance, frozenFee, frozenMisc, reservedBalance, votingBalance }, bestNumber, [vesting, locks]]: Result): DerivedBalancesAll {
let lockedBalance = createType(api.registry, 'Balance');
function calcBalances (api: ApiInterfaceRx, [{ accountId, accountNonce, freeBalance, frozenFee, frozenMisc, reservedBalance, votingBalance }, bestNumber, [vesting, locks]]: Result): DeriveBalancesAll {
let lockedBalance = api.registry.createType('Balance');
let lockedBreakdown: (BalanceLock | BalanceLockTo212)[] = [];
let allLocked = false;
@@ -32,16 +32,16 @@ function calcBalances (api: ApiInterfaceRx, [{ accountId, accountNonce, freeBala
// get the maximum of the locks according to https://github.com/paritytech/substrate/blob/master/srml/balances/src/lib.rs#L699
if (notAll.length) {
lockedBalance = createType(api.registry, 'Balance', bnMax(...notAll.map(({ amount }): Balance => amount)));
lockedBalance = api.registry.createType('Balance', bnMax(...notAll.map(({ amount }): Balance => amount)));
}
}
// Calculate the vesting balances,
// - offset = balance locked at startingBlock
// - perBlock is the unlock amount
const { locked: vestingTotal, perBlock, startingBlock } = vesting || createType(api.registry, 'VestingInfo');
const { locked: vestingTotal, perBlock, startingBlock } = vesting || api.registry.createType('VestingInfo');
const isStarted = bestNumber.gt(startingBlock);
const vestedBalance = createType(api.registry, 'Balance', isStarted ? perBlock.mul(bestNumber.sub(startingBlock)) : 0);
const vestedBalance = api.registry.createType('Balance', isStarted ? perBlock.mul(bestNumber.sub(startingBlock)) : 0);
const isVesting = isStarted && vestedBalance.lt(vestingTotal);
// The available balance & vested has an interplay here
@@ -53,7 +53,7 @@ function calcBalances (api: ApiInterfaceRx, [{ accountId, accountNonce, freeBala
// ""
const floating = freeBalance.sub(lockedBalance);
const extraReceived = isVesting ? freeBalance.sub(vestingTotal) : new BN(0);
const availableBalance = createType(api.registry, 'Balance', allLocked ? 0 : bnMax(new BN(0), isVesting && floating.gt(vestedBalance) ? vestedBalance.add(extraReceived) : floating));
const availableBalance = api.registry.createType('Balance', allLocked ? 0 : bnMax(new BN(0), isVesting && floating.gt(vestedBalance) ? vestedBalance.add(extraReceived) : floating));
return {
accountId,
@@ -84,7 +84,7 @@ function queryOld (api: ApiInterfaceRx, accountId: AccountId): Observable<Result
if (optVesting.isSome) {
const { offset: locked, perBlock, startingBlock } = optVesting.unwrap();
vestingNew = createType(api.registry, 'VestingInfo', { locked, perBlock, startingBlock });
vestingNew = api.registry.createType('VestingInfo', { locked, perBlock, startingBlock });
}
return [vestingNew, locks];
@@ -102,7 +102,7 @@ function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<Re
])
: api.query.balances.locks(accountId).pipe(
map((locks): [Vec<BalanceLock>, Option<VestingInfo>] =>
[locks, createType(api.registry, 'Option<VestingInfo>')]
[locks, api.registry.createType('Option<VestingInfo>')]
)
)
).pipe(
@@ -127,8 +127,8 @@ function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<Re
* });
* ```
*/
export function all (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DerivedBalancesAll> {
return memo((address: AccountIndex | AccountId | Address | string): Observable<DerivedBalancesAll> =>
export function all (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DeriveBalancesAll> {
return memo((address: AccountIndex | AccountId | Address | string): Observable<DeriveBalancesAll> =>
api.derive.balances.account(address).pipe(
switchMap((account): Observable<Result> =>
(!account.accountId.isEmpty
@@ -139,9 +139,9 @@ export function all (api: ApiInterfaceRx): (address: AccountIndex | AccountId |
? queryCurrent(api, account.accountId)
: queryOld(api, account.accountId)
])
: of([account, createType(api.registry, 'BlockNumber'), [null, createType(api.registry, '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))
));
}
+9 -10
View File
@@ -4,11 +4,10 @@
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Balance } from '@polkadot/types/interfaces';
import { DerivedFees } from '../types';
import { DeriveFees } from '../types';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { createType } from '@polkadot/types';
import { memo } from '../util';
@@ -25,19 +24,19 @@ import { memo } from '../util';
* });
* ```
*/
export function fees (api: ApiInterfaceRx): () => Observable<DerivedFees> {
return memo((): Observable<DerivedFees> =>
export function fees (api: ApiInterfaceRx): () => Observable<DeriveFees> {
return memo((): Observable<DeriveFees> =>
of([
// deprecated - remove
(api.consts.balances?.creationFee as Balance) || createType(api.registry, 'Balance'),
(api.consts.balances?.transferFee as Balance) || createType(api.registry, 'Balance'),
(api.consts.balances?.creationFee as Balance) || api.registry.createType('Balance'),
(api.consts.balances?.transferFee as Balance) || api.registry.createType('Balance'),
// current
(api.consts.balances?.existentialDeposit as Balance) || createType(api.registry, 'Balance'),
(api.consts.transactionPayment?.transactionBaseFee as Balance) || createType(api.registry, 'Balance'),
(api.consts.transactionPayment?.transactionByteFee as Balance) || createType(api.registry, 'Balance')
(api.consts.balances?.existentialDeposit 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')
]).pipe(
map(([creationFee, transferFee, existentialDeposit, transactionBaseFee, transactionByteFee]): DerivedFees => ({
map(([creationFee, transferFee, existentialDeposit, transactionBaseFee, transactionByteFee]): DeriveFees => ({
creationFee,
existentialDeposit,
transactionBaseFee,
@@ -3,20 +3,21 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces';
import { DerivedBalancesAccount } from '../types';
import { DeriveBalancesAccount } from '../types';
import { combineLatest, Observable, of } from 'rxjs';
import { Observable, combineLatest, of } from 'rxjs';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { memo } from '../util';
export function votingBalances (api: ApiInterfaceRx): (addresses?: (AccountId | AccountIndex | Address | string)[]) => Observable<DerivedBalancesAccount[]> {
return memo((addresses?: (AccountId | AccountIndex | Address | string)[]): Observable<DerivedBalancesAccount[]> =>
export function votingBalances (api: ApiInterfaceRx): (addresses?: (AccountId | AccountIndex | Address | string)[]) => Observable<DeriveBalancesAccount[]> {
return memo((addresses?: (AccountId | AccountIndex | Address | string)[]): Observable<DeriveBalancesAccount[]> =>
!addresses || !addresses.length
? of([] as DerivedBalancesAccount[])
? of([] as DeriveBalancesAccount[])
: combineLatest(
addresses.map((accountId): Observable<DerivedBalancesAccount> =>
api.derive.balances.account(accountId))
addresses.map((accountId): Observable<DeriveBalancesAccount> =>
api.derive.balances.account(accountId)
)
)
);
}
@@ -7,7 +7,6 @@ import { BlockNumber } from '@polkadot/types/interfaces';
import { Observable, combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { createType } from '@polkadot/types';
import { memo } from '../util';
@@ -31,7 +30,7 @@ export function bestNumberLag (api: ApiInterfaceRx): () => Observable<BlockNumbe
api.derive.chain.bestNumberFinalized()
]).pipe(
map(([bestNumber, bestNumberFinalized]): BlockNumber =>
createType(api.registry, 'BlockNumber', bestNumber.sub(bestNumberFinalized))
api.registry.createType('BlockNumber', bestNumber.sub(bestNumberFinalized))
)
));
}
@@ -4,17 +4,17 @@
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Hash, Proposal, Votes } from '@polkadot/types/interfaces';
import { DerivedCollectiveProposal } from '../types';
import { DeriveCollectiveProposal } from '../types';
import { combineLatest, Observable, of } from 'rxjs';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option } from '@polkadot/types';
type Result = [Hash[], Option<Proposal>[], Option<Votes>[]];
function parse ([hashes, proposals, votes]: Result): DerivedCollectiveProposal[] {
function parse ([hashes, proposals, votes]: Result): DeriveCollectiveProposal[] {
return proposals
.map((proposalOpt, index): DerivedCollectiveProposal | null =>
.map((proposalOpt, index): DeriveCollectiveProposal | null =>
proposalOpt.isSome
? {
hash: hashes[index],
@@ -23,11 +23,11 @@ function parse ([hashes, proposals, votes]: Result): DerivedCollectiveProposal[]
}
: null
)
.filter((proposal): proposal is DerivedCollectiveProposal => !!proposal);
.filter((proposal): proposal is DeriveCollectiveProposal => !!proposal);
}
export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalCommittee'): () => Observable<DerivedCollectiveProposal[]> {
return (): Observable<DerivedCollectiveProposal[]> =>
export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalCommittee'): () => Observable<DeriveCollectiveProposal[]> {
return (): Observable<DeriveCollectiveProposal[]> =>
api.query[section]?.proposals
? api.query[section].proposals().pipe(
switchMap((hashes: Hash[]): Observable<Result> =>
@@ -41,5 +41,5 @@ export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalC
),
map(parse)
)
: of([] as DerivedCollectiveProposal[]);
: of([] as DeriveCollectiveProposal[]);
}
+6 -7
View File
@@ -3,12 +3,11 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DerivedContractFees } from '../types';
import { DeriveContractFees } from '../types';
import BN from 'bn.js';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { createType } from '@polkadot/types';
import { memo } from '../util';
@@ -18,8 +17,8 @@ type ResultV2 = [BN, BN, BN, BN, BN, BN, BN, BN, BN];
function queryConstants (api: ApiInterfaceRx): Observable<ResultV2> {
return of([
// deprecated
api.consts.contracts.creationFee || createType(api.registry, 'Balance'),
api.consts.contracts.transferFee || createType(api.registry, 'Balance'),
api.consts.contracts.creationFee || api.registry.createType('Balance'),
api.consts.contracts.transferFee || api.registry.createType('Balance'),
// current
api.consts.contracts.callBaseFee,
@@ -45,10 +44,10 @@ function queryConstants (api: ApiInterfaceRx): Observable<ResultV2> {
* });
* ```
*/
export function fees (api: ApiInterfaceRx): () => Observable<DerivedContractFees> {
return memo((): Observable<DerivedContractFees> => {
export function fees (api: ApiInterfaceRx): () => Observable<DeriveContractFees> {
return memo((): Observable<DeriveContractFees> => {
return queryConstants(api).pipe(
map(([creationFee, transferFee, callBaseFee, contractFee, rentByteFee, rentDepositOffset, tombstoneDeposit, transactionBaseFee, transactionByteFee]): DerivedContractFees => ({
map(([creationFee, transferFee, callBaseFee, contractFee, rentByteFee, rentDepositOffset, tombstoneDeposit, transactionBaseFee, transactionByteFee]): DeriveContractFees => ({
callBaseFee,
contractFee,
creationFee,
+2
View File
@@ -3,3 +3,5 @@
// of the Apache-2.0 license. See the LICENSE file for details.
export * from './proposals';
export * from './votes';
export * from './votesOf';
+2 -2
View File
@@ -3,12 +3,12 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DerivedCollectiveProposals } from '../types';
import { DeriveCollectiveProposals } from '../types';
import { Observable } from 'rxjs';
import { proposals as collectiveProposals } from '../collective';
import { memo } from '../util';
export function proposals (api: ApiInterfaceRx): () => Observable<DerivedCollectiveProposals> {
export function proposals (api: ApiInterfaceRx): () => Observable<DeriveCollectiveProposals> {
return memo(collectiveProposals(api, 'council'));
}
+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][];
+88
View File
@@ -0,0 +1,88 @@
// 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';
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> {
// since we are using entries, we are not adding a memo
return (): Observable<DeriveCouncilVotes> =>
(api.query.electionsPhragmen || api.query.elections).stakeOf
? retrievePrev(api)
: retrieveCurrent(api);
}
@@ -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 { AccountId } from '@polkadot/types/interfaces';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveCouncilVote } from '../types';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
export function votesOf (api: ApiInterfaceRx): (accountId: string | Uint8Array | AccountId) => Observable<DeriveCouncilVote> {
// no memo, votes actually pulls the entries without a memo (using entries)
return (accountId: string | Uint8Array | AccountId): Observable<DeriveCouncilVote> =>
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,32 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { ReferendumInfo, ReferendumInfoTo239 } from '@polkadot/types/interfaces';
import { DeriveReferendum } from '../types';
import BN from 'bn.js';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { Option } from '@polkadot/types';
import { memo } from '../util';
import { getStatus, parseImage } from './util';
export function _referendumInfo (api: ApiInterfaceRx): (index: BN, info: Option<ReferendumInfo | ReferendumInfoTo239>) => Observable<DeriveReferendum | null> {
return memo((index: BN, info: Option<ReferendumInfo | ReferendumInfoTo239>): Observable<DeriveReferendum | null> => {
const status = getStatus(info);
return status
? api.query.democracy.preimages(status.proposalHash).pipe(
map((preimage): DeriveReferendum => ({
index: api.registry.createType('ReferendumIndex', index),
image: parseImage(api, preimage),
imageHash: status.proposalHash,
status
}))
)
: of(null);
});
}
@@ -0,0 +1,84 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId, Vote, Voting, VotingDirectVote } from '@polkadot/types/interfaces';
import { DeriveBalancesAccount, DeriveReferendum, DeriveReferendumVote, DeriveReferendumVotes } from '../types';
import BN from 'bn.js';
import { Observable, of, combineLatest } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Vec } from '@polkadot/types';
import { memo } from '../util';
import { calcVotes } from './util';
function votesPrev (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveReferendumVote[]> {
return api.query.democracy.votersFor<Vec<AccountId>>(referendumId).pipe(
switchMap((votersFor): Observable<[Vec<AccountId>, Vote[], DeriveBalancesAccount[]]> =>
combineLatest([
of(votersFor),
votersFor.length
? api.query.democracy.voteOf.multi<Vote>(
votersFor.map((accountId): [BN | number, AccountId] =>
[referendumId, accountId]
)
)
: of([]),
api.derive.balances.votingBalances(votersFor)
])
),
map(([votersFor, votes, balances]): DeriveReferendumVote[] =>
votersFor.map((accountId, index): DeriveReferendumVote => ({
accountId,
balance: balances[index].votingBalance || api.registry.createType('Balance'),
vote: votes[index] || api.registry.createType('Vote')
}))
)
);
}
function votesCurr (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveReferendumVote[]> {
return api.query.democracy.votingOf.entries<Voting>().pipe(
map((allVoting): DeriveReferendumVote[] =>
allVoting
.map(([key, voting]): [AccountId, Voting] => [key.args[0] as AccountId, voting])
// FIXME We are ignoring delegated votes
.filter(([, voting]) => voting.isDirect)
.map(([accountId, voting]): [AccountId, VotingDirectVote[]] => [
accountId,
voting.asDirect.votes.filter(([idx]) => idx.eq(referendumId))
])
.filter(([, directVotes]) => !!directVotes.length)
.reduce((result: DeriveReferendumVote[], [accountId, votes]) =>
// FIXME We are ignoring split votes
votes.reduce((result: DeriveReferendumVote[], [, vote]): DeriveReferendumVote[] => {
if (vote.isStandard) {
result.push({
accountId,
...vote.asStandard
});
}
return result;
}, result), []
)
)
);
}
export function _referendumVotes (api: ApiInterfaceRx): (referendum: DeriveReferendum) => Observable<DeriveReferendumVotes> {
return memo((referendum: DeriveReferendum): Observable<DeriveReferendumVotes> =>
combineLatest([
api.derive.democracy.sqrtElectorate(),
api.query.democracy.votingOf
? votesCurr(api, referendum.index)
: votesPrev(api, referendum.index)
]).pipe(
map(([sqrtElectorate, votes]) =>
calcVotes(sqrtElectorate, referendum, votes)
)
)
);
}
@@ -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 { DeriveReferendum, DeriveReferendumVotes } from '../types';
import { Observable, of, combineLatest } from 'rxjs';
import { memo } from '../util';
export function _referendumsVotes (api: ApiInterfaceRx): (referendums: DeriveReferendum[]) => Observable<DeriveReferendumVotes[]> {
return memo((referendums: DeriveReferendum[]): Observable<DeriveReferendumVotes[]> =>
referendums.length
? combineLatest(
referendums.map((referendum): Observable<DeriveReferendumVotes> =>
api.derive.democracy._referendumVotes(referendum)
)
)
: of([])
);
}
@@ -0,0 +1,38 @@
// 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 } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DeriveDispatch } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Vec } from '@polkadot/types';
import { memo } from '../util';
export function dispatchQueue (api: ApiInterfaceRx): () => Observable<DeriveDispatch[]> {
return memo((): Observable<DeriveDispatch[]> =>
api.query.democracy?.dispatchQueue
? api.query.democracy.dispatchQueue<Vec<ITuple<[BlockNumber, Hash, ReferendumIndex]>>>().pipe(
switchMap((dispatches) =>
combineLatest([
of(dispatches),
api.derive.democracy.preimages(
dispatches.map(([, hash]) => hash))
])
),
map(([dispatches, images]) =>
dispatches.map(([at, imageHash, index], dispatchIndex): DeriveDispatch => ({
at,
index,
image: images[dispatchIndex],
imageHash
}))
)
)
: of([])
);
}
+10 -3
View File
@@ -2,8 +2,15 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
export * from './_referendumsVotes';
export * from './_referendumVotes';
export * from './_referendumInfo';
export * from './dispatchQueue';
export * from './nextExternal';
export * from './preimage';
export * from './preimages';
export * from './proposals';
export * from './referendumInfos';
export * from './referendums';
export * from './referendumVotesFor';
export * from './votes';
export * from './referendumsActive';
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
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, Balance, BlockNumber, Hash, PropIndex, Proposal } from '@polkadot/types/interfaces';
import { AccountId, Balance, Hash, PropIndex } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DeriveProposal } from '../types';
import { DeriveProposalImage, DeriveProposal } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Bytes, Option, Vec, createType } from '@polkadot/types';
import { Option, Vec } from '@polkadot/types';
import { memo } from '../util';
export type PreImage = Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>;
type Depositors = Option<ITuple<[Balance, Vec<AccountId>]>>;
type Proposals = Vec<ITuple<[PropIndex, Hash, AccountId]>>;
interface Result {
depositors: Depositors[];
preimages: PreImage[];
proposals: Proposals;
}
function parse (api: ApiInterfaceRx, { depositors, proposals, preimages }: Result): DeriveProposal[] {
function parse ([proposals, images, depositors]: [Proposals, (DeriveProposalImage | undefined)[], Depositors[]]): DeriveProposal[] {
return proposals
.filter(([, , proposer], index): boolean =>
!!(depositors[index]?.isSome) && !proposer.isEmpty
)
.map(([propIndex, hash, proposer], index): DeriveProposal => {
const preimage = preimages[index].unwrapOr(null);
const depositor = depositors[index].unwrap();
let proposal: undefined | Proposal;
// we could end up in a situation where the proposal is non-decodable, e.g. after an upgrade
if (preimage) {
try {
proposal = createType(api.registry, 'Proposal', preimage[0].toU8a(true));
} catch (error) {
console.error(error);
}
}
.map(([index, imageHash, proposer], proposalIndex): DeriveProposal => {
const [balance, seconds] = depositors[proposalIndex].unwrap();
return {
balance: depositor[0],
hash,
index: propIndex,
preimage: preimage
? {
at: preimage[3],
balance: preimage[2],
proposer: preimage[1]
}
: undefined,
proposal,
balance,
index,
image: images[proposalIndex],
imageHash,
proposer,
seconds: depositor[1]
seconds
};
});
}
@@ -68,16 +42,14 @@ export function proposals (api: ApiInterfaceRx): () => Observable<DeriveProposal
switchMap((proposals) =>
combineLatest([
of(proposals),
api.query.democracy.preimages.multi<PreImage>(
api.derive.democracy.preimages(
proposals.map(([, hash]): Hash => hash)),
api.query.democracy.depositOf.multi<Depositors>(
proposals.map(([index]): PropIndex => index))
])
),
map(([proposals, preimages, depositors]): DeriveProposal[] =>
parse(api, { depositors, proposals, preimages })
)
map(parse)
)
: of([] as DeriveProposal[])
: of([])
);
}
@@ -1,64 +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 { 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, createType } from '@polkadot/types';
import { memo } from '../util';
function constructInfo (api: ApiInterfaceRx, index: BN | number, _info: Option<ReferendumInfo>, _preimage?: PreImage): DerivedReferendum | null {
const preImage = _preimage?.isSome
? _preimage.unwrap()
: null;
const info = _info.unwrapOr(null);
if (!info) {
return null;
}
return {
index: createType(api.registry, 'PropIndex', index),
info,
hash: info.proposalHash,
proposal: preImage
? createType(api.registry, 'Proposal', preImage[0].toU8a(true))
: undefined,
preimage: preImage
? {
at: preImage[3],
balance: preImage[2],
proposer: preImage[1]
}
: undefined
};
}
export function retrieveInfo (api: ApiInterfaceRx, index: BN | number, info: Option<ReferendumInfo>): Observable<DerivedReferendum | null> {
return ((
info?.isSome
? api.query.democracy.preimages(info.unwrap().proposalHash)
: of(undefined)
) as Observable<PreImage | undefined>).pipe(
map((preimage?: PreImage): DerivedReferendum | null =>
constructInfo(api, index, info, preimage)
)
);
}
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>>(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 { combineLatest, Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Vec, createType } 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 || createType(api.registry, 'Balance'),
vote: votes[index] || createType(api.registry, 'Vote')
} as DerivedReferendumVote))
)
));
}
@@ -2,33 +2,29 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ReferendumIndex } from '@polkadot/types/interfaces/democracy';
import { DerivedReferendum } from '../types';
import BN from 'bn.js';
import { Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveReferendumExt } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
export function referendums (api: ApiInterfaceRx): () => Observable<DerivedReferendum[]> {
return memo((): Observable<DerivedReferendum[]> =>
api.query.democracy?.lowestUnbaked
? api.queryMulti<[ReferendumIndex, ReferendumIndex]>([
api.query.democracy.lowestUnbaked,
api.query.democracy.referendumCount
]).pipe(
switchMap(([earliest, referendumCount]): Observable<DerivedReferendum[]> =>
referendumCount?.gt(earliest) && referendumCount?.gtn(0)
? api.derive.democracy.referendumInfos(
[...Array(referendumCount.sub(earliest).toNumber())].map((_, i): BN =>
earliest.addn(i)
)
)
: of([])
)
export function referendums (api: ApiInterfaceRx): () => Observable<DeriveReferendumExt[]> {
return memo((): Observable<DeriveReferendumExt[]> =>
api.derive.democracy.referendumsActive().pipe(
switchMap((referendums) =>
combineLatest([
of(referendums),
api.derive.democracy._referendumsVotes(referendums)
])
),
map(([referendums, votes]) =>
referendums.map((referendum, index): DeriveReferendumExt => ({
...referendum,
...votes[index]
}))
)
: of([] as DerivedReferendum[])
)
);
}
@@ -0,0 +1,32 @@
// 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 { DeriveReferendum } from '../types';
import BN from 'bn.js';
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.query.democracy?.lowestUnbaked
? api.queryMulti<[ReferendumIndex, ReferendumIndex]>([
api.query.democracy.lowestUnbaked,
api.query.democracy.referendumCount
]).pipe(
switchMap(([first, total]): Observable<DeriveReferendum[]> =>
total.gt(first)
? api.derive.democracy.referendumsInfo(
[...Array(total.sub(first).toNumber())].map((_, i): BN => first.addn(i))
)
: of([])
)
)
: of([])
);
}
@@ -0,0 +1,33 @@
// 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 } from '@polkadot/types/interfaces';
import { DeriveReferendum } from '../types';
import BN from 'bn.js';
import { Observable, of, combineLatest } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option } from '@polkadot/types';
import { memo } from '../util';
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 {
}
+163
View File
@@ -0,0 +1,163 @@
// 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, 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';
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;
}
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;
}
}
function isPassing (threshold: VoteThreshold, sqrtElectorate: BN, { votedAye, votedNay, votedTotal }: DeriveReferendumVoteState): 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: isPassing(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;
}
export function parseImage (api: ApiInterfaceRx, imageOpt: Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>): DeriveProposalImage | undefined {
if (imageOpt.isNone) {
return;
}
let proposal: Proposal | undefined;
const [bytes, proposer, balance, at] = imageOpt.unwrap();
try {
proposal = api.registry.createType('Proposal', bytes.toU8a(true));
} catch (error) {
console.error(error);
}
return { at, balance, proposal, proposer };
}
@@ -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]
)
)
);
}
+8 -8
View File
@@ -8,16 +8,16 @@ import { ITuple } from '@polkadot/types/types';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { createType, Vec, u32 } from '@polkadot/types';
import { Vec, u32 } from '@polkadot/types';
import { DerivedElectionsInfo } from '../types';
import { DeriveElectionsInfo } from '../types';
import { memo } from '../util';
function sortAccounts ([, balanceA]: ITuple<[AccountId, Balance]>, [, balanceB]: ITuple<[AccountId, Balance]>): number {
return balanceB.cmp(balanceA);
}
function queryElections (api: ApiInterfaceRx): Observable<DerivedElectionsInfo> {
function queryElections (api: ApiInterfaceRx): Observable<DeriveElectionsInfo> {
const section = api.query.electionsPhragmen ? 'electionsPhragmen' : 'elections';
return api.queryMulti<[Vec<AccountId>, Vec<AccountId>, Vec<ITuple<[AccountId, Balance]>>, Vec<ITuple<[AccountId, Balance]>>]>([
@@ -26,14 +26,14 @@ function queryElections (api: ApiInterfaceRx): Observable<DerivedElectionsInfo>
api.query[section].members,
api.query[section].runnersUp
]).pipe(
map(([councilMembers, candidates, members, runnersUp]): DerivedElectionsInfo => ({
map(([councilMembers, candidates, members, runnersUp]): DeriveElectionsInfo => ({
candidates,
candidateCount: createType(api.registry, 'u32', candidates.length),
candidateCount: api.registry.createType('u32', candidates.length),
candidacyBond: api.consts[section].candidacyBond as Balance,
desiredSeats: api.consts[section].desiredMembers as u32,
members: members.length
? members.sort(sortAccounts)
: councilMembers.map((accountId): [AccountId, Balance] => [accountId, createType(api.registry, 'Balance')]),
: councilMembers.map((accountId): [AccountId, Balance] => [accountId, api.registry.createType('Balance')]),
runnersUp: runnersUp.sort(sortAccounts),
termDuration: api.consts[section].termDuration as BlockNumber,
votingBond: api.consts[section].votingBond as Balance
@@ -54,6 +54,6 @@ function queryElections (api: ApiInterfaceRx): Observable<DerivedElectionsInfo>
* });
* ```
*/
export function info (api: ApiInterfaceRx): () => Observable<DerivedElectionsInfo> {
return memo((): Observable<DerivedElectionsInfo> => queryElections(api));
export function info (api: ApiInterfaceRx): () => Observable<DeriveElectionsInfo> {
return memo((): Observable<DeriveElectionsInfo> => queryElections(api));
}
@@ -3,9 +3,9 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId } from '@polkadot/types/interfaces';
import { DerivedHeartbeats } from '../types';
import { DeriveHeartbeats } from '../types';
import { of, Observable, combineLatest } from 'rxjs';
import { Observable, of, combineLatest } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Bytes, Option, u32 } from '@polkadot/types';
@@ -15,8 +15,8 @@ import { memo } from '../util';
/**
* @description Return a boolean array indicating whether the passed accounts had received heartbeats in the current session
*/
export function receivedHeartbeats (api: ApiInterfaceRx): () => Observable<DerivedHeartbeats> {
return memo((): Observable<DerivedHeartbeats> =>
export function receivedHeartbeats (api: ApiInterfaceRx): () => Observable<DeriveHeartbeats> {
return memo((): Observable<DeriveHeartbeats> =>
api.query.imOnline?.receivedHeartbeats
? api.derive.staking.overview().pipe(
switchMap(({ currentIndex, validators }): Observable<[AccountId[], Option<Bytes>[], u32[]]> =>
@@ -28,8 +28,8 @@ export function receivedHeartbeats (api: ApiInterfaceRx): () => Observable<Deriv
validators.map((address) => [currentIndex, address]))
])
),
map(([validators, heartbeats, numBlocks]): DerivedHeartbeats =>
validators.reduce((result: DerivedHeartbeats, validator, index): DerivedHeartbeats => ({
map(([validators, heartbeats, numBlocks]): DeriveHeartbeats =>
validators.reduce((result: DeriveHeartbeats, validator, index): DeriveHeartbeats => ({
...result,
[validator.toString()]: {
blockCount: numBlocks[index],
+2 -4
View File
@@ -49,10 +49,8 @@ describe('derive', (): void => {
testFunction(api)('chain', 'bestNumber', []);
testFunction(api)('chain', 'bestNumberFinalized', []);
testFunction(api)('democracy', 'referendumInfos', []);
testFunction(api)('democracy', 'proposals', []);
testFunction(api)('democracy', 'referendums', []);
testFunction(api)('democracy', 'referendumVotesFor', []);
testFunction(api)('democracy', 'votes', []);
testFunction(api)('elections', 'info', []);
@@ -61,7 +59,7 @@ describe('derive', (): void => {
testFunction(api)('session', 'sessionProgress', []);
testFunction(api)('staking', 'account', []);
testFunction(api)('staking', 'controllers', []);
testFunction(api)('staking', 'stashes', []);
});
describe('custom', (): void => {
+2 -1
View File
@@ -21,10 +21,11 @@ import * as society from './society';
import * as staking from './staking';
import * as technicalCommittee from './technicalCommittee';
import * as treasury from './treasury';
import * as tx from './tx';
export * from './type';
export const derive = { accounts, balances, chain, contracts, council, democracy, elections, imOnline, parachains, session, society, staking, technicalCommittee, treasury };
export const derive = { accounts, balances, chain, contracts, council, democracy, elections, imOnline, parachains, session, society, staking, technicalCommittee, treasury, tx };
type DeriveSection<Section> = {
[Method in keyof Section]: Section[Method] extends AnyFunction
+1 -2
View File
@@ -9,7 +9,6 @@ import { Active, DidUpdate, Heads, ParaInfoResult, PendingSwap, RelayDispatchQue
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { createType } from '@polkadot/types';
import { memo } from '../util';
@@ -92,7 +91,7 @@ export function info (api: ApiInterfaceRx): (id: ParaId | number) => Observable<
])
.pipe(
map((result: Result): DeriveParachainFull | null =>
parse(createType(api.registry, 'ParaId', id), result)
parse(api.registry.createType('ParaId', id), result)
)
)
: of(null)
@@ -12,7 +12,7 @@ import { memo } from '../util';
export function eraProgress (api: ApiInterfaceRx): () => Observable<BlockNumber> {
return memo((): Observable<BlockNumber> =>
api.derive.session.info().pipe(
api.derive.session.progress().pipe(
map((info) => info.eraProgress)
));
}
+1
View File
@@ -6,4 +6,5 @@ export * from './eraLength';
export * from './eraProgress';
export * from './indexes';
export * from './info';
export * from './progress';
export * from './sessionProgress';
+8 -8
View File
@@ -8,7 +8,7 @@ import { DeriveSessionIndexes } from '../types';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { createType, Option, u32 } from '@polkadot/types';
import { Option, u32 } from '@polkadot/types';
import { memo } from '../util';
@@ -34,7 +34,7 @@ function queryNoActive (api: ApiInterfaceRx): Observable<Result> {
]).pipe(
map(([currentEra, currentIndex, validatorCount]): Result => [
currentEra,
createType(api.registry, 'Option<Moment>'),
api.registry.createType('Option<Moment>'),
currentEra,
currentIndex,
validatorCount
@@ -56,7 +56,7 @@ function query (api: ApiInterfaceRx): Observable<Result> {
return [
activeEra,
activeEraStart,
currentEra.unwrapOr(createType(api.registry, 'EraIndex')),
currentEra.unwrapOr(api.registry.createType('EraIndex')),
currentIndex,
validatorCount
];
@@ -67,11 +67,11 @@ function query (api: ApiInterfaceRx): Observable<Result> {
// empty set when none is available
function empty (api: ApiInterfaceRx): Observable<Result> {
return of([
createType(api.registry, 'EraIndex'),
createType(api.registry, 'Option<Moment>'),
createType(api.registry, 'EraIndex'),
createType(api.registry, 'SessionIndex', 1),
createType(api.registry, 'u32')
api.registry.createType('EraIndex'),
api.registry.createType('Option<Moment>'),
api.registry.createType('EraIndex'),
api.registry.createType('SessionIndex', 1),
api.registry.createType('u32')
]);
}
+26 -67
View File
@@ -3,110 +3,69 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { SessionIndex } from '@polkadot/types/interfaces';
import { DerivedSessionInfo, DeriveSessionIndexes } from '../types';
import { DeriveSessionInfo, DeriveSessionIndexes } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { createType, Option, u64 } from '@polkadot/types';
import { u64 } from '@polkadot/types';
import { memo } from '../util';
type ResultSlots = [u64, u64, u64, Option<SessionIndex>];
type ResultSlotsFlat = [u64, u64, u64, SessionIndex];
type ResultType = [boolean, u64, SessionIndex];
type Result = [ResultType, DeriveSessionIndexes, ResultSlotsFlat];
function createDerived (api: ApiInterfaceRx, [[hasBabe, epochDuration, sessionsPerEra], { activeEra, activeEraStart, currentEra, currentIndex, validatorCount }, [currentSlot, epochIndex, epochOrGenesisStartSlot, activeEraStartSessionIndex]]: Result): DerivedSessionInfo {
const epochStartSlot = epochIndex.mul(epochDuration).add(epochOrGenesisStartSlot);
const sessionProgress = currentSlot.sub(epochStartSlot);
const eraProgress = currentIndex.sub(activeEraStartSessionIndex).mul(epochDuration).add(sessionProgress);
type Result = [ResultType, DeriveSessionIndexes];
function createDerive (api: ApiInterfaceRx, [[hasBabe, epochDuration, sessionsPerEra], { activeEra, activeEraStart, currentEra, currentIndex, validatorCount }]: Result): DeriveSessionInfo {
return {
activeEra,
activeEraStart,
currentEra,
currentIndex,
eraLength: createType(api.registry, 'BlockNumber', sessionsPerEra.mul(epochDuration)),
eraProgress: createType(api.registry, 'BlockNumber', eraProgress),
eraLength: api.registry.createType('BlockNumber', sessionsPerEra.mul(epochDuration)),
isEpoch: hasBabe,
sessionLength: epochDuration,
sessionsPerEra,
sessionProgress: createType(api.registry, 'BlockNumber', sessionProgress),
validatorCount
};
}
function queryAura (api: ApiInterfaceRx): Observable<DerivedSessionInfo> {
function queryAura (api: ApiInterfaceRx): Observable<DeriveSessionInfo> {
return api.derive.session.indexes().pipe(
map((indexes): DerivedSessionInfo =>
createDerived(api, [
map((indexes): DeriveSessionInfo =>
createDerive(api, [
[
false,
createType(api.registry, 'u64', 1),
api.consts.staking?.sessionsPerEra || createType(api.registry, 'SessionIndex', 1)
api.registry.createType('u64', 1),
api.consts.staking?.sessionsPerEra || api.registry.createType('SessionIndex', 1)
],
indexes,
[
createType(api.registry, 'u64', 1),
createType(api.registry, 'u64', 1),
createType(api.registry, 'u64', 1),
createType(api.registry, 'SessionIndex', 1)
]
indexes
])
)
);
}
function queryBabe (api: ApiInterfaceRx): Observable<[DeriveSessionIndexes, ResultSlotsFlat]> {
function queryBabe (api: ApiInterfaceRx): Observable<DeriveSessionInfo> {
return api.derive.session.indexes().pipe(
switchMap((indexes): Observable<[DeriveSessionIndexes, ResultSlots]> =>
combineLatest([
of(indexes),
api.queryMulti<ResultSlots>([
api.query.babe.currentSlot,
api.query.babe.epochIndex,
api.query.babe.genesisSlot,
[api.query.staking.erasStartSessionIndex, indexes.activeEra]
])
map((indexes) =>
createDerive(api, [
[
true,
api.consts.babe.epochDuration,
api.consts.staking.sessionsPerEra
],
indexes
])
),
map(([indexes, [currentSlot, epochIndex, genesisSlot, optStartIndex]]): [DeriveSessionIndexes, ResultSlotsFlat] => [
indexes, [currentSlot, epochIndex, genesisSlot, optStartIndex.unwrapOr(createType(api.registry, 'SessionIndex', 1))]
])
)
);
}
function queryBabeNoHistory (api: ApiInterfaceRx): Observable<[DeriveSessionIndexes, ResultSlotsFlat]> {
return combineLatest([
api.derive.session.indexes(),
api.queryMulti<ResultSlotsFlat>([
api.query.babe.currentSlot,
api.query.babe.epochIndex,
api.query.babe.genesisSlot,
api.query.staking.currentEraStartSessionIndex
])
]);
}
/**
* @description Retrieves all the session and era query and calculates specific values on it as the length of the session and eras
*/
export function info (api: ApiInterfaceRx): () => Observable<DerivedSessionInfo> {
return memo((): Observable<DerivedSessionInfo> =>
export function info (api: ApiInterfaceRx): () => Observable<DeriveSessionInfo> {
return memo((): Observable<DeriveSessionInfo> =>
api.consts.babe
? (api.query.staking.erasStartSessionIndex
? queryBabe(api) // 2.x with Babe
: queryBabeNoHistory(api)
).pipe(
map(([indexes, slots]: [DeriveSessionIndexes, ResultSlotsFlat]): DerivedSessionInfo =>
createDerived(api, [
[true, api.consts.babe.epochDuration, api.consts.staking.sessionsPerEra],
indexes,
slots
])
)
)
? queryBabe(api)
: queryAura(api)
);
}
@@ -0,0 +1,90 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { SessionIndex } from '@polkadot/types/interfaces';
import { DeriveSessionInfo, DeriveSessionProgress } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Option, u64 } from '@polkadot/types';
import { memo } from '../util';
type ResultSlots = [u64, u64, u64, Option<SessionIndex>];
type ResultSlotsFlat = [u64, u64, u64, SessionIndex];
function createDerive (api: ApiInterfaceRx, info: DeriveSessionInfo, [currentSlot, epochIndex, epochOrGenesisStartSlot, activeEraStartSessionIndex]: ResultSlotsFlat): DeriveSessionProgress {
const epochStartSlot = epochIndex.mul(info.sessionLength).add(epochOrGenesisStartSlot);
const sessionProgress = currentSlot.sub(epochStartSlot);
const eraProgress = info.currentIndex.sub(activeEraStartSessionIndex).mul(info.sessionLength).add(sessionProgress);
return {
...info,
eraProgress: api.registry.createType('BlockNumber', eraProgress),
sessionProgress: api.registry.createType('BlockNumber', sessionProgress)
};
}
function queryAura (api: ApiInterfaceRx): Observable<DeriveSessionProgress> {
return api.derive.session.info().pipe(
map((info): DeriveSessionProgress =>
createDerive(api, info, [
api.registry.createType('u64', 1),
api.registry.createType('u64', 1),
api.registry.createType('u64', 1),
api.registry.createType('SessionIndex', 1)
])
)
);
}
function queryBabe (api: ApiInterfaceRx): Observable<[DeriveSessionInfo, ResultSlotsFlat]> {
return api.derive.session.info().pipe(
switchMap((info): Observable<[DeriveSessionInfo, ResultSlots]> =>
combineLatest([
of(info),
api.queryMulti<ResultSlots>([
api.query.babe.currentSlot,
api.query.babe.epochIndex,
api.query.babe.genesisSlot,
[api.query.staking.erasStartSessionIndex, info.activeEra]
])
])
),
map(([info, [currentSlot, epochIndex, genesisSlot, optStartIndex]]): [DeriveSessionInfo, ResultSlotsFlat] => [
info, [currentSlot, epochIndex, genesisSlot, optStartIndex.unwrapOr(api.registry.createType('SessionIndex', 1))]
])
);
}
function queryBabeNoHistory (api: ApiInterfaceRx): Observable<[DeriveSessionInfo, ResultSlotsFlat]> {
return combineLatest([
api.derive.session.info(),
api.queryMulti<ResultSlotsFlat>([
api.query.babe.currentSlot,
api.query.babe.epochIndex,
api.query.babe.genesisSlot,
api.query.staking.currentEraStartSessionIndex
])
]);
}
/**
* @description Retrieves all the session and era query and calculates specific values on it as the length of the session and eras
*/
export function progress (api: ApiInterfaceRx): () => Observable<DeriveSessionProgress> {
return memo((): Observable<DeriveSessionProgress> =>
api.consts.babe
? (api.query.staking.erasStartSessionIndex
? queryBabe(api) // 2.x with Babe
: queryBabeNoHistory(api)
).pipe(
map(([info, slots]: [DeriveSessionInfo, ResultSlotsFlat]): DeriveSessionProgress =>
createDerive(api, info, slots)
)
)
: queryAura(api)
);
}
@@ -12,7 +12,7 @@ import { memo } from '../util';
export function sessionProgress (api: ApiInterfaceRx): () => Observable<BlockNumber> {
return memo((): Observable<BlockNumber> =>
api.derive.session.info().pipe(
api.derive.session.progress().pipe(
map((info) => info.sessionProgress)
));
}
+5 -2
View File
@@ -14,11 +14,14 @@ export interface DeriveSessionIndexes {
validatorCount: u32;
}
export interface DerivedSessionInfo extends DeriveSessionIndexes {
export interface DeriveSessionInfo extends DeriveSessionIndexes {
eraLength: BlockNumber;
eraProgress: BlockNumber;
isEpoch: boolean;
sessionLength: BlockNumber;
sessionsPerEra: SessionIndex;
}
export interface DeriveSessionProgress extends DeriveSessionInfo {
eraProgress: BlockNumber;
sessionProgress: BlockNumber;
}
@@ -7,7 +7,7 @@ import { AccountId, BalanceOf, Bid, BidKind } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DeriveSocietyCandidate } from '../types';
import { combineLatest, of, Observable } from 'rxjs';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option, Vec } from '@polkadot/types';
+6 -4
View File
@@ -6,7 +6,7 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId } from '@polkadot/types/interfaces';
import { DeriveSocietyMember } from '../types';
import { combineLatest, Observable } from 'rxjs';
import { Observable, combineLatest } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { memo } from '../util';
@@ -18,9 +18,11 @@ export function members (api: ApiInterfaceRx): () => Observable<DeriveSocietyMem
return memo((): Observable<DeriveSocietyMember[]> =>
api.query.society.members<AccountId[]>().pipe(
switchMap((members): Observable<DeriveSocietyMember[]> =>
combineLatest(members.map((accountId): Observable<DeriveSocietyMember> =>
api.derive.society.member(accountId)
))
combineLatest(
members.map((accountId): Observable<DeriveSocietyMember> =>
api.derive.society.member(accountId)
)
)
)
)
);
+16 -31
View File
@@ -3,13 +3,12 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Balance, BlockNumber, StakingLedger, UnlockChunk } from '@polkadot/types/interfaces';
import { DerivedSessionInfo, DerivedStakingAccount, DerivedStakingQuery, DerivedUnlocking } from '../types';
import { Balance, StakingLedger, UnlockChunk } from '@polkadot/types/interfaces';
import { DeriveSessionInfo, DeriveStakingAccount, DeriveStakingQuery, DeriveUnlocking } from '../types';
import BN from 'bn.js';
import { combineLatest, Observable } from 'rxjs';
import { Observable, combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';
import { createType } from '@polkadot/types';
import { isUndefined } from '@polkadot/util';
@@ -28,27 +27,13 @@ function groupByEra (list: UnlockChunk[]): Record<string, BN> {
}, {});
}
// calculate the remaining blocks in a specific unlock era
function remainingBlocks (api: ApiInterfaceRx, era: BN, sessionInfo: DerivedSessionInfo): BlockNumber {
const remaining = era.sub(sessionInfo.currentEra);
// on the Rust side the current-era >= era-for-unlock (removal done on >)
return createType(api.registry, 'BlockNumber', remaining.gtn(0)
? remaining
.subn(1)
.mul(sessionInfo.eraLength)
.add(sessionInfo.eraLength.sub(sessionInfo.eraProgress))
: 0
);
}
function calculateUnlocking (api: ApiInterfaceRx, stakingLedger: StakingLedger | undefined, sessionInfo: DerivedSessionInfo): DerivedUnlocking[] | undefined {
function calculateUnlocking (api: ApiInterfaceRx, stakingLedger: StakingLedger | undefined, sessionInfo: DeriveSessionInfo): DeriveUnlocking[] | undefined {
if (isUndefined(stakingLedger)) {
return undefined;
}
const unlockingChunks = stakingLedger.unlocking.filter(({ era }): boolean =>
remainingBlocks(api, era.unwrap(), sessionInfo).gtn(0)
era.unwrap().sub(sessionInfo.activeEra).gtn(0)
);
if (!unlockingChunks.length) {
@@ -57,27 +42,27 @@ function calculateUnlocking (api: ApiInterfaceRx, stakingLedger: StakingLedger |
// group the unlock chunks that have the same era and sum their values
const groupedResult = groupByEra(unlockingChunks);
const results = Object.entries(groupedResult).map(([eraString, value]): DerivedUnlocking => ({
value: createType(api.registry, 'Balance', value),
remainingBlocks: remainingBlocks(api, new BN(eraString), sessionInfo)
const results = Object.entries(groupedResult).map(([eraString, value]): DeriveUnlocking => ({
remainingEras: new BN(eraString).sub(sessionInfo.activeEra),
value: api.registry.createType('Balance', value)
}));
return results.length ? results : undefined;
}
function redeemableSum (api: ApiInterfaceRx, stakingLedger: StakingLedger | undefined, sessionInfo: DerivedSessionInfo): Balance {
function redeemableSum (api: ApiInterfaceRx, stakingLedger: StakingLedger | undefined, sessionInfo: DeriveSessionInfo): Balance {
if (isUndefined(stakingLedger)) {
return createType(api.registry, 'Balance');
return api.registry.createType('Balance');
}
return createType(api.registry, 'Balance', stakingLedger.unlocking.reduce((total, { era, value }): BN => {
return remainingBlocks(api, era.unwrap(), sessionInfo).eqn(0)
return api.registry.createType('Balance', stakingLedger.unlocking.reduce((total, { era, value }): BN => {
return sessionInfo.activeEra.gte(era.unwrap())
? total.add(value.unwrap())
: total;
}, new BN(0)));
}
function parseResult (api: ApiInterfaceRx, sessionInfo: DerivedSessionInfo, query: DerivedStakingQuery): DerivedStakingAccount {
function parseResult (api: ApiInterfaceRx, sessionInfo: DeriveSessionInfo, query: DeriveStakingQuery): DeriveStakingAccount {
return {
...query,
redeemable: redeemableSum(api, query.stakingLedger, sessionInfo),
@@ -88,13 +73,13 @@ function parseResult (api: ApiInterfaceRx, sessionInfo: DerivedSessionInfo, quer
/**
* @description From a stash, retrieve the controllerId and fill in all the relevant staking details
*/
export function account (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DerivedStakingAccount> {
return memo((accountId: Uint8Array | string): Observable<DerivedStakingAccount> =>
export function account (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DeriveStakingAccount> {
return memo((accountId: Uint8Array | string): Observable<DeriveStakingAccount> =>
combineLatest([
api.derive.session.info(),
api.derive.staking.query(accountId)
]).pipe(
map(([sessionInfo, query]: [DerivedSessionInfo, DerivedStakingQuery]) =>
map(([sessionInfo, query]: [DeriveSessionInfo, DeriveStakingQuery]) =>
parseResult(api, sessionInfo, query))
));
}
@@ -1,33 +0,0 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId, ValidatorPrefs } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { Observable, combineLatest, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { Option, Vec } from '@polkadot/types';
import { memo } from '../util';
type DeriveControllers = [AccountId[], Option<AccountId>[]];
/**
* @description From the list of stash accounts, retrieve the list of controllers
*/
export function controllers (api: ApiInterfaceRx): () => Observable<DeriveControllers> {
return memo((): Observable<[AccountId[], Option<AccountId>[]]> =>
api.query.staking.validators<ITuple<[Vec<AccountId>, Vec<ValidatorPrefs>]>>().pipe(
switchMap(([stashIds]): Observable<DeriveControllers> =>
combineLatest([
of(stashIds),
// for V2, don't return all the controllers, we call bonded at a later point
api.consts.session
? of([])
: api.query.staking.bonded.multi<Option<AccountId>>(stashIds)
])
)
));
}
+10 -8
View File
@@ -4,25 +4,27 @@
import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId } from '@polkadot/types/interfaces';
import { DerivedStakingQuery, DerivedStakingElected } from '../types';
import { DeriveStakingQuery, DeriveStakingElected } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
export function electedInfo (api: ApiInterfaceRx): () => Observable<DerivedStakingElected> {
return memo((): Observable<DerivedStakingElected> =>
export function electedInfo (api: ApiInterfaceRx): () => Observable<DeriveStakingElected> {
return memo((): Observable<DeriveStakingElected> =>
api.derive.staking.validators().pipe(
switchMap(({ nextElected }): Observable<[AccountId[], DerivedStakingQuery[]]> =>
switchMap(({ nextElected }): Observable<[AccountId[], DeriveStakingQuery[]]> =>
combineLatest([
of(nextElected),
combineLatest(nextElected.map((accountId): Observable<DerivedStakingQuery> =>
api.derive.staking.query(accountId)
))
combineLatest(
nextElected.map((accountId): Observable<DeriveStakingQuery> =>
api.derive.staking.query(accountId)
)
)
])
),
map(([nextElected, info]): DerivedStakingElected => ({
map(([nextElected, info]): DeriveStakingElected => ({
info,
nextElected
}))
+18 -20
View File
@@ -8,12 +8,14 @@ import { DeriveEraExposure, DeriveEraNominatorExposure, DeriveEraValidatorExposu
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap, take } from 'rxjs/operators';
import { map, switchMap } from 'rxjs/operators';
import { StorageKey } from '@polkadot/types';
import { memo } from '../util';
function mapStakers (era: EraIndex, stakers: [StorageKey, Exposure][]): DeriveEraExposure {
type KeysAndExposures = [StorageKey, Exposure][];
function mapStakers (era: EraIndex, stakers: KeysAndExposures): DeriveEraExposure {
const nominators: DeriveEraNominatorExposure = {};
const validators: DeriveEraValidatorExposure = {};
@@ -33,27 +35,23 @@ function mapStakers (era: EraIndex, stakers: [StorageKey, Exposure][]): DeriveEr
return { era, nominators, validators };
}
export function eraExposure (api: ApiInterfaceRx): (era: EraIndex) => Observable<DeriveEraExposure> {
return memo((era: EraIndex): Observable<DeriveEraExposure> =>
api.query.staking.erasStakersClipped.entries(era).pipe(
map((stakers) => mapStakers(era, stakers))
)
);
}
export function erasExposure (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraExposure[]> {
return memo((withActive?: boolean | BN | number): Observable<DeriveEraExposure[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras): Observable<[EraIndex[], [StorageKey, Exposure][][]]> =>
combineLatest([
of(eras),
eras.length
? combineLatest(
// we could just do entries over the full set, however the set can be quite large - split it into
// batches - may need to re-visit this, or alternatively use pages keys for exceptionally large sets
eras.map((era): Observable<[StorageKey, Exposure][]> =>
api.query.staking.erasStakersClipped.entries(era).pipe(take(1))
)
)
: of([])
])
),
map(([eras, erasStakers]): DeriveEraExposure[] =>
eras.map((era, index): DeriveEraExposure =>
mapStakers(era, erasStakers[index])
)
switchMap((eras): Observable<DeriveEraExposure[]> =>
eras.length
? combineLatest(
eras.map((era) => api.derive.staking.eraExposure(era))
)
: of([])
)
)
);
@@ -0,0 +1,46 @@
// 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 { EraIndex, ValidatorPrefs } from '@polkadot/types/interfaces';
import { DeriveEraPrefs, DeriveEraValPrefs } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { StorageKey } from '@polkadot/types';
import { memo } from '../util';
function mapPrefs (era: EraIndex, all: [StorageKey, ValidatorPrefs][]): DeriveEraPrefs {
const validators: DeriveEraValPrefs = {};
all.forEach(([key, prefs]): void => {
validators[key.args[1].toString()] = prefs;
});
return { era, validators };
}
export function eraPrefs (api: ApiInterfaceRx): (era: EraIndex) => Observable<DeriveEraPrefs> {
return memo((era: EraIndex): Observable<DeriveEraPrefs> =>
api.query.staking.erasValidatorPrefs.entries(era).pipe(
map((prefs) => mapPrefs(era, prefs))
)
);
}
export function erasPrefs (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraPrefs[]> {
return memo((withActive?: boolean | BN | number): Observable<DeriveEraPrefs[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras): Observable<DeriveEraPrefs[]> =>
eras.length
? combineLatest(
eras.map((era) => api.derive.staking.eraPrefs(era))
)
: of([])
)
)
);
}
@@ -0,0 +1,55 @@
// 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 { BalanceOf, EraIndex, Perbill } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DeriveEraSlashes, DeriveEraValSlash } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option, StorageKey } from '@polkadot/types';
import { memo } from '../util';
function mapSlashes (era: EraIndex, noms: [StorageKey, Option<BalanceOf>][], vals: [StorageKey, Option<ITuple<[Perbill, BalanceOf]>>][]): DeriveEraSlashes {
const nominators: DeriveEraValSlash = {};
const validators: DeriveEraValSlash = {};
noms.forEach(([key, optBalance]): void => {
nominators[key.args[1].toString()] = optBalance.unwrap();
});
vals.forEach(([key, optRes]): void => {
validators[key.args[1].toString()] = optRes.unwrapOrDefault()[1];
});
return { era, nominators, validators };
}
export function eraSlashes (api: ApiInterfaceRx): (era: EraIndex) => Observable<DeriveEraSlashes> {
return memo((era: EraIndex): Observable<DeriveEraSlashes> =>
combineLatest([
api.query.staking.nominatorSlashInEra.entries(era),
api.query.staking.validatorSlashInEra.entries(era)
]).pipe(
map(([noms, vals]) => mapSlashes(era, noms, vals))
)
);
}
export function erasSlashes (api: ApiInterfaceRx): (withActive?: boolean | BN | number) => Observable<DeriveEraSlashes[]> {
return memo((withActive?: boolean | BN | number): Observable<DeriveEraSlashes[]> =>
api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras): Observable<DeriveEraSlashes[]> =>
eras.length
? combineLatest(
eras.map((era) => api.derive.staking.eraSlashes(era))
)
: of([])
)
)
);
}
+6 -1
View File
@@ -6,12 +6,17 @@ export * from './account';
export * from './erasExposure';
export * from './erasHistoric';
export * from './erasPoints';
export * from './erasPrefs';
export * from './erasRewards';
export * from './controllers';
export * from './erasSlashes';
export * from './electedInfo';
export * from './overview';
export * from './ownExposure';
export * from './ownSlashes';
export * from './query';
export * from './stakerExposure';
export * from './stakerPoints';
export * from './stakerRewards';
export * from './stakerSlashes';
export * from './stashes';
export * from './validators';
+11 -12
View File
@@ -2,24 +2,23 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, EraIndex, EraPoints, EraRewardPoints, RewardPoint } from '@polkadot/types/interfaces';
import { AccountId, EraPoints, EraRewardPoints, RewardPoint } from '@polkadot/types/interfaces';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DerivedStakingOverview } from '../types';
import { DeriveStakingOverview } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { createType } from '@polkadot/types';
import { memo } from '../util';
function retrievePointsPrev (api: ApiInterfaceRx, activeEra: EraIndex, currentElected: AccountId[]): Observable<EraRewardPoints> {
return api.query.staking.currentEraPointsEarned<EraPoints>(activeEra).pipe(
function retrievePointsPrev (api: ApiInterfaceRx, currentElected: AccountId[]): Observable<EraRewardPoints> {
return api.query.staking.currentEraPointsEarned<EraPoints>().pipe(
map(({ individual, total }): EraRewardPoints =>
createType(api.registry, 'EraRewardPoints', {
api.registry.createType('EraRewardPoints', {
total,
individual: new Map<AccountId, RewardPoint>(
individual
.map((points): RewardPoint => createType(api.registry, 'RewardPoint', points))
.map((points): RewardPoint => api.registry.createType('RewardPoint', points))
.map((points, index): [AccountId, RewardPoint] => [currentElected[index], points])
)
})
@@ -30,8 +29,8 @@ function retrievePointsPrev (api: ApiInterfaceRx, activeEra: EraIndex, currentEl
/**
* @description Retrieve the staking overview, including elected and points earned
*/
export function overview (api: ApiInterfaceRx): () => Observable<DerivedStakingOverview> {
return memo((): Observable<DerivedStakingOverview> =>
export function overview (api: ApiInterfaceRx): () => Observable<DeriveStakingOverview> {
return memo((): Observable<DeriveStakingOverview> =>
combineLatest([
api.derive.session.indexes(),
api.derive.staking.validators()
@@ -42,11 +41,11 @@ export function overview (api: ApiInterfaceRx): () => Observable<DerivedStakingO
api.query.staking.erasRewardPoints
? api.query.staking.erasRewardPoints<EraRewardPoints>(indexes.activeEra)
: api.query.staking.currentEraPointsEarned
? retrievePointsPrev(api, indexes.activeEra, nextElected)
: of(createType(api.registry, 'EraRewardPoints'))
? retrievePointsPrev(api, nextElected)
: of(api.registry.createType('EraRewardPoints'))
])
),
map(([info, eraPoints]): DerivedStakingOverview => ({
map(([info, eraPoints]): DeriveStakingOverview => ({
...info, eraPoints
}))
));
@@ -0,0 +1,37 @@
// 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 { DeriveOwnExposure } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
export function ownExposure (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean | BN | number) => Observable<DeriveOwnExposure[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean | BN | number): Observable<DeriveOwnExposure[]> => {
return api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) =>
eras.length
? combineLatest(
eras.map((era) => combineLatest([
of(era),
api.query.staking.erasStakersClipped(era, accountId),
api.query.staking.erasStakers(era, accountId)
]))
)
: of([])
),
map((result): DeriveOwnExposure[] =>
result.map(([era, clipped, exposure]): DeriveOwnExposure => ({
clipped,
era,
exposure
}))
)
);
});
}
@@ -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 { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveStakerSlashes } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
export function ownSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean | BN | number) => Observable<DeriveStakerSlashes[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean | BN | number): Observable<DeriveStakerSlashes[]> => {
return api.derive.staking.erasHistoric(withActive).pipe(
switchMap((eras) =>
eras.length
? combineLatest(
eras.map((era) => combineLatest([
of(era),
api.query.staking.nominatorSlashInEra(era, accountId),
api.query.staking.validatorSlashInEra(era, accountId)
]))
)
: of([])
),
map((result): DeriveStakerSlashes[] =>
result.map(([era, optNom, optVal]): DeriveStakerSlashes => ({
era,
total: optVal.isSome
? optVal.unwrap()[1]
: optNom.isSome
? optNom.unwrap()
: api.registry.createType('Balance')
}))
)
);
});
}
+21 -14
View File
@@ -5,15 +5,15 @@
import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId, Exposure, Keys, Nominations, RewardDestination, ValidatorPrefs } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DerivedStakingQuery } from '../types';
import { DeriveStakingQuery } from '../types';
import { combineLatest, Observable, of } from 'rxjs';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { createType, Option, Vec } from '@polkadot/types';
import { Option, Vec } from '@polkadot/types';
import { memo } from '../util';
type MultiResult = [Option<AccountId>, Option<ITuple<[Nominations]>>, RewardDestination, ITuple<[ValidatorPrefs]>, Option<Keys>, Exposure];
type MultiResult = [Option<AccountId>, Option<ITuple<[Nominations]> | Nominations>, RewardDestination, ITuple<[ValidatorPrefs]> | ValidatorPrefs, Option<Keys>, Exposure];
function unwrapSessionIds (stashId: AccountId, queuedKeys: [AccountId, Keys][], nextKeys: Option<Keys>): { nextSessionIds: AccountId[]; sessionIds: AccountId[] } {
const sessionIds = (queuedKeys.find(([currentId]): boolean =>
@@ -55,20 +55,27 @@ 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, [controllerIdOpt, nominatorsOpt, rewardDestination, validatorPrefs, nextKeys, exposure]]: [Vec<ITuple<[AccountId, Keys]>>, MultiResult]): Observable<DeriveStakingQuery> {
const controllerId = controllerIdOpt.unwrapOr(null);
const nominators = nominatorsOpt.unwrapOr(null);
return controllerId
? api.query.staking.ledger(controllerId).pipe(
map((stakingLedgerOpt): DerivedStakingQuery => ({
map((stakingLedgerOpt): DeriveStakingQuery => ({
accountId: stashId,
controllerId,
exposure,
nominators: nominatorsOpt.unwrapOr([{ targets: [] }])[0].targets,
nominators: nominators
? Array.isArray(nominators)
? nominators[0].targets
: nominators.targets
: [],
rewardDestination,
stakingLedger: stakingLedgerOpt.unwrapOr(undefined),
stashId,
validatorPrefs,
validatorPrefs: Array.isArray(validatorPrefs)
? validatorPrefs[0]
: validatorPrefs,
...unwrapSessionIds(stashId, queuedKeys, nextKeys)
}))
)
@@ -78,9 +85,9 @@ function retrieveController (api: ApiInterfaceRx, stashId: AccountId, [queuedKey
/**
* @description From a stash, retrieve the controllerId and all relevant details
*/
export function query (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DerivedStakingQuery> {
return memo((accountId: Uint8Array | string): Observable<DerivedStakingQuery> => {
const stashId = createType(api.registry, 'AccountId', accountId);
export function query (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DeriveStakingQuery> {
return memo((accountId: Uint8Array | string): Observable<DeriveStakingQuery> => {
const stashId = api.registry.createType('AccountId', accountId);
return combineLatest([
api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>(),
@@ -88,15 +95,15 @@ export function query (api: ApiInterfaceRx): (accountId: Uint8Array | string) =>
? retrieveCurr(api, stashId)
: retrievePrev(api, stashId)
]).pipe(
switchMap((result): Observable<DerivedStakingQuery> =>
switchMap((result): Observable<DeriveStakingQuery> =>
retrieveController(api, stashId, result)
)
);
});
}
export function queryMulti (api: ApiInterfaceRx): (...accountIds: (Uint8Array | string)[]) => Observable<DerivedStakingQuery[]> {
return memo((...accountIds: (Uint8Array | string)[]): Observable<DerivedStakingQuery[]> =>
export function queryMulti (api: ApiInterfaceRx): (...accountIds: (Uint8Array | string)[]) => Observable<DeriveStakingQuery[]> {
return memo((...accountIds: (Uint8Array | string)[]): Observable<DeriveStakingQuery[]> =>
combineLatest(
accountIds.map((accountId) => api.derive.staking.query(accountId))
)
@@ -4,7 +4,7 @@
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Balance } from '@polkadot/types/interfaces';
import { DeriveEraPoints, DeriveEraRewards, DeriveStakerExposure, DeriveStakerReward } from '../types';
import { DeriveEraPoints, DeriveEraPrefs, DeriveEraRewards, DeriveEraValPrefs, DeriveStakerExposure, DeriveStakerReward } from '../types';
import BN from 'bn.js';
import { Observable, combineLatest } from 'rxjs';
@@ -12,18 +12,24 @@ import { map } from 'rxjs/operators';
import { memo } from '../util';
type Result = [DeriveEraPoints[], DeriveEraRewards[], DeriveStakerExposure[]];
const ZERO = new BN(0);
type Result = [DeriveEraPoints[], DeriveEraPrefs[], DeriveEraRewards[], DeriveStakerExposure[]];
function parseRewards (api: ApiInterfaceRx, stakerId: string, [erasPoints, erasRewards, exposures]: Result): DeriveStakerReward[] {
const ZERO = new BN(0);
const COMM_DIV = new BN(1_000_000_000);
function parseRewards (api: ApiInterfaceRx, stakerId: string, [erasPoints, erasPrefs, erasRewards, exposures]: Result): DeriveStakerReward[] {
return exposures.map(({ era, isEmpty, isValidator, nominating, validators: eraValidators }): DeriveStakerReward => {
const { eraPoints, validators: allValPoints } = erasPoints.find((p) => p.era.eq(era)) || { eraPoints: new BN(0), validators: {} };
const { eraReward } = erasRewards.find((r) => r.era.eq(era)) || { eraReward: new BN(0) };
const { eraReward } = erasRewards.find((r) => r.era.eq(era)) || { eraReward: ZERO };
const { validators: allValPrefs } = erasPrefs.find((p) => p.era.eq(era)) || { validators: {} as DeriveEraValPrefs };
const validators: Record<string, Balance> = {};
let total = ZERO;
Object.entries(eraValidators).forEach(([validatorId, exposure]): void => {
const valPoints = allValPoints[validatorId] || new BN(0);
const valPoints = allValPoints[validatorId] || ZERO;
const valComm = allValPrefs[validatorId]?.commission.unwrap() || ZERO;
const avail = eraReward.mul(valPoints).div(eraPoints);
const valCut = valComm.mul(avail).div(COMM_DIV);
const expTotal = exposure.total.unwrap();
let value: BN | undefined;
@@ -40,7 +46,7 @@ function parseRewards (api: ApiInterfaceRx, stakerId: string, [erasPoints, erasR
: ZERO;
}
value = eraReward.mul(valPoints).mul(staked).div(eraPoints).div(expTotal);
value = avail.sub(valCut).mul(staked).div(expTotal).add(validatorId === stakerId ? valCut : ZERO);
total = total.add(value);
}
@@ -64,6 +70,7 @@ export function stakerRewards (api: ApiInterfaceRx): (accountId: Uint8Array | st
return combineLatest([
api.derive.staking.erasPoints(startEra),
api.derive.staking.erasPrefs(startEra),
api.derive.staking.erasRewards(startEra),
api.derive.staking.stakerExposure(stakerId, startEra)
]).pipe(
@@ -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 { DeriveStakerSlashes } from '../types';
import BN from 'bn.js';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { memo } from '../util';
export function stakerSlashes (api: ApiInterfaceRx): (accountId: Uint8Array | string, withActive?: boolean | BN | number) => Observable<DeriveStakerSlashes[]> {
return memo((accountId: Uint8Array | string, withActive?: boolean | BN | number): Observable<DeriveStakerSlashes[]> => {
const stakerId = api.registry.createType('AccountId', accountId).toString();
return api.derive.staking.erasSlashes(withActive).pipe(
map((slashes): DeriveStakerSlashes[] =>
slashes.map(({ era, nominators, validators }): DeriveStakerSlashes => ({
era,
total: nominators[stakerId] || validators[stakerId] || api.registry.createType('Balance')
}))
)
);
});
}
@@ -0,0 +1,28 @@
// 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, ValidatorPrefs } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Vec } from '@polkadot/types';
import { memo } from '../util';
/**
* @description Retrieve the list of all validator stashes
*/
export function stashes (api: ApiInterfaceRx): () => Observable<AccountId[]> {
return memo((): Observable<AccountId[]> =>
api.query.staking.validators.creator.meta.type.asMap.linked.isTrue
? api.query.staking.validators<ITuple<[Vec<AccountId>, Vec<ValidatorPrefs>]>>().pipe(
map(([stashIds]) => stashIds)
)
: api.query.staking.validators.keys().pipe(
map((keys) => keys.map((key) => key.args[0] as AccountId))
)
);
}
+40 -10
View File
@@ -2,22 +2,39 @@
// 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, EraIndex, EraRewardPoints, Exposure, Keys, RewardDestination, RewardPoint, StakingLedger, ValidatorPrefs } from '@polkadot/types/interfaces';
import { AccountId, Balance, EraIndex, EraRewardPoints, Exposure, Keys, RewardDestination, RewardPoint, StakingLedger, ValidatorPrefs } from '@polkadot/types/interfaces';
import { DeriveSessionIndexes } from '../session/types';
import BN from 'bn.js';
export type DeriveEraValPoints = Record<string, RewardPoint>;
export type DeriveEraValPrefs = Record<string, ValidatorPrefs>;
export type DeriveEraValSlash = Record<string, Balance>;
export interface DeriveEraPoints {
era: EraIndex;
eraPoints: RewardPoint;
validators: DeriveEraValPoints;
}
export interface DeriveEraPrefs {
era: EraIndex;
validators: DeriveEraValPrefs;
}
export interface DeriveEraRewards {
era: EraIndex;
eraReward: Balance;
}
export interface DeriveEraSlashes {
era: EraIndex;
nominators: DeriveEraValSlash;
validators: DeriveEraValSlash;
}
export interface DeriveStakerPoints {
era: EraIndex;
eraPoints: RewardPoint;
@@ -34,6 +51,14 @@ export interface DeriveEraExposure {
validators: DeriveEraValidatorExposure;
}
export interface DeriveOwnExposure {
clipped: Exposure;
era: EraIndex;
exposure: Exposure;
}
export type DeriveOwnSlashes = DeriveStakerSlashes;
export interface DeriveStakerExposure {
era: EraIndex;
isEmpty: boolean;
@@ -51,9 +76,14 @@ export interface DeriveStakerReward {
total: Balance;
}
export interface DerivedStakingElected {
export interface DeriveStakerSlashes {
era: EraIndex;
total: Balance;
}
export interface DeriveStakingElected {
nextElected: AccountId[];
info: DerivedStakingQuery[];
info: DeriveStakingQuery[];
}
export interface DeriveStakingValidators {
@@ -61,7 +91,7 @@ export interface DeriveStakingValidators {
validators: AccountId[];
}
export interface DerivedStakingStash {
export interface DeriveStakingStash {
controllerId?: AccountId;
exposure?: Exposure;
nominators?: AccountId[];
@@ -72,25 +102,25 @@ export interface DerivedStakingStash {
validatorPrefs?: ValidatorPrefs;
}
export interface DerivedStakingQuery extends DerivedStakingStash {
export interface DeriveStakingQuery extends DeriveStakingStash {
accountId: AccountId;
nextSessionIds: AccountId[];
sessionIds: AccountId[];
stakingLedger?: StakingLedger;
}
export interface DerivedStakingAccount extends DerivedStakingQuery {
export interface DeriveStakingAccount extends DeriveStakingQuery {
redeemable?: Balance;
unlocking?: DerivedUnlocking[];
unlocking?: DeriveUnlocking[];
}
export interface DerivedStakingOverview extends DeriveSessionIndexes {
export interface DeriveStakingOverview extends DeriveSessionIndexes {
eraPoints: EraRewardPoints;
nextElected: AccountId[];
validators: AccountId[];
}
export type DerivedUnlocking = {
remainingBlocks: BlockNumber;
export type DeriveUnlocking = {
remainingEras: BN;
value: Balance;
};
+16 -14
View File
@@ -7,21 +7,25 @@ import { AccountId } from '@polkadot/types/interfaces';
import { DeriveStakingValidators } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap, take } from 'rxjs/operators';
import { map, switchMap } from 'rxjs/operators';
import { StorageKey } from '@polkadot/types';
import { memo } from '../util';
function queryNextStakers (api: ApiInterfaceRx): Observable<AccountId[]> {
// only populate for next era in the last session, so track both here - entries are not
// subscriptions, so we need a trigger - currentIndex acts as that trigger to refresh
return api.derive.session.indexes().pipe(
switchMap(({ activeEra }): Observable<StorageKey[]> =>
api.query.staking.erasStakers.keys(activeEra.addn(1)).pipe(take(1))
),
map((keys): AccountId[] =>
keys.map((key): AccountId => key.args[1] as AccountId)
)
export function nextElected (api: ApiInterfaceRx): () => Observable<AccountId[]> {
return memo((): Observable<AccountId[]> =>
api.query.staking.erasStakers
? api.derive.session.indexes().pipe(
// only populate for next era in the last session, so track both here - entries are not
// subscriptions, so we need a trigger - currentIndex acts as that trigger to refresh
switchMap(({ currentEra }): Observable<StorageKey[]> =>
api.query.staking.erasStakers.keys(currentEra)
),
map((keys): AccountId[] =>
keys.map((key): AccountId => key.args[1] as AccountId)
)
)
: api.query.staking.currentElected<AccountId[]>()
);
}
@@ -38,9 +42,7 @@ export function validators (api: ApiInterfaceRx): () => Observable<DeriveStaking
? api.query.session.validators()
: of([]),
api.query.staking
? api.query.staking.erasStakers
? queryNextStakers(api)
: api.query.staking.currentElected<AccountId[]>()
? api.derive.staking.nextElected()
: of([])
]).pipe(
map(([validators, nextElected]): DeriveStakingValidators => ({
@@ -3,12 +3,12 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DerivedCollectiveProposals } from '../types';
import { DeriveCollectiveProposals } from '../types';
import { Observable } from 'rxjs';
import { proposals as collectiveProposals } from '../collective';
import { memo } from '../util';
export function proposals (api: ApiInterfaceRx): () => Observable<DerivedCollectiveProposals> {
export function proposals (api: ApiInterfaceRx): () => Observable<DeriveCollectiveProposals> {
return memo(collectiveProposals(api, 'technicalCommittee'));
}
+13 -13
View File
@@ -4,11 +4,11 @@
import { ApiInterfaceRx } from '@polkadot/api/types';
import { ProposalIndex, TreasuryProposal } from '@polkadot/types/interfaces';
import { DerivedCollectiveProposals, DerivedTreasuryProposal, DerivedTreasuryProposals } from '../types';
import { DeriveCollectiveProposals, DeriveTreasuryProposal, DeriveTreasuryProposals } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { createType, Option } from '@polkadot/types';
import { Option } from '@polkadot/types';
import { memo } from '../util';
@@ -16,13 +16,13 @@ interface Result {
allIds: ProposalIndex[];
allProposals: Option<TreasuryProposal>[];
approvalIds: ProposalIndex[];
councilProposals: DerivedCollectiveProposals;
councilProposals: DeriveCollectiveProposals;
proposalCount: ProposalIndex;
}
function parseResult (_api: ApiInterfaceRx, { allIds, allProposals, approvalIds, councilProposals, proposalCount }: Result): DerivedTreasuryProposals {
const approvals: DerivedTreasuryProposal[] = [];
const proposals: DerivedTreasuryProposal[] = [];
function parseResult (_api: ApiInterfaceRx, { allIds, allProposals, approvalIds, councilProposals, proposalCount }: Result): DeriveTreasuryProposals {
const approvals: DeriveTreasuryProposal[] = [];
const proposals: DeriveTreasuryProposal[] = [];
const councilTreasury = councilProposals.filter(({ proposal: { methodName, sectionName } }): boolean =>
sectionName === 'treasury' &&
['approveProposal', 'rejectProposal'].includes(methodName)
@@ -47,7 +47,7 @@ function parseResult (_api: ApiInterfaceRx, { allIds, allProposals, approvalIds,
return { approvals, proposalCount, proposals };
}
function retrieveProposals (api: ApiInterfaceRx, proposalCount: ProposalIndex, approvalIds: ProposalIndex[]): Observable<DerivedTreasuryProposals> {
function retrieveProposals (api: ApiInterfaceRx, proposalCount: ProposalIndex, approvalIds: ProposalIndex[]): Observable<DeriveTreasuryProposals> {
const proposalIds: ProposalIndex[] = [];
const count = proposalCount.toNumber();
@@ -55,7 +55,7 @@ function retrieveProposals (api: ApiInterfaceRx, proposalCount: ProposalIndex, a
const isApproval = approvalIds.some((id): boolean => id.eqn(index));
if (!isApproval) {
proposalIds.push(createType(api.registry, 'ProposalIndex', index));
proposalIds.push(api.registry.createType('ProposalIndex', index));
}
}
@@ -65,7 +65,7 @@ function retrieveProposals (api: ApiInterfaceRx, proposalCount: ProposalIndex, a
api.query.treasury.proposals.multi<Option<TreasuryProposal>>(allIds),
api.derive.council.proposals()
]).pipe(
map(([allProposals, councilProposals]: [Option<TreasuryProposal>[], DerivedCollectiveProposals]): DerivedTreasuryProposals =>
map(([allProposals, councilProposals]: [Option<TreasuryProposal>[], DeriveCollectiveProposals]): DeriveTreasuryProposals =>
parseResult(api, { allIds, allProposals, approvalIds, councilProposals, proposalCount })
)
);
@@ -74,8 +74,8 @@ function retrieveProposals (api: ApiInterfaceRx, proposalCount: ProposalIndex, a
/**
* @description Retrieve all active and approved treasury proposals, along with their info
*/
export function proposals (api: ApiInterfaceRx): () => Observable<DerivedTreasuryProposals> {
return memo((): Observable<DerivedTreasuryProposals> =>
export function proposals (api: ApiInterfaceRx): () => Observable<DeriveTreasuryProposals> {
return memo((): Observable<DeriveTreasuryProposals> =>
api.query.treasury
? combineLatest([
api.query.treasury.proposalCount(),
@@ -87,8 +87,8 @@ export function proposals (api: ApiInterfaceRx): () => Observable<DerivedTreasur
)
: of({
approvals: [],
proposalCount: createType(api.registry, 'ProposalIndex'),
proposalCount: api.registry.createType('ProposalIndex'),
proposals: []
} as DerivedTreasuryProposals)
} as DeriveTreasuryProposals)
);
}
+7
View File
@@ -0,0 +1,7 @@
// 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 BN from 'bn.js';
export const MAX_FINALITY_LAG = new BN(5);
+30
View File
@@ -0,0 +1,30 @@
// 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 { EventRecord, Hash, SignedBlock } from '@polkadot/types/interfaces';
import { Observable, combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { memo } from '../util';
interface Result {
block: SignedBlock;
events: EventRecord[];
}
export function events (api: ApiInterfaceRx): (at: Hash) => Observable<Result> {
return memo((at: Hash): Observable<Result> =>
combineLatest([
api.query.system.events.at(at),
api.rpc.chain.getBlock(at)
]).pipe(
map(([events, block]) => ({
block,
events
}))
)
);
}
+6
View File
@@ -0,0 +1,6 @@
// 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.
export * from './events';
export * from './signingInfo';
+69
View File
@@ -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 { Header, Index } from '@polkadot/types/interfaces';
import { AnyNumber, Codec, IExtrinsicEra } from '@polkadot/types/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 { isNumber, isUndefined } from '@polkadot/util';
interface Result {
header: Header | null;
mortalLength: number;
nonce: Index;
}
// default here to 5 min eras, adjusted based on the actual blocktime
const FALLBACK_PERIOD = new BN(6 * 1000);
const MAX_FINALITY_LAG = new BN(5);
const MORTAL_PERIOD = new BN(5 * 60 * 1000);
function latestNonce (api: ApiInterfaceRx, address: string): Observable<Index> {
return api.derive.balances.account(address).pipe(
map(({ accountNonce }): Index => accountNonce)
);
}
function signingHeader (api: ApiInterfaceRx): Observable<Header> {
return combineLatest([
api.rpc.chain.getHeader(),
api.rpc.chain.getFinalizedHead().pipe(
switchMap((hash) => api.rpc.chain.getHeader(hash))
)
]).pipe(
map(([current, finalized]): Header =>
// determine the hash to use, current when lag > max, else finalized
current.number.unwrap().sub(finalized.number.unwrap()).gt(MAX_FINALITY_LAG)
? current
: finalized
)
);
}
export function signingInfo (api: ApiInterfaceRx): (address: string, nonce?: AnyNumber | Codec, era?: IExtrinsicEra | number) => Observable<Result> {
// no memo, we want to do this fresh on each run
return (address: string, nonce?: AnyNumber | Codec, era?: IExtrinsicEra | number): Observable<Result> =>
combineLatest([
// retrieve nonce if none was specified
isUndefined(nonce)
? latestNonce(api, address)
: of(api.registry.createType('Index', nonce)),
// if no era (create) or era > 0 (mortal), do block retrieval
(isUndefined(era) || (isNumber(era) && era > 0))
? signingHeader(api)
: of(null)
]).pipe(
map(([nonce, header]) => ({
header,
nonce,
mortalLength: MORTAL_PERIOD
.div(api.consts.babe?.expectedBlockTime || api.consts.timestamp?.minimumPeriod.muln(2) || FALLBACK_PERIOD)
.add(MAX_FINALITY_LAG)
.toNumber()
}))
);
}
@@ -1,57 +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 { ReferendumIndex, ReferendumInfo } from '@polkadot/types/interfaces/democracy';
import { AnyJson, Constructor, Registry } from '@polkadot/types/types';
import BN from 'bn.js';
import democracyTypes from '@polkadot/types/interfaces/democracy/definitions';
import { Struct } from '@polkadot/types';
// We can ignore the properties, added via Struct.with
const _ReferendumInfo: Constructor<ReferendumInfo> = Struct.with(democracyTypes.types.ReferendumInfo as any) as any;
/**
* @name ReferendumInfoExtended
* @description
* A [[ReferendumInfo]] with an additional `index` field
*/
export default class ReferendumInfoExtended extends _ReferendumInfo {
readonly #index: ReferendumIndex;
constructor (registry: Registry, value: ReferendumInfo | ReferendumInfoExtended, index?: BN | number) {
super(registry, value);
this.#index = value instanceof ReferendumInfoExtended
? value.index
: registry.createType('ReferendumIndex', index);
}
/**
* @description Convenience getter, returns the referendumIndex
*/
public get index (): ReferendumIndex {
return this.#index;
}
/**
* @description Creates a human-friendly JSON representation
*/
public toHuman (isExtended?: boolean): AnyJson {
return {
...super.toHuman(isExtended) as { [index: string]: AnyJson },
index: this.index.toHuman(isExtended)
};
}
/**
* @description Creates the JSON representation
*/
public toJSON (): AnyJson {
return {
...super.toJSON() as { [index: string]: AnyJson },
index: this.index.toJSON()
};
}
}
-1
View File
@@ -3,4 +3,3 @@
// of the Apache-2.0 license. See the LICENSE file for details.
export { default as HeaderExtended } from './HeaderExtended';
export { default as ReferendumInfoExtended } from './ReferendumInfoExtended';

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