Compare commits

..
82 Commits
Author SHA1 Message Date
Github Actions 06418913e5 [CI Skip] 0.96.1 2019-11-09 13:30:30 +00:00
Jaco Greeff 188363d407 0.96 (#1561) 2019-11-09 14:24:27 +01:00
Github Actions ec79087bab [CI Skip] 0.96.0-beta.40 2019-11-09 11:53:53 +00:00
Jaco Greeff 155fd0f8b1 CHANGELOG for 0.96 series (#1560) 2019-11-09 12:47:06 +01:00
Github Actions 05b7def1a0 [CI Skip] 0.96.0-beta.39 2019-11-09 10:52:37 +00:00
Keith Ingram 5671af8db7 Allow most recent Result.findRecord (#1559)
* combine values

* findRecord newest

* constructor

* Add filterRecords

* Update interface
2019-11-09 11:46:09 +01:00
Github Actions 6aebeec028 [CI Skip] 0.96.0-beta.38 2019-11-08 13:53:46 +00:00
Amaury Martiny 5b5d0a3fb8 Add AuthorityList types (#1557) 2019-11-08 14:45:48 +01:00
Github Actions d405ed1005 [CI Skip] 0.96.0-beta.37 2019-11-07 20:58:26 +00:00
Jaco Greeff 2be97310d3 Add runnersup to elections (#1555) 2019-11-07 21:51:54 +01:00
Github Actions 1f44e4473f [CI Skip] 0.96.0-beta.36 2019-11-07 16:41:38 +00:00
Jaco Greeff 022c7ea645 Swap internal derives to use api.derive.* (#1553)
* Swap internal derives to use api.derive.*

* Rx vs normal decorate

* Small cleanups

* Res-use sessions

* Cleanup types

* Fix refCount lost subs

* Small cleanups
2019-11-07 17:34:53 +01:00
Github Actions fe078ca67c [CI Skip] 0.96.0-beta.35 2019-11-07 09:54:24 +00:00
Keith Ingram 479c742471 Error in ABI message assertion (#1552)
* combine values

* undefined name
2019-11-07 10:47:56 +01:00
Github Actions a52c629ecf [CI Skip] 0.96.0-beta.34 2019-11-06 22:03:58 +00:00
Jaco Greeff c077d0f2e7 Bump deps (#1550)
* Bump deps

* Updates
2019-11-06 22:56:52 +01:00
Github Actions 679994a6fb [CI Skip] 0.96.0-beta.33 2019-11-06 16:25:35 +00:00
Jaco Greeff 8cc256fdcf Derive drr doesn't have delay (#1548) 2019-11-06 17:19:12 +01:00
Github Actions b6b2f2beec [CI Skip] 0.96.0-beta.32 2019-11-05 19:04:14 +00:00
Keith Ingram 6075a21efb Handle AccountId contract params (#1547)
* combine values

* handle accountids

* cleanup

* cleanup

* force ci
2019-11-05 19:58:30 +01:00
Github Actions fa98f8f06d [CI Skip] 0.96.0-beta.31 2019-11-05 14:29:22 +00:00
Github Actions ad570cac5a [CI Skip] 0.96.0-beta.30 2019-11-05 14:20:57 +00:00
Jaco Greeff cb32acc409 Update .123trigger 2019-11-05 14:42:35 +01:00
Jaco Greeff 3998b1bcbd Whack derive memo (#1546)
* Whack derive memo

* Bump common
2019-11-05 14:36:53 +01:00
Github Actions 3fd03b2498 [CI Skip] 0.96.0-beta.29 2019-11-05 12:27:24 +00:00
Keith Ingram cba5710fec Return Codec from contracts.call (#1545)
* combine values

* Contracts with Data return

* Data toU8a()

* return data from contracts.call

* create Data

* cleanup
2019-11-05 12:56:49 +01:00
Github Actions 1ffdba03b3 [CI Skip] 0.96.0-beta.28 2019-11-05 09:33:26 +00:00
Xat_MassacrE fcf89d1501 Fix packages/types/src/codec/utils/encodeTypes.ts encodeSubTypes bug (#1544) 2019-11-05 10:27:00 +01:00
Github Actions 56dc116d92 [CI Skip] 0.96.0-beta.27 2019-11-03 22:54:20 +00:00
Jaco Greeff 2371d6a29c Remove double-up-drr (memo vs rpc) (#1541)
* Remove inner memo (no double-up on stringify)

* Validators-specific query
2019-11-03 23:47:55 +01:00
Github Actions d39878c875 [CI Skip] 0.96.0-beta.26 2019-11-03 16:21:18 +00:00
Jaco Greeff 287ceb2ded Contracts with Data return (#1540)
* Contracts with Data return

* Data toU8a()
2019-11-03 17:15:21 +01:00
Github Actions 7c04be6abc [CI Skip] 0.96.0-beta.25 2019-11-03 12:34:59 +00:00
Jaco Greeff e601ae27a1 Re-add derive memo (def. has an impact) (#1539) 2019-11-03 13:28:42 +01:00
Github Actions 487ad475c7 [CI Skip] 0.96.0-beta.24 2019-11-03 10:45:00 +00:00
Jaco Greeff 506b042f8c Remove derive memos (#1538)
* Remove derive memos

* Remove outer memo

* Over-eager replace
2019-11-03 11:38:36 +01:00
Github Actions 0e037de1b1 [CI Skip] 0.96.0-beta.23 2019-11-02 23:18:33 +00:00
Jaco Greeff 8d3cb72189 currentEraPointsEarned not on V1 2019-11-03 00:12:15 +01:00
Github Actions f8b9615e6b [CI Skip] 0.96.0-beta.22 2019-11-02 22:16:32 +00:00
Jaco Greeff 7cc961f789 Staking overview derive (#1537)
* Staking overview derive

* Expand derives

* Extract currentIndex/currentEra

* WIP

* Controllers opt

* Add memo

* Memomize the whole lot

* Doc building fixes

* Doc fixes #2
2019-11-02 23:10:10 +01:00
Github Actions 1d92b7bead [CI Skip] 0.96.0-beta.21 2019-11-01 16:22:40 +00:00
Jaco Greeff 2c44b5ca8a Add isVesting & vestingTotal to balances derive (#1536) 2019-11-01 17:16:26 +01:00
Github Actions 8d9b50a004 [CI Skip] 0.96.0-beta.20 2019-11-01 15:48:36 +00:00
Jaco Greeff d41f6ec3ef Don't re-create locks empty type, return breakdown (#1524)
* Don't re-create locks empty type

* Return the actual inv. lock information
2019-11-01 16:42:19 +01:00
Github Actions 6aff7db89a [CI Skip] 0.96.0-beta.19 2019-11-01 13:24:29 +00:00
Jaco Greeff dc105e6b31 Sub/unsub cleanups (#1535)
* Sub/unsub cleanups

* drr full idAndIndex

* Memo on nick call

* refCountDelay

* Remove scheduler param, always asap

* Flatten

* Test cleanups

* Make tests pass

* Remove logs

* Drop nick memo

* sourceConnection.unsubscribe

* Small cleanups
2019-11-01 14:17:47 +01:00
Github Actions f41ad2eee7 [CI Skip] 0.96.0-beta.18 2019-10-31 18:39:41 +00:00
Jaco Greeff 276da86dbe Expand heartbeats with num blocks (#1534) 2019-10-31 19:32:53 +01:00
Github Actions 5aa64dddf3 [CI Skip] 0.96.0-beta.17 2019-10-31 17:53:26 +00:00
Keith Ingram cf01c41b33 Contract API for Rx/promises (#1520)
* wip with rxjs/promise

* add outcome process

* contract call decoding solved

* restore messages as dict, cleanup

* linting

* linting

* type fixes
2019-10-31 19:47:14 +02:00
Github Actions 64bc3fbffa [CI Skip] 0.96.0-beta.16 2019-10-31 09:54:54 +00:00
Jaco Greeff 453aacb669 derive.accounts.info returns accountId/Index (#1533)
* derive.accounts.info returns accountId/Index

* Swap all idAndIndex to account.info
2019-10-31 10:48:29 +01:00
Github Actions 2f350e3bc2 [CI Skip] 0.96.0-beta.15 2019-10-30 13:23:24 +00:00
Jaco Greeff 8379689eaa Cleanup staking info (#1532)
* Cleanup staking info

* Cache calls

* V1, V2 (Aura & Babe) tested & working

* Hopefully pacify docs build

* Second time lucky?

* Third time lucky?

* Fouth time
2019-10-30 14:15:20 +01:00
Github Actions 2676909cd0 [CI Skip] 0.96.0-beta.14 2019-10-29 23:34:22 +00:00
Jaco Greeff a53c924248 Council -> consts (#1531)
* Council -> consts

* Additional info, expose Balance

* Types
2019-10-30 00:28:40 +01:00
Github Actions a044a959b6 [CI Skip] 0.96.0-beta.13 2019-10-29 22:32:02 +00:00
Jaco Greeff 7555a3a7ce Use currentEraStartSessionIndex for babe (#1530)
* Use currentEraStartSessionIndex for babe

* Update WithdrawReasons
2019-10-29 23:25:45 +01:00
Github Actions 0fac973645 [CI Skip] 0.96.0-beta.12 2019-10-29 21:57:20 +00:00
Jaco Greeff f533f51003 Update for latest 2.x ForceAlways (#1529) 2019-10-29 22:50:46 +01:00
Github Actions b4c0875ebf [CI Skip] 0.96.0-beta.11 2019-10-29 19:10:54 +00:00
Jaco Greeff 8cab499a83 Update .123trigger 2019-10-29 20:04:09 +01:00
Github Actions f2daae3986 [CI Skip] 0.96.0-beta.10 2019-10-29 16:56:41 +00:00
Jaco Greeff 41cf32c808 Flatten more combineLatest into queryMulti (#1528) 2019-10-29 17:49:42 +01:00
Github Actions b0e970a815 [CI Skip] 0.96.0-beta.9 2019-10-29 11:28:14 +00:00
Jaco Greeff fed9e8f7de Retrieve heartbeats for all validators (#1527)
* Retrieve heartbeats for all validators

* Tested, confirmed working
2019-10-29 12:21:49 +01:00
Github Actions d2e2d3be76 [CI Skip] 0.96.0-beta.8 2019-10-28 16:22:49 +00:00
Jaco Greeff 07b9cb1a16 Use GH_PAT is checkout action 2019-10-28 17:15:52 +01:00
Github Actions 4f24af6d8a [CI Skip] 0.96.0-beta.7 2019-10-28 13:32:14 +00:00
Jaco Greeff a30d467618 Split candidates to separate query (#1526)
* Split candidates to seperate query

* Split only candidates
2019-10-28 14:25:34 +01:00
Github Actions 3daf44bac2 [CI Skip] 0.96.0-beta.6 2019-10-28 10:20:45 +00:00
Jaco Greeff b69d8ec789 Account info derive (#1523) 2019-10-28 11:14:21 +01:00
Github Actions d1b2664071 [CI Skip] 0.96.0-beta.5 2019-10-27 12:01:45 +00:00
Jaco Greeff 8d0f20c2a7 Remove Parity Signer signature hack (#1522) 2019-10-27 12:55:01 +01:00
Github Actions f200a348de [CI Skip] 0.96.0-beta.4 2019-10-26 20:36:49 +00:00
Jaco Greeff fae67e72ee Parity Signer v4 work-around (#1521) 2019-10-26 22:30:40 +02:00
Github Actions a23e71bfb0 [CI Skip] 0.96.0-beta.3 2019-10-26 10:23:58 +00:00
Jaco Greeff 6e96fd6a55 ABI selector updates (#1517) 2019-10-26 13:17:36 +03:00
Github Actions 3ba2bbd581 [CI Skip] 0.96.0-beta.2 2019-10-26 08:38:49 +00:00
Jaco Greeff f8084c2d12 Derive for electionsPhragmen (#1519) 2019-10-26 10:32:11 +02:00
Github Actions 1ad552f03d [CI Skip] 0.96.0-beta.1 2019-10-25 15:11:30 +00:00
Jaco Greeff 6b8d0207a6 Swap to normal publish 2019-10-25 17:04:56 +02:00
208 changed files with 3051 additions and 1814 deletions
+1 -1
View File
@@ -1 +1 @@
6
8
+3 -1
View File
@@ -14,6 +14,8 @@ jobs:
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:
@@ -27,7 +29,7 @@ jobs:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
yarn install --frozen-lockfile
CI_NO_BETA=true yarn polkadot-dev-ghact-build
yarn polkadot-dev-ghact-build
build_docs:
name: Build Docs
+14
View File
@@ -1,3 +1,17 @@
# 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)
+1 -1
View File
@@ -9,5 +9,5 @@
"packages": [
"packages/*"
],
"version": "0.95.2"
"version": "0.96.1"
}
+6 -6
View File
@@ -1,5 +1,5 @@
{
"version": "0.95.2",
"version": "0.96.1",
"private": true,
"engines": {
"yarn": "^1.10.1"
@@ -9,7 +9,7 @@
],
"resolutions": {
"babel-core": "^7.0.0-bridge.0",
"typescript": "^3.6.4"
"typescript": "^3.7.2"
},
"scripts": {
"build": "yarn build:interfaces && polkadot-dev-build-ts",
@@ -28,10 +28,10 @@
"test:watch": "jest --coverage --watch"
},
"devDependencies": {
"@babel/core": "^7.6.4",
"@babel/register": "^7.6.2",
"@babel/core": "^7.7.0",
"@babel/register": "^7.7.0",
"@babel/runtime": "^7.6.3",
"@polkadot/dev": "^0.32.0-beta.11",
"@polkadot/ts": "^0.1.82"
"@polkadot/dev": "^0.32.0-beta.13",
"@polkadot/ts": "^0.1.84"
}
}
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-contract",
"version": "0.95.2",
"version": "0.96.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.3",
"@polkadot/types": "^0.95.2"
"@babel/runtime": "^7.7.1",
"@polkadot/types": "^0.96.1"
}
}
+5 -5
View File
@@ -2,21 +2,21 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import erc20Abi from '../test/contracts/Erc20.json';
import incrementerAbi from '../test/contracts/incrementer.json';
import { Abi } from '.';
describe('Abi', (): void => {
describe('erc20', (): void => {
describe('incrementer', (): void => {
let abi: Abi;
beforeEach((): void => {
abi = new Abi(erc20Abi);
abi = new Abi(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']
);
});
});
+15 -10
View File
@@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ContractABI, ContractABIPre, ContractABIFn, InterfaceAbi, AbiMessages } from './types';
import { AbiConstructors, AbiMessages, ContractABI, ContractABIPre, ContractABIFn, InterfaceAbi } from './types';
import { stringCamelCase } from '@polkadot/util';
import ContractRegistry from './ContractRegistry';
@@ -10,11 +10,11 @@ import ContractRegistry from './ContractRegistry';
export default class ContractAbi extends ContractRegistry implements InterfaceAbi {
public readonly abi: ContractABI;
public readonly constructors: ContractABIFn[];
public readonly constructors: AbiConstructors;
public readonly messages: AbiMessages = {};
public readonly messages: AbiMessages;
public constructor (abi: ContractABIPre) {
constructor (abi: ContractABIPre) {
super(abi);
[this.abi, this.constructors, this.messages] = this.decodeAbi(abi);
}
@@ -25,16 +25,21 @@ export default class ContractAbi extends ContractRegistry implements InterfaceAb
const abi = this.convertAbi(abiPre);
const constructors = abi.contract.constructors.map(
(constructor, index): ContractABIFn => {
return this.createMethod(`constructor ${index}`, constructor);
return this.createMessage(`constructor ${index}`, constructor);
}
);
const messages: AbiMessages = {};
abi.contract.messages.forEach((method): void => {
const name = stringCamelCase(method.name);
const messages: AbiMessages = abi.contract.messages.reduce(
(result: AbiMessages, message): AbiMessages => {
const name = stringCamelCase(message.name);
messages[name] = this.createMethod(`messages.${name}`, method);
});
return {
...result,
[name]: this.createMessage(`messages.${name}`, message)
};
},
{}
);
return [abi, constructors, messages];
}
+73 -29
View File
@@ -2,14 +2,54 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { CodecArg, TypeDef } from '@polkadot/types/types';
import { ContractABIArgBasePre, ContractABIContract, ContractABIContractPre, ContractABIEvent, ContractABIEventPre, ContractABIFn, ContractABIFnArg, ContractABIMethod, ContractABIMethodBase, ContractABIMethodPre, ContractABI, ContractABIPre, ContractABIRange, ContractABIRangePre, ContractABIStorage, ContractABIStorageLayout, ContractABIStorageLayoutPre, ContractABIStoragePre, ContractABIStorageStruct, ContractABIStorageStructPre, ContractABITypePre } from './types';
import { Compact } from '@polkadot/types';
import { CodecArg, Constructor, 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, isNumber, isString, isNull, isObject, isUndefined, stringCamelCase } from '@polkadot/util';
import { assert, hexToU8a, isNumber, isString, isNull, isObject, isUndefined, stringCamelCase, isHex, hexToNumber } from '@polkadot/util';
import MetaRegistry from './MetaRegistry';
import { createArgClass } from './method';
// 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 (fnname: string, input: ContractABIMessageCommon['selector']): u32 {
if (isNumber(input)) {
return createType('u32', input);
} else if (isHex(input)) {
return createType('u32', hexToU8a(input));
} else if (typeof input === 'string') {
try {
const array = JSON.parse(input);
assert(array.length === 4, `${fnname}: Invalid selector length`);
return createType('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 (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.displayName || encodeType(type);
return base;
}, baseDef)
)
);
}
export default class ContractRegistry extends MetaRegistry {
// Contract ABI helpers
@@ -26,7 +66,7 @@ export default class ContractRegistry extends MetaRegistry {
}
public validateConstructors ({ contract: { constructors } }: ContractABIPre): void {
constructors.forEach((constructor: ContractABIMethodPre, index): 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`);
@@ -35,41 +75,46 @@ export default class ContractRegistry extends MetaRegistry {
});
}
public validateMethods ({ contract: { messages } }: ContractABIPre): void {
messages.forEach((method): void => {
const unknownKeys = Object.keys(method).filter((key): boolean => !['args', 'docs', 'mutates', 'name', 'selector', 'return_type'].includes(key));
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.${method.name}`);
const { name, selector, return_type: returnType } = method;
assert(isNumber(name) && isString(this.stringAt(name)), `Expected name for messages.${method.name}`);
assert(isNumber(selector), `Expected selector for messages.${method.name}`);
assert(isNull(returnType) || (isNumber(returnType.ty) && isObject(this.typeDefAt(returnType.ty))), `Expected return_type for messages.${method.name}`);
assert(unknownKeys.length === 0, `Unknown keys ${unknownKeys.join(', ')} found in ABI args for messages.${message.name}`);
this.validateArgs(`messages.${method.name}`, method.args);
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(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.validateMethods(abi);
this.validateMessages(abi);
}
public createMethod (name: string, method: Partial<ContractABIMethod> & ContractABIMethodBase): ContractABIFn {
const args = method.args.map(({ name, type }): ContractABIFnArg => {
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(args, isUndefined(method.selector) ? {} : { __selector: 'u32' });
const baseStruct: { [index: string]: any } = { __selector: method.selector };
const Clazz = createArgClass(args, isUndefined(message.selector) ? {} : { __selector: 'u32' });
const baseStruct: { [index: string]: any } = { __selector: isUndefined(message.selector) ? undefined : parseSelector(name, message.selector) };
const encoder = (...params: CodecArg[]): Uint8Array => {
assert(params.length === args.length, `Expected ${args.length} arguments to contract ${name}, found ${params.length}`);
@@ -87,9 +132,8 @@ export default class ContractRegistry extends MetaRegistry {
const fn = (encoder as ContractABIFn);
fn.args = args;
fn.isConstant = !(method.mutates || false);
fn.type = method.returnType || null;
fn.isConstant = !(message.mutates || false);
fn.type = message.returnType || null;
return fn;
}
@@ -112,7 +156,7 @@ export default class ContractRegistry extends MetaRegistry {
public convertContract ({ constructors, messages, name, events, ...contract }: ContractABIContractPre): ContractABIContract {
return {
constructors: this.convertConstructors(constructors),
messages: messages.map(method => this.convertMethod(method)),
messages: messages.map(message => this.convertMessage(message)),
name: this.stringAt(name),
...(events
? { events: events.map(event => this.convertEvent(event)) }
@@ -121,17 +165,17 @@ export default class ContractRegistry extends MetaRegistry {
};
}
public convertConstructors (constructors: ContractABIMethodPre[]): ContractABIMethod[] {
public convertConstructors (constructors: ContractABIMessagePre[]): ContractABIMessage[] {
return constructors.map(
(constructor: ContractABIMethodPre): ContractABIMethod => {
return this.convertMethod(constructor);
(constructor: ContractABIMessagePre): ContractABIMessage => {
return this.convertMessage(constructor);
}
);
}
public convertMethod ({ args, name, return_type: returnType, ...method }: ContractABIMethodPre): ContractABIMethod {
public convertMessage ({ args, name, return_type: returnType, ...message }: ContractABIMessagePre): ContractABIMessage {
return {
...method,
...message,
args: this.convertArgs(args),
name: this.stringAt(name),
returnType: returnType ? this.convertType(returnType) : null
+2 -2
View File
@@ -40,7 +40,7 @@ class MetadataRegistryLookup {
public typeDefs: TypeDef[] = [];
public constructor ({ registry: { strings, types } }: MetaRegistryJson) {
constructor ({ registry: { strings, types } }: MetaRegistryJson) {
this._strings = strings;
this._types = types;
}
@@ -102,7 +102,7 @@ class MetadataRegistryLookup {
}
export default class MetaRegistry extends MetadataRegistryLookup {
public constructor (json: MetaRegistryJson) {
constructor (json: MetaRegistryJson) {
super(json);
// Generate TypeDefs for each provided registry type
-31
View File
@@ -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, ContractABIPre, 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: ContractABIPre | 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');
}
}
-72
View File
@@ -1,72 +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 { ContractABIPre } 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 { assert } from '@polkadot/util';
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: ContractABIPre | Abi, codeHash: string | Hash) {
super(api, abi);
this.codeHash = createType('Hash', codeHash);
}
public deployContract (constructorIndex = 0, endowment: number | BN, maxGas: number | BN, ...params: any[]): BlueprintCreate {
assert(!!this.abi.constructors[constructorIndex], `Specified constructor index ${constructorIndex} does not exist`);
const signAndSend = (account: IKeyringPair | string | AccountId | Address): BlueprintCreateResultSubscription => {
return this.apiContracts
.create(endowment, maxGas, this.codeHash, this.abi.constructors[constructorIndex](...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);
}
}
-83
View File
@@ -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 { ContractABIPre } 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: ContractABIPre | 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);
}
}
-41
View File
@@ -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 { ContractABIPre, 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: ContractABIPre | Abi, address: string | AccountId | Address) {
super(api, abi);
this.address = createType('Address', address);
Object.entries(this.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-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 { 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('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);
}
}
+71
View File
@@ -0,0 +1,71 @@
// 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 { 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-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 { 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'
? (account: IKeyringPair | string | AccountId | Address): ContractCallResult<'rpc'> => {
return this.rpcContractsCall(
createType('ContractCallRequest', {
origin: account,
dest: this.address.toString(),
value,
gasLimit,
inputData: fn(...params)
})
)
.pipe(
map((result: ContractExecResult): ContractCallOutcome =>
this.createOutcome(result, createType('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(data, message.returnType)
: createType('Data', 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('Address', address);
}
}
+7
View File
@@ -0,0 +1,7 @@
// Copyright 2017-2019 @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';
+74
View File
@@ -0,0 +1,74 @@
// Copyright 2017-2019 @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 { assert, 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>;
constructor (api: ApiObject<ApiType>, abi: ContractABIPre | Abi, decorateMethod: DecorateMethod<ApiType>) {
this.abi = abi instanceof Abi
? abi
: new Abi(abi);
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> {
protected get rpcContractsCall (): DecoratedRpc<'rxjs', RpcInterface>['contracts']['call'] {
return this.api.rx.rpc.contracts.call;
}
constructor (api: ApiObject<ApiType>, abi: ContractABIPre | Abi, decorateMethod: DecorateMethod<ApiType>) {
super(api, abi, decorateMethod);
assert(this.api.rx.rpc.contracts && this.api.rx.tx.contracts.call, 'You need to connect to a node with the contracts module, the metadata does not enable api.rpc.contracts.call on this instance');
}
}
+2 -3
View File
@@ -3,6 +3,5 @@
// 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';
-20
View File
@@ -1,20 +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 { Constructor } from '@polkadot/types/types';
import { ContractABIFnArg } from './types';
import { createClass, encodeType } from '@polkadot/types';
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] = encodeType(type);
return base;
}, baseDef)
)
);
}
@@ -0,0 +1,18 @@
// 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 { 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-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 { 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-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 } 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-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.
export { default as PromiseBlueprint } from './PromiseBlueprint';
export { default as PromiseCode } from './PromiseCode';
export { default as PromiseContract } from './PromiseContract';
@@ -0,0 +1,18 @@
// 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 { 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);
}
}
+17
View File
@@ -0,0 +1,17 @@
// 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 { 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-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 } 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);
}
}
+7
View File
@@ -0,0 +1,7 @@
// 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.
export { default as RxBlueprint } from './RxBlueprint';
export { default as RxCode } from './RxCode';
export { default as RxContract } from './RxContract';
+49 -27
View File
@@ -2,17 +2,26 @@
// 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 ContractBase<ApiType extends ApiTypes> {
readonly abi: InterfaceAbi;
readonly api: ApiObject<ApiType>;
readonly decorateMethod: DecorateMethod<ApiType>;
getMessage: (name: string) => ContractMessage;
messages: ContractMessage[];
}
export interface ContractABITypePre {
ty: TypeIndex;
display_name: StringIndex[];
@@ -28,31 +37,31 @@ export interface ContractABIArgBase {
type: TypeDef;
}
export type ContractABIMethodArgPre = ContractABIArgBasePre;
export type ContractABIMessageArgPre = ContractABIArgBasePre;
export type ContractABIMethodArg = ContractABIArgBase;
export type ContractABIMessageArg = ContractABIArgBase;
export interface ContractABIMethodBase {
args: ContractABIMethodArg[];
export interface ContractABIMessageBase {
args: ContractABIMessageArg[];
}
export interface ContractABIMethodBasePre {
args: ContractABIMethodArgPre[];
export interface ContractABIMessageBasePre {
args: ContractABIMessageArgPre[];
}
export interface ContractABIMethodCommon {
export interface ContractABIMessageCommon {
docs?: ContractABIDocs;
mutates?: boolean;
selector: number;
selector: string | number;
}
export interface ContractABIMethodPre extends ContractABIMethodCommon, ContractABIMethodBasePre {
export interface ContractABIMessagePre extends ContractABIMessageCommon, ContractABIMessageBasePre {
name: StringIndex;
return_type: ContractABITypePre | null;
}
export interface ContractABIMethod extends ContractABIMethodCommon {
args: ContractABIMethodArg[];
export interface ContractABIMessage extends ContractABIMessageCommon {
args: ContractABIMessageArg[];
name: string;
returnType: TypeDef | null;
}
@@ -62,16 +71,16 @@ export interface ContractABIContractCommon {
}
export interface ContractABIContractPre extends ContractABIContractCommon {
constructors: ContractABIMethodPre[];
messages: ContractABIMethodPre[];
constructors: ContractABIMessagePre[];
messages: ContractABIMessagePre[];
name: StringIndex;
events?: ContractABIEventPre[];
docs?: ContractABIDocs;
}
export interface ContractABIContract extends ContractABIContractCommon {
constructors: ContractABIMethod[];
messages: ContractABIMethod[];
constructors: ContractABIMessage[];
messages: ContractABIMessage[];
name: string;
events?: ContractABIEvent[];
docs?: ContractABIDocs;
@@ -121,7 +130,8 @@ export interface ContractABIEvent {
}
export interface ContractABIRangeBase {
'range.offset': number[];
// can be number[] (old) or hex (new)
'range.offset': number[] | string;
'range.len': number;
}
@@ -161,20 +171,22 @@ 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 constructors: 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;
}
@@ -183,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;
}
+21
View File
@@ -0,0 +1,21 @@
// Copyright 2017-2019 @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, TypeDefInfo, TypeDef } from '@polkadot/types/types';
import { Data, Option, createClass } from '@polkadot/types';
import { createTypeUnsafe } from '@polkadot/types/codec';
export function formatData (data: Data, { info, type }: TypeDef): Codec {
const u8a = data.toU8a();
if (info === TypeDefInfo.Option) {
return new Option(
createClass(type),
createTypeUnsafe(type, [u8a], true)
);
}
return createTypeUnsafe(type, [u8a], true);
}
@@ -1,15 +1,15 @@
[
{
"info": 9,
"type": "{ \"total_supply\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u128>\"} }<u128>\", \"balances\": \"{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\"} }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"u128\"} }<([u8;32]), u128>)\", \"Removed\": \"Null\"} }<([u8;32]), u128>>\"} }<([u8;32]), u128>\", \"allowances\": \"{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\"} }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }<(AccountId, AccountId), u128>)\", \"Removed\": \"Null\"} }<(AccountId, AccountId), u128>>\"} }<(AccountId, AccountId), u128>\"} }",
"type": "{ \"total_supply\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u128>\" }<u128>\", \"balances\": \"{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\" }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"u128\" }<([u8;32]), u128>)\", \"Removed\": \"Null\"\" }\" }<([u8;32]), u128>>\" }<([u8;32]), u128>\", \"allowances\": \"{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\" }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }<(AccountId, AccountId), u128>)\", \"Removed\": \"Null\"\" }\" }<(AccountId, AccountId), u128>>\" }<(AccountId, AccountId), u128>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u128>\"} }",
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u128>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"type": "{ \"cell\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -54,15 +54,15 @@
},
{
"info": 9,
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\"} }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"u128\"} }<([u8;32]), u128>)\", \"Removed\": \"Null\"} }<([u8;32]), u128>>\"} }",
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\" }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"u128\" }<([u8;32]), u128>)\", \"Removed\": \"Null\"\" }\" }<([u8;32]), u128>>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }",
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"type": "{ \"cell\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -107,7 +107,7 @@
},
{
"info": 9,
"type": "{ \"cells_key\": \"([u8;32])\"} }",
"type": "{ \"cells_key\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -136,7 +136,7 @@
"params": [
{
"info": 3,
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"u128\"} }<([u8;32]), u128>)\", \"Removed\": \"Null\"} }",
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"u128\" }<([u8;32]), u128>)\", \"Removed\": \"Null\"\" }\" }",
"sub": [
{
"info": 10,
@@ -144,7 +144,7 @@
"sub": [
{
"info": 9,
"type": "{ \"key\": \"AccountId\", \"val\": \"u128\"} }",
"type": "{ \"key\": \"AccountId\", \"val\": \"u128\" }",
"sub": [
{
"info": 10,
@@ -205,7 +205,7 @@
"index": 0
}
],
"type": "({ \"key\": \"AccountId\", \"val\": \"u128\"} }<([u8;32]), u128>)"
"type": "({ \"key\": \"AccountId\", \"val\": \"u128\" }<([u8;32]), u128>)"
},
{
"info": 6,
@@ -278,15 +278,15 @@
},
{
"info": 9,
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\"} }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }<(AccountId, AccountId), u128>)\", \"Removed\": \"Null\"} }<(AccountId, AccountId), u128>>\"} }",
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\" }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }<(AccountId, AccountId), u128>)\", \"Removed\": \"Null\"\" }\" }<(AccountId, AccountId), u128>>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }",
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"type": "{ \"cell\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -331,7 +331,7 @@
},
{
"info": 9,
"type": "{ \"cells_key\": \"([u8;32])\"} }",
"type": "{ \"cells_key\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -360,7 +360,7 @@
"params": [
{
"info": 3,
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }<(AccountId, AccountId), u128>)\", \"Removed\": \"Null\"} }",
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }<(AccountId, AccountId), u128>)\", \"Removed\": \"Null\"\" }\" }",
"sub": [
{
"info": 10,
@@ -368,7 +368,7 @@
"sub": [
{
"info": 9,
"type": "{ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }",
"type": "{ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }",
"sub": [
{
"info": 10,
@@ -484,7 +484,7 @@
"index": 0
}
],
"type": "({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }<(AccountId, AccountId), u128>)"
"type": "({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }<(AccountId, AccountId), u128>)"
},
{
"info": 6,
@@ -615,11 +615,11 @@
},
{
"info": 9,
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u128>\"} }",
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u128>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"type": "{ \"cell\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -668,7 +668,7 @@
},
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"type": "{ \"cell\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -740,15 +740,15 @@
},
{
"info": 9,
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\"} }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"u128\"} }<([u8;32]), u128>)\", \"Removed\": \"Null\"} }<([u8;32]), u128>>\"} }",
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\" }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"u128\" }<([u8;32]), u128>)\", \"Removed\": \"Null\"\" }\" }<([u8;32]), u128>>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }",
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"type": "{ \"cell\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -793,7 +793,7 @@
},
{
"info": 9,
"type": "{ \"cells_key\": \"([u8;32])\"} }",
"type": "{ \"cells_key\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -822,7 +822,7 @@
"params": [
{
"info": 3,
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"u128\"} }<([u8;32]), u128>)\", \"Removed\": \"Null\"} }",
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"u128\" }<([u8;32]), u128>)\", \"Removed\": \"Null\"\" }\" }",
"sub": [
{
"info": 10,
@@ -830,7 +830,7 @@
"sub": [
{
"info": 9,
"type": "{ \"key\": \"AccountId\", \"val\": \"u128\"} }",
"type": "{ \"key\": \"AccountId\", \"val\": \"u128\" }",
"sub": [
{
"info": 10,
@@ -891,7 +891,7 @@
"index": 0
}
],
"type": "({ \"key\": \"AccountId\", \"val\": \"u128\"} }<([u8;32]), u128>)"
"type": "({ \"key\": \"AccountId\", \"val\": \"u128\" }<([u8;32]), u128>)"
},
{
"info": 6,
@@ -985,11 +985,11 @@
},
{
"info": 9,
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }",
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"type": "{ \"cell\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -1038,7 +1038,7 @@
},
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"type": "{ \"cell\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -1073,7 +1073,7 @@
},
{
"info": 9,
"type": "{ \"cells_key\": \"([u8;32])\"} }",
"type": "{ \"cells_key\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -1102,7 +1102,7 @@
"params": [
{
"info": 3,
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"u128\"} }<([u8;32]), u128>)\", \"Removed\": \"Null\"} }",
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"u128\" }<([u8;32]), u128>)\", \"Removed\": \"Null\"\" }\" }",
"sub": [
{
"info": 10,
@@ -1110,7 +1110,7 @@
"sub": [
{
"info": 9,
"type": "{ \"key\": \"AccountId\", \"val\": \"u128\"} }",
"type": "{ \"key\": \"AccountId\", \"val\": \"u128\" }",
"sub": [
{
"info": 10,
@@ -1171,7 +1171,7 @@
"index": 0
}
],
"type": "({ \"key\": \"AccountId\", \"val\": \"u128\"} }<([u8;32]), u128>)"
"type": "({ \"key\": \"AccountId\", \"val\": \"u128\" }<([u8;32]), u128>)"
},
{
"info": 6,
@@ -1213,7 +1213,7 @@
},
{
"info": 3,
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"u128\"} }<([u8;32]), u128>)\", \"Removed\": \"Null\"} }",
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"u128\" }<([u8;32]), u128>)\", \"Removed\": \"Null\"\" }\" }",
"sub": [
{
"info": 10,
@@ -1221,7 +1221,7 @@
"sub": [
{
"info": 9,
"type": "{ \"key\": \"AccountId\", \"val\": \"u128\"} }",
"type": "{ \"key\": \"AccountId\", \"val\": \"u128\" }",
"sub": [
{
"info": 10,
@@ -1282,7 +1282,7 @@
"index": 0
}
],
"type": "({ \"key\": \"AccountId\", \"val\": \"u128\"} }<([u8;32]), u128>)"
"type": "({ \"key\": \"AccountId\", \"val\": \"u128\" }<([u8;32]), u128>)"
},
{
"info": 6,
@@ -1322,7 +1322,7 @@
},
{
"info": 9,
"type": "{ \"key\": \"AccountId\", \"val\": \"u128\"} }",
"type": "{ \"key\": \"AccountId\", \"val\": \"u128\" }",
"sub": [
{
"info": 10,
@@ -1383,15 +1383,15 @@
},
{
"info": 9,
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\"} }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }<(AccountId, AccountId), u128>)\", \"Removed\": \"Null\"} }<(AccountId, AccountId), u128>>\"} }",
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\" }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }<(AccountId, AccountId), u128>)\", \"Removed\": \"Null\"\" }\" }<(AccountId, AccountId), u128>>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }",
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"type": "{ \"cell\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -1436,7 +1436,7 @@
},
{
"info": 9,
"type": "{ \"cells_key\": \"([u8;32])\"} }",
"type": "{ \"cells_key\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -1465,7 +1465,7 @@
"params": [
{
"info": 3,
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }<(AccountId, AccountId), u128>)\", \"Removed\": \"Null\"} }",
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }<(AccountId, AccountId), u128>)\", \"Removed\": \"Null\"\" }\" }",
"sub": [
{
"info": 10,
@@ -1473,7 +1473,7 @@
"sub": [
{
"info": 9,
"type": "{ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }",
"type": "{ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }",
"sub": [
{
"info": 10,
@@ -1589,7 +1589,7 @@
"index": 0
}
],
"type": "({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }<(AccountId, AccountId), u128>)"
"type": "({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }<(AccountId, AccountId), u128>)"
},
{
"info": 6,
@@ -1764,7 +1764,7 @@
},
{
"info": 9,
"type": "{ \"cells_key\": \"([u8;32])\"} }",
"type": "{ \"cells_key\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -1793,7 +1793,7 @@
"params": [
{
"info": 3,
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }<(AccountId, AccountId), u128>)\", \"Removed\": \"Null\"} }",
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }<(AccountId, AccountId), u128>)\", \"Removed\": \"Null\"\" }\" }",
"sub": [
{
"info": 10,
@@ -1801,7 +1801,7 @@
"sub": [
{
"info": 9,
"type": "{ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }",
"type": "{ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }",
"sub": [
{
"info": 10,
@@ -1917,7 +1917,7 @@
"index": 0
}
],
"type": "({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }<(AccountId, AccountId), u128>)"
"type": "({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }<(AccountId, AccountId), u128>)"
},
{
"info": 6,
@@ -1986,7 +1986,7 @@
},
{
"info": 3,
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }<(AccountId, AccountId), u128>)\", \"Removed\": \"Null\"} }",
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }<(AccountId, AccountId), u128>)\", \"Removed\": \"Null\"\" }\" }",
"sub": [
{
"info": 10,
@@ -1994,7 +1994,7 @@
"sub": [
{
"info": 9,
"type": "{ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }",
"type": "{ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }",
"sub": [
{
"info": 10,
@@ -2110,7 +2110,7 @@
"index": 0
}
],
"type": "({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }<(AccountId, AccountId), u128>)"
"type": "({ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }<(AccountId, AccountId), u128>)"
},
{
"info": 6,
@@ -2177,7 +2177,7 @@
},
{
"info": 9,
"type": "{ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\"} }",
"type": "{ \"key\": \"(AccountId, AccountId)\", \"val\": \"u128\" }",
"sub": [
{
"info": 10,
@@ -0,0 +1,188 @@
[
{
"info": 9,
"type": "{ \"value\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }<u32>\"} }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"sub": [
{
"info": 10,
"type": "([u8;32])",
"sub": [
{
"info": 12,
"type": "[u8;32]",
"ext": {
"length": 32,
"type": "u8"
},
"sub": {
"info": 6,
"type": "u8"
},
"index": 0
}
],
"name": "cell",
"namespace": "ink_core::storage::key"
}
],
"name": "cell",
"namespace": "ink_core::storage::cell::sync_cell",
"params": [
{
"info": 6,
"type": "u32"
}
]
}
],
"name": "value",
"namespace": "ink_core::storage::value",
"params": [
{
"info": 6,
"type": "u32"
}
]
}
],
"name": "Incrementer",
"namespace": "incrementer::normal"
},
{
"info": 9,
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"sub": [
{
"info": 10,
"type": "([u8;32])",
"sub": [
{
"info": 12,
"type": "[u8;32]",
"ext": {
"length": 32,
"type": "u8"
},
"sub": {
"info": 6,
"type": "u8"
},
"index": 0
}
],
"name": "cell",
"namespace": "ink_core::storage::key"
}
],
"name": "cell",
"namespace": "ink_core::storage::cell::sync_cell",
"params": [
{
"info": 6,
"type": "u32"
}
]
}
],
"name": "Value",
"namespace": "ink_core::storage::value",
"params": [
{
"info": 6,
"type": "u32"
}
]
},
{
"info": 6,
"type": "u32"
},
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"sub": [
{
"info": 10,
"type": "([u8;32])",
"sub": [
{
"info": 12,
"type": "[u8;32]",
"ext": {
"length": 32,
"type": "u8"
},
"sub": {
"info": 6,
"type": "u8"
},
"index": 0
}
],
"name": "cell",
"namespace": "ink_core::storage::key"
}
],
"name": "SyncCell",
"namespace": "ink_core::storage::cell::sync_cell",
"params": [
{
"info": 6,
"type": "u32"
}
]
},
{
"info": 10,
"type": "([u8;32])",
"sub": [
{
"info": 12,
"type": "[u8;32]",
"ext": {
"length": 32,
"type": "u8"
},
"sub": {
"info": 6,
"type": "u8"
},
"index": 0
}
],
"name": "Key",
"namespace": "ink_core::storage::key"
},
{
"info": 12,
"type": "[u8;32]",
"ext": {
"length": 32,
"type": "u8"
},
"sub": {
"info": 6,
"type": "u8"
}
},
{
"info": 6,
"type": "u8"
},
{
"info": 6,
"type": "bool"
}
]
@@ -1,19 +1,19 @@
[
{
"info": 9,
"type": "{ \"mutators\": \"{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\"} }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }>)\", \"Removed\": \"Null\"} }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }>>\"} }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }>\", \"vec\": \"{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }<u32>\", \"cells\": \"{ \"cells_key\": \"([u8;32])\"} }<i32>\"} }<i32>\"} }",
"type": "{ \"mutators\": \"{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\" }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }>)\", \"Removed\": \"Null\"\" }\" }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }>>\" }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }>\", \"vec\": \"{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }<u32>\", \"cells\": \"{ \"cells_key\": \"([u8;32])\" }<i32>\" }<i32>\" }",
"sub": [
{
"info": 9,
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\"} }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }>)\", \"Removed\": \"Null\"} }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }>>\"} }",
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\" }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }>)\", \"Removed\": \"Null\"\" }\" }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }>>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }",
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"type": "{ \"cell\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -58,7 +58,7 @@
},
{
"info": 9,
"type": "{ \"cells_key\": \"([u8;32])\"} }",
"type": "{ \"cells_key\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -87,7 +87,7 @@
"params": [
{
"info": 3,
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }>)\", \"Removed\": \"Null\"} }",
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }>)\", \"Removed\": \"Null\"\" }\" }",
"sub": [
{
"info": 10,
@@ -95,7 +95,7 @@
"sub": [
{
"info": 9,
"type": "{ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }",
"type": "{ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }",
"sub": [
{
"info": 10,
@@ -120,7 +120,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -183,7 +183,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -223,7 +223,7 @@
"index": 0
}
],
"type": "({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }>)"
"type": "({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }>)"
},
{
"info": 6,
@@ -257,7 +257,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -324,7 +324,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -364,15 +364,15 @@
},
{
"info": 9,
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }<u32>\", \"cells\": \"{ \"cells_key\": \"([u8;32])\"} }<i32>\"} }",
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }<u32>\", \"cells\": \"{ \"cells_key\": \"([u8;32])\" }<i32>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }",
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"type": "{ \"cell\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -417,7 +417,7 @@
},
{
"info": 9,
"type": "{ \"cells_key\": \"([u8;32])\"} }",
"type": "{ \"cells_key\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -466,15 +466,15 @@
},
{
"info": 9,
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\"} }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }>)\", \"Removed\": \"Null\"} }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }>>\"} }",
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }<u32>\", \"entries\": \"{ \"cells_key\": \"([u8;32])\" }<{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }>)\", \"Removed\": \"Null\"\" }\" }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }>>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }",
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"type": "{ \"cell\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -519,7 +519,7 @@
},
{
"info": 9,
"type": "{ \"cells_key\": \"([u8;32])\"} }",
"type": "{ \"cells_key\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -548,7 +548,7 @@
"params": [
{
"info": 3,
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }>)\", \"Removed\": \"Null\"} }",
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }>)\", \"Removed\": \"Null\"\" }\" }",
"sub": [
{
"info": 10,
@@ -556,7 +556,7 @@
"sub": [
{
"info": 9,
"type": "{ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }",
"type": "{ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }",
"sub": [
{
"info": 10,
@@ -581,7 +581,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -644,7 +644,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -684,7 +684,7 @@
"index": 0
}
],
"type": "({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }>)"
"type": "({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }>)"
},
{
"info": 6,
@@ -718,7 +718,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -785,7 +785,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -862,7 +862,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -919,11 +919,11 @@
},
{
"info": 9,
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }",
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"type": "{ \"cell\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -968,7 +968,7 @@
},
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"type": "{ \"cell\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -1024,7 +1024,7 @@
},
{
"info": 9,
"type": "{ \"cells_key\": \"([u8;32])\"} }",
"type": "{ \"cells_key\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -1053,7 +1053,7 @@
"params": [
{
"info": 3,
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }>)\", \"Removed\": \"Null\"} }",
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }>)\", \"Removed\": \"Null\"\" }\" }",
"sub": [
{
"info": 10,
@@ -1061,7 +1061,7 @@
"sub": [
{
"info": 9,
"type": "{ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }",
"type": "{ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }",
"sub": [
{
"info": 10,
@@ -1086,7 +1086,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -1149,7 +1149,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -1189,7 +1189,7 @@
"index": 0
}
],
"type": "({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }>)"
"type": "({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }>)"
},
{
"info": 6,
@@ -1223,7 +1223,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -1265,7 +1265,7 @@
},
{
"info": 3,
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }>)\", \"Removed\": \"Null\"} }",
"type": "{ \"_enum\": { \"Occupied\": \"({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }>)\", \"Removed\": \"Null\"\" }\" }",
"sub": [
{
"info": 10,
@@ -1273,7 +1273,7 @@
"sub": [
{
"info": 9,
"type": "{ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }",
"type": "{ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }",
"sub": [
{
"info": 10,
@@ -1298,7 +1298,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -1361,7 +1361,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -1401,7 +1401,7 @@
"index": 0
}
],
"type": "({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }>)"
"type": "({ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }<([u8;32]), { \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }>)"
},
{
"info": 6,
@@ -1435,7 +1435,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -1475,7 +1475,7 @@
},
{
"info": 9,
"type": "{ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }\"} }",
"type": "{ \"key\": \"AccountId\", \"val\": \"{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }\" }",
"sub": [
{
"info": 10,
@@ -1500,7 +1500,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -1563,7 +1563,7 @@
},
{
"info": 9,
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\"} }",
"type": "{ \"begin\": \"Option<u32><u32>\", \"end\": \"Option<u32><u32>\" }",
"sub": [
{
"info": 5,
@@ -1603,15 +1603,15 @@
},
{
"info": 9,
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }<u32>\", \"cells\": \"{ \"cells_key\": \"([u8;32])\"} }<i32>\"} }",
"type": "{ \"len\": \"{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }<u32>\", \"cells\": \"{ \"cells_key\": \"([u8;32])\" }<i32>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\"} }<u32>\"} }",
"type": "{ \"cell\": \"{ \"cell\": \"([u8;32])\" }<u32>\" }",
"sub": [
{
"info": 9,
"type": "{ \"cell\": \"([u8;32])\"} }",
"type": "{ \"cell\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -1656,7 +1656,7 @@
},
{
"info": 9,
"type": "{ \"cells_key\": \"([u8;32])\"} }",
"type": "{ \"cells_key\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -1705,7 +1705,7 @@
},
{
"info": 9,
"type": "{ \"cells_key\": \"([u8;32])\"} }",
"type": "{ \"cells_key\": \"([u8;32])\" }",
"sub": [
{
"info": 10,
@@ -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,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": []
}
}
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-derive",
"version": "0.95.2",
"version": "0.96.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.3",
"@polkadot/api": "^0.95.2",
"@polkadot/types": "^0.95.2"
"@babel/runtime": "^7.7.1",
"@polkadot/api": "^0.96.1",
"@polkadot/types": "^0.96.1"
},
"devDependencies": {
"@polkadot/keyring": "^1.6.1"
"@polkadot/keyring": "^1.7.0-beta.5"
}
}
+30 -32
View File
@@ -5,17 +5,41 @@
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 { 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 { drr } 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('AccountId', decoded);
return api.derive.accounts.idToIndex(accountId).pipe(
map((accountIndex): AccountIdAndIndex => [accountId, accountIndex] as AccountIdAndIndex)
);
}
const accountIndex = createType('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 (address?: Address | AccountId | AccountIndex | string | null): Observable<AccountIdAndIndex> =>
retrieve(api, address).pipe(drr());
}
+9 -10
View File
@@ -3,13 +3,13 @@
// 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 { drr } from '../util';
/**
* @name idToIndex
@@ -27,12 +27,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()
);
api.derive.accounts.indexes().pipe(
startWith({}),
map((indexes: AccountIndexes): AccountIndex | undefined =>
(indexes || {})[accountId.toString()]
),
drr()
);
}
@@ -6,3 +6,4 @@ export * from './idAndIndex';
export * from './idToIndex';
export * from './indexToId';
export * from './indexes';
export * from './info';
+10 -10
View File
@@ -10,7 +10,7 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
import { ENUMSET_SIZE } from '@polkadot/types/primitive/Generic/AccountIndex';
import { createType, ClassOf, Vec } from '@polkadot/types';
import { drr } from '../util/drr';
import { drr } from '../util';
/**
* @name indexToId
@@ -26,19 +26,19 @@ import { drr } from '../util/drr';
* ```
*/
export function indexToId (api: ApiInterfaceRx): (accountIndex: AccountIndex | string) => Observable<AccountId | undefined> {
const querySection = api.query.indices || api.query.balances;
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);
return (querySection.enumSet<Vec<AccountId>>(accountIndex.div(ENUMSET_SIZE)))
.pipe(
startWith([]),
map((accounts): AccountId | undefined =>
(accounts || [])[accountIndex.mod(ENUMSET_SIZE).toNumber()]
),
drr()
);
return querySection.enumSet<Vec<AccountId>>(accountIndex.div(ENUMSET_SIZE)).pipe(
startWith([]),
map((accounts): AccountId | undefined =>
(accounts || [])[accountIndex.mod(ENUMSET_SIZE).toNumber()]
),
drr()
);
};
}
+24 -27
View File
@@ -2,17 +2,16 @@
// 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 { drr } from '../util/drr';
export type AccountIndexes = Record<string, AccountIndex>;
import { drr } from '../util';
const enumsetSize = ENUMSET_SIZE.toNumber();
@@ -32,29 +31,27 @@ 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 (): 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<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;
result[accountId.toString()] = createType('AccountIndex', index);
});
result[accountId.toString()] = createType('AccountIndex', index);
});
return result;
}, {} as AccountIndexes)),
drr()
);
};
return result;
}, {} as AccountIndexes)),
drr()
);
}
+49
View File
@@ -0,0 +1,49 @@
// 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, AccountIndex, Address, Balance } from '@polkadot/types/interfaces';
import { Codec } from '@polkadot/types/types';
import { DeriveAccountInfo } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Bytes, Option, u32 } from '@polkadot/types';
import { u8aToString } from '@polkadot/util';
import { drr } from '../util';
function retrieveNick (api: ApiInterfaceRx, accountId?: AccountId): Observable<string | undefined> {
return accountId && api.query.nicks
? api.query.nicks
.nameOf<Option<[Bytes, Balance] & Codec>>(accountId)
.pipe(
map((nameOf): string | undefined =>
nameOf?.isSome
? u8aToString(nameOf.unwrap()[0]).substr(0, (api.consts.nicks.maxLength as u32).toNumber())
: undefined
)
)
: of(undefined);
}
/**
* @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 (address?: AccountIndex | AccountId | Address | string | null): Observable<DeriveAccountInfo> =>
api.derive.accounts.idAndIndex(address).pipe(
switchMap(([accountId, accountIndex]): Observable<[DeriveAccountInfo, string?]> =>
combineLatest([
of({ accountId, accountIndex }),
retrieveNick(api, accountId)
])
),
map(([{ accountId, accountIndex }, nickname]): DeriveAccountInfo => ({
accountId, accountIndex, nickname
})),
drr()
);
}
+16 -24
View File
@@ -3,6 +3,7 @@
// 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';
@@ -11,40 +12,30 @@ import { ApiInterfaceRx } from '@polkadot/api/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 { drr } from '../util';
type ResultBalance = [Balance, Balance, BalanceLock[], Option<VestingSchedule>];
type Result = [AccountId, BlockNumber, ResultBalance, Index];
function calcBalances ([accountId, bestNumber, [freeBalance, reservedBalance, locks, vesting], accountNonce]: Result): DerivedBalances {
let lockedBalance = createType('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]
? createType('Balance', bnMax(...totals.map(({ amount }): Balance => amount)))
: createType('Balance');
if (lockedBreakdown.length) {
lockedBalance = createType('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 { offset: vestingTotal, perBlock } = vesting.unwrapOr(createType('VestingSchedule'));
const vestedNow = createType('Balance', perBlock.mul(bestNumber));
const vestedBalance = vestedNow.gt(offset)
? freeBalance
: createType('Balance', freeBalance.sub(offset).add(vestedNow));
// 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 = createType('Balance', bnMax(new BN(0), vestedBalance.sub(lockedBalance)));
const vestedBalance = createType('Balance', vestedNow.gt(vestingTotal) ? new BN(0) : bnMax(new BN(0), freeBalance.sub(vestingTotal).add(vestedNow)));
const availableBalance = createType('Balance', bnMax(new BN(0), (vestedBalance.gtn(0) ? vestedBalance : freeBalance).sub(lockedBalance)));
return {
accountId,
@@ -52,8 +43,10 @@ function calcBalances ([accountId, bestNumber, [freeBalance, reservedBalance, lo
availableBalance,
freeBalance,
lockedBalance,
lockedBreakdown,
reservedBalance,
vestedBalance,
vestingTotal,
votingBalance: createType('Balance', freeBalance.add(reservedBalance))
};
}
@@ -83,13 +76,13 @@ function queryBalances (api: ApiInterfaceRx, accountId: AccountId): Observable<R
* ```
*/
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 (address: AccountIndex | AccountId | Address | string): Observable<DerivedBalances> =>
api.derive.accounts.info(address).pipe(
switchMap(({ accountId }): Observable<Result> =>
(accountId
? combineLatest([
of(accountId),
bestNumber(api)(),
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
@@ -104,5 +97,4 @@ export function all (api: ApiInterfaceRx): (address: AccountIndex | AccountId |
map(calcBalances),
drr()
);
};
}
+7 -8
View File
@@ -9,7 +9,7 @@ import { DerivedFees } from '../types';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
import { drr } from '../util/drr';
import { drr } from '../util';
type Result = [Balance, Balance, Balance, Balance, Balance];
@@ -52,12 +52,12 @@ function queryV1 (api: ApiInterfaceRx): Observable<Result> {
* ```
*/
export function fees (api: ApiInterfaceRx): () => Observable<DerivedFees> {
return (): Observable<DerivedFees> => {
return (
api.consts.balances
? queryV2(api)
: queryV1(api)
).pipe(
const query = api.consts.balances
? queryV2
: queryV1;
return (): Observable<DerivedFees> =>
query(api).pipe(
map(([creationFee, existentialDeposit, transferFee, transactionBaseFee, transactionByteFee]): DerivedFees => ({
creationFee,
existentialDeposit,
@@ -67,5 +67,4 @@ export function fees (api: ApiInterfaceRx): () => Observable<DerivedFees> {
})),
drr()
);
};
}
@@ -8,17 +8,18 @@ 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 { drr } from '../util';
export function votingBalances (api: ApiInterfaceRx): (addresses?: (AccountId | AccountIndex | Address | string)[]) => Observable<DerivedBalances[]> {
return (addresses?: (AccountId | AccountIndex | Address | string)[]): Observable<DerivedBalances[]> => {
return (
return (addresses?: (AccountId | AccountIndex | Address | string)[]): Observable<DerivedBalances[]> =>
(
!addresses || !addresses.length
? of([] as DerivedBalances[])
: combineLatest(addresses.map(all(api)))
: combineLatest(
addresses.map((accountId): Observable<DerivedBalances> =>
api.derive.balances.all(accountId))
)
).pipe(
drr()
);
};
}
@@ -3,27 +3,26 @@
// 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 { drr } 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 (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)),
switchMap((accounts): Observable<DerivedBalances[]> =>
api.derive.balances.votingBalances(accounts)
),
drr()
);
};
}
+4 -4
View File
@@ -2,13 +2,13 @@
// 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 { drr } from '../util';
/**
* @name bestNumber
@@ -24,8 +24,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()),
api.derive.chain.subscribeNewHeads().pipe(
map((header: Header): BlockNumber => header.number.unwrap()),
drr()
);
}
@@ -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 { drr } from '../util';
/**
* @name bestNumberFinalized
@@ -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 { drr } from '../util';
/**
* @name bestNumberLag
@@ -29,8 +27,8 @@ import { bestNumberFinalized } from './bestNumberFinalized';
export function bestNumberLag (api: ApiInterfaceRx): () => Observable<BlockNumber> {
return (): 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))
+10 -7
View File
@@ -2,13 +2,16 @@
// 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 { drr } from '../util';
/**
* @name bestNumberFinalized
@@ -26,12 +29,12 @@ import { HeaderAndValidators } from './subscribeNewHeads';
*/
export function getHeader (api: ApiInterfaceRx): (hash: Uint8Array | string) => Observable<HeaderExtended | undefined> {
return (hash: Uint8Array | string): Observable<HeaderExtended | undefined> =>
(combineLatest([
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)
),
@@ -3,15 +3,12 @@
// 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 { drr } from '../util';
/**
* @name subscribeNewHeads
@@ -28,19 +25,11 @@ 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 =>
combineLatest([
api.rpc.chain.subscribeNewHeads(),
api.derive.staking.validators()
]).pipe(
map(([header, { validators }]): HeaderExtended =>
new HeaderExtended(header, validators)
),
drr()
+1 -1
View File
@@ -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 { drr } from '../util';
type ResultV2 = [BN, BN, BN, BN, BN, BN, BN, BN, BN, BN];
@@ -12,7 +12,7 @@ import { Option } from '@polkadot/types';
import { isNull } from '@polkadot/util';
import { ReferendumInfoExtended } from '../type';
import { drr } from '../util/drr';
import { drr } from '../util';
export function constructInfo (index: BN | number, optionInfo?: Option<ReferendumInfo>): Option<ReferendumInfoExtended> {
const info = optionInfo
@@ -28,13 +28,11 @@ export function constructInfo (index: BN | number, optionInfo?: Option<Referendu
}
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()
);
};
return (index: BN | number): Observable<Option<ReferendumInfoExtended>> =>
api.query.democracy.referendumInfoOf<Option<ReferendumInfo>>(index).pipe(
map((optionInfo): Option<ReferendumInfoExtended> =>
constructInfo(index, optionInfo)
),
drr()
);
}
@@ -11,12 +11,12 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
import { Option, Vec } from '@polkadot/types';
import { ReferendumInfoExtended } from '../type';
import { drr } from '../util/drr';
import { drr } from '../util';
import { constructInfo } from './referendumInfo';
export function referendumInfos (api: ApiInterfaceRx): (ids?: (BN | number)[]) => Observable<Option<ReferendumInfoExtended>[]> {
return (ids: (BN | number)[] = []): Observable<Option<ReferendumInfoExtended>[]> => {
return (
return (ids: (BN | number)[] = []): Observable<Option<ReferendumInfoExtended>[]> =>
(
!ids || !ids.length
? of([] as Option<ReferendumInfo>[])
: api.query.democracy.referendumInfoOf.multi(ids) as Observable<Vec<Option<ReferendumInfo>>>
@@ -28,5 +28,4 @@ export function referendumInfos (api: ApiInterfaceRx): (ids?: (BN | number)[]) =
),
drr()
);
};
}
@@ -11,18 +11,16 @@ 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 { drr } 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(
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[] =>
@@ -11,18 +11,17 @@ 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 { drr } from '../util';
export function referendums (api: ApiInterfaceRx): () => Observable<Option<ReferendumInfoExtended>[]> {
return (): Observable<Option<ReferendumInfoExtended>[]> =>
(api.queryMulti([
api.queryMulti<[ReferendumIndex, ReferendumIndex]>([
api.query.democracy.nextTally,
api.query.democracy.referendumCount
]) as Observable<[ReferendumIndex?, ReferendumIndex?]>).pipe(
]).pipe(
switchMap(([nextTally, referendumCount]): Observable<Option<ReferendumInfoExtended>[]> =>
referendumCount && nextTally && referendumCount.gt(nextTally) && referendumCount.gtn(0)
? referendumInfos(api)(
? api.derive.democracy.referendumInfos(
[...Array(referendumCount.sub(nextTally).toNumber())].map((_, i): BN =>
nextTally.addn(i)
)
+6 -8
View File
@@ -7,20 +7,18 @@ 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 { drr } from '../util';
export function votes (api: ApiInterfaceRx): (referendumId: BN, accountIds?: AccountId[]) => Observable<Vote[]> {
return (referendumId: BN, accountIds: AccountId[] = []): Observable<Vote[]> => {
return ((
return (referendumId: BN, accountIds: AccountId[] = []): Observable<Vote[]> =>
(
!accountIds || !accountIds.length
? of([])
: api.query.democracy.voteOf.multi(
? of([] as Vote[])
: api.query.democracy.voteOf.multi<Vote>(
accountIds.map((accountId): [BN, AccountId] =>
[referendumId, accountId]
)
)
) as Observable<Vec<Vote>>).pipe(drr());
};
).pipe(drr());
}
@@ -9,7 +9,7 @@ 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';
import { drr } from '../util';
/**
* @name approvalsOf
@@ -11,7 +11,7 @@ import { ApiInterfaceRx } from '@polkadot/api/types';
import { Vec } from '@polkadot/types';
import { approvalFlagsToBools } from '../util/approvalFlagsToBools';
import { drr } from '../util/drr';
import { drr } from '../util';
/**
* @name approvalsOfAt
+73 -37
View File
@@ -2,30 +2,81 @@
// 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, SetIndex, VoteIndex } from '@polkadot/types/interfaces';
import { Codec } from '@polkadot/types/types';
import { Observable } from 'rxjs';
import { Observable, combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Vec, u32 } from '@polkadot/types';
import { createType, Vec, u32 } from '@polkadot/types';
import { DerivedElectionsInfo } from '../types';
import { drr } from '../util/drr';
import { drr } from '../util';
type Result = [Vec<[AccountId, BlockNumber] & Codec>, Vec<AccountId>, u32, u32, SetIndex, BlockNumber, VoteIndex, SetIndex];
type ResultElectionsInner = [u32, u32, Vec<[AccountId, BlockNumber] & Codec>, SetIndex, BlockNumber, VoteIndex, SetIndex];
type ResultElections = [Vec<AccountId>, ResultElectionsInner];
function query (api: ApiInterfaceRx): Observable<Result> {
return api.queryMulti<Result>([
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
]);
function deriveElections ([candidates, [candidateCount, desiredSeats, members, nextVoterSet, termDuration, voteCount, voterCount]]: ResultElections): DerivedElectionsInfo {
return {
candidates,
candidateCount,
desiredSeats,
nextVoterSet,
members: members.map(([accountId]): [AccountId, Balance] => [accountId, createType('Balance')]),
runnersUp: [],
termDuration,
voteCount,
voterCount
};
}
function queryElections (api: ApiInterfaceRx): Observable<DerivedElectionsInfo> {
// NOTE We have an issue where candidates can return `null` for an empty array
return combineLatest([
api.query.elections.candidates<Vec<AccountId>>(),
api.queryMulti<ResultElectionsInner>([
api.query.elections.candidateCount,
api.query.elections.desiredSeats,
api.query.elections.members,
api.query.elections.nextVoterSet,
api.query.elections.termDuration,
api.query.elections.voteCount,
api.query.elections.voterCount
])
]).pipe(map(deriveElections));
}
function derivePhragmen (candidates: AccountId[], members: [AccountId, Balance][], runnersUp: [AccountId, Balance][], candidacyBond: Balance, desiredSeats: u32, termDuration: BlockNumber, votingBond: Balance): DerivedElectionsInfo {
return {
candidates,
candidateCount: createType('u32', candidates.length),
candidacyBond,
desiredSeats,
members,
runnersUp,
termDuration,
votingBond
};
}
function queryPhragmen (api: ApiInterfaceRx): Observable<DerivedElectionsInfo> {
// 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.electionsPhragmen.candidates<Vec<AccountId>>(),
api.query.electionsPhragmen.members<Vec<[AccountId, Balance] & Codec>>(),
api.query.electionsPhragmen.runnersUp<Vec<[AccountId, Balance] & Codec>>()
]).pipe(
map(([candidates, members, runnersUp]): DerivedElectionsInfo => derivePhragmen(
candidates,
members,
runnersUp,
api.consts.electionsPhragmen.candidacyBond as Balance,
api.consts.electionsPhragmen.desiredMembers as u32,
api.consts.electionsPhragmen.termDuration as BlockNumber,
api.consts.electionsPhragmen.votingBond as Balance
))
);
}
/**
@@ -42,25 +93,10 @@ function query (api: ApiInterfaceRx): Observable<Result> {
* ```
*/
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
})),
drr()
);
};
const query = api.query.electionsPhragmen
? queryPhragmen
: queryElections;
return (): Observable<DerivedElectionsInfo> =>
query(api).pipe(drr());
}
@@ -10,7 +10,8 @@ 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';
import { drr } from '../util';
/**
* @name voterPositions
@@ -34,6 +35,7 @@ export function voterPositions (api: ApiInterfaceRx): () => Observable<DerivedVo
)),
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
+9 -11
View File
@@ -10,8 +10,7 @@ import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { createType, Vec } from '@polkadot/types';
import { drr } from '../util/drr';
import { voterPositions } from './voterPositions';
import { drr } from '../util';
/**
* @name voters
@@ -27,15 +26,14 @@ import { voterPositions } from './voterPositions';
*/
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))
)
api.derive.elections.voterPositions().pipe(
map((voterPositions: DerivedVoterPositions): Vec<AccountId> =>
createType(
'Vec<AccountId>',
Object.entries(voterPositions)
.sort((a, b): number => a[1].globalIndex.cmp(b[1].globalIndex))
.map(([accountId]): AccountId => createType('AccountId', accountId))
)
),
drr()
);
@@ -3,36 +3,40 @@
// 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 { drr } 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 (): 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)
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)
}
}), {})
),
drr()
)
: of([...new Array(addresses.length).keys()].map((): boolean => false));
};
: of({});
}
+8 -7
View File
@@ -2,18 +2,19 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import BN from 'bn.js';
import { BlockNumber } from '@polkadot/types/interfaces';
import { DerivedSessionInfo } from '../types';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { drr } from '../util/drr';
import { info } from './info';
import { drr } from '../util';
export function eraLength (api: ApiInterfaceRx): () => Observable<BN> {
return (): Observable<BN> =>
info(api)().pipe(
map(({ eraLength }): BN => eraLength),
export function eraLength (api: ApiInterfaceRx): () => Observable<BlockNumber> {
return (): Observable<BlockNumber> =>
api.derive.session.info().pipe(
map(({ eraLength }: DerivedSessionInfo): BlockNumber => eraLength),
drr()
);
}
@@ -2,18 +2,19 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import BN from 'bn.js';
import { BlockNumber } from '@polkadot/types/interfaces';
import { DerivedSessionInfo } from '../types';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { drr } from '../util/drr';
import { info } from './info';
import { drr } from '../util';
export function eraProgress (api: ApiInterfaceRx): () => Observable<BN> {
return (): Observable<BN> =>
info(api)().pipe(
map(({ eraProgress }): BN => eraProgress),
export function eraProgress (api: ApiInterfaceRx): () => Observable<BlockNumber> {
return (): Observable<BlockNumber> =>
api.derive.session.info().pipe(
map(({ eraProgress }: DerivedSessionInfo): BlockNumber => eraProgress),
drr()
);
}
+1
View File
@@ -4,5 +4,6 @@
export * from './eraLength';
export * from './eraProgress';
export * from './indexes';
export * from './info';
export * from './sessionProgress';
@@ -0,0 +1,27 @@
// 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 { EraIndex, SessionIndex } from '@polkadot/types/interfaces';
import { DeriveSessionIndexes } from '../types';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { u32 } from '@polkadot/types';
import { drr } from '../util';
export function indexes (api: ApiInterfaceRx): () => Observable<DeriveSessionIndexes> {
return (): Observable<DeriveSessionIndexes> =>
api.queryMulti<[SessionIndex, EraIndex, u32]>([
api.query.session.currentIndex,
api.query.staking.currentEra,
api.query.staking.validatorCount
]).pipe(
map(([currentIndex, currentEra, validatorCount]): DeriveSessionIndexes => ({
currentIndex, currentEra, validatorCount
})),
drr()
);
}
+59 -64
View File
@@ -2,28 +2,26 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { BlockNumber, EraIndex, SessionIndex } from '@polkadot/types/interfaces';
import { DerivedSessionInfo } from '../types';
import { BlockNumber, SessionIndex } from '@polkadot/types/interfaces';
import { DerivedSessionInfo, DeriveSessionIndexes } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { Observable, combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Option, u64, createType } from '@polkadot/types';
import { drr } from '../util/drr';
import { bestNumber } from '../chain';
import { drr } from '../util';
type Result94Session = [SessionIndex, Option<BlockNumber>, BlockNumber, BlockNumber, SessionIndex];
type Result94 = [BlockNumber, Result94Session];
type ResultV1Session = [Option<BlockNumber>, BlockNumber, BlockNumber, SessionIndex];
type ResultV1 = [BlockNumber, DeriveSessionIndexes, ResultV1Session];
type ResultIndex = [SessionIndex, EraIndex];
type ResultSlots = [u64, u64, u64];
type ResultType = [boolean, boolean, u64, SessionIndex];
type Result = [ResultType, ResultSlots, ResultIndex];
type ResultSlots = [u64, u64, u64, SessionIndex];
type ResultType = [boolean, u64, SessionIndex];
type Result = [ResultType, DeriveSessionIndexes, ResultSlots];
// internal helper to just split the logic - take all inputs, do the calculations and combine
function createDerived94 ([bestNumber, [currentIndex, _lastLengthChange, sessionLength, lastEraLengthChange, sessionsPerEra]]: Result94): DerivedSessionInfo {
const lastLengthChange = (_lastLengthChange && _lastLengthChange.unwrapOr(null)) || createType('BlockNumber');
function createDerivedV1 ([bestNumber, { currentIndex, validatorCount }, [_lastLengthChange, sessionLength, lastEraLengthChange, sessionsPerEra]]: ResultV1): DerivedSessionInfo {
const lastLengthChange = _lastLengthChange?.unwrapOr(null) || createType('BlockNumber');
const sessionProgress = bestNumber
.sub(lastLengthChange)
.add(sessionLength)
@@ -45,21 +43,17 @@ function createDerived94 ([bestNumber, [currentIndex, _lastLengthChange, session
lastLengthChange,
sessionLength,
sessionsPerEra,
sessionProgress: createType('BlockNumber', sessionProgress)
sessionProgress: createType('BlockNumber', sessionProgress),
validatorCount
};
}
function createDerivedLatest ([[hasBabe, isGenesisSlot, epochDuration, sessionsPerEra], [currentSlot, epochIndex, epochOrGenesisStartSlot], [currentIndex, currentEra]]: Result): DerivedSessionInfo {
const epochStartSlot = isGenesisSlot
? epochIndex
.mul(epochDuration)
.add(epochOrGenesisStartSlot)
: epochOrGenesisStartSlot;
function createDerivedLatest ([[hasBabe, epochDuration, sessionsPerEra], { currentIndex, currentEra, validatorCount }, [currentSlot, epochIndex, epochOrGenesisStartSlot, currentEraStartSessionIndex]]: Result): DerivedSessionInfo {
const epochStartSlot = epochIndex.mul(epochDuration).add(epochOrGenesisStartSlot);
const sessionProgress = currentSlot.sub(epochStartSlot);
const eraProgress = epochIndex
.mod(sessionsPerEra)
.mul(epochDuration)
.add(sessionProgress);
const eraProgress = currentIndex.sub(currentEraStartSessionIndex).add(sessionProgress);
// console.log(sessionProgress);
return {
currentEra,
@@ -71,54 +65,55 @@ function createDerivedLatest ([[hasBabe, isGenesisSlot, epochDuration, sessionsP
lastLengthChange: createType('BlockNumber', epochStartSlot),
sessionLength: epochDuration,
sessionsPerEra,
sessionProgress: createType('BlockNumber', sessionProgress)
sessionProgress: createType('BlockNumber', sessionProgress),
validatorCount
};
}
function info94 (api: ApiInterfaceRx): Observable<DerivedSessionInfo> {
function infoV1 (api: ApiInterfaceRx): Observable<DerivedSessionInfo> {
return combineLatest([
bestNumber(api)(),
api.queryMulti<Result94Session>([
api.query.session.currentIndex,
api.derive.chain.bestNumber(),
api.derive.session.indexes(),
api.queryMulti<ResultV1Session>([
api.query.session.lastLengthChange,
api.query.session.sessionLength,
api.query.staking.lastEraLengthChange,
api.query.staking.sessionsPerEra
])
]).pipe(
map(createDerived94),
drr()
map(createDerivedV1)
);
}
function infoLatest (api: ApiInterfaceRx): Observable<DerivedSessionInfo> {
const hasBabe = !!api.consts.babe;
return combineLatest([
of([
hasBabe,
hasBabe && !!api.query.babe.genesisSlot,
hasBabe
? api.consts.babe.epochDuration as u64
: createType('u64', 1),
api.consts.staking.sessionsPerEra as SessionIndex
] as ResultType),
hasBabe
? api.queryMulti<ResultSlots>([
api.query.babe.currentSlot,
api.query.babe.epochIndex,
api.query.babe.genesisSlot
? api.query.babe.genesisSlot
: api.query.babe.epochStartSlot
function infoLatestAura (api: ApiInterfaceRx): Observable<DerivedSessionInfo> {
return api.derive.session.indexes().pipe(
map((indexes): DerivedSessionInfo =>
createDerivedLatest([
[false, createType('u64', 1), api.consts.staking.sessionsPerEra as SessionIndex],
indexes,
[createType('u64', 1), createType('u64', 1), createType('u64', 1), createType('SessionIndex', 1)]
])
: of([createType('u64', 1), createType('u64', 1), createType('u64', 1)] as ResultSlots),
api.queryMulti<ResultIndex>([
api.query.session.currentIndex,
api.query.staking.currentEra
)
);
}
function infoLatestBabe (api: ApiInterfaceRx): Observable<DerivedSessionInfo> {
return combineLatest([
api.derive.session.indexes(),
api.queryMulti<ResultSlots>([
api.query.babe.currentSlot,
api.query.babe.epochIndex,
api.query.babe.genesisSlot,
api.query.staking.currentEraStartSessionIndex
])
]).pipe(
map(createDerivedLatest),
drr()
map(([indexes, slots]: [DeriveSessionIndexes, ResultSlots]): DerivedSessionInfo =>
createDerivedLatest([
[true, api.consts.babe.epochDuration as u64, api.consts.staking.sessionsPerEra as SessionIndex],
indexes,
slots
])
)
);
}
@@ -126,12 +121,12 @@ function infoLatest (api: ApiInterfaceRx): Observable<DerivedSessionInfo> {
* @description Retrieves all the session and era info and calculates specific values on it as the length of the session and eras
*/
export function info (api: ApiInterfaceRx): () => Observable<DerivedSessionInfo> {
return (): Observable<DerivedSessionInfo> => {
// With substrate `spec_version 94`, the era and session has been explicitly exposed as `parameter_types`.
// pre-94 we had more info and needed to calculate (handle old/Alex first)
// https://github.com/paritytech/substrate/commit/dbf322620948935d2bbae214504e6c668c3073ed#diff-c29f42d6b931fa93ba038dbbbfec3055
return api.query.session.lastLengthChange
? info94(api) // 1.x
: infoLatest(api); // 2.x
};
const query = api.consts.staking
? api.consts.babe
? infoLatestBabe // 2.x with Babe
: infoLatestAura // 2.x with Aura (not all info there)
: infoV1;
return (): Observable<DerivedSessionInfo> =>
query(api).pipe(drr());
}
@@ -2,18 +2,19 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import BN from 'bn.js';
import { BlockNumber } from '@polkadot/types/interfaces';
import { DerivedSessionInfo } from '../types';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { drr } from '../util/drr';
import { info } from './info';
import { drr } from '../util';
export function sessionProgress (api: ApiInterfaceRx): () => Observable<BN> {
return (): Observable<BN> =>
info(api)().pipe(
map(({ sessionProgress }): BN => sessionProgress),
export function sessionProgress (api: ApiInterfaceRx): () => Observable<BlockNumber> {
return (): Observable<BlockNumber> =>
api.derive.session.info().pipe(
map(({ sessionProgress }: DerivedSessionInfo): BlockNumber => sessionProgress),
drr()
);
}
+14 -14
View File
@@ -2,31 +2,31 @@
// 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 { Codec } from '@polkadot/types/types';
import { Observable, combineLatest, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { Option } from '@polkadot/types';
import { drr } from '../util/drr';
import { drr } from '../util';
/**
* @description From the list of stash accounts, retrieve the list of controllers
*/
export function controllers (api: ApiInterfaceRx): () => Observable<[AccountId[], Option<AccountId>[]]> {
return (): Observable<[AccountId[], Option<AccountId>[]]> =>
api.query.staking
.validators<[AccountId[]] & Codec>()
.pipe(
switchMap(([stashIds]): Observable<[AccountId[], Option<AccountId>[]]> =>
combineLatest([
of(stashIds),
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
api.query.staking.bonded.multi(stashIds) as Observable<Option<AccountId>[]>
])
),
drr()
);
api.query.staking.validators<[AccountId[]] & Codec>().pipe(
switchMap(([stashIds]): Observable<[AccountId[], Option<AccountId>[]]> =>
combineLatest([
of(stashIds),
// for V2, don't return all the controllers, we call bonded at a later point
api.consts.session
? of([])
: api.query.staking.bonded.multi<Option<AccountId>>(stashIds)
])
),
drr()
);
}
+2
View File
@@ -4,4 +4,6 @@
export * from './controllers';
export * from './info';
export * from './overview';
export * from './recentlyOffline';
export * from './validators';
+105 -72
View File
@@ -2,13 +2,11 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, Balance, BlockNumber } from '@polkadot/types/interfaces/runtime';
import { Keys } from '@polkadot/types/interfaces/session';
import { Exposure, RewardDestination, StakingLedger, UnlockChunk, ValidatorPrefs } from '@polkadot/types/interfaces/staking';
import { AccountId, Balance, BlockNumber, Exposure, Keys, RewardDestination, StakingLedger, UnlockChunk, ValidatorPrefs } from '@polkadot/types/interfaces';
import { Codec } from '@polkadot/types/types';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DerivedStaking, DerivedUnlocking } from '../types';
import { DerivedRecentlyOffline, DerivedStaking, DerivedUnlocking } from '../types';
import BN from 'bn.js';
import { combineLatest, Observable, of } from 'rxjs';
@@ -17,14 +15,24 @@ import { createType, Option, Vec } from '@polkadot/types';
import { isUndefined } from '@polkadot/util';
import { bestNumber } from '../chain/bestNumber';
import { eraLength } from '../session/eraLength';
import { recentlyOffline } from './recentlyOffline';
import { drr } from '../util/drr';
import { drr } from '../util';
type MultiResult = [Option<Keys>, [
Option<AccountId> | Vec<[AccountId, Keys] & Codec>, Option<StakingLedger>, [AccountId[]], RewardDestination, Exposure, [ValidatorPrefs]
]];
interface ParseInput {
accountId: AccountId;
bestNumber: BlockNumber;
controllerId: AccountId;
eraLength: BlockNumber;
recentlyOffline?: DerivedRecentlyOffline;
nominators: AccountId[];
rewardDestination: RewardDestination;
queuedKeys?: [AccountId, Keys][];
stakers: Exposure;
stakingLedger: Option<StakingLedger>;
stashId: AccountId;
validatorPrefs: ValidatorPrefs;
nextKeys?: Option<Keys>;
nextKeyFor?: Option<AccountId>;
}
// groups the supplied chunks by era, i.e. { [era]: BN(total of values) }
function groupByEra (list: UnlockChunk[]): Record<string, BN> {
@@ -84,7 +92,7 @@ function redeemableSum (stakingLedger: StakingLedger | undefined, eraLength: BN,
}, new BN(0)));
}
function unwrapSessionIds (stashId: AccountId, queuedKeys: Option<AccountId> | Vec<[AccountId, Keys] & Codec>, nextKeys: Option<Keys>): { nextSessionIds: AccountId[]; nextSessionId?: AccountId; sessionIds: AccountId[]; sessionId?: AccountId } {
function unwrapSessionIds (stashId: AccountId, queuedKeys: Option<AccountId> | [AccountId, Keys][], nextKeys: Option<Keys>): { nextSessionIds: AccountId[]; sessionIds: AccountId[] } {
// for 2.x we have a Vec<(ValidatorId,Keys)> of the keys
if (Array.isArray(queuedKeys)) {
const sessionIds = (queuedKeys.find(([currentId]): boolean =>
@@ -93,9 +101,7 @@ function unwrapSessionIds (stashId: AccountId, queuedKeys: Option<AccountId> | V
const nextSessionIds = nextKeys.unwrapOr([] as AccountId[]);
return {
nextSessionId: nextSessionIds[0],
nextSessionIds,
sessionId: sessionIds[0],
sessionIds
};
}
@@ -106,85 +112,112 @@ function unwrapSessionIds (stashId: AccountId, queuedKeys: Option<AccountId> | V
: [];
return {
nextSessionId: nextSessionIds[0],
nextSessionIds,
sessionId: nextSessionIds[0],
sessionIds: nextSessionIds
};
}
function retrieveMulti (api: ApiInterfaceRx, stashId: AccountId, controllerId: AccountId): Observable<MultiResult> {
function parseResult ({ accountId, controllerId, stashId, eraLength, bestNumber, recentlyOffline = {}, nextKeyFor = createType('Option<AccountId>', null), queuedKeys, stakingLedger, nominators, rewardDestination, stakers, validatorPrefs, nextKeys = createType('Option<Keys>', null) }: ParseInput): DerivedStaking {
const _stakingLedger = stakingLedger.unwrapOr(undefined);
return {
accountId,
controllerId,
nominators,
offline: recentlyOffline[stashId.toString()],
redeemable: redeemableSum(_stakingLedger, eraLength, bestNumber),
rewardDestination,
stakers,
stakingLedger: _stakingLedger,
stashId,
unlocking: calculateUnlocking(_stakingLedger, eraLength, bestNumber),
validatorPrefs,
...unwrapSessionIds(stashId, queuedKeys || nextKeyFor, nextKeys)
};
}
type MultiResultV1 = [Option<AccountId>, Option<StakingLedger>, [Vec<AccountId>], RewardDestination, Exposure, [ValidatorPrefs] & Codec];
function retrieveInfoV1 (api: ApiInterfaceRx, accountId: AccountId, stashId: AccountId, controllerId: AccountId): Observable<DerivedStaking> {
return combineLatest([
// TODO We really want this as part of the multi, however can only do that
// once we drop substrate 1.x support (nulti requires values for all)
api.query.session.nextKeys
? api.query.session.nextKeys<Option<Keys>>(api.consts.session.dedupKeyPrefix, stashId)
: of(createType('Option<Keys>', null)),
api.derive.chain.bestNumber(),
api.derive.session.eraLength(),
api.derive.staking.recentlyOffline(),
api.queryMulti([
api.query.session.queuedKeys
? [api.query.session.queuedKeys]
: [api.query.session.nextKeyFor, controllerId],
[api.query.session.nextKeyFor, controllerId],
[api.query.staking.ledger, controllerId],
[api.query.staking.nominators, stashId],
[api.query.staking.payee, stashId],
[api.query.staking.stakers, stashId],
[api.query.staking.validators, stashId]
])
]) as Observable<MultiResult>;
]) as Observable<MultiResultV1>
]).pipe(map(([
bestNumber, eraLength, recentlyOffline,
[nextKeyFor, stakingLedger, [nominators], rewardDestination, stakers, [validatorPrefs]]
]: [BlockNumber, BlockNumber, DerivedRecentlyOffline, MultiResultV1]): DerivedStaking =>
parseResult({
accountId, controllerId, stashId, eraLength, bestNumber, recentlyOffline, nextKeyFor, stakingLedger, nominators, rewardDestination, stakers, validatorPrefs
})
));
}
function retrieveInfo (api: ApiInterfaceRx, accountId: AccountId, stashId: AccountId, controllerId: AccountId): Observable<DerivedStaking> {
return combineLatest([
eraLength(api)(),
bestNumber(api)(),
recentlyOffline(api)(),
retrieveMulti(api, stashId, controllerId)
]).pipe(
map(([eraLength, bestNumber, recentlyOffline, [nextKeys, [queuedKeys, _stakingLedger, [nominators], rewardDestination, stakers, [validatorPrefs]]]]): DerivedStaking => {
const stakingLedger = _stakingLedger.unwrapOr(undefined);
type MultiResultV2 = [Option<StakingLedger>, [Vec<AccountId>], RewardDestination, Exposure, [ValidatorPrefs], Option<Keys>];
return {
accountId,
controllerId,
nominators,
offline: recentlyOffline[stashId.toString()],
redeemable: redeemableSum(stakingLedger, eraLength, bestNumber),
rewardDestination,
stakers,
stakingLedger,
stashId,
unlocking: calculateUnlocking(stakingLedger, eraLength, bestNumber),
validatorPrefs,
...unwrapSessionIds(stashId, queuedKeys, nextKeys)
};
function retrieveInfoV2 (api: ApiInterfaceRx, accountId: AccountId, stashId: AccountId, controllerId: AccountId): Observable<DerivedStaking> {
return combineLatest([
api.derive.chain.bestNumber(),
api.derive.session.eraLength(),
api.query.session.queuedKeys<Vec<[AccountId, Keys] & Codec>>(),
api.queryMulti([
[api.query.staking.ledger, controllerId],
[api.query.staking.nominators, stashId],
[api.query.staking.payee, stashId],
[api.query.staking.stakers, stashId],
[api.query.staking.validators, stashId],
[api.query.session.nextKeys, [api.consts.session.dedupKeyPrefix, stashId]]
]) as Observable<MultiResultV2>
]).pipe(map(([
bestNumber, eraLength, queuedKeys,
[stakingLedger, [nominators], rewardDestination, stakers, [validatorPrefs], nextKeys]
]: [BlockNumber, BlockNumber, [AccountId, Keys][], MultiResultV2]): DerivedStaking =>
parseResult({
accountId, controllerId, stashId, eraLength, bestNumber, queuedKeys, stakingLedger, nominators, rewardDestination, stakers, validatorPrefs, nextKeys
})
);
));
}
function retrieveV1 (api: ApiInterfaceRx, controllerId: AccountId): Observable<DerivedStaking> {
return api.query.staking
.ledger<Option<StakingLedger>>(controllerId)
.pipe(
switchMap((stakingLedger): Observable<DerivedStaking> =>
stakingLedger.isSome
? retrieveInfoV1(api, controllerId, stakingLedger.unwrap().stash, controllerId)
: of({ accountId: controllerId, nextSessionIds: [], sessionIds: [] })
)
);
}
function retrieveV2 (api: ApiInterfaceRx, stashId: AccountId): Observable<DerivedStaking> {
return api.query.staking
.bonded<Option<AccountId>>(stashId)
.pipe(
switchMap((controllerId): Observable<DerivedStaking> =>
controllerId.isSome
? retrieveInfoV2(api, stashId, stashId, controllerId.unwrap())
: of({ accountId: stashId, nextSessionIds: [], sessionIds: [] })
)
);
}
/**
* @description From a stash, retrieve the controllerId and fill in all the relevant staking details
*/
export function info (api: ApiInterfaceRx): (_accountId: Uint8Array | string) => Observable<DerivedStaking> {
return (_accountId: Uint8Array | string): Observable<DerivedStaking> => {
const accountId = createType('AccountId', _accountId);
const query = api.consts.session
? retrieveV2
: retrieveV1;
return (
// NOTE For 2.x-only support, only the first path is required, therefore we
// can replace this with `.bonded<Option<AccountId>>(accountId)` - in 2.x
// the session.validators return the stashes (as expected)
api.queryMulti<[Option<AccountId>, Option<StakingLedger>]>([
[api.query.staking.bonded, accountId], // try to map to controller
[api.query.staking.ledger, accountId] // try to map to stash (1.x only)
])
).pipe(
switchMap(([controllerId, stakingLedger]): Observable<DerivedStaking> =>
controllerId.isSome
? retrieveInfo(api, accountId, accountId, controllerId.unwrap())
: stakingLedger.isSome
? retrieveInfo(api, accountId, stakingLedger.unwrap().stash, accountId)
: of({ accountId, nextSessionIds: [], sessionIds: [] })
),
drr()
);
};
return (accountId: Uint8Array | string): Observable<DerivedStaking> =>
query(api, createType('AccountId', accountId)).pipe(drr());
}
@@ -0,0 +1,65 @@
// 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, Exposure, Keys, RewardDestination, ValidatorPrefs } from '@polkadot/types/interfaces';
import { ITuple } from '@polkadot/types/types';
import { DerivedStakingStash } from '../types';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Option, Vec } from '@polkadot/types';
import { drr } from '../util';
// NOTE Unused ATM, preparing for V2-only
type Result = [Option<AccountId>, [Vec<AccountId>], RewardDestination, Exposure, ValidatorPrefs, Option<Keys>?];
type ResultV1 = [Option<AccountId>, ITuple<[Vec<AccountId>]>, RewardDestination, Exposure, ValidatorPrefs];
type ResultV2 = [Option<AccountId>, ITuple<[Vec<AccountId>]>, RewardDestination, Exposure, ValidatorPrefs, Option<Keys>];
function parse (stashId: AccountId, [_controllerId, [nominators], rewardDestination, stakers, validatorPrefs, _nextKeys]: Result): DerivedStakingStash {
return {
controllerId: _controllerId.unwrapOr(undefined),
nextKeys: _nextKeys?.unwrapOr(undefined),
nominators,
rewardDestination,
stakers,
stashId,
validatorPrefs
};
}
function retrieveV1 (api: ApiInterfaceRx, stashId: AccountId): Observable<Result> {
return api.queryMulti<ResultV1>([
[api.query.staking.bonded, stashId],
[api.query.staking.nominators, stashId],
[api.query.staking.payee, stashId],
[api.query.staking.stakers, stashId],
[api.query.staking.validators, stashId]
]);
}
function retrieveV2 (api: ApiInterfaceRx, stashId: AccountId): Observable<Result> {
return api.queryMulti<ResultV2>([
[api.query.staking.bonded, stashId],
[api.query.staking.nominators, stashId],
[api.query.staking.payee, stashId],
[api.query.staking.stakers, stashId],
[api.query.staking.validators, stashId],
[api.query.session.nextKeys, [api.consts.session.dedupKeyPrefix, stashId]]
]);
}
export function infoStash (api: ApiInterfaceRx): (stashId: AccountId) => Observable<DerivedStakingStash> {
const query = api.consts.session
? retrieveV2
: retrieveV1;
return (stashId: AccountId): Observable<DerivedStakingStash> =>
query(api, stashId).pipe(
map((result): DerivedStakingStash => parse(stashId, result)),
drr()
);
}
@@ -0,0 +1,38 @@
// 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 { EraPoints } from '@polkadot/types/interfaces';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DerivedStakingOverview } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { createType } from '@polkadot/types';
import { drr } from '../util';
/**
* @description Retrieve the staking overview, including elected and points earned
*/
export function overview (api: ApiInterfaceRx): () => Observable<DerivedStakingOverview> {
return (): Observable<DerivedStakingOverview> =>
combineLatest([
api.derive.session.indexes(),
api.derive.staking.validators()
]).pipe(
switchMap(([{ currentEra, currentIndex, validatorCount }, { currentElected, validators }]) =>
combineLatest([
of({ currentElected, currentEra, currentIndex, validators, validatorCount }),
// this will change on a per block basis, keep it innermost (and it needs eraIndex)
api.query.staking.currentEraPointsEarned
? api.query.staking.currentEraPointsEarned<EraPoints>(currentEra)
: of(createType('EraPoints'))
])
),
map(([{ currentElected, currentEra, currentIndex, validators, validatorCount }, eraPoints]): DerivedStakingOverview => ({
currentElected, currentEra, currentIndex, eraPoints, validators, validatorCount
})),
drr()
);
}
@@ -11,7 +11,7 @@ import { map } from 'rxjs/operators';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DerivedRecentlyOffline } from '../types';
import { drr } from '../util/drr';
import { drr } from '../util';
type OfflineResult = [AccountId, BlockNumber, BN][] & Codec;
@@ -0,0 +1,29 @@
// 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 } from '@polkadot/types/interfaces';
import { ApiInterfaceRx } from '@polkadot/api/types';
import { DeriveStakingValidators } from '../types';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Vec } from '@polkadot/types';
import { drr } from '../util';
/**
* @description Retrieve latest list of validators
*/
export function validators (api: ApiInterfaceRx): () => Observable<DeriveStakingValidators> {
return (): Observable<DeriveStakingValidators> =>
api.queryMulti<[Vec<AccountId>, Vec<AccountId>]>([
api.query.session.validators,
api.query.staking.currentElected
]).pipe(
map(([validators, currentElected]): DeriveStakingValidators => ({
currentElected, validators
})),
drr()
);
}
@@ -19,7 +19,7 @@ const _Header: Constructor<Header> = Struct.with(runtimeTypes.types.Header as an
export default class HeaderExtended extends _Header {
private _author?: AccountId;
public constructor (header?: Header, sessionValidators?: AccountId[]) {
constructor (header?: Header, sessionValidators?: AccountId[]) {
super(header);
this._author = this.extractAuthor(sessionValidators);
@@ -20,7 +20,7 @@ const _ReferendumInfo: Constructor<ReferendumInfo> = Struct.with(democracyTypes.
export default class ReferendumInfoExtended extends _ReferendumInfo {
private _index: ReferendumIndex;
public constructor (value: ReferendumInfo | ReferendumInfoExtended, index?: BN | number) {
constructor (value: ReferendumInfo | ReferendumInfoExtended, index?: BN | number) {
super(value);
this._index = value instanceof ReferendumInfoExtended
+53 -17
View File
@@ -2,20 +2,30 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountId, Balance, BlockNumber, EraIndex, Exposure, Index, RewardDestination, SessionIndex, SetIndex, StakingLedger, ValidatorPrefs, Vote, VoteIndex } from '@polkadot/types/interfaces';
import { AccountId, AccountIndex, Balance, BalanceLock, BlockNumber, EraIndex, EraPoints, Exposure, Index, Keys, RewardDestination, SessionIndex, SetIndex, StakingLedger, ValidatorPrefs, Vote, VoteIndex } from '@polkadot/types/interfaces';
import BN from 'bn.js';
import { u32 } from '@polkadot/types';
export type AccountIndexes = Record<string, AccountIndex>;
export interface DeriveAccountInfo {
accountId?: AccountId;
accountIndex?: AccountIndex;
nickname?: string;
}
export interface DerivedBalances {
accountId: AccountId;
accountNonce: Index;
freeBalance: Balance;
lockedBalance: Balance;
lockedBreakdown: BalanceLock[];
availableBalance: Balance;
reservedBalance: Balance;
votingBalance: Balance;
vestedBalance: Balance;
vestingTotal: Balance;
}
export type DerivedBalancesMap = Record<string, DerivedBalances>;
@@ -34,14 +44,17 @@ export interface DerivedContractFees {
}
export interface DerivedElectionsInfo {
members: Record<string, BlockNumber>;
candidates: AccountId[];
candidateCount: u32;
candidacyBond?: Balance;
desiredSeats: u32;
nextVoterSet: SetIndex;
members: [AccountId, Balance][];
nextVoterSet?: SetIndex;
runnersUp: [AccountId, Balance][];
termDuration: BlockNumber;
voteCount: VoteIndex;
voterCount: SetIndex;
voteCount?: VoteIndex;
voterCount?: SetIndex;
votingBond?: Balance;
}
export interface DerivedFees {
@@ -52,6 +65,14 @@ export interface DerivedFees {
transferFee: Balance;
}
export interface DerivedHeartbeatAuthor {
blockCount: u32;
hasMessage: boolean;
isOnline: boolean;
}
export type DerivedHeartbeats = Record<string, DerivedHeartbeatAuthor>;
export interface RecentlyOffline {
blockNumber: BlockNumber;
count: BN;
@@ -65,9 +86,13 @@ export interface DerivedReferendumVote {
vote: Vote;
}
export interface DerivedSessionInfo {
export interface DeriveSessionIndexes {
currentEra: EraIndex;
currentIndex: SessionIndex;
validatorCount: u32;
}
export interface DerivedSessionInfo extends DeriveSessionIndexes {
eraLength: BlockNumber;
eraProgress: BlockNumber;
isEpoch: boolean;
@@ -93,25 +118,36 @@ export interface DerivedStakingOnlineStatus {
}[];
}
export interface DerivedStaking extends DerivedStakingOnlineStatus {
accountId: AccountId;
export interface DeriveStakingValidators {
currentElected: AccountId[];
validators: AccountId[];
}
export interface DerivedStakingStash {
controllerId?: AccountId;
// @deprecated Use nextSessionIds instead
nextSessionId?: AccountId;
nextSessionIds: AccountId[];
nominators?: AccountId[];
redeemable?: Balance;
rewardDestination?: RewardDestination;
// @deprecated Use sessionIds instead
sessionId?: AccountId;
sessionIds: AccountId[];
nextKeys?: Keys;
stakers?: Exposure;
stakingLedger?: StakingLedger;
stashId?: AccountId;
unlocking?: DerivedUnlocking[];
validatorPrefs?: ValidatorPrefs;
}
export interface DerivedStaking extends DerivedStakingOnlineStatus, DerivedStakingStash {
accountId: AccountId;
nextSessionIds: AccountId[];
redeemable?: Balance;
sessionIds: AccountId[];
stakingLedger?: StakingLedger;
unlocking?: DerivedUnlocking[];
}
export interface DerivedStakingOverview extends DeriveSessionIndexes {
currentElected: AccountId[];
eraPoints: EraPoints;
validators: AccountId[];
}
export type DerivedUnlocking = { remainingBlocks: BlockNumber; value: Balance };
export interface VoterPosition {
+3 -25
View File
@@ -2,29 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { catchError, distinctUntilChanged, publishReplay, refCount } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { logger } from '@polkadot/util';
import { drr as drrBase, DrrResult } from '@polkadot/rpc-core/rxjs';
type DrrResult = <T> (source$: Observable<T>) => Observable<T>;
const l = logger('drr');
/**
* Shorthand for distinctUntilChanged(), publishReplay(1) and refCount().
*
* @ignore
*/
export const drr = (): DrrResult => <T> (source$: Observable<T>): Observable<T> =>
source$.pipe(
catchError((error): Observable<never> => {
l.error(error);
throw error;
}),
distinctUntilChanged((a: any, b: any): boolean =>
JSON.stringify({ value: a }) === JSON.stringify({ value: b })
),
publishReplay(1),
refCount()
);
export const drr = (): DrrResult =>
drrBase({ skipTimeout: true });
+2
View File
@@ -3,3 +3,5 @@
// of the Apache-2.0 license. See the LICENSE file for details.
export * from './approvalFlagsToBools';
export * from './drr';
export * from './memo';
+14
View File
@@ -0,0 +1,14 @@
// 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.v
import createMemo from 'memoizee';
export function memo <T extends Function> (fn: T, withoutJSON?: boolean): T {
return withoutJSON
? createMemo(fn)
: createMemo(fn, {
// eslint-disable-next-line @typescript-eslint/unbound-method
normalizer: JSON.stringify
});
}
+6 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-metadata",
"version": "0.95.2",
"version": "0.96.1",
"description": "Helpers to extract information from runtime metadata",
"main": "index.js",
"publishConfig": {
@@ -26,12 +26,12 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/type-metadata#readme",
"dependencies": {
"@babel/runtime": "^7.6.3",
"@polkadot/types": "^0.95.2",
"@polkadot/util": "^1.6.1",
"@polkadot/util-crypto": "^1.6.1"
"@babel/runtime": "^7.7.1",
"@polkadot/types": "^0.96.1",
"@polkadot/util": "^1.7.0-beta.5",
"@polkadot/util-crypto": "^1.7.0-beta.5"
},
"devDependencies": {
"@polkadot/keyring": "^1.6.1"
"@polkadot/keyring": "^1.7.0-beta.5"
}
}
+10 -10
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api",
"version": "0.95.2",
"version": "0.96.1",
"description": "Promise and RxJS wrappers around the Polkadot JS RPC",
"main": "index.js",
"keywords": [
@@ -26,16 +26,16 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api#readme",
"dependencies": {
"@babel/runtime": "^7.6.3",
"@polkadot/api-derive": "^0.95.2",
"@polkadot/api-metadata": "^0.95.2",
"@polkadot/keyring": "^1.6.1",
"@polkadot/rpc-core": "^0.95.2",
"@polkadot/rpc-provider": "^0.95.2",
"@polkadot/types": "^0.95.2",
"@polkadot/util-crypto": "^1.6.1"
"@babel/runtime": "^7.7.1",
"@polkadot/api-derive": "^0.96.1",
"@polkadot/api-metadata": "^0.96.1",
"@polkadot/keyring": "^1.7.0-beta.5",
"@polkadot/rpc-core": "^0.96.1",
"@polkadot/rpc-provider": "^0.96.1",
"@polkadot/types": "^0.96.1",
"@polkadot/util-crypto": "^1.7.0-beta.5"
},
"devDependencies": {
"@polkadot/keyring": "^1.6.1"
"@polkadot/keyring": "^1.7.0-beta.5"
}
}
+16 -12
View File
@@ -39,7 +39,7 @@ interface MetaDecoration {
toJSON: () => any;
}
export default abstract class Decorate<ApiType> extends Events {
export default abstract class Decorate<ApiType extends ApiTypes> extends Events {
// HACK Use BN import so decorateDerive works... yes, wtf.
protected __phantom = new BN(0);
@@ -111,7 +111,7 @@ export default abstract class Decorate<ApiType> extends Events {
* });
* ```
*/
public constructor (options: ApiOptions, type: ApiTypes, decorateMethod: DecorateMethod<ApiType>) {
constructor (options: ApiOptions, type: ApiTypes, decorateMethod: DecorateMethod<ApiType>) {
super();
const thisProvider = options.source
@@ -183,7 +183,7 @@ export default abstract class Decorate<ApiType> extends Events {
});
}
protected decorateRpc<ApiType> (rpc: RpcCore, decorateMethod: DecorateMethod<ApiType>): DecoratedRpc<ApiType, RpcInterface> {
protected decorateRpc<ApiType extends ApiTypes> (rpc: RpcCore, decorateMethod: DecorateMethod<ApiType>): DecoratedRpc<ApiType, RpcInterface> {
return rpc.sections.reduce((out, _sectionName): DecoratedRpc<ApiType, RpcInterface> => {
const sectionName = _sectionName as keyof DecoratedRpc<ApiType, RpcInterface>;
@@ -201,7 +201,7 @@ export default abstract class Decorate<ApiType> extends Events {
}, {} as unknown as DecoratedRpc<ApiType, RpcInterface>);
}
protected decorateMulti<ApiType> (decorateMethod: DecorateMethod<ApiType>): QueryableStorageMulti<ApiType> {
protected decorateMulti<ApiType extends ApiTypes> (decorateMethod: DecorateMethod<ApiType>): QueryableStorageMulti<ApiType> {
return decorateMethod((calls: QueryableStorageMultiArg<ApiType>[]): Observable<Codec[]> =>
this._rpcCore.state.subscribeStorage(
calls.map((arg: QueryableStorageMultiArg<ApiType>): [QueryableStorageEntry<ApiType>, ...Arg[]] =>
@@ -211,7 +211,7 @@ export default abstract class Decorate<ApiType> extends Events {
: [arg.creator] as any)));
}
protected decorateExtrinsics<ApiType> (extrinsics: ModulesWithCalls, decorateMethod: DecorateMethod<ApiType>): SubmittableExtrinsics<ApiType> {
protected decorateExtrinsics<ApiType extends ApiTypes> (extrinsics: ModulesWithCalls, decorateMethod: DecorateMethod<ApiType>): SubmittableExtrinsics<ApiType> {
const creator = createSubmittable(this._type, this._rx as ApiInterfaceRx, decorateMethod);
return Object.entries(extrinsics).reduce((out, [name, section]): SubmittableExtrinsics<ApiType> => {
@@ -225,14 +225,14 @@ export default abstract class Decorate<ApiType> extends Events {
}, creator as unknown as SubmittableExtrinsics<ApiType>);
}
private decorateExtrinsicEntry<ApiType> (method: CallFunction, creator: (value: Call | Uint8Array | string) => SubmittableExtrinsic<ApiType>): SubmittableExtrinsicFunction<ApiType> {
private decorateExtrinsicEntry<ApiType extends ApiTypes> (method: CallFunction, creator: (value: Call | Uint8Array | string) => SubmittableExtrinsic<ApiType>): SubmittableExtrinsicFunction<ApiType> {
const decorated = (...params: Arg[]): SubmittableExtrinsic<ApiType> =>
creator(method(...params));
return this.decorateFunctionMeta(method, decorated as any) as SubmittableExtrinsicFunction<ApiType>;
}
protected decorateStorage<ApiType> (storage: Storage, decorateMethod: DecorateMethod<ApiType>): QueryableStorage<ApiType> {
protected decorateStorage<ApiType extends ApiTypes> (storage: Storage, decorateMethod: DecorateMethod<ApiType>): QueryableStorage<ApiType> {
return Object.entries(storage).reduce((out, [name, section]): QueryableStorage<ApiType> => {
out[name] = Object.entries(section).reduce((out, [name, method]): QueryableModuleStorage<ApiType> => {
out[name] = this.decorateStorageEntry(method, decorateMethod);
@@ -244,7 +244,7 @@ export default abstract class Decorate<ApiType> extends Events {
}, {} as unknown as QueryableStorage<ApiType>);
}
private decorateStorageEntry<ApiType> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>): QueryableStorageEntry<ApiType> {
private decorateStorageEntry<ApiType extends ApiTypes> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>): QueryableStorageEntry<ApiType> {
// get the storage arguments, with DoubleMap as an array entry, otherwise spread
const getArgs = (...args: any[]): any[] => creator.meta.type.isDoubleMap
? [creator, args]
@@ -288,7 +288,7 @@ export default abstract class Decorate<ApiType> extends Events {
return this.decorateFunctionMeta(creator, decorated) as unknown as QueryableStorageEntry<ApiType>;
}
private decorateStorageEntryLinked<ApiType> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>): ReturnType<DecorateMethod<ApiType>> {
private decorateStorageEntryLinked<ApiType extends ApiTypes> (creator: StorageEntry, decorateMethod: DecorateMethod<ApiType>): ReturnType<DecorateMethod<ApiType>> {
const result: Map<Codec, [Codec, Linkage<Codec>]> = new Map();
let subject: BehaviorSubject<LinkageResult>;
let head: Codec | null = null;
@@ -356,11 +356,15 @@ export default abstract class Decorate<ApiType> extends Events {
);
}
protected decorateDerive (apiRx: ApiInterfaceRx, decorateMethod: DecorateMethod<ApiType>): DeriveAllSections<ApiType, ExactDerive> {
protected decorateDeriveRx (decorateMethod: DecorateMethod<ApiType>): DeriveAllSections<'rxjs', ExactDerive> {
// Pull in derive from api-derive
const derive = decorateDerive(apiRx, this._options.derives);
const derive = decorateDerive(this._rx as ApiInterfaceRx, this._options.derives);
return decorateSections<ApiType, ExactDerive>(derive, decorateMethod);
return decorateSections<'rxjs', ExactDerive>(derive, decorateMethod);
}
protected decorateDerive (decorateMethod: DecorateMethod<ApiType>): DeriveAllSections<ApiType, ExactDerive> {
return decorateSections<ApiType, ExactDerive>(this._rx.derive as DeriveAllSections<'rxjs', ExactDerive>, decorateMethod);
}
/**
+5 -4
View File
@@ -4,7 +4,7 @@
import { SignedBlock } from '@polkadot/types/interfaces';
import { RegistryTypes } from '@polkadot/types/types';
import { ApiBase, ApiInterfaceRx, ApiOptions, ApiTypes, DecorateMethod } from '../types';
import { ApiBase, ApiOptions, ApiTypes, DecorateMethod } from '../types';
import constantsFromMeta from '@polkadot/api-metadata/consts/fromMetadata';
import extrinsicsFromMeta from '@polkadot/api-metadata/extrinsics/fromMetadata';
@@ -53,10 +53,10 @@ const TYPES_SPEC: Record<string, Record<string, string>> = {
const l = logger('api/decorator');
export default abstract class Init<ApiType> extends Decorate<ApiType> {
export default abstract class Init<ApiType extends ApiTypes> extends Decorate<ApiType> {
private _healthTimer: NodeJS.Timeout | null = null;
public constructor (options: ApiOptions, type: ApiTypes, decorateMethod: DecorateMethod<ApiType>) {
constructor (options: ApiOptions, type: ApiTypes, decorateMethod: DecorateMethod<ApiType>) {
super(options, type, decorateMethod);
if (!this.hasSubscriptions) {
@@ -195,7 +195,8 @@ export default abstract class Init<ApiType> extends Decorate<ApiType> {
this._rx.consts = constants;
// derive is last, since it uses the decorated rx
this._derive = this.decorateDerive(this._rx as ApiInterfaceRx, this.decorateMethod);
this._rx.derive = this.decorateDeriveRx(this.rxDecorateMethod);
this._derive = this.decorateDerive(this.decorateMethod);
return true;
}
+10 -3
View File
@@ -6,7 +6,7 @@ import { RpcInterface } from '@polkadot/rpc-core/jsonrpc.types';
import { Hash, RuntimeVersion } from '@polkadot/types/interfaces';
import { InterfaceRegistry } from '@polkadot/types/interfaceRegistry';
import { CallFunction, InterfaceTypes, RegistryTypes, SignerPayloadRawBase } from '@polkadot/types/types';
import { ApiOptions, ApiTypes, DecoratedRpc, DecorateMethod, QueryableStorage, QueryableStorageMulti, SubmittableExtrinsics, Signer } from '../types';
import { ApiInterfaceRx, ApiOptions, ApiTypes, DecoratedRpc, DecorateMethod, QueryableStorage, QueryableStorageMulti, SubmittableExtrinsics, Signer } from '../types';
import { Constants } from '@polkadot/api-metadata/consts/types';
import { GenericCall, Metadata, createType, getTypeRegistry } from '@polkadot/types';
@@ -33,7 +33,7 @@ function assertResult<T> (value: T | undefined): T {
return value as T;
}
export default abstract class ApiBase<ApiType> extends Init<ApiType> {
export default abstract class ApiBase<ApiType extends ApiTypes> extends Init<ApiType> {
/**
* @description Create an instance of the class
*
@@ -52,7 +52,7 @@ export default abstract class ApiBase<ApiType> extends Init<ApiType> {
* });
* ```
*/
public constructor (options: ApiOptions = {}, type: ApiTypes, decorateMethod: DecorateMethod<ApiType>) {
constructor (options: ApiOptions = {}, type: ApiTypes, decorateMethod: DecorateMethod<ApiType>) {
super(options, type, decorateMethod);
}
@@ -192,6 +192,13 @@ export default abstract class ApiBase<ApiType> extends Init<ApiType> {
return assertResult(this._runtimeVersion);
}
/**
* @description The underlying Rx API interface
*/
public get rx (): Pick<ApiInterfaceRx, 'tx' | 'rpc'> {
return assertResult(this._rx as Pick<ApiInterfaceRx, 'tx' | 'rpc'>);
}
/**
* @description The type of this API instance, either 'rxjs' or 'promise'
*/
+2 -2
View File
@@ -60,7 +60,7 @@ function promiseTracker (resolve: (value: () => void) => void, reject: (value: E
/**
* @description Decorate method for ApiPromise, where the results are converted to the Promise equivalent
*/
function decorateMethod<Method extends AnyFunction> (method: Method, options?: DecorateMethodOptions): StorageEntryPromiseOverloads {
export function decorateMethod<Method extends AnyFunction> (method: Method, options?: DecorateMethodOptions): StorageEntryPromiseOverloads {
const needsCallback = options && options.methodName && options.methodName.includes('subscribe');
return function (...args: any[]): Promise<ObsInnerType<ReturnType<Method>>> | UnsubscribePromise {
@@ -213,7 +213,7 @@ export default class ApiPromise extends ApiBase<'promise'> {
* });
* ```
*/
public constructor (options?: ApiOptions) {
constructor (options?: ApiOptions) {
super(options, 'promise', decorateMethod);
this._isReadyPromise = new Promise((resolve): void => {
+1 -1
View File
@@ -27,7 +27,7 @@ export default class Combinator {
protected _subscriptions: UnsubscribePromise[] = [];
public constructor (fns: (CombinatorFunction | [CombinatorFunction, ...any[]])[], callback: CombinatorCallback) {
constructor (fns: (CombinatorFunction | [CombinatorFunction, ...any[]])[], callback: CombinatorCallback) {
this._callback = callback;
// eslint-disable-next-line @typescript-eslint/require-await
+2 -1
View File
@@ -2,6 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import ApiPromise from './Api';
import ApiPromise, { decorateMethod } from './Api';
export default ApiPromise;
export { decorateMethod };
+2 -2
View File
@@ -9,7 +9,7 @@ import { from, Observable } from 'rxjs';
import ApiBase from '../base';
function decorateMethod <Method extends AnyFunction> (method: Method): Method {
export function decorateMethod <Method extends AnyFunction> (method: Method): Method {
return method;
}
@@ -160,7 +160,7 @@ export default class ApiRx extends ApiBase<'rxjs'> {
* });
* ```
*/
public constructor (options?: ApiOptions) {
constructor (options?: ApiOptions) {
super(options, 'rxjs', decorateMethod);
this._isReadyRx = from(
+2 -1
View File
@@ -2,6 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import ApiRx from './Api';
import ApiRx, { decorateMethod } from './Api';
export default ApiRx;
export { decorateMethod };
+10 -1
View File
@@ -10,7 +10,7 @@ export default class SubmittableResult implements SubmittableResultImpl {
public readonly status: ExtrinsicStatus;
public constructor ({ events, status }: SubmittableResultValue) {
constructor ({ events, status }: SubmittableResultValue) {
this.events = events || [];
this.status = status;
}
@@ -27,6 +27,15 @@ export default class SubmittableResult implements SubmittableResultImpl {
return this.status.isFinalized;
}
/**
* @description Filters EventRecords for the specified method & section (there could be multiple)
*/
public filterRecords (section: string, method: string): EventRecord[] {
return this.events.filter(({ event }): boolean =>
event.section === section && event.method === method
);
}
/**
* @description Finds an EventRecord for the specified method & section
*/
+12 -12
View File
@@ -6,7 +6,7 @@
import { AccountId, Address, Call, Extrinsic, ExtrinsicEra, ExtrinsicStatus, Hash, Header, Index } from '@polkadot/types/interfaces';
import { Callback, Codec, Constructor, IKeyringPair, SignatureOptions } from '@polkadot/types/types';
import { ApiInterfaceRx, ApiTypes, SignerResult } from '../types';
import { SignerOptions, SubmittableExtrinsic, SubmittableResultImpl, SubmitableResultResult, SubmitableResultSubscription } from './types';
import { SignerOptions, SubmittableExtrinsic, SubmittableResultImpl, SubmittableResultResult, SubmittableResultSubscription } from './types';
import { Observable, combineLatest, of } from 'rxjs';
import { first, map, mergeMap, switchMap, tap } from 'rxjs/operators';
@@ -17,7 +17,7 @@ import { filterEvents, isKeyringPair } from '../util';
import ApiBase from '../base';
import SubmittableResult from './Result';
interface SubmittableOptions<ApiType> {
interface SubmittableOptions<ApiType extends ApiTypes> {
api: ApiInterfaceRx;
decorateMethod: ApiBase<ApiType>['decorateMethod'];
type: ApiTypes;
@@ -32,14 +32,14 @@ const DEFAULT_MORTAL_LENGTH = 5 * ONE_MINUTE;
const _Extrinsic: Constructor<Extrinsic> = ClassOf('Extrinsic');
export default class Submittable<ApiType> extends _Extrinsic implements SubmittableExtrinsic<ApiType> {
export default class Submittable<ApiType extends ApiTypes> extends _Extrinsic implements SubmittableExtrinsic<ApiType> {
private readonly _api: ApiInterfaceRx;
private readonly _decorateMethod: ApiBase<ApiType>['decorateMethod'];
private readonly _ignoreStatusCb: boolean;
public constructor (extrinsic: Call | Uint8Array | string, { api, decorateMethod, type }: SubmittableOptions<ApiType>) {
constructor (extrinsic: Call | Uint8Array | string, { api, decorateMethod, type }: SubmittableOptions<ApiType>) {
super(extrinsic, { version: api.extrinsicType });
this._api = api;
@@ -61,16 +61,16 @@ export default class Submittable<ApiType> extends _Extrinsic implements Submitta
}
// signAndSend with an immediate Hash result
public signAndSend (account: IKeyringPair | string | AccountId | Address, options?: Partial<SignerOptions>): SubmitableResultResult<ApiType>;
public signAndSend (account: IKeyringPair | string | AccountId | Address, options?: Partial<SignerOptions>): SubmittableResultResult<ApiType>;
// signAndSend with a subscription, i.e. callback provided
public signAndSend (account: IKeyringPair | string | AccountId | Address, statusCb: Callback<SubmittableResultImpl>): SubmitableResultSubscription<ApiType>;
public signAndSend (account: IKeyringPair | string | AccountId | Address, statusCb: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
// signAndSend with options and a callback
public signAndSend (account: IKeyringPair | string | AccountId | Address, options: Partial<SignerOptions>, statusCb?: Callback<SubmittableResultImpl>): SubmitableResultSubscription<ApiType>;
public signAndSend (account: IKeyringPair | string | AccountId | Address, options: Partial<SignerOptions>, statusCb?: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
// signAndSend implementation for all 3 cases above
public signAndSend (account: IKeyringPair | string | AccountId | Address, optionsOrStatus?: Partial<SignerOptions> | Callback<SubmittableResultImpl>, optionalStatusCb?: Callback<SubmittableResultImpl>): SubmitableResultResult<ApiType> | SubmitableResultSubscription<ApiType> {
public signAndSend (account: IKeyringPair | string | AccountId | Address, optionsOrStatus?: Partial<SignerOptions> | Callback<SubmittableResultImpl>, optionalStatusCb?: Callback<SubmittableResultImpl>): SubmittableResultResult<ApiType> | SubmittableResultSubscription<ApiType> {
const [options, statusCb] = this._makeSignAndSendOptions(optionsOrStatus, optionalStatusCb);
const isSubscription = this._api.hasSubscriptions && (this._ignoreStatusCb || !!statusCb);
const address = isKeyringPair(account) ? account.address : account.toString();
@@ -95,17 +95,17 @@ export default class Submittable<ApiType> extends _Extrinsic implements Submitta
: this._sendObservable(updateId);
})
) as Observable<Codec>) // FIXME This is wrong, SubmittableResult is _not_ a codec
)(statusCb) as SubmitableResultResult<ApiType> | SubmitableResultSubscription<ApiType>;
)(statusCb) as SubmittableResultResult<ApiType> | SubmittableResultSubscription<ApiType>;
}
// send with an immediate Hash result
public send (): SubmitableResultResult<ApiType>;
public send (): SubmittableResultResult<ApiType>;
// send with a status callback
public send (statusCb: Callback<SubmittableResultImpl>): SubmitableResultSubscription<ApiType>;
public send (statusCb: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
// send implementation for both immediate Hash and statusCb variants
public send (statusCb?: Callback<SubmittableResultImpl>): SubmitableResultResult<ApiType> | SubmitableResultSubscription<ApiType> {
public send (statusCb?: Callback<SubmittableResultImpl>): SubmittableResultResult<ApiType> | SubmittableResultSubscription<ApiType> {
const isSubscription = this._api.hasSubscriptions && (this._ignoreStatusCb || !!statusCb);
return this._decorateMethod(
@@ -9,11 +9,11 @@ import { SubmittableExtrinsic } from './types';
import ApiBase from '../base';
type Creator<ApiType> = (extrinsic: Call | Uint8Array | string) => SubmittableExtrinsic<ApiType>;
type Creator<ApiType extends ApiTypes> = (extrinsic: Call | Uint8Array | string) => SubmittableExtrinsic<ApiType>;
let Submittable: Constructor<SubmittableExtrinsic<any>>;
export default function createSubmittable<ApiType> (type: ApiTypes, api: ApiInterfaceRx, decorateMethod: ApiBase<ApiType>['decorateMethod']): Creator<ApiType> {
export default function createSubmittable<ApiType extends ApiTypes> (type: ApiTypes, api: ApiInterfaceRx, decorateMethod: ApiBase<ApiType>['decorateMethod']): Creator<ApiType> {
return (extrinsic: Call | Uint8Array | string): SubmittableExtrinsic<ApiType> => {
// HACK This is not great, but basically what we do here is to lazily only require the class
// right at the point it is actually needed - delaying initialization
+11 -9
View File
@@ -4,6 +4,7 @@
import { AccountId, Address, ExtrinsicStatus, EventRecord, Hash } from '@polkadot/types/interfaces';
import { AnyNumber, AnyU8a, Callback, IExtrinsic, IExtrinsicEra, IKeyringPair, SignatureOptions } from '@polkadot/types/types';
import { ApiTypes } from '../types';
import { Observable } from 'rxjs';
@@ -14,7 +15,8 @@ export interface SubmittableResultImpl {
readonly isError: boolean;
readonly isFinalized: boolean;
findRecord(section: string, method: string): EventRecord | undefined;
filterRecords (section: string, method: string): EventRecord[];
findRecord (section: string, method: string): EventRecord | undefined;
}
export interface SubmittableResultValue {
@@ -22,12 +24,12 @@ export interface SubmittableResultValue {
status: ExtrinsicStatus;
}
export type SubmitableResultResult<ApiType> =
export type SubmittableResultResult<ApiType extends ApiTypes> =
ApiType extends 'rxjs'
? Observable<SubmittableResultImpl>
: Promise<Hash>;
export type SubmitableResultSubscription<ApiType> =
export type SubmittableResultSubscription<ApiType extends ApiTypes> =
ApiType extends 'rxjs'
? Observable<SubmittableResultImpl>
: Promise<() => void>;
@@ -39,16 +41,16 @@ export interface SignerOptions {
tip?: AnyNumber;
}
export interface SubmittableExtrinsic<ApiType> extends IExtrinsic {
send(): SubmitableResultResult<ApiType>;
export interface SubmittableExtrinsic<ApiType extends ApiTypes> extends IExtrinsic {
send(): SubmittableResultResult<ApiType>;
send(statusCb: Callback<SubmittableResultImpl>): SubmitableResultSubscription<ApiType>;
send(statusCb: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
sign(account: IKeyringPair, _options: Partial<SignatureOptions>): this;
signAndSend(account: IKeyringPair | string | AccountId | Address, options?: Partial<SignerOptions>): SubmitableResultResult<ApiType>;
signAndSend(account: IKeyringPair | string | AccountId | Address, options?: Partial<SignerOptions>): SubmittableResultResult<ApiType>;
signAndSend(account: IKeyringPair | string | AccountId | Address, statusCb: Callback<SubmittableResultImpl>): SubmitableResultSubscription<ApiType>;
signAndSend(account: IKeyringPair | string | AccountId | Address, statusCb: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
signAndSend(account: IKeyringPair | string | AccountId | Address, options: Partial<SignerOptions>, statusCb?: Callback<SubmittableResultImpl>): SubmitableResultSubscription<ApiType>;
signAndSend(account: IKeyringPair | string | AccountId | Address, options: Partial<SignerOptions>, statusCb?: Callback<SubmittableResultImpl>): SubmittableResultSubscription<ApiType>;
}
+23 -20
View File
@@ -6,10 +6,11 @@ import { UserRpc } from '@polkadot/rpc-core/types';
import { Hash, RuntimeVersion } from '@polkadot/types/interfaces';
import { AnyFunction, Callback, CallFunction, Codec, CodecArg, RegistryTypes, SignatureOptions, SignerPayloadJSON, SignerPayloadRaw } from '@polkadot/types/types';
import { SubmittableResultImpl, SubmittableExtrinsic } from './submittable/types';
import { DeriveAllSections } from './util/decorate';
import BN from 'bn.js';
import { Observable } from 'rxjs';
import { DeriveCustom } from '@polkadot/api-derive';
import { DeriveCustom, ExactDerive } from '@polkadot/api-derive';
import { Constants } from '@polkadot/api-metadata/consts/types';
import { RpcInterface } from '@polkadot/rpc-core/jsonrpc.types';
import { ProviderInterface, ProviderInterfaceEmitted } from '@polkadot/rpc-provider/types';
@@ -51,11 +52,11 @@ export interface DecorateMethodOptions {
methodName?: string;
}
export type DecorateMethod<ApiType> = <Method extends (...args: any[]) => Observable<any>>(method: Method, options?: DecorateMethodOptions) => any;
export type DecorateMethod<ApiType extends ApiTypes> = <Method extends (...args: any[]) => Observable<any>>(method: Method, options?: DecorateMethodOptions) => any;
// Here are the return types of these parts of the api:
// - api.query.*.*: no exact typings
// - api.tx.*.*: SubmittableExtrinsic<ApiType>
// - api.tx.*.*: SubmittableExtrinsic<ApiType extends ApiTypes>
// - api.derive.*.*: MethodResult<ApiType, F>
// - api.rpc.*.*: no exact typings (for now, FIXME: should be MethodResult<ApiType, F>, like in derive)
@@ -73,22 +74,22 @@ export interface PromiseResult<F extends AnyFunction> {
}
// FIXME The day TS has higher-kinded types, we can remove this hardcoded stuff
export type PromiseOrObs<ApiType, T> = ApiType extends 'rxjs'
export type PromiseOrObs<ApiType extends ApiTypes, T> = ApiType extends 'rxjs'
? Observable<T>
: Promise<T>
// FIXME The day TS has higher-kinded types, we can remove this hardcoded stuff
export type MethodResult<ApiType, F extends AnyFunction> = ApiType extends 'rxjs'
export type MethodResult<ApiType extends ApiTypes, F extends AnyFunction> = ApiType extends 'rxjs'
? RxResult<F>
: PromiseResult<F>;
export type DecoratedRpcSection<ApiType, Section> = {
export type DecoratedRpcSection<ApiType extends ApiTypes, Section> = {
[Method in keyof Section]: Section[Method] extends AnyFunction
? MethodResult<ApiType, Section[Method]>
: never
}
export type DecoratedRpc<ApiType, AllSections> = {
export type DecoratedRpc<ApiType extends ApiTypes, AllSections> = {
[Section in keyof AllSections]: DecoratedRpcSection<ApiType, AllSections[Section]>
}
@@ -101,7 +102,7 @@ interface StorageEntryPromiseMulti {
<T extends Codec>(args: (CodecArg[] | CodecArg)[], callback: Callback<T[]>): UnsubscribePromise;
}
export interface StorageEntryBase<ApiType, F extends AnyFunction> {
export interface StorageEntryBase<ApiType extends ApiTypes, F extends AnyFunction> {
at: (hash: Hash | Uint8Array | string, ...args: Parameters<F>) => PromiseOrObs<ApiType, ObsInnerType<ReturnType<F>>>;
creator: StorageEntry;
hash: (...args: Parameters<F>) => PromiseOrObs<ApiType, Hash>;
@@ -118,33 +119,33 @@ export interface StorageEntryPromiseOverloads {
<T extends Codec>(arg1: CodecArg, arg2: CodecArg, callback: Callback<T>): UnsubscribePromise;
}
export type StorageEntryExact<ApiType, F extends AnyFunction> = MethodResult<ApiType, F> & StorageEntryBase<ApiType, F>
export type StorageEntryExact<ApiType extends ApiTypes, F extends AnyFunction> = MethodResult<ApiType, F> & StorageEntryBase<ApiType, F>
// This is the most generic typings we can have for a storage entry function
type GenericStorageEntryFunction = (arg1?: CodecArg, arg2?: CodecArg) => Observable<Codec>
export type QueryableStorageEntry<ApiType> =
export type QueryableStorageEntry<ApiType extends ApiTypes> =
ApiType extends 'rxjs'
? StorageEntryExact<'rxjs', GenericStorageEntryFunction>
: StorageEntryExact<'promise', GenericStorageEntryFunction> & StorageEntryPromiseOverloads;
export interface QueryableModuleStorage<ApiType> {
export interface QueryableModuleStorage<ApiType extends ApiTypes> {
[index: string]: QueryableStorageEntry<ApiType>;
}
export type QueryableStorageMultiArg<ApiType> =
export type QueryableStorageMultiArg<ApiType extends ApiTypes> =
QueryableStorageEntry<ApiType> |
[QueryableStorageEntry<ApiType>, ...CodecArg[]];
export interface QueryableStorageMultiBase<ApiType> {
export interface QueryableStorageMultiBase<ApiType extends ApiTypes> {
<T extends Codec[]>(calls: QueryableStorageMultiArg<ApiType>[]): Observable<T>;
}
export interface QueryableStorageMultiPromise<ApiType> {
export interface QueryableStorageMultiPromise<ApiType extends ApiTypes> {
<T extends Codec[]>(calls: QueryableStorageMultiArg<ApiType>[], callback: Callback<T>): UnsubscribePromise;
}
export type QueryableStorageMulti<ApiType> =
export type QueryableStorageMulti<ApiType extends ApiTypes> =
ApiType extends 'rxjs'
? QueryableStorageMultiBase<ApiType>
: QueryableStorageMultiPromise<ApiType>;
@@ -152,21 +153,21 @@ export type QueryableStorageMulti<ApiType> =
// QueryableStorageExact will hold the exact typed api.query.*.* generated from
// metadata. For now it's empty, it's ready to be module augmented.
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface QueryableStorageExact<ApiType> { }
export interface QueryableStorageExact<ApiType extends ApiTypes> { }
export interface QueryableStorage<ApiType> extends QueryableStorageExact<ApiType> {
export interface QueryableStorage<ApiType extends ApiTypes> extends QueryableStorageExact<ApiType> {
[index: string]: QueryableModuleStorage<ApiType>;
}
export interface SubmittableExtrinsicFunction<ApiType> extends CallFunction {
export interface SubmittableExtrinsicFunction<ApiType extends ApiTypes> extends CallFunction {
(...params: CodecArg[]): SubmittableExtrinsic<ApiType>;
}
export interface SubmittableModuleExtrinsics<ApiType> {
export interface SubmittableModuleExtrinsics<ApiType extends ApiTypes> {
[index: string]: SubmittableExtrinsicFunction<ApiType>;
}
export interface SubmittableExtrinsics<ApiType> {
export interface SubmittableExtrinsics<ApiType extends ApiTypes> {
(extrinsic: Uint8Array | string): SubmittableExtrinsic<ApiType>;
[index: string]: SubmittableModuleExtrinsics<ApiType>;
}
@@ -216,6 +217,8 @@ export interface ApiOptions {
// A smaller interface of ApiRx, used in derive and in SubmittableExtrinsic
export interface ApiInterfaceRx {
consts: Constants;
// TODO This needs to be typed correctly
derive: DeriveAllSections<'rxjs', ExactDerive>;
extrinsicType: number;
genesisHash: Hash;
hasSubscriptions: boolean;
+5 -5
View File
@@ -3,14 +3,14 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { AnyFunction } from '@polkadot/types/types';
import { DecorateMethod, MethodResult } from '../types';
import { ApiTypes, DecorateMethod, MethodResult } from '../types';
// Most generic typings for `api.derive.*.*`
type AnyDerive = Record<string, Record<string, AnyFunction>>;
// Exact typings for a particular section `api.derive.section.*`
type DeriveSection<ApiType, Section extends Record<string, AnyFunction>> = { [MethodName in keyof Section]: MethodResult<ApiType, Section[MethodName]> };
type DeriveSection<ApiType extends ApiTypes, Section extends Record<string, AnyFunction>> = { [MethodName in keyof Section]: MethodResult<ApiType, Section[MethodName]> };
// Exact typings for all sections `api.derive.*.*`
export type DeriveAllSections<ApiType, AllSections extends AnyDerive> = { [SectionName in keyof AllSections]: DeriveSection<ApiType, AllSections[SectionName]> };
export type DeriveAllSections<ApiType extends ApiTypes, AllSections extends AnyDerive> = { [SectionName in keyof AllSections]: DeriveSection<ApiType, AllSections[SectionName]> };
// A technically unsafe version of Object.keys(obj) that assumes that
// obj only has known properties of T
@@ -21,7 +21,7 @@ function keys<T extends object> (obj: T): (keyof T)[] {
/**
* This is a methods decorator which keeps all type information.
*/
function decorateMethods<ApiType, Section extends Record<string, AnyFunction>> (
function decorateMethods<ApiType extends ApiTypes, Section extends Record<string, AnyFunction>> (
section: Section,
decorateMethod: DecorateMethod<ApiType>
): DeriveSection<ApiType, Section> {
@@ -43,7 +43,7 @@ function decorateMethods<ApiType, Section extends Record<string, AnyFunction>> (
/**
* This is a section decorator which keeps all type information.
*/
export function decorateSections<ApiType, AllSections extends AnyDerive> (
export function decorateSections<ApiType extends ApiTypes, AllSections extends AnyDerive> (
allSections: AllSections,
decorateMethod: DecorateMethod<ApiType>
): DeriveAllSections<ApiType, AllSections> {
@@ -16,7 +16,7 @@ export class SingleAccountSigner implements Signer {
private signDelay: number;
public constructor (keyringPair: KeyringPair, signDelay = 0) {
constructor (keyringPair: KeyringPair, signDelay = 0) {
this.keyringPair = keyringPair;
this.signDelay = signDelay;
}

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