Compare commits

..
145 Commits
Author SHA1 Message Date
Github Actions f6490217ec [CI Skip] 1.1.1
skip-checks: true
2020-02-06 15:12:35 +00:00
Jaco Greeff 601cc62d70 1.1 (#1815) 2020-02-06 16:05:04 +01:00
Github Actions 201480be56 [CI Skip] 1.1.0-beta.22
skip-checks: true
2020-02-06 14:17:09 +00:00
Jaco Greeff 519823bc0e Add resolver for jest (#1813) 2020-02-06 15:09:36 +01:00
Github Actions 0b134c1eb8 [CI Skip] 1.1.0-beta.21
skip-checks: true
2020-02-06 13:16:34 +00:00
Jaco Greeff e6e96aa9c9 Make indices module optional (#1812)
* Make indices optional

* Updtae contracts with optional creation

* Flatten contract fees
2020-02-06 14:09:29 +01:00
Github Actions 84d0d8594e [CI Skip] 1.1.0-beta.20
skip-checks: true
2020-02-06 09:54:57 +00:00
Jaco Greeff 6be25966d8 Enum .toJSON() to return type name as specified (#1811)
* Enum `.toJSON()` to return type name as specified

* Fix text compares
2020-02-06 10:48:33 +01:00
Github Actions a5eb11e5f3 [CI Skip] 1.1.0-beta.19
skip-checks: true
2020-02-05 15:22:43 +00:00
Jaco Greeff 19f87aac4d Council memebrs with no election info (#1810) 2020-02-05 16:15:36 +01:00
Github Actions b217a59310 [CI Skip] 1.1.0-beta.18
skip-checks: true
2020-02-05 14:23:56 +00:00
Jaco Greeff 2de7a3c130 Add .keyPrefix for storage keys (#1809)
* Add .keyPrefix for storage keys

* Fix hex length
2020-02-05 15:15:49 +01:00
Github Actions deecf4853e [CI Skip] 1.1.0-beta.17
skip-checks: true
2020-02-04 15:19:57 +00:00
Jaco Greeff 8889e69341 Bump common (#1807)
* Bump common

* yarn.lock
2020-02-04 16:12:18 +01:00
Github Actions 14194a363e [CI Skip] 1.1.0-beta.16
skip-checks: true
2020-02-04 11:23:05 +00:00
Jaco Greeff 9c50e81ab9 Cleanup sanitize boxes (#1805)
* Cleanup sanitize boxes

* yarn.lock

* Add space before box as allowed
2020-02-04 12:16:18 +01:00
Jaco Greeff 6505e73355 Adjust submittable augmentation (#1806)
* Adjust submittable augmentation

* Add missing extends
2020-02-04 12:15:42 +01:00
Github Actions cefeb37ae6 [CI Skip] 1.1.0-beta.15
skip-checks: true
2020-02-03 16:32:53 +00:00
Jaco Greeff 9e29e89baf Update known extensions (with Polkadot) (#1800)
* Update known extensions (with Polkadot)

* Split definitions for signed extensions
2020-02-03 17:25:33 +01:00
Github Actions b82c90679d [CI Skip] 1.1.0-beta.14
skip-checks: true
2020-02-03 12:49:36 +00:00
Jaco Greeff eeb8d20e58 Bump common (detection) (#1799) 2020-02-03 13:42:49 +01:00
Github Actions b891edbd37 [CI Skip] 1.1.0-beta.13
skip-checks: true
2020-02-03 11:03:16 +00:00
Jaco Greeff 2ee3afcd61 Expand enum & struct defnitions, generator strict mode (#1798) 2020-02-03 11:56:06 +01:00
Github Actions 328630fb17 [CI Skip] 1.1.0-beta.12
skip-checks: true
2020-02-03 09:27:36 +00:00
Jaco Greeff 325080cf71 Cleanup some generation duplication (#1797)
* Cleanup some generation duplicaton

* Override for Metadata import

* Import order in generators
2020-02-03 10:20:33 +01:00
Github Actions 549a536328 [CI Skip] 1.1.0-beta.11
skip-checks: true
2020-02-02 19:26:52 +00:00
Jaco Greeff 23f41a0bab Exclude all augment from cc 2020-02-02 20:19:41 +01:00
Jaco Greeff 5e0c0ba91a Align jsonrpc augmentation with others (#1796) 2020-02-02 20:16:41 +01:00
Github Actions 812a077e63 [CI Skip] 1.1.0-beta.10
skip-checks: true
2020-02-02 18:54:18 +00:00
Jaco Greeff 6ba28c8ad2 Expand simple enums in type generation (#1795) 2020-02-02 19:47:19 +01:00
Github Actions 6cd0074ce4 [CI Skip] 1.1.0-beta.9
skip-checks: true
2020-02-02 18:24:56 +00:00
Jaco Greeff b3d592357f Override for Vote type (not a struct, not caught) (#1794)
* Override for Vote type (not a struct, not caught)

* Generate simple Vote object (first, Struct to be done)

* Comment for hex type (string)

* Expand conviction (like we should on enum)

* Cool, use conviction def for input

* aye is required

* Remove FIXMEs
2020-02-02 19:17:33 +01:00
Github Actions f499946f1f [CI Skip] 1.1.0-beta.8
skip-checks: true
2020-02-02 08:19:04 +00:00
Jaco Greeff 56e28bed7f Rename frozenFee (#1792) 2020-02-02 09:11:49 +01:00
Github Actions c76fb20a83 [CI Skip] 1.1.0-beta.7
skip-checks: true
2020-02-02 07:57:22 +00:00
Jaco Greeff 9d4b0ea56a Update Substrate with vesting (#1790)
* Update Substrate with vesting

* Update balances & vesting queries with compat)

* Split base account queries

* Linting, simpler referendum voters

* Fix (some) tests
2020-02-02 08:50:37 +01:00
Github Actions f9d569ddd1 [CI Skip] 1.1.0-beta.6
skip-checks: true
2020-02-01 20:27:44 +00:00
Jaco Greeff 7221a3637c Add UInt .isMax() (#1791)
* Add UInt .isMax()

* Filter lockedBlance by max
2020-02-01 21:20:48 +01:00
Github Actions 438c830366 [CI Skip] 1.1.0-beta.5
skip-checks: true
2020-02-01 17:47:00 +00:00
Jaco Greeff 3d0fd5a6a8 Warn on unknown extensions (once per registry) (#1788) 2020-02-01 18:40:45 +01:00
Github Actions de57876c7f [CI Skip] 1.1.0-beta.4
skip-checks: true
2020-02-01 13:24:47 +00:00
Jaco Greeff b24a1ff350 SignedExtension injection into payload (#1778)
* Make a start ... V11 definitions

* V11 conversion

* Fix ErrorMetadataV11

* Extension point for signed extensions

* Add V11 to mapped

* Expand toLatest comments

* Make a start at signer extension defs

* exports

* Extract extension definitions

* Add extension registration

* Remove old override

* Get definition on extrinsic creation

* Add missing V4 base

* Optional extrinsic

* Pull extrinsic version from metadata (if available)

* asLatest.extrinsic should now be available

* Don't export non-types for Extrinsic

* Setup registry with default extensions

* Async test really runs async

* Trace test failures (V1 orig, V4 now)

* CHANGELOG

* Add extension data to actual signature

* Cleanups

* Return cleanups

* Mark all type deocde static internal

* Apply extensions fully to payload

* Cleanup duplication

* ExtrinsicSignature* via createType
2020-02-01 14:17:17 +01:00
Github Actions 5f8c623179 [CI Skip] 1.1.0-beta.3
skip-checks: true
2020-02-01 11:07:19 +00:00
Jaco Greeff 00026a173f Keep original doc-line formats (#1787) 2020-02-01 11:59:47 +01:00
Github Actions 8da895efd4 [CI Skip] 1.1.0-beta.2
skip-checks: true
2020-02-01 10:23:48 +00:00
Jaco Greeff 89d029eca3 Expand bool & Enum generation (#1785)
* Expand bool & Enum generation

* Swap consts to Augmented (align with others)
2020-02-01 11:16:27 +01:00
Github Actions ac2a7eea67 [CI Skip] 1.1.0-beta.1
skip-checks: true
2020-01-31 21:42:23 +00:00
Jaco Greeff 4f0e573adf Cleanup to tx generation (#1784) 2020-01-31 22:34:24 +01:00
Github Actions 8417eff2b3 [CI Skip] 1.1.0-beta.0
skip-checks: true
2020-01-31 14:41:36 +00:00
Jaco Greeff 4aa5693906 Extend type generation (#1783)
* Cleanup type overrides

* Generate (with catch-all removal)

* Progress

* Re-gen tx types

* Remove unneeded option check

* Linting updates

* Update CHANGELOG (cleanups as per comments)
2020-01-31 15:34:06 +01:00
Jaco Greeff 982665c337 Update CHANGELOG with missing change (#1782) 2020-01-30 17:22:56 +01:00
Github Actions 6dce57b394 [CI Skip] 1.0.1
skip-checks: true
2020-01-30 16:06:14 +00:00
Jaco Greeff ca7edf1593 1.0 (#1781)
* 1.0

* signAsync typing

* Merge master
2020-01-30 16:59:04 +01:00
Jakub Pánik 59e069f091 Added unsubscribe return function to wsProvider.on() (#1780)
* Added unsubscribe return function to wsProvider.on()

* Updated mocks, added noop to http provider
2020-01-30 16:48:11 +01:00
Github Actions 65ff5c8f30 [CI Skip] 1.0.0-beta.44
skip-checks: true
2020-01-30 14:58:02 +00:00
Jaco Greeff 1c327c60d9 Metadata V11 (#1774)
* Make a start ... V11 definitions

* V11 conversion

* Fix ErrorMetadataV11

* Extension point for signed extensions

* Add V11 to mapped

* Expand toLatest comments
2020-01-30 15:49:37 +01:00
Github Actions de9f033d99 [CI Skip] 1.0.0-beta.43
skip-checks: true
2020-01-30 11:16:33 +00:00
Jaco Greeff 9c913fb482 Cleanup generated doc (only top-level docs) (#1777)
* Cleanup generated doc (only top-level docs)

* Single-line name
2020-01-30 12:09:16 +01:00
Github Actions e19e530c1c [CI Skip] 1.0.0-beta.42
skip-checks: true
2020-01-29 21:28:15 +00:00
Jaco Greeff aa91e0b8b5 Small gen doc updates (#1773) 2020-01-29 22:20:54 +01:00
Github Actions 9a6ba2fe0f [CI Skip] 1.0.0-beta.41
skip-checks: true
2020-01-29 17:33:29 +00:00
Jaco Greeff de853d9cc0 Add EVM types (#1771)
* Add EVM types

* Add findError for metadata
2020-01-29 18:26:06 +01:00
Github Actions 07063134b8 [CI Skip] 1.0.0-beta.40
skip-checks: true
2020-01-29 16:56:40 +00:00
Jaco Greeff 20b8cd762d Add sidebar doc link to TS user gen (#1770) 2020-01-29 17:49:40 +01:00
Github Actions bd3338c3df [CI Skip] 1.0.0-beta.39
skip-checks: true
2020-01-29 16:44:42 +00:00
Jaco Greeff 4c328964d5 Allow chain to use user-defined types (#1769)
* Allow chain to use user-defined types

* --package docs on chain extract
2020-01-29 17:37:19 +01:00
Github Actions 70e5e2b60a [CI Skip] 1.0.0-beta.38
skip-checks: true
2020-01-29 14:59:20 +00:00
Jaco Greeff 4329c0a411 Add polkadot-types-from-{chain,defs} (#1766)
* Add polkadot-types-from-{chain,defs}

* Generate scripts working

* User types generation docs

* Rebuild with new comment line
2020-01-29 15:51:23 +01:00
Github Actions 0713afa0e0 [CI Skip] 1.0.0-beta.37
skip-checks: true
2020-01-29 09:43:41 +00:00
Jaco Greeff 8b518a909b Bump deps (#1765) 2020-01-29 10:36:04 +01:00
Github Actions 794f1fe398 [CI Skip] 1.0.0-beta.36
skip-checks: true
2020-01-28 22:07:54 +00:00
Lae 51423e20b5 Make sure awaiting on an api object won't stuck forever on error (#1763)
* Make sure awaiting on an api object won't stuck forever when error occurs.

* Fix lint issues.
2020-01-28 23:01:07 +01:00
Github Actions d4b27ba670 [CI Skip] 1.0.0-beta.35
skip-checks: true
2020-01-28 21:52:49 +00:00
Jaco Greeff 8ca194a3d2 Cleanup society types (#1764)
* Cleanup society types

* Update types
2020-01-28 22:47:07 +01:00
Github Actions 5fd2c70924 [CI Skip] 1.0.0-beta.34
skip-checks: true
2020-01-28 21:03:11 +00:00
Jaco Greeff d36ee7de2f Add society hasDefender (#1762) 2020-01-28 21:55:55 +01:00
Github Actions 3683f9e5ff [CI Skip] 1.0.0-beta.33
skip-checks: true
2020-01-28 18:22:37 +00:00
Jaco Greeff 18c302d2cf Allow author extract from empty (#1761) 2020-01-28 19:16:08 +01:00
Github Actions 1686f8b357 [CI Skip] 1.0.0-beta.32
skip-checks: true
2020-01-28 17:58:51 +00:00
Jaco Greeff 15158b763c Bump common (#1760) 2020-01-28 18:51:17 +01:00
Github Actions f5f338a9ae [CI Skip] 1.0.0-beta.31
skip-checks: true
2020-01-28 17:17:15 +00:00
Jaco Greeff 458dec53dc Session validators availability detection (#1759) 2020-01-28 18:10:06 +01:00
Github Actions ab05045686 [CI Skip] 1.0.0-beta.30
skip-checks: true
2020-01-28 16:47:39 +00:00
Jaco Greeff b2c84eb461 Bump deps (#1758)
* Bump deps

* api detect
2020-01-28 17:40:57 +01:00
Github Actions 1ee1d70d55 [CI Skip] 1.0.0-beta.29
skip-checks: true
2020-01-28 15:25:22 +00:00
Jaco Greeff 7de647ec0b Cleanup module-specific type-overrides (#1756) 2020-01-28 16:18:40 +01:00
Github Actions cedbd8fa06 [CI Skip] 1.0.0-beta.28
skip-checks: true
2020-01-28 14:40:38 +00:00
Jaco Greeff cba34b4b65 Fill signAsync with expanded chain options (#1753)
* Fill signAsync with expanded chain options

* Use mapTo

* Fill test with defined storage value

* Remove .only
2020-01-28 15:33:44 +01:00
Github Actions 1a99d67c77 [CI Skip] 1.0.0-beta.27
skip-checks: true
2020-01-28 10:13:45 +00:00
Jaco Greeff 2a5c5ce3fe Only include derives with parent query (#1755)
* Only include derives with parent query

* Update CHANGELOG
2020-01-28 11:07:02 +01:00
Github Actions e4ca0a1c64 [CI Skip] 1.0.0-beta.26
skip-checks: true
2020-01-28 08:59:33 +00:00
Jaco Greeff e6018f2f75 Add society-specific Vote type (#1754)
* Add society-specific Vote type

* Cnvert storage types via toLatest
2020-01-28 09:52:40 +01:00
Github Actions a9b4f8d841 [CI Skip] 1.0.0-beta.25
skip-checks: true
2020-01-27 18:42:41 +00:00
Amaury Martiny 7fe68857a0 Init api when provider is already connected (#1752)
* Init api when provider is already connected

* Spacing
2020-01-27 19:35:38 +01:00
Github Actions 4f63fc77a3 [CI Skip] 1.0.0-beta.24
skip-checks: true
2020-01-27 16:20:13 +00:00
Jaco Greeff 6e2ad7789e Expose .entries() for DoubleMaps (#1750)
* Expose .entries() for DoubleMaps

* DoubleMap vs Map test

* Fix decoration

* Remove prefixed map

* Allow SoubleMap entries() with arguments

* DoubleMap with & without params

* Remove debug log

* Update CHANGELOG

* ... and working... finally.

* Cleanup debug logs
2020-01-27 17:13:53 +01:00
Github Actions edb856c94f [CI Skip] 1.0.0-beta.23
skip-checks: true
2020-01-27 14:12:40 +00:00
Jaco Greeff 2f215fe2de Cleanup entries() (#1751) 2020-01-27 15:07:00 +01:00
Github Actions ffa1279c64 [CI Skip] 1.0.0-beta.22
skip-checks: true
2020-01-27 11:56:57 +00:00
Jaco Greeff 83aca87dac Skip types.ts for typedoc (#1749) 2020-01-27 12:50:36 +01:00
Github Actions bf782f6f65 [CI Skip] 1.0.0-beta.21
skip-checks: true
2020-01-27 11:43:36 +00:00
Jaco Greeff 7adad82786 Remove v11 metadata (#1748)
* Remove v11 metadata

* Linting
2020-01-27 12:37:01 +01:00
Github Actions 693cf855f0 [CI Skip] 1.0.0-beta.20
skip-checks: true
2020-01-27 08:45:51 +00:00
Jaco Greeff 854a520517 Mark some function @internal (no doc extraction) (#1746) 2020-01-27 09:38:02 +01:00
Github Actions 6e6fc98cd1 [CI Skip] 1.0.0-beta.19
skip-checks: true
2020-01-26 09:36:27 +00:00
Jaco Greeff 3db15e73a5 Bump deps (#1745)
* Bump deps

* Fix test expectation

* Mark doc internal
2020-01-26 10:27:44 +01:00
Github Actions 215b659a9a [CI Skip] 1.0.0-beta.18
skip-checks: true
2020-01-23 17:12:43 +00:00
Jaco Greeff 7ef945d15b Make invalid V9 metadata parse (won't work, but parses) (#1743)
* Make invalid V9 metadata parse (won't work, but parses)

* Add invalid to V4 (simpler, no code)
2020-01-23 18:06:25 +01:00
Github Actions 73ec345fcc [CI Skip] 1.0.0-beta.17
skip-checks: true
2020-01-22 14:59:54 +00:00
Jaco Greeff c1c537a3b5 Type aliases on a per-module basis (#1740)
* Type aliasses on a per-module basis

* Remove test interface

* Update wrapper

* Move known types to types
2020-01-22 15:51:23 +01:00
Github Actions dc64076c79 [CI Skip] 1.0.0-beta.16
skip-checks: true
2020-01-22 14:22:49 +00:00
Jaco Greeff da8ff51615 Remove unmaintained & outdated E2E (#1739) 2020-01-22 15:14:57 +01:00
Github Actions 60b1bc87a4 [CI Skip] 1.0.0-beta.15
skip-checks: true
2020-01-22 09:41:19 +00:00
Jaco Greeff 7ed1857589 Update SlashingSpans (#1738)
* Update SlashingSpans

* Digest 0toX -> ToX
2020-01-22 10:33:05 +01:00
Github Actions 4c0e60f3d6 [CI Skip] 1.0.0-beta.14
skip-checks: true
2020-01-21 13:52:44 +00:00
Jaco Greeff 20ed3bb5fe Allow passing of signer via sign options (#1734)
* Allow passing of signer via sign options

* Pass signer via api.sign
2020-01-21 14:45:53 +01:00
Jaco Greeff be3f9c8fe8 Remove outdated derive + combineLatest comment (#1733)
As per https://github.com/polkadot-js/api/pull/1732/files#r368599021
2020-01-21 14:45:07 +01:00
Github Actions e850955e55 [CI Skip] 1.0.0-beta.13
skip-checks: true
2020-01-20 13:05:49 +00:00
Jaco Greeff eb5ee9860b Multi query adjustments (#1732) 2020-01-20 13:58:07 +01:00
Github Actions f31bbdde02 [CI Skip] 1.0.0-beta.12
skip-checks: true
2020-01-19 21:55:43 +00:00
Jaco Greeff f67c435378 Trigger build 2020-01-19 22:49:09 +01:00
Jaco Greeff bf9a60a202 Update .123trigger 2020-01-19 22:46:50 +01:00
Jaco Greeff 9c3c07fa9b Derives for society (#1727)
* Deries for society

* Candidates

* Add overview

* Candidate types

* WIP, stash before merge

* Linting

* Readability

* Typo

* Split option maps
2020-01-19 21:56:39 +01:00
Github Actions 11786ca102 [CI Skip] 1.0.0-beta.11
skip-checks: true
2020-01-19 20:14:25 +00:00
Nikolay Volf ffaea83e3e Fix typo (#1730) 2020-01-19 21:05:58 +01:00
Github Actions 954540b944 [CI Skip] 1.0.0-beta.10
skip-checks: true
2020-01-19 10:29:05 +00:00
Jaco Greeff 204cf6769d Bump mtadata (latest Substrate) (#1728) 2020-01-19 11:20:33 +01:00
Github Actions f319bc4c50 [CI Skip] 1.0.0-beta.9
skip-checks: true
2020-01-19 09:24:49 +00:00
Jaco Greeff 7b9a11ac25 Don't map empty tuples to Null (#1725)
* Don't map empty tuples to Null

* Remove unused var

* Regen with tuple Result

* Generated types lint fixes
2020-01-19 10:17:20 +01:00
Github Actions 5d2feca2d4 [CI Skip] 1.0.0-beta.8
skip-checks: true
2020-01-16 13:54:01 +00:00
Jaco Greeff dd97e9daee Add registry error lookup (#1723) 2020-01-16 14:46:21 +01:00
Github Actions be258a1f7c [CI Skip] 1.0.0-beta.7
skip-checks: true
2020-01-15 09:05:23 +00:00
Jaco Greeff 72e9474f6f imOnline Heartbeat struct (#1721) 2020-01-15 09:56:58 +01:00
Github Actions d1f63a7864 [CI Skip] 1.0.0-beta.6
skip-checks: true
2020-01-14 18:15:57 +00:00
Jaco Greeff 07ca18502b Society/Recovery types (#1719)
* Society/Recovery types

* camelCase (linting)
2020-01-14 19:08:40 +01:00
Github Actions cddbe411f7 [CI Skip] 1.0.0-beta.5
skip-checks: true
2020-01-14 15:03:44 +00:00
Jaco Greeff ffa60d1cfa Drop V1 support in derive (#1718)
* Drop V1 support in derive

* Re-do staking with multi

* Re-bump deps

* Adjusts tests (no alice_session)

* CC
2020-01-14 15:55:25 +01:00
Github Actions 88193b6a75 [CI Skip] 1.0.0-beta.4
skip-checks: true
2020-01-14 13:15:58 +00:00
Stefanie Doll cc4a4607f1 Updated child storage parameters (#1709)
* Added child_definition and child_type to chicl dtorage RPC methods

* reset comments in test file

* reverse docs re-built

* Fix linting on child storage tests
2020-01-14 14:07:41 +01:00
Github Actions 6c25d0ab0d [CI Skip] 1.0.0-beta.3
skip-checks: true
2020-01-13 21:26:52 +00:00
Amaury Martiny fbbbcd2612 Enum toJSON returns toString for a basic enum (#1697)
* Update kusama static from 1032 to 1033

* Test 1032 and 1033

* Got exact metadata from kusama

* First pass: enum TOJSON and fix some tests

* Build interfaces

* Fix import

* Use camelCase for enum toJSON

* Build interface

* Fix lint

* Fix tests

* Generate static json
2020-01-13 22:18:51 +01:00
Github Actions dd57b1a007 [CI Skip] 1.0.0-beta.2
skip-checks: true
2020-01-13 17:03:58 +00:00
Jaco Greeff 47d0e68f7d Remove old known keys (#1715)
* Remove old known keys

* Don't import removed

* Update storage keys
2020-01-13 17:55:21 +01:00
Github Actions 7b6397215d [CI Skip] 1.0.0-beta.1
skip-checks: true
2020-01-13 16:39:56 +00:00
Jaco Greeff 5739b69757 Bump to 1.0 beta (#1717)
* Bump to 1.0 beta bump

* Bump common to 2.0 beta
2020-01-13 17:31:33 +01:00
355 changed files with 18449 additions and 11747 deletions
+1 -1
View File
@@ -1 +1 @@
16
17
+1 -1
View File
@@ -4,6 +4,6 @@ exclude_patterns:
- "**/*.test.js"
- "**/*.test.ts"
- "docs/**/*.js"
- "packages/api/src/query.types.ts"
- "packages/api/src/types/augment/"
- "packages/types/src/interfaces/"
- "packages/types/src/scripts/"
+32
View File
@@ -1,3 +1,35 @@
# 1.1.1
- Add support for `balances.account` in all applicable derives (incl. `vesting` module)
- Inject and use SignedExtensions by name from V11 metadata (V4 extrinsics only)
- Add typings for `api.tx.*.*` - the `polkadot-types-from-chain` now also generates these
- Remove additional V1-only derives `(staking.recentlyOffline`, `balances.nominatorsFor`)
- Add `.isMax()` on int values, an opposite of `isZero()` (e.g. `u128`, as well as derived, e.g. `Balances`)
- Add `.keyPrefix()` to all `api.query.*` complementing the `.key()` call, both returning a hex string
- Council derives now takes bootstrapping (member, no elections) into account
- Account derives now allow for an optional indices module (not required)
- Adjust balances fees derivation with optional transfer and creation fees (removed in Substrate)
- Adjust enum `.toJSON()` to return type name as specified
# 1.0.1
- **Breaking change** Drop support for Substrate v1 chain in all derives
- Return unsub functions from provider .on emitters (Thanks to https://github.com/jak-pan)
- `ApiPromise.isReady` now rejects on unrecoverable errors (Thanks to https://github.com/laec)
- Add `polkadot-types-from-chain` & `polkadot-types-from-defs` TypeScript generators to `@polkadot/types`
- Only decorate derives where relevant parent `api.query.*` is available
- Support `.entries(arg?: any)` lookups on DoubleMaps (in addition to previously supported maps)
- Allow v9 metadata to parse even in cases where it was wrongly deployed pre-v10
- Allow type-aliases on a per-module basis (e.g. `Judgement` in identity as well as society)
- Allow passing `{ signer }` to both `api.tx.*` and `api.sign` (in addition to `api.setSigner`)
- Add derives for the society module
- Don't map empty tuples, e.. `()` to `Null`, rather keep them empty
- Add lookups to the metadata errors via `findMetaError`
- Update metadata and types for the latest Substrate & Polkadot versions
- Support metadata V11 as per latest Substrate
- Remove support for un-deployed metadata
- Remove old known types for Substrate V1
# 0.100.1
- **Important** This will the the last API version with Substrate 1.x support. Although you will still be able to use subsequent versions with older chans, dependent libraries such as sr25519 may not be compatible.
+1
View File
@@ -45,6 +45,7 @@ module.exports = {
['start/types.extend.md', 'Extending types'],
['start/extrinsic.extend.md', 'Extending extrinsics'],
['start/typescript.md', 'TypeScript interfaces'],
['start/typescript.user.md', 'TypeScript user generated'],
['start/FAQ.md', 'FAQ']
]
},
+1
View File
@@ -17,6 +17,7 @@
- [Type basics](start/types.basics.md)
- [Type extension](start/types.extend.md)
- [TypeScript interfaces](start/typescript.md)
- [TypeScript user generated](start/typescript.user.md)
## Packages
+2 -7
View File
@@ -46,11 +46,6 @@ As of this writing, there are still some gray areas to type detection, specifica
- `.at` & `.multi` on `api.query` does not (yet) have a `<TypeOverride>` interface. This means `as <TypeOverride>` casts are presently needed for these results
- `api.queryMulti` does not (yet) allow you to provide a hint to the types returned, this ties to the previous point
In addition to expanding the type coverage, we wish to make the actual generation script for the types from `@polkadot/types/interfaces` available in 2 ways -
## Adding user types
- allowing you to point to a folder of types and auto-generate the TypeScript typings from those. (Which is akin to what we do internally). This would allow a reduction in type classes explicitly written and injected.
- once the metadata itself supports full type definitions, the script can be used to generate interface definitions specifically tailored for a chain
## And that's a wrap
This brings us to the end of our overview and jump through the API. While the documentation is still very much and ever evolving item, we can encourage you to try out what you have learned with some [examples](../examples). As we [indicated right at the start of this journey](README.md#help-us-help-others), if there are areas for improvement, let us know.
In addition to the generated and available interfaces, there is also the ability to [create TypeScript interfaces from your own definitions and well as your on-chain modules](typescript.user.md).
+26
View File
@@ -0,0 +1,26 @@
# 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 defintions and chain types.
## Definitions
A large part of the type definitions are defined not as classes, but rather as structures from which type definitions are extracted and that can be used as-is to let the API know how to decode a type. By now you should be familiar with [type extensions](types.extend.md), but effectively the [types library does exactly the same](https://github.com/polkadot-js/api/tree/master/packages/types/src/interfaces).
To create TypeScript-aware definitions and keep your files in a single place, you can follow the same approach. Assuming you have a package named `@MeInc/stuff` where you have the definitions in an `stuff/interfaces` folder. Each sub-folder would indicate a runtime module, e.g.
- `stuff/interfaces/<module>/definitions.ts` for each module (`types.ts` & `index.ts` will be generated)
- `stuff/interfaces/defnitions.ts` importing all sub-definitions`
With this structure setup, you can generate TypeScript defintions.
In the root of your project (with the `@polkadot/api`), you can run `yarn polkadot-types-from-defs --input ./stuff/interfaces --package @MeInc/stuff/interfaces` which will create `types.ts` and `index.ts` files with the generated types. You can use these in exactly the same way as you would use your types from `@polkadot/types/interfaces`.
## Chain modules
In the same way as the type library provides defaults from a substrate-base chain, you can also, directly from chain from metadata, generate a complete `api.{consts,query}.*` defintion for your specific chain. The command will create 2 files, `{consts, query}.types.ts` which you can either use to augment the TypeScript defintions, or replace those in `@polkadot/api/*` with your versions (copy, TypeScript replacement or browser/node aliassing).
In the root of your project, you can run `yarn polkadot-types-from-chain --endpoint wss://<url> --output ./stuff` and it will create the required output. (Here you can specify an optional `--package @MeInc/stuff` to read definitions for the targetted output folder with the specified package name.)
## And that's a wrap
This brings us to the end of our overview and jump through the API. While the documentation is still very much and ever evolving item, we can encourage you to try out what you have learned with some [examples](../examples). As we [indicated right at the start of this journey](README.md#help-us-help-others), if there are areas for improvement, let us know.
+2 -1
View File
@@ -31,5 +31,6 @@ module.exports = Object.assign({}, config, {
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'
});
+15
View File
@@ -0,0 +1,15 @@
// Copyright 2017-2020 @polkadot/util authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
// eslint-disable-next-line @typescript-eslint/no-var-requires
const path = require('path');
module.exports = function resolver (file, config) {
if (file.includes('package.json')) {
console.error(file, config);
return path.join(config.basedir.replace('/src', '/'), file);
}
return config.defaultResolver(file, config);
};
+1 -1
View File
@@ -9,5 +9,5 @@
"packages": [
"packages/*"
],
"version": "0.100.1"
"version": "1.1.1"
}
+7 -10
View File
@@ -1,5 +1,5 @@
{
"version": "0.100.1",
"version": "1.1.1",
"private": true,
"engines": {
"yarn": "^1.10.1"
@@ -9,7 +9,7 @@
],
"resolutions": {
"babel-core": "^7.0.0-bridge.0",
"typescript": "^3.7.4"
"typescript": "^3.7.5"
},
"scripts": {
"build": "yarn build:interfaces && polkadot-dev-build-ts",
@@ -22,17 +22,14 @@
"postinstall": "polkadot-dev-yarn-only",
"test": "jest --coverage --runInBand --testPathIgnorePatterns e2e",
"test:all": "jest",
"test:e2e": "jest packages/api/test/e2e",
"test:e2e-docker": "TEST_DOCKER=1 jest packages/api/test/e2e",
"test:e2e-remote": "TEST_REMOTE=1 jest packages/api/test/e2e",
"test:one": "jest",
"test:watch": "jest --coverage --watch"
},
"devDependencies": {
"@babel/core": "^7.7.7",
"@babel/register": "^7.7.7",
"@babel/runtime": "^7.7.7",
"@polkadot/dev": "^0.32.14",
"@polkadot/ts": "^0.1.90"
"@babel/core": "^7.8.3",
"@babel/register": "^7.8.3",
"@babel/runtime": "^7.8.3",
"@polkadot/dev": "^0.33.3",
"@polkadot/ts": "^0.2.1"
}
}
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-contract",
"version": "0.100.1",
"version": "1.1.1",
"description": "Interfaces for interacting with contracts and contract ABIs",
"main": "index.js",
"keywords": [
@@ -26,7 +26,7 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-contract#readme",
"dependencies": {
"@babel/runtime": "^7.7.7",
"@polkadot/types": "^0.100.1"
"@babel/runtime": "^7.8.3",
"@polkadot/types": "^1.1.1"
}
}
+2 -2
View File
@@ -3,9 +3,9 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiTypes, DecorateMethod, DecoratedRpc, SubmittableModuleExtrinsics } from '@polkadot/api/types';
import { ApiObject, ContractABIMessage, ContractABIPre, ContractBase, ContractMessage } from '../types';
import { RpcInterface } from '@polkadot/rpc-core/jsonrpc.types';
import { RpcInterface } from '@polkadot/rpc-core/types';
import { Registry } from '@polkadot/types/types';
import { ApiObject, ContractABIMessage, ContractABIPre, ContractBase, ContractMessage } from '../types';
import { assert, isFunction, stringCamelCase } from '@polkadot/util';
import Abi from '../Abi';
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-derive",
"version": "0.100.1",
"version": "1.1.1",
"description": "Common functions used across Polkadot, derived from RPC calls and storage queries.",
"main": "index.js",
"keywords": [
@@ -27,11 +27,11 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme",
"dependencies": {
"@babel/runtime": "^7.7.7",
"@polkadot/api": "^0.100.1",
"@polkadot/types": "^0.100.1"
"@babel/runtime": "^7.8.3",
"@polkadot/api": "^1.1.1",
"@polkadot/types": "^1.1.1"
},
"devDependencies": {
"@polkadot/keyring": "^1.8.1"
"@polkadot/keyring": "^2.2.1"
}
}
@@ -4,7 +4,7 @@
import { AccountId, AccountIndex } from '@polkadot/types/interfaces';
import { Observable } from 'rxjs';
import { Observable, of } from 'rxjs';
import { map, startWith } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { ENUMSET_SIZE } from '@polkadot/types/primitive/Generic/AccountIndex';
@@ -26,18 +26,18 @@ import { memo } from '../util';
* ```
*/
export function indexToId (api: ApiInterfaceRx): (accountIndex: AccountIndex | string) => Observable<AccountId | undefined> {
const querySection = api.query.indices || api.query.balances;
return memo((_accountIndex: AccountIndex | string): Observable<AccountId | undefined> => {
const accountIndex = _accountIndex instanceof ClassOf(api.registry, 'AccountIndex')
? _accountIndex
: createType(api.registry, 'AccountIndex', _accountIndex);
return querySection.enumSet<Vec<AccountId>>(accountIndex.div(ENUMSET_SIZE)).pipe(
startWith([]),
map((accounts): AccountId | undefined =>
(accounts || [])[accountIndex.mod(ENUMSET_SIZE).toNumber()]
return api.query.indices.enumSet
? api.query.indices.enumSet<Vec<AccountId>>(accountIndex.div(ENUMSET_SIZE)).pipe(
startWith([]),
map((accounts): AccountId | undefined =>
(accounts || [])[accountIndex.mod(ENUMSET_SIZE).toNumber()]
)
)
);
: of(undefined);
});
}
+13 -9
View File
@@ -6,7 +6,7 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId, AccountIndex } from '@polkadot/types/interfaces';
import { AccountIndexes } from '../types';
import { Observable } from 'rxjs';
import { Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { ENUMSET_SIZE } from '@polkadot/types/primitive/Generic/AccountIndex';
import { Vec, createType } from '@polkadot/types';
@@ -32,14 +32,18 @@ const enumsetSize = ENUMSET_SIZE.toNumber();
*/
export function indexes (api: ApiInterfaceRx): () => Observable<AccountIndexes> {
return memo((): Observable<AccountIndexes> =>
api.query.indices.nextEnumSet<AccountIndex>().pipe(
// use the nextEnumSet (which is a counter of the number of sets) to construct
// a range of values to query [0, 1, 2, ...]. Retrieve the full enum set for the
// specific index - each query can return up to ENUMSET_SIZE (64) records, each
// containing an AccountId
switchMap((next: AccountIndex): Observable<Vec<AccountId>[]> =>
api.query.indices.enumSet.multi<Vec<AccountId>>([...Array(next.toNumber() + 1).keys()])
),
(api.query.indices.nextEnumSet
? api.query.indices.nextEnumSet<AccountIndex>().pipe(
// use the nextEnumSet (which is a counter of the number of sets) to construct
// a range of values to query [0, 1, 2, ...]. Retrieve the full enum set for the
// specific index - each query can return up to ENUMSET_SIZE (64) records, each
// containing an AccountId
switchMap((next: AccountIndex): Observable<Vec<AccountId>[]> =>
api.query.indices.enumSet.multi<Vec<AccountId>>([...Array(next.toNumber() + 1).keys()])
)
)
: of([] as AccountId[][])
).pipe(
map((all: AccountId[][]): AccountIndexes =>
all.reduce((result: AccountIndexes, list, outerIndex): AccountIndexes => {
(list || []).forEach((accountId, innerIndex): void => {
@@ -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 { AccountId, AccountData, AccountIndex, Address, Balance, Index } from '@polkadot/types/interfaces';
import { DerivedBalancesAccount } from '../types';
import { combineLatest, of, Observable } 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 {
return {
accountId,
accountNonce,
freeBalance,
frozenFee,
frozenMisc,
reservedBalance,
votingBalance: createType(api.registry, 'Balance', freeBalance.add(reservedBalance))
};
}
// old
function queryOld (api: ApiInterfaceRx, accountId: AccountId): Observable<Result> {
return api.queryMulti<[Balance, Balance, Index]>([
[api.query.balances.freeBalance, accountId],
[api.query.balances.reservedBalance, accountId],
[api.query.system.accountNonce, accountId]
]).pipe(
map(([freeBalance, reservedBalance, accountNonce]): Result =>
[freeBalance, reservedBalance, createType(api.registry, 'Balance'), createType(api.registry, 'Balance'), accountNonce]
)
);
}
function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<Result> {
return api.queryMulti<[AccountData, Index]>([
[api.query.balances.account, accountId],
[api.query.system.accountNonce, accountId]
]).pipe(
map(([{ free, reserved, miscFrozen, feeFrozen }, accountNonce]): Result =>
[free, reserved, feeFrozen, miscFrozen, accountNonce]
)
);
}
/**
* @name account
* @param {( AccountIndex | AccountId | Address | string )} address - An accounts Id in different formats.
* @returns An object containing the results of various balance queries
* @example
* <BR>
*
* ```javascript
* const ALICE = 'F7Hs';
*
* api.derive.balances.all(ALICE, ({ accountId, lockedBalance }) => {
* console.log(`The account ${accountId} has a locked balance ${lockedBalance} units.`);
* });
* ```
*/
export function account (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DerivedBalancesAccount> {
return memo((address: AccountIndex | AccountId | Address | string): Observable<DerivedBalancesAccount> =>
api.derive.accounts.info(address).pipe(
switchMap(({ accountId }): Observable<[AccountId, Result]> =>
(accountId
? combineLatest([
of(accountId),
api.query.balances.account
? queryCurrent(api, accountId)
: queryOld(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')]])
)
),
map((result): DerivedBalancesAccount => calcBalances(api, result))
));
}
+66 -34
View File
@@ -2,8 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, AccountIndex, Address, Balance, BalanceLock, BlockNumber, Index, VestingSchedule } from '@polkadot/types/interfaces';
import { DerivedBalances } from '../types';
import { AccountId, AccountIndex, Address, Balance, BalanceLock, BalanceLockTo212, BlockNumber, VestingInfo, VestingSchedule } from '@polkadot/types/interfaces';
import { DerivedBalancesAccount, DerivedBalancesAll } from '../types';
import BN from 'bn.js';
import { combineLatest, of, Observable } from 'rxjs';
@@ -14,29 +14,32 @@ import { bnMax } from '@polkadot/util';
import { memo } from '../util';
type ResultBalance = [Balance, Balance, BalanceLock[], Option<VestingSchedule>];
type Result = [AccountId, BlockNumber, ResultBalance, Index];
type ResultBalance = [VestingInfo | null, (BalanceLock | BalanceLockTo212)[]];
type Result = [DerivedBalancesAccount, BlockNumber, ResultBalance];
function calcBalances (api: ApiInterfaceRx, [accountId, bestNumber, [freeBalance, reservedBalance, locks, vesting], accountNonce]: Result): DerivedBalances {
function calcBalances (api: ApiInterfaceRx, [{ accountId, accountNonce, freeBalance, frozenFee, frozenMisc, reservedBalance, votingBalance }, bestNumber, [vesting, locks]]: Result): DerivedBalancesAll {
let lockedBalance = createType(api.registry, 'Balance');
let lockedBreakdown: BalanceLock[] = [];
let lockedBreakdown: (BalanceLock | BalanceLockTo212)[] = [];
if (Array.isArray(locks)) {
// only get the locks that are valid until passed the current block
lockedBreakdown = locks.filter(({ until }): boolean => bestNumber && until.gt(bestNumber));
lockedBreakdown = (locks as BalanceLockTo212[]).filter(({ until }): boolean => !until || (bestNumber && until.gt(bestNumber)));
const notAll = lockedBreakdown.filter(({ amount }): boolean => !amount.isMax());
// get the maximum of the locks according to https://github.com/paritytech/substrate/blob/master/srml/balances/src/lib.rs#L699
if (lockedBreakdown.length) {
lockedBalance = createType(api.registry, 'Balance', bnMax(...lockedBreakdown.map(({ amount }): Balance => amount)));
if (notAll.length) {
lockedBalance = createType(api.registry, 'Balance', bnMax(...notAll.map(({ amount }): Balance => amount)));
}
}
// Calculate the vesting balances,
// - offset = balance locked at genesis,
// - offset = balance locked at startingBlock
// - perBlock is the unlock amount
const { offset: vestingTotal, perBlock } = vesting.unwrapOr(createType(api.registry, 'VestingSchedule'));
const vestedBalance = createType(api.registry, 'Balance', perBlock.mul(bestNumber));
const isVesting = vestedBalance.lt(vestingTotal);
const { locked: vestingTotal, perBlock, startingBlock } = vesting || createType(api.registry, 'VestingInfo');
const isStarted = bestNumber.gt(startingBlock);
const vestedBalance = createType(api.registry, 'Balance', isStarted ? perBlock.mul(bestNumber.sub(startingBlock)) : 0);
const isVesting = isStarted && vestedBalance.lt(vestingTotal);
// The available balance & vested has an interplay here
// "
@@ -54,23 +57,56 @@ function calcBalances (api: ApiInterfaceRx, [accountId, bestNumber, [freeBalance
accountNonce,
availableBalance,
freeBalance,
frozenFee,
frozenMisc,
isVesting,
lockedBalance,
lockedBreakdown,
reservedBalance,
vestedBalance,
vestingTotal,
votingBalance: createType(api.registry, 'Balance', freeBalance.add(reservedBalance))
votingBalance
};
}
function queryBalances (api: ApiInterfaceRx, accountId: AccountId): Observable<ResultBalance> {
return api.queryMulti<[Balance, Balance, Vec<BalanceLock>, Option<VestingSchedule>]>([
[api.query.balances.freeBalance, accountId],
[api.query.balances.reservedBalance, accountId],
// old
function queryOld (api: ApiInterfaceRx, accountId: AccountId): Observable<ResultBalance> {
return api.queryMulti<[Vec<BalanceLock>, Option<VestingSchedule>]>([
[api.query.balances.locks, accountId],
[api.query.balances.vesting, accountId]
]);
]).pipe(
map(([locks, optVesting]): ResultBalance => {
let vestingNew = null;
if (optVesting.isSome) {
const { offset: locked, perBlock, startingBlock } = optVesting.unwrap();
vestingNew = createType(api.registry, 'VestingInfo', { locked, perBlock, startingBlock });
}
return [vestingNew, locks];
})
);
}
// current (balances vesting)
function queryCurrent (api: ApiInterfaceRx, accountId: AccountId): Observable<ResultBalance> {
return (
api.query.vesting.vesting
? api.queryMulti<[Vec<BalanceLock>, Option<VestingInfo>]>([
[api.query.balances.locks, accountId],
[api.query.vesting.vesting, accountId]
])
: api.query.balances.locks(accountId).pipe(
map((locks): [Vec<BalanceLock>, Option<VestingInfo>] =>
[locks, createType(api.registry, 'Option<VestingInfo>')]
)
)
).pipe(
map(([locks, optVesting]): ResultBalance =>
[optVesting.unwrapOr(null), locks]
)
);
}
/**
@@ -88,25 +124,21 @@ function queryBalances (api: ApiInterfaceRx, accountId: AccountId): Observable<R
* });
* ```
*/
export function all (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DerivedBalances> {
return memo((address: AccountIndex | AccountId | Address | string): Observable<DerivedBalances> =>
api.derive.accounts.info(address).pipe(
switchMap(({ accountId }): Observable<Result> =>
(accountId
export function all (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DerivedBalancesAll> {
return memo((address: AccountIndex | AccountId | Address | string): Observable<DerivedBalancesAll> =>
api.derive.balances.account(address).pipe(
switchMap((account): Observable<Result> =>
(!account.accountId.isEmpty
? combineLatest([
of(accountId),
of(account),
api.derive.chain.bestNumber(),
queryBalances(api, accountId),
// FIXME This is having issues with Kusama, only use accountNonce atm
// api.rpc.account && api.rpc.account.nextIndex
// ? api.rpc.account.nextIndex(accountId)
// // otherwise we end up with this: type 'Codec | Index' is not assignable to type 'Index'.
// : api.query.system.accountNonce<Index>(accountId)
api.query.system.accountNonce<Index>(accountId)
api.query.balances.account
? queryCurrent(api, account.accountId)
: queryOld(api, account.accountId)
])
: of([createType(api.registry, 'AccountId'), createType(api.registry, 'BlockNumber'), [createType(api.registry, 'Balance'), createType(api.registry, 'Balance'), createType(api.registry, 'Vec<BalanceLock>'), createType(api.registry, 'Option<VestingSchedule>', null)], createType(api.registry, 'Index')])
: of([account, createType(api.registry, 'BlockNumber'), [null, createType(api.registry, 'Vec<BalanceLock>')]])
)
),
map((result): DerivedBalances => calcBalances(api, result))
map((result): DerivedBalancesAll => calcBalances(api, result))
));
}
+10 -25
View File
@@ -8,33 +8,22 @@ import { DerivedFees } from '../types';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { createType } from '@polkadot/types';
import { memo } from '../util';
type Result = [Balance, Balance, Balance, Balance, Balance];
function queryV2 (api: ApiInterfaceRx): Observable<Result> {
const paymentBase = api.consts.transactionPayment || api.consts.balances;
function query (api: ApiInterfaceRx): Observable<Result> {
return of([
// get values from api.const for substrate versions post spec_version: 101
// https://github.com/paritytech/substrate/pull/2883/files#diff-5e5e1c3aec9ddfde0a9054d062ab3db9R131
api.consts.balances.creationFee,
api.consts.balances.existentialDeposit,
api.consts.balances.transferFee,
paymentBase.transactionBaseFee as Balance,
paymentBase.transactionByteFee as Balance
]);
}
// deprecated - remove
(api.consts.balances.creationFee as Balance) || createType(api.registry, 'Balance'),
(api.consts.balances.transferFee as Balance) || createType(api.registry, 'Balance'),
function queryV1 (api: ApiInterfaceRx): Observable<Result> {
return api.queryMulti<Result>([
// Support older versions and get values from storage
api.query.balances.creationFee,
api.query.balances.existentialDeposit,
api.query.balances.transferFee,
api.query.balances.transactionBaseFee,
api.query.balances.transactionByteFee
// current
api.consts.balances.existentialDeposit,
api.consts.transactionPayment.transactionBaseFee,
api.consts.transactionPayment.transactionByteFee
]);
}
@@ -52,13 +41,9 @@ function queryV1 (api: ApiInterfaceRx): Observable<Result> {
* ```
*/
export function fees (api: ApiInterfaceRx): () => Observable<DerivedFees> {
const query = api.consts.balances
? queryV2
: queryV1;
return memo((): Observable<DerivedFees> =>
query(api).pipe(
map(([creationFee, existentialDeposit, transferFee, transactionBaseFee, transactionByteFee]): DerivedFees => ({
map(([creationFee, transferFee, existentialDeposit, transactionBaseFee, transactionByteFee]): DerivedFees => ({
creationFee,
existentialDeposit,
transactionBaseFee,
+1 -1
View File
@@ -4,9 +4,9 @@
import { all } from './all';
export * from './account';
export * from './fees';
export * from './votingBalances';
export * from './votingBalancesNominatorsFor';
const votingBalance = all;
@@ -3,20 +3,20 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces';
import { DerivedBalances } from '../types';
import { DerivedBalancesAccount } from '../types';
import { combineLatest, Observable, of } from 'rxjs';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { memo } from '../util';
export function votingBalances (api: ApiInterfaceRx): (addresses?: (AccountId | AccountIndex | Address | string)[]) => Observable<DerivedBalances[]> {
return memo((addresses?: (AccountId | AccountIndex | Address | string)[]): Observable<DerivedBalances[]> =>
export function votingBalances (api: ApiInterfaceRx): (addresses?: (AccountId | AccountIndex | Address | string)[]) => Observable<DerivedBalancesAccount[]> {
return memo((addresses?: (AccountId | AccountIndex | Address | string)[]): Observable<DerivedBalancesAccount[]> =>
!addresses || !addresses.length
? of([] as DerivedBalances[])
? of([] as DerivedBalancesAccount[])
: combineLatest(
addresses.map((accountId): Observable<DerivedBalances> =>
api.derive.balances.all(accountId))
addresses.map((accountId): Observable<DerivedBalancesAccount> =>
api.derive.balances.account(accountId))
)
);
}
@@ -1,27 +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, AccountIndex, Address } from '@polkadot/types/interfaces';
import { DerivedBalances } from '../types';
import { Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Vec } from '@polkadot/types';
import { memo } from '../util';
export function votingBalancesNominatorsFor (api: ApiInterfaceRx): (address: AccountId | AccountIndex | Address | string) => Observable<DerivedBalances[]> {
return memo((address: AccountId | AccountIndex | Address | string): Observable<DerivedBalances[]> =>
api.derive.accounts.info(address).pipe(
switchMap(({ accountId }): Observable<AccountId[]> =>
accountId
? api.query.staking.nominatorsFor<Vec<AccountId>>(accountId)
: of([] as AccountId[])
),
switchMap((accounts): Observable<DerivedBalances[]> =>
api.derive.balances.votingBalances(accounts)
)
));
}
@@ -4,7 +4,7 @@
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Observable, combineLatest } from 'rxjs';
import { Observable, combineLatest, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { HeaderExtended } from '../type';
@@ -27,9 +27,11 @@ export function subscribeNewHeads (api: ApiInterfaceRx): () => Observable<Header
return memo((): Observable<HeaderExtended> =>
combineLatest([
api.rpc.chain.subscribeNewHeads(),
api.derive.staking.validators()
api.query.session
? api.query.session.validators()
: of([])
]).pipe(
map(([header, { validators }]): HeaderExtended =>
map(([header, validators]): HeaderExtended =>
new HeaderExtended(api.registry, header, validators)
)
));
+26 -27
View File
@@ -4,41 +4,40 @@
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Hash, Proposal, Votes } from '@polkadot/types/interfaces';
import { DerivedCollectiveProposals } from '../types';
import { DerivedCollectiveProposal } from '../types';
import { combineLatest, Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option } from '@polkadot/types';
export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalCommittee'): () => Observable<DerivedCollectiveProposals> {
return (): Observable<DerivedCollectiveProposals> =>
api.query[section]
? api.query[section].proposals()
.pipe(
switchMap((hashes: Hash[]): Observable<[Hash[], Option<Proposal>[], Option<Votes>[]]> => {
return combineLatest([
of(hashes),
combineLatest(
hashes.map((hash): Observable<Option<Proposal>> => api.query[section].proposalOf(hash))
),
api.query[section].voting.multi<Option<Votes>>(hashes)
]);
}),
map(([hashes, proposals, votes]): DerivedCollectiveProposals => {
const result: DerivedCollectiveProposals = [];
type Result = [Hash[], Option<Proposal>[], Option<Votes>[]];
proposals.forEach((proposalOpt, index): void => {
if (proposalOpt.isSome) {
result.push({
export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalCommittee'): () => Observable<DerivedCollectiveProposal[]> {
return (): Observable<DerivedCollectiveProposal[]> =>
api.query[section]
? api.query[section].proposals().pipe(
switchMap((hashes: Hash[]): Observable<Result> =>
hashes.length
? combineLatest([
of(hashes),
api.query[section].proposalOf.multi<Option<Proposal>>(hashes),
api.query[section].voting.multi<Option<Votes>>(hashes)
])
: of([[], [], []])
),
map(([hashes, proposals, votes]: Result): DerivedCollectiveProposal[] =>
proposals
.map((proposalOpt, index): DerivedCollectiveProposal | null =>
proposalOpt.isSome
? {
hash: hashes[index],
proposal: proposalOpt.unwrap(),
votes: votes[index].unwrapOr(null)
});
}
});
return result;
})
}
: null
)
.filter((proposal): boolean => !!proposal) as DerivedCollectiveProposal[]
)
: of([] as DerivedCollectiveProposals);
)
: of([] as DerivedCollectiveProposal[]);
}
+20 -34
View File
@@ -8,42 +8,27 @@ import { DerivedContractFees } 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';
type ResultV2 = [BN, BN, BN, BN, BN, BN, BN, BN, BN, BN];
const ZERO = new BN(0);
// parse the result
function parseResult ([callBaseFee, contractFee, createBaseFee, creationFee, rentByteFee, rentDepositOffset, tombstoneDeposit, transactionBaseFee, transactionByteFee, transferFee]: ResultV2): DerivedContractFees {
return {
callBaseFee,
contractFee,
createBaseFee,
creationFee,
rentByteFee,
rentDepositOffset,
tombstoneDeposit,
transactionBaseFee,
transactionByteFee,
transferFee
};
}
type ResultV2 = [BN, BN, BN, BN, BN, BN, BN, BN, BN];
// query via constants (current applicable path)
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'),
// current
api.consts.contracts.callBaseFee,
api.consts.contracts.contractFee,
api.consts.contracts.createBaseFee,
api.consts.contracts.creationFee,
api.consts.contracts.rentByteFee,
api.consts.contracts.rentDepositOffset,
api.consts.contracts.tombstoneDeposit,
api.consts.contracts.transactionBaseFee,
api.consts.contracts.transactionByteFee,
api.consts.contracts.transferFee
api.consts.contracts.transactionByteFee
]) as unknown as Observable<ResultV2>;
}
@@ -62,17 +47,18 @@ function queryConstants (api: ApiInterfaceRx): Observable<ResultV2> {
*/
export function fees (api: ApiInterfaceRx): () => Observable<DerivedContractFees> {
return memo((): Observable<DerivedContractFees> => {
return (
api.consts.contracts
? queryConstants(api)
: of([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO])
).pipe(
map(([callBaseFee, contractFee, createBaseFee, creationFee, rentByteFee, rentDepositOffset, tombstoneDeposit, transactionBaseFee, transactionByteFee, transferFee]): DerivedContractFees =>
// We've done this on purpose, i.e. so we can just copy the name/order from the parse above and see gaps
parseResult([
callBaseFee, contractFee, createBaseFee, creationFee, rentByteFee, rentDepositOffset, tombstoneDeposit, transactionBaseFee, transactionByteFee, transferFee
])
)
return queryConstants(api).pipe(
map(([creationFee, transferFee, callBaseFee, contractFee, rentByteFee, rentDepositOffset, tombstoneDeposit, transactionBaseFee, transactionByteFee]): DerivedContractFees => ({
callBaseFee,
contractFee,
creationFee,
rentByteFee,
rentDepositOffset,
tombstoneDeposit,
transactionBaseFee,
transactionByteFee,
transferFee
}))
);
});
}
+13 -13
View File
@@ -64,20 +64,20 @@ function parse (api: ApiInterfaceRx, { depositors, proposals, preimages }: Resul
export function proposals (api: ApiInterfaceRx): () => Observable<DeriveProposal[]> {
return memo((): Observable<DeriveProposal[]> =>
api.query.democracy?.publicProps
? api.query.democracy
.publicProps<Proposals>()
.pipe(
switchMap((proposals) =>
combineLatest([
of(proposals),
api.query.democracy.preimages.multi<PreImage>(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 })
)
? api.query.democracy.publicProps<Proposals>().pipe(
switchMap((proposals) =>
combineLatest([
of(proposals),
api.query.democracy.preimages.multi<PreImage>(
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 })
)
)
: of([] as DeriveProposal[])
);
}
@@ -9,7 +9,7 @@ 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, Vec } from '@polkadot/types';
import { Option } from '@polkadot/types';
import { memo } from '../util';
import { retrieveInfo } from './referendumInfo';
@@ -17,9 +17,9 @@ import { retrieveInfo } from './referendumInfo';
export function referendumInfos (api: ApiInterfaceRx): (ids?: (BN | number)[]) => Observable<DerivedReferendum[]> {
return memo((ids: (BN | number)[] = []): Observable<DerivedReferendum[]> =>
(
!ids || !ids.length
!ids?.length
? of([] as Option<ReferendumInfo>[])
: api.query.democracy.referendumInfoOf.multi(ids) as Observable<Vec<Option<ReferendumInfo>>>
: api.query.democracy.referendumInfoOf.multi<Option<ReferendumInfo>>(ids)
).pipe(
switchMap((infos): Observable<(DerivedReferendum | null)[]> =>
combineLatest(
@@ -10,16 +10,16 @@ import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Vec, createType } from '@polkadot/types';
import { DerivedBalances, DerivedReferendumVote } from '../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[], DerivedBalances[]]> =>
switchMap((votersFor): Observable<[Vec<AccountId>, Vote[], DerivedBalancesAccount[]]> =>
combineLatest([
of(votersFor),
api.derive.democracy.votes(referendumId as BN, votersFor),
api.derive.democracy.votes(referendumId, votersFor),
api.derive.balances.votingBalances(votersFor)
])
),
@@ -14,10 +14,9 @@ import { memo } from '../util';
export function referendums (api: ApiInterfaceRx): () => Observable<DerivedReferendum[]> {
return memo((): Observable<DerivedReferendum[]> =>
// V2 vs V1 (and early V2)
api.query.democracy?.lowestUnbaked || api.query.democracy?.nextTally
api.query.democracy?.lowestUnbaked
? api.queryMulti<[ReferendumIndex, ReferendumIndex]>([
api.query.democracy.lowestUnbaked || api.query.democracy.nextTally,
api.query.democracy.lowestUnbaked,
api.query.democracy.referendumCount
]).pipe(
switchMap(([earliest, referendumCount]): Observable<DerivedReferendum[]> =>
+3 -3
View File
@@ -10,12 +10,12 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
import { memo } from '../util';
export function votes (api: ApiInterfaceRx): (referendumId: BN, accountIds?: AccountId[]) => Observable<Vote[]> {
return memo((referendumId: BN, accountIds: AccountId[] = []): Observable<Vote[]> =>
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, AccountId] =>
accountIds.map((accountId): [BN | number, AccountId] =>
[referendumId, accountId]
)
)
+19 -27
View File
@@ -5,7 +5,7 @@
import { AccountId, Balance, BlockNumber } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { Observable, combineLatest } from 'rxjs';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { createType, Vec, u32 } from '@polkadot/types';
@@ -13,39 +13,31 @@ import { createType, Vec, u32 } from '@polkadot/types';
import { DerivedElectionsInfo } from '../types';
import { memo } from '../util';
function deriveElections (api: ApiInterfaceRx, candidates: AccountId[], members: [AccountId, Balance][], runnersUp: [AccountId, Balance][], candidacyBond: Balance, desiredSeats: u32, termDuration: BlockNumber, votingBond: Balance): DerivedElectionsInfo {
return {
candidates,
candidateCount: createType(api.registry, 'u32', candidates.length),
candidacyBond,
desiredSeats,
members: members.sort((a, b): number => b[1].cmp(a[1])),
runnersUp: runnersUp.sort((a, b): number => b[1].cmp(a[1])),
termDuration,
votingBond
};
function sortAccounts ([, balanceA]: ITuple<[AccountId, Balance]>, [, balanceB]: ITuple<[AccountId, Balance]>): number {
return balanceB.cmp(balanceA);
}
function queryElections (api: ApiInterfaceRx): Observable<DerivedElectionsInfo> {
const section = api.query.electionsPhragmen ? 'electionsPhragmen' : 'elections';
// NOTE We have an issue where candidates can return `null` for an empty array, hence
// we are not using multi queries here, so empty array is empty (instead of space-filled)
return combineLatest([
api.query[section].candidates<Vec<AccountId>>(),
api.query[section].members<Vec<ITuple<[AccountId, Balance]>>>(),
api.query[section].runnersUp<Vec<ITuple<[AccountId, Balance]>>>()
return api.queryMulti<[Vec<AccountId>, Vec<AccountId>, Vec<ITuple<[AccountId, Balance]>>, Vec<ITuple<[AccountId, Balance]>>]>([
api.query.council.members,
api.query[section].candidates,
api.query[section].members,
api.query[section].runnersUp
]).pipe(
map(([candidates, members, runnersUp]): DerivedElectionsInfo => deriveElections(
api,
map(([councilMembers, candidates, members, runnersUp]): DerivedElectionsInfo => ({
candidates,
members,
runnersUp,
api.consts[section].candidacyBond as Balance,
api.consts[section].desiredMembers as u32,
api.consts[section].termDuration as BlockNumber,
api.consts[section].votingBond as Balance
))
candidateCount: createType(api.registry, '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')]),
runnersUp: runnersUp.sort(sortAccounts),
termDuration: api.consts[section].termDuration as BlockNumber,
votingBond: api.consts[section].votingBond as Balance
}))
);
}
@@ -17,13 +17,15 @@ import { memo } from '../util';
*/
export function receivedHeartbeats (api: ApiInterfaceRx): () => Observable<DerivedHeartbeats> {
return memo((): Observable<DerivedHeartbeats> =>
api.query.imOnline?.receivedHeartbeats && api.query.imOnline.authoredBlocks
api.query.imOnline?.receivedHeartbeats
? api.derive.staking.overview().pipe(
switchMap(({ currentIndex, validators }): Observable<[AccountId[], Option<Bytes>[], u32[]]> =>
combineLatest([
of(validators),
api.query.imOnline.receivedHeartbeats.multi<Option<Bytes>>(validators.map((_address, index): [SessionIndex, number] => [currentIndex, index])),
api.query.imOnline.authoredBlocks.multi<u32>(validators.map((address): [SessionIndex, AccountId] => [currentIndex, address]))
api.query.imOnline.receivedHeartbeats.multi<Option<Bytes>>(
validators.map((_address, index): [SessionIndex, number] => [currentIndex, index])),
api.query.imOnline.authoredBlocks.multi<u32>(
validators.map((address): [SessionIndex, AccountId] => [currentIndex, address]))
])
),
map(([validators, heartbeats, numBlocks]): DerivedHeartbeats =>
-2
View File
@@ -45,7 +45,6 @@ describe('derive', (): void => {
testFunction(api)('balances', 'fees', []);
testFunction(api)('balances', 'votingBalance', []);
testFunction(api)('balances', 'votingBalances', []);
testFunction(api)('balances', 'votingBalancesNominatorsFor', []);
testFunction(api)('chain', 'bestNumber', []);
testFunction(api)('chain', 'bestNumberFinalized', []);
@@ -62,7 +61,6 @@ describe('derive', (): void => {
testFunction(api)('session', 'sessionProgress', []);
testFunction(api)('staking', 'account', []);
testFunction(api)('staking', 'recentlyOffline', []);
testFunction(api)('staking', 'controllers', []);
});
+26 -3
View File
@@ -16,12 +16,15 @@ import * as democracy from './democracy';
import * as elections from './elections';
import * as imOnline from './imOnline';
import * as session from './session';
import * as society from './society';
import * as staking from './staking';
import * as technicalCommittee from './technicalCommittee';
import * as treasury from './treasury';
export * from './type';
export const derive = { accounts, balances, chain, contracts, council, democracy, elections, imOnline, session, society, staking, technicalCommittee, treasury };
type DeriveSection<Section> = {
[Method in keyof Section]: Section[Method] extends AnyFunction
? ReturnType<Section[Method]> // ReturnType<Section[Method]> will be the inner function, i.e. without (api) argument
@@ -33,13 +36,35 @@ type DeriveAllSections<AllSections> = {
export type DeriveCustom = Record<string, Record<string, (api: ApiInterfaceRx) => (...args: any[]) => Observable<any>>>;
export type ExactDerive = DeriveAllSections<typeof derive>;
// Enable derive only if some of these modules are available
const deriveAvail: Record<string, string[]> = {
contracts: ['contracts'],
council: ['council'],
democracy: ['democracy'],
elections: ['electionsPhragmen', 'elections'],
imOnline: ['imOnline'],
session: ['session'],
society: ['society'],
staking: ['staking'],
technicalCommittee: ['technicalCommittee'],
treasury: ['treasury']
};
/**
* Returns an object that will inject `api` into all the functions inside
* `allSections`, and keep the object architecture of `allSections`.
*/
/** @internal */
function injectFunctions<AllSections> (api: ApiInterfaceRx, allSections: AllSections): DeriveAllSections<AllSections> {
const queryKeys = Object.keys(api.query);
return Object
.keys(allSections)
.filter((sectionName): boolean =>
!deriveAvail[sectionName] || deriveAvail[sectionName].some((query): boolean => queryKeys.includes(query))
)
.reduce((deriveAcc, sectionName): DeriveAllSections<AllSections> => {
const section = allSections[sectionName as keyof AllSections];
@@ -59,11 +84,9 @@ function injectFunctions<AllSections> (api: ApiInterfaceRx, allSections: AllSect
}, {} as DeriveAllSections<AllSections>);
}
export const derive = { accounts, balances, chain, contracts, council, democracy, elections, imOnline, session, staking, technicalCommittee, treasury };
export type ExactDerive = DeriveAllSections<typeof derive>;
// FIXME The return type of this function should be {...ExactDerive, ...DeriveCustom}
// For now we just drop the custom derive typings
/** @internal */
export default function decorateDerive (api: ApiInterfaceRx, custom: DeriveCustom = {}): ExactDerive {
return {
...injectFunctions(api, derive),
+5 -52
View File
@@ -2,50 +2,20 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { BlockNumber, SessionIndex } from '@polkadot/types/interfaces';
import { SessionIndex } from '@polkadot/types/interfaces';
import { DerivedSessionInfo, DeriveSessionIndexes } from '../types';
import { Observable, combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Option, u64, createType } from '@polkadot/types';
import { u64, createType } from '@polkadot/types';
import { memo } from '../util';
type ResultV1Session = [Option<BlockNumber>, BlockNumber, BlockNumber, SessionIndex];
type ResultV1 = [BlockNumber, DeriveSessionIndexes, ResultV1Session];
type ResultSlots = [u64, u64, u64, SessionIndex];
type ResultType = [boolean, u64, SessionIndex];
type Result = [ResultType, DeriveSessionIndexes, ResultSlots];
// internal helper to just split the logic - take all inputs, do the calculations and combine
function createDerivedV1 (api: ApiInterfaceRx, [bestNumber, { currentIndex, validatorCount }, [_lastLengthChange, sessionLength, lastEraLengthChange, sessionsPerEra]]: ResultV1): DerivedSessionInfo {
const lastLengthChange = _lastLengthChange?.unwrapOr(null) || createType(api.registry, 'BlockNumber');
const sessionProgress = bestNumber
.sub(lastLengthChange)
.add(sessionLength)
.mod(sessionLength);
const currentEra = currentIndex
.sub(lastEraLengthChange)
.mod(sessionsPerEra);
const eraProgress = currentEra
.mul(sessionLength)
.add(sessionProgress);
return {
currentEra: createType(api.registry, 'EraIndex', currentEra),
currentIndex,
eraLength: createType(api.registry, 'BlockNumber', sessionLength.mul(sessionsPerEra)),
eraProgress: createType(api.registry, 'BlockNumber', eraProgress),
isEpoch: false,
sessionLength,
sessionsPerEra,
sessionProgress: createType(api.registry, 'BlockNumber', sessionProgress),
validatorCount
};
}
function createDerivedLatest (api: ApiInterfaceRx, [[hasBabe, epochDuration, sessionsPerEra], { currentIndex, currentEra, validatorCount }, [currentSlot, epochIndex, epochOrGenesisStartSlot, currentEraStartSessionIndex]]: Result): DerivedSessionInfo {
const epochStartSlot = epochIndex.mul(epochDuration).add(epochOrGenesisStartSlot);
const sessionProgress = currentSlot.sub(epochStartSlot);
@@ -64,21 +34,6 @@ function createDerivedLatest (api: ApiInterfaceRx, [[hasBabe, epochDuration, ses
};
}
function infoV1 (api: ApiInterfaceRx): Observable<DerivedSessionInfo> {
return combineLatest([
api.derive.chain.bestNumber(),
api.derive.session.indexes(),
api.queryMulti<ResultV1Session>([
api.query.session.lastLengthChange,
api.query.session.sessionLength,
api.query.staking.lastEraLengthChange,
api.query.staking.sessionsPerEra
])
]).pipe(
map((result): DerivedSessionInfo => createDerivedV1(api, result))
);
}
function infoLatestAura (api: ApiInterfaceRx): Observable<DerivedSessionInfo> {
return api.derive.session.indexes().pipe(
map((indexes): DerivedSessionInfo =>
@@ -115,11 +70,9 @@ function infoLatestBabe (api: ApiInterfaceRx): Observable<DerivedSessionInfo> {
* @description Retrieves all the session and era info and calculates specific values on it as the length of the session and eras
*/
export function info (api: ApiInterfaceRx): () => Observable<DerivedSessionInfo> {
const query = api.consts.timestamp || api.consts.babe || api.consts.aura
? api.consts.babe
? infoLatestBabe // 2.x with Babe
: infoLatestAura // 2.x with Aura (not all info there)
: infoV1;
const query = api.consts.babe
? infoLatestBabe // 2.x with Babe
: infoLatestAura; // 2.x with Aura (not all info there)
return memo((): Observable<DerivedSessionInfo> =>
query(api));
@@ -0,0 +1,42 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
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 { map, switchMap } from 'rxjs/operators';
import { Option, Vec } from '@polkadot/types';
import { memo } from '../util';
type ResultSuspend = Option<ITuple<[BalanceOf, BidKind]>>;
type Result = [Bid[], ResultSuspend[]]
/**
* @description Get the candidate info for a society
*/
export function candidates (api: ApiInterfaceRx): () => Observable<DeriveSocietyCandidate[]> {
return memo((): Observable<DeriveSocietyCandidate[]> =>
api.query.society.candidates<Vec<Bid>>().pipe(
switchMap((candidates: Vec<Bid>): Observable<Result> =>
combineLatest([
of(candidates),
api.query.society.suspendedCandidates.multi<ResultSuspend>(
candidates.map(({ who }): AccountId => who))
])
),
map(([candidates, suspended]: Result): DeriveSocietyCandidate[] =>
candidates.map(({ who, kind, value }, index) => ({
accountId: who,
isSuspended: suspended[index].isSome,
kind,
value
}))
)
)
);
}
+8
View File
@@ -0,0 +1,8 @@
// 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 './candidates';
export * from './info';
export * from './member';
export * from './members';
+41
View File
@@ -0,0 +1,41 @@
// 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, BalanceOf, Bid } from '@polkadot/types/interfaces';
import { DeriveSociety } from '../types';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Option, Vec, u32 } from '@polkadot/types';
import { memo } from '../util';
type Result = [Vec<Bid>, Option<AccountId>, Option<AccountId>, Option<AccountId>, u32, BalanceOf]
/**
* @description Get the overall info for a society
*/
export function info (api: ApiInterfaceRx): () => Observable<DeriveSociety> {
return memo((): Observable<DeriveSociety> =>
api.queryMulti<Result>([
api.query.society.bids,
api.query.society.defender,
api.query.society.founder,
api.query.society.head,
api.query.society.maxMembers,
api.query.society.pot
]).pipe(
map(([bids, defender, founder, head, maxMembers, pot]: Result): DeriveSociety => ({
bids,
defender: defender.unwrapOr(undefined),
hasDefender: (defender.isSome && head.isSome && !head.eq(defender)) || false,
head: head.unwrapOr(undefined),
founder: founder.unwrapOr(undefined),
maxMembers,
pot
}))
)
);
}
+40
View File
@@ -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 { AccountId, Balance, BlockNumber, SocietyVote, StrikeCount, VouchingStatus } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DeriveSocietyMember } from '../types';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { bool, Option, Vec } from '@polkadot/types';
import { memo } from '../util';
type Result = [Vec<ITuple<[BlockNumber, Balance]>>, StrikeCount, Option<SocietyVote>, bool, Option<VouchingStatus>];
/**
* @description Get the member info for a society
*/
export function member (api: ApiInterfaceRx): (accountId: AccountId) => Observable<DeriveSocietyMember> {
return memo((accountId: AccountId): Observable<DeriveSocietyMember> =>
api.queryMulti<Result>([
[api.query.society.payouts, accountId],
[api.query.society.strikes, accountId],
[api.query.society.defenderVotes, accountId],
[api.query.society.suspendedMembers, accountId],
[api.query.society.vouching, accountId]
]).pipe(
map(([payouts, strikes, defenderVote, suspended, vouching]: Result): DeriveSocietyMember => ({
accountId,
payouts,
isSuspended: suspended.isTrue,
strikes,
vote: defenderVote.unwrapOr(undefined),
vouching: vouching.unwrapOr(undefined)
}))
)
);
}
@@ -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 { AccountId } from '@polkadot/types/interfaces';
import { DeriveSocietyMember } from '../types';
import { combineLatest, Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { memo } from '../util';
/**
* @description Get the member info for a society
*/
export function members (api: ApiInterfaceRx): () => Observable<DeriveSocietyMember[]> {
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)
))
)
)
);
}
-1
View File
@@ -7,5 +7,4 @@ export * from './controllers';
export * from './electedInfo';
export * from './overview';
export * from './query';
export * from './recentlyOffline';
export * from './validators';
+9 -27
View File
@@ -3,27 +3,23 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId, Exposure, Keys, RewardDestination, ValidatorPrefs } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { AccountId, Exposure, Keys, Nominations, RewardDestination, ValidatorPrefs } from '@polkadot/types/interfaces';
import { DerivedStakingStash } from '../types';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Option, Vec } from '@polkadot/types';
import { Option } from '@polkadot/types';
import { memo } from '../util';
// NOTE Unused ATM, preparing for V2-only
type Result = [Option<AccountId>, Nominations, RewardDestination, Exposure, ValidatorPrefs, Option<Keys>];
type Result = [Option<AccountId>, [Vec<AccountId>], RewardDestination, Exposure, ValidatorPrefs, Option<Keys>?];
type ResultV1 = [Option<AccountId>, ITuple<[Vec<AccountId>]>, RewardDestination, Exposure, ValidatorPrefs];
type ResultV2 = [Option<AccountId>, ITuple<[Vec<AccountId>]>, RewardDestination, Exposure, ValidatorPrefs, Option<Keys>];
function parse (stashId: AccountId, [_controllerId, [nominators], rewardDestination, stakers, validatorPrefs, _nextKeys]: Result): DerivedStakingStash {
function parse (stashId: AccountId, [_controllerId, nominators, rewardDestination, stakers, validatorPrefs, _nextKeys]: Result): DerivedStakingStash {
return {
controllerId: _controllerId.unwrapOr(undefined),
nextKeys: _nextKeys?.unwrapOr(undefined),
nominators,
nextKeys: _nextKeys.unwrapOr(undefined),
nominators: nominators.targets,
nominateAt: nominators.submittedIn,
rewardDestination,
stakers,
stashId,
@@ -31,18 +27,8 @@ function parse (stashId: AccountId, [_controllerId, [nominators], rewardDestinat
};
}
function retrieveV1 (api: ApiInterfaceRx, stashId: AccountId): Observable<Result> {
return api.queryMulti<ResultV1>([
[api.query.staking.bonded, stashId],
[api.query.staking.nominators, stashId],
[api.query.staking.payee, stashId],
[api.query.staking.stakers, stashId],
[api.query.staking.validators, stashId]
]);
}
function retrieveV2 (api: ApiInterfaceRx, stashId: AccountId): Observable<Result> {
return api.queryMulti<ResultV2>([
function query (api: ApiInterfaceRx, stashId: AccountId): Observable<Result> {
return api.queryMulti<Result>([
[api.query.staking.bonded, stashId],
[api.query.staking.nominators, stashId],
[api.query.staking.payee, stashId],
@@ -53,10 +39,6 @@ function retrieveV2 (api: ApiInterfaceRx, stashId: AccountId): Observable<Result
}
export function infoStash (api: ApiInterfaceRx): (stashId: AccountId) => Observable<DerivedStakingStash> {
const query = api.consts.session
? retrieveV2
: retrieveV1;
return memo((stashId: AccountId): Observable<DerivedStakingStash> =>
query(api, stashId).pipe(
map((result): DerivedStakingStash => parse(stashId, result))
+1 -5
View File
@@ -8,7 +8,6 @@ import { DerivedStakingOverview } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { createType } from '@polkadot/types';
import { memo } from '../util';
@@ -24,10 +23,7 @@ export function overview (api: ApiInterfaceRx): () => Observable<DerivedStakingO
switchMap(([{ currentEra, currentIndex, validatorCount }, { currentElected, validators }]) =>
combineLatest([
of({ currentElected, currentEra, currentIndex, validators, validatorCount }),
// this will change on a per block basis, keep it innermost (and it needs eraIndex)
api.query.staking?.currentEraPointsEarned
? api.query.staking.currentEraPointsEarned<EraPoints>(currentEra)
: of(createType(api.registry, 'EraPoints'))
api.query.staking.currentEraPointsEarned<EraPoints>(currentEra)
])
),
map(([{ currentElected, currentEra, currentIndex, validators, validatorCount }, eraPoints]): DerivedStakingOverview => ({
+37 -118
View File
@@ -13,142 +13,61 @@ import { createType, Option, Vec } from '@polkadot/types';
import { memo } from '../util';
interface ParseInput {
accountId: AccountId;
controllerId: AccountId;
nominators: AccountId[];
rewardDestination: RewardDestination;
queuedKeys?: [AccountId, Keys][];
stakers: Exposure;
stakingLedger: Option<StakingLedger>;
stashId: AccountId;
validatorPrefs: ValidatorPrefs;
nextKeys?: Option<Keys>;
nextKeyFor?: Option<AccountId>;
}
type MultiResultV2 = [Option<AccountId>, Option<ITuple<[Nominations]>>, RewardDestination, Exposure, [ValidatorPrefs], Option<Keys>, Option<StakingLedger>];
function unwrapSessionIds (stashId: AccountId, queuedKeys: Option<AccountId> | [AccountId, Keys][], nextKeys: Option<Keys>): { nextSessionIds: AccountId[]; sessionIds: AccountId[] } {
// for 2.x we have a Vec<(ValidatorId,Keys)> of the keys
if (Array.isArray(queuedKeys)) {
const sessionIds = (queuedKeys.find(([currentId]): boolean =>
currentId.eq(stashId)
) || [undefined, [] as AccountId[]])[1];
const nextSessionIds = nextKeys.unwrapOr([] as AccountId[]);
return {
nextSessionIds,
sessionIds
};
}
// substrate 1.x
const nextSessionIds = queuedKeys.isSome
? [queuedKeys.unwrap()]
: [];
function unwrapSessionIds (stashId: AccountId, queuedKeys: [AccountId, Keys][], nextKeys: Option<Keys>): { nextSessionIds: AccountId[]; sessionIds: AccountId[] } {
const sessionIds = (queuedKeys.find(([currentId]): boolean =>
currentId.eq(stashId)
) || [undefined, [] as AccountId[]])[1];
const nextSessionIds = nextKeys.unwrapOr([] as AccountId[]);
return {
nextSessionIds,
sessionIds: nextSessionIds
sessionIds
};
}
function parseResult (api: ApiInterfaceRx, { accountId, controllerId, stashId, nextKeyFor, queuedKeys, stakingLedger, nominators, rewardDestination, stakers, validatorPrefs, nextKeys }: ParseInput): DerivedStakingQuery {
const _stakingLedger = stakingLedger.unwrapOr(undefined);
const _nextKeyFor = nextKeyFor || createType(api.registry, 'Option<AccountId>', null);
const _nextKeys = nextKeys || createType(api.registry, 'Option<Keys>', null);
return {
accountId,
controllerId,
nominators,
rewardDestination,
stakers,
stakingLedger: _stakingLedger,
stashId,
validatorPrefs,
...unwrapSessionIds(stashId, queuedKeys || _nextKeyFor, _nextKeys)
};
}
type MultiResultV1 = [Option<AccountId>, Option<StakingLedger>, [Vec<AccountId>], RewardDestination, Exposure, ITuple<[ValidatorPrefs]>];
function retrieveInfoV1 (api: ApiInterfaceRx, accountId: AccountId, stashId: AccountId, controllerId: AccountId): Observable<DerivedStakingQuery> {
return (
api.queryMulti([
[api.query.session.nextKeyFor, controllerId],
[api.query.staking.ledger, controllerId],
[api.query.staking.nominators, stashId],
[api.query.staking.payee, stashId],
[api.query.staking.stakers, stashId],
[api.query.staking.validators, stashId]
]) as Observable<MultiResultV1>
).pipe(map(([nextKeyFor, stakingLedger, [nominators], rewardDestination, stakers, [validatorPrefs]]: MultiResultV1): DerivedStakingQuery =>
parseResult(api, {
accountId, controllerId, stashId, nextKeyFor, stakingLedger, nominators, rewardDestination, stakers, validatorPrefs
})
));
}
type MultiResultV2 = [[Vec<AccountId>] | Option<ITuple<[Nominations]>>, RewardDestination, Exposure, [ValidatorPrefs], Option<Keys>, Option<StakingLedger>];
function retrieveInfoV2 (api: ApiInterfaceRx, accountId: AccountId, stashId: AccountId, controllerId: AccountId): Observable<DerivedStakingQuery> {
function retrieve (api: ApiInterfaceRx, stashId: AccountId): Observable<[Vec<ITuple<[AccountId, Keys]>>, MultiResultV2]> {
return combineLatest([
api.query.session.queuedKeys<Vec<ITuple<[AccountId, Keys]>>>(),
api.queryMulti([
[api.query.staking.bonded, stashId],
[api.query.staking.nominators, stashId],
[api.query.staking.payee, stashId],
[api.query.staking.stakers, stashId],
[api.query.staking.validators, stashId],
[api.query.session.nextKeys, [api.consts.session.dedupKeyPrefix, stashId]],
[api.query.staking.ledger, controllerId]
[api.query.session.nextKeys, [api.consts.session.dedupKeyPrefix, stashId]]
]) as Observable<MultiResultV2>
]).pipe(map(([queuedKeys, [_nominators, rewardDestination, stakers, [validatorPrefs], nextKeys, stakingLedger]]: [[AccountId, Keys][], MultiResultV2]): DerivedStakingQuery => {
// if we have staking.storageVersion it indicates the new structure, unwrap as needed
// FIXME We really want to be pulling all the new (valuable) info along
const nominators: AccountId[] = api.query.staking.storageVersion
? (_nominators as Option<ITuple<[Nominations]>>).isSome
? (_nominators as Option<ITuple<[Nominations]>>).unwrap()[0].targets
: []
: (_nominators as [Vec<AccountId>])[0];
return parseResult(api, {
accountId, controllerId, stashId, queuedKeys, stakingLedger, nominators, rewardDestination, stakers, validatorPrefs, nextKeys
});
}));
}
function retrieveV1 (api: ApiInterfaceRx, accountId: AccountId): Observable<DerivedStakingQuery> {
// depending on where we come from, this may be a controller or stash
return combineLatest([
api.query.staking.bonded<Option<AccountId>>(accountId),
api.query.staking.ledger<Option<StakingLedger>>(accountId)
]).pipe(switchMap(([bonded, stakingLedger]): Observable<DerivedStakingQuery> =>
stakingLedger.isSome
? retrieveInfoV1(api, accountId, stakingLedger.unwrap().stash, accountId)
: bonded.isSome
? retrieveInfoV1(api, accountId, accountId, bonded.unwrap())
: of({ accountId: accountId, nextSessionIds: [], sessionIds: [] })
));
}
function retrieveV2 (api: ApiInterfaceRx, stashId: AccountId): Observable<DerivedStakingQuery> {
return api.query.staking
.bonded<Option<AccountId>>(stashId)
.pipe(switchMap((controllerId): Observable<DerivedStakingQuery> =>
controllerId.isSome
? retrieveInfoV2(api, stashId, stashId, controllerId.unwrap())
: of({ accountId: stashId, nextSessionIds: [], sessionIds: [] })
));
]);
}
/**
* @description From a stash, retrieve the controllerId and fill in all the relevant staking details
* @description From a stash, retrieve the controllerId and all relevant details
*/
export function query (api: ApiInterfaceRx): (_accountId: Uint8Array | string) => Observable<DerivedStakingQuery> {
const retrieve = api.consts.session
? retrieveV2
: retrieveV1;
export function query (api: ApiInterfaceRx): (accountId: Uint8Array | string) => Observable<DerivedStakingQuery> {
return memo((accountId: Uint8Array | string): Observable<DerivedStakingQuery> => {
const stashId = createType(api.registry, 'AccountId', accountId);
return memo((accountId: Uint8Array | string): Observable<DerivedStakingQuery> =>
retrieve(api, createType(api.registry, 'AccountId', accountId)));
return retrieve(api, stashId).pipe(
switchMap(([queuedKeys, [controllerIdOpt, nominatorsOpt, rewardDestination, stakers, [validatorPrefs], nextKeys]]): Observable<DerivedStakingQuery> => {
const controllerId = controllerIdOpt.unwrapOr(null);
return controllerId
? api.query.staking.ledger(controllerId).pipe(
map((stakingLedgerOpt): DerivedStakingQuery => ({
accountId: stashId,
controllerId,
nominators: nominatorsOpt.unwrapOr([{ targets: [] }])[0].targets,
rewardDestination,
stakers,
stakingLedger: stakingLedgerOpt.unwrapOr(undefined),
stashId,
validatorPrefs,
...unwrapSessionIds(stashId, queuedKeys, nextKeys)
}))
)
: of({ accountId: stashId, nextSessionIds: [], sessionIds: [] });
})
);
});
}
@@ -1,49 +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, BlockNumber } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DerivedRecentlyOffline } from '../types';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { Vec, u32 } from '@polkadot/types';
import { memo } from '../util';
type OfflineResult = Vec<ITuple<[AccountId, BlockNumber, u32]>>;
function expandDerived (recentlyOffline: OfflineResult): DerivedRecentlyOffline {
return recentlyOffline.reduce((result: DerivedRecentlyOffline, [accountId, blockNumber, count]): DerivedRecentlyOffline => {
const key = accountId.toString();
if (!result[key]) {
result[key] = [];
}
result[key].push({
blockNumber,
count
});
return result;
}, {});
}
/**
* @description Retrieve a keyed record of accounts recently reported to be offline
*/
export function recentlyOffline (api: ApiInterfaceRx): () => Observable<DerivedRecentlyOffline> {
return memo((): Observable<DerivedRecentlyOffline> =>
(
// TODO recentlyOffline has been dropped for 2.x and replaced, figure out the
// replacement as actually use and implement it
api.query.staking.recentlyOffline
? api.query.staking.recentlyOffline<OfflineResult>()
: of([] as unknown as OfflineResult)
).pipe(
map(expandDerived)
));
}
+12 -13
View File
@@ -2,13 +2,11 @@
// 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 { DeriveStakingValidators } from '../types';
import { Observable, of } from 'rxjs';
import { Observable, combineLatest, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { Vec } from '@polkadot/types';
import { memo } from '../util';
@@ -17,16 +15,17 @@ import { memo } from '../util';
*/
export function validators (api: ApiInterfaceRx): () => Observable<DeriveStakingValidators> {
return memo((): Observable<DeriveStakingValidators> =>
(
// Sadly the node-template is (for some obscure reason) not comprehensive, so while the derive works
// in all actual real-world deployed chains, it does create some confusion for limited template chains
api.query.session && api.query.staking
? api.queryMulti<[Vec<AccountId>, Vec<AccountId>]>([
api.query.session.validators,
api.query.staking.currentElected
])
: of([[], []] as [AccountId[], AccountId[]])
).pipe(
// Sadly the node-template is (for some obscure reason) not comprehensive, so while the derive works
// in all actual real-world deployed chains, it does create some confusion for limited template chains
// NOTE: Not doing multi queries here, since we have validators as a single in the derived newHead
combineLatest([
api.query.session
? api.query.session.validators()
: of([]),
api.query.staking
? api.query.staking.currentElected()
: of([])
]).pipe(
map(([validators, currentElected]): DeriveStakingValidators => ({
currentElected, validators
}))
@@ -62,10 +62,7 @@ function retrieveProposals (api: ApiInterfaceRx, proposalCount: ProposalIndex, a
const allIds = [...proposalIds, ...approvalIds];
return combineLatest([
// We are doing single subscriptions on all these, multi may yield old results
combineLatest(
allIds.map((id): Observable<Option<TreasuryProposal>> => api.query.treasury.proposals(id))
),
api.query.treasury.proposals.multi<Option<TreasuryProposal>>(allIds),
api.derive.council.proposals()
]).pipe(
map(([allProposals, councilProposals]: [Option<TreasuryProposal>[], DerivedCollectiveProposals]): DerivedTreasuryProposals =>
+38 -6
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 { AccountId, AccountIndex, Balance, BalanceLock, BlockNumber, EraIndex, EraPoints, Exposure, Hash, Index, Keys, Proposal, PropIndex, ProposalIndex, ReferendumInfo, RegistrationJudgement, RewardDestination, SessionIndex, SetIndex, StakingLedger, TreasuryProposal, ValidatorPrefs, Vote, Votes, VoteIndex } from '@polkadot/types/interfaces';
import { AccountId, AccountIndex, Balance, BalanceLock, BalanceLockTo212, BalanceOf, Bid, BidKind, BlockNumber, EraIndex, EraPoints, Exposure, Hash, Index, Keys, Proposal, PropIndex, ProposalIndex, ReferendumInfo, RegistrationJudgement, RewardDestination, SessionIndex, SetIndex, SocietyVote, StakingLedger, StrikeCount, TreasuryProposal, ValidatorPrefs, Vote, Votes, VoteIndex, VouchingStatus } from '@polkadot/types/interfaces';
import BN from 'bn.js';
import { u32, Vec } from '@polkadot/types';
@@ -30,26 +30,31 @@ export interface DeriveAccountInfo {
nickname?: string;
}
export interface DerivedBalances {
export interface DerivedBalancesAccount {
accountId: AccountId;
accountNonce: Index;
freeBalance: Balance;
frozenFee: Balance;
frozenMisc: Balance;
reservedBalance: Balance;
votingBalance: Balance;
}
export interface DerivedBalancesAll extends DerivedBalancesAccount {
isVesting: boolean;
lockedBalance: Balance;
lockedBreakdown: BalanceLock[];
lockedBreakdown: (BalanceLock | BalanceLockTo212)[];
availableBalance: Balance;
reservedBalance: Balance;
votingBalance: Balance;
vestedBalance: Balance;
vestingTotal: Balance;
}
export type DerivedBalancesMap = Record<string, DerivedBalances>;
export type DerivedBalancesMap = Record<string, DerivedBalancesAll>;
export interface DerivedContractFees {
callBaseFee: BN;
contractFee: BN;
createBaseFee: BN;
creationFee: BN;
rentByteFee: BN;
rentDepositOffset: BN;
@@ -149,6 +154,32 @@ export interface DerivedSessionInfo extends DeriveSessionIndexes {
sessionProgress: BlockNumber;
}
export interface DeriveSociety {
bids: Bid[];
defender?: AccountId;
hasDefender: boolean;
head?: AccountId;
founder?: AccountId;
maxMembers: u32;
pot: BalanceOf;
}
export interface DeriveSocietyCandidate {
accountId: AccountId;
kind: BidKind;
value: Balance;
isSuspended: boolean;
}
export interface DeriveSocietyMember {
accountId: AccountId;
isSuspended: boolean;
payouts: [BlockNumber, Balance][];
strikes: StrikeCount;
vote?: SocietyVote;
vouching?: VouchingStatus;
}
export interface DerivedStakingElected {
currentElected: AccountId[];
info: DerivedStakingQuery[];
@@ -162,6 +193,7 @@ export interface DeriveStakingValidators {
export interface DerivedStakingStash {
controllerId?: AccountId;
nominators?: AccountId[];
nominateAt?: EraIndex;
rewardDestination?: RewardDestination;
nextKeys?: Keys;
stakers?: Exposure;
@@ -6,6 +6,7 @@ import { ApprovalFlag } from '@polkadot/types/interfaces/elections';
import { Vec } from '@polkadot/types';
/** @internal */
export function approvalFlagsToBools (flags: Vec<ApprovalFlag> | ApprovalFlag[]): boolean[] {
const bools: boolean[] = [];
+1
View File
@@ -15,6 +15,7 @@ const normalizer = JSON.stringify;
// Wraps a derive, doing 2 things to optimize calls -
// 1. creates a memo of the inner fn -> Observable, removing when unsubscribed
// 2. wraps the observable in a drr() (which includes an unsub delay)
/** @internal */
export function memo <T> (inner: ObsFn<T>): ObsFn<T> {
const cached = createMemo(
(...params: any[]): Observable<T> =>
+10 -10
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api",
"version": "0.100.1",
"version": "1.1.1",
"description": "Promise and RxJS wrappers around the Polkadot JS RPC",
"main": "index.js",
"keywords": [
@@ -26,16 +26,16 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api#readme",
"dependencies": {
"@babel/runtime": "^7.7.7",
"@polkadot/api-derive": "^0.100.1",
"@polkadot/keyring": "^1.8.1",
"@polkadot/metadata": "^0.100.1",
"@polkadot/rpc-core": "^0.100.1",
"@polkadot/rpc-provider": "^0.100.1",
"@polkadot/types": "^0.100.1",
"@polkadot/util-crypto": "^1.8.1"
"@babel/runtime": "^7.8.3",
"@polkadot/api-derive": "^1.1.1",
"@polkadot/keyring": "^2.2.1",
"@polkadot/metadata": "^1.1.1",
"@polkadot/rpc-core": "^1.1.1",
"@polkadot/rpc-provider": "^1.1.1",
"@polkadot/types": "^1.1.1",
"@polkadot/util-crypto": "^2.2.1"
},
"devDependencies": {
"@polkadot/keyring": "^1.8.1"
"@polkadot/keyring": "^2.2.1"
}
}
+35 -37
View File
@@ -3,28 +3,25 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Constants, Storage } from '@polkadot/metadata/Decorated/types';
import { RpcInterface } from '@polkadot/rpc-core/jsonrpc.types';
import { RpcInterface } from '@polkadot/rpc-core/types';
import { InterfaceRegistry } from '@polkadot/types/interfaceRegistry';
import { Call, Hash, RuntimeVersion } from '@polkadot/types/interfaces';
import { AnyFunction, CallFunction, Codec, CodecArg as Arg, ITuple, ModulesWithCalls, Registry } from '@polkadot/types/types';
import { AnyFunction, CallFunction, Codec, CodecArg as Arg, ITuple, InterfaceTypes, ModulesWithCalls, Registry, RegistryTypes } from '@polkadot/types/types';
import { SubmittableExtrinsic } from '../submittable/types';
import {
ApiInterfaceRx, ApiOptions, ApiTypes,
DecorateMethod, DecoratedRpc, DecoratedRpcSection,
QueryableModuleStorage, QueryableStorage, QueryableStorageEntry, QueryableStorageMulti, QueryableStorageMultiArg,
SubmittableExtrinsicFunction, SubmittableExtrinsics, SubmittableModuleExtrinsics
} from '../types';
import { ApiInterfaceRx, ApiOptions, ApiTypes, DecorateMethod, DecoratedRpc, DecoratedRpcSection, QueryableModuleStorage, QueryableStorage, QueryableStorageEntry, QueryableStorageMulti, QueryableStorageMultiArg, SubmittableExtrinsicFunction, SubmittableExtrinsics, SubmittableModuleExtrinsics } from '../types';
import BN from 'bn.js';
import { BehaviorSubject, Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import decorateDerive, { ExactDerive } from '@polkadot/api-derive';
import getHasher from '@polkadot/metadata/Decorated/storage/fromMetadata/getHasher';
import RpcCore from '@polkadot/rpc-core';
import { WsProvider } from '@polkadot/rpc-provider';
import { Metadata, Null, Option, TypeRegistry, u64, Vec } from '@polkadot/types';
import Linkage, { LinkageResult } from '@polkadot/types/codec/Linkage';
import { DEFAULT_VERSION as EXTRINSIC_DEFAULT_VERSION } from '@polkadot/types/primitive/Extrinsic/constants';
import StorageKey, { StorageEntry } from '@polkadot/types/primitive/StorageKey';
import { assert, compactStripLength, u8aToHex } from '@polkadot/util';
import { assert, compactStripLength, isNull, isUndefined, u8aConcat, u8aToHex } from '@polkadot/util';
import { createSubmittable } from '../submittable';
import { decorateSections, DeriveAllSections } from '../util/decorate';
@@ -132,6 +129,10 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
this._rx.registry = this.registry;
}
public abstract createType <K extends InterfaceTypes> (type: K, ...params: any[]): InterfaceRegistry[K];
public abstract registerTypes (types?: RegistryTypes): void;
/**
* @returns `true` if the API operates with subscriptions
*/
@@ -257,10 +258,8 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
: [creator, ...args];
// FIXME We probably want to be able to query the full list with non-subs as well
const decorated = this.hasSubscriptions && creator.iterKey && (creator.meta.type.asMap.kind.isLinkedMap || creator.meta.type.asMap.kind.isPrefixedMap)
? creator.meta.type.asMap.kind.isLinkedMap
? this.decorateStorageLinked(creator, decorateMethod)
: this.decorateStoragePrefixed(creator, decorateMethod)
const decorated = this.hasSubscriptions && creator.iterKey && creator.meta.type.isMap && creator.meta.type.asMap.linked.isTrue
? this.decorateStorageLinked(creator, decorateMethod)
: decorateMethod((...args: any[]): Observable<Codec> => (
this.hasSubscriptions
? this._rpcCore.state
@@ -277,8 +276,8 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
decorated.at = decorateMethod((hash: Hash, arg1?: Arg, arg2?: Arg): Observable<Codec> =>
this._rpcCore.state.getStorage(getArgs(arg1, arg2), hash));
decorated.entries = decorateMethod((): Observable<[StorageKey, Codec][]> =>
this.retrieveMapEntries(creator));
decorated.entries = decorateMethod((doubleMapArg?: Arg): Observable<[StorageKey, Codec][]> =>
this.retrieveMapEntries(creator, doubleMapArg));
decorated.hash = decorateMethod((arg1?: Arg, arg2?: Arg): Observable<Hash> =>
this._rpcCore.state.getStorageHash(getArgs(arg1, arg2)));
@@ -286,6 +285,9 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
decorated.key = (arg1?: Arg, arg2?: Arg): string =>
u8aToHex(compactStripLength(creator(creator.meta.type.isDoubleMap ? [arg1, arg2] : arg1))[1]);
decorated.keyPrefix = (): string =>
u8aToHex(creator.keyPrefix);
if (this.hasSubscriptions) {
// When using double map storage function, user need to pass double map key as an array
decorated.multi = decorateMethod((args: (Arg | Arg[])[]): Observable<Codec[]> =>
@@ -371,15 +373,26 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
);
}
private retrieveMapData (creator: StorageEntry): Observable<[StorageKey[], Vec<Codec>]> {
assert(creator.meta.type.isMap, 'entries can only be retrieved on maps');
private retrieveMapEntries (creator: StorageEntry, arg?: Arg): Observable<[StorageKey, Codec][]> {
assert(creator.iterKey && (creator.meta.type.isMap || creator.meta.type.isDoubleMap), 'entries can only be retrieved on maps, linked maps and double maps');
const outputType = creator.meta.type.asMap.value.toString();
const outputType = creator.meta.type.isMap
? creator.meta.type.asMap.value.toString()
: creator.meta.type.asDoubleMap.value.toString();
return this._rpcCore.state
// FIXME This should really be some sort of subscription, so we can get stuff as
// it changes (as of now it is a one-shot query). Not sure how to do this though...
.getKeys(creator.iterKey)
.getKeys(
this.createType('Raw', u8aConcat(
creator.iterKey,
creator.meta.type.isDoubleMap && !isUndefined(arg) && !isNull(arg)
? getHasher(creator.meta.type.asDoubleMap.hasher)(
this.createType(creator.meta.type.asDoubleMap.key1.toString() as 'Raw', arg).toU8a()
)
: new Uint8Array([])
))
)
.pipe(
switchMap((keys): Observable<[StorageKey[], Vec<Codec>]> =>
combineLatest([
@@ -389,28 +402,13 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
keys.map((key) => key.setOutputType(outputType))
)
])
),
map(([keys, values]): [StorageKey, Codec][] =>
keys.map((key, index): [StorageKey, Codec] => [key, values[index]])
)
);
}
private retrieveMapEntries (creator: StorageEntry): Observable<[StorageKey, Codec][]> {
return this.retrieveMapData(creator).pipe(
map(([keys, values]): [StorageKey, Codec][] =>
keys.map((key, index): [StorageKey, Codec] => [key, values[index]])
)
);
}
private decorateStoragePrefixed<ApiType extends ApiTypes> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>): ReturnType<DecorateMethod<ApiType>> {
return decorateMethod((...args: any[]): Observable<Codec> =>
args.length
? this._rpcCore.state
.subscribeStorage<[Codec]>([[creator, ...args]])
.pipe(map(([data]): Codec => data))
: this.retrieveMapData(creator).pipe(map(([, values]): Vec<Codec> => values))
);
}
protected decorateDeriveRx (decorateMethod: DecorateMethod<ApiType>): DeriveAllSections<'rxjs', ExactDerive> {
// Pull in derive from api-derive
const derive = decorateDerive(this._rx as ApiInterfaceRx, this._options.derives);
+12 -5
View File
@@ -3,18 +3,17 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { SignedBlock } from '@polkadot/types/interfaces';
import { RegistryTypes } from '@polkadot/types/types';
import { ApiBase, ApiOptions, ApiTypes, DecorateMethod } from '../types';
import DecoratedMeta from '@polkadot/metadata/Decorated';
import { Metadata, u32 as U32 } from '@polkadot/types';
import { getChainTypes, getMetadataTypes } from '@polkadot/types/known';
import { LATEST_EXTRINSIC_VERSION } from '@polkadot/types/primitive/Extrinsic/Extrinsic';
import { logger } from '@polkadot/util';
import { cryptoWaitReady, setSS58Format } from '@polkadot/util-crypto';
import addressDefaults from '@polkadot/util-crypto/address/defaults';
import Decorate from './Decorate';
import { getChainTypes, getMetadataTypes } from './typeInjector';
const KEEPALIVE_INTERVAL = 15000;
@@ -46,9 +45,14 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
this._rpcCore.provider.on('disconnected', this._onProviderDisconnect);
this._rpcCore.provider.on('error', this._onProviderError);
this._rpcCore.provider.on('connected', this._onProviderConnect);
}
public abstract registerTypes (types?: RegistryTypes): void;
// If the provider was instantiated earlier, and has already emitted a
// 'connected' event, then the `on('connected')` won't fire anymore. To
// cater for this case, we call manually `this._onProviderConnect`.
if (this._rpcCore.provider.isConnected()) {
this._onProviderConnect();
}
}
protected async loadMeta (): Promise<boolean> {
const { metadata = {} } = this._options;
@@ -124,9 +128,12 @@ export default abstract class Init<ApiType extends ApiTypes> extends Decorate<Ap
this.registerTypes(getMetadataTypes(metadata.version));
const decoratedMeta = new DecoratedMeta(this.registry, metadata);
const metaExtrinsic = metadata.asLatest.extrinsic;
// only inject if we are not a clone (global init)
if (!this._options.source) {
if (metaExtrinsic.version.gtn(0)) {
this._extrinsicType = metaExtrinsic.version.toNumber();
} else if (!this._options.source) {
// detect the extrinsic version in-use based on the last block
const { block: { extrinsics: [firstTx] } }: SignedBlock = await this._rpcCore.chain.getBlock().toPromise();
+22 -10
View File
@@ -3,10 +3,10 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { Constants } from '@polkadot/metadata/Decorated/types';
import { RpcInterface } from '@polkadot/rpc-core/jsonrpc.types';
import { RpcInterface } from '@polkadot/rpc-core/types';
import { Hash, RuntimeVersion } from '@polkadot/types/interfaces';
import { InterfaceRegistry } from '@polkadot/types/interfaceRegistry';
import { CallFunction, InterfaceTypes, RegistryTypes, SignerPayloadRawBase } from '@polkadot/types/types';
import { CallFunction, InterfaceTypes, RegistryError, RegistryTypes, SignerPayloadRawBase } from '@polkadot/types/types';
import { ApiInterfaceRx, ApiOptions, ApiTypes, DecoratedRpc, DecorateMethod, QueryableStorage, QueryableStorageMulti, SubmittableExtrinsics, Signer } from '../types';
import { Metadata, createType } from '@polkadot/types';
@@ -18,6 +18,10 @@ interface KeyringSigner {
sign (message: Uint8Array): Uint8Array;
}
interface SignerRawOptions {
signer?: Signer;
}
let pkgJson: { name: string; version: string };
try {
@@ -239,12 +243,19 @@ export default abstract class ApiBase<ApiType extends ApiTypes> extends Init<Api
}
/**
* @description Finds the definition for a specific [[Call]] based on the index supplied
* @description Finds the definition for a specific [[CallFunction]] based on the index supplied
*/
public findCall (callIndex: Uint8Array | string): CallFunction {
return this.registry.findMetaCall(u8aToU8a(callIndex));
}
/**
* @description Finds the definition for a specific [[RegistryError]] based on the index supplied
*/
public findError (errorIndex: Uint8Array | string): RegistryError {
return this.registry.findMetaError(u8aToU8a(errorIndex));
}
/**
* @description Register additional user-defined of chain-specific types in the type registry
*/
@@ -262,20 +273,21 @@ export default abstract class ApiBase<ApiType extends ApiTypes> extends Init<Api
/**
* @description Signs a raw signer payload, string or Uint8Array
*/
public async sign (signer: KeyringSigner | string, data: SignerPayloadRawBase): Promise<string> {
// NOTE Do we really want to do this? Or turn it into an observable for rxjs?
if (isString(signer)) {
assert(this._rx.signer?.signRaw, 'No signer exists with a signRaw interface');
public async sign (address: KeyringSigner | string, data: SignerPayloadRawBase, { signer }: SignerRawOptions = {}): Promise<string> {
if (isString(address)) {
const _signer = signer || this._rx.signer;
assert(_signer?.signRaw, 'No signer exists with a signRaw interface');
return (
await this._rx.signer.signRaw({
await _signer.signRaw({
type: 'bytes',
...data,
address: signer
address
})
).signature;
}
return u8aToHex(signer.sign(u8aToU8a(data.data)));
return u8aToHex(address.sign(u8aToU8a(data.data)));
}
}
-101
View File
@@ -1,101 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { RuntimeVersion } from '@polkadot/types/interfaces';
import { RegistryTypes } from '@polkadot/types/types';
import { Text } from '@polkadot/types';
import { isUndefined } from '@polkadot/util';
interface VersionedType {
minmax: [number?, number?]; // min (v >= min) and max (v <= max)
types: RegistryTypes;
}
// these are override types for Polkadot & Kusama chains
// NOTE The SessionKeys definition for Polkadot and Substrate (OpaqueKeys
// implementation) are different. Detect Polkadot and inject the `Keys`
// definition as applicable. (4 keys in substrate vs 5 in Polkadot/CC3).
const TYPES_POLKADOT_VERSIONED: VersionedType[] = [
{
minmax: [1000, undefined], // from launch
types: {
Keys: 'SessionKeys5'
}
}
];
const TYPES_KUSAMA_VERSIONED: VersionedType[] = [
{
minmax: [1019, 1031], // CC3, from launch
types: {
DispatchError: 'DispatchErrorTo198',
Keys: 'SessionKeys5'
}
},
{
minmax: [1032, undefined], // CC3, with DispatchError
types: {
Keys: 'SessionKeys5'
}
}
];
// Type overrides based on specific nodes
const TYPES_CHAIN: Record<string, VersionedType[]> = {};
// Type overrides based on metadata versions
const TYPES_META: VersionedType[] = [
{
// NOTE this is for support of old, e.g. Alex, old metadata and BlockNumber/Index
// This is detected based on metadata version, since this is what we have up-front
// v3 = Alex
// v4 = v1.0 branch
minmax: [0, 4],
types: {
BlockNumber: 'u64',
Index: 'u64',
EventRecord: 'EventRecordTo76',
ValidatorPrefs: 'ValidatorPrefsTo145'
}
}
];
// Type overrides for specific spec types & versions as given in runtimeVersion
const TYPES_SPEC: Record<string, VersionedType[]> = {
kusama: TYPES_KUSAMA_VERSIONED,
polkadot: TYPES_POLKADOT_VERSIONED
};
// flatten a VersionedType[] into a Record<string, string>
function filterVersions (versions: VersionedType[] = [], version: number): RegistryTypes {
return versions
.filter(({ minmax: [min, max] }): boolean =>
(isUndefined(min) || version >= min) &&
(isUndefined(max) || version <= max)
)
.reduce((result: RegistryTypes, { types }): RegistryTypes => ({
...result,
...types
}), {});
}
// based on the metadata version, return the registry types
export function getMetadataTypes (version: number): RegistryTypes {
return filterVersions(TYPES_META, version);
}
// based on the chain and runtimeVersion, get the applicable types (ready for registration)
export function getChainTypes (chainName: Text, { specName, specVersion }: RuntimeVersion, typesChain: Record<string, RegistryTypes> = {}, typesSpec: Record<string, RegistryTypes> = {}): RegistryTypes {
const _chainName = chainName.toString();
const _specName = specName.toString();
const _specVersion = specVersion.toNumber();
return {
...filterVersions(TYPES_SPEC[_specName], _specVersion),
...filterVersions(TYPES_CHAIN[_chainName], _specVersion),
...(typesSpec[_specName] || {}),
...(typesChain[_chainName] || {})
};
}
+8 -1
View File
@@ -35,7 +35,7 @@ async function derive (api: ApiPromise): Promise<void> {
}
async function query (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
const intentions = await api.query.staking.intentions();
const intentions = await api.query.staking.bonded();
console.log('intentions:', intentions);
// api.query.*.* is well-typed
@@ -116,6 +116,13 @@ async function tx (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
unsub2();
});
// it allows for query & then using the submittable
const second = api.tx.democracy.second(123);
second.signAndSend('123', (result): void => {
console.log(result);
});
}
async function main (): Promise<void> {
-98
View File
@@ -1,98 +0,0 @@
// Auto-generated via `yarn build:interfaces`, do not edit
/* eslint-disable @typescript-eslint/no-empty-interface */
import { Bytes, u32, u64 } from '@polkadot/types';
import { Balance, BalanceOf, BlockNumber, Moment, Permill } from '@polkadot/types/interfaces/runtime';
import { Gas } from '@polkadot/types/interfaces/contracts';
import { SessionIndex } from '@polkadot/types/interfaces/session';
import { EraIndex } from '@polkadot/types/interfaces/staking';
import { Codec } from '@polkadot/types/types';
declare module '@polkadot/metadata/Decorated/types' {
export interface Constants {
babe: {
[index: string]: Codec;
epochDuration: u64 & ConstantCodec;
expectedBlockTime: Moment & ConstantCodec;
};
timestamp: {
[index: string]: Codec;
minimumPeriod: Moment & ConstantCodec;
};
balances: {
[index: string]: Codec;
existentialDeposit: Balance & ConstantCodec;
transferFee: Balance & ConstantCodec;
creationFee: Balance & ConstantCodec;
};
transactionPayment: {
[index: string]: Codec;
transactionBaseFee: BalanceOf & ConstantCodec;
transactionByteFee: BalanceOf & ConstantCodec;
};
staking: {
[index: string]: Codec;
sessionsPerEra: SessionIndex & ConstantCodec;
bondingDuration: EraIndex & ConstantCodec;
};
session: {
[index: string]: Codec;
dedupKeyPrefix: Bytes & ConstantCodec;
};
democracy: {
[index: string]: Codec;
enactmentPeriod: BlockNumber & ConstantCodec;
launchPeriod: BlockNumber & ConstantCodec;
votingPeriod: BlockNumber & ConstantCodec;
minimumDeposit: BalanceOf & ConstantCodec;
emergencyVotingPeriod: BlockNumber & ConstantCodec;
cooloffPeriod: BlockNumber & ConstantCodec;
preimageByteDeposit: BalanceOf & ConstantCodec;
};
elections: {
[index: string]: Codec;
candidacyBond: BalanceOf & ConstantCodec;
votingBond: BalanceOf & ConstantCodec;
desiredMembers: u32 & ConstantCodec;
desiredRunnersUp: u32 & ConstantCodec;
termDuration: BlockNumber & ConstantCodec;
};
finalityTracker: {
[index: string]: Codec;
windowSize: BlockNumber & ConstantCodec;
reportLatency: BlockNumber & ConstantCodec;
};
treasury: {
[index: string]: Codec;
proposalBond: Permill & ConstantCodec;
proposalBondMinimum: BalanceOf & ConstantCodec;
spendPeriod: BlockNumber & ConstantCodec;
burn: Permill & ConstantCodec;
};
contracts: {
[index: string]: Codec;
signedClaimHandicap: BlockNumber & ConstantCodec;
tombstoneDeposit: BalanceOf & ConstantCodec;
storageSizeOffset: u32 & ConstantCodec;
rentByteFee: BalanceOf & ConstantCodec;
rentDepositOffset: BalanceOf & ConstantCodec;
surchargeReward: BalanceOf & ConstantCodec;
transferFee: BalanceOf & ConstantCodec;
creationFee: BalanceOf & ConstantCodec;
transactionBaseFee: BalanceOf & ConstantCodec;
transactionByteFee: BalanceOf & ConstantCodec;
contractFee: BalanceOf & ConstantCodec;
callBaseFee: Gas & ConstantCodec;
instantiateBaseFee: Gas & ConstantCodec;
maxDepth: u32 & ConstantCodec;
maxValueSize: u32 & ConstantCodec;
blockGasLimit: Gas & ConstantCodec;
};
nicks: {
[index: string]: Codec;
reservationFee: BalanceOf & ConstantCodec;
minLength: u32 & ConstantCodec;
maxLength: u32 & ConstantCodec;
};
}
}
+8 -2
View File
@@ -2,9 +2,15 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { assertSingletonPackage } from '@polkadot/util';
import { detectPackage } from '@polkadot/util';
assertSingletonPackage('@polkadot/api');
// eslint-disable-next-line no-useless-catch
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
detectPackage(require('./package.json'), __dirname);
} catch (error) {
throw error;
}
export { Keyring } from '@polkadot/keyring';
export { WsProvider } from '@polkadot/rpc-provider';
+48 -9
View File
@@ -4,16 +4,24 @@
import { ApiOptions } from '../types';
import testingPairs from '@polkadot/keyring/testingPairs';
import createPair from '@polkadot/keyring/pair';
import testKeyring from '@polkadot/keyring/testing';
import Mock from '@polkadot/rpc-provider/mock/index';
import { createType, TypeRegistry } from '@polkadot/types';
import { hexToU8a } from '@polkadot/util';
import { SingleAccountSigner } from '../../test/util';
import ApiPromise from './Api';
describe('ApiPromise', (): void => {
const registry = new TypeRegistry();
const keyring = testingPairs({ type: 'ed25519' });
const keyring = testKeyring({ type: 'ed25519' });
const aliceEd = keyring.addPair(
createPair('ed25519', {
secretKey: hexToU8a('0xabf8e5bdbe30c65656c0a3cbd181ff8a56294a69dfedd27982aace4a7690911588dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee'),
publicKey: hexToU8a('0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee')
})
);
let provider: Mock;
beforeEach((): void => {
@@ -52,6 +60,25 @@ describe('ApiPromise', (): void => {
expect(api.tx).toBeDefined();
expect(api.derive).toBeDefined();
});
it('Create API instance will error on failure to await ready', async (): Promise<void> => {
class ErrorApiPromise extends ApiPromise {
constructor () {
super({ provider });
}
protected loadMeta (): Promise<boolean> {
throw new Error('Simulate failure to load meta');
}
}
try {
await new ErrorApiPromise().isReady;
fail('Expected an error but none occurred.');
} catch {
// Pass
}
});
});
describe('api.sign', (): void => {
@@ -63,7 +90,7 @@ describe('ApiPromise', (): void => {
const api = new ApiPromise({ provider, registry });
expect(
await api.sign(keyring.alice_session, TEST)
await api.sign(aliceEd, TEST)
).toEqual(SIG);
});
@@ -71,7 +98,7 @@ describe('ApiPromise', (): void => {
const api = new ApiPromise({
provider,
registry,
signer: new SingleAccountSigner(registry, keyring.alice_session)
signer: new SingleAccountSigner(registry, aliceEd)
});
expect(
@@ -82,14 +109,26 @@ describe('ApiPromise', (): void => {
describe('decorator.signAsync', (): void => {
it('signs a transfer using an external signer', async (): Promise<void> => {
const signer = new SingleAccountSigner(registry, keyring.alice_session);
const api = await ApiPromise.create({ provider, registry, signer });
const transfer = api.tx.balances.transfer(keyring.eve.address, 12345);
provider.subscriptions.state_subscribeStorage.lastValue = {
changes: [
[
'0x26aa394eea5630e07c48ae0c9558cef79c2f82b23e5fd031fb54c292794b4cc4d560eb8d00e57357cf76492334e43bb2ecaa9f28df6a8c4426d7b6090f7ad3c9',
'0x00'
]
]
};
await transfer.signAsync(keyring.alice_session, {});
const signer = new SingleAccountSigner(registry, aliceEd);
const api = await ApiPromise.create({ provider, registry, signer });
const transfer = api.tx.balances.transfer(keyring.getPair('0xe659a7a1628cdd93febc04a4e0646ea20e9f5f0ce097d9a05290d4a9e054df4e').address, 12345);
await transfer.signAsync(aliceEd.address, {});
expect(transfer.signature.toHex()).toEqual(
'0x97f3cfe5088fcd575313e983f45d02b0f630e7b94ff9a3ac50e20cd096a8f554fda73d42ead891b5a1d3ce5607d83f20b0c6570b555e949cfb5763d0abcd590b'
// v1 extrinsic
// '0x6b9ccc95afbd4e916d30c65c720f4f7b70a77db545735b48a763844aa5210e695aa346686bad1224af77d00bcfbf6fc8d2c216a60731027835d5a414186a2607'
// v4 extrinsic
'0x0716cbdc3b649dad8741238bcc8e4336f859c518cf2b17a3427b2f5d0b8a79cf518da71b9ac71d92c517342e0978f297f5e05362babf5987d3f1c5ba3314af08'
);
});
});
+4 -1
View File
@@ -216,10 +216,13 @@ export default class ApiPromise extends ApiBase<'promise'> {
constructor (options?: ApiOptions) {
super(options, 'promise', decorateMethod);
this._isReadyPromise = new Promise((resolve): void => {
this._isReadyPromise = new Promise((resolve, reject): void => {
super.once('ready', (): void => {
resolve(this);
});
super.once('error', (e): void => {
reject(e);
});
});
}
-223
View File
@@ -1,223 +0,0 @@
// Auto-generated via `yarn build:interfaces`, do not edit
/* eslint-disable @typescript-eslint/no-empty-interface */
import { Observable } from 'rxjs';
import { Option, Raw, Vec } from '@polkadot/types/codec';
import { Bytes, Null, bool, u32, u64 } from '@polkadot/types';
import { AccountId, AccountIndex, Balance, BalanceOf, BlockNumber, Hash, Index, KeyTypeId, Moment, Perbill, ValidatorId, Weight } from '@polkadot/types/interfaces/runtime';
import { UncleEntryItem } from '@polkadot/types/interfaces/authorship';
import { BabeAuthorityWeight, MaybeVrf } from '@polkadot/types/interfaces/babe';
import { BalanceLock, VestingSchedule } from '@polkadot/types/interfaces/balances';
import { ProposalIndex, Votes } from '@polkadot/types/interfaces/collective';
import { AuthorityId } from '@polkadot/types/interfaces/consensus';
import { CodeHash, ContractInfo, Gas, PrefabWasmModule, Schedule } from '@polkadot/types/interfaces/contracts';
import { Conviction, PropIndex, Proposal, ReferendumIndex, ReferendumInfo } from '@polkadot/types/interfaces/democracy';
import { Vote, VoteThreshold } from '@polkadot/types/interfaces/elections';
import { AuthorityList, SetId, StoredPendingChange, StoredState } from '@polkadot/types/interfaces/grandpa';
import { AuthIndex } from '@polkadot/types/interfaces/imOnline';
import { Kind, OffenceDetails, OpaqueTimeSlot, ReportIdOf } from '@polkadot/types/interfaces/offences';
import { Keys, SessionIndex } from '@polkadot/types/interfaces/session';
import { EraIndex, EraPoints, Exposure, Forcing, MomentOf, Nominations, RewardDestination, SlashingSpans, SpanIndex, SpanRecord, StakingLedger, UnappliedSlash, ValidatorPrefs } from '@polkadot/types/interfaces/staking';
import { DigestOf, EventIndex, EventRecord } from '@polkadot/types/interfaces/system';
import { TreasuryProposal } from '@polkadot/types/interfaces/treasury';
import { Multiplier } from '@polkadot/types/interfaces/txpayment';
import { ITuple } from '@polkadot/types/types';
declare module './types' {
export interface QueryableStorageExact<ApiType> {
system: {
[index: string]: QueryableStorageEntry<ApiType>;
accountNonce: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Index>> & QueryableStorageEntry<ApiType>;
extrinsicCount: StorageEntryExact<ApiType, () => Observable<Option<u32>>> & QueryableStorageEntry<ApiType>;
allExtrinsicsWeight: StorageEntryExact<ApiType, () => Observable<Option<Weight>>> & QueryableStorageEntry<ApiType>;
allExtrinsicsLen: StorageEntryExact<ApiType, () => Observable<Option<u32>>> & QueryableStorageEntry<ApiType>;
blockHash: StorageEntryExact<ApiType, (arg: BlockNumber | Uint8Array | number | string) => Observable<Hash>> & QueryableStorageEntry<ApiType>;
extrinsicData: StorageEntryExact<ApiType, (arg: u32 | Uint8Array | number | string) => Observable<Bytes>> & QueryableStorageEntry<ApiType>;
number: StorageEntryExact<ApiType, () => Observable<BlockNumber>> & QueryableStorageEntry<ApiType>;
parentHash: StorageEntryExact<ApiType, () => Observable<Hash>> & QueryableStorageEntry<ApiType>;
extrinsicsRoot: StorageEntryExact<ApiType, () => Observable<Hash>> & QueryableStorageEntry<ApiType>;
digest: StorageEntryExact<ApiType, () => Observable<DigestOf>> & QueryableStorageEntry<ApiType>;
events: StorageEntryExact<ApiType, () => Observable<Vec<EventRecord>>> & QueryableStorageEntry<ApiType>;
eventCount: StorageEntryExact<ApiType, () => Observable<EventIndex>> & QueryableStorageEntry<ApiType>;
eventTopics: StorageEntryExact<ApiType, (key1: Null, key2: Hash | Uint8Array | string) => Observable<Vec<ITuple<[BlockNumber, EventIndex]>>>> & QueryableStorageEntry<ApiType>;
};
babe: {
[index: string]: QueryableStorageEntry<ApiType>;
epochIndex: StorageEntryExact<ApiType, () => Observable<u64>> & QueryableStorageEntry<ApiType>;
authorities: StorageEntryExact<ApiType, () => Observable<Vec<ITuple<[AuthorityId, BabeAuthorityWeight]>>>> & QueryableStorageEntry<ApiType>;
genesisSlot: StorageEntryExact<ApiType, () => Observable<u64>> & QueryableStorageEntry<ApiType>;
currentSlot: StorageEntryExact<ApiType, () => Observable<u64>> & QueryableStorageEntry<ApiType>;
randomness: StorageEntryExact<ApiType, () => Observable<Raw>> & QueryableStorageEntry<ApiType>;
nextRandomness: StorageEntryExact<ApiType, () => Observable<Raw>> & QueryableStorageEntry<ApiType>;
segmentIndex: StorageEntryExact<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
underConstruction: StorageEntryExact<ApiType, (arg: u32 | Uint8Array | number | string) => Observable<Vec<Raw>>> & QueryableStorageEntry<ApiType>;
initialized: StorageEntryExact<ApiType, () => Observable<Option<MaybeVrf>>> & QueryableStorageEntry<ApiType>;
};
timestamp: {
[index: string]: QueryableStorageEntry<ApiType>;
now: StorageEntryExact<ApiType, () => Observable<Moment>> & QueryableStorageEntry<ApiType>;
didUpdate: StorageEntryExact<ApiType, () => Observable<bool>> & QueryableStorageEntry<ApiType>;
};
authorship: {
[index: string]: QueryableStorageEntry<ApiType>;
uncles: StorageEntryExact<ApiType, () => Observable<Vec<UncleEntryItem>>> & QueryableStorageEntry<ApiType>;
author: StorageEntryExact<ApiType, () => Observable<Option<AccountId>>> & QueryableStorageEntry<ApiType>;
didSetUncles: StorageEntryExact<ApiType, () => Observable<bool>> & QueryableStorageEntry<ApiType>;
};
indices: {
[index: string]: QueryableStorageEntry<ApiType>;
nextEnumSet: StorageEntryExact<ApiType, () => Observable<AccountIndex>> & QueryableStorageEntry<ApiType>;
enumSet: StorageEntryExact<ApiType, (arg: AccountIndex | Uint8Array | number | string) => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
};
balances: {
[index: string]: QueryableStorageEntry<ApiType>;
totalIssuance: StorageEntryExact<ApiType, () => Observable<Balance>> & QueryableStorageEntry<ApiType>;
vesting: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<VestingSchedule>>> & QueryableStorageEntry<ApiType>;
freeBalance: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Balance>> & QueryableStorageEntry<ApiType>;
reservedBalance: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Balance>> & QueryableStorageEntry<ApiType>;
locks: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Vec<BalanceLock>>> & QueryableStorageEntry<ApiType>;
};
transactionPayment: {
[index: string]: QueryableStorageEntry<ApiType>;
nextFeeMultiplier: StorageEntryExact<ApiType, () => Observable<Multiplier>> & QueryableStorageEntry<ApiType>;
};
staking: {
[index: string]: QueryableStorageEntry<ApiType>;
validatorCount: StorageEntryExact<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
minimumValidatorCount: StorageEntryExact<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
invulnerables: StorageEntryExact<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
bonded: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<AccountId>>> & QueryableStorageEntry<ApiType>;
ledger: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<StakingLedger>>> & QueryableStorageEntry<ApiType>;
payee: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<RewardDestination>> & QueryableStorageEntry<ApiType>;
validators: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<ValidatorPrefs>> & QueryableStorageEntry<ApiType>;
nominators: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<Nominations>>> & QueryableStorageEntry<ApiType>;
stakers: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Exposure>> & QueryableStorageEntry<ApiType>;
currentElected: StorageEntryExact<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
currentEra: StorageEntryExact<ApiType, () => Observable<EraIndex>> & QueryableStorageEntry<ApiType>;
currentEraStart: StorageEntryExact<ApiType, () => Observable<MomentOf>> & QueryableStorageEntry<ApiType>;
currentEraStartSessionIndex: StorageEntryExact<ApiType, () => Observable<SessionIndex>> & QueryableStorageEntry<ApiType>;
currentEraPointsEarned: StorageEntryExact<ApiType, () => Observable<EraPoints>> & QueryableStorageEntry<ApiType>;
slotStake: StorageEntryExact<ApiType, () => Observable<BalanceOf>> & QueryableStorageEntry<ApiType>;
forceEra: StorageEntryExact<ApiType, () => Observable<Forcing>> & QueryableStorageEntry<ApiType>;
slashRewardFraction: StorageEntryExact<ApiType, () => Observable<Perbill>> & QueryableStorageEntry<ApiType>;
canceledSlashPayout: StorageEntryExact<ApiType, () => Observable<BalanceOf>> & QueryableStorageEntry<ApiType>;
unappliedSlashes: StorageEntryExact<ApiType, (arg: EraIndex | Uint8Array | number | string) => Observable<Vec<UnappliedSlash>>> & QueryableStorageEntry<ApiType>;
bondedEras: StorageEntryExact<ApiType, () => Observable<Vec<ITuple<[EraIndex, SessionIndex]>>>> & QueryableStorageEntry<ApiType>;
validatorSlashInEra: StorageEntryExact<ApiType, (key1: EraIndex | Uint8Array | number | string, key2: AccountId | Uint8Array | string) => Observable<Option<ITuple<[Perbill, BalanceOf]>>>> & QueryableStorageEntry<ApiType>;
nominatorSlashInEra: StorageEntryExact<ApiType, (key1: EraIndex | Uint8Array | number | string, key2: AccountId | Uint8Array | string) => Observable<Option<BalanceOf>>> & QueryableStorageEntry<ApiType>;
slashingSpans: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<SlashingSpans>>> & QueryableStorageEntry<ApiType>;
spanSlash: StorageEntryExact<ApiType, (arg: ITuple<[AccountId, SpanIndex]>) => Observable<SpanRecord>> & QueryableStorageEntry<ApiType>;
earliestUnappliedSlash: StorageEntryExact<ApiType, () => Observable<Option<EraIndex>>> & QueryableStorageEntry<ApiType>;
storageVersion: StorageEntryExact<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
};
session: {
[index: string]: QueryableStorageEntry<ApiType>;
validators: StorageEntryExact<ApiType, () => Observable<Vec<ValidatorId>>> & QueryableStorageEntry<ApiType>;
currentIndex: StorageEntryExact<ApiType, () => Observable<SessionIndex>> & QueryableStorageEntry<ApiType>;
queuedChanged: StorageEntryExact<ApiType, () => Observable<bool>> & QueryableStorageEntry<ApiType>;
queuedKeys: StorageEntryExact<ApiType, () => Observable<Vec<ITuple<[ValidatorId, Keys]>>>> & QueryableStorageEntry<ApiType>;
disabledValidators: StorageEntryExact<ApiType, () => Observable<Vec<u32>>> & QueryableStorageEntry<ApiType>;
nextKeys: StorageEntryExact<ApiType, (key1: Bytes | Uint8Array | string, key2: ValidatorId | Uint8Array | string) => Observable<Option<Keys>>> & QueryableStorageEntry<ApiType>;
keyOwner: StorageEntryExact<ApiType, (key1: Bytes | Uint8Array | string, key2: ITuple<[KeyTypeId, Bytes]>) => Observable<Option<ValidatorId>>> & QueryableStorageEntry<ApiType>;
};
democracy: {
[index: string]: QueryableStorageEntry<ApiType>;
publicPropCount: StorageEntryExact<ApiType, () => Observable<PropIndex>> & QueryableStorageEntry<ApiType>;
publicProps: StorageEntryExact<ApiType, () => Observable<Vec<ITuple<[PropIndex, Hash, AccountId]>>>> & QueryableStorageEntry<ApiType>;
preimages: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<Option<ITuple<[Bytes, AccountId, BalanceOf, BlockNumber]>>>> & QueryableStorageEntry<ApiType>;
depositOf: StorageEntryExact<ApiType, (arg: PropIndex | Uint8Array | number | string) => Observable<Option<ITuple<[BalanceOf, Vec<AccountId>]>>>> & QueryableStorageEntry<ApiType>;
referendumCount: StorageEntryExact<ApiType, () => Observable<ReferendumIndex>> & QueryableStorageEntry<ApiType>;
nextTally: StorageEntryExact<ApiType, () => Observable<ReferendumIndex>> & QueryableStorageEntry<ApiType>;
referendumInfoOf: StorageEntryExact<ApiType, (arg: ReferendumIndex | Uint8Array | number | string) => Observable<Option<ReferendumInfo>>> & QueryableStorageEntry<ApiType>;
dispatchQueue: StorageEntryExact<ApiType, (arg: BlockNumber | Uint8Array | number | string) => Observable<Vec<Option<ITuple<[Hash, ReferendumIndex]>>>>> & QueryableStorageEntry<ApiType>;
votersFor: StorageEntryExact<ApiType, (arg: ReferendumIndex | Uint8Array | number | string) => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
voteOf: StorageEntryExact<ApiType, (arg: ITuple<[ReferendumIndex, AccountId]>) => Observable<Vote>> & QueryableStorageEntry<ApiType>;
proxy: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<AccountId>>> & QueryableStorageEntry<ApiType>;
delegations: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<ITuple<[AccountId, Conviction]>>> & QueryableStorageEntry<ApiType>;
lastTabledWasExternal: StorageEntryExact<ApiType, () => Observable<bool>> & QueryableStorageEntry<ApiType>;
nextExternal: StorageEntryExact<ApiType, () => Observable<Option<ITuple<[Hash, VoteThreshold]>>>> & QueryableStorageEntry<ApiType>;
blacklist: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<Option<ITuple<[BlockNumber, Vec<AccountId>]>>>> & QueryableStorageEntry<ApiType>;
cancellations: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<bool>> & QueryableStorageEntry<ApiType>;
};
council: {
[index: string]: QueryableStorageEntry<ApiType>;
proposals: StorageEntryExact<ApiType, () => Observable<Vec<Hash>>> & QueryableStorageEntry<ApiType>;
proposalOf: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<Option<Proposal>>> & QueryableStorageEntry<ApiType>;
voting: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<Option<Votes>>> & QueryableStorageEntry<ApiType>;
proposalCount: StorageEntryExact<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
members: StorageEntryExact<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
};
technicalCommittee: {
[index: string]: QueryableStorageEntry<ApiType>;
proposals: StorageEntryExact<ApiType, () => Observable<Vec<Hash>>> & QueryableStorageEntry<ApiType>;
proposalOf: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<Option<Proposal>>> & QueryableStorageEntry<ApiType>;
voting: StorageEntryExact<ApiType, (arg: Hash | Uint8Array | string) => Observable<Option<Votes>>> & QueryableStorageEntry<ApiType>;
proposalCount: StorageEntryExact<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
members: StorageEntryExact<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
};
elections: {
[index: string]: QueryableStorageEntry<ApiType>;
members: StorageEntryExact<ApiType, () => Observable<Vec<ITuple<[AccountId, BalanceOf]>>>> & QueryableStorageEntry<ApiType>;
runnersUp: StorageEntryExact<ApiType, () => Observable<Vec<ITuple<[AccountId, BalanceOf]>>>> & QueryableStorageEntry<ApiType>;
electionRounds: StorageEntryExact<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
votesOf: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
stakeOf: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<BalanceOf>> & QueryableStorageEntry<ApiType>;
candidates: StorageEntryExact<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
};
technicalMembership: {
[index: string]: QueryableStorageEntry<ApiType>;
members: StorageEntryExact<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
};
grandpa: {
[index: string]: QueryableStorageEntry<ApiType>;
authorities: StorageEntryExact<ApiType, () => Observable<AuthorityList>> & QueryableStorageEntry<ApiType>;
state: StorageEntryExact<ApiType, () => Observable<StoredState>> & QueryableStorageEntry<ApiType>;
pendingChange: StorageEntryExact<ApiType, () => Observable<Option<StoredPendingChange>>> & QueryableStorageEntry<ApiType>;
nextForced: StorageEntryExact<ApiType, () => Observable<Option<BlockNumber>>> & QueryableStorageEntry<ApiType>;
stalled: StorageEntryExact<ApiType, () => Observable<Option<ITuple<[BlockNumber, BlockNumber]>>>> & QueryableStorageEntry<ApiType>;
currentSetId: StorageEntryExact<ApiType, () => Observable<SetId>> & QueryableStorageEntry<ApiType>;
setIdSession: StorageEntryExact<ApiType, (arg: SetId | Uint8Array | number | string) => Observable<Option<SessionIndex>>> & QueryableStorageEntry<ApiType>;
};
treasury: {
[index: string]: QueryableStorageEntry<ApiType>;
proposalCount: StorageEntryExact<ApiType, () => Observable<ProposalIndex>> & QueryableStorageEntry<ApiType>;
proposals: StorageEntryExact<ApiType, (arg: ProposalIndex | Uint8Array | number | string) => Observable<Option<TreasuryProposal>>> & QueryableStorageEntry<ApiType>;
approvals: StorageEntryExact<ApiType, () => Observable<Vec<ProposalIndex>>> & QueryableStorageEntry<ApiType>;
};
contracts: {
[index: string]: QueryableStorageEntry<ApiType>;
gasSpent: StorageEntryExact<ApiType, () => Observable<Gas>> & QueryableStorageEntry<ApiType>;
currentSchedule: StorageEntryExact<ApiType, () => Observable<Schedule>> & QueryableStorageEntry<ApiType>;
pristineCode: StorageEntryExact<ApiType, (arg: CodeHash | Uint8Array | string) => Observable<Option<Bytes>>> & QueryableStorageEntry<ApiType>;
codeStorage: StorageEntryExact<ApiType, (arg: CodeHash | Uint8Array | string) => Observable<Option<PrefabWasmModule>>> & QueryableStorageEntry<ApiType>;
accountCounter: StorageEntryExact<ApiType, () => Observable<u64>> & QueryableStorageEntry<ApiType>;
contractInfoOf: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<ContractInfo>>> & QueryableStorageEntry<ApiType>;
gasPrice: StorageEntryExact<ApiType, () => Observable<BalanceOf>> & QueryableStorageEntry<ApiType>;
};
sudo: {
[index: string]: QueryableStorageEntry<ApiType>;
key: StorageEntryExact<ApiType, () => Observable<AccountId>> & QueryableStorageEntry<ApiType>;
};
imOnline: {
[index: string]: QueryableStorageEntry<ApiType>;
gossipAt: StorageEntryExact<ApiType, () => Observable<BlockNumber>> & QueryableStorageEntry<ApiType>;
keys: StorageEntryExact<ApiType, () => Observable<Vec<AuthorityId>>> & QueryableStorageEntry<ApiType>;
receivedHeartbeats: StorageEntryExact<ApiType, (key1: SessionIndex | Uint8Array | number | string, key2: AuthIndex | Uint8Array | number | string) => Observable<Option<Bytes>>> & QueryableStorageEntry<ApiType>;
authoredBlocks: StorageEntryExact<ApiType, (key1: SessionIndex | Uint8Array | number | string, key2: ValidatorId | Uint8Array | string) => Observable<u32>> & QueryableStorageEntry<ApiType>;
};
offences: {
[index: string]: QueryableStorageEntry<ApiType>;
reports: StorageEntryExact<ApiType, (arg: ReportIdOf | Uint8Array | string) => Observable<Option<OffenceDetails>>> & QueryableStorageEntry<ApiType>;
concurrentReportsIndex: StorageEntryExact<ApiType, (key1: Kind | Uint8Array | string, key2: OpaqueTimeSlot | Uint8Array | string) => Observable<Vec<ReportIdOf>>> & QueryableStorageEntry<ApiType>;
reportsByKindIndex: StorageEntryExact<ApiType, (arg: Kind | Uint8Array | string) => Observable<Bytes>> & QueryableStorageEntry<ApiType>;
};
randomnessCollectiveFlip: {
[index: string]: QueryableStorageEntry<ApiType>;
randomMaterial: StorageEntryExact<ApiType, () => Observable<Vec<Hash>>> & QueryableStorageEntry<ApiType>;
};
nicks: {
[index: string]: QueryableStorageEntry<ApiType>;
nameOf: StorageEntryExact<ApiType, (arg: AccountId | Uint8Array | string) => Observable<Option<ITuple<[Bytes, BalanceOf]>>>> & QueryableStorageEntry<ApiType>;
};
}
}
+45 -44
View File
@@ -3,15 +3,15 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, Address, Call, ExtrinsicEra, ExtrinsicStatus, Hash, Header, Index, RuntimeDispatchInfo } from '@polkadot/types/interfaces';
import { Address, Call, ExtrinsicEra, ExtrinsicStatus, Hash, Header, Index, RuntimeDispatchInfo } from '@polkadot/types/interfaces';
import { Callback, Codec, Constructor, IKeyringPair, Registry, SignatureOptions } from '@polkadot/types/types';
import { ApiInterfaceRx, ApiTypes, SignerResult } from '../types';
import { SignerOptions, SubmittableExtrinsic, SubmittablePaymentResult, SubmittableResultImpl, SubmittableResultResult, SubmittableResultSubscription, SubmittableThis } from './types';
import { AddressOrPair, SignerOptions, SubmittableExtrinsic, SubmittablePaymentResult, SubmittableResultImpl, SubmittableResultResult, SubmittableResultSubscription, SubmittableThis } from './types';
import { Observable, combineLatest, from, of } from 'rxjs';
import { Observable, combineLatest, of } from 'rxjs';
import { first, map, mapTo, mergeMap, switchMap, tap } from 'rxjs/operators';
import { createType, ClassOf } from '@polkadot/types';
import { isBn, isFunction, isNumber, isUndefined } from '@polkadot/util';
import { assert, isBn, isFunction, isNumber, isUndefined } from '@polkadot/util';
import { filterEvents, isKeyringPair } from '../util';
import ApiBase from '../base';
@@ -50,7 +50,7 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
}
// calculate the payment info for this transaction (if signed and submitted)
public paymentInfo (account: IKeyringPair | string | AccountId | Address, options?: Partial<SignerOptions>): SubmittablePaymentResult<ApiType> {
public paymentInfo (account: AddressOrPair, options?: Partial<SignerOptions>): SubmittablePaymentResult<ApiType> {
const [allOptions] = this._makeSignAndSendOptions(options);
const address = isKeyringPair(account) ? account.address : account.toString();
@@ -82,54 +82,35 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
// signs a transaction, returning `this` to allow chaining. E.g.: `sign(...).send()`
//
// also supports signing through external signers
public signAsync (account: IKeyringPair, optionsOrNonce: Partial<SignerOptions>): SubmittableThis<ApiType, this> {
public signAsync (account: AddressOrPair, optionsOrNonce: Partial<SignerOptions>): SubmittableThis<ApiType, this> {
return this._decorateMethod(
(): Observable<this> => {
const optionsWithNonce = this._optionsOrNonce(optionsOrNonce);
return from(
this._api.signer
? this._signViaSigner(account.address, this._makeSignOptions(optionsWithNonce, {}), null)
: Promise.resolve(this.sign(account, optionsWithNonce))
).pipe(mapTo(this));
}
(): Observable<this> =>
this._signObservable(account, optionsOrNonce).pipe(mapTo(this))
)();
}
// signAndSend with an immediate Hash result
public signAndSend (account: IKeyringPair | string | AccountId | Address, options?: Partial<SignerOptions>): SubmittableResultResult<ApiType>;
public signAndSend (account: AddressOrPair, options?: Partial<SignerOptions>): SubmittableResultResult<ApiType>;
// signAndSend with a subscription, i.e. callback provided
public signAndSend (account: IKeyringPair | string | AccountId | Address, statusCb: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
public signAndSend (account: AddressOrPair, statusCb: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
// signAndSend with options and a callback
public signAndSend (account: IKeyringPair | string | AccountId | Address, options: Partial<SignerOptions>, statusCb?: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
public signAndSend (account: AddressOrPair, options: Partial<SignerOptions>, statusCb?: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
// signAndSend implementation for all 3 cases above
public signAndSend (account: IKeyringPair | string | AccountId | Address, optionsOrStatus?: Partial<SignerOptions> | Callback<SubmittableResultImpl>, optionalStatusCb?: Callback<SubmittableResultImpl>): SubmittableResultResult<ApiType> | SubmittableResultSubscription<ApiType> {
public signAndSend (account: AddressOrPair, optionsOrStatus?: Partial<SignerOptions> | Callback<SubmittableResultImpl>, optionalStatusCb?: Callback<SubmittableResultImpl>): SubmittableResultResult<ApiType> | SubmittableResultSubscription<ApiType> {
const [options, statusCb] = this._makeSignAndSendOptions(optionsOrStatus, optionalStatusCb);
const isSubscription = this._api.hasSubscriptions && (this._ignoreStatusCb || !!statusCb);
const address = isKeyringPair(account) ? account.address : account.toString();
let updateId: number | undefined;
return this._decorateMethod(
(): Observable<Codec> => (
this._getPrelimState(address, options).pipe(
first(),
mergeMap(async ([nonce, header]): Promise<void> => {
const eraOptions = this._makeEraOptions(options, { header, nonce });
if (isKeyringPair(account)) {
this.sign(account, eraOptions);
} else {
updateId = await this._signViaSigner(address, eraOptions, header);
}
}),
switchMap((): Observable<SubmittableResultImpl> | Observable<Hash> => {
return isSubscription
this._signObservable(account, options).pipe(
switchMap((updateId: number | undefined): Observable<SubmittableResultImpl> | Observable<Hash> =>
isSubscription
? this._subscribeObservable(updateId)
: this._sendObservable(updateId);
})
: this._sendObservable(updateId)
)
) as Observable<Codec>) // FIXME This is wrong, SubmittableResult is _not_ a codec
)(statusCb);
}
@@ -163,10 +144,30 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
return [options, statusCb];
}
private async _signViaSigner (address: string, options: SignatureOptions, header: Header | null): Promise<number> {
if (!this._api.signer) {
throw new Error('no signer attached');
}
private _signObservable (account: AddressOrPair, optionsOrNonce: Partial<SignerOptions>): Observable<number | undefined> {
const address = isKeyringPair(account) ? account.address : account.toString();
const options = this._optionsOrNonce(optionsOrNonce);
let updateId: number | undefined;
return this._getPrelimState(address, options).pipe(
first(),
mergeMap(async ([nonce, header]): Promise<void> => {
const eraOptions = this._makeEraOptions(options, { header, nonce });
if (isKeyringPair(account)) {
this.sign(account, eraOptions);
} else {
updateId = await this._signViaSigner(address, eraOptions, header);
}
}),
mapTo(updateId)
);
}
private async _signViaSigner (address: Address | string | Uint8Array, options: SignatureOptions, header: Header | null): Promise<number> {
const signer = options.signer || this._api.signer;
assert(signer, 'No signer specified, either via api.setSigner or via sign options');
const payload = createType(this.registry, 'SignerPayload', {
...options,
@@ -176,10 +177,10 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
});
let result: SignerResult;
if (this._api.signer.signPayload) {
result = await this._api.signer.signPayload(payload.toPayload());
} else if (this._api.signer.signRaw) {
result = await this._api.signer.signRaw(payload.toRaw());
if (signer.signPayload) {
result = await signer.signPayload(payload.toPayload());
} else if (signer.signRaw) {
result = await signer.signRaw(payload.toRaw());
} else {
throw new Error('Invalid signer interface, it should implement either signPayload or signRaw (or both)');
}
+9 -6
View File
@@ -4,7 +4,7 @@
import { AccountId, Address, ExtrinsicStatus, EventRecord, Hash, RuntimeDispatchInfo } from '@polkadot/types/interfaces';
import { AnyNumber, AnyU8a, Callback, IExtrinsic, IExtrinsicEra, IKeyringPair, SignatureOptions } from '@polkadot/types/types';
import { ApiTypes } from '../types';
import { ApiTypes, Signer } from '../types';
import { Observable } from 'rxjs';
@@ -48,11 +48,14 @@ export interface SignerOptions {
blockHash: AnyU8a;
era?: IExtrinsicEra | number;
nonce: AnyNumber;
signer?: Signer;
tip?: AnyNumber;
}
export type AddressOrPair = IKeyringPair | string | AccountId | Address;
export interface SubmittableExtrinsic<ApiType extends ApiTypes> extends IExtrinsic {
paymentInfo (account: IKeyringPair | string | AccountId | Address, options?: Partial<SignerOptions>): SubmittablePaymentResult<ApiType>;
paymentInfo (account: AddressOrPair, options?: Partial<SignerOptions>): SubmittablePaymentResult<ApiType>;
send(): SubmittableResultResult<ApiType>;
@@ -60,11 +63,11 @@ export interface SubmittableExtrinsic<ApiType extends ApiTypes> extends IExtrins
sign(account: IKeyringPair, _options: Partial<SignatureOptions>): this;
signAsync(account: IKeyringPair, _options: Partial<SignatureOptions>): SubmittableThis<ApiType, this>;
signAsync(account: AddressOrPair, _options: Partial<SignatureOptions>): SubmittableThis<ApiType, this>;
signAndSend(account: IKeyringPair | string | AccountId | Address, options?: Partial<SignerOptions>): SubmittableResultResult<ApiType>;
signAndSend(account: AddressOrPair, options?: Partial<SignerOptions>): SubmittableResultResult<ApiType>;
signAndSend(account: IKeyringPair | string | AccountId | Address, statusCb: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
signAndSend(account: AddressOrPair, statusCb: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
signAndSend(account: IKeyringPair | string | AccountId | Address, options: Partial<SignerOptions>, statusCb?: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
signAndSend(account: AddressOrPair, options: Partial<SignerOptions>, statusCb?: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
}
-283
View File
@@ -1,283 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
// These two files add module augmentation so that `api.{query,consts}.*.*`
// get typed. Import them to make these types effective.
import './consts.types';
import './query.types';
import { Constants } from '@polkadot/metadata/Decorated/types';
import { UserRpc } from '@polkadot/rpc-core/types';
import { Hash, RuntimeVersion } from '@polkadot/types/interfaces';
import { AnyFunction, Callback, CallFunction, Codec, CodecArg, RegistryTypes, SignatureOptions, SignerPayloadJSON, SignerPayloadRaw, Registry } from '@polkadot/types/types';
import { SubmittableResultImpl, SubmittableExtrinsic } from './submittable/types';
import { DeriveAllSections } from './util/decorate';
import BN from 'bn.js';
import { Observable } from 'rxjs';
import { DeriveCustom, ExactDerive } from '@polkadot/api-derive';
import { RpcInterface } from '@polkadot/rpc-core/jsonrpc.types';
import { ProviderInterface, ProviderInterfaceEmitted } from '@polkadot/rpc-provider/types';
import { Metadata, u64 } from '@polkadot/types';
import StorageKey, { StorageEntry } from '@polkadot/types/primitive/StorageKey';
import ApiBase from './base';
export * from './submittable/types';
// Prepend an element V onto the beginning of a tuple T.
// Cons<1, [2,3,4]> is [1,2,3,4]
type Cons<V, T extends any[]> = ((v: V, ...t: T) => void) extends ((...r: infer R) => void)
? R
: never;
// Append an element V onto the end of a tuple T
// Push<[1,2,3],4> is [1,2,3,4]
// note that this DOES NOT PRESERVE optionality/readonly in tuples.
// So unfortunately Push<[1, 2?, 3?], 4> is [1,2|undefined,3|undefined,4]
type Push<T extends any[], V> = (
(
Cons<any, Required<T>> extends infer R
? { [K in keyof R]: K extends keyof T ? T[K] : V }
: never
) extends infer P
? P extends any[] ? P : never
: never
);
// Returns the inner type of an Observable
export type ObsInnerType<O extends Observable<any>> = O extends Observable<infer U> ? U : never;
export type UnsubscribePromise = Promise<() => void>;
// In the abstract `decorateMethod` in Base.ts, we can also pass in some meta-
// information. This describes it.
export interface DecorateMethodOptions {
methodName?: string;
}
export type DecorateMethod<ApiType extends ApiTypes> = <Method extends (...args: any[]) => Observable<any>>(method: Method, options?: DecorateMethodOptions) => any;
// Here are the return types of these parts of the api:
// - api.query.*.*: no exact typings
// - api.tx.*.*: SubmittableExtrinsic<ApiType extends ApiTypes>
// - api.derive.*.*: MethodResult<ApiType, F>
// - api.rpc.*.*: no exact typings (for now, FIXME: should be MethodResult<ApiType, F>, like in derive)
// These are the types that don't lose type information (used for api.derive.*)
// Also use these for api.rpc.* https://github.com/polkadot-js/api/issues/1009
export interface RxResult<F extends AnyFunction> {
(...args: Parameters<F>): Observable<ObsInnerType<ReturnType<F>>>;
<T>(...args: Parameters<F>): Observable<T>;
}
export interface PromiseResult<F extends AnyFunction> {
(...args: Parameters<F>): Promise<ObsInnerType<ReturnType<F>>>;
(...args: Push<Parameters<F>, Callback<ObsInnerType<ReturnType<F>>>>): UnsubscribePromise;
<T extends Codec | Codec[]>(...args: Parameters<F>): Promise<T>;
<T extends Codec | Codec[]>(...args: Push<Parameters<F>, Callback<T>>): UnsubscribePromise;
}
// FIXME The day TS has higher-kinded types, we can remove this hardcoded stuff
export type PromiseOrObs<ApiType extends ApiTypes, T> = ApiType extends 'rxjs'
? Observable<T>
: Promise<T>
// FIXME The day TS has higher-kinded types, we can remove this hardcoded stuff
export type MethodResult<ApiType extends ApiTypes, F extends AnyFunction> = ApiType extends 'rxjs'
? RxResult<F>
: PromiseResult<F>;
export type DecoratedRpcSection<ApiType extends ApiTypes, Section> = {
[Method in keyof Section]: Section[Method] extends AnyFunction
? MethodResult<ApiType, Section[Method]>
: never
}
export type DecoratedRpc<ApiType extends ApiTypes, AllSections> = {
[Section in keyof AllSections]: DecoratedRpcSection<ApiType, AllSections[Section]>
}
interface StorageEntryObservableMulti {
<T extends Codec>(args: (CodecArg[] | CodecArg)[]): Observable<T[]>;
}
interface StorageEntryPromiseMulti {
<T extends Codec>(args: (CodecArg[] | CodecArg)[]): Promise<T[]>;
<T extends Codec>(args: (CodecArg[] | CodecArg)[], callback: Callback<T[]>): UnsubscribePromise;
}
export interface StorageEntryBase<ApiType extends ApiTypes, F extends AnyFunction> {
at: (hash: Hash | Uint8Array | string, ...args: Parameters<F>) => PromiseOrObs<ApiType, ObsInnerType<ReturnType<F>>>;
creator: StorageEntry;
entries: () => PromiseOrObs<ApiType, [StorageKey, ObsInnerType<ReturnType<F>>][]>;
hash: (...args: Parameters<F>) => PromiseOrObs<ApiType, Hash>;
key: (...args: Parameters<F>) => string;
size: (...args: Parameters<F>) => PromiseOrObs<ApiType, u64>;
multi: ApiType extends 'rxjs' ? StorageEntryObservableMulti : StorageEntryPromiseMulti;
}
export interface StorageEntryPromiseOverloads {
(arg1?: CodecArg, arg2?: CodecArg): Promise<Codec>;
<T extends Codec>(arg1?: CodecArg, arg2?: CodecArg): Promise<T>;
<T extends Codec>(callback: Callback<T>): UnsubscribePromise;
<T extends Codec>(arg: CodecArg, callback: Callback<T>): UnsubscribePromise;
<T extends Codec>(arg1: CodecArg, arg2: CodecArg, callback: Callback<T>): UnsubscribePromise;
}
export type StorageEntryExact<ApiType extends ApiTypes, F extends AnyFunction> = MethodResult<ApiType, F> & StorageEntryBase<ApiType, F>
// This is the most generic typings we can have for a storage entry function
type GenericStorageEntryFunction = (arg1?: CodecArg, arg2?: CodecArg) => Observable<Codec>
export type QueryableStorageEntry<ApiType extends ApiTypes> =
ApiType extends 'rxjs'
? StorageEntryExact<'rxjs', GenericStorageEntryFunction>
: StorageEntryExact<'promise', GenericStorageEntryFunction> & StorageEntryPromiseOverloads;
export interface QueryableModuleStorage<ApiType extends ApiTypes> {
[index: string]: QueryableStorageEntry<ApiType>;
}
export type QueryableStorageMultiArg<ApiType extends ApiTypes> =
QueryableStorageEntry<ApiType> |
[QueryableStorageEntry<ApiType>, ...CodecArg[]];
export interface QueryableStorageMultiBase<ApiType extends ApiTypes> {
<T extends Codec[]>(calls: QueryableStorageMultiArg<ApiType>[]): Observable<T>;
}
export interface QueryableStorageMultiPromise<ApiType extends ApiTypes> {
<T extends Codec[]>(calls: QueryableStorageMultiArg<ApiType>[], callback: Callback<T>): UnsubscribePromise;
}
export type QueryableStorageMulti<ApiType extends ApiTypes> =
ApiType extends 'rxjs'
? QueryableStorageMultiBase<ApiType>
: QueryableStorageMultiPromise<ApiType>;
// QueryableStorageExact will hold the exact typed api.query.*.* generated from
// metadata. For now it's empty, it's ready to be module augmented.
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface QueryableStorageExact<ApiType extends ApiTypes> { }
export interface QueryableStorage<ApiType extends ApiTypes> extends QueryableStorageExact<ApiType> {
[index: string]: QueryableModuleStorage<ApiType>;
}
export interface SubmittableExtrinsicFunction<ApiType extends ApiTypes> extends CallFunction {
(...params: CodecArg[]): SubmittableExtrinsic<ApiType>;
}
export interface SubmittableModuleExtrinsics<ApiType extends ApiTypes> {
[index: string]: SubmittableExtrinsicFunction<ApiType>;
}
export interface SubmittableExtrinsics<ApiType extends ApiTypes> {
(extrinsic: Uint8Array | string): SubmittableExtrinsic<ApiType>;
[index: string]: SubmittableModuleExtrinsics<ApiType>;
}
export interface ApiOptions {
/**
* @description Add custom derives to be injected
*/
derives?: DeriveCustom;
/**
* @description prebundles is a map of 'genesis hash and runtime spec version' as key to metadata's hex string
* if genesis hash and runtime spec version matches, then use metadata, else fetch it from chain
*/
metadata?: Record<string, string>;
/**
* @description Transport Provider from rpc-provider. If not specified, it will default to
* connecting to a WsProvider connecting localhost with the default port, i.e. `ws://127.0.0.1:9944`
*/
provider?: ProviderInterface;
/**
* @description A type registry to use along with this instance
*/
registry?: Registry;
/**
* @description User-defined RPC methods
*/
rpc?: UserRpc;
/**
* @description An external signer which will be used to sign extrinsic when account passed in is not KeyringPair
*/
signer?: Signer;
/**
* @description The source object to use for runtime information (only used when cloning)
*/
source?: ApiBase<any>;
/**
* @description Additional types used by runtime modules. This is nessusary if the runtime modules
* uses types not available in the base Substrate runtime.
*/
types?: RegistryTypes;
/**
* @description Additional types that are injected based on the chain we are connecting to. There are keyed by the chain, i.e. `{ 'Kusama CC1': { ... } }`
*/
typesChain?: Record<string, RegistryTypes>;
/**
* @description Additional types that are injected based on the type of node we are connecting to, as set via specName in the runtime version. There are keyed by the node, i.e. `{ 'edgeware': { ... } }`
*/
typesSpec?: Record<string, RegistryTypes>;
}
// A smaller interface of ApiRx, used in derive and in SubmittableExtrinsic
export interface ApiInterfaceRx {
consts: Constants;
// TODO This needs to be typed correctly
derive: DeriveAllSections<'rxjs', ExactDerive>;
extrinsicType: number;
genesisHash: Hash;
hasSubscriptions: boolean;
registry: Registry;
runtimeMetadata: Metadata;
runtimeVersion: RuntimeVersion;
query: QueryableStorage<'rxjs'>;
queryMulti: QueryableStorageMulti<'rxjs'>;
rpc: DecoratedRpc<'rxjs', RpcInterface>;
tx: SubmittableExtrinsics<'rxjs'>;
signer?: Signer;
}
export type ApiInterfaceEvents = ProviderInterfaceEmitted | 'ready';
export type ApiTypes = 'promise' | 'rxjs';
export interface SignerOptions extends SignatureOptions {
blockNumber: BN;
genesisHash: Hash;
}
export interface SignerResult {
/**
* @description The id for this request
*/
id: number;
/**
* @description The resulting signature in hex
*/
signature: string;
}
export interface Signer {
/**
* @description signs an extrinsic payload from a serialized form
*/
signPayload?: (payload: SignerPayloadJSON) => Promise<SignerResult>;
/**
* @description signs a raw payload, only the bytes data as supplied
*/
signRaw?: (raw: SignerPayloadRaw) => Promise<SignerResult>;
/**
* @description Receives an update for the extrinsic signed by a `signer.sign`
*/
update?: (id: number, status: Hash | SubmittableResultImpl) => void;
}
export { ApiBase };
+276
View File
@@ -0,0 +1,276 @@
// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
/* eslint-disable @typescript-eslint/no-empty-interface */
import { Codec } from '@polkadot/types/types';
import { Bytes, u32, u64 } from '@polkadot/types/primitive';
import { Balance, BalanceOf, BlockNumber, Moment, Percent, Permill } from '@polkadot/types/interfaces/runtime';
import { Gas } from '@polkadot/types/interfaces/contracts';
import { SessionIndex } from '@polkadot/types/interfaces/session';
import { EraIndex } from '@polkadot/types/interfaces/staking';
declare module '@polkadot/metadata/Decorated/consts/types' {
export interface Constants {
babe: {
[index: string]: Codec;
/**
* The number of **slots** that an epoch takes. We couple sessions to
* epochs, i.e. we start a new session once the new epoch begins.
**/
epochDuration: AugmentedConst<u64>;
/**
* The expected average block time at which BABE should be creating
* blocks. Since BABE is probabilistic it is not trivial to figure out
* what the expected average block time should be based on the slot
* duration and the security parameter `c` (where `1 - c` represents
* the probability of a slot being empty).
**/
expectedBlockTime: AugmentedConst<Moment>;
};
timestamp: {
[index: string]: Codec;
/**
* The minimum period between blocks. Beware that this is different to the *expected* period
* that the block production apparatus provides. Your chosen consensus system will generally
* work with this to determine a sensible block time. e.g. For Aura, it will be double this
* period on default settings.
**/
minimumPeriod: AugmentedConst<Moment>;
};
balances: {
[index: string]: Codec;
/**
* The minimum amount required to keep an account open.
**/
existentialDeposit: AugmentedConst<Balance>;
/**
* The fee required to create an account.
**/
creationFee: AugmentedConst<Balance>;
};
transactionPayment: {
[index: string]: Codec;
/**
* The fee to be paid for making a transaction; the base.
**/
transactionBaseFee: AugmentedConst<BalanceOf>;
/**
* The fee to be paid for making a transaction; the per-byte portion.
**/
transactionByteFee: AugmentedConst<BalanceOf>;
};
staking: {
[index: string]: Codec;
/**
* Number of sessions per era.
**/
sessionsPerEra: AugmentedConst<SessionIndex>;
/**
* Number of eras that staked funds must remain bonded for.
**/
bondingDuration: AugmentedConst<EraIndex>;
};
session: {
[index: string]: Codec;
/**
* Used as first key for `NextKeys` and `KeyOwner` to put all the data into the same branch
* of the trie.
**/
dedupKeyPrefix: AugmentedConst<Bytes>;
};
democracy: {
[index: string]: Codec;
/**
* The minimum period of locking and the period between a proposal being approved and enacted.
* It should generally be a little more than the unstake period to ensure that
* voting stakers have an opportunity to remove themselves from the system in the case where
* they are on the losing side of a vote.
**/
enactmentPeriod: AugmentedConst<BlockNumber>;
/**
* How often (in blocks) new public referenda are launched.
**/
launchPeriod: AugmentedConst<BlockNumber>;
/**
* How often (in blocks) to check for new votes.
**/
votingPeriod: AugmentedConst<BlockNumber>;
/**
* The minimum amount to be used as a deposit for a public referendum proposal.
**/
minimumDeposit: AugmentedConst<BalanceOf>;
/**
* Minimum voting period allowed for an emergency referendum.
**/
emergencyVotingPeriod: AugmentedConst<BlockNumber>;
/**
* Period in blocks where an external proposal may not be re-submitted after being vetoed.
**/
cooloffPeriod: AugmentedConst<BlockNumber>;
/**
* The amount of balance that must be deposited per byte of preimage stored.
**/
preimageByteDeposit: AugmentedConst<BalanceOf>;
};
elections: {
[index: string]: Codec;
candidacyBond: AugmentedConst<BalanceOf>;
votingBond: AugmentedConst<BalanceOf>;
desiredMembers: AugmentedConst<u32>;
desiredRunnersUp: AugmentedConst<u32>;
termDuration: AugmentedConst<BlockNumber>;
};
finalityTracker: {
[index: string]: Codec;
/**
* The number of recent samples to keep from this chain. Default is 101.
**/
windowSize: AugmentedConst<BlockNumber>;
/**
* The delay after which point things become suspicious. Default is 1000.
**/
reportLatency: AugmentedConst<BlockNumber>;
};
treasury: {
[index: string]: Codec;
/**
* Fraction of a proposal's value that should be bonded in order to place the proposal.
* An accepted proposal gets these back. A rejected proposal does not.
**/
proposalBond: AugmentedConst<Permill>;
/**
* Minimum amount of funds that should be placed in a deposit for making a proposal.
**/
proposalBondMinimum: AugmentedConst<BalanceOf>;
/**
* Period between successive spends.
**/
spendPeriod: AugmentedConst<BlockNumber>;
/**
* Percentage of spare funds (if any) that are burnt per spend period.
**/
burn: AugmentedConst<Permill>;
/**
* The period for which a tip remains open after is has achieved threshold tippers.
**/
tipCountdown: AugmentedConst<BlockNumber>;
/**
* The amount of the final tip which goes to the original reporter of the tip.
**/
tipFindersFee: AugmentedConst<Percent>;
/**
* The amount held on deposit for placing a tip report.
**/
tipReportDepositBase: AugmentedConst<BalanceOf>;
/**
* The amount held on deposit per byte within the tip report reason.
**/
tipReportDepositPerByte: AugmentedConst<BalanceOf>;
};
contracts: {
[index: string]: Codec;
/**
* Number of block delay an extrinsic claim surcharge has.
* When claim surcharge is called by an extrinsic the rent is checked
* for current_block - delay
**/
signedClaimHandicap: AugmentedConst<BlockNumber>;
/**
* The minimum amount required to generate a tombstone.
**/
tombstoneDeposit: AugmentedConst<BalanceOf>;
/**
* Size of a contract at the time of instantiaion. This is a simple way to ensure that
* empty contracts eventually gets deleted.
**/
storageSizeOffset: AugmentedConst<u32>;
/**
* Price of a byte of storage per one block interval. Should be greater than 0.
**/
rentByteFee: AugmentedConst<BalanceOf>;
/**
* The amount of funds a contract should deposit in order to offset
* the cost of one byte.
* Let's suppose the deposit is 1,000 BU (balance units)/byte and the rent is 1 BU/byte/day,
* then a contract with 1,000,000 BU that uses 1,000 bytes of storage would pay no rent.
* But if the balance reduced to 500,000 BU and the storage stayed the same at 1,000,
* then it would pay 500 BU/day.
**/
rentDepositOffset: AugmentedConst<BalanceOf>;
/**
* Reward that is received by the party whose touch has led
* to removal of a contract.
**/
surchargeReward: AugmentedConst<BalanceOf>;
/**
* The fee required to create an account.
**/
creationFee: AugmentedConst<BalanceOf>;
/**
* The fee to be paid for making a transaction; the base.
**/
transactionBaseFee: AugmentedConst<BalanceOf>;
/**
* The fee to be paid for making a transaction; the per-byte portion.
**/
transactionByteFee: AugmentedConst<BalanceOf>;
/**
* The fee required to instantiate a contract instance. A reasonable default value
* is 21.
**/
contractFee: AugmentedConst<BalanceOf>;
/**
* The base fee charged for calling into a contract. A reasonable default
* value is 135.
**/
callBaseFee: AugmentedConst<Gas>;
/**
* The base fee charged for instantiating a contract. A reasonable default value
* is 175.
**/
instantiateBaseFee: AugmentedConst<Gas>;
/**
* The maximum nesting level of a call/instantiate stack. A reasonable default
* value is 100.
**/
maxDepth: AugmentedConst<u32>;
/**
* The maximum size of a storage value in bytes. A reasonable default is 16 KiB.
**/
maxValueSize: AugmentedConst<u32>;
/**
* The maximum amount of gas that could be expended per block. A reasonable
* default value is 10_000_000.
**/
blockGasLimit: AugmentedConst<Gas>;
};
society: {
[index: string]: Codec;
/**
* The minimum amount of a deposit required for a bid to be made.
**/
candidateDeposit: AugmentedConst<BalanceOf>;
/**
* The amount of the unpaid reward that gets deducted in the case that either a skeptic
* doesn't vote or someone votes in the wrong way.
**/
wrongSideDeduction: AugmentedConst<BalanceOf>;
/**
* The number of times a member may vote the wrong way (or not at all, when they are a skeptic)
* before they become suspended.
**/
maxStrikes: AugmentedConst<u32>;
/**
* The amount of incentive paid within each period. Doesn't include VoterTip.
**/
periodSpend: AugmentedConst<BalanceOf>;
/**
* The number of blocks between candidate/membership rotation periods.
**/
rotationPeriod: AugmentedConst<BlockNumber>;
/**
* The number of blocks between membership challenges.
**/
challengePeriod: AugmentedConst<BlockNumber>;
};
}
}
+8
View File
@@ -0,0 +1,8 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import './consts';
import './query';
import './rpc';
import './tx';
+804
View File
@@ -0,0 +1,804 @@
// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
/* eslint-disable @typescript-eslint/no-empty-interface */
import { AnyNumber, ITuple } from '@polkadot/types/types';
import { Option, Raw, Vec } from '@polkadot/types/codec';
import { Bytes, Data, bool, u32, u64 } from '@polkadot/types/primitive';
import { AccountId, AccountIndex, Balance, BalanceOf, BlockNumber, Hash, Index, KeyTypeId, Moment, Perbill, ValidatorId, Weight } from '@polkadot/types/interfaces/runtime';
import { UncleEntryItem } from '@polkadot/types/interfaces/authorship';
import { BabeAuthorityWeight, MaybeVrf } from '@polkadot/types/interfaces/babe';
import { AccountData, BalanceLock } from '@polkadot/types/interfaces/balances';
import { ProposalIndex, Votes } from '@polkadot/types/interfaces/collective';
import { AuthorityId } from '@polkadot/types/interfaces/consensus';
import { CodeHash, ContractInfo, Gas, PrefabWasmModule, Schedule } from '@polkadot/types/interfaces/contracts';
import { Conviction, PropIndex, Proposal, ReferendumIndex, ReferendumInfo } from '@polkadot/types/interfaces/democracy';
import { Vote, VoteThreshold } from '@polkadot/types/interfaces/elections';
import { AuthorityList, SetId, StoredPendingChange, StoredState } from '@polkadot/types/interfaces/grandpa';
import { RegistrarInfo, Registration } from '@polkadot/types/interfaces/identity';
import { AuthIndex } from '@polkadot/types/interfaces/imOnline';
import { Kind, OffenceDetails, OpaqueTimeSlot, ReportIdOf } from '@polkadot/types/interfaces/offences';
import { ActiveRecovery, RecoveryConfig } from '@polkadot/types/interfaces/recovery';
import { Keys, SessionIndex } from '@polkadot/types/interfaces/session';
import { Bid, BidKind, SocietyVote, StrikeCount, VouchingStatus } from '@polkadot/types/interfaces/society';
import { EraIndex, EraPoints, Exposure, Forcing, MomentOf, Nominations, RewardDestination, SlashingSpans, SpanIndex, SpanRecord, StakingLedger, UnappliedSlash, ValidatorPrefs } from '@polkadot/types/interfaces/staking';
import { DigestOf, EventIndex, EventRecord } from '@polkadot/types/interfaces/system';
import { OpenTip, TreasuryProposal } from '@polkadot/types/interfaces/treasury';
import { Multiplier } from '@polkadot/types/interfaces/txpayment';
import { Multisig } from '@polkadot/types/interfaces/utility';
import { VestingInfo } from '@polkadot/types/interfaces/vesting';
import { Observable } from 'rxjs';
declare module '@polkadot/api/types/storage' {
export interface AugmentedQueries<ApiType> {
system: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* Extrinsics nonce for accounts.
**/
accountNonce: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Index>> & QueryableStorageEntry<ApiType>;
/**
* Total extrinsics count for the current block.
**/
extrinsicCount: AugmentedQuery<ApiType, () => Observable<Option<u32>>> & QueryableStorageEntry<ApiType>;
/**
* Total weight for all extrinsics put together, for the current block.
**/
allExtrinsicsWeight: AugmentedQuery<ApiType, () => Observable<Option<Weight>>> & QueryableStorageEntry<ApiType>;
/**
* Total length (in bytes) for all extrinsics put together, for the current block.
**/
allExtrinsicsLen: AugmentedQuery<ApiType, () => Observable<Option<u32>>> & QueryableStorageEntry<ApiType>;
/**
* Map of block numbers to block hashes.
**/
blockHash: AugmentedQuery<ApiType, (arg: BlockNumber | AnyNumber | Uint8Array) => Observable<Hash>> & QueryableStorageEntry<ApiType>;
/**
* Extrinsics data for the current block (maps an extrinsic's index to its data).
**/
extrinsicData: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Bytes>> & QueryableStorageEntry<ApiType>;
/**
* The current block number being processed. Set by `execute_block`.
**/
number: AugmentedQuery<ApiType, () => Observable<BlockNumber>> & QueryableStorageEntry<ApiType>;
/**
* Hash of the previous block.
**/
parentHash: AugmentedQuery<ApiType, () => Observable<Hash>> & QueryableStorageEntry<ApiType>;
/**
* Extrinsics root of the current block, also part of the block header.
**/
extrinsicsRoot: AugmentedQuery<ApiType, () => Observable<Hash>> & QueryableStorageEntry<ApiType>;
/**
* Digest of the current block, also part of the block header.
**/
digest: AugmentedQuery<ApiType, () => Observable<DigestOf>> & QueryableStorageEntry<ApiType>;
/**
* Events deposited for the current block.
**/
events: AugmentedQuery<ApiType, () => Observable<Vec<EventRecord>>> & QueryableStorageEntry<ApiType>;
/**
* The number of events in the `Events<T>` list.
**/
eventCount: AugmentedQuery<ApiType, () => Observable<EventIndex>> & QueryableStorageEntry<ApiType>;
/**
* Mapping between a topic (represented by T::Hash) and a vector of indexes
* of events in the `<Events<T>>` list.
* All topic vectors have deterministic storage locations depending on the topic. This
* allows light-clients to leverage the changes trie storage tracking mechanism and
* in case of changes fetch the list of events of interest.
* The value has the type `(T::BlockNumber, EventIndex)` because if we used only just
* the `EventIndex` then in case if the topic has the same contents on the next block
* no notification will be triggered thus the event might be lost.
**/
eventTopics: AugmentedQuery<ApiType, (arg: Hash | string | Uint8Array) => Observable<Vec<ITuple<[BlockNumber, EventIndex]>>>> & QueryableStorageEntry<ApiType>;
};
utility: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* The set of open multisig operations.
**/
multisigs: AugmentedQuery<ApiType, (key1: AccountId | string | Uint8Array, key2: Raw | string | Uint8Array) => Observable<Option<Multisig>>> & QueryableStorageEntry<ApiType>;
};
babe: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* Current epoch index.
**/
epochIndex: AugmentedQuery<ApiType, () => Observable<u64>> & QueryableStorageEntry<ApiType>;
/**
* Current epoch authorities.
**/
authorities: AugmentedQuery<ApiType, () => Observable<Vec<ITuple<[AuthorityId, BabeAuthorityWeight]>>>> & QueryableStorageEntry<ApiType>;
/**
* The slot at which the first epoch actually started. This is 0
* until the first block of the chain.
**/
genesisSlot: AugmentedQuery<ApiType, () => Observable<u64>> & QueryableStorageEntry<ApiType>;
/**
* Current slot number.
**/
currentSlot: AugmentedQuery<ApiType, () => Observable<u64>> & QueryableStorageEntry<ApiType>;
/**
* The epoch randomness for the *current* epoch.
* # Security
* This MUST NOT be used for gambling, as it can be influenced by a
* malicious validator in the short term. It MAY be used in many
* cryptographic protocols, however, so long as one remembers that this
* (like everything else on-chain) it is public. For example, it can be
* used where a number is needed that cannot have been chosen by an
* adversary, for purposes such as public-coin zero-knowledge proofs.
**/
randomness: AugmentedQuery<ApiType, () => Observable<Raw>> & QueryableStorageEntry<ApiType>;
/**
* Next epoch randomness.
**/
nextRandomness: AugmentedQuery<ApiType, () => Observable<Raw>> & QueryableStorageEntry<ApiType>;
/**
* Randomness under construction.
* We make a tradeoff between storage accesses and list length.
* We store the under-construction randomness in segments of up to
* `UNDER_CONSTRUCTION_SEGMENT_LENGTH`.
* Once a segment reaches this length, we begin the next one.
* We reset all segments and return to `0` at the beginning of every
* epoch.
**/
segmentIndex: AugmentedQuery<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
underConstruction: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Vec<Raw>>> & QueryableStorageEntry<ApiType>;
/**
* Temporary value (cleared at block finalization) which is `Some`
* if per-block initialization has already been called for current block.
**/
initialized: AugmentedQuery<ApiType, () => Observable<Option<MaybeVrf>>> & QueryableStorageEntry<ApiType>;
};
timestamp: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* Current time for the current block.
**/
now: AugmentedQuery<ApiType, () => Observable<Moment>> & QueryableStorageEntry<ApiType>;
/**
* Did the timestamp get updated in this block?
**/
didUpdate: AugmentedQuery<ApiType, () => Observable<bool>> & QueryableStorageEntry<ApiType>;
};
authorship: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* Uncles
**/
uncles: AugmentedQuery<ApiType, () => Observable<Vec<UncleEntryItem>>> & QueryableStorageEntry<ApiType>;
/**
* Author of current block.
**/
author: AugmentedQuery<ApiType, () => Observable<Option<AccountId>>> & QueryableStorageEntry<ApiType>;
/**
* Whether uncles were already set in this block.
**/
didSetUncles: AugmentedQuery<ApiType, () => Observable<bool>> & QueryableStorageEntry<ApiType>;
};
indices: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* The next free enumeration set.
**/
nextEnumSet: AugmentedQuery<ApiType, () => Observable<AccountIndex>> & QueryableStorageEntry<ApiType>;
/**
* The enumeration sets.
**/
enumSet: AugmentedQuery<ApiType, (arg: AccountIndex | AnyNumber | Uint8Array) => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
};
balances: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* The total units issued in the system.
**/
totalIssuance: AugmentedQuery<ApiType, () => Observable<Balance>> & QueryableStorageEntry<ApiType>;
/**
* The balance of an account.
* NOTE: THIS MAY NEVER BE IN EXISTENCE AND YET HAVE A `total().is_zero()`. If the total
* is ever zero, then the entry *MUST* be removed.
**/
account: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<AccountData>> & QueryableStorageEntry<ApiType>;
/**
* Any liquidity locks on some account balances.
* NOTE: Should only be accessed when setting, changing and freeing a lock.
**/
locks: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Vec<BalanceLock>>> & QueryableStorageEntry<ApiType>;
/**
* True if network has been upgraded to this version.
* True for new networks.
**/
isUpgraded: AugmentedQuery<ApiType, () => Observable<bool>> & QueryableStorageEntry<ApiType>;
};
transactionPayment: {
[index: string]: QueryableStorageEntry<ApiType>;
nextFeeMultiplier: AugmentedQuery<ApiType, () => Observable<Multiplier>> & QueryableStorageEntry<ApiType>;
};
staking: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* The ideal number of staking participants.
**/
validatorCount: AugmentedQuery<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
/**
* Minimum number of staking participants before emergency conditions are imposed.
**/
minimumValidatorCount: AugmentedQuery<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
/**
* Any validators that may never be slashed or forcibly kicked. It's a Vec since they're
* easy to initialize and the performance hit is minimal (we expect no more than four
* invulnerables) and restricted to testnets.
**/
invulnerables: AugmentedQuery<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
/**
* Map from all locked "stash" accounts to the controller account.
**/
bonded: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<AccountId>>> & QueryableStorageEntry<ApiType>;
/**
* Map from all (unlocked) "controller" accounts to the info regarding the staking.
**/
ledger: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<StakingLedger>>> & QueryableStorageEntry<ApiType>;
/**
* Where the reward payment should be made. Keyed by stash.
**/
payee: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<RewardDestination>> & QueryableStorageEntry<ApiType>;
/**
* The map from (wannabe) validator stash key to the preferences of that validator.
**/
validators: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<ValidatorPrefs>> & QueryableStorageEntry<ApiType>;
/**
* The map from nominator stash key to the set of stash keys of all validators to nominate.
* NOTE: is private so that we can ensure upgraded before all typical accesses.
* Direct storage APIs can still bypass this protection.
**/
nominators: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<Nominations>>> & QueryableStorageEntry<ApiType>;
/**
* Nominators for a particular account that is in action right now. You can't iterate
* through validators here, but you can find them in the Session module.
* This is keyed by the stash account.
**/
stakers: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Exposure>> & QueryableStorageEntry<ApiType>;
/**
* The currently elected validator set keyed by stash account ID.
**/
currentElected: AugmentedQuery<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
/**
* The current era index.
**/
currentEra: AugmentedQuery<ApiType, () => Observable<EraIndex>> & QueryableStorageEntry<ApiType>;
/**
* The start of the current era.
**/
currentEraStart: AugmentedQuery<ApiType, () => Observable<MomentOf>> & QueryableStorageEntry<ApiType>;
/**
* The session index at which the current era started.
**/
currentEraStartSessionIndex: AugmentedQuery<ApiType, () => Observable<SessionIndex>> & QueryableStorageEntry<ApiType>;
/**
* Rewards for the current era. Using indices of current elected set.
**/
currentEraPointsEarned: AugmentedQuery<ApiType, () => Observable<EraPoints>> & QueryableStorageEntry<ApiType>;
/**
* The amount of balance actively at stake for each validator slot, currently.
* This is used to derive rewards and punishments.
**/
slotStake: AugmentedQuery<ApiType, () => Observable<BalanceOf>> & QueryableStorageEntry<ApiType>;
/**
* True if the next session change will be a new era regardless of index.
**/
forceEra: AugmentedQuery<ApiType, () => Observable<Forcing>> & QueryableStorageEntry<ApiType>;
/**
* The percentage of the slash that is distributed to reporters.
* The rest of the slashed value is handled by the `Slash`.
**/
slashRewardFraction: AugmentedQuery<ApiType, () => Observable<Perbill>> & QueryableStorageEntry<ApiType>;
/**
* The amount of currency given to reporters of a slash event which was
* canceled by extraordinary circumstances (e.g. governance).
**/
canceledSlashPayout: AugmentedQuery<ApiType, () => Observable<BalanceOf>> & QueryableStorageEntry<ApiType>;
/**
* All unapplied slashes that are queued for later.
**/
unappliedSlashes: AugmentedQuery<ApiType, (arg: EraIndex | AnyNumber | Uint8Array) => Observable<Vec<UnappliedSlash>>> & QueryableStorageEntry<ApiType>;
/**
* A mapping from still-bonded eras to the first session index of that era.
**/
bondedEras: AugmentedQuery<ApiType, () => Observable<Vec<ITuple<[EraIndex, SessionIndex]>>>> & QueryableStorageEntry<ApiType>;
/**
* All slashing events on validators, mapped by era to the highest slash proportion
* and slash value of the era.
**/
validatorSlashInEra: AugmentedQuery<ApiType, (key1: EraIndex | AnyNumber | Uint8Array, key2: AccountId | string | Uint8Array) => Observable<Option<ITuple<[Perbill, BalanceOf]>>>> & QueryableStorageEntry<ApiType>;
/**
* All slashing events on nominators, mapped by era to the highest slash value of the era.
**/
nominatorSlashInEra: AugmentedQuery<ApiType, (key1: EraIndex | AnyNumber | Uint8Array, key2: AccountId | string | Uint8Array) => Observable<Option<BalanceOf>>> & QueryableStorageEntry<ApiType>;
/**
* Slashing spans for stash accounts.
**/
slashingSpans: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<SlashingSpans>>> & QueryableStorageEntry<ApiType>;
/**
* Records information about the maximum slash of a stash within a slashing span,
* as well as how much reward has been paid out.
**/
spanSlash: AugmentedQuery<ApiType, (arg: ITuple<[AccountId, SpanIndex]>) => Observable<SpanRecord>> & QueryableStorageEntry<ApiType>;
/**
* The earliest era for which we have a pending, unapplied slash.
**/
earliestUnappliedSlash: AugmentedQuery<ApiType, () => Observable<Option<EraIndex>>> & QueryableStorageEntry<ApiType>;
/**
* The version of storage for upgrade.
**/
storageVersion: AugmentedQuery<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
};
session: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* The current set of validators.
**/
validators: AugmentedQuery<ApiType, () => Observable<Vec<ValidatorId>>> & QueryableStorageEntry<ApiType>;
/**
* Current index of the session.
**/
currentIndex: AugmentedQuery<ApiType, () => Observable<SessionIndex>> & QueryableStorageEntry<ApiType>;
/**
* True if the underlying economic identities or weighting behind the validators
* has changed in the queued validator set.
**/
queuedChanged: AugmentedQuery<ApiType, () => Observable<bool>> & QueryableStorageEntry<ApiType>;
/**
* The queued keys for the next session. When the next session begins, these keys
* will be used to determine the validator's session keys.
**/
queuedKeys: AugmentedQuery<ApiType, () => Observable<Vec<ITuple<[ValidatorId, Keys]>>>> & QueryableStorageEntry<ApiType>;
/**
* Indices of disabled validators.
* The set is cleared when `on_session_ending` returns a new set of identities.
**/
disabledValidators: AugmentedQuery<ApiType, () => Observable<Vec<u32>>> & QueryableStorageEntry<ApiType>;
/**
* The next session keys for a validator.
* The first key is always `DEDUP_KEY_PREFIX` to have all the data in the same branch of
* the trie. Having all data in the same branch should prevent slowing down other queries.
**/
nextKeys: AugmentedQuery<ApiType, (key1: Bytes | string | Uint8Array, key2: ValidatorId | string | Uint8Array) => Observable<Option<Keys>>> & QueryableStorageEntry<ApiType>;
/**
* The owner of a key. The second key is the `KeyTypeId` + the encoded key.
* The first key is always `DEDUP_KEY_PREFIX` to have all the data in the same branch of
* the trie. Having all data in the same branch should prevent slowing down other queries.
**/
keyOwner: AugmentedQuery<ApiType, (key1: Bytes | string | Uint8Array, key2: ITuple<[KeyTypeId, Bytes]>) => Observable<Option<ValidatorId>>> & QueryableStorageEntry<ApiType>;
};
democracy: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* The number of (public) proposals that have been made so far.
**/
publicPropCount: AugmentedQuery<ApiType, () => Observable<PropIndex>> & QueryableStorageEntry<ApiType>;
/**
* The public proposals. Unsorted. The second item is the proposal's hash.
**/
publicProps: AugmentedQuery<ApiType, () => Observable<Vec<ITuple<[PropIndex, Hash, AccountId]>>>> & QueryableStorageEntry<ApiType>;
/**
* Map of hashes to the proposal preimage, along with who registered it and their deposit.
* The block number is the block at which it was deposited.
**/
preimages: AugmentedQuery<ApiType, (arg: Hash | string | Uint8Array) => Observable<Option<ITuple<[Bytes, AccountId, BalanceOf, BlockNumber]>>>> & QueryableStorageEntry<ApiType>;
/**
* Those who have locked a deposit.
**/
depositOf: AugmentedQuery<ApiType, (arg: PropIndex | AnyNumber | Uint8Array) => Observable<Option<ITuple<[BalanceOf, Vec<AccountId>]>>>> & QueryableStorageEntry<ApiType>;
/**
* The next free referendum index, aka the number of referenda started so far.
**/
referendumCount: AugmentedQuery<ApiType, () => Observable<ReferendumIndex>> & QueryableStorageEntry<ApiType>;
/**
* The lowest referendum index representing an unbaked referendum. Equal to
* `ReferendumCount` if there isn't a unbaked referendum.
**/
lowestUnbaked: AugmentedQuery<ApiType, () => Observable<ReferendumIndex>> & QueryableStorageEntry<ApiType>;
/**
* Information concerning any given referendum.
**/
referendumInfoOf: AugmentedQuery<ApiType, (arg: ReferendumIndex | AnyNumber | Uint8Array) => Observable<Option<ReferendumInfo>>> & QueryableStorageEntry<ApiType>;
/**
* Queue of successful referenda to be dispatched. Stored ordered by block number.
**/
dispatchQueue: AugmentedQuery<ApiType, () => Observable<Vec<ITuple<[BlockNumber, Hash, ReferendumIndex]>>>> & QueryableStorageEntry<ApiType>;
/**
* Get the voters for the current proposal.
**/
votersFor: AugmentedQuery<ApiType, (arg: ReferendumIndex | AnyNumber | Uint8Array) => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
/**
* Get the vote in a given referendum of a particular voter. The result is meaningful only
* if `voters_for` includes the voter when called with the referendum (you'll get the
* default `Vote` value otherwise). If you don't want to check `voters_for`, then you can
* also check for simple existence with `VoteOf::exists` first.
**/
voteOf: AugmentedQuery<ApiType, (arg: ITuple<[ReferendumIndex, AccountId]>) => Observable<Vote>> & QueryableStorageEntry<ApiType>;
/**
* Who is able to vote for whom. Value is the fund-holding account, key is the
* vote-transaction-sending account.
**/
proxy: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<AccountId>>> & QueryableStorageEntry<ApiType>;
/**
* Get the account (and lock periods) to which another account is delegating vote.
**/
delegations: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<ITuple<[AccountId, Conviction]>>> & QueryableStorageEntry<ApiType>;
/**
* Accounts for which there are locks in action which may be removed at some point in the
* future. The value is the block number at which the lock expires and may be removed.
**/
locks: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<BlockNumber>>> & QueryableStorageEntry<ApiType>;
/**
* True if the last referendum tabled was submitted externally. False if it was a public
* proposal.
**/
lastTabledWasExternal: AugmentedQuery<ApiType, () => Observable<bool>> & QueryableStorageEntry<ApiType>;
/**
* The referendum to be tabled whenever it would be valid to table an external proposal.
* This happens when a referendum needs to be tabled and one of two conditions are met:
* - `LastTabledWasExternal` is `false`; or
* - `PublicProps` is empty.
**/
nextExternal: AugmentedQuery<ApiType, () => Observable<Option<ITuple<[Hash, VoteThreshold]>>>> & QueryableStorageEntry<ApiType>;
/**
* A record of who vetoed what. Maps proposal hash to a possible existent block number
* (until when it may not be resubmitted) and who vetoed it.
**/
blacklist: AugmentedQuery<ApiType, (arg: Hash | string | Uint8Array) => Observable<Option<ITuple<[BlockNumber, Vec<AccountId>]>>>> & QueryableStorageEntry<ApiType>;
/**
* Record of all proposals that have been subject to emergency cancellation.
**/
cancellations: AugmentedQuery<ApiType, (arg: Hash | string | Uint8Array) => Observable<bool>> & QueryableStorageEntry<ApiType>;
};
council: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* The hashes of the active proposals.
**/
proposals: AugmentedQuery<ApiType, () => Observable<Vec<Hash>>> & QueryableStorageEntry<ApiType>;
/**
* Actual proposal for a given hash, if it's current.
**/
proposalOf: AugmentedQuery<ApiType, (arg: Hash | string | Uint8Array) => Observable<Option<Proposal>>> & QueryableStorageEntry<ApiType>;
/**
* Votes on a given proposal, if it is ongoing.
**/
voting: AugmentedQuery<ApiType, (arg: Hash | string | Uint8Array) => Observable<Option<Votes>>> & QueryableStorageEntry<ApiType>;
/**
* Proposals so far.
**/
proposalCount: AugmentedQuery<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
/**
* The current members of the collective. This is stored sorted (just by value).
**/
members: AugmentedQuery<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
};
technicalCommittee: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* The hashes of the active proposals.
**/
proposals: AugmentedQuery<ApiType, () => Observable<Vec<Hash>>> & QueryableStorageEntry<ApiType>;
/**
* Actual proposal for a given hash, if it's current.
**/
proposalOf: AugmentedQuery<ApiType, (arg: Hash | string | Uint8Array) => Observable<Option<Proposal>>> & QueryableStorageEntry<ApiType>;
/**
* Votes on a given proposal, if it is ongoing.
**/
voting: AugmentedQuery<ApiType, (arg: Hash | string | Uint8Array) => Observable<Option<Votes>>> & QueryableStorageEntry<ApiType>;
/**
* Proposals so far.
**/
proposalCount: AugmentedQuery<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
/**
* The current members of the collective. This is stored sorted (just by value).
**/
members: AugmentedQuery<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
};
elections: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* The current elected membership. Sorted based on account id.
**/
members: AugmentedQuery<ApiType, () => Observable<Vec<ITuple<[AccountId, BalanceOf]>>>> & QueryableStorageEntry<ApiType>;
/**
* The current runners_up. Sorted based on low to high merit (worse to best runner).
**/
runnersUp: AugmentedQuery<ApiType, () => Observable<Vec<ITuple<[AccountId, BalanceOf]>>>> & QueryableStorageEntry<ApiType>;
/**
* The total number of vote rounds that have happened, excluding the upcoming one.
**/
electionRounds: AugmentedQuery<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
/**
* Votes of a particular voter, with the round index of the votes.
**/
votesOf: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
/**
* Locked stake of a voter.
**/
stakeOf: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<BalanceOf>> & QueryableStorageEntry<ApiType>;
/**
* The present candidate list. Sorted based on account-id. A current member or a runner can
* never enter this vector and is always implicitly assumed to be a candidate.
**/
candidates: AugmentedQuery<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
};
technicalMembership: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* The current membership, stored as an ordered Vec.
**/
members: AugmentedQuery<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
};
grandpa: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* DEPRECATED
* This used to store the current authority set, which has been migrated to the well-known
* GRANDPA_AUTHORITES_KEY unhashed key.
**/
authorities: AugmentedQuery<ApiType, () => Observable<AuthorityList>> & QueryableStorageEntry<ApiType>;
/**
* State of the current authority set.
**/
state: AugmentedQuery<ApiType, () => Observable<StoredState>> & QueryableStorageEntry<ApiType>;
/**
* Pending change: (signaled at, scheduled change).
**/
pendingChange: AugmentedQuery<ApiType, () => Observable<Option<StoredPendingChange>>> & QueryableStorageEntry<ApiType>;
/**
* next block number where we can force a change.
**/
nextForced: AugmentedQuery<ApiType, () => Observable<Option<BlockNumber>>> & QueryableStorageEntry<ApiType>;
/**
* `true` if we are currently stalled.
**/
stalled: AugmentedQuery<ApiType, () => Observable<Option<ITuple<[BlockNumber, BlockNumber]>>>> & QueryableStorageEntry<ApiType>;
/**
* The number of changes (both in terms of keys and underlying economic responsibilities)
* in the "set" of Grandpa validators from genesis.
**/
currentSetId: AugmentedQuery<ApiType, () => Observable<SetId>> & QueryableStorageEntry<ApiType>;
/**
* A mapping from grandpa set ID to the index of the *most recent* session for which its members were responsible.
**/
setIdSession: AugmentedQuery<ApiType, (arg: SetId | AnyNumber | Uint8Array) => Observable<Option<SessionIndex>>> & QueryableStorageEntry<ApiType>;
};
treasury: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* Number of proposals that have been made.
**/
proposalCount: AugmentedQuery<ApiType, () => Observable<ProposalIndex>> & QueryableStorageEntry<ApiType>;
/**
* Proposals that have been made.
**/
proposals: AugmentedQuery<ApiType, (arg: ProposalIndex | AnyNumber | Uint8Array) => Observable<Option<TreasuryProposal>>> & QueryableStorageEntry<ApiType>;
/**
* Proposal indices that have been approved but not yet awarded.
**/
approvals: AugmentedQuery<ApiType, () => Observable<Vec<ProposalIndex>>> & QueryableStorageEntry<ApiType>;
/**
* Tips that are not yet completed. Keyed by the hash of `(reason, who)` from the value.
* This has the insecure enumerable hash function since the key itself is already
* guaranteed to be a secure hash.
**/
tips: AugmentedQuery<ApiType, (arg: Hash | string | Uint8Array) => Observable<Option<OpenTip>>> & QueryableStorageEntry<ApiType>;
/**
* Simple preimage lookup from the reason's hash to the original data. Again, has an
* insecure enumerable hash since the key is guaranteed to be the result of a secure hash.
**/
reasons: AugmentedQuery<ApiType, (arg: Hash | string | Uint8Array) => Observable<Option<Bytes>>> & QueryableStorageEntry<ApiType>;
};
contracts: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* Gas spent so far in this block.
**/
gasSpent: AugmentedQuery<ApiType, () => Observable<Gas>> & QueryableStorageEntry<ApiType>;
/**
* Current cost schedule for contracts.
**/
currentSchedule: AugmentedQuery<ApiType, () => Observable<Schedule>> & QueryableStorageEntry<ApiType>;
/**
* A mapping from an original code hash to the original code, untouched by instrumentation.
**/
pristineCode: AugmentedQuery<ApiType, (arg: CodeHash | string | Uint8Array) => Observable<Option<Bytes>>> & QueryableStorageEntry<ApiType>;
/**
* A mapping between an original code hash and instrumented wasm code, ready for execution.
**/
codeStorage: AugmentedQuery<ApiType, (arg: CodeHash | string | Uint8Array) => Observable<Option<PrefabWasmModule>>> & QueryableStorageEntry<ApiType>;
/**
* The subtrie counter.
**/
accountCounter: AugmentedQuery<ApiType, () => Observable<u64>> & QueryableStorageEntry<ApiType>;
/**
* The code associated with a given account.
**/
contractInfoOf: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<ContractInfo>>> & QueryableStorageEntry<ApiType>;
/**
* The price of one unit of gas.
**/
gasPrice: AugmentedQuery<ApiType, () => Observable<BalanceOf>> & QueryableStorageEntry<ApiType>;
};
sudo: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* The `AccountId` of the sudo key.
**/
key: AugmentedQuery<ApiType, () => Observable<AccountId>> & QueryableStorageEntry<ApiType>;
};
imOnline: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* The block number after which it's ok to send heartbeats in current session.
* At the beginning of each session we set this to a value that should
* fall roughly in the middle of the session duration.
* The idea is to first wait for the validators to produce a block
* in the current session, so that the heartbeat later on will not be necessary.
**/
heartbeatAfter: AugmentedQuery<ApiType, () => Observable<BlockNumber>> & QueryableStorageEntry<ApiType>;
/**
* The current set of keys that may issue a heartbeat.
**/
keys: AugmentedQuery<ApiType, () => Observable<Vec<AuthorityId>>> & QueryableStorageEntry<ApiType>;
/**
* For each session index, we keep a mapping of `AuthIndex`
* to `offchain::OpaqueNetworkState`.
**/
receivedHeartbeats: AugmentedQuery<ApiType, (key1: SessionIndex | AnyNumber | Uint8Array, key2: AuthIndex | AnyNumber | Uint8Array) => Observable<Option<Bytes>>> & QueryableStorageEntry<ApiType>;
/**
* For each session index, we keep a mapping of `T::ValidatorId` to the
* number of blocks authored by the given authority.
**/
authoredBlocks: AugmentedQuery<ApiType, (key1: SessionIndex | AnyNumber | Uint8Array, key2: ValidatorId | string | Uint8Array) => Observable<u32>> & QueryableStorageEntry<ApiType>;
};
offences: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* The primary structure that holds all offence records keyed by report identifiers.
**/
reports: AugmentedQuery<ApiType, (arg: ReportIdOf | string | Uint8Array) => Observable<Option<OffenceDetails>>> & QueryableStorageEntry<ApiType>;
/**
* A vector of reports of the same kind that happened at the same time slot.
**/
concurrentReportsIndex: AugmentedQuery<ApiType, (key1: Kind | string | Uint8Array, key2: OpaqueTimeSlot | string | Uint8Array) => Observable<Vec<ReportIdOf>>> & QueryableStorageEntry<ApiType>;
/**
* Enumerates all reports of a kind along with the time they happened.
* All reports are sorted by the time of offence.
* Note that the actual type of this mapping is `Vec<u8>`, this is because values of
* different types are not supported at the moment so we are doing the manual serialization.
**/
reportsByKindIndex: AugmentedQuery<ApiType, (arg: Kind | string | Uint8Array) => Observable<Bytes>> & QueryableStorageEntry<ApiType>;
};
randomnessCollectiveFlip: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* Series of block headers from the last 81 blocks that acts as random seed material. This
* is arranged as a ring buffer with `block_number % 81` being the index into the `Vec` of
* the oldest hash.
**/
randomMaterial: AugmentedQuery<ApiType, () => Observable<Vec<Hash>>> & QueryableStorageEntry<ApiType>;
};
identity: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* Information that is pertinent to identify the entity behind an account.
**/
identityOf: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<Registration>>> & QueryableStorageEntry<ApiType>;
/**
* The super-identity of an alternative "sub" identity together with its name, within that
* context. If the account is not some other account's sub-identity, then just `None`.
**/
superOf: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<ITuple<[AccountId, Data]>>>> & QueryableStorageEntry<ApiType>;
/**
* Alternative "sub" identities of this account.
* The first item is the deposit, the second is a vector of the accounts.
**/
subsOf: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<ITuple<[BalanceOf, Vec<AccountId>]>>> & QueryableStorageEntry<ApiType>;
/**
* The set of registrars. Not expected to get very big as can only be added through a
* special origin (likely a council motion).
* The index into this can be cast to `RegistrarIndex` to get a valid value.
**/
registrars: AugmentedQuery<ApiType, () => Observable<Vec<Option<RegistrarInfo>>>> & QueryableStorageEntry<ApiType>;
};
society: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* The first member.
**/
founder: AugmentedQuery<ApiType, () => Observable<Option<AccountId>>> & QueryableStorageEntry<ApiType>;
/**
* A hash of the rules of this society concerning membership. Can only be set once and
* only by the founder.
**/
rules: AugmentedQuery<ApiType, () => Observable<Option<Hash>>> & QueryableStorageEntry<ApiType>;
/**
* The current set of candidates; bidders that are attempting to become members.
**/
candidates: AugmentedQuery<ApiType, () => Observable<Vec<Bid>>> & QueryableStorageEntry<ApiType>;
/**
* The set of suspended candidates.
**/
suspendedCandidates: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<ITuple<[BalanceOf, BidKind]>>>> & QueryableStorageEntry<ApiType>;
/**
* Amount of our account balance that is specifically for the next round's bid(s).
**/
pot: AugmentedQuery<ApiType, () => Observable<BalanceOf>> & QueryableStorageEntry<ApiType>;
/**
* The most primary from the most recently approved members.
**/
head: AugmentedQuery<ApiType, () => Observable<Option<AccountId>>> & QueryableStorageEntry<ApiType>;
/**
* The current set of members, ordered.
**/
members: AugmentedQuery<ApiType, () => Observable<Vec<AccountId>>> & QueryableStorageEntry<ApiType>;
/**
* The set of suspended members.
**/
suspendedMembers: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<bool>> & QueryableStorageEntry<ApiType>;
/**
* The current bids, stored ordered by the value of the bid.
**/
bids: AugmentedQuery<ApiType, () => Observable<Vec<Bid>>> & QueryableStorageEntry<ApiType>;
/**
* Members currently vouching or banned from vouching again
**/
vouching: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<VouchingStatus>>> & QueryableStorageEntry<ApiType>;
/**
* Pending payouts; ordered by block number, with the amount that should be paid out.
**/
payouts: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Vec<ITuple<[BlockNumber, BalanceOf]>>>> & QueryableStorageEntry<ApiType>;
/**
* The ongoing number of losing votes cast by the member.
**/
strikes: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<StrikeCount>> & QueryableStorageEntry<ApiType>;
/**
* Double map from Candidate -> Voter -> (Maybe) Vote.
**/
votes: AugmentedQuery<ApiType, (key1: AccountId | string | Uint8Array, key2: AccountId | string | Uint8Array) => Observable<Option<SocietyVote>>> & QueryableStorageEntry<ApiType>;
/**
* The defending member currently being challenged.
**/
defender: AugmentedQuery<ApiType, () => Observable<Option<AccountId>>> & QueryableStorageEntry<ApiType>;
/**
* Votes for the defender.
**/
defenderVotes: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<SocietyVote>>> & QueryableStorageEntry<ApiType>;
/**
* The max number of members for the society at one time.
**/
maxMembers: AugmentedQuery<ApiType, () => Observable<u32>> & QueryableStorageEntry<ApiType>;
};
recovery: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* The set of recoverable accounts and their recovery configuration.
**/
recoverable: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<RecoveryConfig>>> & QueryableStorageEntry<ApiType>;
/**
* Active recovery attempts.
* First account is the account to be recovered, and the second account
* is the user trying to recover the account.
**/
activeRecoveries: AugmentedQuery<ApiType, (key1: AccountId | string | Uint8Array, key2: AccountId | string | Uint8Array) => Observable<Option<ActiveRecovery>>> & QueryableStorageEntry<ApiType>;
/**
* The final list of recovered accounts.
* Map from the recovered account to the user who can access it.
**/
recovered: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<AccountId>>> & QueryableStorageEntry<ApiType>;
};
vesting: {
[index: string]: QueryableStorageEntry<ApiType>;
/**
* Information regarding the vesting of a given account.
**/
vesting: AugmentedQuery<ApiType, (arg: AccountId | string | Uint8Array) => Observable<Option<VestingInfo>>> & QueryableStorageEntry<ApiType>;
};
}
}
+178
View File
@@ -0,0 +1,178 @@
// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
/* eslint-disable @typescript-eslint/no-empty-interface */
import { AnyNumber, Codec, IExtrinsic } from '@polkadot/types/types';
import { Option, Vec } from '@polkadot/types/codec';
import { Bytes, H256, StorageData, StorageKey, Text, u32, u64 } from '@polkadot/types/primitive';
import { Metadata } from '@polkadot/types';
import { AccountId, BlockNumber, Extrinsic, Hash, Header, Index, SignedBlock } from '@polkadot/types/interfaces/runtime';
import { ContractCallRequest, ContractExecResult } from '@polkadot/types/interfaces/contracts';
import { BlockHash, ChainProperties, ExtrinsicOrHash, ExtrinsicStatus, Health, NetworkState, PeerInfo, RpcMethods, RuntimeDispatchInfo, RuntimeVersion, StorageChangeSet } from '@polkadot/types/interfaces/rpc';
import { Observable } from 'rxjs';
declare module '@polkadot/rpc-core/types.jsonrpc' {
export interface RpcInterface {
account: {
/**
* Retrieves the next accountIndex as available on the node
**/
nextIndex(accountId: AccountId | string | Uint8Array): Observable<Index>;
};
author: {
/**
* Insert a key into the keystore.
**/
insertKey(keyType: Text | string, suri: Text | string, publicKey: Bytes | string | Uint8Array): Observable<Bytes>;
/**
* Returns all pending extrinsics, potentially grouped by sender
**/
pendingExtrinsics(): Observable<Vec<Extrinsic>>;
/**
* Remove given extrinsic from the pool and temporarily ban it to prevent reimporting
**/
removeExtrinsic(bytesOrHash: Vec<ExtrinsicOrHash> | (ExtrinsicOrHash | { hash: any } | { extrinsic: any } | string | Uint8Array)[]): Observable<Vec<Hash>>;
/**
* Generate new session keys and returns the corresponding public keys
**/
rotateKeys(): Observable<Bytes>;
/**
* Submit and subscribe to watch an extrinsic until unsubscribed
**/
submitAndWatchExtrinsic(extrinsic: IExtrinsic): Observable<ExtrinsicStatus>;
/**
* Submit a fully formatted extrinsic for block inclusion
**/
submitExtrinsic(extrinsic: IExtrinsic): Observable<Hash>;
};
chain: {
/**
* Get header and body of a relay chain block
**/
getBlock(hash?: BlockHash | string | Uint8Array): Observable<SignedBlock>;
/**
* Get the block hash for a specific block
**/
getBlockHash(blockNumber?: BlockNumber | AnyNumber | Uint8Array): Observable<BlockHash>;
/**
* Get hash of the last finalized block in the canon chain
**/
getFinalizedHead(): Observable<BlockHash>;
/**
* Retrieves the header for a specific block
**/
getHeader(hash?: BlockHash | string | Uint8Array): Observable<Header>;
/**
* Retrieves the best finalized header via subscription
**/
subscribeFinalizedHeads(): Observable<Header>;
/**
* Retrieves the best header via subscription
**/
subscribeNewHeads(): Observable<Header>;
};
contracts: {
/**
* Executes a call to a contract
**/
call(callRequest: ContractCallRequest | { origin?: any; dest?: any; value?: any; gasLimit?: any; inputData?: any } | string | Uint8Array, at?: BlockHash | string | Uint8Array): Observable<ContractExecResult>;
/**
* Returns the value under a specified storage key in a contract
**/
getStorage(address: AccountId | string | Uint8Array, key: H256 | string | Uint8Array, at?: BlockHash | string | Uint8Array): Observable<Option<Bytes>>;
};
payment: {
/**
* Retrieves the fee information for an encoded extrinsic
**/
queryInfo(extrinsic: Bytes | string | Uint8Array, at?: BlockHash | string | Uint8Array): Observable<RuntimeDispatchInfo>;
};
rpc: {
/**
* Retrieves the list of RPC methods that are exposed by the node
**/
methods(): Observable<RpcMethods>;
};
state: {
/**
* Perform a call to a builtin on the chain
**/
call(method: Text | string, data: Bytes | string | Uint8Array, at?: BlockHash | string | Uint8Array): Observable<Bytes>;
/**
* Retrieves the keys with prefix of a specific child storage
**/
getChildKeys(childStorageKey: StorageKey | string | Uint8Array | any, childDefinition: StorageKey | string | Uint8Array | any, childType: u32 | AnyNumber | Uint8Array, key: StorageKey | string | Uint8Array | any, at?: BlockHash | string | Uint8Array): Observable<Vec<StorageKey>>;
/**
* Retrieves the child storage for a key
**/
getChildStorage(childStorageKey: StorageKey | string | Uint8Array | any, childDefinition: StorageKey | string | Uint8Array | any, childType: u32 | AnyNumber | Uint8Array, key: StorageKey | string | Uint8Array | any, at?: BlockHash | string | Uint8Array): Observable<StorageData>;
/**
* Retrieves the child storage hash
**/
getChildStorageHash(childStorageKey: StorageKey | string | Uint8Array | any, childDefinition: StorageKey | string | Uint8Array | any, childType: u32 | AnyNumber | Uint8Array, key: StorageKey | string | Uint8Array | any, at?: BlockHash | string | Uint8Array): Observable<Hash>;
/**
* Retrieves the child storage size
**/
getChildStorageSize(childStorageKey: StorageKey | string | Uint8Array | any, childDefinition: StorageKey | string | Uint8Array | any, childType: u32 | AnyNumber | Uint8Array, key: StorageKey | string | Uint8Array | any, at?: BlockHash | string | Uint8Array): Observable<u64>;
/**
* Retrieves the keys with a certain prefix
**/
getKeys(key: StorageKey | string | Uint8Array | any, at?: BlockHash | string | Uint8Array): Observable<Vec<StorageKey>>;
/**
* Returns the runtime metadata
**/
getMetadata(at?: BlockHash | string | Uint8Array): Observable<Metadata>;
/**
* Get the runtime version
**/
getRuntimeVersion(at?: BlockHash | string | Uint8Array): Observable<RuntimeVersion>;
getStorage<T = Codec>(key: any, block?: Hash | Uint8Array | string): Observable<T>;
/**
* Retrieves the storage hash
**/
getStorageHash(key: StorageKey | string | Uint8Array | any, at?: BlockHash | string | Uint8Array): Observable<Hash>;
/**
* Retrieves the storage size
**/
getStorageSize(key: StorageKey | string | Uint8Array | any, at?: BlockHash | string | Uint8Array): Observable<u64>;
/**
* Query historical storage entries (by key) starting from a start block
**/
queryStorage(keys: Vec<StorageKey> | (StorageKey | string | Uint8Array | any)[], startBlock: Hash | string | Uint8Array, at?: BlockHash | string | Uint8Array): Observable<Vec<StorageChangeSet>>;
/**
* Retrieves the runtime version via subscription
**/
subscribeRuntimeVersion(): Observable<RuntimeVersion>;
subscribeStorage<T = Codec[]>(keys: any[]): Observable<T>;
};
system: {
/**
* Retrieves the chain
**/
chain(): Observable<Text>;
/**
* Return health status of the node
**/
health(): Observable<Health>;
/**
* Retrieves the node name
**/
name(): Observable<Text>;
/**
* Returns current state of the network
**/
networkState(): Observable<NetworkState>;
/**
* Returns the currently connected peers
**/
peers(): Observable<Vec<PeerInfo>>;
/**
* Get a custom set of properties as a JSON object, defined in the chain spec
**/
properties(): Observable<ChainProperties>;
/**
* Retrieves the version of the node
**/
version(): Observable<Text>;
};
}
}
File diff suppressed because it is too large Load Diff
+70
View File
@@ -0,0 +1,70 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Observable } from 'rxjs';
import { AnyFunction, Callback, Codec } from '@polkadot/types/types';
// Prepend an element V onto the beginning of a tuple T.
// Cons<1, [2,3,4]> is [1,2,3,4]
type Cons<V, T extends any[]> = ((v: V, ...t: T) => void) extends ((...r: infer R) => void)
? R
: never;
// Append an element V onto the end of a tuple T
// Push<[1,2,3],4> is [1,2,3,4]
// note that this DOES NOT PRESERVE optionality/readonly in tuples.
// So unfortunately Push<[1, 2?, 3?], 4> is [1,2|undefined,3|undefined,4]
type Push<T extends any[], V> = (
(
Cons<any, Required<T>> extends infer R
? { [K in keyof R]: K extends keyof T ? T[K] : V }
: never
) extends infer P
? P extends any[] ? P : never
: never
);
export type ApiTypes = 'promise' | 'rxjs';
// Returns the inner type of an Observable
export type ObsInnerType<O extends Observable<any>> = O extends Observable<infer U> ? U : never;
export type UnsubscribePromise = Promise<() => void>;
// FIXME The day TS has higher-kinded types, we can remove this hardcoded stuff
export type PromiseOrObs<ApiType extends ApiTypes, T> = ApiType extends 'rxjs'
? Observable<T>
: Promise<T>;
// Here are the return types of these parts of the api:
// - api.query.*.*: no exact typings
// - api.tx.*.*: SubmittableExtrinsic<ApiType extends ApiTypes>
// - api.derive.*.*: MethodResult<ApiType, F>
// - api.rpc.*.*: no exact typings (for now, FIXME: should be MethodResult<ApiType, F>, like in derive)
// These are the types that don't lose type information (used for api.derive.*)
// Also use these for api.rpc.* https://github.com/polkadot-js/api/issues/1009
export interface RxResult<F extends AnyFunction> {
(...args: Parameters<F>): Observable<ObsInnerType<ReturnType<F>>>;
<T>(...args: Parameters<F>): Observable<T>;
}
export interface PromiseResult<F extends AnyFunction> {
(...args: Parameters<F>): Promise<ObsInnerType<ReturnType<F>>>;
(...args: Push<Parameters<F>, Callback<ObsInnerType<ReturnType<F>>>>): UnsubscribePromise;
<T extends Codec | Codec[]>(...args: Parameters<F>): Promise<T>;
<T extends Codec | Codec[]>(...args: Push<Parameters<F>, Callback<T>>): UnsubscribePromise;
}
// FIXME The day TS has higher-kinded types, we can remove this hardcoded stuff
export type MethodResult<ApiType extends ApiTypes, F extends AnyFunction> = ApiType extends 'rxjs'
? RxResult<F>
: PromiseResult<F>;
// In the abstract `decorateMethod` in Base.ts, we can also pass in some meta-
// information. This describes it.
export interface DecorateMethodOptions {
methodName?: string;
}
export type DecorateMethod<ApiType extends ApiTypes> = <Method extends (...args: any[]) => Observable<any>>(method: Method, options?: DecorateMethodOptions) => any;
+130
View File
@@ -0,0 +1,130 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
// Module augmentation so that `api.{consts,query,rpc,tx}.*.*` work
import './augment';
import BN from 'bn.js';
import { DeriveCustom, ExactDerive } from '@polkadot/api-derive';
import { Constants } from '@polkadot/metadata/Decorated/types';
import { RpcInterface, UserRpc } from '@polkadot/rpc-core/types';
import { Metadata } from '@polkadot/types';
import { Hash, RuntimeVersion } from '@polkadot/types/interfaces';
import { RegistryTypes, SignatureOptions, SignerPayloadJSON, SignerPayloadRaw, Registry } from '@polkadot/types/types';
import ApiBase from '../base';
import { SubmittableResultImpl } from '../submittable/types';
import { DeriveAllSections } from '../util/decorate';
import { DecoratedRpc } from './rpc';
import { QueryableStorage, QueryableStorageMulti } from './storage';
import { SubmittableExtrinsics } from './submittable';
import { ProviderInterface, ProviderInterfaceEmitted } from '@polkadot/rpc-provider/types';
export * from '../submittable/types';
export * from './base';
export * from './rpc';
export * from './storage';
export * from './submittable';
export interface ApiOptions {
/**
* @description Add custom derives to be injected
*/
derives?: DeriveCustom;
/**
* @description prebundles is a map of 'genesis hash and runtime spec version' as key to metadata's hex string
* if genesis hash and runtime spec version matches, then use metadata, else fetch it from chain
*/
metadata?: Record<string, string>;
/**
* @description Transport Provider from rpc-provider. If not specified, it will default to
* connecting to a WsProvider connecting localhost with the default port, i.e. `ws://127.0.0.1:9944`
*/
provider?: ProviderInterface;
/**
* @description A type registry to use along with this instance
*/
registry?: Registry;
/**
* @description User-defined RPC methods
*/
rpc?: UserRpc;
/**
* @description An external signer which will be used to sign extrinsic when account passed in is not KeyringPair
*/
signer?: Signer;
/**
* @description The source object to use for runtime information (only used when cloning)
*/
source?: ApiBase<any>;
/**
* @description Additional types used by runtime modules. This is nessusary if the runtime modules
* uses types not available in the base Substrate runtime.
*/
types?: RegistryTypes;
/**
* @description Additional types that are injected based on the chain we are connecting to. There are keyed by the chain, i.e. `{ 'Kusama CC1': { ... } }`
*/
typesChain?: Record<string, RegistryTypes>;
/**
* @description Additional types that are injected based on the type of node we are connecting to, as set via specName in the runtime version. There are keyed by the node, i.e. `{ 'edgeware': { ... } }`
*/
typesSpec?: Record<string, RegistryTypes>;
}
// A smaller interface of ApiRx, used in derive and in SubmittableExtrinsic
export interface ApiInterfaceRx {
consts: Constants;
// TODO This needs to be typed correctly
derive: DeriveAllSections<'rxjs', ExactDerive>;
extrinsicType: number;
genesisHash: Hash;
hasSubscriptions: boolean;
registry: Registry;
runtimeMetadata: Metadata;
runtimeVersion: RuntimeVersion;
query: QueryableStorage<'rxjs'>;
queryMulti: QueryableStorageMulti<'rxjs'>;
rpc: DecoratedRpc<'rxjs', RpcInterface>;
tx: SubmittableExtrinsics<'rxjs'>;
signer?: Signer;
}
export type ApiInterfaceEvents = ProviderInterfaceEmitted | 'ready';
export interface SignerOptions extends SignatureOptions {
blockNumber: BN;
genesisHash: Hash;
}
export interface SignerResult {
/**
* @description The id for this request
*/
id: number;
/**
* @description The resulting signature in hex
*/
signature: string;
}
export interface Signer {
/**
* @description signs an extrinsic payload from a serialized form
*/
signPayload?: (payload: SignerPayloadJSON) => Promise<SignerResult>;
/**
* @description signs a raw payload, only the bytes data as supplied
*/
signRaw?: (raw: SignerPayloadRaw) => Promise<SignerResult>;
/**
* @description Receives an update for the extrinsic signed by a `signer.sign`
*/
update?: (id: number, status: Hash | SubmittableResultImpl) => void;
}
export { ApiBase };
+17
View File
@@ -0,0 +1,17 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyFunction } from '@polkadot/types/types';
import { ApiTypes, MethodResult } from './base';
export type DecoratedRpcSection<ApiType extends ApiTypes, Section> = {
[Method in keyof Section]: Section[Method] extends AnyFunction
? MethodResult<ApiType, Section[Method]>
: never
}
export type DecoratedRpc<ApiType extends ApiTypes, AllSections> = {
[Section in keyof AllSections]: DecoratedRpcSection<ApiType, AllSections[Section]>
}
+77
View File
@@ -0,0 +1,77 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Observable } from 'rxjs';
import { u64 } from '@polkadot/types';
import { Hash } from '@polkadot/types/interfaces';
import { AnyFunction, Callback, Codec, CodecArg } from '@polkadot/types/types';
import StorageKey, { StorageEntry } from '@polkadot/types/primitive/StorageKey';
import { ApiTypes, MethodResult, ObsInnerType, PromiseOrObs, UnsubscribePromise } from './base';
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface AugmentedQueries<ApiType extends ApiTypes> { }
export type AugmentedQuery<ApiType extends ApiTypes, F extends AnyFunction> = MethodResult<ApiType, F> & StorageEntryBase<ApiType, F>
// This is the most generic typings we can have for a storage entry function
type GenericStorageEntryFunction = (arg1?: CodecArg, arg2?: CodecArg) => Observable<Codec>
export type QueryableStorageEntry<ApiType extends ApiTypes> =
ApiType extends 'rxjs'
? AugmentedQuery<'rxjs', GenericStorageEntryFunction>
: AugmentedQuery<'promise', GenericStorageEntryFunction> & StorageEntryPromiseOverloads;
export interface StorageEntryBase<ApiType extends ApiTypes, F extends AnyFunction> {
at: (hash: Hash | Uint8Array | string, ...args: Parameters<F>) => PromiseOrObs<ApiType, ObsInnerType<ReturnType<F>>>;
creator: StorageEntry;
entries: () => PromiseOrObs<ApiType, [StorageKey, ObsInnerType<ReturnType<F>>][]>;
hash: (...args: Parameters<F>) => PromiseOrObs<ApiType, Hash>;
key: (...args: Parameters<F>) => string;
keyPrefix: () => string;
size: (...args: Parameters<F>) => PromiseOrObs<ApiType, u64>;
multi: ApiType extends 'rxjs' ? StorageEntryObservableMulti : StorageEntryPromiseMulti;
}
interface StorageEntryObservableMulti {
<T extends Codec>(args: (CodecArg[] | CodecArg)[]): Observable<T[]>;
}
interface StorageEntryPromiseMulti {
<T extends Codec>(args: (CodecArg[] | CodecArg)[]): Promise<T[]>;
<T extends Codec>(args: (CodecArg[] | CodecArg)[], callback: Callback<T[]>): UnsubscribePromise;
}
export interface StorageEntryPromiseOverloads {
(arg1?: CodecArg, arg2?: CodecArg): Promise<Codec>;
<T extends Codec>(arg1?: CodecArg, arg2?: CodecArg): Promise<T>;
<T extends Codec>(callback: Callback<T>): UnsubscribePromise;
<T extends Codec>(arg: CodecArg, callback: Callback<T>): UnsubscribePromise;
<T extends Codec>(arg1: CodecArg, arg2: CodecArg, callback: Callback<T>): UnsubscribePromise;
}
export interface QueryableModuleStorage<ApiType extends ApiTypes> {
[index: string]: QueryableStorageEntry<ApiType>;
}
export type QueryableStorageMultiArg<ApiType extends ApiTypes> =
QueryableStorageEntry<ApiType> |
[QueryableStorageEntry<ApiType>, ...CodecArg[]];
export interface QueryableStorageMultiBase<ApiType extends ApiTypes> {
<T extends Codec[]>(calls: QueryableStorageMultiArg<ApiType>[]): Observable<T>;
}
export interface QueryableStorageMultiPromise<ApiType extends ApiTypes> {
<T extends Codec[]>(calls: QueryableStorageMultiArg<ApiType>[], callback: Callback<T>): UnsubscribePromise;
}
export type QueryableStorageMulti<ApiType extends ApiTypes> =
ApiType extends 'rxjs'
? QueryableStorageMultiBase<ApiType>
: QueryableStorageMultiPromise<ApiType>;
export interface QueryableStorage<ApiType extends ApiTypes> extends AugmentedQueries<ApiType> {
[index: string]: QueryableModuleStorage<ApiType>;
}
+26
View File
@@ -0,0 +1,26 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyFunction, CallBase } from '@polkadot/types/types';
import { SubmittableExtrinsic } from '../submittable/types';
import { ApiTypes } from './base';
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface AugmentedSubmittables<ApiType extends ApiTypes> { }
export type AugmentedSubmittable<T extends AnyFunction> = T & CallBase;
export interface SubmittableExtrinsicFunction<ApiType extends ApiTypes> extends CallBase {
(...params: any[]): SubmittableExtrinsic<ApiType>;
}
export interface SubmittableModuleExtrinsics<ApiType extends ApiTypes> {
[index: string]: SubmittableExtrinsicFunction<ApiType>;
}
export interface SubmittableExtrinsics<ApiType extends ApiTypes> extends AugmentedSubmittables<ApiType> {
(extrinsic: Uint8Array | string): SubmittableExtrinsic<ApiType>;
[index: string]: SubmittableModuleExtrinsics<ApiType>;
}
@@ -1,169 +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 ApiPromise from '@polkadot/api/promise/Api';
import testingPairs from '@polkadot/keyring/testingPairs';
import { WsProvider } from '@polkadot/rpc-provider';
import { SubmittableResult } from '@polkadot/api';
import { DerivedBalances, DerivedStakingAccount } from '@polkadot/api-derive/types';
import { describeE2E } from '../../util';
const ALICE_STASH = testingPairs().alice_stash.address;
describeE2E({
except: [
'remote-polkadot-alexander',
'remote-substrate-1.0'
]
})('Derive Promise e2e development', (wsUrl: string): void => {
let api: ApiPromise;
beforeEach(async (done): Promise<void> => {
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
done();
});
it('retrieves the balances', (done): Promise<() => void> => {
return api.derive.balances.all('5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y', (balance: DerivedBalances): void => {
console.error(JSON.stringify(balance));
if (balance.freeBalance.gtn(1)) {
done();
}
});
});
it('retrieves balances for a problematic account', (done): Promise<() => void> => {
return api.derive.balances.all('5F7BJL6Z4m8RLtK7nXEqqpEqhBbd535Z3CZeYF6ccvaQAY6N', (balance: DerivedBalances): void => {
console.error(JSON.stringify(balance));
if (balance.availableBalance.eqn(0)) {
done();
}
});
});
describe('staking', (): void => {
it('retrieves all staking info (for controller)', (done): Promise<() => void> => {
const accountId = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY';
return api.derive.staking.account(accountId, (info: DerivedStakingAccount): void => {
console.error(JSON.stringify(info));
expect(info.accountId.eq(accountId)).toBe(true);
expect(info.controllerId!.eq(accountId)).toBe(true);
expect(info.stashId!.eq('5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY')).toBe(true);
expect(info.stashId!.eq(info.stakingLedger!.stash)).toBe(true);
done();
});
});
it('retrieves all staking info (for stash)', (done): Promise<() => void> => {
const accountId = '5GNJqTPyNqANBkUVMN1LPPrxXnFouWXoe2wNSmmEoLctxiZY';
return api.derive.staking.account(accountId, (info: DerivedStakingAccount): void => {
console.error(JSON.stringify(info));
if (!info.stashId || !info.controllerId || !info.stakingLedger) {
done.fail(new Error('At least one of info.stashId, info.controllerId or info.stakingLedger is undefined.'));
return;
}
expect(info.accountId.eq(accountId)).toBe(true);
expect(info.controllerId.eq('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY')).toBe(true);
expect(info.stashId.eq(accountId)).toBe(true);
expect(info.stashId.eq(info.stakingLedger.stash)).toBe(true);
done();
});
});
describe('verifies derive.staking.unlocking', (): void => {
const UNBOND_VALUE = 1;
const alicePair = testingPairs().alice;
it('unbonds dots for Alice (from Alice Stash)', (done): Promise<() => void> => {
return api.tx.staking.unbond(UNBOND_VALUE)
.signAndSend(alicePair, (result: SubmittableResult): void => {
if (result.status.isFinalized) {
done();
}
});
});
it('verifies that derive.staking.unlocking isn\'t empty/undefined', (): Promise<() => void> => {
return api.derive.staking.account(ALICE_STASH, (info: DerivedStakingAccount): void => {
expect(info.unlocking).toBeDefined();
});
});
});
describe('verifies derive.staking.rewardDestination', (): void => {
const PAYEE = 2;
const alicePair = testingPairs().alice;
it('Set payee for ALICE to 2', (done): Promise<() => void> => {
return api.tx.staking
.setPayee(PAYEE)
.signAndSend(alicePair, (result: SubmittableResult): void => {
if (result.status.isFinalized) {
done();
}
});
});
it('verifies payee for ALICE_STASH', (done): Promise<() => void> => {
return api.derive.staking.account(ALICE_STASH, (info: DerivedStakingAccount): void => {
if (!info.rewardDestination) {
return done.fail(new Error('rewardDestination is undefined.'));
} else {
expect(info.rewardDestination.toString()).toBe('Controller');
}
done();
});
});
it('staking.account updates itself after changing reward destination', async (done): Promise<void> => {
const stashId = testingPairs().alice_stash.address;
// start by setting the reqred to Staked, so we have a common starting point
await api.tx.staking
.setPayee('Staked')
.signAndSend(testingPairs().alice, ({ status }): void => {
if (status.isFinalized) {
console.error('setPayee(Staked) isFinalized');
}
});
let count = 0; // The # of times we got a callback response from api.derive.staking.account
// Subscribe to staking.account
api.derive.staking.account(stashId, (result): void => {
++count;
console.error('***', count, JSON.stringify(result));
if (count >= 2 && result.rewardDestination!.toString() === 'Stash') {
done();
}
});
// Wait a bit, and change reward destination
// eslint-disable-next-line @typescript-eslint/no-misused-promises
setTimeout(async (): Promise<void> => {
await api.tx.staking
.setPayee('Stash')
.signAndSend(testingPairs().alice, ({ status }): void => {
if (status.isFinalized) {
console.error('setPayee(Stash) isFinalized');
}
});
}, 5000);
});
});
});
});
@@ -1,71 +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 ApiPromise from '@polkadot/api/promise/Api';
import { WsProvider } from '@polkadot/rpc-provider';
import { HeaderExtended } from '@polkadot/api-derive/type';
import { DerivedElectionsInfo, DerivedFees, DerivedSessionInfo } from '@polkadot/api-derive/types';
import { describeE2E } from '../../util';
describeE2E()('Derive Promise e2e', (wsUrl: string): void => {
let api: ApiPromise;
beforeEach(async (done): Promise<void> => {
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
done();
});
it('Get the latest block number', async (): Promise<void> => {
// https://github.com/polkadot-js/api/issues/777
const block1 = await api.derive.chain.bestNumber();
await new Promise((resolve): void => {
setTimeout(resolve, 10000);
});
const block2 = await api.derive.chain.bestNumber();
expect(block1.eq(block2)).toBe(false);
});
it('subscribes to newHead, retrieving the actual validator', (done): Promise<() => void> => {
return api.derive.chain.subscribeNewHeads(({ author }: HeaderExtended): void => {
console.log('author', author && author.toString());
if (author) {
done();
}
});
});
it('retrieves the fees (api.queryMulti)', (done): Promise<() => void> => {
return api.derive.balances.fees((fees: DerivedFees): void => {
console.error('fees', JSON.stringify(fees));
done();
});
});
it('retrieves elections info', (done): Promise<() => void> => {
return api.derive.elections.info((info: DerivedElectionsInfo): void => {
console.error('fees', JSON.stringify(info));
done();
});
});
it('retrieves all session info', (done): Promise<() => void> => {
let count = 0;
return api.derive.session.info((info: DerivedSessionInfo): void => {
console.error(JSON.stringify(info));
// 5 blocks only, then go our merry way
if (++count === 5) {
done();
}
});
});
});
-302
View File
@@ -1,302 +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 { BlockNumber } from '@polkadot/types/interfaces';
import BN from 'bn.js';
import ApiRx from '@polkadot/api/rx/Api';
import { HeaderExtended } from '@polkadot/api-derive';
import { DerivedBalances, DerivedContractFees, DerivedElectionsInfo, DerivedFees, DerivedSessionInfo } from '@polkadot/api-derive/types';
import { createType, ClassOf, TypeRegistry } from '@polkadot/types';
import { WsProvider } from '@polkadot/rpc-provider';
import { describeE2E } from '../../util';
// Dev account Alice
const ID = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY';
const IX = 'F7Hs';
describeE2E({
except: [
'remote-polkadot-alexander',
'remote-substrate-1.0'
]
})('Api-RX derive e2e', (wsUrl: string): void => {
const registry = new TypeRegistry();
let api: ApiRx;
beforeAll((): void => {
jest.setTimeout(10000);
});
beforeEach(async (done): Promise<void> => {
api = await ApiRx.create({ provider: new WsProvider(wsUrl) }).toPromise();
done();
});
afterAll((): void => {
jest.setTimeout(10000);
});
// These derive.accounts tests only work on localhost, not the poc-3 URL
// (and it is assuming it sent at least 1 tx)
describe('derive.accounts', (): void => {
describe('idAndIndex', (): void => {
it('looks up AccountId & AccountIndex from AccountId', (done): void => {
api.derive.accounts.idAndIndex(ID).subscribe(([accountId, accountIndex]): void => {
expect(accountId!.toString()).toEqual(ID);
// The first emitted value for ix is undefined when passing the ID
if (accountIndex) {
expect(accountIndex.toString()).toEqual(IX);
} else {
expect(accountIndex).toEqual(undefined);
}
done();
});
});
it('looks up AccountId & AccountIndex from AccountIndex', (done): void => {
api.derive.accounts.idAndIndex(IX).subscribe(([accountId, accountIndex]): void => {
// The first emitted value for id is undefined when passing the IX
if (accountId) {
expect(accountId.toString()).toEqual(ID);
} else {
expect(accountId).toEqual(undefined);
}
expect(accountIndex!.toString()).toEqual(IX);
done();
});
});
});
describe('indexToId', (): void => {
it('looks up AccountId from AccountIndex', (done): void => {
api.derive.accounts.indexToId(IX).subscribe((accountId): void => {
// The first emitted value for accountId is undefined when passing the IX
if (accountId) {
expect(accountId instanceof ClassOf(registry, 'AccountId')).toBe(true);
expect(accountId.toString()).toEqual(ID);
} else {
expect(accountId).toEqual(undefined);
}
done();
});
});
});
describe('idToIndex', (): void => {
it('looks up AccountIndex from AccountId', (done): void => {
api.derive.accounts.idToIndex(ID).subscribe((accountIndex): void => {
// The first emitted value for AccountIndex is undefined when passing the ID
if (accountIndex) {
expect(accountIndex instanceof ClassOf(registry, 'AccountIndex')).toBe(true);
expect(accountIndex.toString()).toEqual(IX);
} else {
expect(accountIndex).toEqual(undefined);
}
done();
});
});
});
describe('indexes', (): void => {
it('looks up all AccountIndexes', (done): void => {
api.derive.accounts.indexes().subscribe((accountIndexes): void => {
// A local dev chain should have the AccountIndex of Alice
expect(accountIndexes).toHaveProperty(
ID,
createType(registry, 'AccountIndex', IX)
);
done();
});
});
});
});
// these only work on localhost, not the poc-3 URL
// (and it is assuming it sent at least 1 tx)
describe('derive.balances', (): void => {
describe('all', (): void => {
it('It returns an object with all relevant balance information of an account', (done): void => {
api.derive.balances.all(ID).subscribe((balances: DerivedBalances): void => {
expect(balances).toEqual(expect.objectContaining({
accountId: expect.any(ClassOf(registry, 'AccountId')),
accountNonce: expect.any(ClassOf(registry, 'Index')),
availableBalance: expect.any(BN),
freeBalance: expect.any(BN),
lockedBalance: expect.any(BN),
reservedBalance: expect.any(BN),
vestedBalance: expect.any(BN),
votingBalance: expect.any(BN)
}));
done();
});
});
});
describe('fees', (): void => {
it('fees: It returns an object with all relevant fees of type BN', (done): void => {
api.derive.balances.fees().subscribe((fees: DerivedFees): void => {
expect(fees).toEqual(expect.objectContaining({
creationFee: expect.any(BN),
existentialDeposit: expect.any(BN),
transactionBaseFee: expect.any(BN),
transactionByteFee: expect.any(BN),
transferFee: expect.any(BN)
}));
done();
});
});
});
});
describe('derive.chain', (): void => {
describe('bestNumber', (): void => {
it('Get the latest block number', (done): void => {
api.derive.chain.bestNumber().subscribe((blockNumber: BlockNumber): void => {
expect(blockNumber instanceof ClassOf(registry, 'BlockNumber')).toBe(true);
expect(blockNumber.gten(0)).toBe(true);
done();
});
});
});
describe('bestNumberFinalized', (): void => {
it('Get the latest finalised block number', (done): void => {
api.derive.chain.bestNumberFinalized().subscribe((blockNumber: BlockNumber): void => {
expect(blockNumber instanceof ClassOf(registry, 'BlockNumber')).toBe(true);
expect(blockNumber.gten(0)).toBe(true);
done();
});
});
});
describe('bestNumberLag', (): void => {
it('lag between finalised head and best head', (done): void => {
api.derive.chain.bestNumberLag().subscribe((numberLag: BlockNumber): void => {
expect(numberLag instanceof ClassOf(registry, 'BlockNumber')).toBe(true);
expect(numberLag.gten(0)).toBe(true);
done();
});
});
});
// FIXME https://github.com/polkadot-js/api/issues/868
describe('getHeader', (): void => {
it('gets a specific block header and extended with it`s author', (done): void => {
api.derive.chain.getHeader('TODO').subscribe((headerExtended: HeaderExtended | undefined): void => {
// WIP
expect(headerExtended).toEqual(expect.arrayContaining([]));
done();
});
});
});
describe('subscribeNewHeads', (): void => {
it('gets an observable of the current block header and it\'s author', (done): void => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
api.derive.chain.subscribeNewHeads().subscribe((headerExtended: HeaderExtended): void => {
// WIP https://github.com/polkadot-js/api/issues/868
done();
});
});
});
});
describe('derive.contracts', (): void => {
describe('fees', (): void => {
it('fees: It returns an object with all relevant constract fees of type Balance', (done): void => {
api.derive.contracts.fees().subscribe((fees: DerivedContractFees): void => {
expect(fees).toEqual(expect.objectContaining({
callBaseFee: expect.any(BN),
contractFee: expect.any(BN),
createBaseFee: expect.any(BN),
creationFee: expect.any(BN),
rentByteFee: expect.any(BN),
rentDepositOffset: expect.any(BN),
tombstoneDeposit: expect.any(BN),
transactionBaseFee: expect.any(BN),
transactionByteFee: expect.any(BN),
transferFee: expect.any(BN)
}));
done();
});
});
});
});
describe('derive.elections', (): void => {
describe('info', (): void => {
it('It returns an object with all relevant elections properties', (done): void => {
api.derive.elections.info().subscribe((info: DerivedElectionsInfo): void => {
expect(info).toEqual(expect.objectContaining({
members: expect.anything(),
candidates: expect.anything(),
candidateCount: expect.any(BN),
desiredSeats: expect.any(BN),
termDuration: expect.any(BN),
voteCount: expect.any(BN)
}));
done();
});
});
});
});
describe('derive.session', (): void => {
describe('sessionProgress', (): void => {
it('derive.session.sessionProgress', (done): void => {
api.derive.session.sessionProgress().subscribe((progress: BN): void => {
expect(progress instanceof BN).toBe(true);
done();
});
});
});
describe('session.info', (): void => {
it('retrieves all session info', (done): void => {
api.derive.session.info().subscribe((info: DerivedSessionInfo): void => {
expect(info).toEqual(expect.objectContaining({
currentEra: expect.anything(),
currentIndex: expect.anything(),
eraLength: expect.anything(),
eraProgress: expect.anything(),
lastEraLengthChange: expect.anything(),
lastLengthChange: expect.anything(),
sessionLength: expect.anything(),
sessionsPerEra: expect.anything(),
sessionProgress: expect.anything()
}));
done();
});
});
});
describe('session.eraLength', (): void => {
it('derive.session.eraLength', (done): void => {
api.derive.session.eraLength().subscribe((length: BN): void => {
expect(length instanceof BN).toBe(true);
done();
});
});
});
describe('session.eraProgress', (): void => {
it('derive.session.eraProgress', (done): void => {
api.derive.session.eraProgress().subscribe((progress: BN): void => {
expect(progress instanceof BN).toBe(true);
done();
});
});
});
});
describe('derive.staking', (): void => {
describe('controllers', (): void => {
// @TODO https://github.com/polkadot-js/api/issues/868
});
});
});
@@ -1,59 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Extrinsic, SignedBlock } from '@polkadot/types/interfaces';
import WsProvider from '@polkadot/rpc-provider/ws';
import ApiPromise from '../../../src/promise';
import { describeE2E } from '../../util';
describeE2E({
only: [] // To run these tests locally you need to run a Alexander full archive node locally
})('Promise e2e alex archive queries (local)', (wsUrl: string): void => {
let api: ApiPromise;
beforeEach(async (done): Promise<void> => {
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
done();
});
// https://github.com/polkadot-js/api/issues/845
it('retrieves block with no issues', async (): Promise<boolean> => {
const metadata = await api.rpc.state.getMetadata('0x6f6f9bba0eed8e3ae9446c37eee763f93118b52a315a7b46090453ba6288da1f');
console.error(JSON.stringify(metadata, null, 2));
const block = await api.rpc.chain.getBlock('0x6f6f9bba0eed8e3ae9446c37eee763f93118b52a315a7b46090453ba6288da1f');
console.error(block);
expect(block).toBeDefined();
return true;
});
// https://github.com/polkadot-js/api/issues/846
it('handles toJSON with no issues', (done): Promise<() => void> => {
return api.rpc.chain.getBlock('0x85c62b581f38cb81c3e443d34392672beb1fb877017fd7237cc87704113259dc', (result: SignedBlock): void => {
const failed: Extrinsic[] = result.block.extrinsics.filter((extrinsic: Extrinsic): boolean => {
try {
const json = extrinsic.method.toJSON();
console.error(json);
return false;
} catch (error) {
console.log(extrinsic.method);
console.log(extrinsic.method.keys());
console.error(error);
return true;
}
});
expect(failed).toBeTruthy();
done();
});
});
});
@@ -1,89 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, EventRecord } from '@polkadot/types/interfaces';
import WsProvider from '@polkadot/rpc-provider/ws';
import { ClassOf, Option, TypeRegistry, Vec } from '@polkadot/types';
import ApiPromise from '../../../src/promise';
import { describeE2E } from '../../util';
describeE2E({
only: ['docker-polkadot-alexander', 'remote-polkadot-alexander']
})('Promise e2e alex queries', (wsUrl: string): void => {
const registry = new TypeRegistry();
let api: ApiPromise;
beforeEach(async (done): Promise<void> => {
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
done();
});
it('retrieves the list of validators', (done): Promise<() => void> => {
return (
api.query.staking.validators((res): void => {
console.error(res);
console.log('api.query.staking.validators():', res.toJSON());
done();
})
);
});
describe('retrieves a single value', (): void => {
it('retrieves the list of stash validators', (done): Promise<() => void> => {
return (
api.query.staking.validators('5DuiZFa184E9iCwbh4WjXYvJ88NHvWJbS8SARY8Ev1YEqrri', (res): void => {
console.error(res);
console.log('api.query.staking.validators(id):', res.toJSON());
done();
})
);
});
it('Gets the hash of the last finalized header', async (done): Promise<() => void> => {
return (
api.rpc.chain.getFinalizedHead((head): void => {
expect(head instanceof ClassOf(registry, 'Hash')).toBe(true);
done();
})
);
});
it('Subscribes to the best finalized header on ALEX', async (done): Promise<() => void> => {
return (
api.rpc.chain.subscribeFinalizedHeads((head): void => {
expect(head instanceof ClassOf(registry, 'Header')).toBe(true);
done();
})
);
});
});
it('derives a list of the controllers', (done): Promise<() => void> => {
return (
api.derive.staking.controllers((res: [AccountId[], Option<AccountId>[]]): void => {
console.log('api.derive.staking.controllers:', JSON.stringify(res));
done();
})
);
});
it('makes a query at a latest block (specified)', async (): Promise<void> => {
const header = await api.rpc.chain.getHeader();
const events = await api.query.system.events.at(header.hash);
expect(events.length).not.toEqual(0);
});
it('subscribes to events', (done): Promise<() => void> => {
return api.query.system.events((events: Vec<EventRecord>): void => {
expect(events).not.toHaveLength(0);
done();
});
});
});
@@ -1,35 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import WsProvider from '@polkadot/rpc-provider/ws';
import { ClassOf, TypeRegistry } from '@polkadot/types';
import ApiPromise from '../../../src/promise';
import { describeE2E } from '../../util';
describeE2E({
only: [
'local',
'docker-polkadot-master',
'docker-substrate-master',
'docker-substrate-2.0'
]
})('Promise e2e consts', (wsUrl: string): void => {
const registry = new TypeRegistry();
let api: ApiPromise;
beforeEach(async (done): Promise<void> => {
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
done();
});
it('democracy.cooloffPeriod parameter type', (): void => {
expect(api.consts.democracy.cooloffPeriod).toBeInstanceOf(ClassOf(registry, 'BlockNumber'));
expect(
api.consts.democracy.cooloffPeriod.eq(432000) || // Substrate
api.consts.democracy.cooloffPeriod.eq(259200) // Polkadot
).toBeTruthy();
});
});
@@ -1,117 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import fs from 'fs';
import path from 'path';
import { Abi } from '@polkadot/api-contract';
import testingPairs from '@polkadot/keyring/testingPairs';
import WsProvider from '@polkadot/rpc-provider/ws';
import { Address, Hash } from '@polkadot/types/interfaces';
import { ApiPromise, SubmittableResult } from '../../../src';
import { describeE2E } from '../../util';
// Backwards compatibility:
// A breaking change was introduced by substrate runtime spec version 97. https://github.com/paritytech/substrate/pull/2911/files
// The change had to be implemented in ink! which changed the structure of the Wasm files.
// The Polkadot JS API is only supporting srml-contracts module of substrate version greater or equal spec_version 97.
import incrementerAbi from '../../../../api-contract/test/contracts/Incrementer.json'; // eslint-disable-line
const incrementerCode = fs.readFileSync(path.join(__dirname, '../../../../api-contract/test/contracts/incrementer-pruned.wasm')).toString('hex'); // eslint-disable-line
describeE2E({
except: [
'docker-polkadot-master',
'docker-polkadot-alexander',
'docker-substrate-1.0',
'remote-polkadot-alexander',
'remote-substrate-1.0'
]
})('Promise e2e contracts', (wsUrl: string): void => {
let address: Address;
let codeHash: Hash;
const keyring = testingPairs({ type: 'sr25519' });
let api: ApiPromise;
let CREATION_FEE: number;
beforeEach(async (done): Promise<void> => {
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
CREATION_FEE = 123456789123456;
done();
});
describe('incrementer', (): void => {
const MAX_GAS = 50000;
let abi: Abi;
beforeEach((): void => {
abi = new Abi(api.registry, incrementerAbi);
});
it('allows putCode', (done): Promise<() => void> => {
return (
api.tx.contracts
.putCode(MAX_GAS, `0x${incrementerCode}`)
.signAndSend(keyring.eve, (result: SubmittableResult): void => {
if (result.status.isFinalized) {
const record = result.findRecord('contracts', 'CodeStored');
if (record) {
codeHash = record.event.data[0] as Hash;
done();
}
}
})
);
});
it('Verifies that codeHash is defined', (): void => {
expect(codeHash).toBeDefined();
});
it('allows contract create', (done): Promise<() => void> => {
// An instance of a contract can only be deployed once by one specific account.
// That's why we need a random starting point for our incrementer contract to be
// able to run this test multiple times without the need of pruning the database
const randomStart = Math.floor(Date.now() / 1000);
return (
api.tx.contracts
.create(CREATION_FEE, MAX_GAS, codeHash, abi.constructors[0](randomStart))
.signAndSend(keyring.dave, (result: SubmittableResult): void => {
// console.error('create', JSON.stringify(result));
if (result.status.isFinalized) {
const record = result.findRecord('contracts', 'Instantiated');
if (record) {
address = record.event.data[1] as Address;
done();
}
}
})
);
});
it('Verifies that the contract address is defined', (): void => {
expect(address).toBeDefined();
});
it('allows contract call', (done): Promise<() => void> => {
return (
api.tx.contracts
.call(address, CREATION_FEE, MAX_GAS, abi.messages.inc(3))
.signAndSend(keyring.bob, (result: SubmittableResult): void => {
console.error('call', JSON.stringify(result));
if (result.status.isFinalized && result.findRecord('system', 'ExtrinsicSuccess')) {
done();
}
})
);
});
});
});
@@ -1,25 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import WsProvider from '@polkadot/rpc-provider/ws';
import ApiPromise from '../../../src/promise';
import { describeE2E } from '../../util';
describeE2E({
only: ['remote-polkadot-kusama']
})('Promise e2e kusama queries', (wsUrl: string): void => {
let api: ApiPromise;
beforeEach(async (done): Promise<void> => {
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
done();
});
it('retrieves the list of validators', async (): Promise<void> => {
const intentions = await api.query.staking.validators();
console.error(JSON.parse(JSON.stringify(intentions)));
});
});
@@ -1,208 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Balance, Index } from '@polkadot/types/interfaces';
import BN from 'bn.js';
import { DerivedBalances } from '@polkadot/api-derive/types';
import testingPairs from '@polkadot/keyring/testingPairs';
import WsProvider from '@polkadot/rpc-provider/ws';
import { Option, u32, createType, TypeRegistry } from '@polkadot/types';
import ApiPromise from '../../../src/promise';
import { describeE2E } from '../../util';
const ZERO = new BN(0);
// The following tests require a development node with the default funded testing accounts
describeE2E({
except: [
'remote-polkadot-alexander',
'remote-substrate-1.0'
]
})('Promise e2e development queries', (wsUrl: string): void => {
const registry = new TypeRegistry();
let api: ApiPromise;
beforeEach(async (done): Promise<void> => {
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
done();
});
const keyring = testingPairs({ type: 'ed25519' });
it('allows retrieval of an fallback entry (once-off query)', async (): Promise<void> => {
const nonce = await api.query.system.accountNonce('5DSo5RVtfrtgHoz2c7jK7Tca7FgJgpCzFnxoRVDeYUQcKPng');
expect(nonce.toHex()).toEqual('0x0000000000000000');
});
it('allows retrieval of fallback when at query is made', async (): Promise<void> => {
const header = await api.rpc.chain.getHeader();
const nonce = await api.query.system.accountNonce.at(header.hash, '5DSo5RVtfrtgHoz2c7jK7Tca7FgJgpCzFnxoRVDeYUQcKPng');
expect(nonce.toHex()).toEqual('0x0000000000000000');
});
it('queries state for a balance', async (): Promise<() => void> => {
return api.query.balances.freeBalance(keyring.alice_stash.address, (balance: Balance): void => {
expect(balance).toBeInstanceOf(BN);
expect(balance.isZero()).toBe(false);
});
});
it('subscribes to queries', (done): Promise<() => void> => {
return (
api.query.system.accountNonce(keyring.ferdie.address, (nonce: Index): void => {
expect(nonce instanceof BN).toBe(true);
done();
})
);
});
it('subscribes to queries (default)', (done): Promise<() => void> => {
return (
api.query.staking.minimumValidatorCount((defaultCount: u32): void => {
expect(defaultCount.toNumber()).toBe(1);
done();
})
);
});
it('subscribes to multiple results (freeBalance.multi)', (done): Promise<() => void> => {
return (
api.query.balances.freeBalance.multi([
keyring.alice.address,
keyring.bob.address,
'5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y',
keyring.ferdie.address
], (balances): void => {
expect(balances).toHaveLength(4);
done();
})
);
});
it('subscribes to multiple results (api.queryMulti)', (done): Promise<() => void> => {
return api.queryMulti([
[api.query.balances.freeBalance, keyring.alice.address],
[api.query.balances.freeBalance, keyring.bob.address],
[api.query.balances.freeBalance, '5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y'],
[api.query.balances.freeBalance, keyring.ferdie.address]
], (balances: Balance[]): void => {
expect(balances).toHaveLength(4);
done();
});
});
it('subscribes to derived balances (balances.all)', (done): Promise<() => void> => {
return (
api.derive.balances.all(
keyring.bob_stash.address,
(all: DerivedBalances): void => {
expect(all.accountId.toString()).toEqual(keyring.bob_stash.address);
expect(all.freeBalance).toBeDefined();
expect(all.freeBalance.gt(ZERO)).toBe(true);
expect(all.availableBalance).toBeDefined();
expect(all.availableBalance.gt(ZERO)).toBe(true);
expect(all.reservedBalance).toBeDefined();
expect(all.lockedBalance).toBeDefined();
expect(all.vestedBalance).toBeDefined();
done();
}
)
);
});
describe('with map type', (): void => {
it('queries correct value', async (): Promise<void> => {
const balance = await api.query.balances.freeBalance(keyring.bob_stash.address);
expect(balance.isZero()).toBe(false);
});
it('queries correct value at a specified block', async (): Promise<void> => {
// assume the account Alice is only used in test(the balance of Alice does not change in this test case)
const balance = await api.query.balances.freeBalance(keyring.alice_stash.address);
const header = await api.rpc.chain.getHeader();
const balanceAt = await api.query.balances.freeBalance.at(header.hash, keyring.alice_stash.address);
expect(balanceAt.isZero()).toBe(false);
expect(balanceAt.toString()).toEqual(balance.toString());
});
it('subscribes to query and get correct result', async (done): Promise<() => void> => {
// assume the account Alice is only used in test(the balance of Alice does not change in this test case)
const balance = await api.query.balances.freeBalance(keyring.alice_stash.address);
return api.query.balances.freeBalance(keyring.alice_stash.address, (balanceSubscribed: Balance): void => {
expect(balanceSubscribed.isZero()).toBe(false);
expect(balanceSubscribed.toString()).toEqual(balance.toString());
done();
});
});
it('queries correct hash', async (): Promise<void> => {
const hash = await api.query.balances.freeBalance.hash(keyring.alice.address);
expect(hash).toBeDefined();
});
it('gets correct key', async (): Promise<void> => {
// assume the account Alice is only used in test(the balance of Alice does not change in this test case)
const key = api.query.balances.freeBalance.key(keyring.alice_stash.address);
const balanceData = await api.rpc.state.getStorage(key) as Option<any>;
const balanceRPC = createType(registry, 'Balance', balanceData.unwrapOr(undefined));
const balance = await api.query.balances.freeBalance(keyring.alice_stash.address);
expect(balanceRPC.isZero()).toBe(false);
expect(balanceRPC.toString()).toEqual(balance.toString());
});
it('queries multiple results', async (): Promise<void> => {
// assume the account Alice and Bob are only used in test(the balance of them do not change in this test case)
const balanceAlice = await api.query.balances.freeBalance(keyring.alice.address);
const balanceBob = await api.query.balances.freeBalance(keyring.bob.address);
const balances = await api.query.balances.freeBalance.multi([
keyring.alice.address,
keyring.bob.address
]);
expect(balances).toHaveLength(2);
expect((balances as any)[0].toString()).toEqual(balanceAlice.toString());
expect((balances as any)[1].toString()).toEqual(balanceBob.toString());
});
it('subscribes to multiple queries and get correct results', async (done): Promise<() => void> => {
// assume the account Alice and Bob are only used in test(the balance of them do not change in this test case)
const balanceAlice = await api.query.balances.freeBalance(keyring.alice.address);
const balanceBob = await api.query.balances.freeBalance(keyring.bob.address);
return api.query.balances.freeBalance.multi([
keyring.alice.address,
keyring.bob.address
], (balances): void => {
expect(balances).toHaveLength(2);
expect(balances[0].toString()).toEqual(balanceAlice.toString());
expect(balances[1].toString()).toEqual(balanceBob.toString());
done();
});
});
it('queries correct size', async (): Promise<void> => {
const size = await api.query.balances.freeBalance.size(keyring.alice_stash.address);
expect(size.toNumber()).not.toEqual(0);
});
});
});
@@ -1,149 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Keys } from '@polkadot/types/interfaces';
import testingPairs from '@polkadot/keyring/testingPairs';
import WsProvider from '@polkadot/rpc-provider/ws';
import { Option } from '@polkadot/types';
import { encodeAddress, randomAsU8a } from '@polkadot/util-crypto';
import ApiPromise from '../../../src/promise';
import { describeE2E } from '../../util';
// The following tests only run on nodes that support doubleMapType introduced by metadata v5
describeE2E({
only: [
'local',
'docker-polkadot-master',
'docker-substrate-master',
'docker-substrate-2.0'
]
})('Promise e2e doubleMap queries (since Metadata v5)', (wsUrl: string): void => {
let api: ApiPromise;
const keyring = testingPairs({ type: 'ed25519' });
beforeEach(async (done): Promise<void> => {
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
done();
});
// TODO Update ['any', '0x1234'] to the key of a known event topic and update EXPECTED_VALUE to the expected value
describe('with double map type', (): void => {
const KEY1 = 'any';
const KEY2 = '0x1234';
it('queries correct value', async (): Promise<void> => {
const eventTopics = await api.query.system.eventTopics(KEY1, KEY2);
expect(eventTopics.toJSON()).toEqual([]);
});
it('queries correct value at a specified block', async (): Promise<void> => {
const header = await api.rpc.chain.getHeader();
// TODO check & fix: this will throw the error: Encoding for input doesn't match output, created 0x00 from 0x
const eventTopicsAt = await api.query.system.eventTopics.at(header.hash, KEY1, KEY2);
expect(eventTopicsAt.toJSON()).toEqual([]);
// const eventTopicsAt = await api.query.system.eventTopics.at(header.hash, KEY1, KEY2);
// expect(eventTopicsAt.toJSON()).toEqual([]);
});
it('subscribes to query and get correct result', async (done): Promise<() => void> => {
return api.query.system.eventTopics(KEY1, KEY2, (eventTopicsAt): void => {
expect(eventTopicsAt.toJSON()).toEqual([]);
done();
});
});
it('queries correct hash', async (): Promise<void> => {
const hash = await api.query.system.eventTopics(KEY1, KEY2);
expect(hash).toBeDefined();
});
it('gets correct key', async (): Promise<void> => {
const key = api.query.system.eventTopics.key(KEY1, KEY2);
const eventTopicsData = await api.rpc.state.getStorage(key) as Option<any>;
expect(eventTopicsData.unwrapOr(undefined)).toEqual(undefined);
});
it('queries multiple results', async (): Promise<void> => {
const eventTopicsList = await api.query.system.eventTopics.multi([
[KEY1, KEY2]
]);
expect(eventTopicsList).toHaveLength(1);
expect((eventTopicsList as any)[0].toJSON()).toEqual([]);
});
it('subscribes to multiple queries and get correct results', async (done): Promise<() => void> => {
return api.query.system.eventTopics.multi([
[KEY1, KEY2]
], (eventTopicsList): void => {
expect(eventTopicsList).toHaveLength(1);
expect(eventTopicsList[0].toJSON()).toEqual([]);
done();
});
});
it('queries correct size', async (): Promise<void> => {
const size = await api.query.system.eventTopics.size(KEY1, KEY2);
expect(size.toNumber()).toEqual(0);
});
});
describe('session Keys', (): void => {
it('sets a session key, retrieves the value', (done): void => {
const babe = encodeAddress(randomAsU8a());
const grandpa = encodeAddress(randomAsU8a());
const imOnline = encodeAddress(randomAsU8a());
async function queryKeys (): Promise<void> {
console.error('*** query.session.nextKeys');
const result = JSON.stringify(
(await api.query.session.nextKeys<Keys>(
api.consts.session.dedupKeyPrefix,
keyring.bob.address
))
);
console.error(result, [grandpa, babe, imOnline]);
expect(result).toEqual(JSON.stringify([grandpa, babe, imOnline]));
done();
}
async function setKeys (): Promise<void> {
console.error('*** tx.session.setKeys');
await api.tx.session
.setKeys({ babe, grandpa, imOnline }, new Uint8Array([]))
.signAndSend(keyring.eve, (result): void => {
if (result.isCompleted) {
queryKeys();
}
});
}
async function setBond (): Promise<void> {
console.error('*** tx.staking.bond');
await api.tx.staking
.bond(keyring.eve.address, 123456789012345, 'Stash')
.signAndSend(keyring.bob, (result): void => {
if (result.isCompleted) {
setKeys();
}
});
}
setBond();
});
});
});
@@ -1,143 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { EventRecord, Hash, Header, SessionIndex } from '@polkadot/types/interfaces';
import { HeaderExtended } from '@polkadot/api-derive';
import WsProvider from '@polkadot/rpc-provider/ws';
import { LinkageResult } from '@polkadot/types/codec/Linkage';
import { Option } from '@polkadot/types';
import ApiPromise from '../../../src/promise';
import { describeE2E } from '../../util';
describeE2E()('Promise e2e queries', (wsUrl: string): void => {
let api: ApiPromise;
beforeEach(async (done): Promise<void> => {
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
done();
});
it('makes the runtime, rpc, state & extrinsics available', (): void => {
expect(api.genesisHash).toBeDefined();
expect(api.runtimeMetadata).toBeDefined();
expect(api.runtimeVersion).toBeDefined();
expect(api.rpc).toBeDefined();
expect(api.query).toBeDefined();
expect(api.tx).toBeDefined();
expect(api.derive).toBeDefined();
});
it('subscribes to rpc', (done): Promise<() => void> => {
return (
api.rpc.chain.subscribeNewHeads((header: Header): void => {
expect(header.number.isEmpty).toBe(false);
done();
})
);
});
it('subscribes to finalized', (done): Promise<() => void> => {
return (
api.rpc.chain.subscribeFinalizedHeads((header: Header): void => {
expect(header.number.isEmpty).toBe(false);
done();
})
);
});
it('subscribes to derive', (done): Promise<() => void> => {
return (
api.derive.chain.subscribeNewHeads((header: HeaderExtended): void => {
expect(header.number.isEmpty).toBe(false);
done();
})
);
});
it('subscribes to a linked map (staking.validators)', (done): Promise<() => void> => {
return (
api.query.staking.validators((prefs: LinkageResult): void => {
expect(prefs instanceof LinkageResult).toBe(true);
done();
})
);
});
it('can retrive header by hash', async (): Promise<void> => {
const latest = await api.rpc.chain.getHeader();
const specific = await api.rpc.chain.getHeader(latest.hash);
expect(latest.hash).toEqual(specific.hash);
});
it('makes a query at a latest block (specified)', async (): Promise<void> => {
const header = await api.rpc.chain.getHeader();
const events = await api.query.system.events.at(header.hash);
expect(events.length).not.toEqual(0);
events.forEach(({ event: { data, method, section }, phase, topics }: EventRecord): void => {
console.error(phase.toString(), `: ${section}.${method}`, data.toString(), topics.toString());
});
});
it('subscribes to events', (done): Promise<() => void> => {
return (
api.query.system.events((events): void => {
expect(events).not.toHaveLength(0);
done();
})
);
});
describe('with plain type', (): void => {
it('queries a correct value', async (): Promise<void> => {
const sessionIndex = await api.query.session.currentIndex();
expect(sessionIndex.toNumber()).toBeGreaterThanOrEqual(0);
});
it('queries correct value at a specified block', async (): Promise<void> => {
const header = await api.rpc.chain.getHeader();
const sessionIndex = await api.query.session.currentIndex.at(header.hash);
expect(sessionIndex.toNumber()).toBeGreaterThanOrEqual(0);
});
it('subscribes to query and get correct result', (done): Promise<() => void> => {
return api.query.session.currentIndex((sessionIndex: SessionIndex): void => {
expect(sessionIndex.toNumber()).toBeGreaterThanOrEqual(0);
done();
});
});
it('queries correct hash', async (): Promise<void> => {
const hash: Hash = await api.query.session.currentIndex.hash();
expect(hash).toBeDefined();
});
it('gets correct key', async (): Promise<void> => {
const key = api.query.session.currentIndex.key();
const sessionIndexData = await api.rpc.state.getStorage<Option<any>>(key);
const sessionIndexRPC = api.createType('SessionIndex', sessionIndexData.unwrapOr(undefined));
expect(sessionIndexRPC.toNumber()).toBeGreaterThanOrEqual(0);
});
it('queries correct size', async (): Promise<void> => {
const size = await api.query.session.currentIndex.size();
expect(size).not.toHaveLength(0);
expect(size.toNumber()).toBeGreaterThanOrEqual(0);
});
});
});
@@ -1,44 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import Keyring from '@polkadot/keyring';
import testingPairs from '@polkadot/keyring/testingPairs';
import WsProvider from '@polkadot/rpc-provider/ws';
import ApiPromise from '../../../src/promise';
import { describeE2E, calculateAccountDeposit, logEvents } from '../../util';
describeE2E({
except: ['remote-polkadot-alexander', 'remote-substrate-1.0']
})('Promise e2e transactions', (wsUrl: string): void => {
const keyring = testingPairs({ type: 'ed25519' });
let api: ApiPromise;
beforeEach(async (done): Promise<void> => {
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
done();
});
it('makes a transfer, and uses new balance to transfers to new', async (done): Promise<() => void> => {
const pair = new Keyring().addFromUri('testing123', {}, 'ed25519');
const amount = calculateAccountDeposit(api);
function doOne (cb: any): Promise<() => void> {
return api.tx.balances
.transfer(pair.address, amount)
.signAndSend(keyring.bob_stash, logEvents(cb));
}
async function doTwo (cb: any): Promise<() => void> {
return api.tx.balances
.transfer(keyring.bob_stash.address, 111)
.signAndSend(pair, logEvents(cb));
}
return doOne(async (): Promise<() => void> => {
return doTwo(done);
});
});
});
@@ -1,116 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import testingPairs from '@polkadot/keyring/testingPairs';
import WsProvider from '@polkadot/rpc-provider/ws';
import { Header } from '@polkadot/types/interfaces';
import { createType, TypeRegistry } from '@polkadot/types';
import ApiPromise from '../../../src/promise';
import { Signer } from '../../../src/types';
import { describeE2E, logEvents, SingleAccountSigner } from '../../util';
describeE2E({
except: [
'remote-polkadot-alexander',
'remote-substrate-1.0',
'docker-polkadot-alexander',
'docker-substrate-1.0'
]
})('Promise e2e transactions with specified eras', (wsUrl: string): void => {
const registry = new TypeRegistry();
const keyring = testingPairs({ type: 'ed25519' });
let api: ApiPromise;
beforeEach(async (done): Promise<void> => {
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
done();
});
describe('eras', (): void => {
it('makes a transfer (specified era)', async (done): Promise<void> => {
const signedBlock = await api.rpc.chain.getBlock();
const currentHeight = signedBlock.block.header.number;
const exERA = createType(registry, 'ExtrinsicEra', { current: currentHeight, period: 4 });
const ex = api.tx.balances.transfer(keyring.eve.address, 12345);
await ex.signAndSend(keyring.charlie, {
blockHash: signedBlock.block.header.hash,
era: exERA
}, logEvents(done));
});
it('makes a transfer (specified era, previous block)', async (done): Promise<void> => {
const signedBlock = await api.rpc.chain.getBlock();
const currentHeight = signedBlock.block.header.number.toBn().subn(1);
const exERA = createType(registry, 'ExtrinsicEra', { current: currentHeight, period: 10 });
const ex = api.tx.balances.transfer(keyring.eve.address, 12345);
await ex.signAndSend(keyring.charlie, {
blockHash: signedBlock.block.header.parentHash,
era: exERA
}, logEvents(done));
});
it('fails on a transfer with invalid time', async (done): Promise<void> => {
const nonce = await api.query.system.accountNonce(keyring.alice.address);
const signedBlock = await api.rpc.chain.getBlock();
const currentHeight = signedBlock.block.header.number;
const exERA = createType(registry, 'ExtrinsicEra', { current: currentHeight, period: 4 });
const eraDeath = exERA.asMortalEra.death(currentHeight.toNumber());
const blockHash = signedBlock.block.header.hash;
const ex = api.tx.balances.transfer(keyring.eve.address, 12345);
await api.rpc.chain.subscribeNewHeads(async (header: Header): Promise<void> => {
if (header.number.toNumber() === eraDeath - 1) {
try {
await ex.signAndSend(keyring.alice, { blockHash, era: exERA, nonce } as any);
} catch (error) {
// The "invalid-era" specific error code 127 was introduced along with the transaction version 2
// For the transaction format version 1 the error code is simply 0
expect(error.message).toMatch(
/1010: Invalid Transaction \(-127\)|1010: Invalid Transaction \(0\)/
);
}
done();
}
});
});
it('fails on a transfer with invalid time (via Signer)', async (done): Promise<void> => {
const signer: Signer = new SingleAccountSigner(registry, keyring.alice);
api.setSigner(signer);
const nonce = await api.query.system.accountNonce(keyring.bob_stash.address);
const signedBlock = await api.rpc.chain.getBlock();
const currentHeight = signedBlock.block.header.number;
const exERA = createType(registry, 'ExtrinsicEra', { current: currentHeight, period: 4 });
const eraDeath = exERA.asMortalEra.death(currentHeight.toNumber());
const blockHash = signedBlock.block.header.hash;
const ex = api.tx.balances.transfer(keyring.eve.address, 12121);
await api.rpc.chain.subscribeNewHeads(async (header: Header): Promise<void> => {
if (header.number.toNumber() === eraDeath - 1) {
try {
await ex.signAndSend(keyring.alice.address, { blockHash, era: exERA, nonce } as any);
} catch (error) {
// NOTE As per above 0 or -127 error code
expect(error.message).toMatch(
/1010: Invalid Transaction \(-127\)|1010: Invalid Transaction \(0\)/
);
}
done();
}
});
});
it('makes a transfer with custom numeric era', async (done): Promise<void> => {
await api.tx.balances
.transfer(keyring.eve.address, 12345)
.signAndSend(keyring.charlie, { era: 2 }, logEvents(done));
});
});
});
@@ -1,78 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import testingPairs from '@polkadot/keyring/testingPairs';
import WsProvider from '@polkadot/rpc-provider/ws';
import { TypeRegistry } from '@polkadot/types';
import ApiPromise from '../../../src/promise';
import { Signer } from '../../../src/types';
import { describeE2E, logEvents, SingleAccountSigner } from '../../util';
describeE2E({
except: ['remote-polkadot-alexander', 'remote-substrate-1.0']
})('Promise e2e transactions with Signer injection', (wsUrl: string): void => {
const registry = new TypeRegistry();
const keyring = testingPairs({ type: 'ed25519' });
let api: ApiPromise;
beforeEach(async (done): Promise<void> => {
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
done();
});
describe('Signer injection', (): void => {
it('makes a transfer (signAndSend via Signer)', async (done): Promise<void> => {
const signer = new SingleAccountSigner(registry, keyring.bob_stash);
api.setSigner(signer);
await api.tx.balances
.transfer(keyring.eve.address, 12345)
.signAndSend(keyring.bob_stash.address, logEvents(done));
});
it('succeeds when waiting some blocks before submission', async (done): Promise<void> => {
// 10 second delay
const signer = new SingleAccountSigner(registry, keyring.bob_stash, 10000);
api.setSigner(signer);
await api.tx.balances
.transfer(keyring.eve.address, 12345)
.signAndSend(keyring.bob_stash.address, logEvents(done));
});
it('fails (signAndSend via Signer) with undefined Signer', async (): Promise<void> => {
const signer: any = undefined;
// no signer
api.setSigner(signer);
await expect(api.tx.balances
.transfer(keyring.eve.address, 12345)
.signAndSend(keyring.alice.address)).rejects.toThrow('no signer exists');
});
it('fails (signAndSend via Signer) with the wrong keyring pair', async (): Promise<void> => {
const signer: Signer = new SingleAccountSigner(registry, keyring.dave);
api.setSigner(signer);
// no callback
await expect(api.tx.balances
.transfer(keyring.eve.address, 12345)
.signAndSend(keyring.alice.address)).rejects.toThrow('does not have the keyringPair');
});
it('fails (signAndSend via Signer) with the wrong keyring pair with a callback', async (): Promise<void> => {
// with callback
await expect(api.tx.balances
.transfer(keyring.eve.address, 12345)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.signAndSend(keyring.alice.address, (cb: any): void => { /* do nothing */ }))
.rejects.toThrow('no signer exists');
});
});
});
@@ -1,102 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import testingPairs from '@polkadot/keyring/testingPairs';
import WsProvider from '@polkadot/rpc-provider/ws';
import { randomAsHex } from '@polkadot/util-crypto';
import { u8aToHex } from '@polkadot/util';
import ApiPromise from '../../../src/promise';
import randomAsHex2097152 from '../../mock-data/randomAsHex_2097152';
import { calculateAccountDeposit, describeE2E, logEvents } from '../../util';
describeE2E({
except: ['remote-polkadot-alexander', 'remote-substrate-1.0']
})('Promise e2e transactions', (wsUrl: string): void => {
const keyring = testingPairs({ type: 'ed25519' });
let api: ApiPromise;
beforeEach(async (done): Promise<void> => {
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
done();
});
it('can submit an extrinsic from hex', async (done): Promise<() => void> => {
const nonce = await api.query.system.accountNonce(keyring.bob_stash.address);
const hex = api.tx.balances
.transfer(keyring.eve.address, 12345)
.sign(keyring.bob_stash, { nonce })
.toHex();
return api.tx(hex).send(logEvents(done));
});
it('invalid hex does throw a catchable exception', async (done): Promise<void> => {
const nonce = await api.query.system.accountNonce(keyring.bob_stash.address);
const hex = api.tx.balances
.transfer(keyring.eve.address, 12345)
.sign(keyring.bob_stash, { nonce })
.toHex();
// change to an invalid signature, 32 * 2 for hex
const sigIdx = hex.indexOf(u8aToHex(keyring.bob_stash.publicKey).substr(2)) + 64;
const mangled = hex.replace(
hex.substr(sigIdx, 32), // first 16 bytes of sig
hex.substr(2, 32) // replaced by first 16 bytes of tx
);
try {
await api.tx(mangled).send(logEvents(done));
} catch (error) {
console.error(error);
done();
}
});
it('makes a transfer (sign, then send)', async (done): Promise<() => void> => {
const nonce = await api.query.system.accountNonce(keyring.bob_stash.address);
return api.tx.balances
.transfer(keyring.eve.address, 12345)
.sign(keyring.bob_stash, { nonce })
.send(logEvents(done));
});
it('makes a transfer (sign, then send - compat version)', async (done): Promise<() => void> => {
const nonce = await api.query.system.accountNonce(keyring.bob_stash.address);
return api.tx.balances
.transfer(keyring.eve.address, 12345)
.sign(keyring.bob_stash, { nonce })
.send(logEvents(done));
});
it('makes a transfer (signAndSend, immortal)', async (done): Promise<() => void> => {
return api.tx.balances
.transfer(keyring.eve.address, 12345)
.signAndSend(keyring.bob_stash, { era: 0 }, logEvents(done));
});
it('makes a transfer (no callback)', async (): Promise<void> => {
const hash = await api.tx.balances
.transfer(keyring.eve.address, 12345)
.signAndSend(keyring.bob_stash);
expect(hash.toHex()).toHaveLength(66);
});
it('makes a proposal', async (done): Promise<void> => {
// don't wait for status, just get hash. Here we generate a large-ish payload
// to ensure that we can sign with the hashed version as well (and have it accepted)
const amount = calculateAccountDeposit(api);
await api.tx.democracy
.propose(
api.tx.system && api.tx.system.setCode
? api.tx.system.setCode(randomAsHex2097152) // since impl_version 94 https://github.com/paritytech/substrate/pull/2802
: api.tx.consensus.setCode(randomAsHex(4096)) // impl_version 0 - 93
, amount)
.signAndSend(keyring.bob_stash, logEvents(done));
});
});
@@ -1,35 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import BN from 'bn.js';
import testingPairs from '@polkadot/keyring/testingPairs';
import WsProvider from '@polkadot/rpc-provider/ws';
import ApiRx from '../../../src/rx';
import { describeE2E } from '../../util';
describeE2E({
except: [
'remote-polkadot-alexander',
'remote-substrate-1.0'
]
})('Rx e2e queries', (wsUrl: string): void => {
const keyring = testingPairs({ type: 'ed25519' });
let api: ApiRx;
beforeEach(async (done): Promise<void> => {
api = await ApiRx.create({ provider: new WsProvider(wsUrl) }).toPromise();
done();
});
it('queries state for a balance', (done): void => {
api.query.balances.freeBalance(keyring.alice_stash.address).subscribe((balance): void => {
expect(balance).toBeInstanceOf(BN);
expect(balance.isZero()).toBe(false);
done();
});
});
});
@@ -1,46 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Header } from '@polkadot/types/interfaces';
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import WsProvider from '@polkadot/rpc-provider/ws';
import ApiRx from '../../../src/rx';
import { describeE2E } from '../../util';
describeE2E()('Rx e2e queries', (wsUrl: string): void => {
let api: ApiRx;
beforeEach(async (done): Promise<void> => {
api = await ApiRx.create({ provider: new WsProvider(wsUrl) }).toPromise();
done();
});
it('makes the runtime, rpc, state & extrinsics available', (): void => {
expect(api.genesisHash).toBeDefined();
expect(api.runtimeMetadata).toBeDefined();
expect(api.runtimeVersion).toBeDefined();
expect(api.rpc).toBeDefined();
expect(api.query).toBeDefined();
expect(api.tx).toBeDefined();
expect(api.derive).toBeDefined();
});
it('makes a query at a specific block', (done): void => {
api.rpc.chain
.getHeader()
.pipe(
switchMap(({ hash }: Header): Observable<any> =>
api.query.system.events.at(hash)
)
)
.subscribe((events: any): void => {
expect(events.length).not.toEqual(0);
done();
});
});
});
-71
View File
@@ -1,71 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Index } from '@polkadot/types/interfaces';
import { Observable } from 'rxjs';
import { first, switchMap } from 'rxjs/operators';
import testingPairs from '@polkadot/keyring/testingPairs';
import WsProvider from '@polkadot/rpc-provider/ws';
import { randomAsHex } from '@polkadot/util-crypto';
import ApiRx from '../../../src/rx';
import { SubmittableResult } from '../../../src';
import randomAsHex2097152 from '../../mock-data/randomAsHex_2097152';
import { calculateAccountDeposit, describeE2E } from '../../util';
describeE2E()('Rx e2e transactions', (wsUrl: string): void => {
const keyring = testingPairs({ type: 'ed25519' });
let api: ApiRx;
beforeEach(async (done): Promise<void> => {
api = await ApiRx.create({ provider: new WsProvider(wsUrl) }).toPromise();
done();
});
it('makes a transfer', (done): void => {
api.query.system
.accountNonce<Index>(keyring.bob_stash.address)
.pipe(
first(),
switchMap((nonce: Index): Observable<SubmittableResult> =>
api.tx.balances
.transfer(keyring.bob.address, 12345)
.sign(keyring.bob_stash, { nonce })
.send()
)
)
.subscribe(({ status }: SubmittableResult): void => {
if (status.isFinalized) {
done();
}
});
});
it('makes a proposal', (done): void => {
const amount = calculateAccountDeposit(api);
const proposal = api.tx.system && api.tx.system.setCode
? api.tx.system.setCode(randomAsHex2097152) // since impl_version 94 https://github.com/paritytech/substrate/pull/2802
: api.tx.consensus.setCode(randomAsHex(4096)); // impl_version 0 - 93
api.query.system
.accountNonce<Index>(keyring.bob_stash.address)
.pipe(
first(),
switchMap((nonce: Index): Observable<SubmittableResult> =>
api.tx.democracy
.propose(proposal, amount)
.sign(keyring.bob_stash, { nonce })
.send()
)
)
.subscribe(({ status }: SubmittableResult): void => {
if (status.isFinalized) {
done();
}
});
});
});
@@ -1,70 +0,0 @@
// Copyright 2017-2020 @polkadot/rpc-core 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, Index, SignedBlock } from '@polkadot/types/interfaces';
import Metadata from '@polkadot/metadata/Decorated';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import WsProvider from '@polkadot/rpc-provider/ws';
import { ClassOf, TypeRegistry } from '@polkadot/types';
import Rpc from '@polkadot/rpc-core';
import { describeE2E } from '../../util';
const randomAccount = '5HTqyWJHAVUieZnpb1V8gK4T1E4mnhkrUVSSzWBQd6kYgsVJ';
describeE2E({
only: [
'remote-polkadot-alexander',
'docker-polkadot-alexander'
]
})('e2e Alexander - Polkadot', (wsUrl: string): void => {
const registry = new TypeRegistry();
const metadata = new Metadata(registry, rpcMetadata);
let rpc: Rpc;
beforeEach((): void => {
rpc = new Rpc(registry, new WsProvider(wsUrl));
});
it('subscribes to storage', (done): void => {
rpc.state
.subscribeStorage<[BlockNumber, Index]>([
[metadata.query.system.accountNonce, randomAccount],
[metadata.query.session.currentIndex]
])
.subscribe((data): void => {
expect(data).toHaveLength(2);
expect(data).toEqual(
expect.arrayContaining([
expect.any(ClassOf(registry, 'Index')),
expect.any(ClassOf(registry, 'Index'))
])
);
done();
});
});
it('retrieves a block by hash (krumme lanke #1)', (done): void => {
rpc.chain
.getBlock('0x627847bffdf5f3e01ac440d057dec6a37a12a6f329db7ef8367665574b76b5df')
.subscribe((block: SignedBlock): void => {
expect(block).toBeDefined();
expect(block).toBeInstanceOf(ClassOf(registry, 'SignedBlock'));
done();
});
});
it('retrieves a block by hash (krumme lanke #2)', (done): void => {
rpc.chain
.getBlock('0x53416d53a4b1dfcae9165a89d193608e4aa770414f02267f5b2c4015a2e66091')
.subscribe((block: SignedBlock): void => {
expect(block).toBeDefined();
expect(block).toBeInstanceOf(ClassOf(registry, 'SignedBlock'));
done();
});
});
});
@@ -1,44 +0,0 @@
// Copyright 2017-2020 @polkadot/rpc-core 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 { ChainProperties, Extrinsic } from '@polkadot/types/interfaces';
import { ClassOf, TypeRegistry, Vec } from '@polkadot/types';
import WsProvider from '@polkadot/rpc-provider/ws';
import Rpc from '@polkadot/rpc-core';
import { describeE2E } from '../../util';
describeE2E({
except: [
'remote-polkadot-alexander',
'remote-substrate-1.0'
]
})('RPC-core e2e basics', (wsUrl: string): void => {
const registry = new TypeRegistry();
let rpc: Rpc;
beforeEach((): void => {
jest.setTimeout(30000);
rpc = new Rpc(registry, new WsProvider(wsUrl));
});
it('retrieves the pending extrinsics', (done): void => {
rpc.author
.pendingExtrinsics()
.subscribe((extrinsics: Vec<Extrinsic>): void => {
expect(extrinsics).toBeInstanceOf(Vec);
done();
});
});
it('retrieves the system properties', (done): void => {
rpc.system
.properties()
.subscribe((properties: ChainProperties): void => {
expect(properties).toBeInstanceOf(ClassOf(registry, 'ChainProperties'));
done();
});
});
});
@@ -1,40 +0,0 @@
// Copyright 2017-2020 @polkadot/rpc-core 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 } from '@polkadot/types/interfaces';
import { ClassOf, TypeRegistry } from '@polkadot/types';
import WsProvider from '@polkadot/rpc-provider/ws';
import Rpc from '@polkadot/rpc-core';
import { describeE2E } from '../../util';
describeE2E({
except: [
'remote-polkadot-alexander',
'remote-substrate-1.0'
]
})('RPC-core e2e chain', (wsUrl: string): void => {
const registry = new TypeRegistry();
let rpc: Rpc;
beforeEach((): void => {
jest.setTimeout(30000);
rpc = new Rpc(registry, new WsProvider(wsUrl));
});
it('subscribes via subscribeNewHeads', (done): void => {
let count = 0;
rpc.chain
.subscribeNewHeads()
.subscribe((header: Header): void => {
expect(header).toBeInstanceOf(ClassOf(registry, 'Header'));
if (++count === 3) {
done();
}
});
});
});
@@ -1,151 +0,0 @@
// Copyright 2017-2020 @polkadot/rpc-core 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 } from '@polkadot/types/interfaces';
import BN from 'bn.js';
import fs from 'fs';
import path from 'path';
import { ApiPromise, SubmittableResult } from '@polkadot/api';
import { Abi } from '@polkadot/api-contract';
import testingPairs from '@polkadot/keyring/testingPairs';
import { KeyringPair } from '@polkadot/keyring/types';
import Rpc from '@polkadot/rpc-core';
import WsProvider from '@polkadot/rpc-provider/ws';
import { H256, StorageData, StorageKey, TypeRegistry } from '@polkadot/types';
import { hexToBn, isInstanceOf } from '@polkadot/util';
import { describeE2E } from '../../util';
// Backwards compatibility:
// A breaking change was introduced by substrate runtime spec version 97. https://github.com/paritytech/substrate/pull/2911/files
// The change had to be implemented in ink! which changed the structure of the Wasm files.
// The Polkadot JS API is only supporting INK! versions that are working with substrate greater or equal to spec_version 97.
import incrementerAbi from '../../../../api-contract/test/contracts/Incrementer.json';
const incrementerCode = fs.readFileSync(path.join(__dirname, '../../../../api-contract/test/contracts/incrementer-pruned.wasm')).toString('hex');
const CHILD_STORAGE = '0x3a6368696c645f73746f726167653a'; // :child_storage:
describeE2E({
except: [
'docker-polkadot-master',
'docker-polkadot-alexander',
'docker-substrate-1.0',
'remote-polkadot-alexander',
'remote-substrate-1.0'
]
})('RPC-core e2e child-storage', (wsUrl: string): void => {
const MAX_GAS = 50000;
const registry = new TypeRegistry();
const keyring: Record<string, KeyringPair> = testingPairs({ type: 'sr25519' });
const randomStart = Math.floor(Date.now() / 1000);
let abi: Abi;
let api: ApiPromise;
let codeHash: Hash;
let rpc: Rpc;
beforeAll(async (done): Promise<() => void> => {
abi = new Abi(registry, incrementerAbi);
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
return (
api.tx.contracts
.putCode(MAX_GAS, `0x${incrementerCode}`)
.signAndSend(keyring.eve, (result: SubmittableResult): void => {
if (result.status.isFinalized) {
const record = result.findRecord('contracts', 'CodeStored');
if (record) {
codeHash = record.event.data[0] as Hash;
done();
}
}
})
);
});
beforeEach((done): void => {
rpc = new Rpc(registry, new WsProvider(wsUrl));
done();
});
// `child_storage` is currently not used anywhere in Polkadot or Substrate, that's why we need to
// add a Smart Contract that is using `child_storage` before being able to test it.
// @TODO Add tests for Polkadot once child storage is being used there.
describe('e2e state child methods', (): void => {
beforeAll(async (done): Promise<() => void> => {
abi = new Abi(registry, incrementerAbi);
api = await ApiPromise.create({ provider: new WsProvider(wsUrl) });
// An instance of a contract can only be deployed once by one specific account.
// That's why we need a random starting point for our incrementer contract to be
// able to run this test multiple times without the need of pruning the database
const CREATION_FEE = api.consts && api.consts.contracts
? 123456789123456
: 12345;
return (
api.tx.contracts
.create(CREATION_FEE, MAX_GAS, codeHash, abi.constructors[0](randomStart))
.signAndSend(keyring.dave, (result: SubmittableResult): void => {
if (result.status.isFinalized) {
const record = result.findRecord('contracts', 'Instantiated');
if (record) {
done();
}
}
})
);
});
it('getChildKeys(): retrieves :child_storage: keys for one deployed incrementer contract', async (done):
Promise<void> => {
const storageKeys = await rpc.state.getKeys(CHILD_STORAGE).toPromise();
rpc.state
.getChildKeys(storageKeys[0], '0x')
.subscribe((keys: StorageKey[]): void => {
expect(keys.length).toBeGreaterThanOrEqual(1);
done();
});
});
it('getChildStorage(): retrieves the default value of the incrementer smart contract', async (done): Promise<void> => {
const storageKeys = await rpc.state.getKeys(CHILD_STORAGE).toPromise();
const childStorageKeys = await rpc.state.getChildKeys(storageKeys[0], '0x').toPromise();
rpc.state
.getChildStorage(storageKeys[0], childStorageKeys[0])
.subscribe((storage: StorageData): void => {
const storageValue = hexToBn(storage.toHex(), { isLe: true });
expect(storageValue).toBeInstanceOf(BN);
expect(storageValue.toNumber()).toBeGreaterThan(1500000000);
done();
});
});
it('getChildStorageHash(): retrieves the Hash of the incrementer smart contract', async (done): Promise<void> => {
const storageKeys = await rpc.state.getKeys(CHILD_STORAGE).toPromise();
const childStorageKeys = await rpc.state.getChildKeys(storageKeys[0].toHex(), '0x').toPromise();
rpc.state
.getChildStorageHash(storageKeys[0], childStorageKeys[0])
.subscribe((storage: StorageData): void => {
expect(isInstanceOf(storage, H256)).toBeTruthy();
done();
});
});
it('getChildStorageSize(): retrieves the size of the incrementer smart contract', async (done): Promise<void> => {
const storageKeys = await rpc.state.getKeys(CHILD_STORAGE).toPromise();
const childStorageKeys = await rpc.state.getChildKeys(storageKeys[0], '0x').toPromise();
rpc.state
.getChildStorageSize(storageKeys[0], childStorageKeys[0])
.subscribe((storage): void => {
expect(storage.toString()).toBe('4');
done();
});
});
});
});
@@ -1,117 +0,0 @@
// Copyright 2017-2020 @polkadot/rpc-core 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 { Balance, Moment, RuntimeVersion } from '@polkadot/types/interfaces';
import DecorateMeta from '@polkadot/metadata/Decorated';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import Rpc from '@polkadot/rpc-core';
import WsProvider from '@polkadot/rpc-provider/ws';
import { Bytes, ClassOf, Metadata, StorageKey, TypeRegistry } from '@polkadot/types';
import { describeE2E } from '../../util';
const BOB_STASH = '5HpG9w8EBLe5XCrbczpwq5TSXvedjrBGCwqxK1iQ7qUsSWFc';
const CODE = '0x3a636f6465'; // :code
const registry = new TypeRegistry();
const metadata = new DecorateMeta(registry, rpcMetadata);
describeE2E({
except: [
'remote-polkadot-alexander',
'remote-substrate-1.0'
]
})('RPC-core e2e state', (wsUrl: string): void => {
let rpc: Rpc;
beforeEach((): void => {
jest.setTimeout(30000);
rpc = new Rpc(registry, new WsProvider(wsUrl));
});
it('getMetadata(): retrieves the wasm metadata', (done): void => {
rpc.state
.getMetadata()
.subscribe((meta: Metadata): void => {
expect(meta).toBeDefined();
expect(meta).toBeInstanceOf(Metadata);
done();
});
});
it('getKeys(): retrieves storage keys for ":code"', (done): void => {
rpc.state
.getKeys(CODE)
.subscribe((keys: StorageKey[]): void => {
expect(keys.length).toEqual(1);
done();
});
});
it('retrieves the runtime version', (done): void => {
rpc.state
.getRuntimeVersion()
.subscribe((version: RuntimeVersion): void => {
expect(version).toBeInstanceOf(ClassOf(registry, 'RuntimeVersion'));
done();
});
});
describe('test-suite getStorage()', (): void => {
it('retrieves code', (done): void => {
rpc.state
.getStorage<Bytes>([
metadata.query.substrate.code
])
.subscribe((code: Bytes): void => {
expect(code).toBeDefined();
expect(code).toBeInstanceOf(Bytes);
done();
});
});
it('retrieves balances', (done): void => {
rpc.state
.getStorage<Balance>([
metadata.query.balances.freeBalance, BOB_STASH
])
.subscribe((balance): void => {
expect(balance.isZero()).not.toEqual(true);
done();
});
});
it('retrieves timestamp', (done): void => {
rpc.state
.getStorage<Moment>([
metadata.query.timestamp.now
])
.subscribe((moment: Moment): void => {
expect(moment.toNumber()).not.toEqual(0);
done();
});
});
it('accepts StorageKey as input type', async (done): Promise<void> => {
// get storage keys for ':code' storage
const keys = await rpc.state.getKeys('0x3a636f6465').toPromise();
const key = keys[0];
const storageHash = await rpc.state.getStorageHash(key, '0x').toPromise();
expect(storageHash).toBeDefined();
done();
});
it('accepts a hex value as input type', async (done): Promise<void> => {
// get storage keys for ':code' storage
const keys = await rpc.state.getKeys('0x3a636f6465').toPromise();
const key = keys[0].toHex();
const storageHash = await rpc.state.getStorageHash(key, '0x').toPromise();
expect(storageHash).toBeDefined();
done();
});
});
});
@@ -1,64 +0,0 @@
// Copyright 2017-2020 @polkadot/rpc-core 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 Metadata from '@polkadot/metadata/Decorated';
import rpcMetadata from '@polkadot/metadata/Metadata/static';
import testingPairs from '@polkadot/keyring/testingPairs';
import WsProvider from '@polkadot/rpc-provider/ws';
import Rpc from '@polkadot/rpc-core';
import { Index, Moment, SessionIndex } from '@polkadot/types/interfaces';
import { ClassOf, TypeRegistry } from '@polkadot/types';
import { describeE2E } from '../../util';
const registry = new TypeRegistry();
const metadata = new Metadata(registry, rpcMetadata);
describeE2E({
except: [
'remote-polkadot-alexander',
'remote-substrate-1.0'
]
})('RPC-core e2e subscriptions', (wsUrl: string): void => {
let rpc: Rpc;
const keyring = testingPairs({ type: 'ed25519' });
beforeEach((): void => {
jest.setTimeout(30000);
rpc = new Rpc(registry, new WsProvider(wsUrl));
});
it('subscribes to storage', (done): void => {
rpc.state
.subscribeStorage<[Index, SessionIndex]>([
[metadata.query.system.accountNonce, keyring.eve.address],
[metadata.query.session.currentIndex]
])
.subscribe((data): void => {
expect(data).toHaveLength(2);
expect(data).toEqual(
expect.arrayContaining([
expect.any(ClassOf(registry, 'Index')),
expect.any(ClassOf(registry, 'Index'))
])
);
done();
});
});
it('retrieves current timestamp', (done): void => {
let count = 0;
rpc.state
.subscribeStorage<Moment>([[metadata.query.timestamp.now]])
.subscribe((data): void => {
expect(data).toBeDefined();
if (++count === 3) {
done();
}
});
});
});
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long

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