Compare commits

...
84 Commits
Author SHA1 Message Date
Github Actions cb791d3963 [CI Skip] release/stable 2.5.1
skip-checks: true
2020-11-02 11:30:30 +00:00
Jaco Greeff bc49e75e61 CHANGELOG for 2.5.1 2020-11-02 12:22:24 +01:00
Jaco Greeff 67f8dcafdb 2.5 (#2813) 2020-11-02 11:45:57 +01:00
Github Actions e95117839b [CI Skip] release/beta 2.4.2-20
skip-checks: true
2020-10-31 12:27:54 +00:00
Jaco Greeff 9f60a8cd5f Add decoded contract events to execution (#2812)
* Cleanup assignments

* Small adjustments

* Add decoded contract events to execution

* Adjust all applyOnEvent
2020-10-31 13:19:57 +01:00
Github Actions e23fae86d5 [CI Skip] release/beta 2.4.2-19
skip-checks: true
2020-10-31 11:58:34 +00:00
Jaco Greeff 94a4594d32 Cleanup assignments (#2811)
* Cleanup assignments

* Small adjustments

* Cleanup AnyJson results

* Event toHuman
2020-10-31 12:50:44 +01:00
Github Actions 5be8ef8f0d [CI Skip] release/beta 2.4.2-18
skip-checks: true
2020-10-31 10:25:53 +00:00
Jaco Greeff e855d5a9d4 Cater for new/old contracts_call results (#2810)
* Cater for new/old contracts_call results

* Update packages/types/src/interfaces/contracts/definitions.ts

* Allow RPC layer to output JSON

* Typing for json outputs

* Convert results

* RPC compat mapping

* Ensure RPC .json is exposed

* Remove compat layer

* Old error detection

* Map to unknown

* Update packages/rpc-core/src/index.ts

* linting
2020-10-31 11:18:58 +01:00
Github Actions 2a0e481710 [CI Skip] release/beta 2.4.2-17
skip-checks: true
2020-10-30 13:37:09 +00:00
Jaco Greeff 161c121cb2 Cleanups for maintainability (#2809)
* Cleanups for maintainability

* Split referendumsInfo

* Extract didUpdate -> bool

* Era filtering

* Default to council

* Points cache

* Remove cache

* Move map arg
2020-10-30 14:28:38 +01:00
Github Actions de38735498 [CI Skip] release/beta 2.4.2-16
skip-checks: true
2020-10-30 11:17:23 +00:00
Jaco Greeff ce1e6615e3 Add derive for single council proposal (#2808) 2020-10-30 12:09:12 +01:00
Github Actions 3ebe9f5243 [CI Skip] release/beta 2.4.2-15
skip-checks: true
2020-10-30 09:54:52 +00:00
Jaco Greeff f686cfcce7 Cleanup always primitive (caters for solang) (#2807)
* Cleanup always primitive (caters for solang)

* Compare (with primitive)
2020-10-30 10:47:18 +01:00
Github Actions c27e49c6f5 [CI Skip] release/beta 2.4.2-14
skip-checks: true
2020-10-30 09:25:37 +00:00
Jaco Greeff 5c69f78676 Expand Call errors with actual callIndex info (#2806)
* Expand Call errors with actutl callIndex info

* Update test expectation

* casing
2020-10-30 10:17:19 +01:00
Github Actions 8f00351405 [CI Skip] release/beta 2.4.2-13
skip-checks: true
2020-10-29 16:25:25 +00:00
Jaco Greeff 1f6c8c2eb8 Use assertReturn to cleanup (#2804)
* Use assertReturn to cleanup

* Remove Uint/Int duplication

* Adjust

* ws errors, part 2

* .

* Adj. manual

* adj

* switchMap

* Revert "switchMap"

This reverts commit edfa4a2258f09042b61a27fd3812f0c53039fe4f.

* Revert.

* Revert.

* protected constructor

* Correct isHexJson flag

* Remove isHexJson (always detect)

* Adjust

* Flags
2020-10-29 17:17:22 +01:00
Github Actions 9bb1343255 [CI Skip] release/beta 2.4.2-12
skip-checks: true
2020-10-29 13:27:28 +00:00
Jaco Greeff 94ebb321f1 Complexity adjustments (#2803)
* Complexity adjustments

* cleanups

* Small cleanups

* Additional

* revert era

* ExtrinsicEra
2020-10-29 14:20:10 +01:00
Github Actions 63fd5baa8f [CI Skip] release/beta 2.4.2-11
skip-checks: true
2020-10-29 11:08:09 +00:00
Jaco Greeff ea3ee428d8 Rework asLatest update (#2802)
* Revert "[CI Skip] release/beta 2.4.2-10"

This reverts commit 5cb1c2d33a.

* Revert "Use asLatest in metadata extraction (#2800)"

This reverts commit 600666de1c.

* Bumps

* Expansion

* Flatten

* Metadata class imports

* Cleanup Decorate exports

* Move Metadata to top-level

* Swap logger on ABI

* Adjust imports

* Cleanups

* Updates
2020-10-29 11:59:37 +01:00
Github Actions 5cb1c2d33a [CI Skip] release/beta 2.4.2-10
skip-checks: true
2020-10-29 08:13:14 +00:00
Jaco Greeff 600666de1c Use asLatest in metadata extraction (#2800)
* User asLatest in metadata extraction

* Cleanup Decorated, bump

* linting

* cleanup decorate

* Remove registry arg from Decorated
2020-10-29 09:05:53 +01:00
Github Actions 524885e8de [CI Skip] release/beta 2.4.2-9
skip-checks: true
2020-10-28 13:37:25 +00:00
Jaco Greeff 1476e5e5e9 Bump common, string* with String (#2799)
* Bump common, string* with String

* Linting, TS 4.0.5
2020-10-28 14:28:49 +01:00
Github Actions 3f48b3c29f [CI Skip] release/beta 2.4.2-8
skip-checks: true
2020-10-28 12:34:15 +00:00
Jaco Greeff 9debb854f9 syncState RPCs (#2797)
* syncState RPCs

* Use endpoint override as available

* Allow Json construction, update syncstate_get def
2020-10-28 13:26:37 +01:00
Github Actions db3fe7d103 [CI Skip] release/beta 2.4.2-7
skip-checks: true
2020-10-28 09:40:45 +00:00
Jaco Greeff a93063c6fb Know-types for Rococo v1 (#2795) 2020-10-28 10:31:32 +01:00
Github Actions 8e4bbd2b23 [CI Skip] release/beta 2.4.2-6
skip-checks: true
2020-10-27 14:27:45 +00:00
Jaco Greeff cf1c2ea58a Add dryRun capability on Submittable (#2793)
* Add dryRun capability on Submittable

* Ordering, add to interface

* Dry run with signing

* Revert paymentInfo changes
2020-10-27 15:19:00 +01:00
Github Actions ca2909e4ba [CI Skip] release/beta 2.4.2-5
skip-checks: true
2020-10-27 12:55:21 +00:00
Jaco Greeff cc9ea53e1a Registry hash returns H256 object (#2791)
* Use logger in error/warning messages

* Update packages/types/src/codec/BTreeSet.ts

* Update expectation

* Some additional type tests

* resgirty.hash returns H256

* Additional override test
2020-10-27 13:47:18 +01:00
Github Actions d876e19fa1 [CI Skip] release/beta 2.4.2-4
skip-checks: true
2020-10-27 12:22:14 +00:00
Jaco Greeff bb7b94dc35 Use logger in error/warning messages (#2790)
* Use logger in error/warning messages

* Update packages/types/src/codec/BTreeSet.ts

* Update expectation

* Some additional type tests
2020-10-27 13:14:03 +01:00
Github Actions be1deb1a75 [CI Skip] release/beta 2.4.2-3
skip-checks: true
2020-10-27 11:30:53 +00:00
Jaco Greeff 14026fef42 Format similar types transparently (#2788)
* Format similar types transparently

* Adjust test expectations

* Remove console.error

* Adjust getTypeDef for check-only
2020-10-27 12:23:18 +01:00
Github Actions b2ea2da6aa [CI Skip] release/beta 2.4.2-2
skip-checks: true
2020-10-27 09:07:26 +00:00
Jaco Greeff f1d21847db Bump deps (util) (#2787) 2020-10-27 09:59:27 +01:00
Github Actions b1fcfd11f4 [CI Skip] release/beta 2.4.2-1
skip-checks: true
2020-10-26 21:44:52 +00:00
Jeremías Díaz 7d1f0e2900 fix(typegen): dedupe similar types (#2786) 2020-10-26 22:37:09 +01:00
Jaco Greeff fb377fb0d4 Adjust index WS imports (#2785) 2020-10-26 22:36:03 +01:00
Github Actions 26de59ed79 [CI Skip] release/beta 2.4.2-0
skip-checks: true
2020-10-26 14:51:50 +00:00
Jaco Greeff 964bd33bb1 Bump GH actions, root cleanups (#2783)
* Bump GH actions, root cleanups

* Remove copy scripts
2020-10-26 15:42:51 +01:00
Github Actions f068ef76a5 [CI Skip] release/stable 2.4.1
skip-checks: true
2020-10-26 08:45:33 +00:00
Jaco Greeff e6e60ec6d0 2.4 (#2782) 2020-10-26 09:36:34 +01:00
Github Actions 9f9680ba92 [CI Skip] release/beta 2.3.2-17
skip-checks: true
2020-10-26 07:24:04 +00:00
Jaco Greeff bb63de1653 Add to/fromU8a on contract events and messages (#2778)
* Add to/fromU8a on contract events and messages

* Add constructor decoding
2020-10-26 08:14:51 +01:00
Github Actions a2c2b24198 [CI Skip] release/beta 2.3.2-16
skip-checks: true
2020-10-25 13:53:59 +00:00
Jaco Greeff 1944ffe017 Remove specName-specific warnings (#2781) 2020-10-25 14:45:13 +01:00
Github Actions d4aa36981d [CI Skip] release/beta 2.3.2-15
skip-checks: true
2020-10-25 13:42:52 +00:00
Jaco Greeff 2c735fbc53 Add node-template to known types (#2780) 2020-10-25 14:34:43 +01:00
Github Actions 7038045bc8 [CI Skip] release/beta 2.3.2-14
skip-checks: true
2020-10-25 08:44:22 +00:00
Jaco Greeff 0be5c969aa Bump dev & berry (#2779) 2020-10-25 09:37:41 +01:00
Github Actions 9ead2bdc41 [CI Skip] release/beta 2.3.2-13
skip-checks: true
2020-10-24 08:01:51 +00:00
Jaco Greeff 1ae37ed2d3 Add initial MultiAddress impl. (#2776)
* Add intitial MultiAddress impl.

* Allow invalid ss58 to be handled upstream
2020-10-24 09:52:36 +02:00
Github Actions 7ca78c5679 [CI Skip] release/beta 2.3.2-12
skip-checks: true
2020-10-23 11:02:34 +00:00
Jaco Greeff cd94d01b06 Bump deps (#2774)
* Bump deps

* Fix linting
2020-10-23 12:53:56 +02:00
Github Actions dafc92809d [CI Skip] release/beta 2.3.2-11
skip-checks: true
2020-10-23 10:13:36 +00:00
Jaco Greeff 298884d885 Adjust type ordering injection (#2771) 2020-10-23 12:04:42 +02:00
Github Actions 2a64c7c29a [CI Skip] release/beta 2.3.2-10
skip-checks: true
2020-10-23 08:25:02 +00:00
Jaco Greeff d2b7dc550a Add docs root redirects (#2769) 2020-10-23 10:16:21 +02:00
Github Actions 25f18d5455 [CI Skip] release/beta 2.3.2-9
skip-checks: true
2020-10-22 22:25:43 +00:00
Jaco Greeff c9c872c736 Expand metadata typeDefs for contracts (#2767)
* Expand metada typeDefs for contracts

* Adjust with actual displayName
2020-10-23 00:17:41 +02:00
Github Actions 8394b7fb5a [CI Skip] release/beta 2.3.2-8
skip-checks: true
2020-10-22 18:02:12 +00:00
Jaco Greeff fb82db382e Add derive.chain.subscribeNewBlocks (#2765)
* Add derive.chain.subscribeNewBlocks

* Expand
2020-10-22 19:52:03 +02:00
Github Actions 9f83f5cac3 [CI Skip] release/beta 2.3.2-7
skip-checks: true
2020-10-22 13:11:03 +00:00
Jaco Greeff 45a895b64f Decode contract events (#2763)
* Decode contract events

* Untable marker
2020-10-22 15:01:09 +02:00
Github Actions 93fbd6e13f [CI Skip] release/beta 2.3.2-6
skip-checks: true
2020-10-22 09:49:44 +00:00
Jaco Greeff b53490bd26 Add solang tests, re-organize sample layouts (#2760)
* Add solang tests, re-organize sample layouts

* Extra lines
2020-10-22 11:39:55 +02:00
Github Actions 594376367a [CI Skip] release/beta 2.3.2-5
skip-checks: true
2020-10-22 08:14:07 +00:00
Jaco Greeff 180fe57531 Register external types before using (#2759) 2020-10-22 10:04:29 +02:00
Github Actions bddb4465fb [CI Skip] release/beta 2.3.2-4
skip-checks: true
2020-10-22 07:11:52 +00:00
Jaco Greeff 3cdc647506 Format tuples (and others) in rpc args (#2758) 2020-10-22 09:02:31 +02:00
Github Actions 82ee7cc4f1 [CI Skip] release/beta 2.3.2-3
skip-checks: true
2020-10-21 09:59:22 +00:00
Jaco Greeff 9f9658d6a0 Format generated consts values (allow eg. tuple) (#2754) 2020-10-21 11:51:23 +02:00
Github Actions 1abc519297 [CI Skip] release/beta 2.3.2-2
skip-checks: true
2020-10-20 14:12:49 +00:00
Sean Young b939bcd57d Solang requires u256 and i256 types (#2752)
Tested with latest solang (current master).

Signed-off-by: Sean Young <sean@mess.org>
2020-10-20 16:03:55 +02:00
Github Actions d487a27676 [CI Skip] release/beta 2.3.2-1
skip-checks: true
2020-10-19 18:23:55 +00:00
Jaco Greeff 0525feb6f2 Match contract ids on camelCase (in addition to original) (#2747) 2020-10-19 20:15:19 +02:00
Github Actions 4ea343e369 [CI Skip] release/beta 2.3.2-0
skip-checks: true
2020-10-19 17:54:54 +00:00
Jaco Greeff 6f2173778e Add keysAt & entriesAt (#2746)
* At keysAt & entriesAt

* Update packages/api/src/base/Decorate.ts
2020-10-19 19:43:58 +02:00
270 changed files with 3275 additions and 3771 deletions
-4
View File
@@ -1,4 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
module.exports = require('./babel.config.js');
-5
View File
@@ -1,5 +0,0 @@
.eslintrc.js
**/build/*
**/coverage/*
**/node_modules/*
docs/examples/promise/90_typegen/*
+9
View File
@@ -5,6 +5,15 @@ const base = require('@polkadot/dev/config/eslint');
module.exports = {
...base,
ignorePatterns: [
'.eslintrc.js',
'.github/**',
'.vscode/**',
'.yarn/**',
'**/build/*',
'**/coverage/*',
'**/node_modules/*'
],
parserOptions: {
...base.parserOptions,
project: [
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
name: ${{ matrix.step }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
- name: ${{ matrix.step }}
run: |
yarn install --immutable | grep -v 'YN0013'
+1 -1
View File
@@ -13,7 +13,7 @@ jobs:
if: "! startsWith(github.event.head_commit.message, '[CI Skip]') && github.repository == 'polkadot-js/api'"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2
with:
token: ${{ secrets.GH_PAT }}
- name: ${{ matrix.step }}
+1 -1
View File
@@ -1 +1 @@
10
12
-55
View File
File diff suppressed because one or more lines are too long
+55
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -12,4 +12,4 @@ plugins:
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
spec: "@yarnpkg/plugin-workspace-tools"
yarnPath: .yarn/releases/yarn-2.2.2.cjs
yarnPath: .yarn/releases/yarn-2.3.3.cjs
+48 -1
View File
@@ -1,8 +1,55 @@
# CHANGELOG
## 2.5.1 Nov 2, 2020
Upgrade priority: Low. Recommended for `api-contract` developers.
- **Breaking change** Substrate changed the `ContractExecResult` from `api.rpc.contracts.call`. The API does have pass-through support for both old and new variants via the `Contract` interface, however it means the structure has changed to accommodate the new Substrate structure. Refer to the [docs for the latest interface](https://polkadot.js.org/docs/api-contract/start/contract.read) (including `isSuccess/isError` -> `isOk/isErr`, and the availability of the `gasConsumed`)
Contributed:
- Dedup similar types on generation (Thanks to https://github.com/monitz87)
Changes:
- `Contract` execution will now return contract events decoded in the result
- Add `.dryRun` on extrinsics (alongside `.paymentInfo` usage)
- Add `system_syncState` and `syncstate_genSyncSpec` RPCs
- Enhance error reporting, `Call` indicates explicit call as found
- Adjust internal metadata decoration and use as exposed from `@types/metadata`
- Expand Rococo known types to cater for v1 (specVersion 10)
- `registry.hash` now returns an `H256` object (as opposed to raw Uint8Array)
- Use utility logger in all relevant error messages (consistency in logging)
- Add `derive.council.proposal(<hash>)` for retrieval of a single (expanded) proposal
- Correctly and transparently format type generation types (allowing for nested variants)
## 2.4.1 Oct 26, 2020
Upgrade priority: Low. No breaking changes, however it does move `api-contract` forward with additional features.
Contributed:
- Add support for both `{i,u}256` types on contracts (Thanks to https://github.com/seanyoung)
Changes:
- Add `.keysAt` & `.entriesAt` to query maps at a specific blockHash
- Adjust ordering of type injection, any `types: { ... }` definitions not have precedence
- Correctly format Tuples in both RPC and const definitions as part of type generation
- Add node-template to known types (tracking inside API), remove warnings for the spec
- Add initial implementation for new Substrate `MultiAddress` type
- Add `api.derive.chain.subscribeNewBlocks` for full block retrievals
- Contracts identifiers to `.{exec, read}('name', ...)` now matches on both snake_case and camelCase (consistency)
- Cleanup contracts serialization for messages to allow both to and from
- Add deserialization of contract events against the ABI
- Adjust contracts metadata parsing to be future-proof with type retrievals
- Add tests for Solang into contracts, re-organize layout per type
## 2.3.1 Oct 19, 2020
Upgrade priority: Low. Recommended for `api-contracts` developers and those using large messages via Node.js WS.
Upgrade priority: Low. Recommended for `api-contract` developers and those using large messages via Node.js WS.
Contributed:
-25
View File
@@ -1,25 +0,0 @@
#!/usr/bin/env bash
# Copyright 2017-2020 @polkadot/api authors & contributors
# SPDX-License-Identifier: Apache-2.0
function copy_folder () {
SRC="packages/$1/build"
DST="../apps/node_modules/@polkadot/$1"
echo "** Copying $SRC to $DST"
rm -rf $DST
cp -r $SRC $DST
}
yarn polkadot-dev-build-ts
copy_folder "api"
copy_folder "api-contract"
copy_folder "api-derive"
copy_folder "metadata"
copy_folder "rpc-core"
copy_folder "rpc-provider"
copy_folder "types"
copy_folder "types-known"
copy_folder "typegen"
-25
View File
@@ -1,25 +0,0 @@
#!/usr/bin/env bash
# Copyright 2017-2020 @polkadot/api authors & contributors
# SPDX-License-Identifier: Apache-2.0
function copy_folder () {
SRC="packages/$1/build"
DST="../test/js-test/node_modules/@polkadot/$1"
echo "** Copying $SRC to $DST"
rm -rf $DST
cp -r $SRC $DST
}
yarn polkadot-dev-build-ts
copy_folder "api"
copy_folder "api-contract"
copy_folder "api-derive"
copy_folder "metadata"
copy_folder "rpc-core"
copy_folder "rpc-provider"
copy_folder "types"
copy_folder "types-known"
copy_folder "typegen"
View File
+12
View File
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=0.5, maximum-scale=1">
<meta http-equiv="refresh" content="0;URL='https://polkadot.js.org/docs/api/'" />
<title>Redirecting to https://polkadot.js.org/docs/api/</title>
</head>
<body>
Redirecting to <a href="https://polkadot.js.org/docs/api/">https://polkadot.js.org/docs/api/</a>
</body>
</html>
+12
View File
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=0.5, maximum-scale=1">
<meta http-equiv="refresh" content="0;URL='https://polkadot.js.org/docs/api/'" />
<title>Redirecting to https://polkadot.js.org/docs/api/</title>
</head>
<body>
Redirecting to <a href="https://polkadot.js.org/docs/api/">https://polkadot.js.org/docs/api/</a>
</body>
</html>
+1 -1
View File
@@ -25,5 +25,5 @@ module.exports = Object.assign({}, config, {
'<rootDir>/packages/types/build',
'<rootDir>/packages/types-known/build'
],
resolver: './jest.resolver.js'
resolver: '@polkadot/dev/config/jest-resolver'
});
-12
View File
@@ -1,12 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
const path = require('path');
module.exports = function resolver (file, config) {
if (file.includes('package.json')) {
return path.join(config.basedir.replace('/src', '/'), file);
}
return config.defaultResolver(file, config);
};
+5 -5
View File
@@ -8,7 +8,7 @@
],
"resolutions": {
"babel-core": "^7.0.0-bridge.0",
"typescript": "^4.0.3"
"typescript": "^4.0.5"
},
"scripts": {
"build": "yarn build:interfaces && polkadot-dev-build-ts && (cd packages/typegen && copyfiles scripts/* build)",
@@ -27,11 +27,11 @@
"@babel/core": "^7.12.3",
"@babel/register": "^7.12.1",
"@babel/runtime": "^7.12.1",
"@polkadot/dev": "^0.58.3",
"@polkadot/ts": "^0.3.49",
"@polkadot/dev": "^0.59.14",
"@polkadot/ts": "^0.3.53",
"@polkadot/typegen": "workspace:packages/typegen",
"@types/jest": "^26.0.14",
"@types/jest": "^26.0.15",
"copyfiles": "^2.4.0"
},
"version": "2.3.1"
"version": "2.5.1"
}
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-contract",
"version": "2.3.1",
"version": "2.5.1",
"description": "Interfaces for interacting with contracts and contract ABIs",
"main": "index.js",
"keywords": [
@@ -27,10 +27,10 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-contract#readme",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@polkadot/api": "2.3.1",
"@polkadot/rpc-core": "2.3.1",
"@polkadot/types": "2.3.1",
"@polkadot/util": "^3.6.1",
"@polkadot/api": "^2.5.1",
"@polkadot/rpc-core": "^2.5.1",
"@polkadot/types": "^2.5.1",
"@polkadot/util": "^3.7.1",
"bn.js": "^5.1.3",
"rxjs": "^6.6.3"
}
+15 -72
View File
@@ -7,84 +7,27 @@ import * as testContracts from '../test/contracts';
const abis: Record<string, any> = { ...testContracts };
function compareInterface (name: string, messageIds: string[]): void {
try {
const inkAbi = new Abi(abis[name]);
expect(inkAbi.messages.map(({ identifier }) => identifier)).toEqual(messageIds);
} catch (error) {
console.error(error);
throw error;
interface JSONAbi {
spec: {
messages: {
name: string[] | string
}[]
}
}
describe('Abi', (): void => {
describe('construction', (): void => {
it('initializes from a contract ABI (flipper)', (): void => {
compareInterface('flipper', ['flip', 'get']);
});
Object.entries(abis).forEach(([abiName, abi]) => {
it(`initializes from a contract ABI (${abiName})`, (): void => {
try {
const messageIds = (abi as JSONAbi).spec.messages.map(({ name }) => Array.isArray(name) ? name[0] : name);
const inkAbi = new Abi(abis[abiName]);
it('initializes from a contract ABI (incrementer)', (): void => {
compareInterface('incrementer', ['inc', 'get']);
});
expect(inkAbi.messages.map(({ identifier }) => identifier)).toEqual(messageIds);
} catch (error) {
console.error(error);
it('initializes from a contract ABI (erc20)', (): void => {
compareInterface('erc20', [
'total_supply',
'balance_of',
'allowance',
'transfer',
'approve',
'transfer_from'
]);
});
it('initializes from a contract ABI (delegator)', (): void => {
compareInterface('delegator', [
'get',
'change',
'switch'
]);
});
it('initializes from a contract ABI (dns)', (): void => {
compareInterface('dns', [
'register',
'set_address',
'transfer',
'get_address'
]);
});
it('initializes from a contract ABI (erc721)', (): void => {
compareInterface('erc721', [
'balance_of',
'owner_of',
'get_approved',
'is_approved_for_all',
'set_approval_for_all',
'approve',
'transfer',
'transfer_from',
'mint',
'burn'
]);
});
it('initializes from a contract ABI (multisig_plain)', (): void => {
compareInterface('multisigPlain', [
'add_owner',
'remove_owner',
'replace_owner',
'change_requirement',
'submit_transaction',
'cancel_transaction',
'confirm_transaction',
'revoke_confirmation',
'invoke_transaction',
'eval_transaction'
]);
throw error;
}
});
});
});
+115 -21
View File
@@ -1,27 +1,29 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { AnyJson } from '@polkadot/types/types';
import { ChainProperties, ContractConstructorSpec, ContractMessageSpec, ContractProject } from '@polkadot/types/interfaces';
import { AbiConstructor, AbiMessage, AbiMessageParam } from './types';
import { AnyJson, Codec, CodecArg } from '@polkadot/types/types';
import { ChainProperties, ContractConstructorSpec, ContractEventSpec, ContractMessageSpec, ContractMessageParamSpec, ContractProject } from '@polkadot/types/interfaces';
import { AbiConstructor, AbiEvent, AbiMessage, AbiParam, DecodedEvent, DecodedMessage } from './types';
import { assert, isNumber, isObject, isString, stringCamelCase } from '@polkadot/util';
import { assert, assertReturn, compactAddLength, compactStripLength, isNumber, isObject, isString, logger, stringCamelCase, u8aConcat, u8aToHex } from '@polkadot/util';
import MetaRegistry from './MetaRegistry';
const l = logger('Abi');
function findMessage <T extends AbiMessage> (list: T[], messageOrId: T | string | number): T {
const message = isNumber(messageOrId)
? list[messageOrId]
: isString(messageOrId)
? list.find(({ identifier }: T) => identifier === messageOrId.toString())
? list.find(({ identifier }) => [identifier, stringCamelCase(identifier)].includes(messageOrId.toString()))
: messageOrId;
assert(message, `Attempted to call an invalid contract interface, ${JSON.stringify(messageOrId)}`);
return message;
return assertReturn(message, `Attempted to call an invalid contract interface, ${JSON.stringify(messageOrId)}`);
}
export default class Abi {
readonly #events: AbiEvent[];
public readonly constructors: AbiConstructor[];
public readonly json: AnyJson;
@@ -45,25 +47,56 @@ export default class Abi {
this.registry.setMetaTypes(this.project.types);
this.project.types.forEach((_, index) => this.registry.getMetaTypeDef(this.registry.createType('SiLookupTypeId', index + 1)));
this.project.types.forEach((_, index) =>
this.registry.getMetaTypeDef({ type: this.registry.createType('SiLookupTypeId', index + 1) })
);
this.constructors = this.project.spec.constructors.map((spec: ContractConstructorSpec, index) =>
this.#createBase(spec, index, {
this.#createMessage(spec, index, {
isConstructor: true
})
);
this.#events = this.project.spec.events.map((spec: ContractEventSpec, index) =>
this.#createEvent(spec, index)
);
this.messages = this.project.spec.messages.map((spec: ContractMessageSpec, index): AbiMessage => {
const typeSpec = spec.returnType.unwrapOr(null);
return this.#createBase(spec, index, {
return this.#createMessage(spec, index, {
isMutating: spec.mutates.isTrue,
isPayable: spec.payable.isTrue,
returnType: typeSpec
? this.registry.getMetaTypeDef(typeSpec.type)
? this.registry.getMetaTypeDef(typeSpec)
: null
});
});
}
/**
* Warning: Unstable API, bound to change
*/
public decodeEvent (data: Uint8Array): DecodedEvent {
const index = data[0];
const event = this.#events[index];
assert(event, `Unable to find event with index ${index}`);
return event.fromU8a(data.subarray(1));
}
/**
* Warning: Unstable API, bound to change
*/
public decodeConstructor (data: Uint8Array): DecodedMessage {
return this.#decodeMessage('message', this.constructors, data);
}
/**
* Warning: Unstable API, bound to change
*/
public decodeMessage (data: Uint8Array): DecodedMessage {
return this.#decodeMessage('message', this.messages, data);
}
public findConstructor (constructorOrId: AbiConstructor | string | number): AbiConstructor {
return findMessage(this.constructors, constructorOrId);
}
@@ -72,30 +105,91 @@ export default class Abi {
return findMessage(this.messages, messageOrId);
}
#createBase = (spec: ContractMessageSpec | ContractConstructorSpec, index: number, add: Partial<AbiMessage> = {}): AbiMessage => {
const identifier = spec.name.toString();
const args = spec.args.map((arg, index): AbiMessageParam => {
#createArgs = (args: ContractMessageParamSpec[], spec: unknown): AbiParam[] => {
return args.map((arg, index): AbiParam => {
try {
assert(isObject(arg.type), 'Invalid type definition found');
return {
name: stringCamelCase(arg.name.toString()),
type: this.registry.getMetaTypeDef(arg.type.type)
name: stringCamelCase(arg.name),
type: this.registry.getMetaTypeDef(arg.type)
};
} catch (error) {
console.error(`Error expanding argument ${index} in ${JSON.stringify(spec)}`);
l.error(`Error expanding argument ${index} in ${JSON.stringify(spec)}`);
throw error;
}
});
}
return {
#createEvent = (spec: ContractEventSpec, index: number): AbiEvent => {
const args = this.#createArgs(spec.args, spec);
const event = {
args,
docs: spec.docs.map((doc) => doc.toString()),
fromU8a: (data: Uint8Array): DecodedEvent => ({
args: this.#decodeArgs(args, data),
event
}),
identifier: spec.name.toString(),
index
};
return event;
}
#createMessage = (spec: ContractMessageSpec | ContractConstructorSpec, index: number, add: Partial<AbiMessage> = {}): AbiMessage => {
const args = this.#createArgs(spec.args, spec);
const message = {
...add,
args,
docs: spec.docs.map((doc) => doc.toString()),
identifier,
fromU8a: (data: Uint8Array): DecodedMessage => ({
args: this.#decodeArgs(args, data),
message
}),
identifier: spec.name.toString(),
index,
selector: spec.selector
selector: spec.selector,
toU8a: (params: CodecArg[]) =>
this.#encodeArgs(spec, args, params)
};
return message;
}
#decodeArgs = (args: AbiParam[], data: Uint8Array): Codec[] => {
// for decoding we expect the input to be just the arg data, no selectors
// no length added (this allows use with events as well)
let offset = 0;
return args.map(({ type }): Codec => {
const value = this.registry.createType(type.type as 'Text', data.subarray(offset));
offset += value.encodedLength;
return value;
});
}
#decodeMessage = (type: 'constructor' | 'message', list: AbiMessage[], data: Uint8Array): DecodedMessage => {
const [, trimmed] = compactStripLength(data);
const selector = trimmed.subarray(0, 4);
const message = list.find((m) => m.selector.eq(selector));
assert(message, `Unable to find ${type} with selector ${u8aToHex(selector)}`);
return message.fromU8a(trimmed.subarray(4));
}
#encodeArgs = ({ name, selector }: ContractMessageSpec | ContractConstructorSpec, args: AbiParam[], data: CodecArg[]): Uint8Array => {
assert(data.length === args.length, `Expected ${args.length} arguments to contract message '${name.toString()}', found ${data.length}`);
return compactAddLength(
u8aConcat(
this.registry.createType('ContractSelector', selector).toU8a(),
...args.map(({ type }, index) => this.registry.createType(type.type as 'Text', data[index]).toU8a())
)
);
}
}
+14 -46
View File
@@ -7,60 +7,28 @@ import path from 'path';
import Abi from './Abi';
import * as testContracts from '../test/contracts';
import * as userContracts from '../test/contracts/user';
const abis: Record<string, any> = { ...testContracts };
const userAbis: Record<string, any> = { ...userContracts };
function compareTypes (name: string): void {
const abi = new Abi(abis[name] || userAbis[name]);
try {
const cmpPath = path.join(__dirname, `../test/compare/${name}.test.json`);
if (!fs.existsSync(cmpPath)) {
fs.writeFileSync(cmpPath, JSON.stringify(abi.registry.metaTypeDefs, null, 2), { flag: 'w' });
}
// eslint-disable-next-line @typescript-eslint/no-var-requires
expect(abi.registry.metaTypeDefs).toEqual(require(cmpPath));
} catch (error) {
console.error(JSON.stringify(abi.registry.metaTypeDefs));
throw error;
}
}
describe('MetaRegistry', (): void => {
describe('types', (): void => {
it('initializes from a contract ABI (flipper)', (): void => {
compareTypes('flipper');
});
Object.keys(abis).forEach((abiName) => {
it(`initializes from a contract ABI (${abiName})`, (): void => {
const abi = new Abi(abis[abiName]);
it('initializes from a contract ABI (incrementer)', (): void => {
compareTypes('incrementer');
});
try {
const cmpPath = path.join(__dirname, `../test/compare/${abiName}.test.json`);
it('initializes from a contract ABI (erc20)', (): void => {
compareTypes('erc20');
});
if (!fs.existsSync(cmpPath)) {
fs.writeFileSync(cmpPath, JSON.stringify(abi.registry.metaTypeDefs, null, 2), { flag: 'w' });
}
it('initializes from a contract ABI (dns)', (): void => {
compareTypes('dns');
});
// eslint-disable-next-line @typescript-eslint/no-var-requires
expect(abi.registry.metaTypeDefs).toEqual(require(cmpPath));
} catch (error) {
console.error(JSON.stringify(abi.registry.metaTypeDefs));
it('initializes from a contract ABI (erc721)', (): void => {
compareTypes('erc721');
});
it('initializes from a contract ABI (multisig_plain)', (): void => {
compareTypes('multisigPlain');
});
});
describe('user ABIs', (): void => {
it('initializes from a contract ABI (withString)', (): void => {
compareTypes('withString');
throw error;
}
});
});
+42 -21
View File
@@ -1,12 +1,17 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ChainProperties, SiField, SiLookupTypeId, SiType, SiTypeDefArray, SiTypeDefVariant, SiTypeDefSequence, SiTypeDefTuple, SiVariant } from '@polkadot/types/interfaces';
import { ContractDisplayName, ChainProperties, SiField, SiLookupTypeId, SiType, SiTypeDefArray, SiTypeDefVariant, SiTypeDefSequence, SiTypeDefTuple, SiVariant } from '@polkadot/types/interfaces';
import { InterfaceTypes, TypeDef, TypeDefInfo } from '@polkadot/types/types';
import { assert, isUndefined } from '@polkadot/util';
import { TypeRegistry, withTypeString } from '@polkadot/types';
interface PartialTypeSpec {
readonly type: SiLookupTypeId;
readonly displayName?: ContractDisplayName;
}
// convert the offset into project-specific, index-1
export function getRegistryOffset (id: SiLookupTypeId): number {
return id.toNumber() - 1;
@@ -17,6 +22,8 @@ const PRIMITIVE_ALIAS: Record<string, keyof InterfaceTypes> = {
Str: 'Text'
};
const PRIMITIVE_ALWAYS = ['AccountId', 'AccountIndex', 'Address', 'Balance'];
export default class MetaRegistry extends TypeRegistry {
public readonly metaTypeDefs: TypeDef[] = [];
@@ -34,24 +41,38 @@ export default class MetaRegistry extends TypeRegistry {
this.#siTypes = metaTypes;
}
public getMetaTypeDef (id: SiLookupTypeId): TypeDef {
const offset = getRegistryOffset(id);
public getMetaTypeDef (typeSpec: PartialTypeSpec): TypeDef {
const offset = getRegistryOffset(typeSpec.type);
let typeDef = this.metaTypeDefs[offset];
if (!typeDef) {
typeDef = this.#extract(this.#getMetaType(id), id);
typeDef = this.#extract(this.#getMetaType(typeSpec.type), typeSpec.type);
this.metaTypeDefs[offset] = typeDef;
}
// Here we protect against the following cases
// - No displayName present, these are generally known primitives
// - displayName === type, these generate circular references
// - displayName Option & type Option<...something...>
if (typeDef.displayName && !(typeDef.type === typeDef.displayName || typeDef.type.startsWith(`${typeDef.displayName}<`))) {
this.register({ [typeDef.displayName]: typeDef.type });
if (typeSpec.displayName && typeSpec.displayName.length) {
const displayName = typeSpec.displayName[typeSpec.displayName.length - 1].toString();
if (!typeDef.type.startsWith(displayName)) {
typeDef = {
...typeDef,
displayName,
type: PRIMITIVE_ALWAYS.includes(displayName)
? displayName
: typeDef.type
};
}
}
// Here we protect against the following cases
// - No displayName present, these are generally known primitives
// - displayName === type, these generate circular references
// - displayName Option & type Option<...something...>
if (typeDef.displayName && !this.hasType(typeDef.displayName) && !(typeDef.type === typeDef.displayName || typeDef.type.startsWith(`${typeDef.displayName}<`))) {
this.register({ [typeDef.displayName]: typeDef.type });
}
return typeDef;
}
@@ -65,10 +86,10 @@ export default class MetaRegistry extends TypeRegistry {
#extract = (type: SiType, id: SiLookupTypeId): TypeDef => {
const path = [...type.path];
const pathFinal = path.length ? path[path.length - 1].toString() : '';
let typeDef: Omit<TypeDef, 'type'>;
// TODO solang?
if (type.path.join('::').startsWith('ink_env::types::')) {
if (type.path.join('::').startsWith('ink_env::types::') || PRIMITIVE_ALWAYS.includes(pathFinal)) {
typeDef = this.#extractPrimitivePath(type);
} else if (type.def.isPrimitive) {
typeDef = this.#extractPrimitive(type);
@@ -98,7 +119,7 @@ export default class MetaRegistry extends TypeRegistry {
: {}
),
...(type.params.length > 0
? { params: type.params.map((id) => this.getMetaTypeDef(id)) }
? { params: type.params.map((type) => this.getMetaTypeDef({ type })) }
: {}
),
...typeDef
@@ -111,7 +132,7 @@ export default class MetaRegistry extends TypeRegistry {
return {
info: TypeDefInfo.VecFixed,
length: length.toNumber(),
sub: this.getMetaTypeDef(type)
sub: this.getMetaTypeDef({ type })
};
}
@@ -135,7 +156,7 @@ export default class MetaRegistry extends TypeRegistry {
const sub = fields.map(({ name, type }) => {
return {
...this.getMetaTypeDef(type),
...this.getMetaTypeDef({ type }),
...(name.isSome ? { name: name.unwrap().toString() } : {})
};
});
@@ -166,16 +187,16 @@ export default class MetaRegistry extends TypeRegistry {
return {
info: TypeDefInfo.Vec,
sub: this.getMetaTypeDef(type)
sub: this.getMetaTypeDef({ type })
};
}
#extractTuple = (ids: SiTypeDefTuple): Omit<TypeDef, 'type'> => {
return ids.length === 1
? this.getMetaTypeDef(ids[0])
? this.getMetaTypeDef({ type: ids[0] })
: {
info: TypeDefInfo.Tuple,
sub: ids.map((id) => this.getMetaTypeDef(id))
sub: ids.map((type) => this.getMetaTypeDef({ type }))
};
}
@@ -186,14 +207,14 @@ export default class MetaRegistry extends TypeRegistry {
if (specialVariant === 'Option') {
return {
info: TypeDefInfo.Option,
sub: this.getMetaTypeDef(params[0])
sub: this.getMetaTypeDef({ type: params[0] })
};
} else if (specialVariant === 'Result') {
return {
info: TypeDefInfo.Result,
sub: params.map((param, index) => ({
sub: params.map((type, index) => ({
name: ['Ok', 'Error'][index],
...this.getMetaTypeDef(param)
...this.getMetaTypeDef({ type })
}))
};
}
+3 -3
View File
@@ -14,7 +14,7 @@ import ApiBase from '@polkadot/api/base';
import { isUndefined, stringCamelCase } from '@polkadot/util';
import Abi from '../Abi';
import { applyOnEvent, encodeMessage } from '../util';
import { applyOnEvent } from '../util';
import Base from './Base';
import Contract from './Contract';
@@ -54,9 +54,9 @@ export default class Blueprint<ApiType extends ApiTypes> extends Base<ApiType> {
#deploy = (constructorOrId: AbiConstructor | string| number, endowment: BigInt | string | number | BN, gasLimit: BigInt | string | number | BN, params: CodecArg[]): SubmittableExtrinsic<ApiType, BlueprintSubmittableResult<ApiType>> => {
return this.api.tx.contracts
.instantiate(endowment, gasLimit, this.codeHash, encodeMessage(this.registry, this.abi.findConstructor(constructorOrId), params))
.instantiate(endowment, gasLimit, this.codeHash, this.abi.findConstructor(constructorOrId).toU8a(params))
.withResultTransform((result: ISubmittableResult) =>
new BlueprintSubmittableResult(result, applyOnEvent(result, 'Instantiated', (record: EventRecord) =>
new BlueprintSubmittableResult(result, applyOnEvent(result, 'Instantiated', ([record]: EventRecord[]) =>
new Contract<ApiType>(this.api, this.abi, record.event.data[1] as AccountId, this._decorateMethod)
))
);
+1 -1
View File
@@ -38,7 +38,7 @@ export default class Code<ApiType extends ApiTypes> extends Base<ApiType> {
return this.api.tx.contracts
.putCode(compactAddLength(this.code))
.withResultTransform((result: ISubmittableResult) =>
new CodeSubmittableResult(result, applyOnEvent(result, 'CodeStored', (record: EventRecord) =>
new CodeSubmittableResult(result, applyOnEvent(result, 'CodeStored', ([record]: EventRecord[]) =>
new Blueprint<ApiType>(this.api, this.abi, record.event.data[0] as Hash, this._decorateMethod)
))
);
+75 -16
View File
@@ -3,21 +3,60 @@
import { ApiTypes, DecorateMethod } from '@polkadot/api/types';
import { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
import { AccountId, ContractExecResult } from '@polkadot/types/interfaces';
import { AnyJson, CodecArg } from '@polkadot/types/types';
import { AbiMessage, ContractCallOutcome } from '../types';
import { ContractCallResult, ContractRead, MapMessageExec, MapMessageRead } from './types';
import { AccountId, ContractExecResult, EventRecord } from '@polkadot/types/interfaces';
import { AnyJson, CodecArg, ISubmittableResult, Registry } from '@polkadot/types/types';
import { AbiMessage, ContractCallOutcome, DecodedEvent } from '../types';
import { ContractRead, MapMessageExec, MapMessageRead } from './types';
import BN from 'bn.js';
import { map } from 'rxjs/operators';
import { SubmittableResult } from '@polkadot/api';
import ApiBase from '@polkadot/api/base';
import { assert, bnToBn, isFunction, isUndefined, stringCamelCase } from '@polkadot/util';
import { assert, bnToBn, isFunction, isUndefined, logger, stringCamelCase } from '@polkadot/util';
import Abi from '../Abi';
import { encodeMessage, formatData } from '../util';
import { applyOnEvent, formatData } from '../util';
import Base from './Base';
const ERROR_NO_CALL = 'Your node does not expose the contracts.call RPC. This is most probably due to a runtime configuration.';
const l = logger('Contract');
export class ContractSubmittableResult extends SubmittableResult {
public readonly contractEvents?: DecodedEvent[];
constructor (result: ISubmittableResult, contractEvents?: DecodedEvent[]) {
super(result);
this.contractEvents = contractEvents;
}
}
// map from a JSON result to current-style ContractExecResult
function mapExecResult (registry: Registry, json: Record<string, AnyJson>): ContractExecResult {
if (!Object.keys(json).some((key) => ['error', 'success'].includes(key))) {
return registry.createType('ContractExecResult', json);
}
const from = registry.createType('ContractExecResultTo260', json);
if (from.isSuccess) {
const s = from.asSuccess;
return registry.createType('ContractExecResult', {
gasConsumed: s.gasConsumed,
result: {
ok: {
data: s.data,
flags: s.flags
}
}
});
}
// in the old format error has no additional information,
// map it as-is with an "unknown" error
return registry.createType('ContractExecResult', { result: { err: { other: 'unknown' } } });
}
export default class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
public readonly address: AccountId;
@@ -69,7 +108,23 @@ export default class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
}
#exec = (messageOrId: AbiMessage | string | number, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, params: CodecArg[]): SubmittableExtrinsic<ApiType> => {
return this.api.tx.contracts.call(this.address, value, this.#getGas(gasLimit), encodeMessage(this.registry, this.abi.findMessage(messageOrId), params));
return this.api.tx.contracts
.call(this.address, value, this.#getGas(gasLimit), this.abi.findMessage(messageOrId).toU8a(params))
.withResultTransform((result: ISubmittableResult) =>
new ContractSubmittableResult(result, applyOnEvent(result, 'ContractExecution', (records: EventRecord[]) =>
records
.map(({ event: { data: [, data] } }): DecodedEvent | null => {
try {
return this.abi.decodeEvent(data.toU8a());
} catch (error) {
l.error(`Unable to decode contract event: ${(error as Error).message}`);
return null;
}
})
.filter((decoded): decoded is DecodedEvent => !!decoded)
))
);
}
#read = (messageOrId: AbiMessage | string | number, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, params: CodecArg[]): ContractRead<ApiType> => {
@@ -79,21 +134,25 @@ export default class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
return {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
send: this._decorateMethod((origin: string | AccountId | Uint8Array): ContractCallResult<'rpc'> =>
this.api.rx.rpc.contracts.call({
send: this._decorateMethod((origin: string | AccountId | Uint8Array) =>
this.api.rx.rpc.contracts.call.json({
dest: this.address,
gasLimit: this.#getGas(gasLimit),
inputData: encodeMessage(this.registry, message, params),
inputData: message.toU8a(params),
origin,
value
}).pipe(
map((result: ContractExecResult): ContractCallOutcome => ({
output: result.isSuccess && message.returnType
? formatData(this.registry, result.asSuccess.data, message.returnType)
}).pipe(map((json): ContractCallOutcome => {
const { debugMessage, gasConsumed, result } = mapExecResult(this.registry, json.toJSON());
return {
debugMessage,
gasConsumed,
output: result.isOk && message.returnType
? formatData(this.registry, result.asOk.data, message.returnType)
: null,
result
}))
)
};
}))
)
};
}
+5 -12
View File
@@ -1,7 +1,6 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { SubmittableResult } from '@polkadot/api';
import { ApiTypes, ObsInnerType } from '@polkadot/api/types';
import { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
import { AccountId } from '@polkadot/types/interfaces';
@@ -11,20 +10,14 @@ import { ContractCallOutcome } from '../types';
import BN from 'bn.js';
import { Observable } from 'rxjs';
type ContractCallTypes = 'tx' | 'rpc';
type ContractCallResultSubscription<ApiType extends ApiTypes, CallType extends ContractCallTypes> = ApiType extends 'rxjs'
? Observable<ContractCallResult<CallType>>
: Promise<ObsInnerType<ContractCallResult<CallType>>>;
type ContractCallResult<ApiType extends ApiTypes, T> = ApiType extends 'rxjs'
? Observable<Observable<T>>
: Promise<ObsInnerType<Observable<T>>>;
export interface ContractRead<ApiType extends ApiTypes> {
send (account: string | AccountId | Uint8Array): ContractCallResultSubscription<ApiType, 'rpc'>;
send (account: string | AccountId | Uint8Array): ContractCallResult<ApiType, ContractCallOutcome>;
}
export type ContractCallResult<CallType extends ContractCallTypes> = CallType extends 'rpc'
? Observable<ContractCallOutcome>
: Observable<SubmittableResult>;
export interface MapConstructorExec<ApiType extends ApiTypes> {
[message: string]: (endowment: BigInt | string | number | BN, gasLimit: BigInt | string | number | BN, ...params: CodecArg[]) => SubmittableExtrinsic<ApiType>;
}
@@ -34,5 +27,5 @@ export interface MapMessageExec<ApiType extends ApiTypes> {
}
export interface MapMessageRead<ApiType extends ApiTypes> {
[message: string]: (origin: AccountId | string | Uint8Array, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, ...params: CodecArg[]) => ContractCallResultSubscription<ApiType, 'rpc'>;
[message: string]: (origin: AccountId | string | Uint8Array, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, ...params: CodecArg[]) => ContractCallResult<ApiType, ContractCallOutcome>;
}
+30 -6
View File
@@ -2,10 +2,12 @@
// SPDX-License-Identifier: Apache-2.0
import { ApiTypes } from '@polkadot/api/types';
import { ContractExecResult, ContractSelector } from '@polkadot/types/interfaces';
import { Codec, TypeDef } from '@polkadot/types/types';
import { ContractExecResultResult, ContractSelector } from '@polkadot/types/interfaces';
import { Codec, CodecArg, TypeDef } from '@polkadot/types/types';
import ApiBase from '@polkadot/api/base';
import { Text, u64 } from '@polkadot/types';
import Abi from './Abi';
export interface ContractBase<ApiType extends ApiTypes> {
@@ -16,14 +18,23 @@ export interface ContractBase<ApiType extends ApiTypes> {
messages: AbiMessage[];
}
export interface AbiMessageParam {
export interface AbiParam {
name: string;
type: TypeDef;
}
export interface AbiMessage {
args: AbiMessageParam[];
export interface AbiEvent {
args: AbiParam[];
docs: string[];
fromU8a: (data: Uint8Array) => DecodedEvent;
identifier: string;
index: number;
}
export interface AbiMessage {
args: AbiParam[];
docs: string[];
fromU8a: (data: Uint8Array) => DecodedMessage;
identifier: string;
index: number;
isConstructor?: boolean;
@@ -31,6 +42,7 @@ export interface AbiMessage {
isPayable?: boolean;
returnType?: TypeDef | null;
selector: ContractSelector;
toU8a: (params: CodecArg[]) => Uint8Array;
}
export type AbiConstructor = AbiMessage;
@@ -41,6 +53,18 @@ export interface InterfaceContractCalls {
}
export interface ContractCallOutcome {
debugMessage: Text;
gasConsumed: u64;
output: Codec | null;
result: ContractExecResult;
result: ContractExecResultResult;
}
export interface DecodedEvent {
args: Codec[];
event: AbiEvent;
}
export interface DecodedMessage {
args: Codec[];
message: AbiMessage;
}
+7 -27
View File
@@ -3,44 +3,24 @@
import { SubmittableResult } from '@polkadot/api';
import { EventRecord } from '@polkadot/types/interfaces';
import { Codec, CodecArg, Registry, TypeDef } from '@polkadot/types/types';
import { AbiConstructor, AbiMessage } from './types';
import { Codec, Registry, TypeDef } from '@polkadot/types/types';
import { Raw, createClass, createTypeUnsafe, encodeTypeDef } from '@polkadot/types';
import { Raw, createTypeUnsafe } from '@polkadot/types';
import { assert, compactAddLength } from '@polkadot/util';
type ContractEvents = 'CodeStored' | 'ContractExecution' | 'Instantiated';
export function formatData (registry: Registry, data: Raw, { type }: TypeDef): Codec {
return createTypeUnsafe(registry, type, [data], true);
}
export function applyOnEvent <T> (result: SubmittableResult, type: 'CodeStored' | 'Instantiated', fn: (record: EventRecord) => T): T | undefined {
export function applyOnEvent <T> (result: SubmittableResult, type: ContractEvents, fn: (records: EventRecord[]) => T): T | undefined {
if (result.isInBlock || result.isFinalized) {
const record = result.findRecord('contracts', type);
const records = result.filterRecords('contracts', type);
if (record) {
return fn(record);
if (records.length) {
return fn(records);
}
}
return undefined;
}
export function encodeMessage (registry: Registry, message: AbiMessage | AbiConstructor, params: CodecArg[]): Uint8Array {
assert(message, 'Attempted to call an invalid contract message');
assert(params.length === message.args.length, `Expected ${message.args.length} arguments to contract message '${message.identifier}', found ${params.length}`);
const Clazz = createClass(registry, JSON.stringify(
message.args.reduce((r: Record<string, any>, { name, type }): Record<string, any> => {
r[name] = type.displayName || encodeTypeDef(type);
return r;
}, { __selector: 'ContractSelector' })
));
return compactAddLength(new Clazz(registry, message.args.reduce((r: Record<string, CodecArg>, { name }, index): Record<string, CodecArg> => {
r[name] = params[index];
return r;
}, { __selector: message.selector })).toU8a());
}
@@ -0,0 +1,28 @@
[
{
"info": 6,
"type": "u256"
},
{
"info": 6,
"type": "u8"
},
{
"info": 12,
"length": 32,
"sub": {
"info": 6,
"type": "u8"
},
"type": "[u8;32]"
},
{
"displayName": "AccountId",
"info": 6,
"type": "AccountId"
},
{
"info": 6,
"type": "Text"
}
]
@@ -0,0 +1,31 @@
[
{
"displayName": "AccountId",
"namespace": "ink_env::types",
"info": 6,
"type": "AccountId"
},
{
"info": 12,
"length": 32,
"sub": {
"info": 6,
"type": "u8"
},
"type": "[u8;32]"
},
{
"info": 6,
"type": "u8"
},
{
"info": 6,
"type": "i32"
},
{
"displayName": "Hash",
"namespace": "ink_env::types",
"info": 6,
"type": "Hash"
}
]
@@ -0,0 +1,6 @@
[
{
"info": 6,
"type": "u256"
}
]
@@ -1,10 +1,6 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as delegator } from './delegator.json';
export { default as dns } from './dns.json';
export { default as erc20 } from './erc20.json';
export { default as erc721 } from './erc721.json';
export { default as flipper } from './flipper.json';
export { default as incrementer } from './incrementer.json';
export { default as multisigPlain } from './multisig_plain.json';
export * from './ink';
export * from './solang';
export * from './user';
@@ -0,0 +1,10 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as delegator } from './delegator.json';
export { default as dns } from './dns.json';
export { default as erc20 } from './erc20.json';
export { default as erc721 } from './erc721.json';
export { default as flipper } from './flipper.json';
export { default as incrementer } from './incrementer.json';
export { default as multisigPlain } from './multisig_plain.json';
@@ -0,0 +1,4 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as ints256 } from './ints256.json';
@@ -0,0 +1,113 @@
{
"contract": {
"authors": [
"Sean Young <sean@mess.org>"
],
"description": "Test 256 bits types",
"name": "ints256",
"version": "0.0.1"
},
"metadataVersion": "0.1.0",
"source": {
"compiler": "solang 0.1.4",
"hash": "0xa85fb5c61a09d71dce84c15a8bd87e6f4eafac498a1aec3869e8cf7ea4389697",
"language": "Solidity 0.1.4"
},
"spec": {
"constructors": [
{
"args": [],
"docs": [
""
],
"name": "new",
"selector": "0x861731d5"
}
],
"events": [],
"messages": [
{
"args": [
{
"name": "a",
"type": {
"display_name": [
"u256"
],
"type": 1
}
},
{
"name": "b",
"type": {
"display_name": [
"u256"
],
"type": 1
}
}
],
"docs": [
"Multiply two 256 bit values\n\n"
],
"mutates": false,
"name": "multiply",
"payable": false,
"return_type": {
"display_name": [
"u256"
],
"type": 1
},
"selector": "0x165c4a16"
},
{
"args": [
{
"name": "a",
"type": {
"display_name": [
"u256"
],
"type": 1
}
},
{
"name": "b",
"type": {
"display_name": [
"u256"
],
"type": 1
}
}
],
"docs": [
"Add two 256 bit values\n\n"
],
"mutates": false,
"name": "add",
"payable": false,
"return_type": {
"display_name": [
"u256"
],
"type": 1
},
"selector": "0x771602f7"
}
]
},
"storage": {
"struct": {
"fields": []
}
},
"types": [
{
"def": {
"primitive": "u256"
}
}
]
}
@@ -0,0 +1,13 @@
/// @title Test 256 bits types
/// @author Sean Young <sean@mess.org>
contract ints256 {
/// Multiply two 256 bit values
function multiply(uint256 a, uint256 b) public pure returns (uint256) {
return a * b;
}
/// Add two 256 bit values
function add(uint256 a, uint256 b) public pure returns (uint256) {
return a + b;
}
}
@@ -0,0 +1,299 @@
{
"contract": {
"authors": [
"unknown"
],
"name": "AssetTransfer",
"version": "0.0.1"
},
"metadataVersion": "0.1.0",
"source": {
"compiler": "solang 0.1.4",
"hash": "0x7d163f445bec3d33e90d0f60bda40acd42f2760dbc1b731616af70a6001e05c7",
"language": "Solidity 0.1.4"
},
"spec": {
"constructors": [
{
"args": [],
"docs": [
""
],
"name": "new",
"selector": "0x861731d5"
}
],
"events": [
{
"args": [
{
"indexed": false,
"name": "_newUser",
"type": {
"display_name": [
"AccountId"
],
"type": 4
}
}
],
"docs": [
""
],
"name": "successfulRegistration"
},
{
"args": [
{
"indexed": false,
"name": "sender",
"type": {
"display_name": [
"AccountId"
],
"type": 4
}
},
{
"indexed": false,
"name": "_hexAsset",
"type": {
"display_name": [
"String"
],
"type": 5
}
}
],
"docs": [
""
],
"name": "addedAsset"
},
{
"args": [
{
"indexed": false,
"name": "sender",
"type": {
"display_name": [
"AccountId"
],
"type": 4
}
},
{
"indexed": false,
"name": "receiver",
"type": {
"display_name": [
"AccountId"
],
"type": 4
}
},
{
"indexed": false,
"name": "hexOfAsset",
"type": {
"display_name": [
"String"
],
"type": 5
}
}
],
"docs": [
""
],
"name": "assetSent"
}
],
"messages": [
{
"args": [
{
"name": "_user",
"type": {
"display_name": [
"AccountId"
],
"type": 4
}
}
],
"docs": [
""
],
"mutates": false,
"name": "viewBalance",
"payable": false,
"return_type": {
"display_name": [
"u256"
],
"type": 1
},
"selector": "0xc1a13d1a"
},
{
"args": [
{
"name": "_assetHex",
"type": {
"display_name": [
"String"
],
"type": 5
}
}
],
"docs": [
""
],
"mutates": false,
"name": "findOwner",
"payable": false,
"return_type": {
"display_name": [
"AccountId"
],
"type": 4
},
"selector": "0x63560a8e"
},
{
"args": [
{
"name": "_hexAsset",
"type": {
"display_name": [
"String"
],
"type": 5
}
}
],
"docs": [
""
],
"mutates": true,
"name": "addAsset",
"payable": false,
"return_type": null,
"selector": "0xa7c6b52e"
},
{
"args": [],
"docs": [
""
],
"mutates": true,
"name": "receiveAsset",
"payable": false,
"return_type": {
"display_name": [
"String"
],
"type": 5
},
"selector": "0xb2f3b5bc"
},
{
"args": [
{
"name": "_assetHex",
"type": {
"display_name": [
"String"
],
"type": 5
}
},
{
"name": "_receiver",
"type": {
"display_name": [
"AccountId"
],
"type": 4
}
}
],
"docs": [
""
],
"mutates": true,
"name": "sendAsset",
"payable": false,
"return_type": null,
"selector": "0xd6e5288f"
},
{
"args": [
{
"name": "_newUser",
"type": {
"display_name": [
"AccountId"
],
"type": 4
}
}
],
"docs": [
""
],
"mutates": true,
"name": "register",
"payable": false,
"return_type": null,
"selector": "0x4420e486"
}
]
},
"storage": {
"struct": {
"fields": []
}
},
"types": [
{
"def": {
"primitive": "u256"
}
},
{
"def": {
"primitive": "u8"
}
},
{
"def": {
"array": {
"len": 32,
"type": 2
}
}
},
{
"def": {
"composite": {
"fields": [
{
"type": 3
}
]
}
},
"path": [
"AccountId"
]
},
{
"def": {
"primitive": "str"
}
}
]
}
@@ -1,4 +1,5 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as assetTransfer } from './assetTransfer.json';
export { default as withString } from './withString.json';
+8 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-derive",
"version": "2.3.1",
"version": "2.5.1",
"description": "Common functions used across Polkadot, derived from RPC calls and storage queries.",
"main": "index.js",
"keywords": [
@@ -28,17 +28,17 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@polkadot/api": "2.3.1",
"@polkadot/rpc-core": "2.3.1",
"@polkadot/rpc-provider": "2.3.1",
"@polkadot/types": "2.3.1",
"@polkadot/util": "^3.6.1",
"@polkadot/util-crypto": "^3.6.1",
"@polkadot/api": "^2.5.1",
"@polkadot/rpc-core": "^2.5.1",
"@polkadot/rpc-provider": "^2.5.1",
"@polkadot/types": "^2.5.1",
"@polkadot/util": "^3.7.1",
"@polkadot/util-crypto": "^3.7.1",
"bn.js": "^5.1.3",
"memoizee": "^0.4.14",
"rxjs": "^6.6.3"
},
"devDependencies": {
"@polkadot/keyring": "^3.6.1"
"@polkadot/keyring": "^3.7.1"
}
}
@@ -6,7 +6,7 @@ import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { isU8a, assert } from '@polkadot/util';
import { isU8a, assertReturn } from '@polkadot/util';
import { decodeAddress } from '@polkadot/util-crypto';
import { memo } from '../util';
@@ -23,11 +23,7 @@ function retrieve (api: ApiInterfaceRx, address: Address | AccountId | AccountIn
const accountIndex = api.registry.createType('AccountIndex', decoded);
return api.derive.accounts.indexToId(accountIndex.toString()).pipe(
map((accountId) => {
assert(accountId, 'Unable to retrieve accountId');
return accountId;
})
map((accountId) => assertReturn(accountId, 'Unable to retrieve accountId'))
);
}
+29 -32
View File
@@ -20,9 +20,17 @@ type FlagsIntermediate = [
AccountId | undefined
];
function isIncludedFn (accountId: AccountId | Address | string): (_: AccountId | Address |string) => boolean {
return function (id: AccountId | Address | string): boolean {
return id.toString() === accountId.toString();
function parseFlags (address: AccountId | Address | string | null | undefined, [electionsMembers, councilMembers, technicalCommitteeMembers, societyMembers, sudoKey]: FlagsIntermediate): DeriveAccountFlags {
const isIncluded = (id: AccountId | Address | string) =>
address
? id.toString() === address.toString()
: false;
return {
isCouncil: (electionsMembers?.map(([id]: ITuple<[AccountId, Balance]>) => id) || councilMembers || []).some(isIncluded),
isSociety: (societyMembers || []).some(isIncluded),
isSudo: sudoKey?.toString() === address?.toString(),
isTechCommittee: (technicalCommitteeMembers || []).some(isIncluded)
};
}
@@ -34,35 +42,24 @@ export function flags (instanceId: string, api: ApiInterfaceRx): (address?: Acco
return memo(instanceId, (address?: AccountId | Address | string | null): Observable<DeriveAccountFlags> => {
const councilSection = api.query.electionsPhragmen ? 'electionsPhragmen' : 'elections';
return (
combineLatest([
address && api.query[councilSection]?.members
? api.query[councilSection].members()
: of(undefined),
address && api.query.council?.members
? api.query.council.members()
: of([]),
address && api.query.technicalCommittee?.members
? api.query.technicalCommittee.members()
: of([]),
address && api.query.society?.members
? api.query.society.members()
: of([]),
address && api.query.sudo?.key
? api.query.sudo.key()
: of(undefined)
]) as Observable<FlagsIntermediate>
).pipe(
map(([electionsMembers, councilMembers, technicalCommitteeMembers, societyMembers, sudoKey]): DeriveAccountFlags => {
const isIncluded = address ? isIncludedFn(address) : (): boolean => false;
return {
isCouncil: (electionsMembers?.map(([id]: ITuple<[AccountId, Balance]>) => id) || councilMembers || []).some(isIncluded),
isSociety: (societyMembers || []).some(isIncluded),
isSudo: sudoKey?.toString() === address?.toString(),
isTechCommittee: (technicalCommitteeMembers || []).some(isIncluded)
};
})
return combineLatest<FlagsIntermediate>([
address && api.query[councilSection]?.members
? api.query[councilSection].members()
: of(undefined),
address && api.query.council?.members
? api.query.council.members()
: of([]),
address && api.query.technicalCommittee?.members
? api.query.technicalCommittee.members()
: of([]),
address && api.query.society?.members
? api.query.society.members()
: of([]),
address && api.query.sudo?.key
? api.query.sudo.key()
: of(undefined)
]).pipe(
map((result) => parseFlags(address, result))
);
});
}
+21 -23
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import { ApiInterfaceRx } from '@polkadot/api/types';
import { AccountId, AccountIndex, Address, Balance, Registration } from '@polkadot/types/interfaces';
import { AccountId, AccountIndex, Address, Balance, IdentityInfoAdditional, Registration } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DeriveAccountInfo, DeriveAccountRegistration } from '../types';
@@ -13,6 +13,8 @@ import { u8aToString } from '@polkadot/util';
import { memo } from '../util';
const UNDEF_HEX = { toHex: () => undefined };
function dataAsString (data: Data): string | undefined {
return data.isRaw
? u8aToString(data.asRaw.toU8a(true))
@@ -35,6 +37,19 @@ function retrieveNick (api: ApiInterfaceRx, accountId?: AccountId): Observable<s
);
}
function extractOther (additional: IdentityInfoAdditional[]): Record<string, string> {
return additional.reduce((other: Record<string, string>, [_key, _value]): Record<string, string> => {
const key = dataAsString(_key);
const value = dataAsString(_value);
if (key && value) {
other[key] = value;
}
return other;
}, {});
}
function extractIdentity (identityOfOpt?: Option<Registration>, superOf?: [AccountId, Data]): DeriveAccountRegistration {
if (!identityOfOpt?.isSome) {
return { judgements: [] };
@@ -44,32 +59,15 @@ function extractIdentity (identityOfOpt?: Option<Registration>, superOf?: [Accou
const topDisplay = dataAsString(info.display);
return {
display: superOf
? dataAsString(superOf[1]) || topDisplay
: topDisplay,
displayParent: superOf
? topDisplay
: undefined,
display: (superOf && dataAsString(superOf[1])) || topDisplay,
displayParent: superOf && topDisplay,
email: dataAsString(info.email),
image: dataAsString(info.image),
judgements,
legal: dataAsString(info.legal),
other: info.additional.reduce((other: Record<string, string>, [_key, _value]): Record<string, string> => {
const key = dataAsString(_key);
const value = dataAsString(_value);
if (key && value) {
other[key] = value;
}
return other;
}, {}),
parent: superOf
? superOf[0]
: undefined,
pgp: info.pgpFingerprint.isSome
? info.pgpFingerprint.unwrap().toHex()
: undefined,
other: extractOther(info.additional),
parent: superOf && superOf[0],
pgp: info.pgpFingerprint.unwrapOr(UNDEF_HEX).toHex(),
riot: dataAsString(info.riot),
twitter: dataAsString(info.twitter),
web: dataAsString(info.web)
+15 -4
View File
@@ -16,9 +16,16 @@ import { memo } from '../util';
type ResultBalance = [VestingInfo | null, (BalanceLock | BalanceLockTo212)[]];
type Result = [DeriveBalancesAccount, BlockNumber, ResultBalance];
interface AllLocked {
allLocked: boolean,
lockedBalance: Balance,
lockedBreakdown: (BalanceLock | BalanceLockTo212)[],
vestingLocked: Balance
}
const VESTING_ID = '0x76657374696e6720';
function calcBalances (api: ApiInterfaceRx, [{ accountId, accountNonce, freeBalance, frozenFee, frozenMisc, reservedBalance, votingBalance }, bestNumber, [vesting, locks]]: Result): DeriveBalancesAll {
function calcLocked (api: ApiInterfaceRx, bestNumber: BlockNumber, locks: (BalanceLock | BalanceLockTo212)[]): AllLocked {
let lockedBalance = api.registry.createType('Balance');
let lockedBreakdown: (BalanceLock | BalanceLockTo212)[] = [];
let vestingLocked = api.registry.createType('Balance');
@@ -27,18 +34,22 @@ function calcBalances (api: ApiInterfaceRx, [{ accountId, accountNonce, freeBala
if (Array.isArray(locks)) {
// only get the locks that are valid until passed the current block
lockedBreakdown = (locks as BalanceLockTo212[]).filter(({ until }): boolean => !until || (bestNumber && until.gt(bestNumber)));
const notAll = lockedBreakdown.filter(({ amount }) => !amount.isMax());
allLocked = lockedBreakdown.some(({ amount }) => amount.isMax());
vestingLocked = api.registry.createType('Balance', lockedBreakdown.filter(({ id }) => id.eq(VESTING_ID)).reduce((result: BN, { amount }) => result.iadd(amount), new BN(0)));
// get the maximum of the locks according to https://github.com/paritytech/substrate/blob/master/srml/balances/src/lib.rs#L699
const notAll = lockedBreakdown.filter(({ amount }) => !amount.isMax());
if (notAll.length) {
lockedBalance = api.registry.createType('Balance', bnMax(...notAll.map(({ amount }): Balance => amount)));
}
}
return { allLocked, lockedBalance, lockedBreakdown, vestingLocked };
}
function calcBalances (api: ApiInterfaceRx, [{ accountId, accountNonce, freeBalance, frozenFee, frozenMisc, reservedBalance, votingBalance }, bestNumber, [vesting, locks]]: Result): DeriveBalancesAll {
const { allLocked, lockedBalance, lockedBreakdown, vestingLocked } = calcLocked(api, bestNumber, locks);
// Calculate the vesting balances,
// - offset = balance locked at startingBlock
// - perBlock is the unlock amount
+1
View File
@@ -5,4 +5,5 @@ export * from './bestNumber';
export * from './bestNumberFinalized';
export * from './bestNumberLag';
export * from './getHeader';
export * from './subscribeNewBlocks';
export * from './subscribeNewHeads';
@@ -0,0 +1,32 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ApiInterfaceRx } from '@polkadot/api/types';
import { EventRecord, Hash, SignedBlock } from '@polkadot/types/interfaces';
import { FullNewBlock } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
/**
* @name subscribeNewBlocks
* @returns The latest block & events for that block
*/
export function subscribeNewBlocks (instanceId: string, api: ApiInterfaceRx): () => Observable<FullNewBlock> {
return memo(instanceId, (): Observable<FullNewBlock> =>
api.derive.chain.subscribeNewHeads().pipe(
switchMap((header): Observable<[Hash, EventRecord[], SignedBlock]> => {
const blockHash = header.hash;
return combineLatest(
of(blockHash),
api.query.system.events.at(blockHash),
api.rpc.chain.getBlock(header.hash)
);
}),
map(([blockHash, events, block]) => ({ block: block.block, blockHash, blockNumber: block.block.header.number.unwrap(), events, justification: block.justification }))
)
);
}
@@ -11,7 +11,7 @@ import { memo } from '../util';
/**
* @name subscribeNewHeads
* @returns An array containing the block header and the block author
* @returns A header with the current header (including extracted author)
* @description An observable of the current block header and it's author
* @example
* <BR>
+12
View File
@@ -0,0 +1,12 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { Block, BlockNumber, EventRecord, Hash, Justification } from '@polkadot/types/interfaces';
export interface FullNewBlock {
block: Block;
blockHash: Hash;
blockNumber: BlockNumber;
events: EventRecord[];
justification: Justification;
}
+34 -14
View File
@@ -12,14 +12,14 @@ import { isFunction } from '@polkadot/util';
import { memo } from '../util';
type Result = [Hash[], Option<Proposal>[], Option<Votes>[]];
type Result = [(Hash | Uint8Array | string)[], Option<Proposal>[], Option<Votes>[]];
function parse ([hashes, proposals, votes]: Result): DeriveCollectiveProposal[] {
function parse (api: ApiInterfaceRx, [hashes, proposals, votes]: Result): DeriveCollectiveProposal[] {
return proposals
.map((proposalOpt, index): DeriveCollectiveProposal | null =>
proposalOpt.isSome
? {
hash: hashes[index],
hash: api.registry.createType('Hash', hashes[index]),
proposal: proposalOpt.unwrap(),
votes: votes[index].unwrapOr(null)
}
@@ -28,21 +28,41 @@ function parse ([hashes, proposals, votes]: Result): DeriveCollectiveProposal[]
.filter((proposal): proposal is DeriveCollectiveProposal => !!proposal);
}
export function proposals (instanceId: string, api: ApiInterfaceRx, section: 'council' | 'technicalCommittee'): () => Observable<DeriveCollectiveProposal[]> {
function _proposalsFrom (instanceId: string, api: ApiInterfaceRx, section: 'council' | 'technicalCommittee' = 'council'): (hashes: (Hash | Uint8Array | string)[]) => Observable<DeriveCollectiveProposal[]> {
return memo(instanceId, (hashes: (Hash | Uint8Array | string)[]): Observable<DeriveCollectiveProposal[]> =>
(isFunction(api.query[section]?.proposals) && hashes.length
? combineLatest<Result>([
of(hashes),
api.query[section].proposalOf.multi<Option<Proposal>>(hashes),
api.query[section].voting.multi<Option<Votes>>(hashes)
])
: of([[], [], []] as Result)
).pipe(
map((result) => parse(api, result))
)
);
}
export function proposals (instanceId: string, api: ApiInterfaceRx, section: 'council' | 'technicalCommittee' = 'council'): () => Observable<DeriveCollectiveProposal[]> {
const proposalsFrom = _proposalsFrom(instanceId, api, section);
return memo(instanceId, (): Observable<DeriveCollectiveProposal[]> =>
isFunction(api.query[section]?.proposals)
? 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(parse)
switchMap(proposalsFrom)
)
: of([] as DeriveCollectiveProposal[])
);
}
export function proposal (instanceId: string, api: ApiInterfaceRx, section: 'council' | 'technicalCommittee' = 'council'): (hash: Hash | Uint8Array | string) => Observable<DeriveCollectiveProposal | null> {
const proposalsFrom = _proposalsFrom(instanceId, api, section);
return memo(instanceId, (hash: Hash | Uint8Array | string): Observable<DeriveCollectiveProposal | null> =>
isFunction(api.query[section]?.proposals)
? proposalsFrom([hash]).pipe(
map(([proposal]) => proposal)
)
: of(null)
);
}
+9 -4
View File
@@ -2,12 +2,17 @@
// SPDX-License-Identifier: Apache-2.0
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveCollectiveProposals } from '../types';
import { Hash } from '@polkadot/types/interfaces';
import { DeriveCollectiveProposal } from '../types';
import { Observable } from 'rxjs';
import { proposals as collectiveProposals } from '../collective';
import { proposal as collectiveProposal, proposals as collectiveProposals } from '../collective';
import { memo } from '../util';
export function proposals (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveCollectiveProposals> {
return memo(instanceId, collectiveProposals(instanceId, api, 'council'));
export function proposal (instanceId: string, api: ApiInterfaceRx): (hash: Hash | Uint8Array | string) => Observable<DeriveCollectiveProposal | null> {
return memo(instanceId, collectiveProposal(instanceId, api));
}
export function proposals (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveCollectiveProposal[]> {
return memo(instanceId, collectiveProposals(instanceId, api));
}
+14 -15
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { AccountId, ReferendumInfo, ReferendumInfoTo239, VotingDelegating, VotingDirect, VotingDirectVote } from '@polkadot/types/interfaces';
import { AccountId, ReferendumInfo, ReferendumInfoFinished, ReferendumInfoTo239, Vote, VotingDelegating, VotingDirect, VotingDirectVote } from '@polkadot/types/interfaces';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveDemocracyLock } from '../types';
@@ -9,27 +9,26 @@ import BN from 'bn.js';
import { Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Option } from '@polkadot/types';
import { isUndefined } from '@polkadot/util';
import { BN_ZERO, isUndefined } from '@polkadot/util';
import { memo } from '../util';
const LOCKUPS = [0, 1, 2, 4, 8, 16, 32];
const ZERO = new BN(0);
function parseEnd (api: ApiInterfaceRx, vote: Vote, { approved, end }: ReferendumInfoFinished): [BN, BN] {
return [
end,
(approved.isTrue && vote.isAye) || (approved.isFalse && vote.isNay)
? end.add(api.consts.democracy.enactmentPeriod.muln(LOCKUPS[vote.conviction.index]))
: BN_ZERO
];
}
function parseLock (api: ApiInterfaceRx, [referendumId, accountVote]: VotingDirectVote, referendum: ReferendumInfo): DeriveDemocracyLock {
const { balance, vote } = accountVote.asStandard;
let unlockAt = ZERO;
let referendumEnd = ZERO;
if (referendum.isFinished) {
const { approved, end } = referendum.asFinished;
referendumEnd = end;
if ((approved.isTrue && vote.isAye) || (approved.isFalse && vote.isNay)) {
unlockAt = end.add(api.consts.democracy.enactmentPeriod.muln(LOCKUPS[vote.conviction.index]));
}
}
const [referendumEnd, unlockAt] = referendum.isFinished
? parseEnd(api, vote, referendum.asFinished)
: [BN_ZERO, BN_ZERO];
return { balance, isDelegated: false, isFinished: referendum.isFinished, referendumEnd, referendumId, unlockAt, vote };
}
@@ -40,31 +40,35 @@ function votesPrev (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveRef
);
}
function extractVotes (mapped: [AccountId, Voting][], referendumId: BN): DeriveReferendumVote[] {
return mapped
.filter(([, voting]) => voting.isDirect)
.map(([accountId, voting]): [AccountId, VotingDirectVote[]] => [
accountId,
voting.asDirect.votes.filter(([idx]) => idx.eq(referendumId))
])
.filter(([, directVotes]) => !!directVotes.length)
.reduce((result: DeriveReferendumVote[], [accountId, votes]) =>
// FIXME We are ignoring split votes
votes.reduce((result: DeriveReferendumVote[], [, vote]): DeriveReferendumVote[] => {
if (vote.isStandard) {
result.push({
accountId,
isDelegating: false,
...vote.asStandard
});
}
return result;
}, result), []
);
}
function votesCurr (api: ApiInterfaceRx, referendumId: BN): Observable<DeriveReferendumVote[]> {
return api.query.democracy.votingOf.entries<Voting>().pipe(
map((allVoting): DeriveReferendumVote[] => {
const mapped = allVoting.map(([key, voting]): [AccountId, Voting] => [key.args[0] as AccountId, voting]);
const votes = mapped
.filter(([, voting]) => voting.isDirect)
.map(([accountId, voting]): [AccountId, VotingDirectVote[]] => [
accountId,
voting.asDirect.votes.filter(([idx]) => idx.eq(referendumId))
])
.filter(([, directVotes]) => !!directVotes.length)
.reduce((result: DeriveReferendumVote[], [accountId, votes]) =>
// FIXME We are ignoring split votes
votes.reduce((result: DeriveReferendumVote[], [, vote]): DeriveReferendumVote[] => {
if (vote.isStandard) {
result.push({
accountId,
isDelegating: false,
...vote.asStandard
});
}
return result;
}, result), []
);
const votes = extractVotes(mapped, referendumId);
const delegations = mapped
.filter(([, voting]) => voting.isDelegating)
.map(([accountId, voting]): [AccountId, VotingDelegating] => [accountId, voting.asDelegating]);
+11 -16
View File
@@ -58,16 +58,20 @@ export function compareRationals (n1: BN, d1: BN, n2: BN, d2: BN): boolean {
}
}
export function calcPassing (threshold: VoteThreshold, sqrtElectorate: BN, { votedAye, votedNay, votedTotal }: ApproxState): boolean {
function calcPassingOther (threshold: VoteThreshold, sqrtElectorate: BN, { votedAye, votedNay, votedTotal }: ApproxState): boolean {
const sqrtVoters = bnSqrt(votedTotal);
return sqrtVoters.isZero()
? false
: threshold.isSimplemajority
? votedAye.gt(votedNay)
: threshold.isSupermajorityapproval
? compareRationals(votedNay, sqrtVoters, votedAye, sqrtElectorate)
: compareRationals(votedNay, sqrtElectorate, votedAye, sqrtVoters);
: threshold.isSupermajorityapproval
? compareRationals(votedNay, sqrtVoters, votedAye, sqrtElectorate)
: compareRationals(votedNay, sqrtElectorate, votedAye, sqrtVoters);
}
export function calcPassing (threshold: VoteThreshold, sqrtElectorate: BN, state: ApproxState): boolean {
return threshold.isSimplemajority
? state.votedAye.gt(state.votedNay)
: calcPassingOther(threshold, sqrtElectorate, state);
}
function calcVotesPrev (votesFor: DeriveReferendumVote[]): DeriveReferendumVoteState {
@@ -92,16 +96,7 @@ function calcVotesPrev (votesFor: DeriveReferendumVote[]): DeriveReferendumVoteS
state.votedTotal.iadd(counted);
return state;
}, {
allAye: [],
allNay: [],
voteCount: 0,
voteCountAye: 0,
voteCountNay: 0,
votedAye: new BN(0),
votedNay: new BN(0),
votedTotal: new BN(0)
});
}, { allAye: [], allNay: [], voteCount: 0, voteCountAye: 0, voteCountNay: 0, votedAye: new BN(0), votedNay: new BN(0), votedTotal: new BN(0) });
}
function calcVotesCurrent (tally: Tally, votes: DeriveReferendumVote[]): DeriveReferendumVoteState {
+7 -9
View File
@@ -10,6 +10,7 @@ import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { memo } from '../util';
import { didUpdateToBool } from './util';
type Result = [
Active,
@@ -23,7 +24,7 @@ type Result = [
];
function parseActive (id: ParaId, active: Active): DeriveParachainActive | null {
const found = active.find(([paraId]): boolean => paraId === id);
const found = active.find(([paraId]) => paraId === id);
if (found && found[1].isSome) {
const [collatorId, retriable] = found[1].unwrap();
@@ -48,12 +49,11 @@ function parseActive (id: ParaId, active: Active): DeriveParachainActive | null
}
function parseCollators (id: ParaId, collatorQueue: SelectedThreads | RetryQueue): (CollatorId | null)[] {
return collatorQueue
.map((queue): CollatorId | null => {
const found = queue.find(([paraId]): boolean => paraId === id);
return collatorQueue.map((queue): CollatorId | null => {
const found = queue.find(([paraId]) => paraId === id);
return found ? found[1] : null;
});
return found ? found[1] : null;
});
}
function parse (id: ParaId, [active, retryQueue, selectedThreads, didUpdate, info, pendingSwap, heads, relayDispatchQueue]: Result): DeriveParachainFull | null {
@@ -63,9 +63,7 @@ function parse (id: ParaId, [active, retryQueue, selectedThreads, didUpdate, inf
return {
active: parseActive(id, active),
didUpdate: didUpdate.isSome
? !!didUpdate.unwrap().some((paraId): boolean => paraId.eq(id))
: false,
didUpdate: didUpdateToBool(didUpdate, id),
heads,
id,
info: { id, ...info.unwrap() } as DeriveParachainInfo,
+9 -14
View File
@@ -10,6 +10,7 @@ import { map, switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { memo } from '../util';
import { didUpdateToBool } from './util';
type Result = [
ParaId[],
@@ -20,17 +21,13 @@ type Result = [
];
function parse ([ids, didUpdate, infos, pendingSwaps, relayDispatchQueueSizes]: Result): DeriveParachain[] {
return ids.map((id, index): DeriveParachain => {
return {
didUpdate: didUpdate.isSome
? !!didUpdate.unwrap().some((paraId): boolean => paraId.eq(id))
: false,
id,
info: { id, ...infos[index].unwrapOr(null) } as DeriveParachainInfo,
pendingSwapId: pendingSwaps[index].unwrapOr(null),
relayDispatchQueueSize: relayDispatchQueueSizes[index][0].toNumber()
};
});
return ids.map((id, index): DeriveParachain => ({
didUpdate: didUpdateToBool(didUpdate, id),
id,
info: { id, ...infos[index].unwrapOr(null) } as DeriveParachainInfo,
pendingSwapId: pendingSwaps[index].unwrapOr(null),
relayDispatchQueueSize: relayDispatchQueueSizes[index][0].toNumber()
}));
}
export function overview (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveParachain[]> {
@@ -46,9 +43,7 @@ export function overview (instanceId: string, api: ApiInterfaceRx): () => Observ
api.query.parachains.relayDispatchQueueSize.multi<RelayDispatchQueueSize>(paraIds)
])
),
map((result: Result): DeriveParachain[] =>
parse(result)
)
map(parse)
)
: of([] as DeriveParachain[])
);
@@ -0,0 +1,11 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ParaId } from '@polkadot/types/interfaces';
import { DidUpdate } from './types';
export function didUpdateToBool (didUpdate: DidUpdate, id: ParaId): boolean {
return didUpdate.isSome
? didUpdate.unwrap().some((paraId) => paraId.eq(id))
: false;
}
@@ -10,6 +10,7 @@ import { map, switchMap } from 'rxjs/operators';
import { BN_ZERO } from '@polkadot/util';
import { deriveCache, memo } from '../util';
import { filterEras } from './util';
const CACHE_KEY = 'eraPoints';
@@ -42,7 +43,7 @@ export function _erasPoints (instanceId: string, api: ApiInterfaceRx): (eras: Er
: eras
.map((era) => deriveCache.get<DeriveEraPoints>(`${CACHE_KEY}-${era.toString()}`))
.filter((value): value is DeriveEraPoints => !!value);
const remaining = eras.filter((era) => !cached.some((cached) => era.eq(cached.era)));
const remaining = filterEras(eras, cached);
return !remaining.length
? of(cached)
@@ -10,6 +10,7 @@ import { map, switchMap } from 'rxjs/operators';
import { Option } from '@polkadot/types';
import { deriveCache, memo } from '../util';
import { filterEras } from './util';
const CACHE_KEY = 'eraRewards';
@@ -31,7 +32,7 @@ export function _erasRewards (instanceId: string, api: ApiInterfaceRx): (eras: E
: eras
.map((era) => deriveCache.get<DeriveEraRewards>(`${CACHE_KEY}-${era.toString()}`))
.filter((value): value is DeriveEraRewards => !!value);
const remaining = eras.filter((era) => !cached.some((cached) => era.eq(cached.era)));
const remaining = filterEras(eras, cached);
if (!remaining.length) {
return of(cached);
@@ -12,6 +12,7 @@ import { Option } from '@polkadot/types';
import { isFunction } from '@polkadot/util';
import { memo } from '../util';
import { DeriveStakingQuery } from './types';
type ErasResult = [{ unwrapOr: (value: BN) => BN }, DeriveEraPoints[], DeriveEraPrefs[], DeriveEraRewards[]];
@@ -99,24 +100,37 @@ function filterEras (eras: EraIndex[], stakingLedger: StakingLedger): EraIndex[]
return eras.filter((era) => filterEra(era, stakingLedger));
}
function filterRewards (api: ApiInterfaceRx, eras: EraIndex[], migrateEra: BN, rewards: DeriveStakerReward[], stakingLedger: StakingLedger, withActive: boolean): Observable<DeriveStakerReward[]> {
if (withActive) {
return of(rewards);
}
function removeClaimed (validators: string[], queryValidators: DeriveStakingQuery[], reward: DeriveStakerReward): void {
const rm: string[] = [];
Object.keys(reward.validators).forEach((validatorId): void => {
const index = validators.indexOf(validatorId);
if (index !== -1) {
const valLedger = queryValidators[index].stakingLedger;
if (valLedger?.claimedRewards.some((era) => reward.era.eq(era))) {
rm.push(validatorId);
}
}
});
rm.forEach((validatorId): void => {
delete reward.validators[validatorId];
});
}
function filterRewards (api: ApiInterfaceRx, eras: EraIndex[], { migrateEra, rewards, stakingLedger }: { migrateEra: BN, rewards: DeriveStakerReward[]; stakingLedger: StakingLedger }): Observable<DeriveStakerReward[]> {
const validators = uniqValidators(rewards);
const filter = filterEras(eras, stakingLedger);
return (
isFunction(api.tx.staking.payoutStakers)
? api.derive.staking.queryMulti(validators)
: of([])
).pipe(
map((queryValidators): DeriveStakerReward[] => {
const filter = withActive
? eras
: filterEras(eras, stakingLedger);
return rewards
map((queryValidators): DeriveStakerReward[] =>
rewards
.filter(({ isEmpty }) => !isEmpty)
.filter((reward): boolean => {
if (!filter.some((filter) => reward.era.eq(filter))) {
@@ -128,32 +142,16 @@ function filterRewards (api: ApiInterfaceRx, eras: EraIndex[], migrateEra: BN, r
reward.isStakerPayout = true;
const rm: string[] = [];
Object.keys(reward.validators).forEach((validatorId): void => {
const index = validators.indexOf(validatorId);
if (index !== -1) {
const valLedger = queryValidators[index].stakingLedger;
if (valLedger?.claimedRewards.some((era) => reward.era.eq(era))) {
rm.push(validatorId);
}
}
});
rm.forEach((validatorId): void => {
delete reward.validators[validatorId];
});
removeClaimed(validators, queryValidators, reward);
return true;
})
.filter(({ validators }) => Object.keys(validators).length !== 0)
.map((reward) => ({
...reward,
nominators: reward.nominating.filter(({ validatorId }) => !!reward.validators[validatorId])
}));
})
nominators: reward.nominating.filter((n) => !!reward.validators[n.validatorId])
}))
)
);
}
@@ -178,13 +176,15 @@ export function _stakerRewards (instanceId: string, api: ApiInterfaceRx): (accou
api.derive.staking._stakerRewardsEras(eras, withActive)
]).pipe(
switchMap(([{ stakingLedger, stashId }, exposures, erasResult]): Observable<DeriveStakerReward[]> => {
const migrateEra: BN = erasResult[0].unwrapOr(ZERO);
if (!stashId || !stakingLedger) {
return of([]);
}
return filterRewards(api, eras, migrateEra, parseRewards(api, stashId, erasResult, exposures), stakingLedger, withActive);
const rewards = parseRewards(api, stashId, erasResult, exposures);
return withActive
? of(rewards)
: filterRewards(api, eras, { migrateEra: erasResult[0].unwrapOr(ZERO), rewards, stakingLedger });
})
)
);
+8
View File
@@ -0,0 +1,8 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { EraIndex } from '@polkadot/types/interfaces';
export function filterEras <T extends { era: EraIndex }> (eras: EraIndex[], list: T[]): EraIndex[] {
return eras.filter((era) => !list.some((entry) => era.eq(entry.era)));
}
@@ -2,12 +2,12 @@
// SPDX-License-Identifier: Apache-2.0
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveCollectiveProposals } from '../types';
import { DeriveCollectiveProposal } from '../types';
import { Observable } from 'rxjs';
import { proposals as collectiveProposals } from '../collective';
import { memo } from '../util';
export function proposals (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveCollectiveProposals> {
export function proposals (instanceId: string, api: ApiInterfaceRx): () => Observable<DeriveCollectiveProposal[]> {
return memo(instanceId, collectiveProposals(instanceId, api, 'technicalCommittee'));
}
@@ -3,7 +3,7 @@
import { ApiInterfaceRx } from '@polkadot/api/types';
import { ProposalIndex, TreasuryProposal } from '@polkadot/types/interfaces';
import { DeriveCollectiveProposals, DeriveTreasuryProposal, DeriveTreasuryProposals } from '../types';
import { DeriveCollectiveProposal, DeriveTreasuryProposal, DeriveTreasuryProposals } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
@@ -15,7 +15,7 @@ interface Result {
allIds: ProposalIndex[];
allProposals: Option<TreasuryProposal>[];
approvalIds: ProposalIndex[];
councilProposals: DeriveCollectiveProposals;
councilProposals: DeriveCollectiveProposal[];
proposalCount: ProposalIndex;
}
@@ -51,9 +51,7 @@ function retrieveProposals (api: ApiInterfaceRx, proposalCount: ProposalIndex, a
const count = proposalCount.toNumber();
for (let index = 0; index < count; index++) {
const isApproval = approvalIds.some((id): boolean => id.eqn(index));
if (!isApproval) {
if (!approvalIds.some((id) => id.eqn(index))) {
proposalIds.push(api.registry.createType('ProposalIndex', index));
}
}
@@ -64,7 +62,7 @@ function retrieveProposals (api: ApiInterfaceRx, proposalCount: ProposalIndex, a
api.query.treasury.proposals.multi<Option<TreasuryProposal>>(allIds),
api.derive.council.proposals()
]).pipe(
map(([allProposals, councilProposals]: [Option<TreasuryProposal>[], DeriveCollectiveProposals]): DeriveTreasuryProposals =>
map(([allProposals, councilProposals]: [Option<TreasuryProposal>[], DeriveCollectiveProposal[]]): DeriveTreasuryProposals =>
parseResult(api, { allIds, allProposals, approvalIds, councilProposals, proposalCount })
)
);
@@ -36,9 +36,9 @@ export default class HeaderExtended extends _Header {
/**
* @description Creates a human-friendly JSON representation
*/
public toHuman (isExtended?: boolean): AnyJson {
public toHuman (isExtended?: boolean): Record<string, AnyJson> {
return {
...super.toHuman(isExtended) as { [index: string]: AnyJson },
...super.toHuman(isExtended),
author: this.author
? this.author.toHuman()
: undefined
@@ -48,9 +48,9 @@ export default class HeaderExtended extends _Header {
/**
* @description Creates the JSON representation
*/
public toJSON (): AnyJson {
public toJSON (): Record<string, AnyJson> {
return {
...super.toJSON() as { [index: string]: AnyJson },
...super.toJSON(),
author: this.author
? this.author.toJSON()
: undefined
@@ -36,9 +36,9 @@ export default class BlockExtended extends _SignedBlock {
/**
* @description Creates a human-friendly JSON representation
*/
public toHuman (isExtended?: boolean): AnyJson {
public toHuman (isExtended?: boolean): Record<string, AnyJson> {
return {
...super.toHuman(isExtended) as { [index: string]: AnyJson },
...super.toHuman(isExtended),
author: this.author
? this.author.toHuman()
: undefined
@@ -48,9 +48,9 @@ export default class BlockExtended extends _SignedBlock {
/**
* @description Creates the JSON representation
*/
public toJSON (): AnyJson {
public toJSON (): Record<string, AnyJson> {
return {
...super.toJSON() as { [index: string]: AnyJson },
...super.toJSON(),
author: this.author
? this.author.toJSON()
: undefined
+1 -2
View File
@@ -7,6 +7,7 @@ import { AccountId, Balance, BalanceLock, BalanceLockTo212, BalanceOf, Bid, BidK
import { u32 } from '@polkadot/types';
export * from './accounts/types';
export * from './chain/types';
export * from './council/types';
export * from './democracy/types';
export * from './elections/types';
@@ -59,8 +60,6 @@ export interface DeriveCollectiveProposal {
votes: Votes | null;
}
export type DeriveCollectiveProposals = DeriveCollectiveProposal[];
export interface DeriveFees {
creationFee: Balance;
existentialDeposit: Balance;
+11 -11
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api",
"version": "2.3.1",
"version": "2.5.1",
"description": "Promise and RxJS wrappers around the Polkadot JS RPC",
"main": "index.js",
"keywords": [
@@ -27,20 +27,20 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api#readme",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@polkadot/api-derive": "2.3.1",
"@polkadot/keyring": "^3.6.1",
"@polkadot/metadata": "2.3.1",
"@polkadot/rpc-core": "2.3.1",
"@polkadot/rpc-provider": "2.3.1",
"@polkadot/types": "2.3.1",
"@polkadot/types-known": "2.3.1",
"@polkadot/util": "^3.6.1",
"@polkadot/util-crypto": "^3.6.1",
"@polkadot/api-derive": "^2.5.1",
"@polkadot/keyring": "^3.7.1",
"@polkadot/metadata": "^2.5.1",
"@polkadot/rpc-core": "^2.5.1",
"@polkadot/rpc-provider": "^2.5.1",
"@polkadot/types": "^2.5.1",
"@polkadot/types-known": "^2.5.1",
"@polkadot/util": "^3.7.1",
"@polkadot/util-crypto": "^3.7.1",
"bn.js": "^5.1.3",
"eventemitter3": "^4.0.7",
"rxjs": "^6.6.3"
},
"devDependencies": {
"@polkadot/keyring": "^3.6.1"
"@polkadot/keyring": "^3.7.1"
}
}
+12 -2
View File
@@ -2,7 +2,7 @@
/* eslint-disable */
import { AnyNumber, Codec, IExtrinsic, Observable } from '@polkadot/types/types';
import { HashMap, Option, Vec } from '@polkadot/types/codec';
import { HashMap, Json, Option, Vec } from '@polkadot/types/codec';
import { Bytes, Null, StorageKey, Text, bool, u32, u64 } from '@polkadot/types/primitive';
import { Metadata } from '@polkadot/types';
import { ExtrinsicOrHash, ExtrinsicStatus } from '@polkadot/types/interfaces/author';
@@ -19,7 +19,7 @@ import { RuntimeDispatchInfo } from '@polkadot/types/interfaces/payment';
import { RpcMethods } from '@polkadot/types/interfaces/rpc';
import { AccountId, BlockNumber, H256, Hash, Header, Index, Justification, KeyValue, SignedBlock, StorageData } from '@polkadot/types/interfaces/runtime';
import { ReadProof, RuntimeVersion } from '@polkadot/types/interfaces/state';
import { ApplyExtrinsicResult, ChainProperties, ChainType, Health, NetworkState, NodeRole, PeerInfo } from '@polkadot/types/interfaces/system';
import { ApplyExtrinsicResult, ChainProperties, ChainType, Health, NetworkState, NodeRole, PeerInfo, SyncState } from '@polkadot/types/interfaces/system';
declare module '@polkadot/rpc-core/types.jsonrpc' {
export interface RpcInterface {
@@ -245,6 +245,12 @@ declare module '@polkadot/rpc-core/types.jsonrpc' {
**/
subscribeStorage: AugmentedRpc<<T = Codec[]>(keys?: Vec<StorageKey> | (StorageKey | string | Uint8Array | any)[]) => Observable<T>>;
};
syncstate: {
/**
* Returns the json-serialized chainspec running the node, with a sync state.
**/
genSyncSpec: AugmentedRpc<(raw: bool | boolean | Uint8Array) => Observable<Json>>;
};
system: {
/**
* Retrieves the next accountIndex as available on the node
@@ -302,6 +308,10 @@ declare module '@polkadot/rpc-core/types.jsonrpc' {
* Remove a reserved peer
**/
removeReservedPeer: AugmentedRpc<(peerId: Text | string) => Observable<Text>>;
/**
* Returns the state of the syncing of the node
**/
syncState: AugmentedRpc<() => Observable<SyncState>>;
/**
* Retrieves the version of the node
**/
+29 -29
View File
@@ -65,7 +65,7 @@ declare module '@polkadot/api/types/submittable' {
* not assumed to be in the overlay.
* # </weight>
**/
forceTransfer: AugmentedSubmittable<(source: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, dest: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, value: Compact<Balance> | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
forceTransfer: AugmentedSubmittable<(source: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, dest: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, value: Compact<Balance> | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Set the balances of a given account.
*
@@ -86,7 +86,7 @@ declare module '@polkadot/api/types/submittable' {
* - DB Weight: 1 Read, 1 Write to `who`
* # </weight>
**/
setBalance: AugmentedSubmittable<(who: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, newFree: Compact<Balance> | AnyNumber | Uint8Array, newReserved: Compact<Balance> | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
setBalance: AugmentedSubmittable<(who: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, newFree: Compact<Balance> | AnyNumber | Uint8Array, newReserved: Compact<Balance> | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Transfer some liquid free balance to another account.
*
@@ -116,7 +116,7 @@ declare module '@polkadot/api/types/submittable' {
* - Origin account is already in memory, so no DB operations for them.
* # </weight>
**/
transfer: AugmentedSubmittable<(dest: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, value: Compact<Balance> | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
transfer: AugmentedSubmittable<(dest: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, value: Compact<Balance> | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Same as the [`transfer`] call, but with a check that the transfer will not kill the
* origin account.
@@ -130,7 +130,7 @@ declare module '@polkadot/api/types/submittable' {
* - DB Weight: 1 Read and 1 Write to dest (sender is in overlay already)
* #</weight>
**/
transferKeepAlive: AugmentedSubmittable<(dest: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, value: Compact<Balance> | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
transferKeepAlive: AugmentedSubmittable<(dest: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, value: Compact<Balance> | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
};
contracts: {
[key: string]: SubmittableExtrinsicFunction<ApiType>;
@@ -143,7 +143,7 @@ declare module '@polkadot/api/types/submittable' {
* * If no account exists and the call value is not less than `existential_deposit`,
* a regular account will be created and any value will be transferred.
**/
call: AugmentedSubmittable<(dest: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, value: Compact<BalanceOf> | AnyNumber | Uint8Array, gasLimit: Compact<Gas> | AnyNumber | Uint8Array, data: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
call: AugmentedSubmittable<(dest: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, value: Compact<BalanceOf> | AnyNumber | Uint8Array, gasLimit: Compact<Gas> | AnyNumber | Uint8Array, data: Bytes | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Allows block producers to claim a small reward for evicting a contract. If a block producer
* fails to do so, a regular users will be allowed to claim the reward.
@@ -391,7 +391,7 @@ declare module '@polkadot/api/types/submittable' {
* Weight: `O(R)` where R is the number of referendums the voter delegating to has
* voted on. Weight is charged as if maximum votes.
**/
delegate: AugmentedSubmittable<(to: AccountId | string | Uint8Array, conviction: Conviction | 'None'|'Locked1x'|'Locked2x'|'Locked3x'|'Locked4x'|'Locked5x'|'Locked6x' | number | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
delegate: AugmentedSubmittable<(to: AccountId | string | Uint8Array, conviction: Conviction | 'None' | 'Locked1x' | 'Locked2x' | 'Locked3x' | 'Locked4x' | 'Locked5x' | 'Locked6x' | number | Uint8Array, balance: BalanceOf | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Schedule an emergency cancellation of a referendum. Cannot happen twice to the same
* referendum.
@@ -666,7 +666,7 @@ declare module '@polkadot/api/types/submittable' {
* Else, since this is a root call and will go into phragmen, we assume full block for now.
* # </weight>
**/
removeMember: AugmentedSubmittable<(who: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, hasReplacement: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>>;
removeMember: AugmentedSubmittable<(who: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, hasReplacement: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Remove `origin` as a voter. This removes the lock and returns the bond.
*
@@ -872,7 +872,7 @@ declare module '@polkadot/api/types/submittable' {
* The dispatch origin for this call must be _Signed_ and the sender must have a registered
* sub identity of `sub`.
**/
addSub: AugmentedSubmittable<(sub: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, data: Data | { None: any } | { Raw: any } | { BlakeTwo256: any } | { Sha256: any } | { Keccak256: any } | { ShaThree256: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
addSub: AugmentedSubmittable<(sub: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, data: Data | { None: any } | { Raw: any } | { BlakeTwo256: any } | { Sha256: any } | { Keccak256: any } | { ShaThree256: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Cancel a previous request.
*
@@ -935,7 +935,7 @@ declare module '@polkadot/api/types/submittable' {
* - One event.
* # </weight>
**/
killIdentity: AugmentedSubmittable<(target: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
killIdentity: AugmentedSubmittable<(target: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Provide a judgement for an account's identity.
*
@@ -957,7 +957,7 @@ declare module '@polkadot/api/types/submittable' {
* - One event.
* # </weight>
**/
provideJudgement: AugmentedSubmittable<(regIndex: Compact<RegistrarIndex> | AnyNumber | Uint8Array, target: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, judgement: IdentityJudgement | { Unknown: any } | { FeePaid: any } | { Reasonable: any } | { KnownGood: any } | { OutOfDate: any } | { LowQuality: any } | { Erroneous: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
provideJudgement: AugmentedSubmittable<(regIndex: Compact<RegistrarIndex> | AnyNumber | Uint8Array, target: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, judgement: IdentityJudgement | { Unknown: any } | { FeePaid: any } | { Reasonable: any } | { KnownGood: any } | { OutOfDate: any } | { LowQuality: any } | { Erroneous: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Remove the sender as a sub-account.
*
@@ -980,14 +980,14 @@ declare module '@polkadot/api/types/submittable' {
* The dispatch origin for this call must be _Signed_ and the sender must have a registered
* sub identity of `sub`.
**/
removeSub: AugmentedSubmittable<(sub: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
removeSub: AugmentedSubmittable<(sub: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Alter the associated name of the given sub-account.
*
* The dispatch origin for this call must be _Signed_ and the sender must have a registered
* sub identity of `sub`.
**/
renameSub: AugmentedSubmittable<(sub: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, data: Data | { None: any } | { Raw: any } | { BlakeTwo256: any } | { Sha256: any } | { Keccak256: any } | { ShaThree256: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
renameSub: AugmentedSubmittable<(sub: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, data: Data | { None: any } | { Raw: any } | { BlakeTwo256: any } | { Sha256: any } | { Keccak256: any } | { ShaThree256: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Request a judgement from a registrar.
*
@@ -1392,7 +1392,7 @@ declare module '@polkadot/api/types/submittable' {
* Weight is a function of the number of proxies the user has (P).
* # </weight>
**/
addProxy: AugmentedSubmittable<(delegate: AccountId | string | Uint8Array, proxyType: ProxyType | 'Any'|'NonTransfer'|'Governance'|'Staking' | number | Uint8Array, delay: BlockNumber | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
addProxy: AugmentedSubmittable<(delegate: AccountId | string | Uint8Array, proxyType: ProxyType | 'Any' | 'NonTransfer' | 'Governance' | 'Staking' | number | Uint8Array, delay: BlockNumber | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Publish the hash of a proxy-call that will be made in the future.
*
@@ -1442,7 +1442,7 @@ declare module '@polkadot/api/types/submittable' {
* # </weight>
* TODO: Might be over counting 1 read
**/
anonymous: AugmentedSubmittable<(proxyType: ProxyType | 'Any'|'NonTransfer'|'Governance'|'Staking' | number | Uint8Array, delay: BlockNumber | AnyNumber | Uint8Array, index: u16 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
anonymous: AugmentedSubmittable<(proxyType: ProxyType | 'Any' | 'NonTransfer' | 'Governance' | 'Staking' | number | Uint8Array, delay: BlockNumber | AnyNumber | Uint8Array, index: u16 | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Removes a previously spawned anonymous proxy.
*
@@ -1465,7 +1465,7 @@ declare module '@polkadot/api/types/submittable' {
* Weight is a function of the number of proxies the user has (P).
* # </weight>
**/
killAnonymous: AugmentedSubmittable<(spawner: AccountId | string | Uint8Array, proxyType: ProxyType | 'Any'|'NonTransfer'|'Governance'|'Staking' | number | Uint8Array, index: u16 | AnyNumber | Uint8Array, height: Compact<BlockNumber> | AnyNumber | Uint8Array, extIndex: Compact<u32> | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
killAnonymous: AugmentedSubmittable<(spawner: AccountId | string | Uint8Array, proxyType: ProxyType | 'Any' | 'NonTransfer' | 'Governance' | 'Staking' | number | Uint8Array, index: u16 | AnyNumber | Uint8Array, height: Compact<BlockNumber> | AnyNumber | Uint8Array, extIndex: Compact<u32> | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Dispatch the given `call` from an account that the sender is authorised for through
* `add_proxy`.
@@ -1568,7 +1568,7 @@ declare module '@polkadot/api/types/submittable' {
* Weight is a function of the number of proxies the user has (P).
* # </weight>
**/
removeProxy: AugmentedSubmittable<(delegate: AccountId | string | Uint8Array, proxyType: ProxyType | 'Any'|'NonTransfer'|'Governance'|'Staking' | number | Uint8Array, delay: BlockNumber | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
removeProxy: AugmentedSubmittable<(delegate: AccountId | string | Uint8Array, proxyType: ProxyType | 'Any' | 'NonTransfer' | 'Governance' | 'Staking' | number | Uint8Array, delay: BlockNumber | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
};
recovery: {
[key: string]: SubmittableExtrinsicFunction<ApiType>;
@@ -1999,7 +1999,7 @@ declare module '@polkadot/api/types/submittable' {
* Total Complexity: O(M + logM + B + X)
* # </weight>
**/
judgeSuspendedCandidate: AugmentedSubmittable<(who: AccountId | string | Uint8Array, judgement: SocietyJudgement | 'Rebid'|'Reject'|'Approve' | number | Uint8Array) => SubmittableExtrinsic<ApiType>>;
judgeSuspendedCandidate: AugmentedSubmittable<(who: AccountId | string | Uint8Array, judgement: SocietyJudgement | 'Rebid' | 'Reject' | 'Approve' | number | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Allow suspension judgement origin to make judgement on a suspended member.
*
@@ -2149,7 +2149,7 @@ declare module '@polkadot/api/types/submittable' {
* Total Complexity: O(M + logM + C)
* # </weight>
**/
vote: AugmentedSubmittable<(candidate: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, approve: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>>;
vote: AugmentedSubmittable<(candidate: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, approve: bool | boolean | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* As a member, vouch for someone to join society by placing a bid on their behalf.
*
@@ -2224,7 +2224,7 @@ declare module '@polkadot/api/types/submittable' {
* - Write: Bonded, Payee, [Origin Account], Locks, Ledger
* # </weight>
**/
bond: AugmentedSubmittable<(controller: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, value: Compact<BalanceOf> | AnyNumber | Uint8Array, payee: RewardDestination | { Staked: any } | { Stash: any } | { Controller: any } | { Account: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
bond: AugmentedSubmittable<(controller: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, value: Compact<BalanceOf> | AnyNumber | Uint8Array, payee: RewardDestination | { Staked: any } | { Stash: any } | { Controller: any } | { Account: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Add some extra amount that have appeared in the stash `free_balance` into the balance up
* for staking.
@@ -2365,7 +2365,7 @@ declare module '@polkadot/api/types/submittable' {
* - Writes: Validators, Nominators
* # </weight>
**/
nominate: AugmentedSubmittable<(targets: Vec<LookupSource> | (LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>>;
nominate: AugmentedSubmittable<(targets: Vec<LookupSource> | (LookupSource | Address | AccountId | AccountIndex | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>>;
/**
* Pay out all the stakers behind a single validator for a single era.
*
@@ -2460,7 +2460,7 @@ declare module '@polkadot/api/types/submittable' {
* - Write: Bonded, Ledger New Controller, Ledger Old Controller
* # </weight>
**/
setController: AugmentedSubmittable<(controller: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
setController: AugmentedSubmittable<(controller: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Set `HistoryDepth` value. This function will delete any history information
* when `HistoryDepth` is reduced.
@@ -2693,7 +2693,7 @@ declare module '@polkadot/api/types/submittable' {
* - One DB change.
* # </weight>
**/
setKey: AugmentedSubmittable<(updated: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
setKey: AugmentedSubmittable<(updated: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Authenticates the sudo key and dispatches a function call with `Root` origin.
*
@@ -2720,7 +2720,7 @@ declare module '@polkadot/api/types/submittable' {
* - Weight of derivative `call` execution + 10,000.
* # </weight>
**/
sudoAs: AugmentedSubmittable<(who: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, call: Call | { callIndex?: any; args?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
sudoAs: AugmentedSubmittable<(who: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, call: Call | { callIndex?: any; args?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Authenticates the sudo key and dispatches a function call with `Root` origin.
* This function does not check the weight of the call, and instead allows the
@@ -3103,7 +3103,7 @@ declare module '@polkadot/api/types/submittable' {
* - `bounty_id`: Bounty ID to award.
* - `beneficiary`: The beneficiary account whom will receive the payout.
**/
awardBounty: AugmentedSubmittable<(bountyId: Compact<ProposalIndex> | AnyNumber | Uint8Array, beneficiary: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
awardBounty: AugmentedSubmittable<(bountyId: Compact<ProposalIndex> | AnyNumber | Uint8Array, beneficiary: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Claim the payout from an awarded bounty after payout delay.
*
@@ -3176,7 +3176,7 @@ declare module '@polkadot/api/types/submittable' {
* - One DB change.
* # </weight>
**/
proposeCurator: AugmentedSubmittable<(bountyId: Compact<ProposalIndex> | AnyNumber | Uint8Array, curator: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, fee: Compact<BalanceOf> | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
proposeCurator: AugmentedSubmittable<(bountyId: Compact<ProposalIndex> | AnyNumber | Uint8Array, curator: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, fee: Compact<BalanceOf> | AnyNumber | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Put forward a suggestion for spending. A deposit proportional to the value
* is reserved and slashed if the proposal is rejected. It is returned once the
@@ -3188,7 +3188,7 @@ declare module '@polkadot/api/types/submittable' {
* - DbWrites: `ProposalCount`, `Proposals`, `origin account`
* # </weight>
**/
proposeSpend: AugmentedSubmittable<(value: Compact<BalanceOf> | AnyNumber | Uint8Array, beneficiary: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
proposeSpend: AugmentedSubmittable<(value: Compact<BalanceOf> | AnyNumber | Uint8Array, beneficiary: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Reject a proposed spend. The original deposit will be slashed.
*
@@ -3385,7 +3385,7 @@ declare module '@polkadot/api/types/submittable' {
* - Writes: Vesting Storage, Balances Locks, Target Account, Source Account
* # </weight>
**/
forceVestedTransfer: AugmentedSubmittable<(source: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, target: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, schedule: VestingInfo | { locked?: any; perBlock?: any; startingBlock?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
forceVestedTransfer: AugmentedSubmittable<(source: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, target: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, schedule: VestingInfo | { locked?: any; perBlock?: any; startingBlock?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Unlock any vested funds of the sender account.
*
@@ -3419,7 +3419,7 @@ declare module '@polkadot/api/types/submittable' {
* - Writes: Vesting Storage, Balances Locks, Target Account
* # </weight>
**/
vestOther: AugmentedSubmittable<(target: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
vestOther: AugmentedSubmittable<(target: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
/**
* Create a vested transfer.
*
@@ -3438,7 +3438,7 @@ declare module '@polkadot/api/types/submittable' {
* - Writes: Vesting Storage, Balances Locks, Target Account, [Sender Account]
* # </weight>
**/
vestedTransfer: AugmentedSubmittable<(target: LookupSource | Address | AccountId | AccountIndex | LookupSource | string | Uint8Array, schedule: VestingInfo | { locked?: any; perBlock?: any; startingBlock?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
vestedTransfer: AugmentedSubmittable<(target: LookupSource | Address | AccountId | AccountIndex | string | Uint8Array, schedule: VestingInfo | { locked?: any; perBlock?: any; startingBlock?: any } | string | Uint8Array) => SubmittableExtrinsic<ApiType>>;
};
}
+53 -36
View File
@@ -1,10 +1,10 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { Constants, Storage } from '@polkadot/metadata/Decorated/types';
import { Constants, DecoratedMeta } from '@polkadot/metadata/decorate/types';
import { RpcInterface } from '@polkadot/rpc-core/types';
import { Call, Hash, RuntimeVersion } from '@polkadot/types/interfaces';
import { AnyFunction, CallFunction, Codec, CodecArg as Arg, InterfaceTypes, ModulesWithCalls, Registry, RegistryTypes } from '@polkadot/types/types';
import { AnyFunction, CallFunction, Codec, CodecArg as Arg, InterfaceTypes, Registry, RegistryTypes } from '@polkadot/types/types';
import { SubmittableExtrinsic } from '../submittable/types';
import { ApiInterfaceRx, ApiOptions, ApiTypes, DecorateMethod, DecoratedRpc, DecoratedRpcSection, PaginationOptions, QueryableConsts, QueryableModuleStorage, QueryableStorage, QueryableStorageEntry, QueryableStorageMulti, QueryableStorageMultiArg, SubmittableExtrinsicFunction, SubmittableExtrinsics, SubmittableModuleExtrinsics } from '../types';
@@ -13,7 +13,7 @@ import { BehaviorSubject, Observable, combineLatest, of } from 'rxjs';
import { map, switchMap, take, tap, toArray } from 'rxjs/operators';
import decorateDerive, { ExactDerive } from '@polkadot/api-derive';
import { memo } from '@polkadot/api-derive/util';
import DecoratedMeta from '@polkadot/metadata/Decorated';
import { expandMetadata } from '@polkadot/metadata';
import RpcCore from '@polkadot/rpc-core';
import { WsProvider } from '@polkadot/rpc-provider';
import { Metadata, Option, Raw, Text, TypeRegistry, u64 } from '@polkadot/types';
@@ -172,22 +172,22 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
}
public injectMetadata (metadata: Metadata, fromEmpty?: boolean, registry?: Registry): void {
const decoratedMeta = new DecoratedMeta(registry || this.#registry, metadata);
const decoratedMeta = expandMetadata(registry || this.#registry, metadata);
if (fromEmpty || !this._extrinsics) {
this._extrinsics = this._decorateExtrinsics(decoratedMeta.tx, this._decorateMethod);
this._rx.tx = this._decorateExtrinsics(decoratedMeta.tx, this._rxDecorateMethod);
this._extrinsics = this._decorateExtrinsics(decoratedMeta, this._decorateMethod);
this._rx.tx = this._decorateExtrinsics(decoratedMeta, this._rxDecorateMethod);
} else {
augmentObject('tx', this._decorateExtrinsics(decoratedMeta.tx, this._decorateMethod), this._extrinsics, false);
augmentObject(null, this._decorateExtrinsics(decoratedMeta.tx, this._rxDecorateMethod), this._rx.tx, false);
augmentObject('tx', this._decorateExtrinsics(decoratedMeta, this._decorateMethod), this._extrinsics, false);
augmentObject(null, this._decorateExtrinsics(decoratedMeta, this._rxDecorateMethod), this._rx.tx, false);
}
// this API
augmentObject('query', this._decorateStorage(decoratedMeta.query, this._decorateMethod), this._query, fromEmpty);
augmentObject('query', this._decorateStorage(decoratedMeta, this._decorateMethod), this._query, fromEmpty);
augmentObject('consts', decoratedMeta.consts, this._consts, fromEmpty);
// rx
augmentObject(null, this._decorateStorage(decoratedMeta.query, this._rxDecorateMethod), this._rx.query, fromEmpty);
augmentObject(null, this._decorateStorage(decoratedMeta, this._rxDecorateMethod), this._rx.query, fromEmpty);
augmentObject(null, decoratedMeta.consts, this._rx.consts, fromEmpty);
}
@@ -225,7 +225,7 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
protected _filterRpcMethods (exposed: string[]): void {
const hasResults = exposed.length !== 0;
const allKnown = [...this._rpcCore.mapping.entries()];
const allKeys = allKnown.reduce((allKeys: string[], [, { alias, method, pubsub, section }]): string[] => {
const allKeys = allKnown.reduce((allKeys: string[], [, { alias, endpoint, method, pubsub, section }]): string[] => {
allKeys.push(`${section}_${method}`);
if (pubsub) {
@@ -237,6 +237,10 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
allKeys.push(...alias);
}
if (endpoint) {
allKeys.push(endpoint);
}
return allKeys;
}, []);
const unknown = exposed.filter((key) => !allKeys.includes(key));
@@ -270,6 +274,8 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
if (this.hasSubscriptions || !(methodName.startsWith('subscribe') || methodName.startsWith('unsubscribe'))) {
(section as Record<string, unknown>)[methodName] = decorateMethod(method, { methodName }) as unknown;
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
(section as Record<string, { json: unknown }>)[methodName].json = decorateMethod(method.json, { methodName }) as unknown;
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
(section as Record<string, { raw: unknown }>)[methodName].raw = decorateMethod(method.raw, { methodName }) as unknown;
}
@@ -284,18 +290,16 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return decorateMethod((calls: QueryableStorageMultiArg<ApiType>[]): Observable<Codec[]> =>
this._rpcCore.state.subscribeStorage(
calls.map((arg: QueryableStorageMultiArg<ApiType>): [QueryableStorageEntry<ApiType>, ...Arg[]] =>
// the input is a QueryableStorageEntry, convert to StorageEntry
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
calls.map((arg: QueryableStorageMultiArg<ApiType>) =>
Array.isArray(arg)
? [arg[0].creator, ...arg.slice(1)]
: [arg.creator] as any)));
: [arg.creator])));
}
protected _decorateExtrinsics<ApiType extends ApiTypes> (extrinsics: ModulesWithCalls, decorateMethod: DecorateMethod<ApiType>): SubmittableExtrinsics<ApiType> {
protected _decorateExtrinsics<ApiType extends ApiTypes> ({ tx }: DecoratedMeta, decorateMethod: DecorateMethod<ApiType>): SubmittableExtrinsics<ApiType> {
const creator = createSubmittable(this._type, this._rx, decorateMethod);
return Object.entries(extrinsics).reduce((out, [name, section]): SubmittableExtrinsics<ApiType> => {
return Object.entries(tx).reduce((out, [name, section]): SubmittableExtrinsics<ApiType> => {
out[name] = Object.entries(section).reduce((out, [name, method]): SubmittableModuleExtrinsics<ApiType> => {
out[name] = this._decorateExtrinsicEntry(method, creator);
@@ -314,8 +318,8 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
return this._decorateFunctionMeta(method as any, decorated as any) as unknown as SubmittableExtrinsicFunction<ApiType>;
}
protected _decorateStorage<ApiType extends ApiTypes> (storage: Storage, decorateMethod: DecorateMethod<ApiType>): QueryableStorage<ApiType> {
return Object.entries(storage).reduce((out, [name, section]): QueryableStorage<ApiType> => {
protected _decorateStorage<ApiType extends ApiTypes> ({ query }: DecoratedMeta, decorateMethod: DecorateMethod<ApiType>): QueryableStorage<ApiType> {
return Object.entries(query).reduce((out, [name, section]): QueryableStorage<ApiType> => {
out[name] = Object.entries(section).reduce((out, [name, method]): QueryableModuleStorage<ApiType> => {
out[name] = this._decorateStorageEntry(method, decorateMethod);
@@ -359,7 +363,11 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
if (creator.iterKey && (creator.meta.type.isMap || creator.meta.type.isDoubleMap)) {
decorated.entries = decorateMethod(
memo(this.#instanceId, (doubleMapArg?: Arg): Observable<[StorageKey, Codec][]> =>
this._retrieveMapEntries(creator, doubleMapArg)));
this._retrieveMapEntries(creator, null, doubleMapArg)));
decorated.entriesAt = decorateMethod(
memo(this.#instanceId, (hash: Hash | Uint8Array | string, doubleMapArg?: Arg): Observable<[StorageKey, Codec][]> =>
this._retrieveMapEntries(creator, hash, doubleMapArg)));
decorated.entriesPaged = decorateMethod(
memo(this.#instanceId, (opts: PaginationOptions): Observable<[StorageKey, Codec][]> =>
@@ -367,7 +375,11 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
decorated.keys = decorateMethod(
memo(this.#instanceId, (doubleMapArg?: Arg): Observable<StorageKey[]> =>
this._retrieveMapKeys(creator, doubleMapArg)));
this._retrieveMapKeys(creator, null, doubleMapArg)));
decorated.keysAt = decorateMethod(
memo(this.#instanceId, (hash: Hash | Uint8Array | string, doubleMapArg?: Arg): Observable<StorageKey[]> =>
this._retrieveMapKeys(creator, hash, doubleMapArg)));
decorated.keysPaged = decorateMethod(
memo(this.#instanceId, (opts: PaginationOptions): Observable<StorageKey[]> =>
@@ -416,16 +428,19 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
));
}
private _retrieveMapKeys ({ iterKey, meta }: StorageEntry, arg?: Arg): Observable<StorageKey[]> {
private _retrieveMapKeys ({ iterKey, meta, method, section }: StorageEntry, at: Hash | Uint8Array | string | null, arg?: Arg): Observable<StorageKey[]> {
assert(iterKey && (meta.type.isMap || meta.type.isDoubleMap), 'keys can only be retrieved on maps, linked maps and double maps');
const headKey = iterKey(arg).toHex();
const startSubject = new BehaviorSubject<string>(headKey);
const query = at
? (startKey: string) => this._rpcCore.state.getKeysPaged(headKey, PAGE_SIZE_KEYS, startKey, at)
: (startKey: string) => this._rpcCore.state.getKeysPaged(headKey, PAGE_SIZE_KEYS, startKey);
return startSubject.pipe(
switchMap((startKey) =>
this._rpcCore.state.getKeysPaged(headKey, PAGE_SIZE_KEYS, startKey).pipe(
map((keys) => keys.map((key) => key.setMeta(meta)))
query(startKey).pipe(
map((keys) => keys.map((key) => key.setMeta(meta, section, method)))
)
),
tap((keys): void => {
@@ -438,31 +453,33 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
);
}
private _retrieveMapKeysPaged ({ iterKey, meta }: StorageEntry, opts: PaginationOptions): Observable<StorageKey[]> {
private _retrieveMapKeysPaged ({ iterKey, meta, method, section }: StorageEntry, opts: PaginationOptions): Observable<StorageKey[]> {
assert(iterKey && (meta.type.isMap || meta.type.isDoubleMap), 'keys can only be retrieved on maps, linked maps and double maps');
const headKey = iterKey(opts.arg).toHex();
return this._rpcCore.state.getKeysPaged(headKey, opts.pageSize, opts.startKey || headKey).pipe(
map((keys) => keys.map((key) => key.setMeta(meta)))
map((keys) => keys.map((key) => key.setMeta(meta, section, method)))
);
}
private _retrieveMapEntries (entry: StorageEntry, arg?: Arg): Observable<[StorageKey, Codec][]> {
return this._retrieveMapKeys(entry, arg).pipe(
private _retrieveMapEntries (entry: StorageEntry, at: Hash | Uint8Array | string | null, arg?: Arg): Observable<[StorageKey, Codec][]> {
const query = this._rpcCore.state.queryStorageAt
? at
? (keyset: StorageKey[]) => this._rpcCore.state.queryStorageAt<Codec[]>(keyset, at)
: (keyset: StorageKey[]) => this._rpcCore.state.queryStorageAt<Codec[]>(keyset)
// this is horrible, but need older support (which now doesn't work with at)
: (keyset: StorageKey[]) => this._rpcCore.state.subscribeStorage<Codec[]>(keyset).pipe(take(1));
return this._retrieveMapKeys(entry, at, arg).pipe(
switchMap((keys) =>
combineLatest<[StorageKey[], ...Codec[][]]>([
of(keys),
...Array(Math.ceil(keys.length / PAGE_SIZE_VALS))
.fill(0)
.map((_, index): Observable<Codec[]> => {
const keyset = keys.slice(index * PAGE_SIZE_VALS, (index * PAGE_SIZE_VALS) + PAGE_SIZE_VALS);
return this._rpcCore.state.queryStorageAt
? this._rpcCore.state.queryStorageAt<Codec[]>(keyset)
// this is horrible, but need older support
: this._rpcCore.state.subscribeStorage<Codec[]>(keyset).pipe(take(1));
})
.map((_, index): Observable<Codec[]> =>
query(keys.slice(index * PAGE_SIZE_VALS, (index * PAGE_SIZE_VALS) + PAGE_SIZE_VALS))
)
])
),
map(([keys, ...valsArr]): [StorageKey, Codec][] =>
+214
View File
@@ -0,0 +1,214 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { RpcInterface } from '@polkadot/rpc-core/types';
import { Hash, RuntimeVersion } from '@polkadot/types/interfaces';
import { ApiInterfaceRx, ApiTypes, DecoratedRpc, QueryableConsts, QueryableStorage, QueryableStorageMulti, SubmittableExtrinsics } from '../types';
import { Metadata, Text } from '@polkadot/types';
import { assertReturn } from '@polkadot/util';
import Init from './Init';
interface PkgJson {
name: string;
version: string;
}
let pkgJson: PkgJson = { name: '@polkadot/api', version: '-' };
import('../package.json')
.then((_pkgJson: unknown): void => {
pkgJson = _pkgJson as PkgJson;
})
.catch((): void => {
// ignore
});
function assertResult<T> (value: T | undefined): T {
return assertReturn(value, 'Api needs to be initialized before using, listen on \'ready\'');
}
export default abstract class Getters<ApiType extends ApiTypes> extends Init<ApiType> {
/**
* @description Contains the parameter types (constants) of all modules.
*
* The values are instances of the appropriate type and are accessible using `section`.`constantName`,
*
* @example
* <BR>
*
* ```javascript
* console.log(api.consts.democracy.enactmentPeriod.toString())
* ```
*/
public get consts (): QueryableConsts<ApiType> {
return assertResult(this._consts);
}
/**
* @description Derived results that are injected into the API, allowing for combinations of various query results.
*
* @example
* <BR>
*
* ```javascript
* api.derive.chain.bestNumber((number) => {
* console.log('best number', number);
* });
* ```
*/
public get derive (): ReturnType<Getters<ApiType>['_decorateDerive']> {
return assertResult(this._derive);
}
/**
* @description Returns the version of extrinsics in-use on this chain
*/
public get extrinsicVersion (): number {
return this._extrinsicType;
}
/**
* @description Contains the genesis Hash of the attached chain. Apart from being useful to determine the actual chain, it can also be used to sign immortal transactions.
*/
public get genesisHash (): Hash {
return assertResult(this._genesisHash);
}
/**
* @description `true` when subscriptions are supported
*/
public get hasSubscriptions (): boolean {
return this._rpcCore.provider.hasSubscriptions;
}
/**
* @description true is the underlying provider is connected
*/
public get isConnected (): boolean {
return this._isConnected.getValue();
}
/**
* @description The library information name & version (from package.json)
*/
public get libraryInfo (): string {
return `${pkgJson.name} v${pkgJson.version}`;
}
/**
* @description Contains all the chain state modules and their subsequent methods in the API. These are attached dynamically from the runtime metadata.
*
* All calls inside the namespace, is denoted by `section`.`method` and may take an optional query parameter. As an example, `api.query.timestamp.now()` (current block timestamp) does not take parameters, while `api.query.system.account(<accountId>)` (retrieving the associated nonce & balances for an account), takes the `AccountId` as a parameter.
*
* @example
* <BR>
*
* ```javascript
* api.query.system.account(<accountId>, ([nonce, balance]) => {
* console.log('new free balance', balance.free, 'new nonce', nonce);
* });
* ```
*/
public get query (): QueryableStorage<ApiType> {
return assertResult(this._query);
}
/**
* @description Allows for the querying of multiple storage entries and the combination thereof into a single result. This is a very optimal way to make multiple queries since it only makes a single connection to the node and retrieves the data over one subscription.
*
* @example
* <BR>
*
* ```javascript
* const unsub = await api.queryMulti(
* [
* // you can include the storage without any parameters
* api.query.balances.totalIssuance,
* // or you can pass parameters to the storage query
* [api.query.system.account, '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY']
* ],
* ([existential, [, { free }]]) => {
* console.log(`You have ${free.sub(existential)} more than the existential deposit`);
*
* unsub();
* }
* );
* ```
*/
public get queryMulti (): QueryableStorageMulti<ApiType> {
return assertResult(this._queryMulti);
}
/**
* @description Contains all the raw rpc sections and their subsequent methods in the API as defined by the jsonrpc interface definitions. Unlike the dynamic `api.query` and `api.tx` sections, these methods are fixed (although extensible with node upgrades) and not determined by the runtime.
*
* RPC endpoints available here allow for the query of chain, node and system information, in addition to providing interfaces for the raw queries of state (using known keys) and the submission of transactions.
*
* @example
* <BR>
*
* ```javascript
* api.rpc.chain.subscribeNewHeads((header) => {
* console.log('new header', header);
* });
* ```
*/
public get rpc (): DecoratedRpc<ApiType, RpcInterface> {
return assertResult(this._rpc);
}
/**
* @description Contains the chain information for the current node.
*/
public get runtimeChain (): Text {
return assertResult(this._runtimeChain);
}
/**
* @description Yields the current attached runtime metadata. Generally this is only used to construct extrinsics & storage, but is useful for current runtime inspection.
*/
public get runtimeMetadata (): Metadata {
return assertResult(this._runtimeMetadata);
}
/**
* @description Contains the version information for the current runtime.
*/
public get runtimeVersion (): RuntimeVersion {
return assertResult(this._runtimeVersion);
}
/**
* @description The underlying Rx API interface
*/
public get rx (): Pick<ApiInterfaceRx, 'tx' | 'rpc'> {
return assertResult(this._rx as Pick<ApiInterfaceRx, 'tx' | 'rpc'>);
}
/**
* @description The type of this API instance, either 'rxjs' or 'promise'
*/
public get type (): ApiTypes {
return this._type;
}
/**
* @description Contains all the extrinsic modules and their subsequent methods in the API. It allows for the construction of transactions and the submission thereof. These are attached dynamically from the runtime metadata.
*
* @example
* <BR>
*
* ```javascript
* api.tx.balances
* .transfer(<recipientId>, <balance>)
* .signAndSend(<keyPair>, ({status}) => {
* console.log('tx status', status.asFinalized.toHex());
* });
* ```
*/
public get tx (): SubmittableExtrinsics<ApiType> {
return assertResult(this._extrinsics);
}
}
+4 -210
View File
@@ -1,15 +1,12 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { RpcInterface } from '@polkadot/rpc-core/types';
import { Hash, RuntimeVersion } from '@polkadot/types/interfaces';
import { CallFunction, RegistryError, SignerPayloadRawBase } from '@polkadot/types/types';
import { ApiInterfaceRx, ApiOptions, ApiTypes, DecoratedRpc, DecorateMethod, QueryableConsts, QueryableStorage, QueryableStorageMulti, SubmittableExtrinsics, Signer } from '../types';
import { ApiOptions, ApiTypes, DecorateMethod, Signer } from '../types';
import { Metadata, Text } from '@polkadot/types';
import { assert, isString, isUndefined, u8aToHex, u8aToU8a } from '@polkadot/util';
import { assert, isString, u8aToHex, u8aToU8a } from '@polkadot/util';
import Init from './Init';
import Getters from './Getters';
interface KeyringSigner {
sign (message: Uint8Array): Uint8Array;
@@ -19,28 +16,7 @@ interface SignerRawOptions {
signer?: Signer;
}
interface PkgJson {
name: string;
version: string;
}
let pkgJson: PkgJson = { name: '@polkadot/api', version: '-' };
import('../package.json')
.then((_pkgJson: unknown): void => {
pkgJson = _pkgJson as PkgJson;
})
.catch((): void => {
// ignore
});
function assertResult<T> (value: T | undefined): T {
assert(!isUndefined(value), 'Api needs to be initialized before using, listen on \'ready\'');
return value;
}
export default abstract class ApiBase<ApiType extends ApiTypes> extends Init<ApiType> {
export default abstract class ApiBase<ApiType extends ApiTypes> extends Getters<ApiType> {
/**
* @description Create an instance of the class
*
@@ -63,188 +39,6 @@ export default abstract class ApiBase<ApiType extends ApiTypes> extends Init<Api
super(options, type, decorateMethod);
}
/**
* @description Contains the parameter types (constants) of all modules.
*
* The values are instances of the appropriate type and are accessible using `section`.`constantName`,
*
* @example
* <BR>
*
* ```javascript
* console.log(api.consts.democracy.enactmentPeriod.toString())
* ```
*/
public get consts (): QueryableConsts<ApiType> {
return assertResult(this._consts);
}
/**
* @description Derived results that are injected into the API, allowing for combinations of various query results.
*
* @example
* <BR>
*
* ```javascript
* api.derive.chain.bestNumber((number) => {
* console.log('best number', number);
* });
* ```
*/
public get derive (): ReturnType<ApiBase<ApiType>['_decorateDerive']> {
return assertResult(this._derive);
}
/**
* @description Returns the version of extrinsics in-use on this chain
*/
public get extrinsicVersion (): number {
return this._extrinsicType;
}
/**
* @description Contains the genesis Hash of the attached chain. Apart from being useful to determine the actual chain, it can also be used to sign immortal transactions.
*/
public get genesisHash (): Hash {
return assertResult(this._genesisHash);
}
/**
* @description `true` when subscriptions are supported
*/
public get hasSubscriptions (): boolean {
return this._rpcCore.provider.hasSubscriptions;
}
/**
* @description true is the underlying provider is connected
*/
public get isConnected (): boolean {
return this._isConnected.getValue();
}
/**
* @description The library information name & version (from package.json)
*/
public get libraryInfo (): string {
return `${pkgJson.name} v${pkgJson.version}`;
}
/**
* @description Contains all the chain state modules and their subsequent methods in the API. These are attached dynamically from the runtime metadata.
*
* All calls inside the namespace, is denoted by `section`.`method` and may take an optional query parameter. As an example, `api.query.timestamp.now()` (current block timestamp) does not take parameters, while `api.query.system.account(<accountId>)` (retrieving the associated nonce & balances for an account), takes the `AccountId` as a parameter.
*
* @example
* <BR>
*
* ```javascript
* api.query.system.account(<accountId>, ([nonce, balance]) => {
* console.log('new free balance', balance.free, 'new nonce', nonce);
* });
* ```
*/
public get query (): QueryableStorage<ApiType> {
return assertResult(this._query);
}
/**
* @description Allows for the querying of multiple storage entries and the combination thereof into a single result. This is a very optimal way to make multiple queries since it only makes a single connection to the node and retrieves the data over one subscription.
*
* @example
* <BR>
*
* ```javascript
* const unsub = await api.queryMulti(
* [
* // you can include the storage without any parameters
* api.query.balances.totalIssuance,
* // or you can pass parameters to the storage query
* [api.query.system.account, '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY']
* ],
* ([existential, [, { free }]]) => {
* console.log(`You have ${free.sub(existential)} more than the existential deposit`);
*
* unsub();
* }
* );
* ```
*/
public get queryMulti (): QueryableStorageMulti<ApiType> {
return assertResult(this._queryMulti);
}
/**
* @description Contains all the raw rpc sections and their subsequent methods in the API as defined by the jsonrpc interface definitions. Unlike the dynamic `api.query` and `api.tx` sections, these methods are fixed (although extensible with node upgrades) and not determined by the runtime.
*
* RPC endpoints available here allow for the query of chain, node and system information, in addition to providing interfaces for the raw queries of state (using known keys) and the submission of transactions.
*
* @example
* <BR>
*
* ```javascript
* api.rpc.chain.subscribeNewHeads((header) => {
* console.log('new header', header);
* });
* ```
*/
public get rpc (): DecoratedRpc<ApiType, RpcInterface> {
return assertResult(this._rpc);
}
/**
* @description Contains the chain information for the current node.
*/
public get runtimeChain (): Text {
return assertResult(this._runtimeChain);
}
/**
* @description Yields the current attached runtime metadata. Generally this is only used to construct extrinsics & storage, but is useful for current runtime inspection.
*/
public get runtimeMetadata (): Metadata {
return assertResult(this._runtimeMetadata);
}
/**
* @description Contains the version information for the current runtime.
*/
public get runtimeVersion (): RuntimeVersion {
return assertResult(this._runtimeVersion);
}
/**
* @description The underlying Rx API interface
*/
public get rx (): Pick<ApiInterfaceRx, 'tx' | 'rpc'> {
return assertResult(this._rx as Pick<ApiInterfaceRx, 'tx' | 'rpc'>);
}
/**
* @description The type of this API instance, either 'rxjs' or 'promise'
*/
public get type (): ApiTypes {
return this._type;
}
/**
* @description Contains all the extrinsic modules and their subsequent methods in the API. It allows for the construction of transactions and the submission thereof. These are attached dynamically from the runtime metadata.
*
* @example
* <BR>
*
* ```javascript
* api.tx.balances
* .transfer(<recipientId>, <balance>)
* .signAndSend(<keyPair>, ({status}) => {
* console.log('tx status', status.asFinalized.toHex());
* });
* ```
*/
public get tx (): SubmittableExtrinsics<ApiType> {
return assertResult(this._extrinsics);
}
/**
* @description Connect from the underlying provider, halting all network traffic
*/
+1 -1
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { Constants } from '@polkadot/metadata/Decorated/types';
import { Constants } from '@polkadot/metadata/decorate/types';
import { Metadata } from '@polkadot/types';
import { Registry } from '@polkadot/types/types';
+11 -13
View File
@@ -53,9 +53,8 @@ async function query (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
// check multi for unsub
const multiUnsub = await api.queryMulti([
[api.query.system.account, keyring.eve.address],
// older chains only
[api.query.system.accountNonce, keyring.bob.address]
[api.query.staking.validators],
[api.query.system.events]
], (values): void => {
console.log('values', values);
@@ -66,11 +65,13 @@ async function query (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
const multiRes = await api.queryMulti([
[api.query.system.account, keyring.eve.address],
// older chains only
[api.query.system.accountNonce, keyring.bob.address]
[api.query.system.accountNonce, keyring.eve.address]
]);
console.log(multiRes);
}
async function queryExtra (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
// events destructing
await api.query.system.events((records): void => {
records.forEach(({ event, phase }): void => {
@@ -114,7 +115,8 @@ async function rpc (api: ApiPromise): Promise<void> {
console.log('current balance:', balance.toString());
});
// using raw
// using json & raw
await api.rpc.chain.getBlock.json('0x123456');
await api.rpc.chain.getBlock.raw('0x123456');
// using raw subs
@@ -141,8 +143,7 @@ async function tx (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
// transfer, also allows for BigInt inputs here
const transfer = api.tx.balances.transfer(keyring.bob.address, 123456789n);
console.log('transfer as Call', transfer as IMethod);
console.log('transfer as Extrinsic', transfer as IExtrinsic);
console.log('transfer casted', transfer as IMethod, transfer as IExtrinsic);
// simple "return the hash" variant
console.log('hash:', (await transfer.signAndSend(keyring.alice)).toHex());
@@ -158,9 +159,7 @@ async function tx (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
// just with the callback
await api.tx.balances
.transfer(keyring.bob.address, 12345)
.signAndSend(keyring.alice, ({ status }: SubmittableResult): void => {
console.log('transfer status:', status.type);
});
.signAndSend(keyring.alice, ({ status }: SubmittableResult) => console.log(status.type));
// with options and the callback
const nonce2 = await api.query.system.accountNonce(keyring.alice.address);
@@ -176,9 +175,7 @@ async function tx (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
const second = api.tx.democracy.second(123, 5);
// eslint-disable-next-line @typescript-eslint/no-floating-promises
second.signAndSend('123', (result): void => {
console.log(result);
});
await second.signAndSend('123', (result) => console.log(result));
// it handles enum inputs correctly
await api.tx.democracy.proxyVote(123, { Split: { nay: 456, yay: 123 } }).signAndSend(keyring.alice);
@@ -193,6 +190,7 @@ async function main (): Promise<void> {
consts(api),
derive(api),
query(api, keyring),
queryExtra(api, keyring),
rpc(api),
types(api),
tx(api, keyring)
+1 -1
View File
@@ -8,7 +8,7 @@ import { detectPackage } from '@polkadot/util';
detectPackage(require('./package.json'), typeof __dirname !== 'undefined' && __dirname);
export { Keyring } from '@polkadot/keyring';
export { WsProvider } from '@polkadot/rpc-provider';
export { default as WsProvider } from '@polkadot/rpc-provider/ws';
export { default as ApiPromise } from './promise';
export { default as ApiRx } from './rx';
+1 -3
View File
@@ -46,9 +46,7 @@ export default class Combinator<T extends any[] = any[]> {
}
protected _allHasFired (): boolean {
if (!this.#allHasFired) {
this.#allHasFired = this.#fired.filter((hasFired): boolean => !hasFired).length === 0;
}
this.#allHasFired ||= this.#fired.filter((hasFired): boolean => !hasFired).length === 0;
return this.#allHasFired;
}
+40 -23
View File
@@ -3,10 +3,10 @@
/* eslint-disable no-dupe-class-members */
import { Address, Call, Extrinsic, ExtrinsicEra, ExtrinsicStatus, Hash, Header, Index, RuntimeDispatchInfo } from '@polkadot/types/interfaces';
import { Address, ApplyExtrinsicResult, Call, Extrinsic, ExtrinsicEra, ExtrinsicStatus, Hash, Header, Index, RuntimeDispatchInfo } from '@polkadot/types/interfaces';
import { Callback, Codec, Constructor, IKeyringPair, Registry, SignatureOptions, ISubmittableResult } from '@polkadot/types/types';
import { ApiInterfaceRx, ApiTypes, SignerResult } from '../types';
import { AddressOrPair, SignerOptions, SubmittableExtrinsic, SubmittablePaymentResult, SubmittableResultResult, SubmittableResultSubscription, SubmittableThis } from './types';
import { AddressOrPair, SignerOptions, SubmittableExtrinsic, SubmittableDryRunResult, SubmittablePaymentResult, SubmittableResultResult, SubmittableResultSubscription, SubmittableThis } from './types';
import { Observable, of } from 'rxjs';
import { first, map, mapTo, mergeMap, switchMap, tap } from 'rxjs/operators';
@@ -39,11 +39,22 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
this.#ignoreStatusCb = apiType === 'rxjs';
}
// adds a transform to the result, applied before result is returned
withResultTransform (transform: (input: ISubmittableResult) => ISubmittableResult): this {
this.#transformResult = transform;
// dry run an extrinsic
public dryRun (account: AddressOrPair, optionsOrHash?: Partial<SignerOptions> | Uint8Array | string): SubmittableDryRunResult<ApiType> {
if (isString(optionsOrHash) || isU8a(optionsOrHash)) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return decorateMethod(
() => api.rpc.system.dryRun(this.toHex(), optionsOrHash)
);
}
return this;
// eslint-disable-next-line @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-call
return decorateMethod(
(): Observable<ApplyExtrinsicResult> =>
this.#observeSign(account, optionsOrHash).pipe(
switchMap(() => api.rpc.system.dryRun(this.toHex()))
)
)();
}
// calculate the payment info for this transaction (if signed and submitted)
@@ -51,7 +62,7 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
if (isString(optionsOrHash) || isU8a(optionsOrHash)) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return decorateMethod(
() => api.rpc.payment.queryInfo(this.toHex(), optionsOrHash)
(): Observable<RuntimeDispatchInfo> => api.rpc.payment.queryInfo(this.toHex(), optionsOrHash)
);
}
@@ -68,7 +79,6 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
const eraOptions = this.#makeEraOptions(allOptions, signingInfo);
const signOptions = this.#makeSignOptions(eraOptions, {});
// add a fake signature to the extrinsic
this.signFake(address, signOptions);
return api.rpc.payment.queryInfo(this.toHex());
@@ -77,6 +87,24 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
)();
}
// send with an immediate Hash result
public send (): SubmittableResultResult<ApiType>;
// send with a status callback
public send (statusCb: Callback<ISubmittableResult>): SubmittableResultSubscription<ApiType>;
// send implementation for both immediate Hash and statusCb variants
public send (statusCb?: Callback<ISubmittableResult>): SubmittableResultResult<ApiType> | SubmittableResultSubscription<ApiType> {
const isSubscription = api.hasSubscriptions && (this.#ignoreStatusCb || !!statusCb);
// eslint-disable-next-line @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-call
return decorateMethod(
isSubscription
? this.#observeSubscribe
: this.#observeSend
)(statusCb);
}
/**
* @description Sign a transaction, returning the this to allow chaining, i.e. .sign(...).send(). When options, e.g. nonce/blockHash are not specified, it will be inferred. To retrieve eg. nonce use `signAsync` (the preferred interface, this is provided for backwards compatibility)
* @deprecated
@@ -125,22 +153,11 @@ export default function createClass <ApiType extends ApiTypes> ({ api, apiType,
)(statusCb);
}
// send with an immediate Hash result
public send (): SubmittableResultResult<ApiType>;
// adds a transform to the result, applied before result is returned
withResultTransform (transform: (input: ISubmittableResult) => ISubmittableResult): this {
this.#transformResult = transform;
// send with a status callback
public send (statusCb: Callback<ISubmittableResult>): SubmittableResultSubscription<ApiType>;
// send implementation for both immediate Hash and statusCb variants
public send (statusCb?: Callback<ISubmittableResult>): SubmittableResultResult<ApiType> | SubmittableResultSubscription<ApiType> {
const isSubscription = api.hasSubscriptions && (this.#ignoreStatusCb || !!statusCb);
// eslint-disable-next-line @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-call
return decorateMethod(
isSubscription
? this.#observeSubscribe
: this.#observeSend
)(statusCb);
return this;
}
#makeEraOptions = (options: Partial<SignerOptions>, { header, mortalLength, nonce }: { header: Header | null; mortalLength: number; nonce: Index }): SignatureOptions => {
+16 -9
View File
@@ -1,7 +1,7 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { AccountId, Address, DispatchError, DispatchInfo, Extrinsic, ExtrinsicStatus, EventRecord, Hash, RuntimeDispatchInfo } from '@polkadot/types/interfaces';
import { AccountId, Address, ApplyExtrinsicResult, DispatchError, DispatchInfo, Extrinsic, ExtrinsicStatus, EventRecord, Hash, RuntimeDispatchInfo } from '@polkadot/types/interfaces';
import { AnyNumber, Callback, Codec, IExtrinsicEra, IKeyringPair, Signer, ISubmittableResult } from '@polkadot/types/types';
import { ApiTypes } from '../types';
@@ -14,6 +14,11 @@ export interface SubmittableResultValue {
status: ExtrinsicStatus;
}
export type SubmittableDryRunResult<ApiType extends ApiTypes> =
ApiType extends 'rxjs'
? Observable<ApplyExtrinsicResult>
: Promise<ApplyExtrinsicResult>;
export type SubmittablePaymentResult<ApiType extends ApiTypes> =
ApiType extends 'rxjs'
? Observable<RuntimeDispatchInfo>
@@ -45,24 +50,26 @@ export interface SignerOptions {
export type AddressOrPair = IKeyringPair | string | AccountId | Address;
export interface SubmittableExtrinsic<ApiType extends ApiTypes, R extends ISubmittableResult = ISubmittableResult> extends Extrinsic {
withResultTransform (transform: (input: ISubmittableResult) => ISubmittableResult): this;
dryRun (account: AddressOrPair, options?: Partial<SignerOptions>): SubmittableDryRunResult<ApiType>;
paymentInfo (account: AddressOrPair, options?: Partial<SignerOptions>): SubmittablePaymentResult<ApiType>;
send(): SubmittableResultResult<ApiType>;
send (): SubmittableResultResult<ApiType>;
send(statusCb: Callback<R>): SubmittableResultSubscription<ApiType, R>;
send (statusCb: Callback<R>): SubmittableResultSubscription<ApiType, R>;
/**
* @deprecated
*/
sign(account: IKeyringPair, _options?: Partial<SignerOptions>): this;
sign (account: IKeyringPair, _options?: Partial<SignerOptions>): this;
signAsync(account: AddressOrPair, _options?: Partial<SignerOptions>): SubmittableThis<ApiType, this>;
signAsync (account: AddressOrPair, _options?: Partial<SignerOptions>): SubmittableThis<ApiType, this>;
signAndSend(account: AddressOrPair, options?: Partial<SignerOptions>): SubmittableResultResult<ApiType, R>;
signAndSend (account: AddressOrPair, options?: Partial<SignerOptions>): SubmittableResultResult<ApiType, R>;
signAndSend(account: AddressOrPair, statusCb: Callback<R>): SubmittableResultSubscription<ApiType>;
signAndSend (account: AddressOrPair, statusCb: Callback<R>): SubmittableResultSubscription<ApiType>;
signAndSend(account: AddressOrPair, options: Partial<SignerOptions>, statusCb?: Callback<R>): SubmittableResultSubscription<ApiType, R>;
signAndSend (account: AddressOrPair, options: Partial<SignerOptions>, statusCb?: Callback<R>): SubmittableResultSubscription<ApiType, R>;
withResultTransform (transform: (input: ISubmittableResult) => ISubmittableResult): this;
}
+8 -6
View File
@@ -1,24 +1,26 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { AnyFunction, Callback, Codec } from '@polkadot/types/types';
import { AnyFunction, Callback } from '@polkadot/types/types';
import { Observable } from 'rxjs';
import { Json, Raw } from '@polkadot/types/codec';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { ApiTypes, Push, PromiseResult, RxResult, UnsubscribePromise } from './base';
export interface RpcRxResult<F extends AnyFunction> extends RxResult<F> {
raw (...args: Parameters<F>): Observable<Uint8Array & Codec>;
json (...args: Parameters<F>): Observable<Json>;
raw (...args: Parameters<F>): Observable<Raw>;
}
export interface RpcPromiseResult<F extends AnyFunction> extends PromiseResult<F> {
raw (...args: Parameters<F>): Promise<Uint8Array & Codec>;
raw (...args: Push<Parameters<F>, Callback<Uint8Array & Codec>>): UnsubscribePromise;
json (...args: Parameters<F>): Promise<Json>;
json (...args: Push<Parameters<F>, Callback<Json>>): UnsubscribePromise;
raw (...args: Parameters<F>): Promise<Raw>;
raw (...args: Push<Parameters<F>, Callback<Raw>>): UnsubscribePromise;
}
// FIXME The day TS has higher-kinded types, we can remove this hardcoded stuff
export type RpcMethodResult<ApiType extends ApiTypes, F extends AnyFunction> = ApiType extends 'rxjs'
? RpcRxResult<F>
: RpcPromiseResult<F>;
+2
View File
@@ -40,11 +40,13 @@ export interface StorageEntryBase<ApiType extends ApiTypes, F extends AnyFunctio
at: <T extends Codec | any = ObsInnerType<ReturnType<F>>>(hash: Hash | Uint8Array | string, ...args: Parameters<F>) => PromiseOrObs<ApiType, T>;
creator: StorageEntry;
entries: <T extends Codec | any = ObsInnerType<ReturnType<F>>>(arg?: Parameters<F>[0]) => PromiseOrObs<ApiType, [StorageKey, T][]>;
entriesAt: <T extends Codec | any = ObsInnerType<ReturnType<F>>>(hash: Hash | Uint8Array | string, arg?: Parameters<F>[0]) => PromiseOrObs<ApiType, [StorageKey, T][]>;
entriesPaged: <T extends Codec | any = ObsInnerType<ReturnType<F>>>(opts: PaginationOptions<Parameters<F>[0]>) => PromiseOrObs<ApiType, [StorageKey, T][]>;
hash: (...args: Parameters<F>) => PromiseOrObs<ApiType, Hash>;
key: (...args: Parameters<F>) => string;
keyPrefix: () => string;
keys: (arg?: any) => PromiseOrObs<ApiType, StorageKey[]>;
keysAt: (hash: Hash | Uint8Array | string, arg?: any) => PromiseOrObs<ApiType, StorageKey[]>;
keysPaged: (opts: PaginationOptions<Parameters<F>[0]>) => PromiseOrObs<ApiType, StorageKey[]>;
range: <T extends Codec | any = ObsInnerType<ReturnType<F>>>([from, to]: [Hash | Uint8Array | string, Hash | Uint8Array | string | undefined] | [Hash | Uint8Array | string], ...args: Parameters<F>) => PromiseOrObs<ApiType, [Hash, T][]>;
size: (...args: Parameters<F>) => PromiseOrObs<ApiType, u64>;

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