Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ca79f2f70 | ||
|
|
8fb64f77cd | ||
|
|
d1f86ce78e | ||
|
|
64ff226535 | ||
|
|
e762746ff0 | ||
|
|
ce5c8f7443 | ||
|
|
fc4cbb608c | ||
|
|
7ac3043f83 | ||
|
|
44b56fb0cb | ||
|
|
758ce567e5 | ||
|
|
cb5308b476 | ||
|
|
a9211690be | ||
|
|
a7db14a261 | ||
|
|
3a1f284fa8 | ||
|
|
a0b6c42629 | ||
|
|
f77ae4d99f | ||
|
|
5fa9af8fd3 | ||
|
|
1ff029dc11 | ||
|
|
4c8c9fbb07 | ||
|
|
7057cf365b | ||
|
|
d1bc48e936 | ||
|
|
2dee50f019 | ||
|
|
fa76378702 | ||
|
|
e855da1f13 | ||
|
|
adffde368c | ||
|
|
5278138cc3 | ||
|
|
98249a282e | ||
|
|
b7eeb992cd | ||
|
|
01daf32646 | ||
|
|
51a866fd35 | ||
|
|
53401e29ea | ||
|
|
774f41e6db | ||
|
|
1ca3b295a4 | ||
|
|
82828d8e09 | ||
|
|
131055c1d5 | ||
|
|
bd2e690261 | ||
|
|
1a2ca8ea38 | ||
|
|
0c98593aee | ||
|
|
416e2fbc96 | ||
|
|
c04fb9073e | ||
|
|
4f85ceb2c3 | ||
|
|
9196ce85a0 | ||
|
|
26734bf8bf | ||
|
|
53959d482d | ||
|
|
0a0f110c42 | ||
|
|
47f1350652 | ||
|
|
3c3b7290c2 | ||
|
|
006c686c18 | ||
|
|
44d4a07005 | ||
|
|
6e61be960c | ||
|
|
bd57359dc5 | ||
|
|
10bc6b4060 | ||
|
|
9e681c0666 | ||
|
|
e969382fd0 | ||
|
|
1949a13810 | ||
|
|
362262c4e1 | ||
|
|
ddd5eab7f5 | ||
|
|
1da6193f34 | ||
|
|
c4e553ad80 | ||
|
|
0b83a61600 | ||
|
|
382f7d75c8 | ||
|
|
88e4518f64 | ||
|
|
b1a657d68a | ||
|
|
067f17b28b | ||
|
|
99073e2a88 | ||
|
|
f9a42e47e7 | ||
|
|
b80d72edbd | ||
|
|
1f7b9f7f3a | ||
|
|
843efb2146 | ||
|
|
3619fabe5f | ||
|
|
bf598e392e | ||
|
|
f026137545 | ||
|
|
2264f53a43 | ||
|
|
8ba4029633 | ||
|
|
05cb2cef5a | ||
|
|
3a70594594 | ||
|
|
019cb58dd1 | ||
|
|
d487490ca0 | ||
|
|
b9fad61da0 | ||
|
|
77bf33b4e4 | ||
|
|
7ed7c9d3a8 | ||
|
|
0d2896630d | ||
|
|
74dbff32df | ||
|
|
4653cc0d84 | ||
|
|
50e115f6a1 | ||
|
|
8a5a86e8b3 | ||
|
|
48ef5af93f | ||
|
|
e5c20be666 | ||
|
|
6bf0d5eea9 | ||
|
|
21c57b60a1 | ||
|
|
b1dff22954 | ||
|
|
a3d0cb0999 | ||
|
|
bf946c20db | ||
|
|
664d2c8ab6 | ||
|
|
01a4d6b4a9 | ||
|
|
18454083db | ||
|
|
191abe4e08 | ||
|
|
97fbb4732d | ||
|
|
01f3666cc7 | ||
|
|
468fcdccaa | ||
|
|
c8dd26b0da | ||
|
|
61d5dec63a | ||
|
|
64a4bb2e17 | ||
|
|
f78bf9dde1 | ||
|
|
b7ba654e48 | ||
|
|
532a252fe0 | ||
|
|
614cf4e484 | ||
|
|
c576c689d0 | ||
|
|
d86cd94fe2 | ||
|
|
762b16ea13 | ||
|
|
09a72c0f31 | ||
|
|
eded5fede2 | ||
|
|
704df82b1d | ||
|
|
46efc10939 | ||
|
|
74cf8aa30c | ||
|
|
7a60ab81f8 | ||
|
|
c1d7ca67d5 | ||
|
|
7e1eb0fab0 | ||
|
|
af76d7fb04 | ||
|
|
afbe072ad5 | ||
|
|
d86c5be413 | ||
|
|
a695d2a5b5 | ||
|
|
1c087967d3 | ||
|
|
906732bcdc | ||
|
|
c9352af81c | ||
|
|
e2e8e3fedd | ||
|
|
3ca07a5bc8 | ||
|
|
89700f98c5 | ||
|
|
0cae3cf0fa | ||
|
|
eade586044 | ||
|
|
c227c6625c | ||
|
|
4cb8462d50 | ||
|
|
1d671d531c | ||
|
|
a49cd799dd | ||
|
|
8ed2bda3a8 | ||
|
|
2aabbe3cce | ||
|
|
7b37cc79a3 | ||
|
|
34a719e443 | ||
|
|
b440c9b0ea | ||
|
|
03e9a9676f | ||
|
|
094d6f7a1c | ||
|
|
33fd1b1c78 | ||
|
|
9968aa4606 | ||
|
|
9c337422a5 | ||
|
|
cc432e2291 | ||
|
|
aaff64404a | ||
|
|
bfe788cd31 | ||
|
|
883b191ae7 | ||
|
|
fa46debb90 | ||
|
|
ed4af1d04b | ||
|
|
4cea617b13 | ||
|
|
26b6a59725 | ||
|
|
35c63a52c8 | ||
|
|
61bc20aa7b | ||
|
|
db59fbff25 | ||
|
|
49b3104d04 | ||
|
|
2338ecc2d7 | ||
|
|
bab8c852a4 | ||
|
|
cba17aeb55 | ||
|
|
deca8ad216 | ||
|
|
fb4c840549 | ||
|
|
610234c1a1 | ||
|
|
7f39c573ce | ||
|
|
114c437671 | ||
|
|
e12f2f67c6 | ||
|
|
0c61850ad6 | ||
|
|
8b1a7a8584 | ||
|
|
4b6b0305e6 | ||
|
|
3b758a0d64 | ||
|
|
ea2c320f33 | ||
|
|
306857ae07 | ||
|
|
448ecd13bb | ||
|
|
011e24bd49 | ||
|
|
099992627b | ||
|
|
74e20864a6 | ||
|
|
d006f051a3 | ||
|
|
f1fe498801 | ||
|
|
1f2cd5a6f7 | ||
|
|
d6239cbe56 | ||
|
|
d82bb63acb | ||
|
|
a3ae4cf5d2 | ||
|
|
6b74ea39c2 | ||
|
|
87aab2eca5 | ||
|
|
1c6a2582f3 | ||
|
|
ea49095334 | ||
|
|
b2daf7482f | ||
|
|
b0165e41e7 | ||
|
|
0a27f63423 | ||
|
|
20d8a31258 | ||
|
|
ca186a4b2c | ||
|
|
7bd593c8f7 | ||
|
|
75220eb54f | ||
|
|
dde7d49598 | ||
|
|
a31921b88e | ||
|
|
a4c5ca45b2 | ||
|
|
c44cb1858e | ||
|
|
f89867a9ae | ||
|
|
be4b9a4133 | ||
|
|
46b1429da9 | ||
|
|
a70af20eba | ||
|
|
09dc78d6b1 | ||
|
|
921e329d18 | ||
|
|
f86aebf7e1 | ||
|
|
eef1c5327b | ||
|
|
2c25936e2c | ||
|
|
734213a2f9 | ||
|
|
16e0ea9315 | ||
|
|
c87ba33893 | ||
|
|
2875fdf2cf | ||
|
|
e73c147275 | ||
|
|
f080d6ed1c | ||
|
|
8ea07727ba | ||
|
|
3c47c3fdc3 | ||
|
|
06418913e5 | ||
|
|
188363d407 | ||
|
|
ec79087bab | ||
|
|
155fd0f8b1 | ||
|
|
05b7def1a0 | ||
|
|
5671af8db7 | ||
|
|
6aebeec028 | ||
|
|
5b5d0a3fb8 | ||
|
|
d405ed1005 | ||
|
|
2be97310d3 | ||
|
|
1f44e4473f | ||
|
|
022c7ea645 | ||
|
|
fe078ca67c | ||
|
|
479c742471 | ||
|
|
a52c629ecf | ||
|
|
c077d0f2e7 | ||
|
|
679994a6fb | ||
|
|
8cc256fdcf | ||
|
|
b6b2f2beec | ||
|
|
6075a21efb | ||
|
|
fa98f8f06d | ||
|
|
ad570cac5a | ||
|
|
cb32acc409 | ||
|
|
3998b1bcbd | ||
|
|
3fd03b2498 | ||
|
|
cba5710fec | ||
|
|
1ffdba03b3 | ||
|
|
fcf89d1501 | ||
|
|
56dc116d92 | ||
|
|
2371d6a29c | ||
|
|
d39878c875 | ||
|
|
287ceb2ded | ||
|
|
7c04be6abc | ||
|
|
e601ae27a1 | ||
|
|
487ad475c7 | ||
|
|
506b042f8c | ||
|
|
0e037de1b1 | ||
|
|
8d3cb72189 | ||
|
|
f8b9615e6b | ||
|
|
7cc961f789 | ||
|
|
1d92b7bead | ||
|
|
2c44b5ca8a | ||
|
|
8d9b50a004 | ||
|
|
d41f6ec3ef | ||
|
|
6aff7db89a | ||
|
|
dc105e6b31 | ||
|
|
f41ad2eee7 | ||
|
|
276da86dbe | ||
|
|
5aa64dddf3 | ||
|
|
cf01c41b33 | ||
|
|
64bc3fbffa | ||
|
|
453aacb669 | ||
|
|
2f350e3bc2 | ||
|
|
8379689eaa | ||
|
|
2676909cd0 | ||
|
|
a53c924248 | ||
|
|
a044a959b6 | ||
|
|
7555a3a7ce | ||
|
|
0fac973645 | ||
|
|
f533f51003 | ||
|
|
b4c0875ebf | ||
|
|
8cab499a83 | ||
|
|
f2daae3986 | ||
|
|
41cf32c808 | ||
|
|
b0e970a815 | ||
|
|
fed9e8f7de | ||
|
|
d2e2d3be76 | ||
|
|
07b9cb1a16 | ||
|
|
4f24af6d8a | ||
|
|
a30d467618 | ||
|
|
3daf44bac2 | ||
|
|
b69d8ec789 | ||
|
|
d1b2664071 | ||
|
|
8d0f20c2a7 | ||
|
|
f200a348de | ||
|
|
fae67e72ee | ||
|
|
a23e71bfb0 | ||
|
|
6e96fd6a55 | ||
|
|
3ba2bbd581 | ||
|
|
f8084c2d12 | ||
|
|
1ad552f03d | ||
|
|
6b8d0207a6 | ||
|
|
27871135a0 | ||
|
|
26be5e0cc5 | ||
|
|
66142c0137 | ||
|
|
de395c7053 | ||
|
|
ab78245576 | ||
|
|
6ff0efca25 | ||
|
|
fa0fd7140c | ||
|
|
0b71291cf1 | ||
|
|
44d0ced5af | ||
|
|
a8bfa90b87 | ||
|
|
835361d3c5 | ||
|
|
3bb719fcfc | ||
|
|
00a3001df9 | ||
|
|
cac0056fc4 | ||
|
|
a9e55e66d6 | ||
|
|
c10f0e47b2 | ||
|
|
0b45bc6ab9 | ||
|
|
30f62f4024 | ||
|
|
262f01b54e | ||
|
|
26c2774992 | ||
|
|
58ff26cc78 | ||
|
|
62eab2d661 | ||
|
|
d4ab4f8293 | ||
|
|
aed4b3ee6a | ||
|
|
4c90c6158f | ||
|
|
b911bdbd2d | ||
|
|
b5edcb8529 | ||
|
|
9086592252 | ||
|
|
c0b428dfbc | ||
|
|
e49427ac61 | ||
|
|
64149de2d4 | ||
|
|
fe3de4379f | ||
|
|
5532daf640 | ||
|
|
e197c6f114 | ||
|
|
f3b71b21b5 | ||
|
|
db3cb47d05 | ||
|
|
3f135f2da2 | ||
|
|
4ec6a0f9b8 | ||
|
|
eca0d8d81a | ||
|
|
e056675b3a | ||
|
|
71a4b39698 | ||
|
|
d194a6e4c9 | ||
|
|
4a7d8677a3 | ||
|
|
21ac0ac2fb | ||
|
|
acfd856b25 | ||
|
|
d5d8b59f8b | ||
|
|
b24fe30a40 | ||
|
|
207e2982d7 | ||
|
|
6fab577e23 | ||
|
|
f7ca638a1a | ||
|
|
0c96ba7a02 | ||
|
|
7143f5e643 | ||
|
|
910fa20b78 | ||
|
|
4855e631b5 | ||
|
|
698f2725c9 | ||
|
|
492fce1af7 | ||
|
|
397e9494eb | ||
|
|
b8d7f4803b | ||
|
|
89f0d452f4 | ||
|
|
bf8bed36ef | ||
|
|
38529ad13c | ||
|
|
8a6d23d461 | ||
|
|
d80cc717e2 | ||
|
|
a207348c13 | ||
|
|
4a795b4c50 | ||
|
|
e54cee1fad | ||
|
|
4e4108abfa | ||
|
|
3196e66efb | ||
|
|
7e0f20908c | ||
|
|
985749ade1 | ||
|
|
ec8deb8be3 | ||
|
|
b8d4bc5c6a | ||
|
|
2870513453 | ||
|
|
e27b35cd9f | ||
|
|
bc86dbb31e | ||
|
|
d1b047f675 | ||
|
|
8b43ee6ca1 | ||
|
|
f6e5068dae | ||
|
|
fe40e2378a | ||
|
|
2e9192ca02 | ||
|
|
05ec4964fe | ||
|
|
64f8444d47 | ||
|
|
c0f9b45dca | ||
|
|
ffadc335d5 | ||
|
|
9c09386600 |
+1
-1
@@ -1 +1 @@
|
||||
6
|
||||
16
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
branches:
|
||||
ignore:
|
||||
- gh-pages
|
||||
working_directory: ~/polkadot-js
|
||||
docker:
|
||||
- image: circleci/node:10
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: dependency-cache-{{ checksum "yarn.lock" }}
|
||||
- run:
|
||||
name: install-deps
|
||||
command: yarn install --frozen-lockfile
|
||||
- save_cache:
|
||||
key: dependency-cache-{{ checksum "yarn.lock" }}
|
||||
paths:
|
||||
- ./node_modules
|
||||
- ~/.cache/yarn
|
||||
- run:
|
||||
name: build
|
||||
command: yarn polkadot-dev-circleci-build
|
||||
+1
-1
@@ -5,7 +5,7 @@ module.exports = {
|
||||
parserOptions: {
|
||||
...base.parserOptions,
|
||||
project: [
|
||||
'./tsconfig.eslint.json'
|
||||
'./tsconfig.json'
|
||||
]
|
||||
},
|
||||
rules: {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: CI
|
||||
name: PR
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
- name: build
|
||||
run: |
|
||||
yarn install --frozen-lockfile
|
||||
yarn build:split:code
|
||||
yarn build
|
||||
|
||||
build_docs:
|
||||
name: Build Docs
|
||||
@@ -68,4 +68,4 @@ jobs:
|
||||
- name: build
|
||||
run: |
|
||||
yarn install --frozen-lockfile
|
||||
yarn build:split:docs
|
||||
yarn docs
|
||||
@@ -0,0 +1,67 @@
|
||||
name: Master
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build_code:
|
||||
name: Build Code
|
||||
if: "! contains(github.event.head_commit.message, '[CI Skip]')"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
token: ${{ secrets.GH_PAT }}
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: build
|
||||
env:
|
||||
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
||||
GH_PAT: ${{ secrets.GH_PAT }}
|
||||
GH_TOKEN: ${{ secrets.GH_PAT }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: |
|
||||
yarn install --frozen-lockfile
|
||||
yarn polkadot-dev-ghact-build
|
||||
|
||||
build_docs:
|
||||
name: Build Docs
|
||||
if: "! contains(github.event.head_commit.message, '[CI Skip]')"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: build
|
||||
env:
|
||||
GH_PAT: ${{ secrets.GH_PAT }}
|
||||
GH_TOKEN: ${{ secrets.GH_PAT }}
|
||||
GH_PAGES_SRC: build-docs
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
yarn install --frozen-lockfile
|
||||
yarn polkadot-dev-ghact-docs
|
||||
|
||||
dummy:
|
||||
name: Dummy
|
||||
if: "contains(github.event.head_commit.message, '[CI Skip]')"
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x]
|
||||
steps:
|
||||
- name: dummy
|
||||
run: |
|
||||
echo "Dummy skip step"
|
||||
@@ -12,6 +12,7 @@ tmp/
|
||||
.env.production.local
|
||||
.npmrc
|
||||
.rpt2_cache
|
||||
.vscode/
|
||||
cc-test-reporter
|
||||
lerna-debug.log*
|
||||
npm-debug.log*
|
||||
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "10"
|
||||
env:
|
||||
global:
|
||||
- CC_TEST_REPORTER_ID=b8983d04997f43ff9b9df9aa92904967547680e2a229af812b3cf14985713e84
|
||||
- GH_PAGES_SRC="build-docs"
|
||||
cache:
|
||||
yarn: true
|
||||
directories:
|
||||
- node_modules
|
||||
before_install:
|
||||
- curl -o- -L https://yarnpkg.com/install.sh | bash
|
||||
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
||||
- chmod +x ./cc-test-reporter
|
||||
- export PATH=$HOME/.yarn/bin::$(yarn global bin):$PATH
|
||||
before_script:
|
||||
- ./cc-test-reporter before-build
|
||||
script:
|
||||
- yarn polkadot-dev-travis-build
|
||||
after_script:
|
||||
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
||||
deploy:
|
||||
skip_cleanup: true
|
||||
provider: script
|
||||
script: yarn polkadot-dev-travis-deploy
|
||||
on:
|
||||
branch: master
|
||||
@@ -1,3 +1,68 @@
|
||||
# 0.100.1
|
||||
|
||||
- **Important** This will the the last API version with Substrate 1.x support. Although you will still be able to use subsequent versions with older chans, dependent libraries such as sr25519 may not be compatible.
|
||||
- Add support for the Substrate identity module
|
||||
- Remove the `codec/Data` type, to remove a conflict with Substrate. This type is now named `Raw`
|
||||
- Fix for linked maps using `Option`
|
||||
- Add support for `BTreeSet` (Thanks to https://github.com/satellitex)
|
||||
- Add support for Metadata v10
|
||||
- Add support for latest Polkadot/Substrate types
|
||||
- Add `paymentInfo` to submittables to calculate fees
|
||||
|
||||
# 0.99.1
|
||||
|
||||
- **Breaking change** The `Data` and `U8a` type has been renamed and just replaced with the `Raw` type
|
||||
- **Breaking change** The `api.derive.staking.info` has been split into 2 - `staking.query` for non-balance related information (more effective) and `staking.account` that enhances query for all the information previously found `.info`
|
||||
- Cleanup `DoubleMap` hashing to always hash over the full value (in the case of `Vec<T>`, this includes the length)
|
||||
- Update democracy derives to take care of nextTally and lowestU*nbaked
|
||||
- Add additional derives for both council & treasury
|
||||
- Alignment with latest Polkadot/Substrate master branch types
|
||||
|
||||
# 0.98.1
|
||||
|
||||
- Make the TypeScript generation script mor re-usable (Thanks to https://github.com/xlc)
|
||||
- Add `.entries()` for all map-types, returning storage keys and values
|
||||
- Add `.signAsync` to submittable extrinsics (Thanks to https://github.com/c410-f3r)
|
||||
- Cleanup circular references between internal dependencies
|
||||
- Support for new Substrate democracy with preimages in derive
|
||||
- Alignment of types with Substrate/Polkadot master branches
|
||||
|
||||
# 0.97.1
|
||||
|
||||
- **Breaking change** Add the passing on an explicit `Registry` to all calls to `createType` as well as all codec classes. If you are upgrading form an older version, use the [migration guide](UPGRADING.md) to walk through the changes required.
|
||||
- **Breaking change** The metadata classes have been moved from `@polkadot/types` into `@polkadot/metadata`. If you explicitly create `Metadata` classes, you now would need to do so with the `import Metadata from '@polkadot/metadata';` This is a decorated class, where the previous metadata is now available on `Metadata.metadata`, alongside decorated `consts.*`', `tx.*` and `query.*`.
|
||||
- **Breaking change** Session `Keys` defaults to 4 keys now (Substrate master), depending on your node config, you would want to override with e.g. `Keys: 'SessionKeys3'` (1, 2, 3, 4, 5 & 6)
|
||||
- **Breaking change** `ValidatorPrefs` now default to the new percentage commission model, to use the previous `validatorPayment`, you can override with `ValidatorPrefs: 'ValidatorPrefsTo196'`
|
||||
- `api.derive.*` now has built-in memomization
|
||||
- Various fixes and cleanups to `api.derive.*` including era length progress and vesting calculations
|
||||
- Aligned all types with the latest Polkadot & Substrate, including Kusama CC3
|
||||
- Support for Metadata V9, which adjusts the hashing methods of storage entries
|
||||
- Support for Metadata V10 (still un-released), which includes prefixed map support
|
||||
|
||||
# 0.96.1
|
||||
|
||||
- Updated types for latest Kusama
|
||||
- Add `filterRecords` (in addition to `findRecord`) on submittable results
|
||||
- Various ABI v2 contract fixes
|
||||
- Update derive for elections (incl. RunnersUp) and heartbeat derives (with blocks & messages)
|
||||
- Add vesting totals & locked breakdowns to derive balances
|
||||
- Update council derives for the latest Substrate master support (with constants)
|
||||
- Derive cleanups, including sharing of instances between the API and internal to derives
|
||||
|
||||
# 0.95.2
|
||||
|
||||
- Temporary removal of `account_nextIndex` use, will be re-added in a future release
|
||||
|
||||
# 0.95.1
|
||||
|
||||
- Support Extrinsic V4 with additional signature indicator (Latest Polkadot/Substrate/Kusama)
|
||||
- Adjust subscription update checks to avoid duplicated data updates
|
||||
- Support Metadata V8 (exposes per-module `decl_error` definitions)
|
||||
- Support next generation contracts ABI (with additional type definitions)
|
||||
- Support for `BTreeMap<K, V>` types and definitions
|
||||
- All latest Polkadot & Substrate types (as per master branches)
|
||||
- **Breaking change** `Call.injectMethods` is moved to `Call.injectMetadata` to align with `Events` (This _should_ not be used externally, however mentioned as breaking here)
|
||||
|
||||
# 0.94.1
|
||||
|
||||
- Add handling of `Result<Ok, Error>` definitions
|
||||
|
||||
+90
-6
@@ -2,7 +2,91 @@
|
||||
|
||||
This is an upgrade guide for users of the API. It does not attempt to detail each version (the [CHANGELOG](CHANGELOG.md) has all the changes between versions), but rather tries to explain the rationale behind major breaking changes and how users of the API should handle this.
|
||||
|
||||
While we try to keep the user-facing interfaces as stable as possible, sometimes you just need to make additions to move forward and improve things down the road, as painful as they may be. Like you, we are also users of the API, and eat our own dogfood - and as such, feel any pains introduced first.
|
||||
While we try to keep the user-facing interfaces as stable as possible, sometimes you just need to make additions to move forward and improve things down the road, as painful as they may be. Like you, we are also users of the API, and eat our own dog food - and as such, feel any pains introduced first.
|
||||
|
||||
|
||||
## 0.97.1 (and newer)
|
||||
|
||||
The 0.97 series lays the groundwork to allow type registration to be ties to a specific chain and a specific Api instance. In the past, 2 Api instances in the same process would share types, which mean that you could not connect to 2 independent chains with different types. This is very problematic for Polkadot chains, where the idea is to connect to multiple chains.
|
||||
|
||||
When using the Api, a new `Registry` will be created on using `new Api(...)` or `Api.create(...)` and this will be transparently passed when creating types. In the cases where you create type instances explicitly or create type classes for injection, you would need to make adjustments.
|
||||
|
||||
### Type classes
|
||||
|
||||
In a number of instances, developers are creating classes and making these available for interacting with their chains. For instance, an example of a custom type could be -
|
||||
|
||||
```js
|
||||
import { Struct, Text, u32 } from '@polkadot/types';
|
||||
|
||||
export class Preferences extends Struct {
|
||||
constructor (value?: ahy) {
|
||||
super({
|
||||
name: Text,
|
||||
id: u32
|
||||
}, value);
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
In the current iteration, the underlying `@polkadot/types` bases structures now require a `Registry` to be passed as the first parameter. This means that the above signature would be adjusted to -
|
||||
|
||||
```js
|
||||
// the next import is only required for TypeScript
|
||||
import { Registry } from '@polkadot/types/types';
|
||||
import { Struct, Text, u32 } from '@polkadot/types';
|
||||
|
||||
export class Preferences extends Struct {
|
||||
constructor (registry: Registry, value?: ahy) {
|
||||
super(registry, {
|
||||
name: Text,
|
||||
id: u32
|
||||
}, value);
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Where the type is used or returned from the API, the `Registry` will be automatically passed to class creation.
|
||||
|
||||
### createType
|
||||
|
||||
Previously, when creating a type instance such as `BlockNumber`, you would do `api.createType('BlockNumber', <initValue>)`, this is unchanged. In the cases where you directly import from `@polkadot/types`, the following pattern is required -
|
||||
|
||||
```js
|
||||
import { createType } from '@polkadot/types';
|
||||
|
||||
...
|
||||
const blockNumber = createType(api.registry, 'BlockNumber', 12345);
|
||||
```
|
||||
|
||||
In some cases, you would want to explicitly pass a `Registry` interface to the API, instead of relying on it explicitly. This is generally applicable in the cases where you want to use the `createType` independently from the API -
|
||||
|
||||
```js
|
||||
import { ApiPromise } from '@polkadot/api';
|
||||
import { TypeRegistry, createType } from '@polkadot/types';
|
||||
|
||||
...
|
||||
const registry = new TypeRegistry();
|
||||
const blockNumber = createType(registry, 'BlockNumber', 12345);
|
||||
const api = await ApiPromise.create({ registry });
|
||||
```
|
||||
|
||||
### Extrinsic metadata
|
||||
|
||||
In some applications, the undocumented `findFunction` has been used to determine the Api has the metadata for a specific extrinsic. The has been exposed on top of `GenericCall`, and it typically used in applications such as signers. Along with the compulsory registry, the above functions have been moved to the `Registry` itself, so if you previously had -
|
||||
|
||||
```js
|
||||
const { meta, method, section } = GenericCall.findFunction(extrinsic.callIndex);
|
||||
```
|
||||
|
||||
You need to change it to -
|
||||
|
||||
```js
|
||||
const { meta, method, section } = registry.findMetaCall(extrinsic.callIndex);
|
||||
```
|
||||
|
||||
## 0.90.1 (and newer), from 0.81.1 (and older)
|
||||
|
||||
@@ -29,10 +113,10 @@ To better align with the actual types from the metadata, and avoid (too much) co
|
||||
|
||||
The [@polkadot/api](packages/api) has always handled the conversion of types for parameters when making calls or queries. For example, when making a transfer to `BOB` (address), any of the following is valid -
|
||||
|
||||
- `api.tx.balances.transfer(BOB, 12345)` - value specied as a number
|
||||
- `api.tx.balances.transfer(BOB, '12345')` - value specied as a string
|
||||
- `api.tx.balances.transfer(BOB, '0x3039')` - value specied as a hex
|
||||
- `api.tx.balances.transfer(BOB, new BN(12345))` - value specied as a [BN](https://github.com/indutny/bn.js/)
|
||||
- `api.tx.balances.transfer(BOB, 12345)` - value specified as a number
|
||||
- `api.tx.balances.transfer(BOB, '12345')` - value specified as a string
|
||||
- `api.tx.balances.transfer(BOB, '0x3039')` - value specified as a hex
|
||||
- `api.tx.balances.transfer(BOB, new BN(12345))` - value specified as a [BN](https://github.com/indutny/bn.js/)
|
||||
|
||||
Internally the API will take the input and convert the value into a `Balance`, serialize it using the SCALE codec and transfer it to the node. In some cases users would construct the `Balance` type manually, by importing the class and calling `new` on it. This last approach has now been removed, and where classes are still available (limited reach), discouraged.
|
||||
|
||||
@@ -108,7 +192,7 @@ export class MyStruct extends Struct {
|
||||
}
|
||||
```
|
||||
|
||||
Internally the [@polkadot/types](packages/types) package now only defines classes where there are specific encoding logic applied. For all other types, the definitions are done via a JSON-like format and then the TypeScript definitions are generated from these. (In a world where nodes inject types and the type definitions are not needed, this functionality will be useful to allow TS devs to auto-generate type definitions based on what the node defines.)
|
||||
Internally the [@polkadot/types](packages/types) package now only defines classes where there are specific encoding logic applied. For all other types, the definitions are done via a JSON-like format and then the TypeScript definitions are generated from these. (In a world where nodes inject types and the type definitions are not needed, this functionality will be useful to allow TS developers to auto-generate type definitions based on what the node defines.)
|
||||
|
||||
### Signing transactions (Signer interface)
|
||||
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ yarn polkadot-dev-build-ts
|
||||
copy_folder "api" "api"
|
||||
copy_folder "api-contract" "api-contract"
|
||||
copy_folder "api-derive" "api-derive"
|
||||
copy_folder "api-metadata" "api-metadata"
|
||||
copy_folder "metadata" "metadata"
|
||||
copy_folder "rpc-core" "rpc-core"
|
||||
copy_folder "rpc-provider" "rpc-provider"
|
||||
copy_folder "type-jsonrpc" "jsonrpc"
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@
|
||||
- [Unsubscribe from listening](examples/promise/04_unsubscribe/README.md)
|
||||
- [Read chain state](examples/promise/05_read_storage/README.md)
|
||||
- [Make a transfer](examples/promise/06_make_transfer/README.md)
|
||||
- [Display system events](examples/promise/08_system_events/README.md)(
|
||||
- [Display system events](examples/promise/08_system_events/README.md)
|
||||
- [Transaction with events](examples/promise/09_transfer_events/README.md)
|
||||
- [Upgrade via sudo](examples/promise/10_upgrade_chain/README.md)
|
||||
- [ApiRx](examples/rx/README.md)
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
In addition to querying the latest storage, you can make storage queries at a specific blockhash. Be aware that the node applies a pruning strategy and typically only keeps the last 256 blocks, unless run in archive mode.
|
||||
|
||||
<<< @/docs/examples/promise/07_read_storage_at/index.js
|
||||
<<< @/docs/examples/promise/05_read_storage_at/index.js
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
This example shows how to instantiate a Polkadot API object and use it to connect to a node and retrieve balance updates.
|
||||
|
||||
<<< @/docs/examples/rx/03_listent_to_balance_change/index.js
|
||||
<<< @/docs/examples/rx/03_listen_to_balance_change/index.js
|
||||
|
||||
@@ -23,3 +23,13 @@ As of this writing we don't have an explicit example of implementing the signer
|
||||
Some calls in Polkadot/Substrate can only be submitted as root, these are indicated by `ensure_root(origin)` in the Rust codebase. Root here does not refer to the actual account, i.e. `//Alice` on a `--dev` chain, but rather that it cannot be submitted as a bare user transaction. This restriction applies to chain upgrades, changing balances or anything that modifies the state and/or chain operation.
|
||||
|
||||
To submit these transactions, it needs to be send as a [wrapped transaction](api.tx.wrap.md#sudo-use) via either `sudo.sudo` (assuming you have access on your chain) or `democracy.proposal` (which would allow users of the chain to vote on it).
|
||||
|
||||
## How do I call a function with a Tuple input
|
||||
|
||||
Tuples, as defined in the Polkadot/Substrate types appear as `(TypeA, TypeB)`. For instance we may have an `(AccountId, u64)` input as defined in the metadata or as part of the user types. To specify a Tuple as an input, wrap it is an array format, for instance to call `query.module.get((u32, u64))` where a `(u32, u64)` Tuple input is expected, you would do `query.module.get([123, 456])`
|
||||
|
||||
## How long do transactions live
|
||||
|
||||
Polkadot/Substrate supports both immortal and mortal transactions. For immortal, this means that the transaction has an infinite lifetime, for mortals, the transactions expire after a defined period. By default the API sends mortal transactions when no explicit extrinsic era has been specified. This means that all transaction has a limited lifetime and will expire if not included in the period set.
|
||||
|
||||
The length for this transaction validity is set to 50 blocks, which translates to 5 minutes assuming a default of 6 second blocktimes. (10 blocks per minute in this default configuration).
|
||||
|
||||
@@ -295,4 +295,4 @@ ___
|
||||
|
||||
### utility
|
||||
|
||||
▸ **BatchExecuted**(`Vec<Result<Null,DispatchError>>`)
|
||||
▸ **BatchExecuted**(`Vec<DispatchResult>`)
|
||||
|
||||
+2
-2
@@ -6,8 +6,8 @@ module.exports = Object.assign({}, config, {
|
||||
moduleNameMapper: {
|
||||
'@polkadot/api-contract(.*)$': '<rootDir>/packages/api-contract/src/$1',
|
||||
'@polkadot/api-derive(.*)$': '<rootDir>/packages/api-derive/src/$1',
|
||||
'@polkadot/api-metadata(.*)$': '<rootDir>/packages/api-metadata/src/$1',
|
||||
'@polkadot/api(.*)$': '<rootDir>/packages/api/src/$1',
|
||||
'@polkadot/metadata(.*)$': '<rootDir>/packages/metadata/src/$1',
|
||||
'@polkadot/rpc-(core|provider)(.*)$': '<rootDir>/packages/rpc-$1/src/$2',
|
||||
'@polkadot/jsonrpc(.*)$': '<rootDir>/packages/type-jsonrpc/src/$1',
|
||||
'@polkadot/types(.*)$': '<rootDir>/packages/types/src/$1'
|
||||
@@ -16,7 +16,7 @@ module.exports = Object.assign({}, config, {
|
||||
'<rootDir>/packages/api/build',
|
||||
'<rootDir>/packages/api-derive/build',
|
||||
'<rootDir>/packages/api-contract/build',
|
||||
'<rootDir>/packages/api-metadata/build',
|
||||
'<rootDir>/packages/metadata/build',
|
||||
'<rootDir>/packages/rpc-core/build',
|
||||
'<rootDir>/packages/rpc-provider/build',
|
||||
'<rootDir>/packages/type-jsonrpc/build',
|
||||
|
||||
+1
-1
@@ -9,5 +9,5 @@
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "0.94.1"
|
||||
"version": "0.100.1"
|
||||
}
|
||||
|
||||
+10
-14
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "0.94.1",
|
||||
"version": "0.100.1",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"yarn": "^1.10.1"
|
||||
@@ -9,17 +9,14 @@
|
||||
],
|
||||
"resolutions": {
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
"typescript": "^3.6.3"
|
||||
"typescript": "^3.7.4"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn build:split:code && yarn build:split:docs",
|
||||
"build:split:code": "yarn build:interfaces && polkadot-dev-build-ts",
|
||||
"build:split:docs": "yarn run build:methodsdoc && polkadot-dev-build-docs",
|
||||
"build:htmldoc": "yarn clean && typedoc --theme default --out docs/html",
|
||||
"build": "yarn build:interfaces && polkadot-dev-build-ts",
|
||||
"build:interfaces": "node packages/types/src/scripts/interfacesTsWrapper.js",
|
||||
"build:methodsdoc": "node packages/types/src/scripts/MetadataMdWrapper.js",
|
||||
"circular": "madge --circular --extensions ts ./",
|
||||
"docs": "node packages/types/src/scripts/MetadataMdWrapper.js && polkadot-dev-build-docs",
|
||||
"chain:info": "node packages/types/src/scripts/extractChainWrapper.js",
|
||||
"check": "yarn lint",
|
||||
"lint": "eslint --ext .js,.jsx,.ts,.tsx . && tsc --noEmit --pretty",
|
||||
"clean": "polkadot-dev-clean-build",
|
||||
"postinstall": "polkadot-dev-yarn-only",
|
||||
@@ -32,11 +29,10 @@
|
||||
"test:watch": "jest --coverage --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.6.2",
|
||||
"@babel/register": "^7.6.2",
|
||||
"@babel/runtime": "^7.6.2",
|
||||
"@polkadot/dev": "^0.31.1",
|
||||
"@polkadot/ts": "^0.1.73",
|
||||
"gh-pages": "^2.1.1"
|
||||
"@babel/core": "^7.7.7",
|
||||
"@babel/register": "^7.7.7",
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@polkadot/dev": "^0.32.14",
|
||||
"@polkadot/ts": "^0.1.90"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
Interfaces to allow for the encoding and decoding of Substrate contract ABIs.
|
||||
|
||||
```js
|
||||
import {ApiPromise, WsProvider } from '@polkadot/api';
|
||||
import { Abi } from '@polkadot/api-contract';
|
||||
|
||||
const abi = new Abi(<...JSON ABI...>);
|
||||
const wsProvider = new WsProvider(<...Node Url...>);
|
||||
const api = await ApiPromise.create({ provider: wsProvider });
|
||||
const abi = new Abi(api.registry, <...JSON ABI...>);
|
||||
|
||||
api.tx.contracts
|
||||
.call(<contract addr>, <value>, <max gas>, abi.messages.<method name>(<...params...>))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/api-contract",
|
||||
"version": "0.94.1",
|
||||
"version": "0.100.1",
|
||||
"description": "Interfaces for interacting with contracts and contract ABIs",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-contract#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.6.2",
|
||||
"@polkadot/types": "^0.94.1"
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@polkadot/types": "^0.100.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,119 +1,25 @@
|
||||
// Copyright 2017-2019 @polkadot/api-contract authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ContractABIArg } from './types';
|
||||
|
||||
import typesAbi from '../test/abi/types.json';
|
||||
import erc20Abi from '../test/contracts/Erc20.json';
|
||||
import { TypeRegistry } from '@polkadot/types';
|
||||
|
||||
import incrementerAbi from '../test/contracts/incrementer.json';
|
||||
import { Abi } from '.';
|
||||
|
||||
describe('Abi', (): void => {
|
||||
describe('types encoding', (): void => {
|
||||
let abi: Abi;
|
||||
const registry = new TypeRegistry();
|
||||
|
||||
beforeAll((): void => {
|
||||
abi = new Abi(typesAbi);
|
||||
});
|
||||
|
||||
function check (method: string, args: ContractABIArg[], type: string | null): void {
|
||||
const fn = abi.messages[method];
|
||||
|
||||
expect(fn.args).toEqual(args);
|
||||
expect(fn.type).toEqual(type);
|
||||
}
|
||||
|
||||
it('has the primitive method with args & return', (): void => {
|
||||
check(
|
||||
'primitive',
|
||||
[
|
||||
{ name: 'bool', type: 'bool' },
|
||||
{ name: 'u32', type: 'u32' }
|
||||
],
|
||||
'bool'
|
||||
);
|
||||
});
|
||||
|
||||
it('has the vector method with args & return', (): void => {
|
||||
check(
|
||||
'vector',
|
||||
[
|
||||
{ name: 'vecU8', type: 'Vec<u8>' },
|
||||
{ name: 'vecU32', type: 'Vec<u32>' }
|
||||
],
|
||||
'Vec<bool>'
|
||||
);
|
||||
});
|
||||
|
||||
it('has the vector_fixed method with args & return', (): void => {
|
||||
check(
|
||||
'vectorFixed',
|
||||
[
|
||||
{ name: 'vecU8Length32', type: '[u8;32]' }
|
||||
],
|
||||
'[u32;8]'
|
||||
);
|
||||
});
|
||||
|
||||
it('has the option method with args & return', (): void => {
|
||||
check(
|
||||
'option',
|
||||
[
|
||||
{ name: 'optionU32', type: 'Option<u32>' }
|
||||
],
|
||||
'Option<bool>'
|
||||
);
|
||||
});
|
||||
|
||||
it('has the result method with return (empty)', (): void => {
|
||||
check(
|
||||
'result',
|
||||
[],
|
||||
'()'
|
||||
);
|
||||
});
|
||||
|
||||
it('allows for nested args', (): void => {
|
||||
check(
|
||||
'nested',
|
||||
[
|
||||
{ name: 'optionVec', type: 'Option<Vec<u32>>' }
|
||||
],
|
||||
'Vec<(u32,u64)>'
|
||||
);
|
||||
});
|
||||
|
||||
describe('messages', (): void => {
|
||||
it('fails when invalid args are supplied', (): void => {
|
||||
expect(
|
||||
(): Uint8Array => abi.messages.primitive(false)
|
||||
).toThrow(/Expected 2 arguments to contract messages.primitive, found 1/);
|
||||
});
|
||||
|
||||
it('encodes primitives correctly', (): void => {
|
||||
expect(
|
||||
abi.messages.primitive(true, 0x12345678)
|
||||
).toEqual(new Uint8Array([
|
||||
9 << 2, // total length (4 + 1 + 4)
|
||||
0x67, 0x2b, 0, 0, // 11111 -> hex (LE)
|
||||
1, // true
|
||||
0x78, 0x56, 0x34, 0x12 // u32
|
||||
]));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('erc20', (): void => {
|
||||
describe('incrementer', (): void => {
|
||||
let abi: Abi;
|
||||
|
||||
beforeEach((): void => {
|
||||
abi = new Abi(erc20Abi);
|
||||
abi = new Abi(registry, incrementerAbi);
|
||||
});
|
||||
|
||||
it('has the attached methods', (): void => {
|
||||
expect(Object.keys(abi.messages)).toEqual(
|
||||
['totalSupply', 'balanceOf', 'allowance', 'transfer', 'approve', 'transferFrom']
|
||||
expect(Object.values(abi.abi.contract.messages).map(({ name }): string => name)).toEqual(
|
||||
['inc', 'get', 'compare']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,31 +1,48 @@
|
||||
// Copyright 2017-2019 @polkadot/api-contract authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ContractABI, ContractABIFn, InterfaceAbi, AbiMessages } from './types';
|
||||
import { Registry } from '@polkadot/types/types';
|
||||
import { AbiConstructors, AbiMessages, ContractABI, ContractABIPre, ContractABIFn, InterfaceAbi } from './types';
|
||||
|
||||
import { stringCamelCase } from '@polkadot/util';
|
||||
|
||||
import { createMethod } from './method';
|
||||
import { validateAbi } from './validation';
|
||||
import ContractRegistry from './ContractRegistry';
|
||||
|
||||
export default class ContractAbi implements InterfaceAbi {
|
||||
export default class ContractAbi extends ContractRegistry implements InterfaceAbi {
|
||||
public readonly abi: ContractABI;
|
||||
|
||||
public readonly deploy: ContractABIFn;
|
||||
public readonly constructors: AbiConstructors;
|
||||
|
||||
public readonly messages: AbiMessages = {};
|
||||
public readonly messages: AbiMessages;
|
||||
|
||||
public constructor (abi: ContractABI) {
|
||||
validateAbi(abi);
|
||||
constructor (registry: Registry, abi: ContractABIPre) {
|
||||
super(registry, abi);
|
||||
[this.abi, this.constructors, this.messages] = this.decodeAbi(abi);
|
||||
}
|
||||
|
||||
this.abi = abi;
|
||||
this.deploy = createMethod('deploy', abi.deploy);
|
||||
private decodeAbi (abiPre: ContractABIPre): [ContractABI, ContractABIFn[], AbiMessages] {
|
||||
this.validateAbi(abiPre);
|
||||
|
||||
abi.messages.forEach((method): void => {
|
||||
const name = stringCamelCase(method.name);
|
||||
const abi = this.convertAbi(abiPre);
|
||||
const constructors = abi.contract.constructors.map(
|
||||
(constructor, index): ContractABIFn => {
|
||||
return this.createMessage(`constructor ${index}`, constructor);
|
||||
}
|
||||
);
|
||||
|
||||
this.messages[name] = createMethod(`messages.${name}`, method);
|
||||
});
|
||||
const messages: AbiMessages = abi.contract.messages.reduce(
|
||||
(result: AbiMessages, message): AbiMessages => {
|
||||
const name = stringCamelCase(message.name);
|
||||
|
||||
return {
|
||||
...result,
|
||||
[name]: this.createMessage(`messages.${name}`, message)
|
||||
};
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
return [abi, constructors, messages];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { CodecArg, Constructor, Registry, TypeDef } from '@polkadot/types/types';
|
||||
import { ContractABIArgBasePre, ContractABIContract, ContractABIContractPre, ContractABIEvent, ContractABIEventPre, ContractABIFn, ContractABIFnArg, ContractABIMessage, ContractABIMessageBase, ContractABIMessagePre, ContractABI, ContractABIMessageCommon, ContractABIPre, ContractABIRange, ContractABIRangePre, ContractABIStorage, ContractABIStorageLayout, ContractABIStorageLayoutPre, ContractABIStoragePre, ContractABIStorageStruct, ContractABIStorageStructPre, ContractABITypePre } from './types';
|
||||
|
||||
import { Compact, u32, createClass, createType, encodeType } from '@polkadot/types';
|
||||
import { assert, hexToU8a, isNumber, isString, isNull, isObject, isUndefined, stringCamelCase, isHex, hexToNumber } from '@polkadot/util';
|
||||
|
||||
import MetaRegistry from './MetaRegistry';
|
||||
|
||||
// parse a selector, this can be a number (older) or of [<hex>, <hex>, ...]. However,
|
||||
// just catch everything (since this is now non-standard for u32 anyway)
|
||||
function parseSelector (registry: Registry, fnname: string, input: ContractABIMessageCommon['selector']): u32 {
|
||||
if (isNumber(input)) {
|
||||
return createType(registry, 'u32', input);
|
||||
} else if (isHex(input)) {
|
||||
return createType(registry, 'u32', hexToU8a(input));
|
||||
} else if (typeof input === 'string') {
|
||||
try {
|
||||
const array = JSON.parse(input);
|
||||
|
||||
assert(array.length === 4, `${fnname}: Invalid selector length`);
|
||||
|
||||
return createType(registry, 'u32', Uint8Array.from(
|
||||
// the as number[] is here to pacify TS, it doesn't quite know how to handle the cb
|
||||
(array as number[]).map((value: string | number): number =>
|
||||
isHex(value)
|
||||
? hexToNumber(value.toString())
|
||||
: value
|
||||
)
|
||||
));
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`${fnname}: Unable to parse selector`);
|
||||
}
|
||||
|
||||
function createArgClass (registry: Registry, args: ContractABIFnArg[], baseDef: Record<string, string>): Constructor {
|
||||
return createClass(
|
||||
registry,
|
||||
JSON.stringify(
|
||||
args.reduce((base: Record<string, any>, { name, type }): Record<string, any> => {
|
||||
base[name] = type.displayName || encodeType(type);
|
||||
|
||||
return base;
|
||||
}, baseDef)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default class ContractRegistry extends MetaRegistry {
|
||||
// Contract ABI helpers
|
||||
public validateArgs (name: string, args: ContractABIArgBasePre[]): void {
|
||||
assert(Array.isArray(args), `Expected 'args' to exist on ${name}`);
|
||||
|
||||
args.forEach((arg): void => {
|
||||
const unknownKeys = Object.keys(arg).filter((key): boolean => !['name', 'type'].includes(key));
|
||||
|
||||
assert(unknownKeys.length === 0, `Unknown keys ${unknownKeys.join(', ')} found in ABI args for ${name}`);
|
||||
assert(isNumber(arg.name) && isString(this.stringAt(arg.name)), `${name} args should have valid name `);
|
||||
assert(isNumber(arg.type.ty) && isObject(this.typeDefAt(arg.type.ty)), `${name} args should have valid type`);
|
||||
});
|
||||
}
|
||||
|
||||
public validateConstructors ({ contract: { constructors } }: ContractABIPre): void {
|
||||
constructors.forEach((constructor: ContractABIMessagePre, index): void => {
|
||||
const unknownKeys = Object.keys(constructor).filter((key): boolean => !['args', 'docs', 'name', 'selector'].includes(key));
|
||||
|
||||
assert(unknownKeys.length === 0, `Unknown keys ${unknownKeys.join(', ')} found in ABI constructor`);
|
||||
|
||||
this.validateArgs(`constructor ${index}`, constructor.args);
|
||||
});
|
||||
}
|
||||
|
||||
public validateMessages ({ contract: { messages } }: ContractABIPre): void {
|
||||
messages.forEach((message): void => {
|
||||
const unknownKeys = Object.keys(message).filter((key): boolean => !['args', 'docs', 'mutates', 'name', 'selector', 'return_type'].includes(key));
|
||||
const fnname = `messages.${message.name}`;
|
||||
|
||||
assert(unknownKeys.length === 0, `Unknown keys ${unknownKeys.join(', ')} found in ABI args for messages.${message.name}`);
|
||||
|
||||
const { name, selector, return_type: returnType } = message;
|
||||
|
||||
assert(isNumber(name) && isString(this.stringAt(name)), `Expected name for ${fnname}`);
|
||||
assert(isNull(returnType) || (isNumber(returnType.ty) && isObject(this.typeDefAt(returnType.ty))), `Expected return_type for ${fnname}`);
|
||||
|
||||
parseSelector(this.registry, fnname, selector);
|
||||
this.validateArgs(fnname, message.args);
|
||||
});
|
||||
}
|
||||
|
||||
public validateAbi (abi: ContractABIPre): void {
|
||||
const unknownKeys = Object.keys(abi.contract).filter((key): boolean => !['constructors', 'docs', 'events', 'messages', 'name'].includes(key));
|
||||
|
||||
assert(unknownKeys.length === 0, `Unknown fields ${unknownKeys.join(', ')} found in ABI`);
|
||||
|
||||
const { contract: { constructors, messages, name } } = abi;
|
||||
|
||||
assert(constructors && messages && isString(this.stringAt(name)), 'ABI should have constructors, messages & name sections');
|
||||
|
||||
this.validateConstructors(abi);
|
||||
this.validateMessages(abi);
|
||||
}
|
||||
|
||||
public createMessage (name: string, message: Partial<ContractABIMessage> & ContractABIMessageBase): ContractABIFn {
|
||||
const args = message.args.map(({ name, type }): ContractABIFnArg => {
|
||||
assert(isObject(type), `Invalid type at index ${type}`);
|
||||
return {
|
||||
name: stringCamelCase(name),
|
||||
type
|
||||
};
|
||||
});
|
||||
const Clazz = createArgClass(this.registry, args, isUndefined(message.selector) ? {} : { __selector: 'u32' });
|
||||
const baseStruct: { [index: string]: any } = { __selector: isUndefined(message.selector) ? undefined : parseSelector(this.registry, name, message.selector) };
|
||||
const encoder = (...params: CodecArg[]): Uint8Array => {
|
||||
assert(params.length === args.length, `Expected ${args.length} arguments to contract ${name}, found ${params.length}`);
|
||||
|
||||
const u8a = new Clazz(
|
||||
this.registry,
|
||||
args.reduce((mapped, { name }, index): Record<string, CodecArg> => {
|
||||
mapped[name] = params[index];
|
||||
|
||||
return mapped;
|
||||
}, { ...baseStruct })
|
||||
).toU8a();
|
||||
|
||||
return Compact.addLengthPrefix(u8a);
|
||||
};
|
||||
|
||||
const fn = (encoder as ContractABIFn);
|
||||
|
||||
fn.args = args;
|
||||
fn.isConstant = !(message.mutates || false);
|
||||
fn.type = message.returnType || null;
|
||||
return fn;
|
||||
}
|
||||
|
||||
public convertAbi ({ contract, storage }: ContractABIPre): ContractABI {
|
||||
return {
|
||||
contract: this.convertContract(contract),
|
||||
storage: this.convertStorage(storage)
|
||||
};
|
||||
}
|
||||
|
||||
public convertArgs (args: ContractABIArgBasePre[]): any[] {
|
||||
return args.map(({ name, type, ...arg }) => ({ ...arg, name: this.stringAt(name), type: this.convertType(type) }));
|
||||
}
|
||||
|
||||
public convertType ({ ty, display_name: displayNameIndices }: ContractABITypePre): TypeDef {
|
||||
const displayName = this.stringsAt(displayNameIndices).join('::');
|
||||
return this.typeDefAt(ty, { displayName });
|
||||
}
|
||||
|
||||
public convertContract ({ constructors, messages, name, events, ...contract }: ContractABIContractPre): ContractABIContract {
|
||||
return {
|
||||
constructors: this.convertConstructors(constructors),
|
||||
messages: messages.map(message => this.convertMessage(message)),
|
||||
name: this.stringAt(name),
|
||||
...(events
|
||||
? { events: events.map(event => this.convertEvent(event)) }
|
||||
: {}),
|
||||
...contract
|
||||
};
|
||||
}
|
||||
|
||||
public convertConstructors (constructors: ContractABIMessagePre[]): ContractABIMessage[] {
|
||||
return constructors.map(
|
||||
(constructor: ContractABIMessagePre): ContractABIMessage => {
|
||||
return this.convertMessage(constructor);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public convertMessage ({ args, name, return_type: returnType, ...message }: ContractABIMessagePre): ContractABIMessage {
|
||||
return {
|
||||
...message,
|
||||
args: this.convertArgs(args),
|
||||
name: this.stringAt(name),
|
||||
returnType: returnType ? this.convertType(returnType) : null
|
||||
};
|
||||
}
|
||||
|
||||
public convertEvent ({ args }: ContractABIEventPre): ContractABIEvent {
|
||||
return {
|
||||
args: this.convertArgs(args)
|
||||
};
|
||||
}
|
||||
|
||||
public convertStorage (storage: ContractABIStoragePre): ContractABIStorage {
|
||||
return this.convertStorageStruct(storage);
|
||||
}
|
||||
|
||||
public convertStorageLayout (storageLayout: ContractABIStorageLayoutPre): ContractABIStorageLayout {
|
||||
if ((storageLayout as ContractABIStorageStructPre)['struct.type']) {
|
||||
return this.convertStorageStruct(storageLayout as ContractABIStorageStructPre);
|
||||
} else {
|
||||
return this.convertStorageRange(storageLayout as ContractABIRangePre);
|
||||
}
|
||||
}
|
||||
|
||||
public convertStorageStruct ({ 'struct.type': structType, 'struct.fields': structFields }: ContractABIStorageStructPre): ContractABIStorageStruct {
|
||||
return {
|
||||
'struct.type': this.typeDefAt(structType),
|
||||
'struct.fields': structFields.map(({ name, layout }) => ({
|
||||
name: this.stringAt(name),
|
||||
layout: this.convertStorageLayout(layout)
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
public convertStorageRange ({ 'range.elem_type': type, ...range }: ContractABIRangePre): ContractABIRange {
|
||||
return {
|
||||
...range,
|
||||
'range.elem_type': this.typeDefAt(type)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright 2017-2020 @polkadot/types authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { TypeRegistry } from '@polkadot/types';
|
||||
|
||||
import MetaRegistry from './MetaRegistry';
|
||||
|
||||
import erc20Abi from '../test/contracts/Erc20.json';
|
||||
import erc20Cmp from '../test/compare/erc20.test.json';
|
||||
import sharedVecAbi from '../test/contracts/SharedVecV2.json';
|
||||
import sharedVecCmp from '../test/compare/shared-vec.test.json';
|
||||
import test001Abi from '../test/abi/test001.json';
|
||||
import test001Cmp from '../test/compare/test001.cmp.json';
|
||||
|
||||
function compare (meta: MetaRegistry, other: any): void {
|
||||
try {
|
||||
expect(meta.typeDefs).toEqual(other);
|
||||
} catch (error) {
|
||||
console.error(JSON.stringify(meta.typeDefs));
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
describe('MetaRegistry', (): void => {
|
||||
const registry = new TypeRegistry();
|
||||
|
||||
describe('construction', (): void => {
|
||||
it('initializes from a contract ABI (ERC20)', (): void => {
|
||||
compare(new MetaRegistry(registry, erc20Abi), erc20Cmp);
|
||||
});
|
||||
|
||||
it('initializes from a contract ABI (SharedVec)', (): void => {
|
||||
compare(new MetaRegistry(registry, sharedVecAbi), sharedVecCmp);
|
||||
});
|
||||
|
||||
it('initializes from a contract ABI (Other, test001)', (): void => {
|
||||
compare(new MetaRegistry(registry, test001Abi), test001Cmp);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,351 @@
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { MetaRegistryItem, MetaRegistryJson, MetaTypeDefClikeEnum, MetaType, MetaTypeDefEnum, MetaTypeDefEnumVariant, MetaTypeDefEnumVariantStruct, MetaTypeDefEnumVariantTupleStruct, MetaTypeDefEnumVariantUnit, MetaTypeDefStruct, MetaTypeDefStructField, MetaTypeDefTupleStruct, MetaTypeDefUnion, MetaTypeIdCustom, MetaTypeIdVec, MetaTypeIdVecFixed, MetaTypeInfo, Registry, StringIndex, TypeDef, TypeDefInfo, TypeIndex } from '@polkadot/types/types';
|
||||
|
||||
import { assert } from '@polkadot/util';
|
||||
import { displayType, withTypeString } from '@polkadot/types';
|
||||
|
||||
const builtinMap: [(id: any) => boolean, MetaTypeInfo][] = [
|
||||
[(id: any): boolean => typeof id === 'string', MetaTypeInfo.BuiltinPlain],
|
||||
[(id: any): boolean => Array.isArray(id), MetaTypeInfo.BuiltinTuple],
|
||||
[(id: any): boolean => !!(id['array.type']), MetaTypeInfo.BuiltinVecFixed],
|
||||
[(id: any): boolean => !!(id['slice.type']), MetaTypeInfo.BuiltinVec]
|
||||
];
|
||||
|
||||
const typeMap: [string, MetaTypeInfo][] = [
|
||||
['enum.variants', MetaTypeInfo.Enum],
|
||||
['clike_enum.variants', MetaTypeInfo.ClikeEnum],
|
||||
['struct.fields', MetaTypeInfo.Struct],
|
||||
['tuple_struct.types', MetaTypeInfo.TupleStruct]
|
||||
];
|
||||
|
||||
function detectedType ({ def, id }: MetaType): MetaTypeInfo {
|
||||
assert(!(def as MetaTypeDefUnion)['union.fields'], 'Invalid union type definition found');
|
||||
|
||||
const lookup = def === 'builtin'
|
||||
? builtinMap.find(([test]): boolean => test(id))
|
||||
: typeMap.find(([test]): boolean => !!(def as any)[test]);
|
||||
|
||||
return lookup
|
||||
? lookup[1]
|
||||
: MetaTypeInfo.Null;
|
||||
}
|
||||
|
||||
class MetadataRegistryLookup {
|
||||
public readonly registry: Registry;
|
||||
|
||||
protected _strings: string[] = [];
|
||||
|
||||
protected _types: MetaType[] = [];
|
||||
|
||||
public typeDefs: TypeDef[] = [];
|
||||
|
||||
constructor (registry: Registry, { registry: { strings, types } }: MetaRegistryJson) {
|
||||
this.registry = registry;
|
||||
this._strings = strings;
|
||||
this._types = types;
|
||||
}
|
||||
|
||||
protected hasItemAt (index: number, variant: MetaRegistryItem): boolean {
|
||||
switch (variant) {
|
||||
case MetaRegistryItem.String:
|
||||
return this._strings && !!this._strings[index - 1];
|
||||
case MetaRegistryItem.Type:
|
||||
return this._types && !!this._types[index - 1];
|
||||
case MetaRegistryItem.TypeDef:
|
||||
return this.typeDefs && !!this.typeDefs[index - 1];
|
||||
}
|
||||
}
|
||||
|
||||
protected itemAt (index: number, variant: MetaRegistryItem): any {
|
||||
assert(this.hasItemAt(index, variant), `MetaRegistry: Invalid ${variant} index ${index} found in metadata`);
|
||||
|
||||
switch (variant) {
|
||||
case MetaRegistryItem.String:
|
||||
return this._strings[index - 1];
|
||||
case MetaRegistryItem.Type:
|
||||
return this._types[index - 1];
|
||||
case MetaRegistryItem.TypeDef:
|
||||
return this.typeDefs[index - 1];
|
||||
}
|
||||
}
|
||||
|
||||
protected itemsAt (indices: number[], variant: MetaRegistryItem): any[] {
|
||||
return indices.map((index: number): string => this.itemAt(index, variant));
|
||||
}
|
||||
|
||||
protected stringAt (index: StringIndex): string {
|
||||
return this.itemAt(index, MetaRegistryItem.String);
|
||||
}
|
||||
|
||||
public stringsAt (indices: StringIndex[]): string[] {
|
||||
return this.itemsAt(indices, MetaRegistryItem.String);
|
||||
}
|
||||
|
||||
public typeAt (index: TypeIndex): MetaType {
|
||||
return this.itemAt(index, MetaRegistryItem.Type);
|
||||
}
|
||||
|
||||
public typesAt (indices: TypeIndex[]): MetaType[] {
|
||||
return this.itemsAt(indices, MetaRegistryItem.Type);
|
||||
}
|
||||
|
||||
public hasTypeDefAt (index: TypeIndex): boolean {
|
||||
return this.hasItemAt(index, MetaRegistryItem.TypeDef);
|
||||
}
|
||||
|
||||
public typeDefAt (index: TypeIndex, extra: Pick<TypeDef, never> = {}): TypeDef {
|
||||
return {
|
||||
...this.itemAt(index, MetaRegistryItem.TypeDef),
|
||||
...extra
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default class MetaRegistry extends MetadataRegistryLookup {
|
||||
constructor (registry: Registry, json: MetaRegistryJson) {
|
||||
super(registry, json);
|
||||
|
||||
// Generate TypeDefs for each provided registry type
|
||||
this._types.forEach((_, index: number): void => this.setTypeDefAtIndex(index + 1));
|
||||
}
|
||||
|
||||
public setTypeDefAtIndex (typeIndex: TypeIndex): void {
|
||||
this.typeDefs[typeIndex - 1] = this.typeDefFromMetaType(this.typeAt(typeIndex), typeIndex);
|
||||
}
|
||||
|
||||
private typeDefIdFields ({ id }: MetaType): Pick<TypeDef, never> {
|
||||
const { 'custom.name': nameIndex, 'custom.namespace': namespaceIndices, 'custom.params': paramsIndices } = id as MetaTypeIdCustom;
|
||||
|
||||
if (!nameIndex) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
name: this.stringAt(nameIndex),
|
||||
...(namespaceIndices && namespaceIndices.length
|
||||
? { namespace: this.stringsAt(namespaceIndices).join('::') }
|
||||
: {}
|
||||
),
|
||||
...(paramsIndices && paramsIndices.length
|
||||
? { params: this.typesAt(paramsIndices).map((type): TypeDef => this.typeDefFromMetaType(type)) }
|
||||
: {}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
private typeDefDefFields (metaType: MetaType, typeIndex?: TypeIndex): Pick<TypeDef, never> {
|
||||
let typeDef;
|
||||
|
||||
switch (detectedType(metaType)) {
|
||||
case MetaTypeInfo.BuiltinPlain:
|
||||
typeDef = this.typeDefForBuiltinPlain(metaType.id as string);
|
||||
break;
|
||||
case MetaTypeInfo.BuiltinTuple:
|
||||
typeDef = this.typeDefForBuiltinTuple(metaType.id as TypeIndex[]);
|
||||
break;
|
||||
case MetaTypeInfo.BuiltinVec:
|
||||
typeDef = this.typeDefForBuiltinVec(metaType.id as MetaTypeIdVec, typeIndex);
|
||||
break;
|
||||
case MetaTypeInfo.BuiltinVecFixed:
|
||||
typeDef = this.typeDefForBuiltinVecFixed(metaType.id as MetaTypeIdVecFixed, typeIndex);
|
||||
break;
|
||||
case MetaTypeInfo.Enum:
|
||||
typeDef = this.typeDefForEnum(metaType.def as MetaTypeDefEnum, metaType.id as MetaTypeIdCustom, typeIndex);
|
||||
break;
|
||||
case MetaTypeInfo.ClikeEnum:
|
||||
typeDef = this.typeDefForClikeEnum(metaType.def as MetaTypeDefClikeEnum);
|
||||
break;
|
||||
case MetaTypeInfo.Struct:
|
||||
typeDef = this.typeDefForStruct(metaType.def as MetaTypeDefStruct);
|
||||
break;
|
||||
case MetaTypeInfo.TupleStruct:
|
||||
typeDef = this.typeDefForTupleStruct(metaType.def as MetaTypeDefTupleStruct);
|
||||
break;
|
||||
case MetaTypeInfo.Null:
|
||||
default:
|
||||
throw new Error(`Invalid type detected at index ${typeIndex}`);
|
||||
}
|
||||
|
||||
return typeDef;
|
||||
}
|
||||
|
||||
public typeDefFromMetaType (metaType: MetaType, typeIndex?: TypeIndex): TypeDef {
|
||||
return withTypeString({
|
||||
info: TypeDefInfo.Null,
|
||||
type: '',
|
||||
...this.typeDefDefFields(metaType, typeIndex),
|
||||
...this.typeDefIdFields(metaType)
|
||||
}) as TypeDef;
|
||||
}
|
||||
|
||||
public typeDefFromMetaTypeAt (typeIndex: TypeIndex): TypeDef {
|
||||
if (!this.hasTypeDefAt(typeIndex)) {
|
||||
this.setTypeDefAtIndex(typeIndex);
|
||||
}
|
||||
|
||||
return this.typeDefAt(typeIndex);
|
||||
}
|
||||
|
||||
private typeDefForEnumVariant (variant: MetaTypeDefEnumVariant): Pick<TypeDef, any> {
|
||||
const { 'unit_variant.name': unitNameIndex } = variant as MetaTypeDefEnumVariantUnit;
|
||||
|
||||
if (unitNameIndex) {
|
||||
return {
|
||||
info: TypeDefInfo.Plain,
|
||||
name: this.stringAt(unitNameIndex),
|
||||
type: 'Null'
|
||||
};
|
||||
}
|
||||
|
||||
const { 'tuple_struct_variant.name': tupleStructVariantNameIndex } = variant as MetaTypeDefEnumVariantTupleStruct;
|
||||
|
||||
if (tupleStructVariantNameIndex) {
|
||||
return this.typeDefForTupleStruct(variant as MetaTypeDefEnumVariantTupleStruct);
|
||||
}
|
||||
|
||||
const { 'struct_variant.name': structVariantNameIndex } = variant as MetaTypeDefEnumVariantStruct;
|
||||
|
||||
if (structVariantNameIndex) {
|
||||
return this.typeDefForStruct(variant as MetaTypeDefEnumVariantStruct);
|
||||
}
|
||||
|
||||
return {
|
||||
info: TypeDefInfo.Null,
|
||||
type: 'Null'
|
||||
};
|
||||
}
|
||||
|
||||
private typeDefForBuiltinPlain (id: string): Pick<TypeDef, never> {
|
||||
return {
|
||||
info: TypeDefInfo.Plain,
|
||||
type: id
|
||||
};
|
||||
}
|
||||
|
||||
private typeDefForBuiltinTuple (id: TypeIndex[]): Pick<TypeDef, never> {
|
||||
const sub = id.map((tupleTypeIndex: number): TypeDef => this.typeDefFromMetaTypeAt(tupleTypeIndex));
|
||||
|
||||
return {
|
||||
info: TypeDefInfo.Tuple,
|
||||
sub
|
||||
};
|
||||
}
|
||||
|
||||
private typeDefForBuiltinVec (id: MetaTypeIdVec, typeIndex?: TypeIndex): Pick<TypeDef, never> {
|
||||
const { 'slice.type': vecTypeIndex } = id;
|
||||
|
||||
assert(!typeIndex || vecTypeIndex !== typeIndex, `MetaRegistry: self-referencing registry type at index ${typeIndex}`);
|
||||
|
||||
const type = displayType(this.typeDefFromMetaTypeAt(vecTypeIndex));
|
||||
assert(type && type.length > 0, `MetaRegistry: Invalid builtin Vec type found at index ${typeIndex}`);
|
||||
|
||||
return {
|
||||
info: TypeDefInfo.Vec,
|
||||
type: `Vec<${type}>`,
|
||||
sub: this.typeDefFromMetaTypeAt(vecTypeIndex)
|
||||
};
|
||||
}
|
||||
|
||||
private typeDefForBuiltinVecFixed (id: MetaTypeIdVecFixed, typeIndex?: TypeIndex): Pick<TypeDef, never> {
|
||||
const { 'array.type': vecTypeIndex, 'array.len': vecLength } = id;
|
||||
|
||||
assert(!vecLength || vecLength <= 256, 'MetaRegistry: Only support for [Type; <length>], where length <= 256');
|
||||
assert(!typeIndex || vecTypeIndex !== typeIndex, `MetaRegistry: self-referencing registry type at index ${typeIndex}`);
|
||||
|
||||
const type = displayType(this.typeDefFromMetaTypeAt(vecTypeIndex));
|
||||
assert(type && type.length > 0, `MetaRegistry: Invalid vector type found at index ${typeIndex}`);
|
||||
|
||||
return {
|
||||
info: TypeDefInfo.VecFixed,
|
||||
ext: { length: vecLength, type },
|
||||
type: `[${type};${vecLength}]`,
|
||||
sub: this.typeDefFromMetaTypeAt(vecTypeIndex)
|
||||
};
|
||||
}
|
||||
|
||||
private typeDefForEnum (def: MetaTypeDefEnum, id: MetaTypeIdCustom, typeIndex?: TypeIndex): Pick<TypeDef, any> {
|
||||
const name = id && this.stringAt(id['custom.name']);
|
||||
|
||||
switch (name) {
|
||||
case 'Option':
|
||||
return this.typeDefForOption(id, typeIndex);
|
||||
case 'Result':
|
||||
return this.typeDefForResult(id, typeIndex);
|
||||
default: {
|
||||
const sub = def['enum.variants'].map(variant => this.typeDefForEnumVariant(variant));
|
||||
|
||||
return {
|
||||
info: TypeDefInfo.Enum,
|
||||
sub
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private typeDefForClikeEnum (def: MetaTypeDefClikeEnum): Pick<TypeDef, never> {
|
||||
return {
|
||||
info: TypeDefInfo.Enum,
|
||||
sub: def['clike_enum.variants'].map(({ name: nameIndex, discriminant }): TypeDef => ({
|
||||
ext: { discriminant },
|
||||
info: TypeDefInfo.Plain,
|
||||
name: this.stringAt(nameIndex),
|
||||
type: 'Null'
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
public typeDefForOption (id: MetaTypeIdCustom, typeIndex?: TypeIndex): Pick<TypeDef, any> {
|
||||
assert(id['custom.params'] && id['custom.params'][0], `Invalid Option type defined at index ${typeIndex}`);
|
||||
|
||||
return {
|
||||
info: TypeDefInfo.Option,
|
||||
sub: this.typeDefFromMetaTypeAt(id['custom.params']![0])
|
||||
};
|
||||
}
|
||||
|
||||
public typeDefForResult (id: MetaTypeIdCustom, typeIndex?: TypeIndex): Pick<TypeDef, any> {
|
||||
assert(id['custom.params'] && id['custom.params'][0] && id['custom.params'][1], `Invalid Result type defined at index ${typeIndex}`);
|
||||
|
||||
return {
|
||||
info: TypeDefInfo.Result,
|
||||
sub: id['custom.params']!.map((typeIndex): TypeDef => this.typeDefFromMetaTypeAt(typeIndex))
|
||||
};
|
||||
}
|
||||
|
||||
public typeDefForStruct (def: MetaTypeDefStruct | MetaTypeDefEnumVariantStruct): Pick<TypeDef, any> {
|
||||
const structFields = (def as MetaTypeDefStruct)['struct.fields'] || (def as MetaTypeDefEnumVariantStruct)['struct_variant.fields'];
|
||||
const structNameIndex = (def as MetaTypeDefEnumVariantStruct)['struct_variant.name'];
|
||||
|
||||
return withTypeString({
|
||||
info: TypeDefInfo.Struct,
|
||||
...(structNameIndex
|
||||
? { name: this.stringAt(structNameIndex) }
|
||||
: {}
|
||||
),
|
||||
sub: structFields.map((field: MetaTypeDefStructField): TypeDef => ({
|
||||
...this.typeDefFromMetaTypeAt(field.type),
|
||||
name: this.stringAt(field.name)
|
||||
}))
|
||||
});
|
||||
}
|
||||
|
||||
private typeDefForTupleStruct (def: MetaTypeDefTupleStruct | MetaTypeDefEnumVariantTupleStruct): Pick<TypeDef, any> {
|
||||
const tupleStructTypes = (def as MetaTypeDefTupleStruct)['tuple_struct.types'] || (def as MetaTypeDefEnumVariantTupleStruct)['tuple_struct_variant.types'];
|
||||
const tupleStructNameIndex = (def as MetaTypeDefEnumVariantTupleStruct)['tuple_struct_variant.name'];
|
||||
|
||||
return withTypeString({
|
||||
info: TypeDefInfo.Tuple,
|
||||
...(tupleStructNameIndex
|
||||
? { name: this.stringAt(tupleStructNameIndex) }
|
||||
: {}
|
||||
),
|
||||
sub: tupleStructTypes.map((fieldIndex: number, index: number): TypeDef => ({
|
||||
...this.typeDefFromMetaTypeAt(fieldIndex),
|
||||
index
|
||||
}))
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { SubmittableModuleExtrinsics } from '@polkadot/api/types';
|
||||
import { ApiObject, ContractABI, ContractBase } from './types';
|
||||
|
||||
import { assert } from '@polkadot/util';
|
||||
|
||||
import Abi from './Abi';
|
||||
|
||||
// NOTE Experimental, POC, bound to change
|
||||
export default abstract class RxBase implements ContractBase<'rxjs'> {
|
||||
public readonly abi: Abi;
|
||||
|
||||
public readonly api: ApiObject<'rxjs'>;
|
||||
|
||||
public readonly apiContracts: SubmittableModuleExtrinsics<'rxjs'>;
|
||||
|
||||
public constructor (api: ApiObject<'rxjs'>, abi: ContractABI | Abi) {
|
||||
this.abi = abi instanceof Abi
|
||||
? abi
|
||||
: new Abi(abi);
|
||||
this.api = api;
|
||||
|
||||
// cater for substrate 2.x & 1.x (in order)
|
||||
this.apiContracts = api.tx.contracts || api.tx.contract;
|
||||
|
||||
assert(this.apiContracts && this.apiContracts.putCode, 'You need to connect to a node with the contracts module, the metadata does not enable api.tx.contracts on this instance');
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { SubmittableResultImpl } from '@polkadot/api/types';
|
||||
import { AccountId, Address, Hash } from '@polkadot/types/interfaces';
|
||||
import { IKeyringPair } from '@polkadot/types/types';
|
||||
import { ContractABI } from './types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { ApiRx, SubmittableResult } from '@polkadot/api';
|
||||
import { createType } from '@polkadot/types';
|
||||
|
||||
import Abi from './Abi';
|
||||
import RxBase from './RxBase';
|
||||
import RxContract from './RxContract';
|
||||
|
||||
type BlueprintCreateResultSubscription = Observable<BlueprintCreateResult>;
|
||||
|
||||
export interface BlueprintCreate {
|
||||
signAndSend (account: IKeyringPair | string | AccountId | Address): BlueprintCreateResultSubscription;
|
||||
}
|
||||
|
||||
class BlueprintCreateResult extends SubmittableResult {
|
||||
public readonly contract?: RxContract;
|
||||
|
||||
public constructor (result: SubmittableResultImpl, contract?: RxContract) {
|
||||
super(result);
|
||||
|
||||
this.contract = contract;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE Experimental, POC, bound to change
|
||||
export default class Blueprint extends RxBase {
|
||||
public readonly codeHash: Hash;
|
||||
|
||||
public constructor (api: ApiRx, abi: ContractABI | Abi, codeHash: string | Hash) {
|
||||
super(api, abi);
|
||||
|
||||
this.codeHash = createType('Hash', codeHash);
|
||||
}
|
||||
|
||||
public deployContract (endowment: number | BN, maxGas: number | BN, ...params: any[]): BlueprintCreate {
|
||||
const signAndSend = (account: IKeyringPair | string | AccountId | Address): BlueprintCreateResultSubscription => {
|
||||
return this.apiContracts
|
||||
.create(endowment, maxGas, this.codeHash, this.abi.deploy(...params))
|
||||
.signAndSend(account)
|
||||
.pipe(map(this.createResult));
|
||||
};
|
||||
|
||||
return { signAndSend };
|
||||
}
|
||||
|
||||
private createResult = (result: SubmittableResult): BlueprintCreateResult => {
|
||||
let contract: RxContract | undefined;
|
||||
|
||||
if (result.isFinalized) {
|
||||
const record = result.findRecord('contract', 'Instantiated');
|
||||
|
||||
if (record) {
|
||||
contract = new RxContract(this.api, this.abi, record.event.data[1] as Address);
|
||||
}
|
||||
}
|
||||
|
||||
return new BlueprintCreateResult(result, contract);
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { SubmittableResultImpl } from '@polkadot/api/types';
|
||||
import { AccountId, Address, Hash } from '@polkadot/types/interfaces';
|
||||
import { IKeyringPair } from '@polkadot/types/types';
|
||||
import { ContractABI } from './types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { ApiRx, SubmittableResult } from '@polkadot/api';
|
||||
import { compactAddLength, u8aToU8a } from '@polkadot/util';
|
||||
|
||||
import Abi from './Abi';
|
||||
import RxBase from './RxBase';
|
||||
import RxBlueprint from './RxBlueprint';
|
||||
|
||||
// Ok, tried, failed, eventually ... well, we are only trying with RxJs as a
|
||||
// start, so take a big fat shortcut with this version, real intended version
|
||||
// follows this and is commented out
|
||||
type CodePutCodeResultSubscription = Observable<CodePutCodeResult>;
|
||||
// type ICodePutCodeResultSubscription<ApiType> =
|
||||
// ApiType extends 'rxjs'
|
||||
// ? Observable<CodePutCodeResult>
|
||||
// : Promise<() => void>;
|
||||
|
||||
// unlike the ISubmittableExtrinsic, it doesn't extend IExtrinsic and only
|
||||
// implements one var iant of signAndSend - this is purely done to see what
|
||||
// is hanging where, with the bare-mainimum from a simplicity perspective
|
||||
// Very obvious is that it supports only 1 version of signAndSend
|
||||
// (we need to revisit this, but probably ok for initial?)
|
||||
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
|
||||
export interface CodePutCode {
|
||||
signAndSend (account: IKeyringPair | string | AccountId | Address): CodePutCodeResultSubscription;
|
||||
}
|
||||
|
||||
class CodePutCodeResult extends SubmittableResult {
|
||||
public readonly blueprint?: RxBlueprint;
|
||||
|
||||
public constructor (result: SubmittableResultImpl, blueprint?: RxBlueprint) {
|
||||
super(result);
|
||||
|
||||
this.blueprint = blueprint;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE Experimental, POC, bound to change
|
||||
export default class RxCode extends RxBase {
|
||||
public readonly code: Uint8Array;
|
||||
|
||||
public constructor (api: ApiRx, abi: ContractABI | Abi, wasm: string | Uint8Array) {
|
||||
super(api, abi);
|
||||
|
||||
this.code = u8aToU8a(wasm);
|
||||
}
|
||||
|
||||
public createBlueprint (maxGas: number | BN): CodePutCode {
|
||||
const signAndSend = (account: IKeyringPair | string | AccountId | Address): CodePutCodeResultSubscription => {
|
||||
return this.apiContracts
|
||||
.putCode(maxGas, compactAddLength(this.code))
|
||||
.signAndSend(account)
|
||||
.pipe(map(this.createResult));
|
||||
};
|
||||
|
||||
return { signAndSend };
|
||||
}
|
||||
|
||||
private createResult = (result: SubmittableResultImpl): CodePutCodeResult => {
|
||||
let blueprint: RxBlueprint | undefined;
|
||||
|
||||
if (result.isFinalized) {
|
||||
const record = result.findRecord('contract', 'CodeStored');
|
||||
|
||||
if (record) {
|
||||
blueprint = new RxBlueprint(this.api, this.abi, record.event.data[0] as Hash);
|
||||
}
|
||||
}
|
||||
|
||||
return new CodePutCodeResult(result, blueprint);
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, Address } from '@polkadot/types/interfaces';
|
||||
import { IKeyringPair } from '@polkadot/types/types';
|
||||
import { ContractABI, ContractABIFn, InterfaceContract, InterfaceContractCalls } from './types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ApiRx, SubmittableResult } from '@polkadot/api';
|
||||
import { createType } from '@polkadot/types';
|
||||
import Abi from './Abi';
|
||||
import RxBase from './RxBase';
|
||||
|
||||
export type ContractCallResultSubscription = Observable<SubmittableResult>;
|
||||
|
||||
export interface ContractCall {
|
||||
signAndSend (account: IKeyringPair | string | AccountId | Address): ContractCallResultSubscription;
|
||||
}
|
||||
|
||||
type CallResult = (value: BN | number, maxGas: BN | number, ...params: any[]) => ContractCall;
|
||||
|
||||
// NOTE Experimental, POC, bound to change
|
||||
export default class RxContract extends RxBase implements InterfaceContract {
|
||||
public readonly address: Address;
|
||||
|
||||
public readonly calls: InterfaceContractCalls = {};
|
||||
|
||||
public constructor (api: ApiRx, abi: ContractABI | Abi, address: string | AccountId | Address) {
|
||||
super(api, abi);
|
||||
|
||||
this.address = createType('Address', address);
|
||||
|
||||
Object.entries(abi.messages).forEach(([name]): void => {
|
||||
this.calls[name] = (fn: ContractABIFn): CallResult =>
|
||||
(value: BN | number, maxGas: BN | number, ...params: any[]): ContractCall =>
|
||||
this.apiContracts.call(this.address, value, maxGas, fn(...params));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiTypes, DecorateMethod, SubmittableResultImpl } from '@polkadot/api/types';
|
||||
import { AccountId, Address, Hash } from '@polkadot/types/interfaces';
|
||||
import { IKeyringPair } from '@polkadot/types/types';
|
||||
import { ApiObject, ContractABIPre } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { SubmittableResult } from '@polkadot/api';
|
||||
import { createType } from '@polkadot/types';
|
||||
import { assert } from '@polkadot/util';
|
||||
|
||||
import Abi from '../Abi';
|
||||
import Contract from './Contract';
|
||||
import { BaseWithTx } from './util';
|
||||
|
||||
type BlueprintCreateResultSubscription<ApiType extends ApiTypes> = Observable<BlueprintCreateResult<ApiType>>;
|
||||
|
||||
export interface BlueprintCreate<ApiType extends ApiTypes> {
|
||||
signAndSend (account: IKeyringPair | string | AccountId | Address): BlueprintCreateResultSubscription<ApiType>;
|
||||
}
|
||||
|
||||
class BlueprintCreateResult<ApiType extends ApiTypes> extends SubmittableResult {
|
||||
public readonly contract?: Contract<ApiType>;
|
||||
|
||||
constructor (result: SubmittableResultImpl, contract?: Contract<ApiType>) {
|
||||
super(result);
|
||||
|
||||
this.contract = contract;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE Experimental, POC, bound to change
|
||||
export default class Blueprint<ApiType extends ApiTypes> extends BaseWithTx<ApiType> {
|
||||
public readonly codeHash: Hash;
|
||||
|
||||
constructor (api: ApiObject<ApiType>, abi: ContractABIPre | Abi, decorateMethod: DecorateMethod<ApiType>, codeHash: string | Hash) {
|
||||
super(api, abi, decorateMethod);
|
||||
|
||||
this.codeHash = createType(this.registry, 'Hash', codeHash);
|
||||
}
|
||||
|
||||
public deployContract (constructorIndex = 0, endowment: number | BN, maxGas: number | BN, ...params: any[]): BlueprintCreate<ApiType> {
|
||||
assert(!!this.abi.constructors[constructorIndex], `Specified constructor index ${constructorIndex} does not exist`);
|
||||
|
||||
return {
|
||||
signAndSend: this.decorateMethod(
|
||||
(account: IKeyringPair | string | AccountId | Address): BlueprintCreateResultSubscription<ApiType> => {
|
||||
return this.apiContracts
|
||||
.create(endowment, maxGas, this.codeHash, this.abi.constructors[constructorIndex](...params))
|
||||
.signAndSend(account)
|
||||
.pipe(map(this.createResult));
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
private createResult = (result: SubmittableResult): BlueprintCreateResult<ApiType> => {
|
||||
let contract: Contract<ApiType> | undefined;
|
||||
|
||||
if (result.isFinalized) {
|
||||
const record = result.findRecord('contract', 'Instantiated');
|
||||
|
||||
if (record) {
|
||||
contract = new Contract<ApiType>(this.api, this.abi, this.decorateMethod, record.event.data[1] as Address);
|
||||
}
|
||||
}
|
||||
|
||||
return new BlueprintCreateResult(result, contract);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiTypes, DecorateMethod, SubmittableResultImpl } from '@polkadot/api/types';
|
||||
import { AccountId, Address, Hash } from '@polkadot/types/interfaces';
|
||||
import { IKeyringPair } from '@polkadot/types/types';
|
||||
import { ApiObject, ContractABIPre } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { SubmittableResult } from '@polkadot/api';
|
||||
import { compactAddLength, u8aToU8a } from '@polkadot/util';
|
||||
|
||||
import Abi from '../Abi';
|
||||
import Blueprint from './Blueprint';
|
||||
import { BaseWithTx } from './util';
|
||||
|
||||
type CodePutCodeResultSubscription<ApiType extends ApiTypes> = Observable<CodePutCodeResult<ApiType>>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
|
||||
export interface CodePutCode<ApiType extends ApiTypes> {
|
||||
signAndSend (account: IKeyringPair | string | AccountId | Address): CodePutCodeResultSubscription<ApiType>;
|
||||
}
|
||||
|
||||
class CodePutCodeResult<ApiType extends ApiTypes> extends SubmittableResult {
|
||||
public readonly blueprint?: Blueprint<ApiType>;
|
||||
|
||||
constructor (result: SubmittableResultImpl, blueprint?: Blueprint<ApiType>) {
|
||||
super(result);
|
||||
|
||||
this.blueprint = blueprint;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE Experimental, POC, bound to change
|
||||
export default class Code<ApiType extends ApiTypes> extends BaseWithTx<ApiType> {
|
||||
public readonly code: Uint8Array;
|
||||
|
||||
constructor (api: ApiObject<ApiType>, abi: ContractABIPre | Abi, decorateMethod: DecorateMethod<ApiType>, wasm: string | Uint8Array) {
|
||||
super(api, abi, decorateMethod);
|
||||
|
||||
this.code = u8aToU8a(wasm);
|
||||
}
|
||||
|
||||
public createBlueprint = (maxGas: number | BN): CodePutCode<ApiType> => {
|
||||
return {
|
||||
signAndSend: this.decorateMethod(
|
||||
(account: IKeyringPair | string | AccountId | Address): CodePutCodeResultSubscription<ApiType> => this.apiContracts
|
||||
.putCode(maxGas, compactAddLength(this.code))
|
||||
.signAndSend(account)
|
||||
.pipe(map(this.createResult))
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
private createResult = (result: SubmittableResultImpl): CodePutCodeResult<ApiType> => {
|
||||
let blueprint: Blueprint<ApiType> | undefined;
|
||||
|
||||
if (result.isFinalized) {
|
||||
const record = result.findRecord('contract', 'CodeStored');
|
||||
|
||||
if (record) {
|
||||
blueprint = new Blueprint<ApiType>(this.api, this.abi, this.decorateMethod, record.event.data[0] as Hash);
|
||||
}
|
||||
}
|
||||
|
||||
return new CodePutCodeResult(result, blueprint);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiTypes, DecorateMethod, ObsInnerType } from '@polkadot/api/types';
|
||||
import { AccountId, Address, ContractExecResult } from '@polkadot/types/interfaces';
|
||||
import { Codec, IKeyringPair } from '@polkadot/types/types';
|
||||
import { ApiObject, ContractABIMessage, ContractABIPre, ContractCallOutcome } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { SubmittableResult } from '@polkadot/api';
|
||||
import { createType } from '@polkadot/types';
|
||||
import Abi from '../Abi';
|
||||
import { formatData } from '../util';
|
||||
import { BaseWithTxAndRpcCall } from './util';
|
||||
|
||||
type ContractCallTypes = 'tx' | 'rpc';
|
||||
|
||||
type ContractCallResultSubscription<ApiType extends ApiTypes, CallType extends ContractCallTypes> = ApiType extends 'rxjs'
|
||||
? Observable<ContractCallResult<CallType>>
|
||||
: Promise<ObsInnerType<ContractCallResult<CallType>>>;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
|
||||
export interface ContractCall<ApiType extends ApiTypes, CallType extends ContractCallTypes> {
|
||||
send (account: IKeyringPair | string | AccountId | Address): ContractCallResultSubscription<ApiType, CallType>;
|
||||
}
|
||||
|
||||
export type ContractCallResult<CallType extends ContractCallTypes> = CallType extends 'rpc'
|
||||
? Observable<ContractCallOutcome>
|
||||
: Observable<SubmittableResult>;
|
||||
|
||||
export default class Contract<ApiType extends ApiTypes> extends BaseWithTxAndRpcCall<ApiType> {
|
||||
public readonly address: Address;
|
||||
|
||||
public call (as: 'rpc', message: string, value: BN | number, gasLimit: BN | number, ...params: any[]): ContractCall<ApiType, 'rpc'>;
|
||||
public call (as: 'tx', message: string, value: BN | number, gasLimit: BN | number, ...params: any[]): ContractCall<ApiType, 'tx'>;
|
||||
public call<CallType extends ContractCallTypes> (as: CallType, message: string, value: BN | number, gasLimit: BN | number, ...params: any[]): ContractCall<ApiType, CallType> {
|
||||
const { fn, def } = this.getMessage(message);
|
||||
|
||||
return {
|
||||
send: this.decorateMethod(
|
||||
as === 'rpc' && this.hasRpcContractsCall
|
||||
? (account: IKeyringPair | string | AccountId | Address): ContractCallResult<'rpc'> => {
|
||||
return this.rpcContractsCall(
|
||||
createType(this.registry, 'ContractCallRequest', {
|
||||
origin: account,
|
||||
dest: this.address.toString(),
|
||||
value,
|
||||
gasLimit,
|
||||
inputData: fn(...params)
|
||||
})
|
||||
)
|
||||
.pipe(
|
||||
map((result: ContractExecResult): ContractCallOutcome =>
|
||||
this.createOutcome(result, createType(this.registry, 'AccountId', account), def, params)
|
||||
)
|
||||
);
|
||||
}
|
||||
: (account: IKeyringPair | string | AccountId | Address): ContractCallResult<'tx'> => {
|
||||
return this.apiContracts
|
||||
.call(this.address, value, gasLimit, fn(...params))
|
||||
.signAndSend(account);
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
private createOutcome (result: ContractExecResult, origin: AccountId, message: ContractABIMessage, params: any[]): ContractCallOutcome {
|
||||
let output: Codec | null = null;
|
||||
|
||||
if (result.isSuccess) {
|
||||
const { data } = result.asSuccess;
|
||||
|
||||
output = message.returnType
|
||||
? formatData(this.registry, data, message.returnType)
|
||||
: createType(this.registry, 'Raw', data);
|
||||
}
|
||||
|
||||
return {
|
||||
time: Date.now(),
|
||||
message,
|
||||
origin,
|
||||
params,
|
||||
result,
|
||||
isSuccess: result.isSuccess,
|
||||
output
|
||||
};
|
||||
}
|
||||
|
||||
constructor (api: ApiObject<ApiType>, abi: ContractABIPre | Abi, decorateMethod: DecorateMethod<ApiType>, address: string | AccountId | Address) {
|
||||
super(api, abi, decorateMethod);
|
||||
|
||||
this.address = createType(this.registry, 'Address', address);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright 2017-2020 @polkadot/api authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
export { default as Blueprint } from './Blueprint';
|
||||
export { default as Code } from './Code';
|
||||
export { default as Contract } from './Contract';
|
||||
@@ -0,0 +1,78 @@
|
||||
// Copyright 2017-2020 @polkadot/api authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiTypes, DecorateMethod, DecoratedRpc, SubmittableModuleExtrinsics } from '@polkadot/api/types';
|
||||
import { ApiObject, ContractABIMessage, ContractABIPre, ContractBase, ContractMessage } from '../types';
|
||||
import { RpcInterface } from '@polkadot/rpc-core/jsonrpc.types';
|
||||
import { Registry } from '@polkadot/types/types';
|
||||
|
||||
import { assert, isFunction, stringCamelCase } from '@polkadot/util';
|
||||
import Abi from '../Abi';
|
||||
|
||||
export abstract class Base<ApiType extends ApiTypes> implements ContractBase<ApiType> {
|
||||
public readonly abi: Abi;
|
||||
|
||||
public readonly api: ApiObject<ApiType>;
|
||||
|
||||
public readonly decorateMethod: DecorateMethod<ApiType>;
|
||||
|
||||
public readonly registry: Registry;
|
||||
|
||||
constructor (api: ApiObject<ApiType>, abi: ContractABIPre | Abi, decorateMethod: DecorateMethod<ApiType>) {
|
||||
this.abi = abi instanceof Abi
|
||||
? abi
|
||||
: new Abi(api.registry, abi);
|
||||
this.registry = api.registry;
|
||||
this.api = api;
|
||||
this.decorateMethod = decorateMethod;
|
||||
}
|
||||
|
||||
public get messages (): ContractMessage[] {
|
||||
return this.abi.abi.contract.messages
|
||||
.map(
|
||||
(def: ContractABIMessage, index): ContractMessage => ({
|
||||
index,
|
||||
def,
|
||||
fn: this.abi.messages[def.name] || this.abi.messages[stringCamelCase(name)]
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public getMessage (nameOrIndex?: string | number): ContractMessage {
|
||||
const index = nameOrIndex
|
||||
? typeof nameOrIndex === 'number'
|
||||
? nameOrIndex
|
||||
: this.abi.abi.contract.messages.findIndex((message): boolean => nameOrIndex === message.name || nameOrIndex === stringCamelCase(message.name))
|
||||
: 0;
|
||||
const def = this.abi.abi.contract.messages[index];
|
||||
assert(!!def, `Attempted to access a contract message that does not exist: ${typeof nameOrIndex === 'number' ? `index ${nameOrIndex}` : nameOrIndex}`);
|
||||
|
||||
const fn = this.abi.messages[def.name] || this.abi.messages[stringCamelCase(def.name)];
|
||||
return { index, def, fn };
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class BaseWithTx<ApiType extends ApiTypes> extends Base<ApiType> {
|
||||
protected get apiContracts (): SubmittableModuleExtrinsics<'rxjs'> {
|
||||
return this.api.rx.tx.contracts;
|
||||
}
|
||||
|
||||
constructor (api: ApiObject<ApiType>, abi: ContractABIPre | Abi, decorateMethod: DecorateMethod<ApiType>) {
|
||||
super(api, abi, decorateMethod);
|
||||
|
||||
assert(this.api.rx.tx.contracts && this.api.rx.tx.contracts.putCode, 'You need to connect to a node with the contracts module, the metadata does not enable api.tx.contracts on this instance');
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class BaseWithTxAndRpcCall<ApiType extends ApiTypes> extends BaseWithTx<ApiType> {
|
||||
public get hasRpcContractsCall (): boolean {
|
||||
return isFunction(this.api.rx.rpc.contracts?.call);
|
||||
}
|
||||
|
||||
protected get rpcContractsCall (): DecoratedRpc<'rxjs', RpcInterface>['contracts']['call'] {
|
||||
assert(this.hasRpcContractsCall, 'You need to connect to a node with the contracts.call RPC method.');
|
||||
|
||||
return this.api.rx.rpc.contracts.call;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
// Copyright 2017-2019 @polkadot/api-contract authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
export { default as Abi } from './Abi';
|
||||
export { default as RxBlueprint } from './RxBlueprint';
|
||||
export { default as RxCode } from './RxCode';
|
||||
export { default as RxContract } from './RxContract';
|
||||
export * from './rx';
|
||||
export * from './promise';
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { CodecArg, Constructor } from '@polkadot/types/types';
|
||||
import { ContractABIFn, ContractABIFnArg, ContractABIMethod, ContractABIMethodBase, ContractABITypes } from './types';
|
||||
|
||||
import { Compact, createClass } from '@polkadot/types';
|
||||
import { assert, isString, isUndefined, stringCamelCase } from '@polkadot/util';
|
||||
|
||||
export function typeToString (type: ContractABITypes): string {
|
||||
if (isString(type)) {
|
||||
return type;
|
||||
} else if (Array.isArray(type)) {
|
||||
return `(${type.map((type): string => typeToString(type)).join(',')})`;
|
||||
} else if (type['Option<T>']) {
|
||||
return `Option<${typeToString(type['Option<T>'].T)}>`;
|
||||
} else if (type['Result<T,E>']) {
|
||||
return '()'; // Result is not supported, but only applicable for returns
|
||||
} else if (type['Vec<T>']) {
|
||||
return `Vec<${typeToString(type['Vec<T>'].T)}>`;
|
||||
} else if (type['[T;n]']) {
|
||||
return `[${typeToString(type['[T;n]'].T)};${type['[T;n]'].n}]`;
|
||||
}
|
||||
|
||||
throw new Error(`Unknown type specified ${JSON.stringify(type)}`);
|
||||
}
|
||||
|
||||
export function createArgClass (args: ContractABIFnArg[], baseDef: Record<string, string>): Constructor {
|
||||
return createClass(
|
||||
JSON.stringify(
|
||||
args.reduce((base: Record<string, any>, { name, type }): Record<string, any> => {
|
||||
base[name] = type;
|
||||
|
||||
return base;
|
||||
}, baseDef)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export function createMethod (name: string, method: Partial<ContractABIMethod> & ContractABIMethodBase): ContractABIFn {
|
||||
const args: ContractABIFnArg[] = method.args.map(({ name, type }): ContractABIFnArg => ({
|
||||
name: stringCamelCase(name),
|
||||
type: typeToString(type)
|
||||
}));
|
||||
const Clazz = createArgClass(args, isUndefined(method.selector) ? {} : { __selector: 'u32' });
|
||||
const baseStruct: { [index: string]: any } = { __selector: method.selector };
|
||||
const encoder = (...params: CodecArg[]): Uint8Array => {
|
||||
assert(params.length === args.length, `Expected ${args.length} arguments to contract ${name}, found ${params.length}`);
|
||||
|
||||
const u8a = new Clazz(
|
||||
args.reduce((mapped, { name }, index): Record<string, CodecArg> => {
|
||||
mapped[name] = params[index];
|
||||
|
||||
return mapped;
|
||||
}, { ...baseStruct })
|
||||
).toU8a();
|
||||
|
||||
return Compact.addLengthPrefix(u8a);
|
||||
};
|
||||
|
||||
const fn = (encoder as ContractABIFn);
|
||||
|
||||
fn.args = args;
|
||||
fn.isConstant = !(method.mutates || false);
|
||||
fn.type = method.return_type ? typeToString(method.return_type) : null;
|
||||
|
||||
return fn;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { Hash } from '@polkadot/types/interfaces';
|
||||
import { ContractABIPre } from '../types';
|
||||
|
||||
import { ApiPromise } from '@polkadot/api';
|
||||
import { decorateMethod } from '@polkadot/api/promise';
|
||||
|
||||
import Abi from '../Abi';
|
||||
import Blueprint from '../base/Blueprint';
|
||||
|
||||
export default class PromiseBlueprint extends Blueprint<'promise'> {
|
||||
constructor (api: ApiPromise, abi: ContractABIPre | Abi, codeHash: string | Hash) {
|
||||
super(api, abi, decorateMethod, codeHash);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ContractABIPre } from '../types';
|
||||
|
||||
import { ApiPromise } from '@polkadot/api';
|
||||
import { decorateMethod } from '@polkadot/api/promise';
|
||||
|
||||
import Abi from '../Abi';
|
||||
import Code from '../base/Code';
|
||||
|
||||
export default class PromiseCode extends Code<'promise'> {
|
||||
constructor (api: ApiPromise, abi: ContractABIPre | Abi, wasm: string | Uint8Array) {
|
||||
super(api, abi, decorateMethod, wasm);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId } from '@polkadot/types/interfaces';
|
||||
import { ContractABIPre } from '../types';
|
||||
|
||||
import { ApiPromise } from '@polkadot/api';
|
||||
import { decorateMethod } from '@polkadot/api/promise';
|
||||
|
||||
import Abi from '../Abi';
|
||||
import Contract from '../base/Contract';
|
||||
|
||||
export default class PromiseContract extends Contract<'promise'> {
|
||||
constructor (api: ApiPromise, abi: ContractABIPre | Abi, address: string | AccountId) {
|
||||
super(api, abi, decorateMethod, address);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
export { default as PromiseBlueprint } from './PromiseBlueprint';
|
||||
export { default as PromiseCode } from './PromiseCode';
|
||||
export { default as PromiseContract } from './PromiseContract';
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { Hash } from '@polkadot/types/interfaces';
|
||||
import { ContractABIPre } from '../types';
|
||||
|
||||
import { ApiRx } from '@polkadot/api';
|
||||
import { decorateMethod } from '@polkadot/api/rx';
|
||||
|
||||
import Abi from '../Abi';
|
||||
import Blueprint from '../base/Blueprint';
|
||||
|
||||
export default class RxBlueprint extends Blueprint<'rxjs'> {
|
||||
constructor (api: ApiRx, abi: ContractABIPre | Abi, codeHash: string | Hash) {
|
||||
super(api, abi, decorateMethod, codeHash);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ContractABIPre } from '../types';
|
||||
|
||||
import { ApiRx } from '@polkadot/api';
|
||||
import { decorateMethod } from '@polkadot/api/rx';
|
||||
|
||||
import Abi from '../Abi';
|
||||
import Code from '../base/Code';
|
||||
|
||||
export default class RxCode extends Code<'rxjs'> {
|
||||
constructor (api: ApiRx, abi: ContractABIPre | Abi, wasm: string | Uint8Array) {
|
||||
super(api, abi, decorateMethod, wasm);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId } from '@polkadot/types/interfaces';
|
||||
import { ContractABIPre } from '../types';
|
||||
|
||||
import { ApiRx } from '@polkadot/api';
|
||||
import { decorateMethod } from '@polkadot/api/rx';
|
||||
|
||||
import Abi from '../Abi';
|
||||
import Contract from '../base/Contract';
|
||||
|
||||
export default class RxContract extends Contract<'rxjs'> {
|
||||
constructor (api: ApiRx, abi: ContractABIPre | Abi, address: string | AccountId) {
|
||||
super(api, abi, decorateMethod, address);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
export { default as RxBlueprint } from './RxBlueprint';
|
||||
export { default as RxCode } from './RxCode';
|
||||
export { default as RxContract } from './RxContract';
|
||||
@@ -1,87 +1,192 @@
|
||||
// Copyright 2017-2019 @polkadot/api-contract authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { SubmittableModuleExtrinsics } from '@polkadot/api/types';
|
||||
import { Address } from '@polkadot/types/interfaces';
|
||||
import { CodecArg } from '@polkadot/types/types';
|
||||
import { ApiTypes, DecorateMethod } from '@polkadot/api/types';
|
||||
import { AccountId, Address, ContractExecResult } from '@polkadot/types/interfaces';
|
||||
import { Codec, CodecArg } from '@polkadot/types/types';
|
||||
import { MetaRegistryJson, StringIndex, TypeIndex, TypeDef } from '@polkadot/types/codec/create/types';
|
||||
|
||||
// import { Observable } from 'rxjs';
|
||||
import { ApiPromise, ApiRx } from '@polkadot/api';
|
||||
|
||||
export type ApiObject<ApiType> = ApiType extends 'rxjs'
|
||||
export type ApiObject<ApiType extends ApiTypes> = ApiType extends 'rxjs'
|
||||
? ApiRx
|
||||
: ApiPromise;
|
||||
|
||||
export interface ContractABITypesStruct {
|
||||
'Option<T>'?: {
|
||||
T: ContractABITypes;
|
||||
};
|
||||
'Result<T,E>'?: {
|
||||
T: ContractABITypes;
|
||||
E: ContractABITypes;
|
||||
};
|
||||
'Vec<T>'?: {
|
||||
T: ContractABITypes;
|
||||
};
|
||||
'[T;n]'?: {
|
||||
T: ContractABITypes;
|
||||
n: number;
|
||||
};
|
||||
export interface ContractBase<ApiType extends ApiTypes> {
|
||||
readonly abi: InterfaceAbi;
|
||||
readonly api: ApiObject<ApiType>;
|
||||
readonly decorateMethod: DecorateMethod<ApiType>;
|
||||
getMessage: (name: string) => ContractMessage;
|
||||
messages: ContractMessage[];
|
||||
}
|
||||
|
||||
export type ContractABITypes = string | ContractABITypesStruct | (string | ContractABITypesStruct)[];
|
||||
export interface ContractABITypePre {
|
||||
ty: TypeIndex;
|
||||
display_name: StringIndex[];
|
||||
}
|
||||
|
||||
export interface ContractABIArg {
|
||||
export interface ContractABIArgBasePre {
|
||||
name: StringIndex;
|
||||
type: ContractABITypePre;
|
||||
}
|
||||
|
||||
export interface ContractABIArgBase {
|
||||
name: string;
|
||||
type: ContractABITypes;
|
||||
type: TypeDef;
|
||||
}
|
||||
|
||||
export interface ContractABIMethodBase {
|
||||
args: ContractABIArg[];
|
||||
export type ContractABIMessageArgPre = ContractABIArgBasePre;
|
||||
|
||||
export type ContractABIMessageArg = ContractABIArgBase;
|
||||
|
||||
export interface ContractABIMessageBase {
|
||||
args: ContractABIMessageArg[];
|
||||
}
|
||||
|
||||
export interface ContractABIMethod extends ContractABIMethodBase {
|
||||
export interface ContractABIMessageBasePre {
|
||||
args: ContractABIMessageArgPre[];
|
||||
}
|
||||
|
||||
export interface ContractABIMessageCommon {
|
||||
docs?: ContractABIDocs;
|
||||
mutates?: boolean;
|
||||
selector: string | number;
|
||||
}
|
||||
|
||||
export interface ContractABIMessagePre extends ContractABIMessageCommon, ContractABIMessageBasePre {
|
||||
name: StringIndex;
|
||||
return_type: ContractABITypePre | null;
|
||||
}
|
||||
|
||||
export interface ContractABIMessage extends ContractABIMessageCommon {
|
||||
args: ContractABIMessageArg[];
|
||||
name: string;
|
||||
selector: number;
|
||||
return_type: ContractABITypes | null;
|
||||
returnType: TypeDef | null;
|
||||
}
|
||||
|
||||
export interface ContractABIContractCommon {
|
||||
docs?: ContractABIDocs;
|
||||
}
|
||||
|
||||
export interface ContractABIContractPre extends ContractABIContractCommon {
|
||||
constructors: ContractABIMessagePre[];
|
||||
messages: ContractABIMessagePre[];
|
||||
name: StringIndex;
|
||||
events?: ContractABIEventPre[];
|
||||
docs?: ContractABIDocs;
|
||||
}
|
||||
|
||||
export interface ContractABIContract extends ContractABIContractCommon {
|
||||
constructors: ContractABIMessage[];
|
||||
messages: ContractABIMessage[];
|
||||
name: string;
|
||||
events?: ContractABIEvent[];
|
||||
docs?: ContractABIDocs;
|
||||
}
|
||||
|
||||
export interface ContractABIPre extends MetaRegistryJson {
|
||||
storage: ContractABIStoragePre;
|
||||
contract: ContractABIContractPre;
|
||||
}
|
||||
|
||||
export interface ContractABI {
|
||||
deploy: ContractABIMethodBase;
|
||||
messages: ContractABIMethod[];
|
||||
name: string;
|
||||
storage: ContractABIStorage;
|
||||
contract: ContractABIContract;
|
||||
}
|
||||
|
||||
export interface ContractABIFnArg {
|
||||
name: string;
|
||||
type: string;
|
||||
type: TypeDef;
|
||||
}
|
||||
|
||||
export interface ContractABIMeta {
|
||||
args: ContractABIFnArg[];
|
||||
isConstant: boolean;
|
||||
type: string | null;
|
||||
type: TypeDef | null;
|
||||
}
|
||||
|
||||
export interface ContractABIFn extends ContractABIMeta {
|
||||
(...args: CodecArg[]): Uint8Array;
|
||||
}
|
||||
|
||||
export interface ContractABIEventArgBase {
|
||||
indexed: boolean;
|
||||
}
|
||||
|
||||
export interface ContractABIEventArgPre extends ContractABIArgBasePre, ContractABIEventArgBase {}
|
||||
|
||||
export interface ContractABIEventArg extends ContractABIArgBase, ContractABIEventArgBase {}
|
||||
|
||||
export type ContractABIDocs = string[];
|
||||
|
||||
export interface ContractABIEventPre {
|
||||
args: ContractABIEventArgPre[];
|
||||
}
|
||||
|
||||
export interface ContractABIEvent {
|
||||
args: ContractABIEventArg[];
|
||||
}
|
||||
|
||||
export interface ContractABIRangeBase {
|
||||
// can be number[] (old) or hex (new)
|
||||
'range.offset': number[] | string;
|
||||
'range.len': number;
|
||||
}
|
||||
|
||||
export interface ContractABIRangePre extends ContractABIRangeBase {
|
||||
'range.elem_type': TypeIndex;
|
||||
}
|
||||
|
||||
export interface ContractABIRange extends ContractABIRangeBase {
|
||||
'range.elem_type': TypeDef;
|
||||
}
|
||||
|
||||
export type ContractABIStorageLayoutPre = ContractABIStorageStructPre | ContractABIRangePre;
|
||||
|
||||
export type ContractABIStorageLayout = ContractABIStorageStruct | ContractABIRange;
|
||||
|
||||
export interface ContractABIStorageStructFieldPre {
|
||||
name: StringIndex;
|
||||
layout: ContractABIStorageLayoutPre;
|
||||
}
|
||||
|
||||
export interface ContractABIStorageStructField {
|
||||
name: string;
|
||||
layout: ContractABIStorageLayout;
|
||||
}
|
||||
|
||||
export interface ContractABIStorageStructPre {
|
||||
'struct.type': TypeIndex;
|
||||
'struct.fields': ContractABIStorageStructFieldPre[];
|
||||
}
|
||||
|
||||
export interface ContractABIStorageStruct {
|
||||
'struct.type': TypeDef;
|
||||
'struct.fields': ContractABIStorageStructField[];
|
||||
}
|
||||
|
||||
export type ContractABIStoragePre = ContractABIStorageStructPre;
|
||||
|
||||
export type ContractABIStorage = ContractABIStorageStruct;
|
||||
|
||||
export interface ContractMessage {
|
||||
index: number;
|
||||
fn: ContractABIFn;
|
||||
def: ContractABIMessage;
|
||||
}
|
||||
|
||||
export type AbiConstructors = ContractABIFn[];
|
||||
|
||||
export type AbiMessages = Record<string, ContractABIFn>;
|
||||
|
||||
export interface InterfaceAbi {
|
||||
readonly abi: ContractABI;
|
||||
readonly deploy: ContractABIFn;
|
||||
readonly constructors: AbiConstructors;
|
||||
readonly messages: AbiMessages;
|
||||
}
|
||||
|
||||
export interface ContractBase<ApiType> {
|
||||
readonly abi: InterfaceAbi;
|
||||
readonly api: ApiObject<ApiType>;
|
||||
readonly apiContracts: SubmittableModuleExtrinsics<ApiType>;
|
||||
}
|
||||
|
||||
export interface InterfaceContractCalls {
|
||||
[index: string]: Function;
|
||||
}
|
||||
@@ -90,3 +195,13 @@ export interface InterfaceContract {
|
||||
readonly address: Address;
|
||||
readonly calls: InterfaceContractCalls;
|
||||
}
|
||||
|
||||
export interface ContractCallOutcome {
|
||||
time: number;
|
||||
result: ContractExecResult;
|
||||
origin: AccountId;
|
||||
output: Codec | null;
|
||||
params: any[];
|
||||
isSuccess: boolean;
|
||||
message: ContractABIMessage;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 2017-2020 @polkadot/rpc-core authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { Codec, Registry, TypeDefInfo, TypeDef } from '@polkadot/types/types';
|
||||
|
||||
import { Option, Raw, createClass } from '@polkadot/types';
|
||||
import { createTypeUnsafe } from '@polkadot/types/codec';
|
||||
|
||||
export function formatData (registry: Registry, data: Raw, { info, type }: TypeDef): Codec {
|
||||
if (info === TypeDefInfo.Option) {
|
||||
return new Option(
|
||||
registry,
|
||||
createClass(registry, type),
|
||||
createTypeUnsafe(registry, type, [data], true)
|
||||
);
|
||||
}
|
||||
|
||||
return createTypeUnsafe(registry, type, [data], true);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,50 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/api-contract authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ContractABI, ContractABIArg } from './types';
|
||||
|
||||
import { assert, isNumber, isNull, isString, isObject } from '@polkadot/util';
|
||||
|
||||
export function validateArgs (name: string, args: ContractABIArg[]): void {
|
||||
assert(Array.isArray(args), `Expected 'args' to exist on ${name}`);
|
||||
|
||||
args.forEach((arg): void => {
|
||||
const unknownKeys = Object.keys(arg).filter((key): boolean => !['name', 'type'].includes(key));
|
||||
|
||||
assert(unknownKeys.length === 0, `Unknown keys ${unknownKeys.join(', ')} found in ABI args for ${name}`);
|
||||
assert(isString(arg.name), `${name} args should have valid name `);
|
||||
assert(isString(arg.type) || isObject(arg.type), `${name} args should have valid type`);
|
||||
});
|
||||
}
|
||||
|
||||
export function validateDeploy ({ deploy }: ContractABI): void {
|
||||
const unknownKeys = Object.keys(deploy).filter((key): boolean => !['args'].includes(key));
|
||||
|
||||
assert(unknownKeys.length === 0, `Unknown keys ${unknownKeys.join(', ')} found in ABI deploy`);
|
||||
|
||||
validateArgs('deploy', deploy.args);
|
||||
}
|
||||
|
||||
export function validateMethods ({ messages }: ContractABI): void {
|
||||
messages.forEach((method): void => {
|
||||
const unknownKeys = Object.keys(method).filter((key): boolean => !['args', 'mutates', 'name', 'selector', 'return_type'].includes(key));
|
||||
|
||||
assert(unknownKeys.length === 0, `Unknown keys ${unknownKeys.join(', ')} found in ABI args for messages.${method.name}`);
|
||||
assert(isString(method.name), `Expected name for messages.${method.name}`);
|
||||
assert(isNumber(method.selector), `Expected selector for messages.${method.name}`);
|
||||
assert(isNull(method.return_type) || isString(method.return_type) || isObject(method.return_type), `Expected return_type for messages.${method.name}`);
|
||||
|
||||
validateArgs(`messages.${method.name}`, method.args);
|
||||
});
|
||||
}
|
||||
|
||||
export function validateAbi (abi: ContractABI): void {
|
||||
const unknownKeys = Object.keys(abi).filter((key): boolean => !['deploy', 'messages', 'name'].includes(key));
|
||||
|
||||
assert(unknownKeys.length === 0, `Unknown fields ${unknownKeys.join(', ')} found in ABI`);
|
||||
assert(abi.deploy && abi.messages && isString(abi.name), 'ABI should have deploy, messages & name sections');
|
||||
|
||||
validateDeploy(abi);
|
||||
validateMethods(abi);
|
||||
}
|
||||
@@ -0,0 +1,467 @@
|
||||
{
|
||||
"registry": {
|
||||
"strings": [
|
||||
"StorageAndEnv",
|
||||
"app",
|
||||
"__ink_private",
|
||||
"__ink_storage",
|
||||
"__storage",
|
||||
"Storage",
|
||||
"value",
|
||||
"Value",
|
||||
"ink_core",
|
||||
"storage",
|
||||
"cell",
|
||||
"SyncCell",
|
||||
"sync_cell",
|
||||
"Key",
|
||||
"key",
|
||||
"name",
|
||||
"vec",
|
||||
"Vec",
|
||||
"elems",
|
||||
"__env",
|
||||
"EnvAccess",
|
||||
"env2",
|
||||
"env_access",
|
||||
"immutable",
|
||||
"TestEnv",
|
||||
"test",
|
||||
"accessor",
|
||||
"DefaultSrmlTypes",
|
||||
"types",
|
||||
"access",
|
||||
"EnvAccessMut",
|
||||
"mutable",
|
||||
"env",
|
||||
"PhantomData",
|
||||
"buffer",
|
||||
"has_interacted",
|
||||
"has_returned_value",
|
||||
"new",
|
||||
"init_value",
|
||||
"bool",
|
||||
"default",
|
||||
"flip",
|
||||
"get"
|
||||
],
|
||||
"types": [
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 1,
|
||||
"custom.namespace": [
|
||||
2,
|
||||
2,
|
||||
3,
|
||||
4
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 5,
|
||||
"type": 2
|
||||
},
|
||||
{
|
||||
"name": 20,
|
||||
"type": 14
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 6,
|
||||
"custom.namespace": [
|
||||
2,
|
||||
2,
|
||||
3,
|
||||
4
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 7,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"name": 16,
|
||||
"type": 9
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 8,
|
||||
"custom.namespace": [
|
||||
9,
|
||||
10,
|
||||
7
|
||||
],
|
||||
"custom.params": [
|
||||
4
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 11,
|
||||
"type": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "bool",
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 12,
|
||||
"custom.namespace": [
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
13
|
||||
],
|
||||
"custom.params": [
|
||||
4
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 11,
|
||||
"type": 6
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 14,
|
||||
"custom.namespace": [
|
||||
9,
|
||||
10,
|
||||
15
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"tuple_struct.types": [
|
||||
7
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"array.len": 32,
|
||||
"array.type": 8
|
||||
},
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": "u8",
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 8,
|
||||
"custom.namespace": [
|
||||
9,
|
||||
10,
|
||||
7
|
||||
],
|
||||
"custom.params": [
|
||||
10
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 11,
|
||||
"type": 13
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "str",
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 17,
|
||||
"type": 11
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 18,
|
||||
"custom.namespace": [],
|
||||
"custom.params": [
|
||||
8
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 19,
|
||||
"type": 12
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"slice.type": 8
|
||||
},
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 12,
|
||||
"custom.namespace": [
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
13
|
||||
],
|
||||
"custom.params": [
|
||||
10
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 11,
|
||||
"type": 6
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 21,
|
||||
"custom.namespace": [
|
||||
9,
|
||||
22,
|
||||
23,
|
||||
24
|
||||
],
|
||||
"custom.params": [
|
||||
15
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 30,
|
||||
"type": 17
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 25,
|
||||
"custom.namespace": [
|
||||
9,
|
||||
22,
|
||||
26,
|
||||
27
|
||||
],
|
||||
"custom.params": [
|
||||
16
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 28,
|
||||
"custom.namespace": [
|
||||
9,
|
||||
22,
|
||||
29
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"clike_enum.variants": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 31,
|
||||
"custom.namespace": [
|
||||
9,
|
||||
22,
|
||||
23,
|
||||
32
|
||||
],
|
||||
"custom.params": [
|
||||
15
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 33,
|
||||
"type": 18
|
||||
},
|
||||
{
|
||||
"name": 35,
|
||||
"type": 11
|
||||
},
|
||||
{
|
||||
"name": 36,
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"name": 37,
|
||||
"type": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 34,
|
||||
"custom.namespace": [],
|
||||
"custom.params": [
|
||||
15
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"tuple_struct.types": []
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"storage": {
|
||||
"struct.type": 1,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"layout": {
|
||||
"struct.type": 2,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 7,
|
||||
"layout": {
|
||||
"struct.type": 3,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 11,
|
||||
"layout": {
|
||||
"range.offset": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"range.len": 1,
|
||||
"range.elem_type": 4
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 16,
|
||||
"layout": {
|
||||
"struct.type": 9,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 11,
|
||||
"layout": {
|
||||
"range.offset": "0x0000000000000000000000000000000000000000000000000000000000000001",
|
||||
"range.len": 1,
|
||||
"range.elem_type": 10
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"contract": {
|
||||
"name": 2,
|
||||
"constructors": [
|
||||
{
|
||||
"name": 38,
|
||||
"selector": "[\"0x5E\",\"0xBD\",\"0x88\",\"0xD6\"]",
|
||||
"args": [
|
||||
{
|
||||
"name": 16,
|
||||
"type": {
|
||||
"ty": 11,
|
||||
"display_name": [
|
||||
18
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 39,
|
||||
"type": {
|
||||
"ty": 4,
|
||||
"display_name": [
|
||||
40
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"docs": [
|
||||
"Constructor that initializes the `bool` value to the given `init_value`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": 41,
|
||||
"selector": "[\"0x02\",\"0x22\",\"0xFF\",\"0x18\"]",
|
||||
"args": [],
|
||||
"docs": [
|
||||
"Constructor that initializes the `bool` value to `false`.",
|
||||
"",
|
||||
"Constructors can delegate to other constructors."
|
||||
]
|
||||
}
|
||||
],
|
||||
"messages": [
|
||||
{
|
||||
"name": 42,
|
||||
"selector": "[\"0x8C\",\"0x97\",\"0xDB\",\"0x39\"]",
|
||||
"mutates": true,
|
||||
"args": [],
|
||||
"return_type": null,
|
||||
"docs": [
|
||||
"A message that can be called on instantiated contracts.",
|
||||
"This one flips the value of the stored `bool` from `true`",
|
||||
"to `false` and vice versa."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": 43,
|
||||
"selector": "[\"0x25\",\"0x44\",\"0x4A\",\"0xFE\"]",
|
||||
"mutates": false,
|
||||
"args": [],
|
||||
"return_type": {
|
||||
"ty": 4,
|
||||
"display_name": [
|
||||
40
|
||||
]
|
||||
},
|
||||
"docs": [
|
||||
"Simply returns the current value of our `bool`."
|
||||
]
|
||||
}
|
||||
],
|
||||
"events": [],
|
||||
"docs": []
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,184 @@
|
||||
[
|
||||
{
|
||||
"info": 8,
|
||||
"type": "{\"value\": {\"cell\": {\"cell\": ([u8;32])}}}",
|
||||
"name": "Flipper",
|
||||
"namespace": "flipper::normal",
|
||||
"sub": [
|
||||
{
|
||||
"info": 8,
|
||||
"type": "{\"cell\": {\"cell\": ([u8;32])}}",
|
||||
"name": "value",
|
||||
"namespace": "ink_core::storage::value",
|
||||
"params": [
|
||||
{
|
||||
"info": 6,
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"sub": [
|
||||
{
|
||||
"info": 8,
|
||||
"type": "{\"cell\": ([u8;32])}",
|
||||
"name": "cell",
|
||||
"namespace": "ink_core::storage::cell::sync_cell",
|
||||
"params": [
|
||||
{
|
||||
"info": 6,
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"sub": [
|
||||
{
|
||||
"info": 9,
|
||||
"type": "([u8;32])",
|
||||
"name": "cell",
|
||||
"namespace": "ink_core::storage::key",
|
||||
"sub": [
|
||||
{
|
||||
"info": 11,
|
||||
"type": "[u8;32]",
|
||||
"ext": {
|
||||
"length": 32,
|
||||
"type": ""
|
||||
},
|
||||
"sub": {
|
||||
"info": 6,
|
||||
"type": "u8"
|
||||
},
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": 8,
|
||||
"type": "{\"cell\": {\"cell\": ([u8;32])}}",
|
||||
"name": "Value",
|
||||
"namespace": "ink_core::storage::value",
|
||||
"params": [
|
||||
{
|
||||
"info": 6,
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"sub": [
|
||||
{
|
||||
"info": 8,
|
||||
"type": "{\"cell\": ([u8;32])}",
|
||||
"name": "cell",
|
||||
"namespace": "ink_core::storage::cell::sync_cell",
|
||||
"params": [
|
||||
{
|
||||
"info": 6,
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"sub": [
|
||||
{
|
||||
"info": 9,
|
||||
"type": "([u8;32])",
|
||||
"name": "cell",
|
||||
"namespace": "ink_core::storage::key",
|
||||
"sub": [
|
||||
{
|
||||
"info": 11,
|
||||
"type": "[u8;32]",
|
||||
"ext": {
|
||||
"length": 32,
|
||||
"type": ""
|
||||
},
|
||||
"sub": {
|
||||
"info": 6,
|
||||
"type": "u8"
|
||||
},
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": 6,
|
||||
"type": "bool"
|
||||
},
|
||||
{
|
||||
"info": 8,
|
||||
"type": "{\"cell\": ([u8;32])}",
|
||||
"name": "SyncCell",
|
||||
"namespace": "ink_core::storage::cell::sync_cell",
|
||||
"params": [
|
||||
{
|
||||
"info": 6,
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"sub": [
|
||||
{
|
||||
"info": 9,
|
||||
"type": "([u8;32])",
|
||||
"name": "cell",
|
||||
"namespace": "ink_core::storage::key",
|
||||
"sub": [
|
||||
{
|
||||
"info": 11,
|
||||
"type": "[u8;32]",
|
||||
"ext": {
|
||||
"length": 32,
|
||||
"type": ""
|
||||
},
|
||||
"sub": {
|
||||
"info": 6,
|
||||
"type": "u8"
|
||||
},
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": 9,
|
||||
"type": "([u8;32])",
|
||||
"name": "Key",
|
||||
"namespace": "ink_core::storage::key",
|
||||
"sub": [
|
||||
{
|
||||
"info": 11,
|
||||
"type": "[u8;32]",
|
||||
"ext": {
|
||||
"length": 32,
|
||||
"type": ""
|
||||
},
|
||||
"sub": {
|
||||
"info": 6,
|
||||
"type": "u8"
|
||||
},
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": 11,
|
||||
"type": "[u8;32]",
|
||||
"ext": {
|
||||
"length": 32,
|
||||
"type": ""
|
||||
},
|
||||
"sub": {
|
||||
"info": 6,
|
||||
"type": "u8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"info": 6,
|
||||
"type": "u8"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,188 @@
|
||||
[
|
||||
{
|
||||
"info": 10,
|
||||
"type": "{ \"value\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }<u32>\"} }",
|
||||
"sub": [
|
||||
{
|
||||
"info": 10,
|
||||
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }",
|
||||
"sub": [
|
||||
{
|
||||
"info": 10,
|
||||
"type": "{ \"cell\": \"([u8;32])\"} }",
|
||||
"sub": [
|
||||
{
|
||||
"info": 11,
|
||||
"type": "([u8;32])",
|
||||
"sub": [
|
||||
{
|
||||
"info": 13,
|
||||
"type": "[u8;32]",
|
||||
"ext": {
|
||||
"length": 32,
|
||||
"type": "u8"
|
||||
},
|
||||
"sub": {
|
||||
"info": 7,
|
||||
"type": "u8"
|
||||
},
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
"name": "cell",
|
||||
"namespace": "ink_core::storage::key"
|
||||
}
|
||||
],
|
||||
"name": "cell",
|
||||
"namespace": "ink_core::storage::cell::sync_cell",
|
||||
"params": [
|
||||
{
|
||||
"info": 7,
|
||||
"type": "u32"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"name": "value",
|
||||
"namespace": "ink_core::storage::value",
|
||||
"params": [
|
||||
{
|
||||
"info": 7,
|
||||
"type": "u32"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"name": "Incrementer",
|
||||
"namespace": "incrementer::normal"
|
||||
},
|
||||
{
|
||||
"info": 10,
|
||||
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }",
|
||||
"sub": [
|
||||
{
|
||||
"info": 10,
|
||||
"type": "{ \"cell\": \"([u8;32])\"} }",
|
||||
"sub": [
|
||||
{
|
||||
"info": 11,
|
||||
"type": "([u8;32])",
|
||||
"sub": [
|
||||
{
|
||||
"info": 13,
|
||||
"type": "[u8;32]",
|
||||
"ext": {
|
||||
"length": 32,
|
||||
"type": "u8"
|
||||
},
|
||||
"sub": {
|
||||
"info": 7,
|
||||
"type": "u8"
|
||||
},
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
"name": "cell",
|
||||
"namespace": "ink_core::storage::key"
|
||||
}
|
||||
],
|
||||
"name": "cell",
|
||||
"namespace": "ink_core::storage::cell::sync_cell",
|
||||
"params": [
|
||||
{
|
||||
"info": 7,
|
||||
"type": "u32"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"name": "Value",
|
||||
"namespace": "ink_core::storage::value",
|
||||
"params": [
|
||||
{
|
||||
"info": 7,
|
||||
"type": "u32"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": 7,
|
||||
"type": "u32"
|
||||
},
|
||||
{
|
||||
"info": 10,
|
||||
"type": "{ \"cell\": \"([u8;32])\"} }",
|
||||
"sub": [
|
||||
{
|
||||
"info": 11,
|
||||
"type": "([u8;32])",
|
||||
"sub": [
|
||||
{
|
||||
"info": 13,
|
||||
"type": "[u8;32]",
|
||||
"ext": {
|
||||
"length": 32,
|
||||
"type": "u8"
|
||||
},
|
||||
"sub": {
|
||||
"info": 7,
|
||||
"type": "u8"
|
||||
},
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
"name": "cell",
|
||||
"namespace": "ink_core::storage::key"
|
||||
}
|
||||
],
|
||||
"name": "SyncCell",
|
||||
"namespace": "ink_core::storage::cell::sync_cell",
|
||||
"params": [
|
||||
{
|
||||
"info": 7,
|
||||
"type": "u32"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"info": 11,
|
||||
"type": "([u8;32])",
|
||||
"sub": [
|
||||
{
|
||||
"info": 13,
|
||||
"type": "[u8;32]",
|
||||
"ext": {
|
||||
"length": 32,
|
||||
"type": "u8"
|
||||
},
|
||||
"sub": {
|
||||
"info": 7,
|
||||
"type": "u8"
|
||||
},
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
"name": "Key",
|
||||
"namespace": "ink_core::storage::key"
|
||||
},
|
||||
{
|
||||
"info": 13,
|
||||
"type": "[u8;32]",
|
||||
"ext": {
|
||||
"length": 32,
|
||||
"type": "u8"
|
||||
},
|
||||
"sub": {
|
||||
"info": 7,
|
||||
"type": "u8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"info": 7,
|
||||
"type": "u8"
|
||||
},
|
||||
{
|
||||
"info": 7,
|
||||
"type": "bool"
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,201 @@
|
||||
{
|
||||
"registry": {
|
||||
"strings": [
|
||||
"Flipper",
|
||||
"flipper",
|
||||
"normal",
|
||||
"value",
|
||||
"Value",
|
||||
"ink_core",
|
||||
"storage",
|
||||
"cell",
|
||||
"SyncCell",
|
||||
"sync_cell",
|
||||
"Key",
|
||||
"key",
|
||||
"flip",
|
||||
"get"
|
||||
],
|
||||
"types": [
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 1,
|
||||
"custom.namespace": [
|
||||
2,
|
||||
3
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 4,
|
||||
"type": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 5,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
4
|
||||
],
|
||||
"custom.params": [
|
||||
3
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 8,
|
||||
"type": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "bool",
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 9,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
10
|
||||
],
|
||||
"custom.params": [
|
||||
3
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 8,
|
||||
"type": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 11,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
12
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"tuple_struct.types": [
|
||||
6
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"array.len": 32,
|
||||
"array.type": 7
|
||||
},
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": "u8",
|
||||
"def": "builtin"
|
||||
}
|
||||
]
|
||||
},
|
||||
"storage": {
|
||||
"struct.type": 1,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 4,
|
||||
"layout": {
|
||||
"struct.type": 2,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 8,
|
||||
"layout": {
|
||||
"range.offset": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"range.len": 1,
|
||||
"range.elem_type": 3
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"contract": {
|
||||
"name": 1,
|
||||
"deploy": {
|
||||
"args": [],
|
||||
"docs": [
|
||||
"Initializes our state to `false` upon deploying our smart contract."
|
||||
]
|
||||
},
|
||||
"messages": [
|
||||
{
|
||||
"name": 13,
|
||||
"selector": 970692492,
|
||||
"mutates": true,
|
||||
"args": [],
|
||||
"return_type": null,
|
||||
"docs": [
|
||||
"Flips the current state of our smart contract."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": 14,
|
||||
"selector": 4266279973,
|
||||
"mutates": false,
|
||||
"args": [],
|
||||
"return_type": 3,
|
||||
"docs": [
|
||||
"Returns the current state."
|
||||
]
|
||||
}
|
||||
],
|
||||
"events": [],
|
||||
"docs": []
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
{"name":"Incrementer","deploy":{"args":[{"name":"init_value","type":"u32"}]},"messages":[{"name":"inc","selector":257544423,"mutates":true,"args":[{"name":"by","type":"u32"}],"return_type":null},{"name":"get","selector":4266279973,"mutates":false,"args":[],"return_type":"u32"},{"name":"compare","selector":363906316,"mutates":false,"args":[{"name":"with","type":"u32"}],"return_type":"bool"}]}
|
||||
@@ -0,0 +1,935 @@
|
||||
{
|
||||
"registry": {
|
||||
"strings": [
|
||||
"SharedVec",
|
||||
"shared_vec",
|
||||
"normal",
|
||||
"mutators",
|
||||
"HashMap",
|
||||
"ink_core",
|
||||
"storage",
|
||||
"collections",
|
||||
"hash_map",
|
||||
"impls",
|
||||
"AccountId",
|
||||
"env",
|
||||
"srml",
|
||||
"types",
|
||||
"Access",
|
||||
"begin",
|
||||
"Option",
|
||||
"None",
|
||||
"Some",
|
||||
"end",
|
||||
"len",
|
||||
"Value",
|
||||
"value",
|
||||
"cell",
|
||||
"SyncCell",
|
||||
"sync_cell",
|
||||
"Key",
|
||||
"key",
|
||||
"entries",
|
||||
"SyncChunk",
|
||||
"chunk",
|
||||
"sync_chunk",
|
||||
"Entry",
|
||||
"Occupied",
|
||||
"OccupiedEntry",
|
||||
"val",
|
||||
"Removed",
|
||||
"cells_key",
|
||||
"vec",
|
||||
"Vec",
|
||||
"cells",
|
||||
"on_deploy",
|
||||
"push",
|
||||
"i32",
|
||||
"Result",
|
||||
"Ok",
|
||||
"Err",
|
||||
"register",
|
||||
"mutator",
|
||||
"set",
|
||||
"at",
|
||||
"u32",
|
||||
"to",
|
||||
"get",
|
||||
"Mutate",
|
||||
"Push",
|
||||
"Register"
|
||||
],
|
||||
"types": [
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 1,
|
||||
"custom.namespace": [
|
||||
2,
|
||||
3
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 4,
|
||||
"type": 2
|
||||
},
|
||||
{
|
||||
"name": 39,
|
||||
"type": 15
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 5,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10
|
||||
],
|
||||
"custom.params": [
|
||||
3,
|
||||
6
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 21,
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"name": 29,
|
||||
"type": 12
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 11,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
12,
|
||||
13,
|
||||
14
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"tuple_struct.types": [
|
||||
4
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"array.len": 32,
|
||||
"array.type": 5
|
||||
},
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": "u8",
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 15,
|
||||
"custom.namespace": [
|
||||
2
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 16,
|
||||
"type": 7
|
||||
},
|
||||
{
|
||||
"name": 20,
|
||||
"type": 7
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 17,
|
||||
"custom.namespace": [],
|
||||
"custom.params": [
|
||||
8
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"enum.variants": [
|
||||
{
|
||||
"unit_variant.name": 18
|
||||
},
|
||||
{
|
||||
"tuple_struct_variant.name": 19,
|
||||
"tuple_struct_variant.types": [
|
||||
8
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "u32",
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 22,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
23
|
||||
],
|
||||
"custom.params": [
|
||||
8
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 24,
|
||||
"type": 10
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 25,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
24,
|
||||
26
|
||||
],
|
||||
"custom.params": [
|
||||
8
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 24,
|
||||
"type": 11
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 27,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
28
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"tuple_struct.types": [
|
||||
4
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 30,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
31,
|
||||
32,
|
||||
31
|
||||
],
|
||||
"custom.params": [
|
||||
13
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 38,
|
||||
"type": 11
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 33,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10
|
||||
],
|
||||
"custom.params": [
|
||||
3,
|
||||
6
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"enum.variants": [
|
||||
{
|
||||
"tuple_struct_variant.name": 34,
|
||||
"tuple_struct_variant.types": [
|
||||
14
|
||||
]
|
||||
},
|
||||
{
|
||||
"unit_variant.name": 37
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 35,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10
|
||||
],
|
||||
"custom.params": [
|
||||
3,
|
||||
6
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 28,
|
||||
"type": 3
|
||||
},
|
||||
{
|
||||
"name": 36,
|
||||
"type": 6
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 40,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
39,
|
||||
10
|
||||
],
|
||||
"custom.params": [
|
||||
16
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 21,
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"name": 41,
|
||||
"type": 17
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "i32",
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 30,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
31,
|
||||
32,
|
||||
31
|
||||
],
|
||||
"custom.params": [
|
||||
16
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 38,
|
||||
"type": 11
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 45,
|
||||
"custom.namespace": [],
|
||||
"custom.params": [
|
||||
19,
|
||||
8
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"enum.variants": [
|
||||
{
|
||||
"tuple_struct_variant.name": 46,
|
||||
"tuple_struct_variant.types": [
|
||||
19
|
||||
]
|
||||
},
|
||||
{
|
||||
"tuple_struct_variant.name": 47,
|
||||
"tuple_struct_variant.types": [
|
||||
8
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": [],
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 45,
|
||||
"custom.namespace": [],
|
||||
"custom.params": [
|
||||
16,
|
||||
8
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"enum.variants": [
|
||||
{
|
||||
"tuple_struct_variant.name": 46,
|
||||
"tuple_struct_variant.types": [
|
||||
16
|
||||
]
|
||||
},
|
||||
{
|
||||
"tuple_struct_variant.name": 47,
|
||||
"tuple_struct_variant.types": [
|
||||
8
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 17,
|
||||
"custom.namespace": [],
|
||||
"custom.params": [
|
||||
16
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"enum.variants": [
|
||||
{
|
||||
"unit_variant.name": 18
|
||||
},
|
||||
{
|
||||
"tuple_struct_variant.name": 19,
|
||||
"tuple_struct_variant.types": [
|
||||
16
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"storage": {
|
||||
"struct.type": 1,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 4,
|
||||
"layout": {
|
||||
"struct.type": 2,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 21,
|
||||
"layout": {
|
||||
"struct.type": 9,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 24,
|
||||
"layout": {
|
||||
"range.offset": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"range.len": 1,
|
||||
"range.elem_type": 8
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 29,
|
||||
"layout": {
|
||||
"range.offset": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"range.len": 4294967295,
|
||||
"range.elem_type": 13
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 39,
|
||||
"layout": {
|
||||
"struct.type": 15,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 21,
|
||||
"layout": {
|
||||
"struct.type": 9,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 24,
|
||||
"layout": {
|
||||
"range.offset": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"range.len": 1,
|
||||
"range.elem_type": 8
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 41,
|
||||
"layout": {
|
||||
"range.offset": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"range.len": 4294967295,
|
||||
"range.elem_type": 16
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"contract": {
|
||||
"name": 1,
|
||||
"constructors": [
|
||||
{
|
||||
"name": 42,
|
||||
"selector": 0,
|
||||
"args": [],
|
||||
"docs": [
|
||||
"Initializes the value to the initial value."
|
||||
]
|
||||
}
|
||||
],
|
||||
"messages": [
|
||||
{
|
||||
"name": 43,
|
||||
"selector": 865577567,
|
||||
"mutates": true,
|
||||
"args": [
|
||||
{
|
||||
"name": 23,
|
||||
"type": {
|
||||
"ty": 16,
|
||||
"display_name": [
|
||||
44
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"return_type": {
|
||||
"ty": 18,
|
||||
"display_name": [
|
||||
45
|
||||
]
|
||||
},
|
||||
"docs": [
|
||||
"Pushes a new value to the shared vector.",
|
||||
"",
|
||||
"# Errors",
|
||||
"",
|
||||
"- If the caller does not have unlimited access rights."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": 48,
|
||||
"selector": 572030971,
|
||||
"mutates": true,
|
||||
"args": [
|
||||
{
|
||||
"name": 49,
|
||||
"type": {
|
||||
"ty": 3,
|
||||
"display_name": [
|
||||
11
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 16,
|
||||
"type": {
|
||||
"ty": 7,
|
||||
"display_name": [
|
||||
17
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 20,
|
||||
"type": {
|
||||
"ty": 7,
|
||||
"display_name": [
|
||||
17
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"return_type": {
|
||||
"ty": 18,
|
||||
"display_name": [
|
||||
45
|
||||
]
|
||||
},
|
||||
"docs": [
|
||||
"Registers a new user with the given access rights.",
|
||||
"",
|
||||
"Can also be used to change access rights of an already existing user.",
|
||||
"",
|
||||
"# Errors",
|
||||
"",
|
||||
"- If the caller does not have unlimited access rights."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": 50,
|
||||
"selector": 2028185770,
|
||||
"mutates": true,
|
||||
"args": [
|
||||
{
|
||||
"name": 51,
|
||||
"type": {
|
||||
"ty": 8,
|
||||
"display_name": [
|
||||
52
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 53,
|
||||
"type": {
|
||||
"ty": 16,
|
||||
"display_name": [
|
||||
44
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"return_type": {
|
||||
"ty": 20,
|
||||
"display_name": [
|
||||
45
|
||||
]
|
||||
},
|
||||
"docs": [
|
||||
"Sets the value at the given position to the given value.",
|
||||
"",
|
||||
"Returns the previous value.",
|
||||
"",
|
||||
"# Errors",
|
||||
"",
|
||||
"- If the given position is out of bounds.",
|
||||
"- If the caller does not have the required access rights."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": 54,
|
||||
"selector": 4266279973,
|
||||
"mutates": false,
|
||||
"args": [
|
||||
{
|
||||
"name": 51,
|
||||
"type": {
|
||||
"ty": 8,
|
||||
"display_name": [
|
||||
52
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"return_type": {
|
||||
"ty": 21,
|
||||
"display_name": [
|
||||
17
|
||||
]
|
||||
},
|
||||
"docs": [
|
||||
"Returns the value of the shared vector at the given position",
|
||||
"or `None` if the access is out of bounds."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": 21,
|
||||
"selector": 1403873684,
|
||||
"mutates": false,
|
||||
"args": [],
|
||||
"return_type": {
|
||||
"ty": 8,
|
||||
"display_name": [
|
||||
52
|
||||
]
|
||||
},
|
||||
"docs": [
|
||||
"Returns the length of the shared vector."
|
||||
]
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"name": 55,
|
||||
"args": [
|
||||
{
|
||||
"name": 51,
|
||||
"indexed": false,
|
||||
"type": {
|
||||
"ty": 8,
|
||||
"display_name": [
|
||||
52
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 23,
|
||||
"indexed": false,
|
||||
"type": {
|
||||
"ty": 16,
|
||||
"display_name": [
|
||||
44
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"docs": [
|
||||
"Fires whenever a mutator changes the vector."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": 56,
|
||||
"args": [
|
||||
{
|
||||
"name": 49,
|
||||
"indexed": false,
|
||||
"type": {
|
||||
"ty": 3,
|
||||
"display_name": [
|
||||
11
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 23,
|
||||
"indexed": false,
|
||||
"type": {
|
||||
"ty": 16,
|
||||
"display_name": [
|
||||
44
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"docs": [
|
||||
"Fires whenever a mutator pushes the vector successfully."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": 57,
|
||||
"args": [
|
||||
{
|
||||
"name": 49,
|
||||
"indexed": false,
|
||||
"type": {
|
||||
"ty": 3,
|
||||
"display_name": [
|
||||
11
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 16,
|
||||
"indexed": false,
|
||||
"type": {
|
||||
"ty": 7,
|
||||
"display_name": [
|
||||
17
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 20,
|
||||
"indexed": false,
|
||||
"type": {
|
||||
"ty": 7,
|
||||
"display_name": [
|
||||
17
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"docs": [
|
||||
"Fires whenever a new mutator is registered",
|
||||
"or when a mutators access rights are changed."
|
||||
]
|
||||
}
|
||||
],
|
||||
"docs": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,697 @@
|
||||
{
|
||||
"registry": {
|
||||
"strings": [
|
||||
"RustStructures",
|
||||
"structures",
|
||||
"normal",
|
||||
"my_tuple_struct",
|
||||
"Value",
|
||||
"ink_core",
|
||||
"storage",
|
||||
"value",
|
||||
"TupleStruct",
|
||||
"cell",
|
||||
"SyncCell",
|
||||
"sync_cell",
|
||||
"Key",
|
||||
"key",
|
||||
"my_struct",
|
||||
"Struct",
|
||||
"first",
|
||||
"seconds",
|
||||
"my_clike_enum",
|
||||
"ClikeEnum",
|
||||
"FirstVariant",
|
||||
"SecondVariant",
|
||||
"ThirdVariant",
|
||||
"my_enum",
|
||||
"RustEnum",
|
||||
"NoData",
|
||||
"TupleVariant",
|
||||
"StructVariant",
|
||||
"second",
|
||||
"my_union",
|
||||
"Union"
|
||||
],
|
||||
"types": [
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 1,
|
||||
"custom.namespace": [
|
||||
2,
|
||||
3
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 4,
|
||||
"type": 2
|
||||
},
|
||||
{
|
||||
"name": 15,
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"name": 19,
|
||||
"type": 12
|
||||
},
|
||||
{
|
||||
"name": 24,
|
||||
"type": 15
|
||||
},
|
||||
{
|
||||
"name": 30,
|
||||
"type": 18
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 5,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
8
|
||||
],
|
||||
"custom.params": [
|
||||
3
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"type": 6
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 9,
|
||||
"custom.namespace": [
|
||||
2
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"tuple_struct.types": [
|
||||
4,
|
||||
5
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "u8",
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": "u16",
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 11,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
10,
|
||||
12
|
||||
],
|
||||
"custom.params": [
|
||||
3
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"type": 7
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 13,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
14
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"tuple_struct.types": [
|
||||
8
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"array.len": 32,
|
||||
"array.type": 4
|
||||
},
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 5,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
8
|
||||
],
|
||||
"custom.params": [
|
||||
10
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"type": 11
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 16,
|
||||
"custom.namespace": [
|
||||
2
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 17,
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"name": 18,
|
||||
"type": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 11,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
10,
|
||||
12
|
||||
],
|
||||
"custom.params": [
|
||||
10
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"type": 7
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 5,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
8
|
||||
],
|
||||
"custom.params": [
|
||||
13
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"type": 14
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 20,
|
||||
"custom.namespace": [
|
||||
2
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"clike_enum.variants": [
|
||||
{
|
||||
"name": 21,
|
||||
"discriminant": 0
|
||||
},
|
||||
{
|
||||
"name": 22,
|
||||
"discriminant": 1
|
||||
},
|
||||
{
|
||||
"name": 23,
|
||||
"discriminant": 42
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 11,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
10,
|
||||
12
|
||||
],
|
||||
"custom.params": [
|
||||
13
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"type": 7
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 5,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
8
|
||||
],
|
||||
"custom.params": [
|
||||
16
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"type": 17
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 25,
|
||||
"custom.namespace": [
|
||||
2
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"enum.variants": [
|
||||
{
|
||||
"unit_variant.name": 26
|
||||
},
|
||||
{
|
||||
"tuple_struct_variant.name": 27,
|
||||
"tuple_struct_variant.types": [
|
||||
4,
|
||||
5
|
||||
]
|
||||
},
|
||||
{
|
||||
"struct_variant.name": 28,
|
||||
"struct_variant.fields": [
|
||||
{
|
||||
"name": 17,
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"name": 29,
|
||||
"type": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 11,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
10,
|
||||
12
|
||||
],
|
||||
"custom.params": [
|
||||
16
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"type": 7
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 5,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
8
|
||||
],
|
||||
"custom.params": [
|
||||
19
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"type": 20
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 31,
|
||||
"custom.namespace": [
|
||||
2
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"union.fields": [
|
||||
{
|
||||
"name": 17,
|
||||
"type": 4
|
||||
},
|
||||
{
|
||||
"name": 29,
|
||||
"type": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 11,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
10,
|
||||
12
|
||||
],
|
||||
"custom.params": [
|
||||
19
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"type": 7
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"storage": {
|
||||
"struct.type": 1,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 4,
|
||||
"layout": {
|
||||
"struct.type": 2,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"layout": {
|
||||
"range.offset": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"range.len": 1,
|
||||
"range.elem_type": 3
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 15,
|
||||
"layout": {
|
||||
"struct.type": 9,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"layout": {
|
||||
"range.offset": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"range.len": 1,
|
||||
"range.elem_type": 10
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 19,
|
||||
"layout": {
|
||||
"struct.type": 12,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"layout": {
|
||||
"range.offset": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
"range.len": 1,
|
||||
"range.elem_type": 13
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 24,
|
||||
"layout": {
|
||||
"struct.type": 15,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"layout": {
|
||||
"range.offset": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
3
|
||||
],
|
||||
"range.len": 1,
|
||||
"range.elem_type": 16
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": 30,
|
||||
"layout": {
|
||||
"struct.type": 18,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 10,
|
||||
"layout": {
|
||||
"range.offset": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4
|
||||
],
|
||||
"range.len": 1,
|
||||
"range.elem_type": 19
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"contract": {
|
||||
"name": 1,
|
||||
"deploy": {
|
||||
"args": [],
|
||||
"docs": []
|
||||
},
|
||||
"messages": [],
|
||||
"events": [],
|
||||
"docs": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
{
|
||||
"registry": {
|
||||
"strings": [
|
||||
"Incrementer",
|
||||
"incrementer",
|
||||
"normal",
|
||||
"value",
|
||||
"Value",
|
||||
"ink_core",
|
||||
"storage",
|
||||
"cell",
|
||||
"SyncCell",
|
||||
"sync_cell",
|
||||
"Key",
|
||||
"key",
|
||||
"on_deploy",
|
||||
"init_value",
|
||||
"u32",
|
||||
"inc",
|
||||
"by",
|
||||
"get",
|
||||
"compare",
|
||||
"with",
|
||||
"bool"
|
||||
],
|
||||
"types": [
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 1,
|
||||
"custom.namespace": [
|
||||
2,
|
||||
3
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 4,
|
||||
"type": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 5,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
4
|
||||
],
|
||||
"custom.params": [
|
||||
3
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 8,
|
||||
"type": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "u32",
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 9,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
10
|
||||
],
|
||||
"custom.params": [
|
||||
3
|
||||
]
|
||||
},
|
||||
"def": {
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 8,
|
||||
"type": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"custom.name": 11,
|
||||
"custom.namespace": [
|
||||
6,
|
||||
7,
|
||||
12
|
||||
],
|
||||
"custom.params": []
|
||||
},
|
||||
"def": {
|
||||
"tuple_struct.types": [
|
||||
6
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": {
|
||||
"array.len": 32,
|
||||
"array.type": 7
|
||||
},
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": "u8",
|
||||
"def": "builtin"
|
||||
},
|
||||
{
|
||||
"id": "bool",
|
||||
"def": "builtin"
|
||||
}
|
||||
]
|
||||
},
|
||||
"storage": {
|
||||
"struct.type": 1,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 4,
|
||||
"layout": {
|
||||
"struct.type": 2,
|
||||
"struct.fields": [
|
||||
{
|
||||
"name": 8,
|
||||
"layout": {
|
||||
"range.offset": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"range.len": 1,
|
||||
"range.elem_type": 3
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"contract": {
|
||||
"name": 1,
|
||||
"constructors": [
|
||||
{
|
||||
"name": 13,
|
||||
"selector": "[\"0x00\",\"0x00\",\"0x00\",\"0x00\"]",
|
||||
"args": [
|
||||
{
|
||||
"name": 14,
|
||||
"type": {
|
||||
"ty": 3,
|
||||
"display_name": [
|
||||
15
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"docs": [
|
||||
"Initializes the value to the initial value."
|
||||
]
|
||||
}
|
||||
],
|
||||
"messages": [
|
||||
{
|
||||
"name": 16,
|
||||
"selector": "[\"0x0F\",\"0x59\",\"0xD0\",\"0xE7\"]",
|
||||
"mutates": true,
|
||||
"args": [
|
||||
{
|
||||
"name": 17,
|
||||
"type": {
|
||||
"ty": 3,
|
||||
"display_name": [
|
||||
15
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"return_type": null,
|
||||
"docs": [
|
||||
"Flips the current state of our smart contract."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": 18,
|
||||
"selector": "[\"0xFE\",\"0x4A\",\"0x44\",\"0x25\"]",
|
||||
"mutates": false,
|
||||
"args": [],
|
||||
"return_type": {
|
||||
"ty": 3,
|
||||
"display_name": [
|
||||
15
|
||||
]
|
||||
},
|
||||
"docs": [
|
||||
"Returns the current state."
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": 19,
|
||||
"selector": "[\"0x15\",\"0xB0\",\"0xC5\",\"0x0C\"]",
|
||||
"mutates": false,
|
||||
"args": [
|
||||
{
|
||||
"name": 20,
|
||||
"type": {
|
||||
"ty": 3,
|
||||
"display_name": [
|
||||
15
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"return_type": {
|
||||
"ty": 8,
|
||||
"display_name": [
|
||||
21
|
||||
]
|
||||
},
|
||||
"docs": [
|
||||
"Returns `true` if the internal value is greater than or equal to the provided value."
|
||||
]
|
||||
}
|
||||
],
|
||||
"events": [],
|
||||
"docs": []
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/api-derive",
|
||||
"version": "0.94.1",
|
||||
"version": "0.100.1",
|
||||
"description": "Common functions used across Polkadot, derived from RPC calls and storage queries.",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
@@ -27,11 +27,11 @@
|
||||
},
|
||||
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.6.2",
|
||||
"@polkadot/api": "^0.94.1",
|
||||
"@polkadot/types": "^0.94.1"
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@polkadot/api": "^0.100.1",
|
||||
"@polkadot/types": "^0.100.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/keyring": "^1.5.1"
|
||||
"@polkadot/keyring": "^1.8.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,45 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces';
|
||||
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map, startWith } from 'rxjs/operators';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { createType } from '@polkadot/types';
|
||||
import { isU8a } from '@polkadot/util';
|
||||
import { decodeAddress } from '@polkadot/util-crypto';
|
||||
import { createType } from '@polkadot/types';
|
||||
import { idToIndex } from './idToIndex';
|
||||
import { indexToId } from './indexToId';
|
||||
import { drr } from '../util/drr';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
export type AccountIdAndIndex = [AccountId?, AccountIndex?];
|
||||
|
||||
function retrieve (api: ApiInterfaceRx, address: Address | AccountId | AccountIndex | string | null | undefined): Observable<AccountIdAndIndex> {
|
||||
try {
|
||||
// yes, this can fail, don't care too much, catch will catch it
|
||||
const decoded = isU8a(address)
|
||||
? address
|
||||
: decodeAddress((address || '').toString());
|
||||
|
||||
if (decoded.length === 32) {
|
||||
const accountId = createType(api.registry, 'AccountId', decoded);
|
||||
|
||||
return api.derive.accounts.idToIndex(accountId).pipe(
|
||||
map((accountIndex): AccountIdAndIndex => [accountId, accountIndex] as AccountIdAndIndex)
|
||||
);
|
||||
}
|
||||
|
||||
const accountIndex = createType(api.registry, 'AccountIndex', decoded);
|
||||
|
||||
return api.derive.accounts.indexToId(accountIndex).pipe(
|
||||
map((accountId): AccountIdAndIndex => [accountId, accountIndex] as AccountIdAndIndex)
|
||||
);
|
||||
} catch (error) {
|
||||
return of([undefined, undefined] as AccountIdAndIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name idAndIndex
|
||||
* @param {(Address | AccountId | AccountIndex | string | null)} address - An accounts address in various formats.
|
||||
@@ -30,32 +54,6 @@ export type AccountIdAndIndex = [AccountId?, AccountIndex?];
|
||||
* ```
|
||||
*/
|
||||
export function idAndIndex (api: ApiInterfaceRx): (address?: Address | AccountId | AccountIndex | string | null) => Observable<AccountIdAndIndex> {
|
||||
return (address?: Address | AccountId | AccountIndex | string | null): Observable<AccountIdAndIndex> => {
|
||||
try {
|
||||
// yes, this can fail, don't care too much, catch will catch it
|
||||
const decoded = isU8a(address)
|
||||
? address
|
||||
: decodeAddress((address || '').toString());
|
||||
|
||||
if (decoded.length === 32) {
|
||||
const accountId = createType('AccountId', decoded);
|
||||
|
||||
return idToIndex(api)(accountId).pipe(
|
||||
startWith(undefined),
|
||||
map((accountIndex): AccountIdAndIndex => [accountId, accountIndex] as AccountIdAndIndex),
|
||||
drr()
|
||||
);
|
||||
}
|
||||
|
||||
const accountIndex = createType('AccountIndex', decoded);
|
||||
|
||||
return indexToId(api)(accountIndex).pipe(
|
||||
startWith(undefined),
|
||||
map((accountId): AccountIdAndIndex => [accountId, accountIndex] as AccountIdAndIndex),
|
||||
drr()
|
||||
);
|
||||
} catch (error) {
|
||||
return of([undefined, undefined] as AccountIdAndIndex).pipe(drr());
|
||||
}
|
||||
};
|
||||
return memo((address?: Address | AccountId | AccountIndex | string | null): Observable<AccountIdAndIndex> =>
|
||||
retrieve(api, address));
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, AccountIndex } from '@polkadot/types/interfaces';
|
||||
import { AccountIndexes } from '../types';
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import { map, startWith } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
|
||||
import { indexes, AccountIndexes } from './indexes';
|
||||
import { drr } from '../util/drr';
|
||||
import { memo } from '../util';
|
||||
|
||||
/**
|
||||
* @name idToIndex
|
||||
@@ -26,13 +26,11 @@ import { drr } from '../util/drr';
|
||||
* ```
|
||||
*/
|
||||
export function idToIndex (api: ApiInterfaceRx): (accountId: AccountId | string) => Observable<AccountIndex | undefined> {
|
||||
return (accountId: AccountId | string): Observable<AccountIndex | undefined> =>
|
||||
indexes(api)()
|
||||
.pipe(
|
||||
startWith({}),
|
||||
map((indexes: AccountIndexes): AccountIndex | undefined =>
|
||||
(indexes || {})[accountId.toString()]
|
||||
),
|
||||
drr()
|
||||
);
|
||||
return memo((accountId: AccountId | string): Observable<AccountIndex | undefined> =>
|
||||
api.derive.accounts.indexes().pipe(
|
||||
startWith({}),
|
||||
map((indexes: AccountIndexes): AccountIndex | undefined =>
|
||||
(indexes || {})[accountId.toString()]
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
@@ -6,3 +6,4 @@ export * from './idAndIndex';
|
||||
export * from './idToIndex';
|
||||
export * from './indexToId';
|
||||
export * from './indexes';
|
||||
export * from './info';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
@@ -8,9 +8,9 @@ import { Observable } from 'rxjs';
|
||||
import { map, startWith } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { ENUMSET_SIZE } from '@polkadot/types/primitive/Generic/AccountIndex';
|
||||
import { createType, ClassOf, Vec } from '@polkadot/types';
|
||||
import { ClassOf, Vec, createType } from '@polkadot/types';
|
||||
|
||||
import { drr } from '../util/drr';
|
||||
import { memo } from '../util';
|
||||
|
||||
/**
|
||||
* @name indexToId
|
||||
@@ -26,19 +26,18 @@ import { drr } from '../util/drr';
|
||||
* ```
|
||||
*/
|
||||
export function indexToId (api: ApiInterfaceRx): (accountIndex: AccountIndex | string) => Observable<AccountId | undefined> {
|
||||
return (_accountIndex: AccountIndex | string): Observable<AccountId | undefined> => {
|
||||
const querySection = api.query.indices || api.query.balances;
|
||||
const accountIndex = _accountIndex instanceof ClassOf('AccountIndex')
|
||||
? _accountIndex
|
||||
: createType('AccountIndex', _accountIndex);
|
||||
const querySection = api.query.indices || api.query.balances;
|
||||
|
||||
return (querySection.enumSet<Vec<AccountId>>(accountIndex.div(ENUMSET_SIZE)))
|
||||
.pipe(
|
||||
startWith([]),
|
||||
map((accounts): AccountId | undefined =>
|
||||
(accounts || [])[accountIndex.mod(ENUMSET_SIZE).toNumber()]
|
||||
),
|
||||
drr()
|
||||
);
|
||||
};
|
||||
return memo((_accountIndex: AccountIndex | string): Observable<AccountId | undefined> => {
|
||||
const accountIndex = _accountIndex instanceof ClassOf(api.registry, 'AccountIndex')
|
||||
? _accountIndex
|
||||
: createType(api.registry, 'AccountIndex', _accountIndex);
|
||||
|
||||
return querySection.enumSet<Vec<AccountId>>(accountIndex.div(ENUMSET_SIZE)).pipe(
|
||||
startWith([]),
|
||||
map((accounts): AccountId | undefined =>
|
||||
(accounts || [])[accountIndex.mod(ENUMSET_SIZE).toNumber()]
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { AccountId, AccountIndex } from '@polkadot/types/interfaces';
|
||||
import { AccountIndexes } from '../types';
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { ENUMSET_SIZE } from '@polkadot/types/primitive/Generic/AccountIndex';
|
||||
import { createType } from '@polkadot/types';
|
||||
import { Vec, createType } from '@polkadot/types';
|
||||
|
||||
import { drr } from '../util/drr';
|
||||
|
||||
export type AccountIndexes = Record<string, AccountIndex>;
|
||||
import { memo } from '../util';
|
||||
|
||||
const enumsetSize = ENUMSET_SIZE.toNumber();
|
||||
|
||||
@@ -32,29 +31,26 @@ const enumsetSize = ENUMSET_SIZE.toNumber();
|
||||
* ```
|
||||
*/
|
||||
export function indexes (api: ApiInterfaceRx): () => Observable<AccountIndexes> {
|
||||
return (): Observable<AccountIndexes> => {
|
||||
return (api.query.indices.nextEnumSet<AccountIndex>())
|
||||
.pipe(
|
||||
// use the nextEnumSet (which is a counter of the number of sets) to construct
|
||||
// a range of values to query [0, 1, 2, ...]. Retrieve the full enum set for the
|
||||
// specific index - each query can return up to ENUMSET_SIZE (64) records, each
|
||||
// containing an AccountId
|
||||
switchMap((next: AccountIndex): Observable<any> =>
|
||||
api.query.indices.enumSet.multi([...Array(next.toNumber() + 1).keys()]) as Observable<any>
|
||||
),
|
||||
map((all: (AccountId[] | undefined)[]): AccountIndexes =>
|
||||
(all || []).reduce((result, list, outerIndex): AccountIndexes => {
|
||||
(list || []).forEach((accountId, innerIndex): void => {
|
||||
// re-create the index based on position 0 is [0][0] and likewise
|
||||
// 64 (0..63 in first) is [1][0] (the first index value in set 2)
|
||||
const index = (outerIndex * enumsetSize) + innerIndex;
|
||||
return memo((): Observable<AccountIndexes> =>
|
||||
api.query.indices.nextEnumSet<AccountIndex>().pipe(
|
||||
// use the nextEnumSet (which is a counter of the number of sets) to construct
|
||||
// a range of values to query [0, 1, 2, ...]. Retrieve the full enum set for the
|
||||
// specific index - each query can return up to ENUMSET_SIZE (64) records, each
|
||||
// containing an AccountId
|
||||
switchMap((next: AccountIndex): Observable<Vec<AccountId>[]> =>
|
||||
api.query.indices.enumSet.multi<Vec<AccountId>>([...Array(next.toNumber() + 1).keys()])
|
||||
),
|
||||
map((all: AccountId[][]): AccountIndexes =>
|
||||
all.reduce((result: AccountIndexes, list, outerIndex): AccountIndexes => {
|
||||
(list || []).forEach((accountId, innerIndex): void => {
|
||||
// re-create the index based on position 0 is [0][0] and likewise
|
||||
// 64 (0..63 in first) is [1][0] (the first index value in set 2)
|
||||
const index = (outerIndex * enumsetSize) + innerIndex;
|
||||
|
||||
result[accountId.toString()] = createType('AccountIndex', index);
|
||||
});
|
||||
result[accountId.toString()] = createType(api.registry, 'AccountIndex', index);
|
||||
});
|
||||
|
||||
return result;
|
||||
}, {} as AccountIndexes)),
|
||||
drr()
|
||||
);
|
||||
};
|
||||
return result;
|
||||
}, {}))
|
||||
));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { AccountId, AccountIndex, Address, Balance, Registration } from '@polkadot/types/interfaces';
|
||||
import { ITuple } from '@polkadot/types/types';
|
||||
import { DeriveAccountInfo, DeriveAccountRegistration } from '../types';
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { Bytes, Data, Option, u32 } from '@polkadot/types';
|
||||
import { u8aToString } from '@polkadot/util';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
function dataAsString (data: Data): string | undefined {
|
||||
return data.isRaw
|
||||
? u8aToString(data.asRaw.toU8a(true))
|
||||
: data.isSha256
|
||||
? data.asSha256.toHex()
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function retrieveNick (api: ApiInterfaceRx, accountId?: AccountId): Observable<string | undefined> {
|
||||
return ((
|
||||
accountId && api.query.nicks?.nameOf
|
||||
? api.query.nicks.nameOf<Option<ITuple<[Bytes, Balance]>>>(accountId)
|
||||
: of(undefined)
|
||||
) as Observable<Option<ITuple<[Bytes, Balance]>> | undefined>).pipe(
|
||||
map((nameOf): string | undefined =>
|
||||
nameOf?.isSome
|
||||
? u8aToString(nameOf.unwrap()[0]).substr(0, (api.consts.nicks.maxLength as u32).toNumber())
|
||||
: undefined
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function extractIdentity (identityOfOpt?: Option<Registration>, superOf?: [AccountId, Data]): DeriveAccountRegistration {
|
||||
if (!identityOfOpt?.isSome) {
|
||||
return { judgements: [] };
|
||||
}
|
||||
|
||||
const { info, judgements } = identityOfOpt.unwrap();
|
||||
const topDisplay = dataAsString(info.display);
|
||||
|
||||
return {
|
||||
display: superOf
|
||||
? dataAsString(superOf[1]) || topDisplay
|
||||
: topDisplay,
|
||||
displayParent: superOf
|
||||
? topDisplay
|
||||
: undefined,
|
||||
email: dataAsString(info.email),
|
||||
image: dataAsString(info.image),
|
||||
legal: dataAsString(info.legal),
|
||||
parent: superOf
|
||||
? superOf[0]
|
||||
: undefined,
|
||||
pgp: info.pgpFingerprint.isSome
|
||||
? info.pgpFingerprint.unwrap().toHex()
|
||||
: undefined,
|
||||
riot: dataAsString(info.riot),
|
||||
twitter: dataAsString(info.twitter),
|
||||
web: dataAsString(info.web),
|
||||
judgements
|
||||
};
|
||||
}
|
||||
|
||||
function retrieveIdentity (api: ApiInterfaceRx, accountId?: AccountId): Observable<DeriveAccountRegistration> {
|
||||
return ((
|
||||
accountId && api.query.identity?.identityOf
|
||||
? api.queryMulti([
|
||||
[api.query.identity.identityOf, accountId],
|
||||
[api.query.identity.superOf, accountId]
|
||||
])
|
||||
: of([undefined, undefined])
|
||||
) as Observable<[Option<Registration> | undefined, Option<ITuple<[AccountId, Data]>> | undefined]>).pipe(
|
||||
switchMap(([identityOfOpt, superOfOpt]): Observable<[Option<Registration> | undefined, [AccountId, Data] | undefined]> => {
|
||||
if (identityOfOpt?.isSome) {
|
||||
// this identity has something set
|
||||
return of([identityOfOpt, undefined]);
|
||||
} else if (superOfOpt?.isSome) {
|
||||
const superOf = superOfOpt.unwrap();
|
||||
|
||||
// we have a super
|
||||
return combineLatest([
|
||||
api.query.identity.identityOf<Option<Registration>>(superOf[0]),
|
||||
of(superOf)
|
||||
]);
|
||||
}
|
||||
|
||||
// nothing of value returned
|
||||
return of([undefined, undefined]);
|
||||
}),
|
||||
map(([identityOfOpt, superOf]): DeriveAccountRegistration =>
|
||||
extractIdentity(identityOfOpt, superOf)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name info
|
||||
* @description Returns aux. info with regards to an account, current that includes the accountId, accountIndex and nickname
|
||||
*/
|
||||
export function info (api: ApiInterfaceRx): (address?: AccountIndex | AccountId | Address | string | null) => Observable<DeriveAccountInfo> {
|
||||
return memo((address?: AccountIndex | AccountId | Address | string | null): Observable<DeriveAccountInfo> =>
|
||||
api.derive.accounts.idAndIndex(address).pipe(
|
||||
switchMap(([accountId, accountIndex]): Observable<[Partial<DeriveAccountInfo>, DeriveAccountRegistration, string?]> =>
|
||||
combineLatest([
|
||||
of({ accountId, accountIndex }),
|
||||
retrieveIdentity(api, accountId),
|
||||
retrieveNick(api, accountId)
|
||||
])
|
||||
),
|
||||
map(([{ accountId, accountIndex }, identity, nickname]): DeriveAccountInfo => ({
|
||||
accountId, accountIndex, identity, nickname
|
||||
}))
|
||||
));
|
||||
}
|
||||
@@ -1,98 +1,112 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, AccountIndex, Address, Balance, BalanceLock, BlockNumber, Index, VestingSchedule } from '@polkadot/types/interfaces';
|
||||
import { DerivedBalances } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { combineLatest, of, Observable } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { ClassOf, Option, createType } from '@polkadot/types';
|
||||
import { Option, Vec, createType } from '@polkadot/types';
|
||||
import { bnMax } from '@polkadot/util';
|
||||
|
||||
import { idAndIndex } from '../accounts/idAndIndex';
|
||||
import { bestNumber } from '../chain/bestNumber';
|
||||
import { DerivedBalances } from '../types';
|
||||
import { drr } from '../util/drr';
|
||||
import { memo } from '../util';
|
||||
|
||||
type Result = [AccountId | undefined, BlockNumber | undefined, [Balance?, Balance?, BalanceLock[]?, Option<VestingSchedule>?, Index?]];
|
||||
type ResultBalance = [Balance, Balance, BalanceLock[], Option<VestingSchedule>];
|
||||
type Result = [AccountId, BlockNumber, ResultBalance, Index];
|
||||
|
||||
function calcBalances ([accountId = createType('AccountId'), bestNumber = createType('Balance'), [freeBalance = createType('Balance'), reservedBalance = createType('Balance'), locks = [], vesting = new Option<VestingSchedule>(ClassOf('VestingSchedule'), null), accountNonce = createType('Balance')]]: Result): DerivedBalances {
|
||||
let lockedBalance = createType('Balance');
|
||||
function calcBalances (api: ApiInterfaceRx, [accountId, bestNumber, [freeBalance, reservedBalance, locks, vesting], accountNonce]: Result): DerivedBalances {
|
||||
let lockedBalance = createType(api.registry, 'Balance');
|
||||
let lockedBreakdown: BalanceLock[] = [];
|
||||
|
||||
if (Array.isArray(locks)) {
|
||||
// only get the locks that are valid until passed the current block
|
||||
const totals = locks.filter((value): boolean => bestNumber && value.until.gt(bestNumber));
|
||||
lockedBreakdown = locks.filter(({ until }): boolean => bestNumber && until.gt(bestNumber));
|
||||
|
||||
// get the maximum of the locks according to https://github.com/paritytech/substrate/blob/master/srml/balances/src/lib.rs#L699
|
||||
lockedBalance = totals[0]
|
||||
? bnMax(...totals.map(({ amount }): Balance => amount)) as Balance
|
||||
: createType('Balance');
|
||||
if (lockedBreakdown.length) {
|
||||
lockedBalance = createType(api.registry, 'Balance', bnMax(...lockedBreakdown.map(({ amount }): Balance => amount)));
|
||||
}
|
||||
}
|
||||
|
||||
// offset = balance locked at genesis, perBlock is the unlock amount
|
||||
const { offset, perBlock } = vesting.unwrapOr(createType('VestingSchedule'));
|
||||
const vestedNow: BN = perBlock.mul(bestNumber);
|
||||
const vestedBalance: BN = vestedNow.gt(offset)
|
||||
? freeBalance
|
||||
: freeBalance.sub(offset).add(vestedNow);
|
||||
// Calculate the vesting balances,
|
||||
// - offset = balance locked at genesis,
|
||||
// - perBlock is the unlock amount
|
||||
const { offset: vestingTotal, perBlock } = vesting.unwrapOr(createType(api.registry, 'VestingSchedule'));
|
||||
const vestedBalance = createType(api.registry, 'Balance', perBlock.mul(bestNumber));
|
||||
const isVesting = vestedBalance.lt(vestingTotal);
|
||||
|
||||
// NOTE Workaround for this account on Alex (one of a couple reported) -
|
||||
// 5F7BJL6Z4m8RLtK7nXEqqpEqhBbd535Z3CZeYF6ccvaQAY6N
|
||||
// The locked is > the vested and ended up with the locked > free,
|
||||
// i.e. related to https://github.com/paritytech/polkadot/issues/225
|
||||
// (most probably due to movements from stash -> controller -> free)
|
||||
const availableBalance: BN = bnMax(createType('Balance'), vestedBalance.sub(lockedBalance));
|
||||
// The available balance & vested has an interplay here
|
||||
// "
|
||||
// vesting is a guarantee that the account's balance will never go below a certain amount. so it functions in the opposite way, a bit like a lock that is monotonically decreasing rather than a liquid amount that is monotonically increasing.
|
||||
// locks function as the same guarantee - that a balance will not be lower than a particular amount.
|
||||
// because of this you can see that if there is a "vesting lock" that guarantees the balance cannot go below 200, and a "staking lock" that guarantees the balance cannot drop below 300, then we just have two guarantees of which the first is irrelevant.
|
||||
// i.e. (balance >= 200 && balance >= 300) == (balance >= 300)
|
||||
// ""
|
||||
const floating = freeBalance.sub(lockedBalance);
|
||||
const extraReceived = isVesting ? freeBalance.sub(vestingTotal) : new BN(0);
|
||||
const availableBalance = createType(api.registry, 'Balance', bnMax(new BN(0), isVesting && floating.gt(vestedBalance) ? vestedBalance.add(extraReceived) : floating));
|
||||
|
||||
return {
|
||||
accountId,
|
||||
accountNonce,
|
||||
availableBalance,
|
||||
freeBalance,
|
||||
isVesting,
|
||||
lockedBalance,
|
||||
lockedBreakdown,
|
||||
reservedBalance,
|
||||
vestedBalance,
|
||||
votingBalance: freeBalance.add(reservedBalance)
|
||||
} as DerivedBalances;
|
||||
vestingTotal,
|
||||
votingBalance: createType(api.registry, 'Balance', freeBalance.add(reservedBalance))
|
||||
};
|
||||
}
|
||||
|
||||
function queryBalances (api: ApiInterfaceRx, accountId: AccountId): Observable<ResultBalance> {
|
||||
return api.queryMulti<[Balance, Balance, Vec<BalanceLock>, Option<VestingSchedule>]>([
|
||||
[api.query.balances.freeBalance, accountId],
|
||||
[api.query.balances.reservedBalance, accountId],
|
||||
[api.query.balances.locks, accountId],
|
||||
[api.query.balances.vesting, accountId]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name all
|
||||
* @param {( AccountIndex | AccountId | Address | string )} address - An accounts Id in different formats.
|
||||
* @returns An object containing the combined results of the storage queries for
|
||||
* all relevant fees as declared in the substrate chain spec.
|
||||
* @returns An object containing the results of various balance queries
|
||||
* @example
|
||||
* <BR>
|
||||
*
|
||||
* ```javascript
|
||||
* const ALICE = 'F7Hs';
|
||||
*
|
||||
* api.derive.balances.all(ALICE, ([accountId, lockedBalance]) => {
|
||||
* api.derive.balances.all(ALICE, ({ accountId, lockedBalance }) => {
|
||||
* console.log(`The account ${accountId} has a locked balance ${lockedBalance} units.`);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function all (api: ApiInterfaceRx): (address: AccountIndex | AccountId | Address | string) => Observable<DerivedBalances> {
|
||||
return (address: AccountIndex | AccountId | Address | string): Observable<DerivedBalances> => {
|
||||
return idAndIndex(api)(address).pipe(
|
||||
switchMap(([accountId]): Observable<Result> =>
|
||||
return memo((address: AccountIndex | AccountId | Address | string): Observable<DerivedBalances> =>
|
||||
api.derive.accounts.info(address).pipe(
|
||||
switchMap(({ accountId }): Observable<Result> =>
|
||||
(accountId
|
||||
? combineLatest([
|
||||
of(accountId),
|
||||
bestNumber(api)(),
|
||||
api.queryMulti([
|
||||
[api.query.balances.freeBalance, accountId],
|
||||
[api.query.balances.reservedBalance, accountId],
|
||||
[api.query.balances.locks, accountId],
|
||||
[api.query.balances.vesting, accountId],
|
||||
[api.query.system.accountNonce, accountId]
|
||||
])
|
||||
api.derive.chain.bestNumber(),
|
||||
queryBalances(api, accountId),
|
||||
// FIXME This is having issues with Kusama, only use accountNonce atm
|
||||
// api.rpc.account && api.rpc.account.nextIndex
|
||||
// ? api.rpc.account.nextIndex(accountId)
|
||||
// // otherwise we end up with this: type 'Codec | Index' is not assignable to type 'Index'.
|
||||
// : api.query.system.accountNonce<Index>(accountId)
|
||||
api.query.system.accountNonce<Index>(accountId)
|
||||
])
|
||||
: of([undefined, undefined, [undefined, undefined, undefined, undefined, undefined]])
|
||||
) as Observable<Result>
|
||||
: of([createType(api.registry, 'AccountId'), createType(api.registry, 'BlockNumber'), [createType(api.registry, 'Balance'), createType(api.registry, 'Balance'), createType(api.registry, 'Vec<BalanceLock>'), createType(api.registry, 'Option<VestingSchedule>', null)], createType(api.registry, 'Index')])
|
||||
)
|
||||
),
|
||||
map(calcBalances),
|
||||
drr()
|
||||
);
|
||||
};
|
||||
map((result): DerivedBalances => calcBalances(api, result))
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1,39 +1,41 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Balance } from '@polkadot/types/interfaces';
|
||||
import { DerivedFees } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { drr } from '../util/drr';
|
||||
import { memo } from '../util';
|
||||
|
||||
type Result = [BN, BN, BN, BN, BN];
|
||||
type Result = [Balance, Balance, Balance, Balance, Balance];
|
||||
|
||||
function queryV2 (api: ApiInterfaceRx): Observable<Result> {
|
||||
const paymentBase = api.consts.transactionPayment || api.consts.balances;
|
||||
|
||||
function querySubtrateV2 (api: ApiInterfaceRx): Observable<Result> {
|
||||
return of([
|
||||
// get values from api.const for substrate versions post spec_version: 101
|
||||
// https://github.com/paritytech/substrate/pull/2883/files#diff-5e5e1c3aec9ddfde0a9054d062ab3db9R131
|
||||
api.consts.balances.creationFee,
|
||||
api.consts.balances.existentialDeposit,
|
||||
api.consts.balances.transactionBaseFee,
|
||||
api.consts.balances.transactionByteFee,
|
||||
api.consts.balances.transferFee
|
||||
]) as any as Observable<Result>;
|
||||
api.consts.balances.transferFee,
|
||||
paymentBase.transactionBaseFee as Balance,
|
||||
paymentBase.transactionByteFee as Balance
|
||||
]);
|
||||
}
|
||||
|
||||
function querySubtrateV1 (api: ApiInterfaceRx): Observable<Result> {
|
||||
return api.queryMulti([
|
||||
function queryV1 (api: ApiInterfaceRx): Observable<Result> {
|
||||
return api.queryMulti<Result>([
|
||||
// Support older versions and get values from storage
|
||||
api.query.balances.creationFee,
|
||||
api.query.balances.existentialDeposit,
|
||||
api.query.balances.transferFee,
|
||||
api.query.balances.transactionBaseFee,
|
||||
api.query.balances.transactionByteFee,
|
||||
api.query.balances.transferFee
|
||||
]) as any as Observable<Result>;
|
||||
api.query.balances.transactionByteFee
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,26 +46,24 @@ function querySubtrateV1 (api: ApiInterfaceRx): Observable<Result> {
|
||||
* <BR>
|
||||
*
|
||||
* ```javascript
|
||||
* api.derive.balances.fees(([creationFee, transferFee]) => {
|
||||
* api.derive.balances.fees(({ creationFee, transferFee }) => {
|
||||
* console.log(`The fee for creating a new account on this chain is ${creationFee} units. The fee required for making a transfer is ${transferFee} units.`);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function fees (api: ApiInterfaceRx): () => Observable<DerivedFees> {
|
||||
return (): Observable<DerivedFees> => {
|
||||
return (
|
||||
api.consts.balances
|
||||
? querySubtrateV2(api)
|
||||
: querySubtrateV1(api)
|
||||
).pipe(
|
||||
map(([creationFee, existentialDeposit, transactionBaseFee, transactionByteFee, transferFee]): DerivedFees => ({
|
||||
const query = api.consts.balances
|
||||
? queryV2
|
||||
: queryV1;
|
||||
|
||||
return memo((): Observable<DerivedFees> =>
|
||||
query(api).pipe(
|
||||
map(([creationFee, existentialDeposit, transferFee, transactionBaseFee, transactionByteFee]): DerivedFees => ({
|
||||
creationFee,
|
||||
existentialDeposit,
|
||||
transactionBaseFee,
|
||||
transactionByteFee,
|
||||
transferFee
|
||||
})),
|
||||
drr()
|
||||
);
|
||||
};
|
||||
}))
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces';
|
||||
import { DerivedBalances } from '../types';
|
||||
|
||||
import { combineLatest, Observable, of } from 'rxjs';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
|
||||
import { DerivedBalances } from '../types';
|
||||
import { drr } from '../util/drr';
|
||||
import { all } from './all';
|
||||
import { memo } from '../util';
|
||||
|
||||
export function votingBalances (api: ApiInterfaceRx): (addresses?: (AccountId | AccountIndex | Address | string)[]) => Observable<DerivedBalances[]> {
|
||||
return (addresses?: (AccountId | AccountIndex | Address | string)[]): Observable<DerivedBalances[]> => {
|
||||
return (
|
||||
!addresses || !addresses.length
|
||||
? of([] as DerivedBalances[])
|
||||
: combineLatest(addresses.map(all(api)))
|
||||
).pipe(
|
||||
drr()
|
||||
);
|
||||
};
|
||||
return memo((addresses?: (AccountId | AccountIndex | Address | string)[]): Observable<DerivedBalances[]> =>
|
||||
!addresses || !addresses.length
|
||||
? of([] as DerivedBalances[])
|
||||
: combineLatest(
|
||||
addresses.map((accountId): Observable<DerivedBalances> =>
|
||||
api.derive.balances.all(accountId))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,29 +1,27 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, AccountIndex, Address } from '@polkadot/types/interfaces';
|
||||
import { DerivedBalances } from '../types';
|
||||
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Vec } from '@polkadot/types';
|
||||
|
||||
import { idAndIndex } from '../accounts/idAndIndex';
|
||||
import { DerivedBalances } from '../types';
|
||||
import { drr } from '../util/drr';
|
||||
import { votingBalances } from './votingBalances';
|
||||
import { memo } from '../util';
|
||||
|
||||
export function votingBalancesNominatorsFor (api: ApiInterfaceRx): (address: AccountId | AccountIndex | Address | string) => Observable<DerivedBalances[]> {
|
||||
return (address: AccountId | AccountIndex | Address | string): Observable<DerivedBalances[]> => {
|
||||
return idAndIndex(api)(address).pipe(
|
||||
switchMap(([accountId]): Observable<AccountId[]> =>
|
||||
return memo((address: AccountId | AccountIndex | Address | string): Observable<DerivedBalances[]> =>
|
||||
api.derive.accounts.info(address).pipe(
|
||||
switchMap(({ accountId }): Observable<AccountId[]> =>
|
||||
accountId
|
||||
? (api.query.staking.nominatorsFor<Vec<AccountId>>(accountId))
|
||||
? api.query.staking.nominatorsFor<Vec<AccountId>>(accountId)
|
||||
: of([] as AccountId[])
|
||||
),
|
||||
switchMap(votingBalances(api)),
|
||||
drr()
|
||||
);
|
||||
};
|
||||
switchMap((accounts): Observable<DerivedBalances[]> =>
|
||||
api.derive.balances.votingBalances(accounts)
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { BlockNumber } from '@polkadot/types/interfaces';
|
||||
import { BlockNumber, Header } from '@polkadot/types/interfaces';
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
|
||||
import { drr } from '../util/drr';
|
||||
import { memo } from '../util';
|
||||
|
||||
/**
|
||||
* @name bestNumber
|
||||
@@ -23,9 +23,8 @@ import { drr } from '../util/drr';
|
||||
* ```
|
||||
*/
|
||||
export function bestNumber (api: ApiInterfaceRx): () => Observable<BlockNumber> {
|
||||
return (): Observable<BlockNumber> =>
|
||||
api.rpc.chain.subscribeNewHeads().pipe(
|
||||
map((header): BlockNumber => header.number.unwrap()),
|
||||
drr()
|
||||
);
|
||||
return memo((): Observable<BlockNumber> =>
|
||||
api.derive.chain.subscribeNewHeads().pipe(
|
||||
map((header: Header): BlockNumber => header.number.unwrap())
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
|
||||
import { drr } from '../util/drr';
|
||||
import { memo } from '../util';
|
||||
|
||||
/**
|
||||
* @name bestNumberFinalized
|
||||
@@ -24,9 +24,8 @@ import { drr } from '../util/drr';
|
||||
* ```
|
||||
*/
|
||||
export function bestNumberFinalized (api: ApiInterfaceRx): () => Observable<BlockNumber> {
|
||||
return (): Observable<BlockNumber> =>
|
||||
return memo((): Observable<BlockNumber> =>
|
||||
api.rpc.chain.subscribeFinalizedHeads().pipe(
|
||||
map((header): BlockNumber => header.number.unwrap()),
|
||||
drr()
|
||||
);
|
||||
map((header): BlockNumber => header.number.unwrap())
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
@@ -9,9 +9,7 @@ import { map } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { createType } from '@polkadot/types';
|
||||
|
||||
import { drr } from '../util/drr';
|
||||
import { bestNumber } from './bestNumber';
|
||||
import { bestNumberFinalized } from './bestNumberFinalized';
|
||||
import { memo } from '../util';
|
||||
|
||||
/**
|
||||
* @name bestNumberLag
|
||||
@@ -27,14 +25,13 @@ import { bestNumberFinalized } from './bestNumberFinalized';
|
||||
* ```
|
||||
*/
|
||||
export function bestNumberLag (api: ApiInterfaceRx): () => Observable<BlockNumber> {
|
||||
return (): Observable<BlockNumber> =>
|
||||
return memo((): Observable<BlockNumber> =>
|
||||
combineLatest([
|
||||
bestNumber(api)(),
|
||||
bestNumberFinalized(api)()
|
||||
api.derive.chain.bestNumber(),
|
||||
api.derive.chain.bestNumberFinalized()
|
||||
]).pipe(
|
||||
map(([bestNumber, bestNumberFinalized]): BlockNumber =>
|
||||
createType('BlockNumber', bestNumber.sub(bestNumberFinalized))
|
||||
),
|
||||
drr()
|
||||
);
|
||||
createType(api.registry, 'BlockNumber', bestNumber.sub(bestNumberFinalized))
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
import { AccountId } from '@polkadot/types/interfaces';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
|
||||
import { Vec } from '@polkadot/types';
|
||||
|
||||
import { HeaderExtended } from '../type';
|
||||
import { drr } from '../util/drr';
|
||||
import { HeaderAndValidators } from './subscribeNewHeads';
|
||||
import { memo } from '../util';
|
||||
|
||||
/**
|
||||
* @name bestNumberFinalized
|
||||
@@ -25,22 +28,21 @@ import { HeaderAndValidators } from './subscribeNewHeads';
|
||||
* ```
|
||||
*/
|
||||
export function getHeader (api: ApiInterfaceRx): (hash: Uint8Array | string) => Observable<HeaderExtended | undefined> {
|
||||
return (hash: Uint8Array | string): Observable<HeaderExtended | undefined> =>
|
||||
(combineLatest([
|
||||
return memo((hash: Uint8Array | string): Observable<HeaderExtended | undefined> =>
|
||||
combineLatest([
|
||||
api.rpc.chain.getHeader(hash),
|
||||
api.query.session
|
||||
? api.query.session.validators.at(hash)
|
||||
? api.query.session.validators.at(hash) as Observable<Vec<AccountId>>
|
||||
: of([])
|
||||
]) as Observable<HeaderAndValidators>).pipe(
|
||||
]).pipe(
|
||||
map(([header, validators]): HeaderExtended =>
|
||||
new HeaderExtended(header, validators)
|
||||
new HeaderExtended(api.registry, header, validators)
|
||||
),
|
||||
catchError((): Observable<undefined> =>
|
||||
// where rpc.chain.getHeader throws, we will land here - it can happen that
|
||||
// we supplied an invalid hash. (Due to defaults, storeage will have an
|
||||
// empty value, so only the RPC is affected). So return undefined
|
||||
of()
|
||||
),
|
||||
drr()
|
||||
);
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { AccountId, Header } from '@polkadot/types/interfaces';
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { Observable, combineLatest } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { HeaderExtended } from '../type';
|
||||
import { drr } from '../util/drr';
|
||||
|
||||
export type HeaderAndValidators = [Header, AccountId[]];
|
||||
import { memo } from '../util';
|
||||
|
||||
/**
|
||||
* @name subscribeNewHeads
|
||||
@@ -27,22 +24,13 @@ export type HeaderAndValidators = [Header, AccountId[]];
|
||||
* ```
|
||||
*/
|
||||
export function subscribeNewHeads (api: ApiInterfaceRx): () => Observable<HeaderExtended> {
|
||||
return (): Observable<HeaderExtended> =>
|
||||
api.rpc.chain.subscribeNewHeads().pipe(
|
||||
switchMap((header: Header): Observable<HeaderAndValidators> =>
|
||||
(combineLatest([
|
||||
of(header),
|
||||
// theoretically we could combine at the first call with session.validators(), however
|
||||
// we make 100% sure we actually get the validators at a specific block so when these
|
||||
// change at an era boundary, we have the previous values to ensure our indexes are correct
|
||||
api.query.session
|
||||
? api.query.session.validators.at(header.hash)
|
||||
: of([])
|
||||
]) as Observable<HeaderAndValidators>)
|
||||
),
|
||||
map(([header, validators]): HeaderExtended =>
|
||||
new HeaderExtended(header, validators)
|
||||
),
|
||||
drr()
|
||||
);
|
||||
return memo((): Observable<HeaderExtended> =>
|
||||
combineLatest([
|
||||
api.rpc.chain.subscribeNewHeads(),
|
||||
api.derive.staking.validators()
|
||||
]).pipe(
|
||||
map(([header, { validators }]): HeaderExtended =>
|
||||
new HeaderExtended(api.registry, header, validators)
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
export * from './proposals';
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Hash, Proposal, Votes } from '@polkadot/types/interfaces';
|
||||
import { DerivedCollectiveProposals } from '../types';
|
||||
|
||||
import { combineLatest, Observable, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { Option } from '@polkadot/types';
|
||||
|
||||
export function proposals (api: ApiInterfaceRx, section: 'council' | 'technicalCommittee'): () => Observable<DerivedCollectiveProposals> {
|
||||
return (): Observable<DerivedCollectiveProposals> =>
|
||||
api.query[section]
|
||||
? api.query[section].proposals()
|
||||
.pipe(
|
||||
switchMap((hashes: Hash[]): Observable<[Hash[], Option<Proposal>[], Option<Votes>[]]> => {
|
||||
return combineLatest([
|
||||
of(hashes),
|
||||
combineLatest(
|
||||
hashes.map((hash): Observable<Option<Proposal>> => api.query[section].proposalOf(hash))
|
||||
),
|
||||
api.query[section].voting.multi<Option<Votes>>(hashes)
|
||||
]);
|
||||
}),
|
||||
map(([hashes, proposals, votes]): DerivedCollectiveProposals => {
|
||||
const result: DerivedCollectiveProposals = [];
|
||||
|
||||
proposals.forEach((proposalOpt, index): void => {
|
||||
if (proposalOpt.isSome) {
|
||||
result.push({
|
||||
hash: hashes[index],
|
||||
proposal: proposalOpt.unwrap(),
|
||||
votes: votes[index].unwrapOr(null)
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
})
|
||||
)
|
||||
: of([] as DerivedCollectiveProposals);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
@@ -9,7 +9,7 @@ import BN from 'bn.js';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { drr } from '../util/drr';
|
||||
import { memo } from '../util';
|
||||
|
||||
type ResultV2 = [BN, BN, BN, BN, BN, BN, BN, BN, BN, BN];
|
||||
|
||||
@@ -31,49 +31,6 @@ function parseResult ([callBaseFee, contractFee, createBaseFee, creationFee, ren
|
||||
};
|
||||
}
|
||||
|
||||
// Only for 1.0 support. rentByteFee, rentDepositOffset, tombstoneDeposit are not available in substrate 1.0.
|
||||
// TODO remove this once 1.0 support is dropped
|
||||
function queryV1 (api: ApiInterfaceRx): Observable<DerivedContractFees> {
|
||||
return (
|
||||
api.queryMulti([
|
||||
api.query.contract.callBaseFee,
|
||||
api.query.contract.contractFee,
|
||||
api.query.contract.createBaseFee,
|
||||
api.query.contract.creationFee,
|
||||
api.query.contract.transactionBaseFee,
|
||||
api.query.contract.transactionByteFee,
|
||||
api.query.contract.transferFee
|
||||
]) as unknown as Observable<BN[]>
|
||||
).pipe(
|
||||
map(([callBaseFee, contractFee, createBaseFee, creationFee, transactionBaseFee, transactionByteFee, transferFee]): DerivedContractFees =>
|
||||
// We've done this on purpose, i.e. so we can just copy the name/order from the parse above and
|
||||
// see gaps, in this case those are filled with `ZERO`
|
||||
parseResult([
|
||||
callBaseFee, contractFee, createBaseFee, creationFee, ZERO, ZERO, ZERO, transactionBaseFee, transactionByteFee, transferFee
|
||||
])
|
||||
),
|
||||
drr()
|
||||
);
|
||||
}
|
||||
|
||||
// query via query (early v2, non-current, support to be dropped])
|
||||
function queryQuery (api: ApiInterfaceRx): Observable<ResultV2> {
|
||||
const queryBase = api.query.contracts || api.query.contract;
|
||||
|
||||
return api.queryMulti([
|
||||
queryBase.callBaseFee,
|
||||
queryBase.contractFee,
|
||||
queryBase.createBaseFee,
|
||||
queryBase.creationFee,
|
||||
queryBase.rentByteFee,
|
||||
queryBase.rentDepositOffset,
|
||||
queryBase.tombstoneDeposit,
|
||||
queryBase.transactionBaseFee,
|
||||
queryBase.transactionByteFee,
|
||||
queryBase.transferFee
|
||||
]) as unknown as Observable<ResultV2>;
|
||||
}
|
||||
|
||||
// query via constants (current applicable path)
|
||||
function queryConstants (api: ApiInterfaceRx): Observable<ResultV2> {
|
||||
return of([
|
||||
@@ -104,23 +61,18 @@ function queryConstants (api: ApiInterfaceRx): Observable<ResultV2> {
|
||||
* ```
|
||||
*/
|
||||
export function fees (api: ApiInterfaceRx): () => Observable<DerivedContractFees> {
|
||||
return (): Observable<DerivedContractFees> => {
|
||||
if (api.query.contract && !api.query.contract.rentByteFee) {
|
||||
return queryV1(api);
|
||||
}
|
||||
|
||||
return memo((): Observable<DerivedContractFees> => {
|
||||
return (
|
||||
api.consts.contracts
|
||||
? queryConstants(api)
|
||||
: queryQuery(api)
|
||||
: of([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO])
|
||||
).pipe(
|
||||
map(([callBaseFee, contractFee, createBaseFee, creationFee, rentByteFee, rentDepositOffset, tombstoneDeposit, transactionBaseFee, transactionByteFee, transferFee]): DerivedContractFees =>
|
||||
// We've done this on purpose, i.e. so we can just copy the name/order from the parse above and see gaps
|
||||
parseResult([
|
||||
callBaseFee, contractFee, createBaseFee, creationFee, rentByteFee, rentDepositOffset, tombstoneDeposit, transactionBaseFee, transactionByteFee, transferFee
|
||||
])
|
||||
),
|
||||
drr()
|
||||
)
|
||||
);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
export * from './proposals';
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { DerivedCollectiveProposals } from '../types';
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import { proposals as collectiveProposals } from '../collective';
|
||||
import { memo } from '../util';
|
||||
|
||||
export function proposals (api: ApiInterfaceRx): () => Observable<DerivedCollectiveProposals> {
|
||||
return memo(collectiveProposals(api, 'council'));
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
export * from './proposals';
|
||||
export * from './referendumInfos';
|
||||
export * from './referendums';
|
||||
export * from './referendumVotesFor';
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, Balance, BlockNumber, Hash, PropIndex, Proposal } from '@polkadot/types/interfaces';
|
||||
import { ITuple } from '@polkadot/types/types';
|
||||
import { DeriveProposal } from '../types';
|
||||
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Bytes, Option, Vec, createType } from '@polkadot/types';
|
||||
|
||||
import { memo } from '../util';
|
||||
|
||||
export type PreImage = Option<ITuple<[Bytes, AccountId, Balance, BlockNumber]>>;
|
||||
|
||||
type Depositors = Option<ITuple<[Balance, Vec<AccountId>]>>;
|
||||
type Proposals = Vec<ITuple<[PropIndex, Hash, AccountId]>>;
|
||||
|
||||
interface Result {
|
||||
depositors: Depositors[];
|
||||
preimages: PreImage[];
|
||||
proposals: Proposals;
|
||||
}
|
||||
|
||||
function parse (api: ApiInterfaceRx, { depositors, proposals, preimages }: Result): DeriveProposal[] {
|
||||
return proposals
|
||||
.filter(([, , proposer], index): boolean =>
|
||||
!!(depositors[index]?.isSome) && !proposer.isEmpty
|
||||
)
|
||||
.map(([propIndex, hash, proposer], index): DeriveProposal => {
|
||||
const preimage = preimages[index].unwrapOr(null);
|
||||
const depositor = depositors[index].unwrap();
|
||||
let proposal: undefined | Proposal;
|
||||
|
||||
// we could end up in a situation where the proposal is non-decodable, e.g. after an upgrade
|
||||
if (preimage) {
|
||||
try {
|
||||
proposal = createType(api.registry, 'Proposal', preimage[0].toU8a(true));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
balance: depositor[0],
|
||||
hash,
|
||||
index: propIndex,
|
||||
preimage: preimage
|
||||
? {
|
||||
at: preimage[3],
|
||||
balance: preimage[2],
|
||||
proposer: preimage[1]
|
||||
}
|
||||
: undefined,
|
||||
proposal,
|
||||
proposer,
|
||||
seconds: depositor[1]
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function proposals (api: ApiInterfaceRx): () => Observable<DeriveProposal[]> {
|
||||
return memo((): Observable<DeriveProposal[]> =>
|
||||
api.query.democracy?.publicProps
|
||||
? api.query.democracy
|
||||
.publicProps<Proposals>()
|
||||
.pipe(
|
||||
switchMap((proposals) =>
|
||||
combineLatest([
|
||||
of(proposals),
|
||||
api.query.democracy.preimages.multi<PreImage>(proposals.map(([, hash]): Hash => hash)),
|
||||
api.query.democracy.depositOf.multi<Depositors>(proposals.map(([index]): PropIndex => index))
|
||||
])
|
||||
),
|
||||
map(([proposals, preimages, depositors]): DeriveProposal[] =>
|
||||
parse(api, { depositors, proposals, preimages })
|
||||
)
|
||||
)
|
||||
: of([] as DeriveProposal[])
|
||||
);
|
||||
}
|
||||
@@ -1,40 +1,64 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ReferendumInfo } from '@polkadot/types/interfaces/democracy';
|
||||
import { DerivedReferendum } from '../types';
|
||||
import { PreImage } from './proposals';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Option } from '@polkadot/types';
|
||||
import { isNull } from '@polkadot/util';
|
||||
import { Option, createType } from '@polkadot/types';
|
||||
|
||||
import { ReferendumInfoExtended } from '../type';
|
||||
import { drr } from '../util/drr';
|
||||
import { memo } from '../util';
|
||||
|
||||
export function constructInfo (index: BN | number, optionInfo?: Option<ReferendumInfo>): Option<ReferendumInfoExtended> {
|
||||
const info = optionInfo
|
||||
? optionInfo.unwrapOr(null)
|
||||
function constructInfo (api: ApiInterfaceRx, index: BN | number, _info: Option<ReferendumInfo>, _preimage?: PreImage): DerivedReferendum | null {
|
||||
const preImage = _preimage?.isSome
|
||||
? _preimage.unwrap()
|
||||
: null;
|
||||
const info = _info.unwrapOr(null);
|
||||
|
||||
return new Option<ReferendumInfoExtended>(
|
||||
ReferendumInfoExtended,
|
||||
isNull(info)
|
||||
? null
|
||||
: new ReferendumInfoExtended(info, index)
|
||||
if (!info) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
index: createType(api.registry, 'PropIndex', index),
|
||||
info,
|
||||
hash: info.proposalHash,
|
||||
proposal: preImage
|
||||
? createType(api.registry, 'Proposal', preImage[0].toU8a(true))
|
||||
: undefined,
|
||||
preimage: preImage
|
||||
? {
|
||||
at: preImage[3],
|
||||
balance: preImage[2],
|
||||
proposer: preImage[1]
|
||||
}
|
||||
: undefined
|
||||
};
|
||||
}
|
||||
|
||||
export function retrieveInfo (api: ApiInterfaceRx, index: BN | number, info: Option<ReferendumInfo>): Observable<DerivedReferendum | null> {
|
||||
return ((
|
||||
info?.isSome
|
||||
? api.query.democracy.preimages<PreImage>(info.unwrap().proposalHash)
|
||||
: of(undefined)
|
||||
) as Observable<PreImage | undefined>).pipe(
|
||||
map((preimage?: PreImage): DerivedReferendum | null =>
|
||||
constructInfo(api, index, info, preimage)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export function referendumInfo (api: ApiInterfaceRx): (index: BN | number) => Observable<Option<ReferendumInfoExtended>> {
|
||||
return (index: BN | number): Observable<Option<ReferendumInfoExtended>> => {
|
||||
return (api.query.democracy.referendumInfoOf<Option<ReferendumInfo>>(index))
|
||||
.pipe(
|
||||
map((optionInfo): Option<ReferendumInfoExtended> =>
|
||||
constructInfo(index, optionInfo)
|
||||
),
|
||||
drr()
|
||||
);
|
||||
};
|
||||
export function referendumInfo (api: ApiInterfaceRx): (index: BN | number) => Observable<DerivedReferendum | null> {
|
||||
return memo((index: BN | number): Observable<DerivedReferendum | null> =>
|
||||
api.query.democracy.referendumInfoOf<Option<ReferendumInfo>>(index).pipe(
|
||||
switchMap((info): Observable<DerivedReferendum | null> =>
|
||||
retrieveInfo(api, index, info)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,32 +1,35 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ReferendumInfo } from '@polkadot/types/interfaces/democracy';
|
||||
import { DerivedReferendum } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Observable, combineLatest, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Option, Vec } from '@polkadot/types';
|
||||
|
||||
import { ReferendumInfoExtended } from '../type';
|
||||
import { drr } from '../util/drr';
|
||||
import { constructInfo } from './referendumInfo';
|
||||
import { memo } from '../util';
|
||||
import { retrieveInfo } from './referendumInfo';
|
||||
|
||||
export function referendumInfos (api: ApiInterfaceRx): (ids?: (BN | number)[]) => Observable<Option<ReferendumInfoExtended>[]> {
|
||||
return (ids: (BN | number)[] = []): Observable<Option<ReferendumInfoExtended>[]> => {
|
||||
return (
|
||||
export function referendumInfos (api: ApiInterfaceRx): (ids?: (BN | number)[]) => Observable<DerivedReferendum[]> {
|
||||
return memo((ids: (BN | number)[] = []): Observable<DerivedReferendum[]> =>
|
||||
(
|
||||
!ids || !ids.length
|
||||
? of([] as Option<ReferendumInfo>[])
|
||||
: api.query.democracy.referendumInfoOf.multi(ids) as Observable<Vec<Option<ReferendumInfo>>>
|
||||
).pipe(
|
||||
map((infos): Option<ReferendumInfoExtended>[] =>
|
||||
ids.map((id, index): Option<ReferendumInfoExtended> =>
|
||||
constructInfo(id, infos[index])
|
||||
switchMap((infos): Observable<(DerivedReferendum | null)[]> =>
|
||||
combineLatest(
|
||||
...ids.map((id, index): Observable<DerivedReferendum | null> =>
|
||||
retrieveInfo(api, id, infos[index])
|
||||
)
|
||||
)
|
||||
),
|
||||
drr()
|
||||
);
|
||||
};
|
||||
map((infos): DerivedReferendum[] =>
|
||||
infos.filter((referendum): boolean => !!referendum) as DerivedReferendum[]
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
@@ -11,27 +11,24 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Vec, createType } from '@polkadot/types';
|
||||
|
||||
import { DerivedBalances, DerivedReferendumVote } from '../types';
|
||||
import { drr } from '../util/drr';
|
||||
import { votes } from './votes';
|
||||
import { votingBalances } from '../balances/votingBalances';
|
||||
import { memo } from '../util';
|
||||
|
||||
export function referendumVotesFor (api: ApiInterfaceRx): (referendumId: BN | number) => Observable<DerivedReferendumVote[]> {
|
||||
return (referendumId: BN | number): Observable<DerivedReferendumVote[]> =>
|
||||
(api.query.democracy.votersFor<Vec<AccountId>>(referendumId)).pipe(
|
||||
return memo((referendumId: BN | number): Observable<DerivedReferendumVote[]> =>
|
||||
api.query.democracy.votersFor<Vec<AccountId>>(referendumId).pipe(
|
||||
switchMap((votersFor): Observable<[Vec<AccountId>, Vote[], DerivedBalances[]]> =>
|
||||
combineLatest([
|
||||
of(votersFor),
|
||||
votes(api)(referendumId as BN, votersFor),
|
||||
votingBalances(api)(votersFor)
|
||||
api.derive.democracy.votes(referendumId as BN, votersFor),
|
||||
api.derive.balances.votingBalances(votersFor)
|
||||
])
|
||||
),
|
||||
map(([votersFor, votes, balances]): DerivedReferendumVote[] =>
|
||||
votersFor.map((accountId, index): DerivedReferendumVote => ({
|
||||
accountId,
|
||||
balance: balances[index].votingBalance || createType('Balance'),
|
||||
vote: votes[index] || createType('Vote')
|
||||
} as unknown as DerivedReferendumVote))
|
||||
),
|
||||
drr()
|
||||
);
|
||||
balance: balances[index].votingBalance || createType(api.registry, 'Balance'),
|
||||
vote: votes[index] || createType(api.registry, 'Vote')
|
||||
} as DerivedReferendumVote))
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1,34 +1,35 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ReferendumIndex } from '@polkadot/types/interfaces/democracy';
|
||||
import { DerivedReferendum } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Option } from '@polkadot/types';
|
||||
|
||||
import { ReferendumInfoExtended } from '../type';
|
||||
import { drr } from '../util/drr';
|
||||
import { referendumInfos } from './referendumInfos';
|
||||
import { memo } from '../util';
|
||||
|
||||
export function referendums (api: ApiInterfaceRx): () => Observable<Option<ReferendumInfoExtended>[]> {
|
||||
return (): Observable<Option<ReferendumInfoExtended>[]> =>
|
||||
(api.queryMulti([
|
||||
api.query.democracy.nextTally,
|
||||
api.query.democracy.referendumCount
|
||||
]) as Observable<[ReferendumIndex?, ReferendumIndex?]>).pipe(
|
||||
switchMap(([nextTally, referendumCount]): Observable<Option<ReferendumInfoExtended>[]> =>
|
||||
referendumCount && nextTally && referendumCount.gt(nextTally) && referendumCount.gtn(0)
|
||||
? referendumInfos(api)(
|
||||
[...Array(referendumCount.sub(nextTally).toNumber())].map((_, i): BN =>
|
||||
nextTally.addn(i)
|
||||
export function referendums (api: ApiInterfaceRx): () => Observable<DerivedReferendum[]> {
|
||||
return memo((): Observable<DerivedReferendum[]> =>
|
||||
// V2 vs V1 (and early V2)
|
||||
api.query.democracy?.lowestUnbaked || api.query.democracy?.nextTally
|
||||
? api.queryMulti<[ReferendumIndex, ReferendumIndex]>([
|
||||
api.query.democracy.lowestUnbaked || api.query.democracy.nextTally,
|
||||
api.query.democracy.referendumCount
|
||||
]).pipe(
|
||||
switchMap(([earliest, referendumCount]): Observable<DerivedReferendum[]> =>
|
||||
referendumCount?.gt(earliest) && referendumCount?.gtn(0)
|
||||
? api.derive.democracy.referendumInfos(
|
||||
[...Array(referendumCount.sub(earliest).toNumber())].map((_, i): BN =>
|
||||
earliest.addn(i)
|
||||
)
|
||||
)
|
||||
)
|
||||
: of([])
|
||||
),
|
||||
drr()
|
||||
);
|
||||
: of([])
|
||||
)
|
||||
)
|
||||
: of([] as DerivedReferendum[])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
@@ -7,20 +7,17 @@ import { AccountId, Vote } from '@polkadot/types/interfaces';
|
||||
import BN from 'bn.js';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Vec } from '@polkadot/types';
|
||||
|
||||
import { drr } from '../util/drr';
|
||||
import { memo } from '../util';
|
||||
|
||||
export function votes (api: ApiInterfaceRx): (referendumId: BN, accountIds?: AccountId[]) => Observable<Vote[]> {
|
||||
return (referendumId: BN, accountIds: AccountId[] = []): Observable<Vote[]> => {
|
||||
return ((
|
||||
!accountIds || !accountIds.length
|
||||
? of([])
|
||||
: api.query.democracy.voteOf.multi(
|
||||
accountIds.map((accountId): [BN, AccountId] =>
|
||||
[referendumId, accountId]
|
||||
)
|
||||
return memo((referendumId: BN, accountIds: AccountId[] = []): Observable<Vote[]> =>
|
||||
!accountIds || !accountIds.length
|
||||
? of([] as Vote[])
|
||||
: api.query.democracy.voteOf.multi<Vote>(
|
||||
accountIds.map((accountId): [BN, AccountId] =>
|
||||
[referendumId, accountId]
|
||||
)
|
||||
) as Observable<Vec<Vote>>).pipe(drr());
|
||||
};
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, ApprovalFlag, SetIndex } from '@polkadot/types/interfaces';
|
||||
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Vec } from '@polkadot/types';
|
||||
import { switchMap, map } from 'rxjs/operators';
|
||||
import { approvalFlagsToBools } from '../util/approvalFlagsToBools';
|
||||
import { drr } from '../util/drr';
|
||||
|
||||
/**
|
||||
* @name approvalsOf
|
||||
* @returns A nested array of boolean approvals for the given account in each voter set index, converted from its ApprovalFlag(s).
|
||||
* @example
|
||||
* <BR>
|
||||
*
|
||||
* ```javascript
|
||||
* api.derive.elections.approvalsOf(ALICE, (approvals) => {
|
||||
* // approvals === [[false], [true, false], ...]
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function approvalsOf (api: ApiInterfaceRx): (who: AccountId) => Observable<boolean[][]> {
|
||||
return (who: AccountId | string): Observable<boolean[][]> =>
|
||||
api.query.elections.nextVoterSet<SetIndex>().pipe(
|
||||
switchMap((nextVoterSet: SetIndex): Observable<Vec<ApprovalFlag>[]> =>
|
||||
api.query.elections.approvalsOf.multi(
|
||||
[...Array(nextVoterSet.toNumber() + 1).keys()].map((i): [string, number] => [
|
||||
who.toString(), i]
|
||||
)
|
||||
) as any as Observable<Vec<ApprovalFlag>[]>
|
||||
),
|
||||
map((votes: Vec<ApprovalFlag>[]): boolean[][] =>
|
||||
votes.map((flags: Vec<ApprovalFlag>): boolean[] =>
|
||||
approvalFlagsToBools(flags)
|
||||
)
|
||||
),
|
||||
drr()
|
||||
);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, ApprovalFlag, SetIndex } from '@polkadot/types/interfaces';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Vec } from '@polkadot/types';
|
||||
|
||||
import { approvalFlagsToBools } from '../util/approvalFlagsToBools';
|
||||
import { drr } from '../util/drr';
|
||||
|
||||
/**
|
||||
* @name approvalsOfAt
|
||||
* @returns An array of boolean approvals for the account and set index, converted from the returned ApprovalFlag.
|
||||
* @example
|
||||
* <BR>
|
||||
*
|
||||
* ```javascript
|
||||
* api.derive.elections.approvalsOfAt(ALICE, new BN(0), (approvals) => {
|
||||
* // approvals === [false, true, ...]
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function approvalsOfAt (api: ApiInterfaceRx): (who: AccountId, at: SetIndex) => Observable<boolean[]> {
|
||||
return (who: AccountId | string, at: SetIndex | BN | number): Observable<boolean[]> =>
|
||||
api.query.elections.approvalsOf<Vec<ApprovalFlag>>([who.toString(), at]).pipe(
|
||||
map((flags: Vec<ApprovalFlag>): boolean[] => approvalFlagsToBools(flags)),
|
||||
drr()
|
||||
);
|
||||
}
|
||||
@@ -1,9 +1,5 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
export * from './approvalsOf';
|
||||
export * from './approvalsOfAt';
|
||||
export * from './info';
|
||||
export * from './voters';
|
||||
export * from './voterPositions';
|
||||
|
||||
@@ -1,28 +1,52 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, BlockNumber, SetIndex, VoteIndex } from '@polkadot/types/interfaces';
|
||||
import { AccountId, Balance, BlockNumber } from '@polkadot/types/interfaces';
|
||||
import { ITuple } from '@polkadot/types/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Observable, combineLatest } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { createType, Vec, u32 } from '@polkadot/types';
|
||||
|
||||
import { DerivedElectionsInfo } from '../types';
|
||||
import { drr } from '../util/drr';
|
||||
import { memo } from '../util';
|
||||
|
||||
function query (api: ApiInterfaceRx): Observable<[[AccountId, BlockNumber][], AccountId[], BN, BN, SetIndex, BlockNumber, VoteIndex, SetIndex]> {
|
||||
return api.queryMulti([
|
||||
api.query.elections.members,
|
||||
api.query.elections.candidates,
|
||||
api.query.elections.candidateCount,
|
||||
api.query.elections.desiredSeats,
|
||||
api.query.elections.nextVoterSet,
|
||||
api.query.elections.termDuration,
|
||||
api.query.elections.voteCount,
|
||||
api.query.elections.voterCount
|
||||
]) as any;
|
||||
function deriveElections (api: ApiInterfaceRx, candidates: AccountId[], members: [AccountId, Balance][], runnersUp: [AccountId, Balance][], candidacyBond: Balance, desiredSeats: u32, termDuration: BlockNumber, votingBond: Balance): DerivedElectionsInfo {
|
||||
return {
|
||||
candidates,
|
||||
candidateCount: createType(api.registry, 'u32', candidates.length),
|
||||
candidacyBond,
|
||||
desiredSeats,
|
||||
members: members.sort((a, b): number => b[1].cmp(a[1])),
|
||||
runnersUp: runnersUp.sort((a, b): number => b[1].cmp(a[1])),
|
||||
termDuration,
|
||||
votingBond
|
||||
};
|
||||
}
|
||||
|
||||
function queryElections (api: ApiInterfaceRx): Observable<DerivedElectionsInfo> {
|
||||
const section = api.query.electionsPhragmen ? 'electionsPhragmen' : 'elections';
|
||||
|
||||
// NOTE We have an issue where candidates can return `null` for an empty array, hence
|
||||
// we are not using multi queries here, so empty array is empty (instead of space-filled)
|
||||
return combineLatest([
|
||||
api.query[section].candidates<Vec<AccountId>>(),
|
||||
api.query[section].members<Vec<ITuple<[AccountId, Balance]>>>(),
|
||||
api.query[section].runnersUp<Vec<ITuple<[AccountId, Balance]>>>()
|
||||
]).pipe(
|
||||
map(([candidates, members, runnersUp]): DerivedElectionsInfo => deriveElections(
|
||||
api,
|
||||
candidates,
|
||||
members,
|
||||
runnersUp,
|
||||
api.consts[section].candidacyBond as Balance,
|
||||
api.consts[section].desiredMembers as u32,
|
||||
api.consts[section].termDuration as BlockNumber,
|
||||
api.consts[section].votingBond as Balance
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,31 +57,11 @@ function query (api: ApiInterfaceRx): Observable<[[AccountId, BlockNumber][], Ac
|
||||
* <BR>
|
||||
*
|
||||
* ```javascript
|
||||
* api.derive.elections.info(([members, candidates]) => {
|
||||
* api.derive.elections.info(({ members, candidates }) => {
|
||||
* console.log(`There are currently ${members.length} council members and ${candidates.length} prospective council candidates.`);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function info (api: ApiInterfaceRx): () => Observable<DerivedElectionsInfo> {
|
||||
return (): Observable<DerivedElectionsInfo> => {
|
||||
return query(api).pipe(
|
||||
map(([members, candidates, candidateCount, desiredSeats, nextVoterSet, termDuration, voteCount, voterCount]): DerivedElectionsInfo => ({
|
||||
members: members.reduce(
|
||||
(record: Record<string, BlockNumber>, [accountId, blockNumber]): Record<string, BlockNumber> => {
|
||||
record[accountId.toString()] = blockNumber;
|
||||
return record;
|
||||
},
|
||||
{}
|
||||
),
|
||||
candidates,
|
||||
candidateCount,
|
||||
desiredSeats,
|
||||
nextVoterSet,
|
||||
termDuration,
|
||||
voteCount,
|
||||
voterCount
|
||||
} as unknown as DerivedElectionsInfo)),
|
||||
drr()
|
||||
);
|
||||
};
|
||||
return memo((): Observable<DerivedElectionsInfo> => queryElections(api));
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, SetIndex } from '@polkadot/types/interfaces';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Vec, Option, createType } from '@polkadot/types';
|
||||
import { DerivedVoterPositions } from '../types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { of, combineLatest, Observable } from 'rxjs';
|
||||
import { switchMap, map } from 'rxjs/operators';
|
||||
import { drr } from '../util/drr';
|
||||
|
||||
/**
|
||||
* @name voterPositions
|
||||
* @returns An mapping of all current voter accounts to their voter set and global index.
|
||||
* @example
|
||||
* <BR>
|
||||
*
|
||||
* ```javascript
|
||||
* api.derive.elections.voterPositions((voters) => {
|
||||
* const { index, setIndex, globalIndex } = voters[ALICE];
|
||||
* console.log(`ALICE is a voter at index ${index} in voter set ${setIndex}, with global index ${globalIndex}.`);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function voterPositions (api: ApiInterfaceRx): () => Observable<DerivedVoterPositions> {
|
||||
return (): Observable<DerivedVoterPositions> =>
|
||||
api.query.elections.nextVoterSet<SetIndex>().pipe(
|
||||
switchMap((nextVoterSet: SetIndex): Observable<[BN, Vec<Option<AccountId>>[]]> => combineLatest(
|
||||
of(api.consts.elections.voterSetSize) as any as Observable<BN>,
|
||||
api.query.elections.voters.multi([...Array(+nextVoterSet + 1).keys()].map((_, i): [number] => [i])) as any as Observable<Vec<Option<AccountId>>[]>
|
||||
)),
|
||||
map((result: [BN, Vec<Option<AccountId>>[]]): DerivedVoterPositions => {
|
||||
const [setSize, voters] = result;
|
||||
return voters.reduce((result: DerivedVoterPositions, vec, setIndex): DerivedVoterPositions => {
|
||||
vec.forEach((e, index): void => {
|
||||
// re-create the index based on position 0 is [0][0] and likewise
|
||||
// 64 (0..63 in first) is [1][0] (the first index value in set 2)
|
||||
const accountId: AccountId | null = e.unwrapOr(null);
|
||||
|
||||
if (accountId) {
|
||||
result[accountId.toString()] = {
|
||||
globalIndex: setSize.muln(setIndex).addn(index),
|
||||
index: new BN(index),
|
||||
setIndex: createType('SetIndex', setIndex)
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}, {});
|
||||
}),
|
||||
drr()
|
||||
);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { AccountId } from '@polkadot/types/interfaces';
|
||||
import { DerivedVoterPositions } from '../types';
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { createType, Vec } from '@polkadot/types';
|
||||
|
||||
import { drr } from '../util/drr';
|
||||
import { voterPositions } from './voterPositions';
|
||||
|
||||
/**
|
||||
* @name voters
|
||||
* @returns An array of all current voters from all sets.
|
||||
* @example
|
||||
* <BR>
|
||||
*
|
||||
* ```javascript
|
||||
* api.derive.elections.voters((voters) => {
|
||||
* console.log(`There are ${voters.length} current voters.`);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function voters (api: ApiInterfaceRx): () => Observable<Vec<AccountId>> {
|
||||
return (): Observable<Vec<AccountId>> =>
|
||||
voterPositions(api)().pipe(
|
||||
map(
|
||||
(voterPositions: DerivedVoterPositions): Vec<AccountId> =>
|
||||
createType(
|
||||
'Vec<AccountId>',
|
||||
Object.entries(voterPositions)
|
||||
.sort((a, b): 0 | 1 | -1 => a[1].globalIndex.cmp(b[1].globalIndex))
|
||||
.map(([accountId]): AccountId => createType('AccountId', accountId))
|
||||
)
|
||||
),
|
||||
drr()
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
|
||||
@@ -1,38 +1,41 @@
|
||||
// Copyright 2017-2019 @polkadot/api-derive authors & contributors
|
||||
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import { AccountId, SessionIndex } from '@polkadot/types/interfaces';
|
||||
import { DerivedHeartbeats } from '../types';
|
||||
|
||||
import { of, Observable } from 'rxjs';
|
||||
import { of, Observable, combineLatest } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { ApiInterfaceRx } from '@polkadot/api/types';
|
||||
import { Bytes, Vec } from '@polkadot/types';
|
||||
import { Bytes, Option, u32 } from '@polkadot/types';
|
||||
|
||||
import { drr } from '../util/drr';
|
||||
import { memo } from '../util';
|
||||
|
||||
/**
|
||||
* @description Return a boolean array indicating whether the passed accounts had received heartbeats in the current session
|
||||
*/
|
||||
export function receivedHeartbeats (api: ApiInterfaceRx): (addresses: (AccountId | string)[]) => Observable<boolean[]> {
|
||||
return (addresses: (AccountId | string)[]): Observable<boolean[]> => {
|
||||
return api.query.imOnline && api.query.imOnline.receivedHeartbeats
|
||||
? api.queryMulti<[SessionIndex, Vec<AccountId>]>([
|
||||
api.query.session.currentIndex,
|
||||
api.query.imOnline.keys
|
||||
]).pipe(
|
||||
switchMap(([currentIndex, keys]): Observable<Bytes[]> =>
|
||||
api.query.imOnline.receivedHeartbeats.multi(
|
||||
addresses.map((address): [SessionIndex, number] =>
|
||||
[currentIndex, keys.indexOf(address)]
|
||||
)
|
||||
)
|
||||
export function receivedHeartbeats (api: ApiInterfaceRx): () => Observable<DerivedHeartbeats> {
|
||||
return memo((): Observable<DerivedHeartbeats> =>
|
||||
api.query.imOnline?.receivedHeartbeats && api.query.imOnline.authoredBlocks
|
||||
? api.derive.staking.overview().pipe(
|
||||
switchMap(({ currentIndex, validators }): Observable<[AccountId[], Option<Bytes>[], u32[]]> =>
|
||||
combineLatest([
|
||||
of(validators),
|
||||
api.query.imOnline.receivedHeartbeats.multi<Option<Bytes>>(validators.map((_address, index): [SessionIndex, number] => [currentIndex, index])),
|
||||
api.query.imOnline.authoredBlocks.multi<u32>(validators.map((address): [SessionIndex, AccountId] => [currentIndex, address]))
|
||||
])
|
||||
),
|
||||
map((heartbeats): boolean[] =>
|
||||
heartbeats.map((heartbeat): boolean => !heartbeat.isEmpty)
|
||||
),
|
||||
drr()
|
||||
map(([validators, heartbeats, numBlocks]): DerivedHeartbeats =>
|
||||
validators.reduce((result: DerivedHeartbeats, validator, index): DerivedHeartbeats => ({
|
||||
...result,
|
||||
[validator.toString()]: {
|
||||
blockCount: numBlocks[index],
|
||||
hasMessage: !heartbeats[index].isEmpty,
|
||||
isOnline: !heartbeats[index].isEmpty || numBlocks[index].gtn(0)
|
||||
}
|
||||
}), {})
|
||||
)
|
||||
)
|
||||
: of([...new Array(addresses.length).keys()].map((): boolean => false));
|
||||
};
|
||||
: of({}));
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user