Compare commits

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

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

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

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

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

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

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

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

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

* Update packages/api/src/base/Decorate.ts
2020-10-19 19:43:58 +02:00
Github Actions bb6166e65f [CI Skip] release/stable 2.3.1
skip-checks: true
2020-10-18 14:45:15 +00:00
Jaco Greeff dec82380c3 2.3 (#2743)
* 2.3

* Apply suggestions from code review
2020-10-18 16:36:35 +02:00
Jaco Greeff a980d4ae11 Allow for max block limit on gas (#2744) 2020-10-18 15:57:08 +02:00
Github Actions 5c194b6f5f [CI Skip] release/beta 2.2.2-11
skip-checks: true
2020-10-17 15:43:30 +00:00
Jaco Greeff c4662e6fd8 Adjust types based on use (#2742)
* Adjust types based on use

* MetaRegistry

* Remove FIXME

* Split path extraction

* casing

* Rewrite

* Rewrite interfaces

* Remove unused vuepress
2020-10-17 17:34:45 +02:00
Github Actions 995de2012e [CI Skip] release/beta 2.2.2-10
skip-checks: true
2020-10-17 13:04:16 +00:00
Jaco Greeff b1a8c011f4 Cleanup with meta registry (#2741)
* Cleanup with meta registry

* Update packages/api-contract/src/MetaRegistry.ts

* Allow for Str type

* No .only

* Cleanups

* Registry references

* Cleanups, real registry

* Ordering

* Future-proof
2020-10-17 14:54:50 +02:00
Github Actions 86cd550ad3 [CI Skip] release/beta 2.2.2-9
skip-checks: true
2020-10-17 08:53:12 +00:00
Jaco Greeff 57529998f9 Remove (unused) typedoc (#2739)
* Remove (unused) typedoc

* rm typedoc package
2020-10-17 10:45:27 +02:00
Github Actions 0e0d733e65 [CI Skip] release/beta 2.2.2-8
skip-checks: true
2020-10-16 20:06:14 +00:00
Mokhtar NaamaniandJaco Greeff 773618acfb Disable websocket outgoing message fragmentation for w3cwebsocket (#2738)
* Disable websocket outgoing message fragmentation for w3cwebsocket

* Message fragmentation with 256K fragment size

Co-authored-by: Jaco Greeff <jacogr@gmail.com>

Co-authored-by: Jaco Greeff <jacogr@gmail.com>
2020-10-16 21:57:26 +02:00
Github Actions c5fcb0d06b [CI Skip] release/beta 2.2.2-7
skip-checks: true
2020-10-15 15:17:18 +00:00
Jaco Greeff e25272c986 Expose dispatch{Error, Info} on SubmittableResult (#2735)
* Expose dispatch{Error, Info} on SubmittableResult

* Cleanups

* De-dup
2020-10-15 17:07:14 +02:00
Jaco Greeff d389c6737e Cleanup README (& Call) (#2736) 2020-10-15 17:06:51 +02:00
Github Actions 9e1313f140 [CI Skip] release/beta 2.2.2-6
skip-checks: true
2020-10-15 07:32:02 +00:00
Jaco Greeff d2a2887d32 Add explicit normalizer test (#2730)
* Add explicit normalizer test

* More expansive

* nested
2020-10-15 09:22:04 +02:00
Github Actions b3d9549c0b [CI Skip] release/beta 2.2.2-5
skip-checks: true
2020-10-15 07:10:03 +00:00
Jaco Greeff 240cadd045 Bump deps (#2729) 2020-10-15 09:00:18 +02:00
Jaco Greeff d47faa4687 Fix memomization on BigInt values (#2728) 2020-10-15 08:59:48 +02:00
Github Actions 393c677a16 [CI Skip] release/beta 2.2.2-4
skip-checks: true
2020-10-14 23:40:43 +00:00
Jaco Greeff 074ddd8632 Add Polkadot update blocks for runtime 25 (#2725)
* Add Polkadot update blocks for runtime 25

* Update manual linting

* Bump deps
2020-10-15 01:32:04 +02:00
Jaco Greeff a8a10aec0c Manual testcase for Tuples (#2201)
* Manual testcase for Tuples

* Unused import

* Length check
2020-10-14 19:38:06 +02:00
Github Actions fed93e2459 [CI Skip] release/beta 2.2.2-3
skip-checks: true
2020-10-13 17:09:07 +00:00
Mark Robert Henderson 374df23011 Update warnings.ts to have the latest URLs (#2720)
Previously, 404s:

- https://polkadot.js.org/api/start/FAQ.html#i-cannot-send-transactions-from-my-node-template-based-chain
- https://polkadot.js.org/api/start/FAQ.html#using-a-non-current-master-node-i-have-issues-parsing-events

Changed to: 

- https://polkadot.js.org/docs/api/FAQ#i-cannot-send-transactions-from-my-node-template-based-chain
- https://polkadot.js.org/docs/api/FAQ#using-a-non-current-master-node-i-have-issues-parsing-events
2020-10-13 18:59:16 +02:00
Github Actions 9c098c3fbf [CI Skip] release/beta 2.2.2-2
skip-checks: true
2020-10-13 12:03:50 +00:00
Jaco Greeff 4e799858ad Cleanup type extraction overrides (#2719)
* Combine contract type get/init

* Cleanup type overrides
2020-10-13 13:54:14 +02:00
Github Actions ee6924324f [CI Skip] release/beta 2.2.2-1
skip-checks: true
2020-10-13 08:55:18 +00:00
Jaco Greeff 75f86bb43e Combine contract type get/init (#2718) 2020-10-13 10:44:50 +02:00
Github Actions bfd3113a55 [CI Skip] release/beta 2.2.2-0
skip-checks: true
2020-10-12 16:37:13 +00:00
Jaco Greeff 8d8d5bd7d7 Expose ABI messages on Contract/Blueprint (#2715)
* Expose ABI messages on Contract/Blueprint

* Rename actual files & exports

* Adjust .query signature (origin)

* Assert contracts.call
2020-10-12 18:27:47 +02:00
117 changed files with 3986 additions and 2488 deletions
-55
View File
File diff suppressed because one or more lines are too long
+55
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -12,4 +12,4 @@ plugins:
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
spec: "@yarnpkg/plugin-workspace-tools"
yarnPath: .yarn/releases/yarn-2.2.2.cjs
yarnPath: .yarn/releases/yarn-2.3.3.cjs
+46 -3
View File
@@ -1,6 +1,48 @@
# CHANGELOG
## 2.2.1 Oct 13, 2020
## 2.4.1 Oct 26, 2020
Upgrade priority: Low. No breaking changes, however it does move `api-contract` forward with additional features.
Contributed:
- Add support for both `{i,u}256` types on contracts (Thanks to https://github.com/seanyoung)
Changes:
- Add `.keysAt` & `.entriesAt` to query maps at a specific blockHash
- Adjust ordering of type injection, any `types: { ... }` definitions not have precedence
- Correctly format Tuples in both RPC and const definitions as part of type generation
- Add node-template to known types (tracking inside API), remove warnings for the spec
- Add initial implementation for new Substrate `MultiAddress` type
- Add `api.derive.chain.subscribeNewBlocks` for full block retrievals
- Contracts identifiers to `.{exec, read}('name', ...)` now matches on both snake_case and camelCase (consistency)
- Cleanup contracts serialization for messages to allow both to and from
- Add deserialization of contract events against the ABI
- Adjust contracts metadata parsing to be future-proof with type retrievals
- Add tests for Solang into contracts, re-organize layout per type
## 2.3.1 Oct 19, 2020
Upgrade priority: Low. Recommended for `api-contract` developers and those using large messages via Node.js WS.
Contributed:
- Adjust frame size for Node.js WebSockets (Thanks to https://github.com/mnaamani)
- Update warnings to reflect new docs URLs (Thanks to https://github.com/aphelionz)
Changes:
- Expose `dispatch{Error, Info}` on all `.tx` results (less boilerplate on info checks)
- Add missing primitive types inside contracts type parsing
- Adjust api-contract to expose `Contract.{query, tx}.<message>` and `Blueprint.tx.<constructor>`
- Rework contracts registry to be generic to all scale-info definitions
- Allow for auto-max weight on contract read/exec (useful in estimation)
- Fix memoization where `BigInt` params are passed
## 2.2.1 Oct 12, 2020
Upgrade priority: Low.
@@ -14,10 +56,11 @@ Contributed:
Changes:
- Introduce `OriginCaller` type (& apply to scheduler types)
- Adjust `ContractInfo` struct to cater for latest Substrate
- Adjust `ContractInfo` type for latest Substrate (contracts)
- Adjust `Schedule` type for latest Substrate (contracts)
- Allow snake_case to be handled transparently in structs
- Full new api-contract developer interfaces (Code, Blueprint, Contract)
- Rework Abi & Abi Registry use & parse (on-top-of-contributed) for efficiency & non-global clobber
- Rework Abi & Abi Registry use & parse (based on contributed) for efficiency & non-global clobber
- Allow `null` input on `Text` values in addition to existing `undefined`
- Remove all documentation after move to https://github.com/polkadot-js/docs repo
- Adjust type encoding from TypeDef, s/encodeType/encodeTypeDef/
View File
+12
View File
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=0.5, maximum-scale=1">
<meta http-equiv="refresh" content="0;URL='https://polkadot.js.org/docs/api/'" />
<title>Redirecting to https://polkadot.js.org/docs/api/</title>
</head>
<body>
Redirecting to <a href="https://polkadot.js.org/docs/api/">https://polkadot.js.org/docs/api/</a>
</body>
</html>
+12
View File
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=0.5, maximum-scale=1">
<meta http-equiv="refresh" content="0;URL='https://polkadot.js.org/docs/api/'" />
<title>Redirecting to https://polkadot.js.org/docs/api/</title>
</head>
<body>
Redirecting to <a href="https://polkadot.js.org/docs/api/">https://polkadot.js.org/docs/api/</a>
</body>
</html>
+8 -12
View File
@@ -24,18 +24,14 @@
"test:watch": "polkadot-dev-run-test --watch"
},
"devDependencies": {
"@babel/core": "^7.11.6",
"@babel/register": "^7.11.5",
"@babel/runtime": "^7.11.2",
"@polkadot/dev": "^0.58.1",
"@polkadot/ts": "^0.3.49",
"@babel/core": "^7.12.3",
"@babel/register": "^7.12.1",
"@babel/runtime": "^7.12.1",
"@polkadot/dev": "^0.59.6",
"@polkadot/ts": "^0.3.51",
"@polkadot/typegen": "workspace:packages/typegen",
"@types/jest": "^26.0.14",
"@vuepress/plugin-search": "^1.6.0",
"copyfiles": "^2.4.0",
"typedoc": "^0.19.2",
"typedoc-plugin-markdown": "^3.0.7",
"typedoc-plugin-no-inherit": "^1.2.0"
"@types/jest": "^26.0.15",
"copyfiles": "^2.4.0"
},
"version": "2.2.1"
"version": "2.4.1"
}
+6 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-contract",
"version": "2.2.1",
"version": "2.4.1",
"description": "Interfaces for interacting with contracts and contract ABIs",
"main": "index.js",
"keywords": [
@@ -26,11 +26,11 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-contract#readme",
"dependencies": {
"@babel/runtime": "^7.11.2",
"@polkadot/api": "2.2.1",
"@polkadot/rpc-core": "2.2.1",
"@polkadot/types": "2.2.1",
"@polkadot/util": "^3.5.1",
"@babel/runtime": "^7.12.1",
"@polkadot/api": "^2.4.1",
"@polkadot/rpc-core": "^2.4.1",
"@polkadot/types": "^2.4.1",
"@polkadot/util": "^3.6.1",
"bn.js": "^5.1.3",
"rxjs": "^6.6.3"
}
+15 -76
View File
@@ -7,88 +7,27 @@ import * as testContracts from '../test/contracts';
const abis: Record<string, any> = { ...testContracts };
function compare (name: string, messageIds: string[]): void {
try {
const inkAbi = new Abi(abis[name]);
expect(inkAbi.messages.map(({ identifier }) => identifier)).toEqual(messageIds);
} catch (error) {
console.error(error);
throw error;
interface JSONAbi {
spec: {
messages: {
name: string[] | string
}[]
}
}
describe('Abi', (): void => {
describe('construction', (): void => {
it('initializes from a contract ABI (flipper)', (): void => {
compare('flipper', ['flip', 'get']);
});
Object.entries(abis).forEach(([abiName, abi]) => {
it(`initializes from a contract ABI (${abiName})`, (): void => {
try {
const messageIds = (abi as JSONAbi).spec.messages.map(({ name }) => Array.isArray(name) ? name[0] : name);
const inkAbi = new Abi(abis[abiName]);
it('initializes from a contract ABI (incrementer)', (): void => {
compare('incrementer', ['inc', 'get']);
});
expect(inkAbi.messages.map(({ identifier }) => identifier)).toEqual(messageIds);
} catch (error) {
console.error(error);
it('initializes from a contract ABI (erc20)', (): void => {
compare('erc20', [
'total_supply',
'balance_of',
'allowance',
'transfer',
'approve',
'transfer_from'
]);
throw error;
}
});
it('initializes from a contract ABI (delegator)', (): void => {
compare('delegator', [
'get',
'change',
'switch'
]);
});
it('initializes from a contract ABI (dns)', (): void => {
compare('dns', [
'register',
'set_address',
'transfer',
'get_address'
]);
});
it('initializes from a contract ABI (erc721)', (): void => {
compare('erc721', [
'balance_of',
'owner_of',
'get_approved',
'is_approved_for_all',
'set_approval_for_all',
'approve',
'transfer',
'transfer_from',
'mint',
'burn'
]);
});
it('initializes from a contract ABI (multisig_plain)', (): void => {
compare('multisigPlain', [
'add_owner',
'remove_owner',
'replace_owner',
'change_requirement',
'submit_transaction',
'cancel_transaction',
'confirm_transaction',
'revoke_confirmation',
'invoke_transaction',
'eval_transaction'
]);
});
});
it('stores base project as JSON', (): void => {
expect(new Abi(abis.dns).json).toEqual(abis.dns);
});
});
+123 -21
View File
@@ -1,19 +1,19 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { AnyJson } from '@polkadot/types/types';
import { ChainProperties, InkConstructorSpec, InkMessageSpec } from '@polkadot/types/interfaces';
import { AbiConstructor, AbiMessage, AbiMessageParam } from './types';
import { AnyJson, Codec, CodecArg } from '@polkadot/types/types';
import { ChainProperties, ContractConstructorSpec, ContractEventSpec, ContractMessageSpec, ContractMessageParamSpec, ContractProject } from '@polkadot/types/interfaces';
import { AbiConstructor, AbiEvent, AbiMessage, AbiParam, DecodedEvent, DecodedMessage } from './types';
import { assert, isNumber, isObject, isString, stringCamelCase } from '@polkadot/util';
import { assert, compactAddLength, compactStripLength, isNumber, isObject, isString, stringCamelCase, u8aConcat, u8aToHex } from '@polkadot/util';
import ContractRegistry from './ContractRegistry';
import MetaRegistry from './MetaRegistry';
function findMessage <T extends AbiMessage> (list: T[], messageOrId: T | string | number): T {
const message = isNumber(messageOrId)
? list[messageOrId]
: isString(messageOrId)
? list.find(({ identifier }: T) => identifier === messageOrId.toString())
? list.find(({ identifier }) => [identifier, stringCamelCase(identifier)].includes(messageOrId.toString()))
: messageOrId;
assert(message, `Attempted to call an invalid contract interface, ${JSON.stringify(messageOrId)}`);
@@ -21,13 +21,19 @@ function findMessage <T extends AbiMessage> (list: T[], messageOrId: T | string
return message;
}
export default class Abi extends ContractRegistry {
export default class Abi {
readonly #events: AbiEvent[];
public readonly constructors: AbiConstructor[];
public readonly json: AnyJson;
public readonly messages: AbiMessage[];
public readonly project: ContractProject;
public readonly registry: MetaRegistry;
constructor (abiJson: AnyJson, chainProperties?: ChainProperties) {
const json = isString(abiJson)
? JSON.parse(abiJson) as AnyJson
@@ -35,27 +41,62 @@ export default class Abi extends ContractRegistry {
assert(isObject(json) && !Array.isArray(json) && json.metadataVersion && isObject(json.spec) && !Array.isArray(json.spec) && Array.isArray(json.spec.constructors) && Array.isArray(json.spec.messages), 'Invalid JSON ABI structure supplied, expected a recent metadata version');
super(json, chainProperties);
this.json = json;
this.constructors = this.project.spec.constructors.map((spec: InkConstructorSpec, index) =>
this._createBase(spec, index, {
this.registry = new MetaRegistry(chainProperties);
this.project = this.registry.createType('ContractProject', json);
this.registry.setMetaTypes(this.project.types);
this.project.types.forEach((_, index) =>
this.registry.getMetaTypeDef({ type: this.registry.createType('SiLookupTypeId', index + 1) })
);
this.constructors = this.project.spec.constructors.map((spec: ContractConstructorSpec, index) =>
this.#createMessage(spec, index, {
isConstructor: true
})
);
this.messages = this.project.spec.messages.map((spec: InkMessageSpec, index): AbiMessage => {
this.#events = this.project.spec.events.map((spec: ContractEventSpec, index) =>
this.#createEvent(spec, index)
);
this.messages = this.project.spec.messages.map((spec: ContractMessageSpec, index): AbiMessage => {
const typeSpec = spec.returnType.unwrapOr(null);
return this._createBase(spec, index, {
return this.#createMessage(spec, index, {
isMutating: spec.mutates.isTrue,
isPayable: spec.payable.isTrue,
returnType: typeSpec
? this.typeDefAt(typeSpec.type, { displayName: typeSpec.displayName.map((s) => s.toString()).join('::') || undefined })
? this.registry.getMetaTypeDef(typeSpec)
: null
});
});
}
/**
* Warning: Unstable API, bound to change
*/
public decodeEvent (data: Uint8Array): DecodedEvent {
const index = data[0];
const event = this.#events[index];
assert(event, `Unable to find event with index ${index}`);
return event.fromU8a(data.subarray(1));
}
/**
* Warning: Unstable API, bound to change
*/
public decodeConstructor (data: Uint8Array): DecodedMessage {
return this.#decodeMessage('message', this.constructors, data);
}
/**
* Warning: Unstable API, bound to change
*/
public decodeMessage (data: Uint8Array): DecodedMessage {
return this.#decodeMessage('message', this.messages, data);
}
public findConstructor (constructorOrId: AbiConstructor | string | number): AbiConstructor {
return findMessage(this.constructors, constructorOrId);
}
@@ -64,15 +105,14 @@ export default class Abi extends ContractRegistry {
return findMessage(this.messages, messageOrId);
}
private _createBase (spec: InkMessageSpec | InkConstructorSpec, index: number, add: Partial<AbiMessage> = {}): AbiMessage {
const identifier = spec.name.toString();
const args = spec.args.map((arg, index): AbiMessageParam => {
#createArgs = (args: ContractMessageParamSpec[], spec: unknown): AbiParam[] => {
return args.map((arg, index): AbiParam => {
try {
assert(isObject(arg.type), 'Invalid type definition found');
return {
name: stringCamelCase(arg.name.toString()),
type: this.typeDefAt(arg.type.type)
type: this.registry.getMetaTypeDef(arg.type)
};
} catch (error) {
console.error(`Error expanding argument ${index} in ${JSON.stringify(spec)}`);
@@ -80,14 +120,76 @@ export default class Abi extends ContractRegistry {
throw error;
}
});
}
return {
#createEvent = (spec: ContractEventSpec, index: number): AbiEvent => {
const args = this.#createArgs(spec.args, spec);
const event = {
args,
docs: spec.docs.map((doc) => doc.toString()),
fromU8a: (data: Uint8Array): DecodedEvent => ({
args: this.#decodeArgs(args, data),
event
}),
identifier: spec.name.toString(),
index
};
return event;
}
#createMessage = (spec: ContractMessageSpec | ContractConstructorSpec, index: number, add: Partial<AbiMessage> = {}): AbiMessage => {
const args = this.#createArgs(spec.args, spec);
const message = {
...add,
args,
docs: spec.docs.map((doc) => doc.toString()),
identifier,
fromU8a: (data: Uint8Array): DecodedMessage => ({
args: this.#decodeArgs(args, data),
message
}),
identifier: spec.name.toString(),
index,
selector: spec.selector
selector: spec.selector,
toU8a: (params: CodecArg[]) =>
this.#encodeArgs(spec, args, params)
};
return message;
}
#decodeArgs = (args: AbiParam[], data: Uint8Array): Codec[] => {
// for decoding we expect the input to be just the arg data, no selectors
// no length added (this allows use with events as well)
let offset = 0;
return args.map(({ type }): Codec => {
const value = this.registry.createType(type.type as 'Text', data.subarray(offset));
offset += value.encodedLength;
return value;
});
}
#decodeMessage = (type: 'constructor' | 'message', list: AbiMessage[], data: Uint8Array): DecodedMessage => {
const [, trimmed] = compactStripLength(data);
const selector = trimmed.subarray(0, 4);
const message = list.find((m) => m.selector.eq(selector));
assert(message, `Unable to find ${type} with selector ${u8aToHex(selector)}`);
return message.fromU8a(trimmed.subarray(4));
}
#encodeArgs = ({ name, selector }: ContractMessageSpec | ContractConstructorSpec, args: AbiParam[], data: CodecArg[]): Uint8Array => {
assert(data.length === args.length, `Expected ${args.length} arguments to contract message '${name.toString()}', found ${data.length}`);
return compactAddLength(
u8aConcat(
this.registry.createType('ContractSelector', selector).toU8a(),
...args.map(({ type }, index) => this.registry.createType(type.type as 'Text', data[index]).toU8a())
)
);
}
}
@@ -1,58 +0,0 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
/* eslint-disable @typescript-eslint/no-var-requires */
import fs from 'fs';
import path from 'path';
import ContractRegistry from './ContractRegistry';
import * as testContracts from '../test/contracts';
const abis: Record<string, any> = { ...testContracts };
function compare (name: string): void {
const inkRegistry = new ContractRegistry(abis[name]);
try {
const cmpPath = path.join(__dirname, `../test/compare/${name}.test.json`);
if (!fs.existsSync(cmpPath)) {
fs.writeFileSync(cmpPath, JSON.stringify(inkRegistry.typeDefs, null, 2), { flag: 'w' });
}
expect(inkRegistry.typeDefs).toEqual(require(cmpPath));
} catch (error) {
console.error(JSON.stringify(inkRegistry.typeDefs));
throw error;
}
}
describe('ContractRegistry', (): void => {
describe('construction', (): void => {
it('initializes from a contract ABI (flipper)', (): void => {
compare('flipper');
});
it('initializes from a contract ABI (incrementer)', (): void => {
compare('incrementer');
});
it('initializes from a contract ABI (erc20)', (): void => {
compare('erc20');
});
it('initializes from a contract ABI (dns)', (): void => {
compare('dns');
});
it('initializes from a contract ABI (erc721)', (): void => {
compare('erc721');
});
it('initializes from a contract ABI (multisig_plain)', (): void => {
compare('multisigPlain');
});
});
});
@@ -1,226 +0,0 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ChainProperties, InkProject, MtField, MtLookupTypeId, MtType, MtTypeDefArray, MtTypeDefVariant, MtTypeDefSequence, MtTypeDefTuple, MtVariant } from '@polkadot/types/interfaces';
import { AnyJson, Registry, TypeDef, TypeDefInfo } from '@polkadot/types/types';
import { assert, isUndefined } from '@polkadot/util';
import { TypeRegistry, withTypeString } from '@polkadot/types';
// convert the offset into project-specific, index-1
export function getRegistryOffset (id: MtLookupTypeId): number {
return id.toNumber() - 1;
}
export default class ContractRegistry {
public readonly typeDefs: TypeDef[] = [];
public readonly registry: Registry;
public readonly project: InkProject;
constructor (json: Record<string, AnyJson>, chainProperties?: ChainProperties) {
this.registry = new TypeRegistry();
if (chainProperties) {
this.registry.setChainProperties(chainProperties);
}
this.project = this.registry.createType('InkProject', json);
// Generate TypeDefs for each provided registry type
this.project.types.forEach((_, index) => this.setTypeDef(this.registry.createType('MtLookupTypeId', index + 1)));
}
public getAbiType (id: MtLookupTypeId): MtType {
const offset = getRegistryOffset(id);
const type = this.project.types[offset];
assert(!isUndefined(type), `getAbiType:: Unable to find ${id.toNumber()} in type values`);
return this.registry.createType('MtType', type);
}
public typeDefAt (id: MtLookupTypeId, extra: Pick<TypeDef, never> = {}): TypeDef {
if (!this.typeDefs[getRegistryOffset(id)]) {
this.setTypeDef(id);
}
return {
...this.typeDefs[getRegistryOffset(id)],
...extra
};
}
public setTypeDef (id: MtLookupTypeId): void {
const typeDef = this.extractType(this.getAbiType(id), id) as TypeDef;
this.typeDefs[getRegistryOffset(id)] = typeDef;
// We have a displayName for non-primitives and non-results
// FIXME here we protect against "Option: 'Option<...something...>' definitions (same with result)
if (typeDef.displayName && typeDef.info !== TypeDefInfo.Plain && !typeDef.type.startsWith(typeDef.displayName)) {
this.registry.register({ [typeDef.displayName]: typeDef.type });
}
}
private extractType (inkType: MtType, id: MtLookupTypeId): Pick<TypeDef, never> {
const path = [...inkType.path];
let typeDef;
if (inkType.path.join('::').startsWith('ink_env::types::') || inkType.def.isPrimitive) {
typeDef = this.extractPrimitive(inkType);
} else if (inkType.def.isComposite) {
typeDef = this.extractFields(inkType.def.asComposite.fields);
} else if (inkType.def.isVariant) {
typeDef = this.extractVariant(inkType.def.asVariant, id);
} else if (inkType.def.isArray) {
typeDef = this.extractArray(inkType.def.asArray);
} else if (inkType.def.isSequence) {
typeDef = this.extractSequence(inkType.def.asSequence, id);
} else if (inkType.def.isTuple) {
typeDef = this.extractTuple(inkType.def.asTuple);
} else {
throw new Error(`Invalid ink! type at index ${id.toString()}`);
}
const displayName = path.pop()?.toString();
return withTypeString({
...(displayName
? { displayName }
: {}
),
...(path.length > 1
? { namespace: path.map((segment) => segment.toString()).join('::') }
: {}
),
...(inkType.params.length > 0
? { params: inkType.params.map((id) => this.typeDefAt(id)) }
: {}
),
...typeDef
});
}
private extractVariant ({ variants }: MtTypeDefVariant, id: MtLookupTypeId): Pick<TypeDef, never> {
const { params, path } = this.getAbiType(id);
const specialVariant = path[0].toString();
if (specialVariant === 'Option') {
return {
info: TypeDefInfo.Option,
sub: this.typeDefAt(params[0])
};
} else if (specialVariant === 'Result') {
return {
info: TypeDefInfo.Result,
sub: params.map((param, index) => ({
name: ['Ok', 'Error'][index],
...this.typeDefAt(param)
}))
};
}
return {
info: TypeDefInfo.Enum,
sub: this.extractVariantSub(variants)
};
}
private extractVariantSub (variants: MtVariant[]): Pick<TypeDef, any>[] {
const isAllUnitVariants = variants.every(({ fields }) => fields.length === 0);
if (isAllUnitVariants) {
return variants.map(({ discriminant, name }) => ({
...(
discriminant.isSome
? { ext: { discriminant: discriminant.unwrap().toNumber() } }
: {}
),
info: TypeDefInfo.Plain,
name: name.toString(),
type: 'Null'
}));
}
return variants.map(({ fields, name }) => ({
...this.extractFields(fields),
name: name.toString()
}));
}
private extractFields (fields: MtField[]): Pick<TypeDef, any> {
const [isStruct, isTuple] = fields.reduce(([isAllNamed, isAllUnnamed], { name }) => ([
isAllNamed && name.isSome,
isAllUnnamed && name.isNone
]),
[true, true]);
let info;
// check for tuple first (no fields may be available)
if (isTuple) {
info = TypeDefInfo.Tuple;
} else if (isStruct) {
info = TypeDefInfo.Struct;
} else {
throw new Error('Invalid fields type detected, expected either Tuple or Struct');
}
const sub = fields.map(({ name, type }) => {
return {
...this.typeDefAt(type),
...(name.isSome ? { name: name.unwrap().toString() } : {})
};
});
return isTuple && sub.length === 1
? sub[0]
: { info, sub };
}
private extractArray ({ len: length, type }: MtTypeDefArray): Pick<TypeDef, never> {
assert(!length || length.toNumber() <= 256, 'ContractRegistry: Only support for [Type; <length>], where length > 256');
return {
info: TypeDefInfo.VecFixed,
length: length.toNumber(),
sub: this.typeDefAt(type)
};
}
private extractSequence ({ type }: MtTypeDefSequence, id: MtLookupTypeId): Pick<TypeDef, never> {
assert(!!type, `ContractRegistry: Invalid sequence type found at id ${id.toString()}`);
return {
info: TypeDefInfo.Vec,
sub: this.typeDefAt(type)
};
}
private extractTuple (ids: MtTypeDefTuple): Pick<TypeDef, never> {
return ids.length === 1
? this.typeDefAt(ids[0])
: {
info: TypeDefInfo.Tuple,
sub: ids.map((id) => this.typeDefAt(id))
};
}
private extractPrimitive (inkType: MtType): Pick<TypeDef, never> {
if (inkType.def.isPrimitive) {
return {
info: TypeDefInfo.Plain,
type: inkType.def.asPrimitive.type.toLowerCase()
};
} else if (inkType.path.length > 1) {
return {
info: TypeDefInfo.Plain,
type: inkType.path[inkType.path.length - 1].toString()
};
}
throw new Error('Invalid primitive type');
}
}
@@ -0,0 +1,38 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import fs from 'fs';
import path from 'path';
import Abi from './Abi';
import * as testContracts from '../test/contracts';
const abis: Record<string, any> = { ...testContracts };
describe('MetaRegistry', (): void => {
Object.keys(abis).forEach((abiName) => {
it(`initializes from a contract ABI (${abiName})`, (): void => {
const abi = new Abi(abis[abiName]);
try {
const cmpPath = path.join(__dirname, `../test/compare/${abiName}.test.json`);
if (!fs.existsSync(cmpPath)) {
fs.writeFileSync(cmpPath, JSON.stringify(abi.registry.metaTypeDefs, null, 2), { flag: 'w' });
}
// eslint-disable-next-line @typescript-eslint/no-var-requires
expect(abi.registry.metaTypeDefs).toEqual(require(cmpPath));
} catch (error) {
console.error(JSON.stringify(abi.registry.metaTypeDefs));
throw error;
}
});
});
it('stores base project as JSON', (): void => {
expect(new Abi(abis.dns).json).toEqual(abis.dns);
});
});
+249
View File
@@ -0,0 +1,249 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ContractDisplayName, ChainProperties, SiField, SiLookupTypeId, SiType, SiTypeDefArray, SiTypeDefVariant, SiTypeDefSequence, SiTypeDefTuple, SiVariant } from '@polkadot/types/interfaces';
import { InterfaceTypes, TypeDef, TypeDefInfo } from '@polkadot/types/types';
import { assert, isUndefined } from '@polkadot/util';
import { TypeRegistry, withTypeString } from '@polkadot/types';
interface PartialTypeSpec {
readonly type: SiLookupTypeId;
readonly displayName?: ContractDisplayName;
}
// convert the offset into project-specific, index-1
export function getRegistryOffset (id: SiLookupTypeId): number {
return id.toNumber() - 1;
}
const PRIMITIVE_ALIAS: Record<string, keyof InterfaceTypes> = {
Char: 'u32', // Rust char is 4-bytes
Str: 'Text'
};
export default class MetaRegistry extends TypeRegistry {
public readonly metaTypeDefs: TypeDef[] = [];
#siTypes: SiType[] = [];
constructor (chainProperties?: ChainProperties) {
super();
if (chainProperties) {
this.setChainProperties(chainProperties);
}
}
public setMetaTypes (metaTypes: SiType[]): void {
this.#siTypes = metaTypes;
}
public getMetaTypeDef (typeSpec: PartialTypeSpec): TypeDef {
const offset = getRegistryOffset(typeSpec.type);
let typeDef = this.metaTypeDefs[offset];
if (!typeDef) {
typeDef = this.#extract(this.#getMetaType(typeSpec.type), typeSpec.type);
this.metaTypeDefs[offset] = typeDef;
}
if (typeSpec.displayName && typeSpec.displayName.length) {
const displayName = typeSpec.displayName[typeSpec.displayName.length - 1].toString();
if (!typeDef.type.startsWith(displayName)) {
typeDef = {
...typeDef,
displayName,
type: ['Balance'].includes(displayName)
? 'Balance'
: typeDef.type
};
}
}
// Here we protect against the following cases
// - No displayName present, these are generally known primitives
// - displayName === type, these generate circular references
// - displayName Option & type Option<...something...>
if (typeDef.displayName && !this.hasType(typeDef.displayName) && !(typeDef.type === typeDef.displayName || typeDef.type.startsWith(`${typeDef.displayName}<`))) {
this.register({ [typeDef.displayName]: typeDef.type });
}
return typeDef;
}
#getMetaType = (id: SiLookupTypeId): SiType => {
const type = this.#siTypes[getRegistryOffset(id)];
assert(!isUndefined(type), `getMetaType:: Unable to find ${id.toNumber()} in type values`);
return this.createType('SiType', type);
}
#extract = (type: SiType, id: SiLookupTypeId): TypeDef => {
const path = [...type.path];
let typeDef: Omit<TypeDef, 'type'>;
// TODO solang?
if (type.path.join('::').startsWith('ink_env::types::')) {
typeDef = this.#extractPrimitivePath(type);
} else if (type.def.isPrimitive) {
typeDef = this.#extractPrimitive(type);
} else if (type.def.isComposite) {
typeDef = this.#extractFields(type.def.asComposite.fields);
} else if (type.def.isVariant) {
typeDef = this.#extractVariant(type.def.asVariant, id);
} else if (type.def.isArray) {
typeDef = this.#extractArray(type.def.asArray);
} else if (type.def.isSequence) {
typeDef = this.#extractSequence(type.def.asSequence, id);
} else if (type.def.isTuple) {
typeDef = this.#extractTuple(type.def.asTuple);
} else {
throw new Error(`Invalid ink! type at index ${id.toString()}`);
}
const displayName = path.pop()?.toString();
return withTypeString({
...(displayName
? { displayName }
: {}
),
...(path.length > 1
? { namespace: path.map((segment) => segment.toString()).join('::') }
: {}
),
...(type.params.length > 0
? { params: type.params.map((type) => this.getMetaTypeDef({ type })) }
: {}
),
...typeDef
});
}
#extractArray = ({ len: length, type }: SiTypeDefArray): Omit<TypeDef, 'type'> => {
assert(!length || length.toNumber() <= 256, 'MetaRegistry: Only support for [Type; <length>], where length > 256');
return {
info: TypeDefInfo.VecFixed,
length: length.toNumber(),
sub: this.getMetaTypeDef({ type })
};
}
#extractFields = (fields: SiField[]): Omit<TypeDef, 'type'> => {
const [isStruct, isTuple] = fields.reduce(([isAllNamed, isAllUnnamed], { name }) => ([
isAllNamed && name.isSome,
isAllUnnamed && name.isNone
]),
[true, true]);
let info;
// check for tuple first (no fields may be available)
if (isTuple) {
info = TypeDefInfo.Tuple;
} else if (isStruct) {
info = TypeDefInfo.Struct;
} else {
throw new Error('Invalid fields type detected, expected either Tuple or Struct');
}
const sub = fields.map(({ name, type }) => {
return {
...this.getMetaTypeDef({ type }),
...(name.isSome ? { name: name.unwrap().toString() } : {})
};
});
return isTuple && sub.length === 1
? sub[0]
: { info, sub };
}
#extractPrimitive = (type: SiType): TypeDef => {
const typeStr = type.def.asPrimitive.type.toString();
return {
info: TypeDefInfo.Plain,
type: PRIMITIVE_ALIAS[typeStr] || typeStr.toLowerCase()
};
}
#extractPrimitivePath = (type: SiType): TypeDef => {
return {
info: TypeDefInfo.Plain,
type: type.path[type.path.length - 1].toString()
};
}
#extractSequence = ({ type }: SiTypeDefSequence, id: SiLookupTypeId): Omit<TypeDef, 'type'> => {
assert(!!type, `ContractRegistry: Invalid sequence type found at id ${id.toString()}`);
return {
info: TypeDefInfo.Vec,
sub: this.getMetaTypeDef({ type })
};
}
#extractTuple = (ids: SiTypeDefTuple): Omit<TypeDef, 'type'> => {
return ids.length === 1
? this.getMetaTypeDef({ type: ids[0] })
: {
info: TypeDefInfo.Tuple,
sub: ids.map((type) => this.getMetaTypeDef({ type }))
};
}
#extractVariant = ({ variants }: SiTypeDefVariant, id: SiLookupTypeId): Omit<TypeDef, 'type'> => {
const { params, path } = this.#getMetaType(id);
const specialVariant = path[0].toString();
if (specialVariant === 'Option') {
return {
info: TypeDefInfo.Option,
sub: this.getMetaTypeDef({ type: params[0] })
};
} else if (specialVariant === 'Result') {
return {
info: TypeDefInfo.Result,
sub: params.map((type, index) => ({
name: ['Ok', 'Error'][index],
...this.getMetaTypeDef({ type })
}))
};
}
return {
info: TypeDefInfo.Enum,
sub: this.#extractVariantSub(variants)
};
}
#extractVariantSub = (variants: SiVariant[]): TypeDef[] => {
const isAllUnitVariants = variants.every(({ fields }) => fields.length === 0);
if (isAllUnitVariants) {
return variants.map(({ discriminant, name }) => ({
...(
discriminant.isSome
? { ext: { discriminant: discriminant.unwrap().toNumber() } }
: {}
),
info: TypeDefInfo.Plain,
name: name.toString(),
type: 'Null'
}));
}
return variants.map(({ fields, name }) =>
withTypeString({
...this.#extractFields(fields),
name: name.toString()
})
);
}
}
+24 -3
View File
@@ -6,13 +6,15 @@ import { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
import { AccountId, EventRecord, Hash } from '@polkadot/types/interfaces';
import { AnyJson, CodecArg, ISubmittableResult } from '@polkadot/types/types';
import { AbiConstructor } from '../types';
import { MapConstructorExec } from './types';
import BN from 'bn.js';
import { SubmittableResult } from '@polkadot/api';
import ApiBase from '@polkadot/api/base';
import { isUndefined, stringCamelCase } from '@polkadot/util';
import Abi from '../Abi';
import { applyOnEvent, encodeMessage } from '../util';
import { applyOnEvent } from '../util';
import Base from './Base';
import Contract from './Contract';
@@ -29,19 +31,38 @@ export class BlueprintSubmittableResult<ApiType extends ApiTypes> extends Submit
export default class Blueprint<ApiType extends ApiTypes> extends Base<ApiType> {
public readonly codeHash: Hash;
readonly #tx: MapConstructorExec<ApiType> = {};
constructor (api: ApiBase<ApiType>, abi: AnyJson | Abi, codeHash: string | Hash | Uint8Array, decorateMethod: DecorateMethod<ApiType>) {
super(api, abi, decorateMethod);
this.codeHash = this.registry.createType('Hash', codeHash);
this.abi.constructors.forEach((c): void => {
const messageName = stringCamelCase(c.identifier);
if (isUndefined(this.#tx[messageName])) {
this.#tx[messageName] = (endowment: BigInt | string | number | BN, gasLimit: BigInt | string | number | BN, ...params: CodecArg[]) =>
this.#deploy(c, endowment, gasLimit, params);
}
});
}
public createContract (constructorOrId: AbiConstructor | string| number, endowment: BigInt | string | number | BN, gasLimit: BigInt | string | number | BN, ...params: CodecArg[]): SubmittableExtrinsic<ApiType, BlueprintSubmittableResult<ApiType>> {
public get tx (): MapConstructorExec<ApiType> {
return this.#tx;
}
#deploy = (constructorOrId: AbiConstructor | string| number, endowment: BigInt | string | number | BN, gasLimit: BigInt | string | number | BN, params: CodecArg[]): SubmittableExtrinsic<ApiType, BlueprintSubmittableResult<ApiType>> => {
return this.api.tx.contracts
.instantiate(endowment, gasLimit, this.codeHash, encodeMessage(this.registry, this.abi.findConstructor(constructorOrId), params))
.instantiate(endowment, gasLimit, this.codeHash, this.abi.findConstructor(constructorOrId).toU8a(params))
.withResultTransform((result: ISubmittableResult) =>
new BlueprintSubmittableResult(result, applyOnEvent(result, 'Instantiated', (record: EventRecord) =>
new Contract<ApiType>(this.api, this.abi, record.event.data[1] as AccountId, this._decorateMethod)
))
);
}
public createContract (constructorOrId: AbiConstructor | string| number, endowment: BigInt | string | number | BN, gasLimit: BigInt | string | number | BN, ...params: CodecArg[]): SubmittableExtrinsic<ApiType, BlueprintSubmittableResult<ApiType>> {
return this.#deploy(constructorOrId, endowment, gasLimit, params);
}
}
+58 -29
View File
@@ -1,69 +1,90 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ApiTypes, DecorateMethod, ObsInnerType } from '@polkadot/api/types';
import { ApiTypes, DecorateMethod } from '@polkadot/api/types';
import { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
import { AccountId, ContractExecResult } from '@polkadot/types/interfaces';
import { AnyJson, CodecArg, IKeyringPair } from '@polkadot/types/types';
import { AnyJson, CodecArg } from '@polkadot/types/types';
import { AbiMessage, ContractCallOutcome } from '../types';
import { ContractRead, MapMessageExec, MapMessageRead } from './types';
import BN from 'bn.js';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { SubmittableResult } from '@polkadot/api';
import ApiBase from '@polkadot/api/base';
import { assert, isFunction } from '@polkadot/util';
import { assert, bnToBn, isFunction, isUndefined, stringCamelCase } from '@polkadot/util';
import Abi from '../Abi';
import { encodeMessage, formatData } from '../util';
import { formatData } from '../util';
import Base from './Base';
type ContractCallTypes = 'tx' | 'rpc';
type ContractCallResultSubscription<ApiType extends ApiTypes, CallType extends ContractCallTypes> = ApiType extends 'rxjs'
// eslint-disable-next-line no-use-before-define
? Observable<ContractCallResult<CallType>>
// eslint-disable-next-line no-use-before-define
: Promise<ObsInnerType<ContractCallResult<CallType>>>;
export interface ContractRead<ApiType extends ApiTypes> {
send (account: IKeyringPair | string | AccountId): ContractCallResultSubscription<ApiType, 'rpc'>;
}
export type ContractCallResult<CallType extends ContractCallTypes> = CallType extends 'rpc'
? Observable<ContractCallOutcome>
: Observable<SubmittableResult>;
const ERROR_NO_CALL = 'Your node does not expose the contracts.call RPC. This is most probably due to a runtime configuration.';
export default class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
public readonly address: AccountId;
readonly #tx: MapMessageExec<ApiType> = {};
readonly #query: MapMessageRead<ApiType> = {};
constructor (api: ApiBase<ApiType>, abi: AnyJson | Abi, address: string | AccountId, decorateMethod: DecorateMethod<ApiType>) {
super(api, abi, decorateMethod);
this.address = this.registry.createType('AccountId', address);
this.abi.messages.forEach((m): void => {
const messageName = stringCamelCase(m.identifier);
if (isUndefined(this.#tx[messageName])) {
this.#tx[messageName] = (value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, ...params: CodecArg[]) =>
this.#exec(m, value, gasLimit, params);
}
if (isUndefined(this.#query[messageName])) {
this.#query[messageName] = (origin: string | AccountId | Uint8Array, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, ...params: CodecArg[]) =>
this.#read(m, value, gasLimit, params).send(origin);
}
});
}
public get hasRpcContractsCall (): boolean {
return isFunction(this.api.rx.rpc.contracts?.call);
}
public exec (messageOrId: AbiMessage | string | number, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, ...params: CodecArg[]): SubmittableExtrinsic<ApiType> {
return this.api.tx.contracts.call(this.address, value, gasLimit, encodeMessage(this.registry, this.abi.findMessage(messageOrId), params));
public get query (): MapMessageRead<ApiType> {
assert(this.hasRpcContractsCall, ERROR_NO_CALL);
return this.#query;
}
public read (messageOrId: AbiMessage | string | number, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, ...params: CodecArg[]): ContractRead<ApiType> {
assert(this.hasRpcContractsCall, 'Your node does not support contract RPC read calls');
public get tx (): MapMessageExec<ApiType> {
return this.#tx;
}
#getGas = (_gasLimit: BigInt | BN | string | number): BN => {
const gasLimit = bnToBn(_gasLimit);
return gasLimit.lten(0)
? this.api.consts.system.maximumBlockWeight.muln(64).divn(100)
: gasLimit;
}
#exec = (messageOrId: AbiMessage | string | number, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, params: CodecArg[]): SubmittableExtrinsic<ApiType> => {
return this.api.tx.contracts.call(this.address, value, this.#getGas(gasLimit), this.abi.findMessage(messageOrId).toU8a(params));
}
#read = (messageOrId: AbiMessage | string | number, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, params: CodecArg[]): ContractRead<ApiType> => {
assert(this.hasRpcContractsCall, ERROR_NO_CALL);
const message = this.abi.findMessage(messageOrId);
return {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
send: this._decorateMethod((account: string | AccountId | Uint8Array): ContractCallResult<'rpc'> =>
send: this._decorateMethod((origin: string | AccountId | Uint8Array) =>
this.api.rx.rpc.contracts.call({
dest: this.address,
gasLimit,
inputData: encodeMessage(this.registry, message, params),
origin: account,
gasLimit: this.#getGas(gasLimit),
inputData: message.toU8a(params),
origin,
value
}).pipe(
map((result: ContractExecResult): ContractCallOutcome => ({
@@ -76,4 +97,12 @@ export default class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
)
};
}
public exec (messageOrId: AbiMessage | string | number, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, ...params: CodecArg[]): SubmittableExtrinsic<ApiType> {
return this.#exec(messageOrId, value, gasLimit, params);
}
public read (messageOrId: AbiMessage | string | number, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, ...params: CodecArg[]): ContractRead<ApiType> {
return this.#read(messageOrId, value, gasLimit, params);
}
}
+2 -2
View File
@@ -1,6 +1,6 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as Blueprint } from './Blueprint';
export { default as Code } from './Code';
export { default as Blueprint, BlueprintSubmittableResult } from './Blueprint';
export { default as Code, CodeSubmittableResult } from './Code';
export { default as Contract } from './Contract';
+31
View File
@@ -0,0 +1,31 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ApiTypes, ObsInnerType } from '@polkadot/api/types';
import { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
import { AccountId } from '@polkadot/types/interfaces';
import { CodecArg } from '@polkadot/types/types';
import { ContractCallOutcome } from '../types';
import BN from 'bn.js';
import { Observable } from 'rxjs';
type ContractCallResult<ApiType extends ApiTypes, T> = ApiType extends 'rxjs'
? Observable<Observable<T>>
: Promise<ObsInnerType<Observable<T>>>;
export interface ContractRead<ApiType extends ApiTypes> {
send (account: string | AccountId | Uint8Array): ContractCallResult<ApiType, ContractCallOutcome>;
}
export interface MapConstructorExec<ApiType extends ApiTypes> {
[message: string]: (endowment: BigInt | string | number | BN, gasLimit: BigInt | string | number | BN, ...params: CodecArg[]) => SubmittableExtrinsic<ApiType>;
}
export interface MapMessageExec<ApiType extends ApiTypes> {
[message: string]: (value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, ...params: CodecArg[]) => SubmittableExtrinsic<ApiType>;
}
export interface MapMessageRead<ApiType extends ApiTypes> {
[message: string]: (origin: AccountId | string | Uint8Array, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, ...params: CodecArg[]) => ContractCallResult<ApiType, ContractCallOutcome>;
}
+2 -5
View File
@@ -1,10 +1,7 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { CodeSubmittableResult } from './base/Code';
export { BlueprintSubmittableResult } from './base/Blueprint';
export { default as Abi } from './Abi';
export * from './rx';
export * from './promise';
export { Blueprint as BlueprintRx, Code as CodeRx, Contract as ContractRx } from './rx';
export { Blueprint as BlueprintPromise, Code as CodePromise, Contract as ContractPromise } from './promise';
@@ -8,9 +8,9 @@ import { ApiPromise } from '@polkadot/api';
import { decorateMethod } from '@polkadot/api/promise';
import Abi from '../Abi';
import Blueprint from '../base/Blueprint';
import BaseBlueprint from '../base/Blueprint';
export default class PromiseBlueprint extends Blueprint<'promise'> {
export default class Blueprint extends BaseBlueprint<'promise'> {
constructor (api: ApiPromise, abi: AnyJson | Abi, codeHash: string | Hash) {
super(api, abi, codeHash, decorateMethod);
}
@@ -6,9 +6,9 @@ import { decorateMethod } from '@polkadot/api/promise';
import { AnyJson } from '@polkadot/types/types';
import Abi from '../Abi';
import Code from '../base/Code';
import BaseCode from '../base/Code';
export default class PromiseCode extends Code<'promise'> {
export default class Code extends BaseCode<'promise'> {
constructor (api: ApiPromise, abi: AnyJson | Abi, wasm: Uint8Array | string | Buffer) {
super(api, abi, wasm, decorateMethod);
}
@@ -8,9 +8,9 @@ import { ApiPromise } from '@polkadot/api';
import { decorateMethod } from '@polkadot/api/promise';
import Abi from '../Abi';
import Contract from '../base/Contract';
import BaseContract from '../base/Contract';
export default class PromiseContract extends Contract<'promise'> {
export default class Contract extends BaseContract<'promise'> {
constructor (api: ApiPromise, abi: AnyJson | Abi, address: string | AccountId) {
super(api, abi, address, decorateMethod);
}
+3 -3
View File
@@ -1,6 +1,6 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as BlueprintPromise } from './PromiseBlueprint';
export { default as CodePromise } from './PromiseCode';
export { default as ContractPromise } from './PromiseContract';
export { default as Blueprint } from './Blueprint';
export { default as Code } from './Code';
export { default as Contract } from './Contract';
@@ -0,0 +1,7 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { BlueprintSubmittableResult as BaseBlueprintSubmittableResult, CodeSubmittableResult as BaseCodeSubmittableResult } from '../base';
export type BlueprintSubmittableResult = BaseBlueprintSubmittableResult<'promise'>;
export type CodeSubmittableResult = BaseCodeSubmittableResult<'promise'>;
@@ -8,9 +8,9 @@ import { ApiRx } from '@polkadot/api';
import { decorateMethod } from '@polkadot/api/rx';
import Abi from '../Abi';
import Blueprint from '../base/Blueprint';
import BaseBlueprint from '../base/Blueprint';
export default class RxBlueprint extends Blueprint<'rxjs'> {
export default class Blueprint extends BaseBlueprint<'rxjs'> {
constructor (api: ApiRx, abi: AnyJson | Abi, codeHash: string | Hash) {
super(api, abi, codeHash, decorateMethod);
}
@@ -7,9 +7,9 @@ import { ApiRx } from '@polkadot/api';
import { decorateMethod } from '@polkadot/api/rx';
import Abi from '../Abi';
import Code from '../base/Code';
import BaseCode from '../base/Code';
export default class RxCode extends Code<'rxjs'> {
export default class Code extends BaseCode<'rxjs'> {
constructor (api: ApiRx, abi: AnyJson | Abi, wasm: Uint8Array | string | Buffer) {
super(api, abi, wasm, decorateMethod);
}
@@ -8,9 +8,9 @@ import { ApiRx } from '@polkadot/api';
import { decorateMethod } from '@polkadot/api/rx';
import Abi from '../Abi';
import Contract from '../base/Contract';
import BaseContract from '../base/Contract';
export default class RxContract extends Contract<'rxjs'> {
export default class Contract extends BaseContract<'rxjs'> {
constructor (api: ApiRx, abi: AnyJson | Abi, address: string | AccountId) {
super(api, abi, address, decorateMethod);
}
+3 -3
View File
@@ -1,6 +1,6 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as BlueprintRx } from './RxBlueprint';
export { default as CodeRx } from './RxCode';
export { default as ContractRx } from './RxContract';
export { default as Blueprint } from './Blueprint';
export { default as Code } from './Code';
export { default as Contract } from './Contract';
+7
View File
@@ -0,0 +1,7 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { BlueprintSubmittableResult as BaseBlueprintSubmittableResult, CodeSubmittableResult as BaseCodeSubmittableResult } from '../base';
export type BlueprintSubmittableResult = BaseBlueprintSubmittableResult<'promise'>;
export type CodeSubmittableResult = BaseCodeSubmittableResult<'promise'>;
+26 -6
View File
@@ -2,8 +2,8 @@
// SPDX-License-Identifier: Apache-2.0
import { ApiTypes } from '@polkadot/api/types';
import { ContractExecResult, InkSelector } from '@polkadot/types/interfaces';
import { Codec, TypeDef } from '@polkadot/types/types';
import { ContractExecResult, ContractSelector } from '@polkadot/types/interfaces';
import { Codec, CodecArg, TypeDef } from '@polkadot/types/types';
import ApiBase from '@polkadot/api/base';
import Abi from './Abi';
@@ -16,21 +16,31 @@ export interface ContractBase<ApiType extends ApiTypes> {
messages: AbiMessage[];
}
export interface AbiMessageParam {
export interface AbiParam {
name: string;
type: TypeDef;
}
export interface AbiMessage {
args: AbiMessageParam[];
export interface AbiEvent {
args: AbiParam[];
docs: string[];
fromU8a: (data: Uint8Array) => DecodedEvent;
identifier: string;
index: number;
}
export interface AbiMessage {
args: AbiParam[];
docs: string[];
fromU8a: (data: Uint8Array) => DecodedMessage;
identifier: string;
index: number;
isConstructor?: boolean;
isMutating?: boolean;
isPayable?: boolean;
returnType?: TypeDef | null;
selector: InkSelector;
selector: ContractSelector;
toU8a: (params: CodecArg[]) => Uint8Array;
}
export type AbiConstructor = AbiMessage;
@@ -44,3 +54,13 @@ export interface ContractCallOutcome {
output: Codec | null;
result: ContractExecResult;
}
export interface DecodedEvent {
args: Codec[];
event: AbiEvent;
}
export interface DecodedMessage {
args: Codec[];
message: AbiMessage;
}
+2 -24
View File
@@ -3,12 +3,9 @@
import { SubmittableResult } from '@polkadot/api';
import { EventRecord } from '@polkadot/types/interfaces';
import { Codec, CodecArg, Registry, TypeDef } from '@polkadot/types/types';
import { AbiConstructor, AbiMessage } from './types';
import { Codec, Registry, TypeDef } from '@polkadot/types/types';
import { Raw, createClass, createTypeUnsafe, encodeTypeDef } from '@polkadot/types';
import { assert, compactAddLength } from '@polkadot/util';
import { Raw, createTypeUnsafe } from '@polkadot/types';
export function formatData (registry: Registry, data: Raw, { type }: TypeDef): Codec {
return createTypeUnsafe(registry, type, [data], true);
@@ -25,22 +22,3 @@ export function applyOnEvent <T> (result: SubmittableResult, type: 'CodeStored'
return undefined;
}
export function encodeMessage (registry: Registry, message: AbiMessage | AbiConstructor, params: CodecArg[]): Uint8Array {
assert(message, 'Attempted to call an invalid contract message');
assert(params.length === message.args.length, `Expected ${message.args.length} arguments to contract message '${message.identifier}', found ${params.length}`);
const Clazz = createClass(registry, JSON.stringify(
message.args.reduce((r: Record<string, any>, { name, type }): Record<string, any> => {
r[name] = type.displayName || encodeTypeDef(type);
return r;
}, { __selector: 'InkSelector' })
));
return compactAddLength(new Clazz(registry, message.args.reduce((r: Record<string, CodecArg>, { name }, index): Record<string, CodecArg> => {
r[name] = params[index];
return r;
}, { __selector: message.selector })).toU8a());
}
@@ -0,0 +1,31 @@
[
{
"displayName": "AccountId",
"namespace": "ink_env::types",
"info": 6,
"type": "AccountId"
},
{
"info": 12,
"length": 32,
"sub": {
"info": 6,
"type": "u8"
},
"type": "[u8;32]"
},
{
"info": 6,
"type": "u8"
},
{
"info": 6,
"type": "i32"
},
{
"displayName": "Hash",
"namespace": "ink_env::types",
"info": 6,
"type": "Hash"
}
]
@@ -0,0 +1,6 @@
[
{
"info": 6,
"type": "u256"
}
]
@@ -488,7 +488,8 @@
{
"info": 10,
"sub": [],
"name": "Confirmed"
"name": "Confirmed",
"type": "()"
},
{
"info": 6,
@@ -509,7 +510,8 @@
{
"info": 10,
"sub": [],
"name": "Confirmed"
"name": "Confirmed",
"type": "()"
},
{
"info": 6,
@@ -677,4 +679,4 @@
},
"type": "Option<Vec<u8>>"
}
]
]
@@ -0,0 +1,247 @@
[
{
"info": 6,
"type": "u128"
},
{
"displayName": "Header",
"namespace": "ink_storage::collections::stash",
"info": 9,
"sub": [
{
"info": 6,
"type": "u32",
"name": "last_vacant"
},
{
"info": 6,
"type": "u32",
"name": "len"
},
{
"info": 6,
"type": "u32",
"name": "len_entries"
}
],
"type": "{\"last_vacant\":\"u32\",\"len\":\"u32\",\"len_entries\":\"u32\"}"
},
{
"info": 6,
"type": "u32"
},
{
"displayName": "Entry",
"namespace": "ink_storage::collections::stash",
"params": [
{
"displayName": "AccountId",
"namespace": "ink_env::types",
"info": 6,
"type": "AccountId"
}
],
"info": 3,
"sub": [
{
"displayName": "VacantEntry",
"namespace": "ink_storage::collections::stash",
"info": 9,
"sub": [
{
"info": 6,
"type": "u32",
"name": "next"
},
{
"info": 6,
"type": "u32",
"name": "prev"
}
],
"type": "{\"next\":\"u32\",\"prev\":\"u32\"}",
"name": "Vacant"
},
{
"displayName": "AccountId",
"namespace": "ink_env::types",
"info": 6,
"type": "AccountId",
"name": "Occupied"
}
],
"type": "{\"_enum\":{\"Vacant\":\"VacantEntry\",\"Occupied\":\"AccountId\"}}"
},
{
"displayName": "AccountId",
"namespace": "ink_env::types",
"info": 6,
"type": "AccountId"
},
{
"info": 12,
"length": 32,
"sub": {
"info": 6,
"type": "u8"
},
"type": "[u8;32]"
},
{
"info": 6,
"type": "u8"
},
{
"displayName": "VacantEntry",
"namespace": "ink_storage::collections::stash",
"info": 9,
"sub": [
{
"info": 6,
"type": "u32",
"name": "next"
},
{
"info": 6,
"type": "u32",
"name": "prev"
}
],
"type": "{\"next\":\"u32\",\"prev\":\"u32\"}"
},
{
"displayName": "ValueEntry",
"namespace": "ink_storage::collections::hashmap",
"params": [
{
"info": 6,
"type": "u128"
}
],
"info": 9,
"sub": [
{
"info": 6,
"type": "u128",
"name": "value"
},
{
"info": 6,
"type": "u32",
"name": "key_index"
}
],
"type": "{\"value\":\"u128\",\"key_index\":\"u32\"}"
},
{
"displayName": "Entry",
"namespace": "ink_storage::collections::stash",
"params": [
{
"info": 10,
"sub": [
{
"displayName": "AccountId",
"namespace": "ink_env::types",
"info": 6,
"type": "AccountId"
},
{
"displayName": "AccountId",
"namespace": "ink_env::types",
"info": 6,
"type": "AccountId"
}
],
"type": "(AccountId, AccountId)"
}
],
"info": 3,
"sub": [
{
"displayName": "VacantEntry",
"namespace": "ink_storage::collections::stash",
"info": 9,
"sub": [
{
"info": 6,
"type": "u32",
"name": "next"
},
{
"info": 6,
"type": "u32",
"name": "prev"
}
],
"type": "{\"next\":\"u32\",\"prev\":\"u32\"}",
"name": "Vacant"
},
{
"info": 10,
"sub": [
{
"displayName": "AccountId",
"namespace": "ink_env::types",
"info": 6,
"type": "AccountId"
},
{
"displayName": "AccountId",
"namespace": "ink_env::types",
"info": 6,
"type": "AccountId"
}
],
"type": "(AccountId, AccountId)",
"name": "Occupied"
}
],
"type": "{\"_enum\":{\"Vacant\":\"VacantEntry\",\"Occupied\":\"(AccountId, AccountId)\"}}"
},
{
"info": 10,
"sub": [
{
"displayName": "AccountId",
"namespace": "ink_env::types",
"info": 6,
"type": "AccountId"
},
{
"displayName": "AccountId",
"namespace": "ink_env::types",
"info": 6,
"type": "AccountId"
}
],
"type": "(AccountId, AccountId)"
},
{
"info": 6,
"type": "Text"
},
{
"info": 6,
"type": "bool"
},
{
"displayName": "Option",
"params": [
{
"displayName": "AccountId",
"namespace": "ink_env::types",
"info": 6,
"type": "AccountId"
}
],
"info": 5,
"sub": {
"displayName": "AccountId",
"namespace": "ink_env::types",
"info": 6,
"type": "AccountId"
},
"type": "Option<AccountId>"
}
]
@@ -1,10 +1,6 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as delegator } from './delegator.json';
export { default as dns } from './dns.json';
export { default as erc20 } from './erc20.json';
export { default as erc721 } from './erc721.json';
export { default as flipper } from './flipper.json';
export { default as incrementer } from './incrementer.json';
export { default as multisigPlain } from './multisig_plain.json';
export * from './ink';
export * from './solang';
export * from './user';
@@ -0,0 +1,10 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as delegator } from './delegator.json';
export { default as dns } from './dns.json';
export { default as erc20 } from './erc20.json';
export { default as erc721 } from './erc721.json';
export { default as flipper } from './flipper.json';
export { default as incrementer } from './incrementer.json';
export { default as multisigPlain } from './multisig_plain.json';
@@ -0,0 +1,4 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as ints256 } from './ints256.json';
@@ -0,0 +1,113 @@
{
"contract": {
"authors": [
"Sean Young <sean@mess.org>"
],
"description": "Test 256 bits types",
"name": "ints256",
"version": "0.0.1"
},
"metadataVersion": "0.1.0",
"source": {
"compiler": "solang 0.1.4",
"hash": "0xa85fb5c61a09d71dce84c15a8bd87e6f4eafac498a1aec3869e8cf7ea4389697",
"language": "Solidity 0.1.4"
},
"spec": {
"constructors": [
{
"args": [],
"docs": [
""
],
"name": "new",
"selector": "0x861731d5"
}
],
"events": [],
"messages": [
{
"args": [
{
"name": "a",
"type": {
"display_name": [
"u256"
],
"type": 1
}
},
{
"name": "b",
"type": {
"display_name": [
"u256"
],
"type": 1
}
}
],
"docs": [
"Multiply two 256 bit values\n\n"
],
"mutates": false,
"name": "multiply",
"payable": false,
"return_type": {
"display_name": [
"u256"
],
"type": 1
},
"selector": "0x165c4a16"
},
{
"args": [
{
"name": "a",
"type": {
"display_name": [
"u256"
],
"type": 1
}
},
{
"name": "b",
"type": {
"display_name": [
"u256"
],
"type": 1
}
}
],
"docs": [
"Add two 256 bit values\n\n"
],
"mutates": false,
"name": "add",
"payable": false,
"return_type": {
"display_name": [
"u256"
],
"type": 1
},
"selector": "0x771602f7"
}
]
},
"storage": {
"struct": {
"fields": []
}
},
"types": [
{
"def": {
"primitive": "u256"
}
}
]
}
@@ -0,0 +1,13 @@
/// @title Test 256 bits types
/// @author Sean Young <sean@mess.org>
contract ints256 {
/// Multiply two 256 bit values
function multiply(uint256 a, uint256 b) public pure returns (uint256) {
return a * b;
}
/// Add two 256 bit values
function add(uint256 a, uint256 b) public pure returns (uint256) {
return a + b;
}
}
@@ -0,0 +1,4 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as withString } from './withString.json';
@@ -0,0 +1,777 @@
{
"metadataVersion": "0.1.0",
"source": {
"hash": "0xafcd0acf1a747cca1febe5bad81a6c0244a381ceb02635ab1069a1a396adda3f",
"language": "ink! 3.0.0-rc1",
"compiler": "rustc 1.49.0-nightly"
},
"contract": {
"name": "erc20",
"version": "0.1.0",
"authors": [
"[your_name] <[your_email]>"
]
},
"spec": {
"constructors": [
{
"args": [
{
"name": "initial_supply",
"type": {
"displayName": [
"Balance"
],
"type": 1
}
},
{
"name": "_name",
"type": {
"displayName": [
"String"
],
"type": 12
}
},
{
"name": "_symbol",
"type": {
"displayName": [
"String"
],
"type": 12
}
}
],
"docs": [],
"name": [
"new"
],
"selector": "0xd183512b"
}
],
"docs": [],
"events": [
{
"args": [
{
"docs": [],
"indexed": true,
"name": "from",
"type": {
"displayName": [
"Option"
],
"type": 14
}
},
{
"docs": [],
"indexed": true,
"name": "to",
"type": {
"displayName": [
"Option"
],
"type": 14
}
},
{
"docs": [],
"indexed": true,
"name": "value",
"type": {
"displayName": [
"Balance"
],
"type": 1
}
}
],
"docs": [],
"name": "Transfer"
},
{
"args": [
{
"docs": [],
"indexed": true,
"name": "owner",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
},
{
"docs": [],
"indexed": true,
"name": "spender",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
},
{
"docs": [],
"indexed": true,
"name": "value",
"type": {
"displayName": [
"Balance"
],
"type": 1
}
}
],
"docs": [],
"name": "Approval"
}
],
"messages": [
{
"args": [],
"docs": [],
"mutates": false,
"name": [
"total_supply"
],
"payable": false,
"returnType": {
"displayName": [
"Balance"
],
"type": 1
},
"selector": "0xdcb736b5"
},
{
"args": [],
"docs": [],
"mutates": false,
"name": [
"name"
],
"payable": false,
"returnType": {
"displayName": [
"String"
],
"type": 12
},
"selector": "0xa0a95494"
},
{
"args": [],
"docs": [],
"mutates": false,
"name": [
"symbol"
],
"payable": false,
"returnType": {
"displayName": [
"String"
],
"type": 12
},
"selector": "0x57178a4a"
},
{
"args": [
{
"name": "owner",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
}
],
"docs": [],
"mutates": false,
"name": [
"balance_of"
],
"payable": false,
"returnType": {
"displayName": [
"Balance"
],
"type": 1
},
"selector": "0x56e929b2"
},
{
"args": [
{
"name": "owner",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
},
{
"name": "spender",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
}
],
"docs": [],
"mutates": false,
"name": [
"allowance"
],
"payable": false,
"returnType": {
"displayName": [
"Balance"
],
"type": 1
},
"selector": "0xf3cfff66"
},
{
"args": [
{
"name": "to",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
},
{
"name": "value",
"type": {
"displayName": [
"Balance"
],
"type": 1
}
}
],
"docs": [],
"mutates": true,
"name": [
"transfer"
],
"payable": false,
"returnType": {
"displayName": [
"bool"
],
"type": 13
},
"selector": "0xfae3a09d"
},
{
"args": [
{
"name": "spender",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
},
{
"name": "value",
"type": {
"displayName": [
"Balance"
],
"type": 1
}
}
],
"docs": [],
"mutates": true,
"name": [
"approve"
],
"payable": false,
"returnType": {
"displayName": [
"bool"
],
"type": 13
},
"selector": "0x03d0e114"
},
{
"args": [
{
"name": "from",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
},
{
"name": "to",
"type": {
"displayName": [
"AccountId"
],
"type": 5
}
},
{
"name": "value",
"type": {
"displayName": [
"Balance"
],
"type": 1
}
}
],
"docs": [],
"mutates": true,
"name": [
"transfer_from"
],
"payable": false,
"returnType": {
"displayName": [
"bool"
],
"type": 13
},
"selector": "0xfcfb2ccd"
}
]
},
"storage": {
"struct": {
"fields": [
{
"layout": {
"cell": {
"key": "0x0000000000000000000000000000000000000000000000000000000000000000",
"ty": 1
}
},
"name": "total_supply"
},
{
"layout": {
"struct": {
"fields": [
{
"layout": {
"struct": {
"fields": [
{
"layout": {
"cell": {
"key": "0x0100000000000000000000000000000000000000000000000000000000000000",
"ty": 2
}
},
"name": "header"
},
{
"layout": {
"struct": {
"fields": [
{
"layout": {
"cell": {
"key": "0x0200000000000000000000000000000000000000000000000000000000000000",
"ty": 3
}
},
"name": "len"
},
{
"layout": {
"array": {
"cellsPerElem": 1,
"layout": {
"cell": {
"key": "0x0200000001000000000000000000000000000000000000000000000000000000",
"ty": 4
}
},
"len": 4294967295,
"offset": "0x0300000000000000000000000000000000000000000000000000000000000000"
}
},
"name": "elems"
}
]
}
},
"name": "entries"
}
]
}
},
"name": "keys"
},
{
"layout": {
"hash": {
"layout": {
"cell": {
"key": "0x0300000001000000000000000000000000000000000000000000000000000000",
"ty": 9
}
},
"offset": "0x0200000001000000000000000000000000000000000000000000000000000000",
"strategy": {
"hasher": "Blake2x256",
"postfix": "",
"prefix": "0x696e6b20686173686d6170"
}
}
},
"name": "values"
}
]
}
},
"name": "balances"
},
{
"layout": {
"struct": {
"fields": [
{
"layout": {
"struct": {
"fields": [
{
"layout": {
"cell": {
"key": "0x0300000001000000000000000000000000000000000000000000000000000000",
"ty": 2
}
},
"name": "header"
},
{
"layout": {
"struct": {
"fields": [
{
"layout": {
"cell": {
"key": "0x0400000001000000000000000000000000000000000000000000000000000000",
"ty": 3
}
},
"name": "len"
},
{
"layout": {
"array": {
"cellsPerElem": 1,
"layout": {
"cell": {
"key": "0x0400000002000000000000000000000000000000000000000000000000000000",
"ty": 10
}
},
"len": 4294967295,
"offset": "0x0500000001000000000000000000000000000000000000000000000000000000"
}
},
"name": "elems"
}
]
}
},
"name": "entries"
}
]
}
},
"name": "keys"
},
{
"layout": {
"hash": {
"layout": {
"cell": {
"key": "0x0500000002000000000000000000000000000000000000000000000000000000",
"ty": 9
}
},
"offset": "0x0400000002000000000000000000000000000000000000000000000000000000",
"strategy": {
"hasher": "Blake2x256",
"postfix": "",
"prefix": "0x696e6b20686173686d6170"
}
}
},
"name": "values"
}
]
}
},
"name": "allowances"
},
{
"layout": {
"cell": {
"key": "0x0500000002000000000000000000000000000000000000000000000000000000",
"ty": 12
}
},
"name": "name"
},
{
"layout": {
"cell": {
"key": "0x0600000002000000000000000000000000000000000000000000000000000000",
"ty": 12
}
},
"name": "symbol"
}
]
}
},
"types": [
{
"def": {
"primitive": "u128"
}
},
{
"def": {
"composite": {
"fields": [
{
"name": "last_vacant",
"type": 3
},
{
"name": "len",
"type": 3
},
{
"name": "len_entries",
"type": 3
}
]
}
},
"path": [
"ink_storage",
"collections",
"stash",
"Header"
]
},
{
"def": {
"primitive": "u32"
}
},
{
"def": {
"variant": {
"variants": [
{
"fields": [
{
"type": 8
}
],
"name": "Vacant"
},
{
"fields": [
{
"type": 5
}
],
"name": "Occupied"
}
]
}
},
"params": [
5
],
"path": [
"ink_storage",
"collections",
"stash",
"Entry"
]
},
{
"def": {
"composite": {
"fields": [
{
"type": 6
}
]
}
},
"path": [
"ink_env",
"types",
"AccountId"
]
},
{
"def": {
"array": {
"len": 32,
"type": 7
}
}
},
{
"def": {
"primitive": "u8"
}
},
{
"def": {
"composite": {
"fields": [
{
"name": "next",
"type": 3
},
{
"name": "prev",
"type": 3
}
]
}
},
"path": [
"ink_storage",
"collections",
"stash",
"VacantEntry"
]
},
{
"def": {
"composite": {
"fields": [
{
"name": "value",
"type": 1
},
{
"name": "key_index",
"type": 3
}
]
}
},
"params": [
1
],
"path": [
"ink_storage",
"collections",
"hashmap",
"ValueEntry"
]
},
{
"def": {
"variant": {
"variants": [
{
"fields": [
{
"type": 8
}
],
"name": "Vacant"
},
{
"fields": [
{
"type": 11
}
],
"name": "Occupied"
}
]
}
},
"params": [
11
],
"path": [
"ink_storage",
"collections",
"stash",
"Entry"
]
},
{
"def": {
"tuple": [
5,
5
]
}
},
{
"def": {
"primitive": "str"
}
},
{
"def": {
"primitive": "bool"
}
},
{
"def": {
"variant": {
"variants": [
{
"name": "None"
},
{
"fields": [
{
"type": 5
}
],
"name": "Some"
}
]
}
},
"params": [
5
],
"path": [
"Option"
]
}
]
}
+9 -9
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-derive",
"version": "2.2.1",
"version": "2.4.1",
"description": "Common functions used across Polkadot, derived from RPC calls and storage queries.",
"main": "index.js",
"keywords": [
@@ -27,18 +27,18 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme",
"dependencies": {
"@babel/runtime": "^7.11.2",
"@polkadot/api": "2.2.1",
"@polkadot/rpc-core": "2.2.1",
"@polkadot/rpc-provider": "2.2.1",
"@polkadot/types": "2.2.1",
"@polkadot/util": "^3.5.1",
"@polkadot/util-crypto": "^3.5.1",
"@babel/runtime": "^7.12.1",
"@polkadot/api": "^2.4.1",
"@polkadot/rpc-core": "^2.4.1",
"@polkadot/rpc-provider": "^2.4.1",
"@polkadot/types": "^2.4.1",
"@polkadot/util": "^3.6.1",
"@polkadot/util-crypto": "^3.6.1",
"bn.js": "^5.1.3",
"memoizee": "^0.4.14",
"rxjs": "^6.6.3"
},
"devDependencies": {
"@polkadot/keyring": "^3.5.1"
"@polkadot/keyring": "^3.6.1"
}
}
+1
View File
@@ -5,4 +5,5 @@ export * from './bestNumber';
export * from './bestNumberFinalized';
export * from './bestNumberLag';
export * from './getHeader';
export * from './subscribeNewBlocks';
export * from './subscribeNewHeads';
@@ -0,0 +1,32 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ApiInterfaceRx } from '@polkadot/api/types';
import { EventRecord, Hash, SignedBlock } from '@polkadot/types/interfaces';
import { FullNewBlock } from '../types';
import { Observable, combineLatest, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { memo } from '../util';
/**
* @name subscribeNewBlocks
* @returns The latest block & events for that block
*/
export function subscribeNewBlocks (instanceId: string, api: ApiInterfaceRx): () => Observable<FullNewBlock> {
return memo(instanceId, (): Observable<FullNewBlock> =>
api.derive.chain.subscribeNewHeads().pipe(
switchMap((header): Observable<[Hash, EventRecord[], SignedBlock]> => {
const blockHash = header.hash;
return combineLatest(
of(blockHash),
api.query.system.events.at(blockHash),
api.rpc.chain.getBlock(header.hash)
);
}),
map(([blockHash, events, block]) => ({ block: block.block, blockHash, blockNumber: block.block.header.number.unwrap(), events, justification: block.justification }))
)
);
}
@@ -11,7 +11,7 @@ import { memo } from '../util';
/**
* @name subscribeNewHeads
* @returns An array containing the block header and the block author
* @returns A header with the current header (including extracted author)
* @description An observable of the current block header and it's author
* @example
* <BR>
+12
View File
@@ -0,0 +1,12 @@
// Copyright 2017-2020 @polkadot/api-derive authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { Block, BlockNumber, EventRecord, Hash, Justification } from '@polkadot/types/interfaces';
export interface FullNewBlock {
block: Block;
blockHash: Hash;
blockNumber: BlockNumber;
events: EventRecord[];
justification: Justification;
}
+1
View File
@@ -7,6 +7,7 @@ import { AccountId, Balance, BalanceLock, BalanceLockTo212, BalanceOf, Bid, BidK
import { u32 } from '@polkadot/types';
export * from './accounts/types';
export * from './chain/types';
export * from './council/types';
export * from './democracy/types';
export * from './elections/types';
+2 -2
View File
@@ -4,6 +4,7 @@
import createMemo from 'memoizee';
import { Observable, Observer, TeardownLogic } from 'rxjs';
import { drr } from '@polkadot/rpc-core/rxjs';
import normalizer from '@polkadot/rpc-core/normalizer';
type ObsFn <T> = (...params: any[]) => Observable<T>;
@@ -24,8 +25,7 @@ export function memo <T> (instanceId: string, inner: ObsFn<T>): ObsFn<T> {
}).pipe(drr()),
{
// Normalize via JSON.stringify, allow e.g. AccountId -> ss58
// eslint-disable-next-line @typescript-eslint/unbound-method
normalizer: (args) => instanceId + JSON.stringify(args)
normalizer: normalizer(instanceId)
}
);
+12 -12
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api",
"version": "2.2.1",
"version": "2.4.1",
"description": "Promise and RxJS wrappers around the Polkadot JS RPC",
"main": "index.js",
"keywords": [
@@ -26,21 +26,21 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api#readme",
"dependencies": {
"@babel/runtime": "^7.11.2",
"@polkadot/api-derive": "2.2.1",
"@polkadot/keyring": "^3.5.1",
"@polkadot/metadata": "2.2.1",
"@polkadot/rpc-core": "2.2.1",
"@polkadot/rpc-provider": "2.2.1",
"@polkadot/types": "2.2.1",
"@polkadot/types-known": "2.2.1",
"@polkadot/util": "^3.5.1",
"@polkadot/util-crypto": "^3.5.1",
"@babel/runtime": "^7.12.1",
"@polkadot/api-derive": "^2.4.1",
"@polkadot/keyring": "^3.6.1",
"@polkadot/metadata": "^2.4.1",
"@polkadot/rpc-core": "^2.4.1",
"@polkadot/rpc-provider": "^2.4.1",
"@polkadot/types": "^2.4.1",
"@polkadot/types-known": "^2.4.1",
"@polkadot/util": "^3.6.1",
"@polkadot/util-crypto": "^3.6.1",
"bn.js": "^5.1.3",
"eventemitter3": "^4.0.7",
"rxjs": "^6.6.3"
},
"devDependencies": {
"@polkadot/keyring": "^3.5.1"
"@polkadot/keyring": "^3.6.1"
}
}
+2 -2
View File
@@ -153,11 +153,11 @@ declare module '@polkadot/rpc-core/types.jsonrpc' {
/**
* Get offchain local storage under given key and prefix
**/
localStorageGet: AugmentedRpc<(kind: StorageKind | '__UNUSED' | 'PERSISTENT' | 'LOCAL' | number | Uint8Array, key: Bytes | string | Uint8Array) => Observable<Option<Bytes>>>;
localStorageGet: AugmentedRpc<(kind: StorageKind | '__UNUSED'|'PERSISTENT'|'LOCAL' | number | Uint8Array, key: Bytes | string | Uint8Array) => Observable<Option<Bytes>>>;
/**
* Set offchain local storage under given key and prefix
**/
localStorageSet: AugmentedRpc<(kind: StorageKind | '__UNUSED' | 'PERSISTENT' | 'LOCAL' | number | Uint8Array, key: Bytes | string | Uint8Array, value: Bytes | string | Uint8Array) => Observable<Null>>;
localStorageSet: AugmentedRpc<(kind: StorageKind | '__UNUSED'|'PERSISTENT'|'LOCAL' | number | Uint8Array, key: Bytes | string | Uint8Array, value: Bytes | string | Uint8Array) => Observable<Null>>;
};
payment: {
/**
+27 -14
View File
@@ -359,7 +359,11 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
if (creator.iterKey && (creator.meta.type.isMap || creator.meta.type.isDoubleMap)) {
decorated.entries = decorateMethod(
memo(this.#instanceId, (doubleMapArg?: Arg): Observable<[StorageKey, Codec][]> =>
this._retrieveMapEntries(creator, doubleMapArg)));
this._retrieveMapEntries(creator, null, doubleMapArg)));
decorated.entriesAt = decorateMethod(
memo(this.#instanceId, (hash: Hash | Uint8Array | string, doubleMapArg?: Arg): Observable<[StorageKey, Codec][]> =>
this._retrieveMapEntries(creator, hash, doubleMapArg)));
decorated.entriesPaged = decorateMethod(
memo(this.#instanceId, (opts: PaginationOptions): Observable<[StorageKey, Codec][]> =>
@@ -367,7 +371,11 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
decorated.keys = decorateMethod(
memo(this.#instanceId, (doubleMapArg?: Arg): Observable<StorageKey[]> =>
this._retrieveMapKeys(creator, doubleMapArg)));
this._retrieveMapKeys(creator, null, doubleMapArg)));
decorated.keysAt = decorateMethod(
memo(this.#instanceId, (hash: Hash | Uint8Array | string, doubleMapArg?: Arg): Observable<StorageKey[]> =>
this._retrieveMapKeys(creator, hash, doubleMapArg)));
decorated.keysPaged = decorateMethod(
memo(this.#instanceId, (opts: PaginationOptions): Observable<StorageKey[]> =>
@@ -416,15 +424,18 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
));
}
private _retrieveMapKeys ({ iterKey, meta }: StorageEntry, arg?: Arg): Observable<StorageKey[]> {
private _retrieveMapKeys ({ iterKey, meta }: StorageEntry, at: Hash | Uint8Array | string | null, arg?: Arg): Observable<StorageKey[]> {
assert(iterKey && (meta.type.isMap || meta.type.isDoubleMap), 'keys can only be retrieved on maps, linked maps and double maps');
const headKey = iterKey(arg).toHex();
const startSubject = new BehaviorSubject<string>(headKey);
const query = at
? (startKey: string) => this._rpcCore.state.getKeysPaged(headKey, PAGE_SIZE_KEYS, startKey, at)
: (startKey: string) => this._rpcCore.state.getKeysPaged(headKey, PAGE_SIZE_KEYS, startKey);
return startSubject.pipe(
switchMap((startKey) =>
this._rpcCore.state.getKeysPaged(headKey, PAGE_SIZE_KEYS, startKey).pipe(
query(startKey).pipe(
map((keys) => keys.map((key) => key.setMeta(meta)))
)
),
@@ -448,21 +459,23 @@ export default abstract class Decorate<ApiType extends ApiTypes> extends Events
);
}
private _retrieveMapEntries (entry: StorageEntry, arg?: Arg): Observable<[StorageKey, Codec][]> {
return this._retrieveMapKeys(entry, arg).pipe(
private _retrieveMapEntries (entry: StorageEntry, at: Hash | Uint8Array | string | null, arg?: Arg): Observable<[StorageKey, Codec][]> {
const query = at
? this._rpcCore.state.queryStorageAt
? (keyset: StorageKey[]) => this._rpcCore.state.queryStorageAt<Codec[]>(keyset, at)
: (keyset: StorageKey[]) => this._rpcCore.state.queryStorageAt<Codec[]>(keyset)
// this is horrible, but need older support (which now doesn't work with at)
: (keyset: StorageKey[]) => this._rpcCore.state.subscribeStorage<Codec[]>(keyset).pipe(take(1));
return this._retrieveMapKeys(entry, at, arg).pipe(
switchMap((keys) =>
combineLatest<[StorageKey[], ...Codec[][]]>([
of(keys),
...Array(Math.ceil(keys.length / PAGE_SIZE_VALS))
.fill(0)
.map((_, index): Observable<Codec[]> => {
const keyset = keys.slice(index * PAGE_SIZE_VALS, (index * PAGE_SIZE_VALS) + PAGE_SIZE_VALS);
return this._rpcCore.state.queryStorageAt
? this._rpcCore.state.queryStorageAt<Codec[]>(keyset)
// this is horrible, but need older support
: this._rpcCore.state.subscribeStorage<Codec[]>(keyset).pipe(take(1));
})
.map((_, index): Observable<Codec[]> =>
query(keys.slice(index * PAGE_SIZE_VALS, (index * PAGE_SIZE_VALS) + PAGE_SIZE_VALS))
)
])
),
map(([keys, ...valsArr]): [StorageKey, Codec][] =>
+15 -1
View File
@@ -3,7 +3,7 @@
// Simple non-runnable checks to test type definitions in the editor itself
import { Balance, Header, Index } from '@polkadot/types/interfaces';
import { AccountId, Balance, Header, Index } from '@polkadot/types/interfaces';
import { IExtrinsic, IMethod } from '@polkadot/types/types';
import { ApiPromise } from '@polkadot/api';
@@ -71,6 +71,20 @@ async function query (api: ApiPromise, keyring: TestKeyringMap): Promise<void> {
console.log(multiRes);
// events destructing
await api.query.system.events((records): void => {
records.forEach(({ event, phase }): void => {
if (phase.isApplyExtrinsic) {
// Dunno... this should work
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const [accountId, value]: [AccountId, Balance] = event.data;
console.log(`${accountId.toString()} has ${value.toHuman()}`);
}
});
});
// at queries
const events = await api.query.system.events.at('0x12345');
+34 -8
View File
@@ -1,16 +1,44 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ExtrinsicStatus, EventRecord } from '@polkadot/types/interfaces';
import { DispatchError, DispatchInfo, ExtrinsicStatus, EventRecord } from '@polkadot/types/interfaces';
import { AnyJson, ISubmittableResult } from '@polkadot/types/types';
import { SubmittableResultValue } from './types';
const recordIdentity = (record: EventRecord) => record;
function filterAndApply <T> (events: EventRecord[], section: string, methods: string[], onFound: (record: EventRecord) => T): T[] {
return events
.filter(({ event }) => section === event.section && methods.includes(event.method))
.map((record) => onFound(record));
}
function extractError (events: EventRecord[] = []): DispatchError | undefined {
return filterAndApply(events, 'system', ['ExtrinsicFailed'], ({ event: { data } }) =>
data[0] as DispatchError
)[0];
}
function extractInfo (events: EventRecord[] = []): DispatchInfo | undefined {
return filterAndApply(events, 'system', ['ExtrinsicFailed', 'ExtrinsicSuccess'], ({ event: { data, method } }) =>
method === 'ExtrinsicSuccess'
? data[0] as DispatchInfo
: data[1] as DispatchInfo
)[0];
}
export default class SubmittableResult implements ISubmittableResult {
public readonly dispatchError?: DispatchError;
public readonly dispatchInfo?: DispatchInfo;
public readonly events: EventRecord[];
public readonly status: ExtrinsicStatus;
constructor ({ events, status }: SubmittableResultValue) {
constructor ({ dispatchError, dispatchInfo, events, status }: SubmittableResultValue) {
this.dispatchError = dispatchError || extractError(events);
this.dispatchInfo = dispatchInfo || extractInfo(events);
this.events = events || [];
this.status = status;
}
@@ -39,18 +67,14 @@ export default class SubmittableResult implements ISubmittableResult {
* @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
);
return filterAndApply(this.events, section, [method], recordIdentity);
}
/**
* @description Finds an EventRecord for the specified method & section
*/
public findRecord (section: string, method: string): EventRecord | undefined {
return this.events.find(({ event }): boolean =>
event.section === section && event.method === method
);
return this.filterRecords(section, method)[0];
}
/**
@@ -58,6 +82,8 @@ export default class SubmittableResult implements ISubmittableResult {
*/
public toHuman (isExtended?: boolean): AnyJson {
return {
dispatchError: this.dispatchError?.toHuman(),
dispatchInfo: this.dispatchInfo?.toHuman(),
events: this.events.map((event) => event.toHuman(isExtended)),
status: this.status.toHuman(isExtended)
};
+3 -1
View File
@@ -1,13 +1,15 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { AccountId, Address, Extrinsic, ExtrinsicStatus, EventRecord, Hash, RuntimeDispatchInfo } from '@polkadot/types/interfaces';
import { AccountId, Address, DispatchError, DispatchInfo, Extrinsic, ExtrinsicStatus, EventRecord, Hash, RuntimeDispatchInfo } from '@polkadot/types/interfaces';
import { AnyNumber, Callback, Codec, IExtrinsicEra, IKeyringPair, Signer, ISubmittableResult } from '@polkadot/types/types';
import { ApiTypes } from '../types';
import { Observable } from 'rxjs';
export interface SubmittableResultValue {
dispatchError?: DispatchError;
dispatchInfo?: DispatchInfo;
events?: EventRecord[];
status: ExtrinsicStatus;
}
+2
View File
@@ -40,11 +40,13 @@ export interface StorageEntryBase<ApiType extends ApiTypes, F extends AnyFunctio
at: <T extends Codec | any = ObsInnerType<ReturnType<F>>>(hash: Hash | Uint8Array | string, ...args: Parameters<F>) => PromiseOrObs<ApiType, T>;
creator: StorageEntry;
entries: <T extends Codec | any = ObsInnerType<ReturnType<F>>>(arg?: Parameters<F>[0]) => PromiseOrObs<ApiType, [StorageKey, T][]>;
entriesAt: <T extends Codec | any = ObsInnerType<ReturnType<F>>>(hash: Hash | Uint8Array | string, arg?: Parameters<F>[0]) => PromiseOrObs<ApiType, [StorageKey, T][]>;
entriesPaged: <T extends Codec | any = ObsInnerType<ReturnType<F>>>(opts: PaginationOptions<Parameters<F>[0]>) => PromiseOrObs<ApiType, [StorageKey, T][]>;
hash: (...args: Parameters<F>) => PromiseOrObs<ApiType, Hash>;
key: (...args: Parameters<F>) => string;
keyPrefix: () => string;
keys: (arg?: any) => PromiseOrObs<ApiType, StorageKey[]>;
keysAt: (hash: Hash | Uint8Array | string, arg?: any) => PromiseOrObs<ApiType, StorageKey[]>;
keysPaged: (opts: PaginationOptions<Parameters<F>[0]>) => PromiseOrObs<ApiType, StorageKey[]>;
range: <T extends Codec | any = ObsInnerType<ReturnType<F>>>([from, to]: [Hash | Uint8Array | string, Hash | Uint8Array | string | undefined] | [Hash | Uint8Array | string], ...args: Parameters<F>) => PromiseOrObs<ApiType, [Hash, T][]>;
size: (...args: Parameters<F>) => PromiseOrObs<ApiType, u64>;
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/metadata",
"version": "2.2.1",
"version": "2.4.1",
"description": "Helpers to extract information from runtime metadata",
"main": "index.js",
"publishConfig": {
@@ -26,14 +26,14 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/type-metadata#readme",
"dependencies": {
"@babel/runtime": "^7.11.2",
"@polkadot/types": "2.2.1",
"@polkadot/types-known": "2.2.1",
"@polkadot/util": "^3.5.1",
"@polkadot/util-crypto": "^3.5.1",
"@babel/runtime": "^7.12.1",
"@polkadot/types": "^2.4.1",
"@polkadot/types-known": "^2.4.1",
"@polkadot/util": "^3.6.1",
"@polkadot/util-crypto": "^3.6.1",
"bn.js": "^5.1.3"
},
"devDependencies": {
"@polkadot/keyring": "^3.5.1"
"@polkadot/keyring": "^3.6.1"
}
}
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/rpc-core",
"version": "2.2.1",
"version": "2.4.1",
"description": "A JavaScript wrapper for the Polkadot JsonRPC interface",
"main": "index.js",
"keywords": [
@@ -26,15 +26,15 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/rpc-core#readme",
"dependencies": {
"@babel/runtime": "^7.11.2",
"@polkadot/metadata": "2.2.1",
"@polkadot/rpc-provider": "2.2.1",
"@polkadot/types": "2.2.1",
"@polkadot/util": "^3.5.1",
"@babel/runtime": "^7.12.1",
"@polkadot/metadata": "^2.4.1",
"@polkadot/rpc-provider": "^2.4.1",
"@polkadot/types": "^2.4.1",
"@polkadot/util": "^3.6.1",
"memoizee": "^0.4.14",
"rxjs": "^6.6.3"
},
"devDependencies": {
"@polkadot/keyring": "^3.5.1"
"@polkadot/keyring": "^3.6.1"
}
}
+3 -3
View File
@@ -13,6 +13,7 @@ import jsonrpc from '@polkadot/types/interfaces/jsonrpc';
import { Option, StorageKey, Vec, createClass, createTypeUnsafe } from '@polkadot/types';
import { assert, hexToU8a, isFunction, isNull, isUndefined, logger, u8aToU8a } from '@polkadot/util';
import normalizer from './normalizer';
import { drr, refCountDelay } from './rxjs';
interface StorageChangeSetJSON {
@@ -267,7 +268,7 @@ export default class Rpc implements RpcInterface {
memoized = memoizee(this._createMethodWithRaw(creator), {
length: false,
normalizer: (args) => this.#instanceId + JSON.stringify(args)
normalizer: normalizer(this.#instanceId)
});
return memoized;
@@ -355,8 +356,7 @@ export default class Rpc implements RpcInterface {
// Normalize args so that different args that should be cached
// together are cached together.
// E.g.: `query.my.method('abc') === query.my.method(createType('AccountId', 'abc'));`
// eslint-disable-next-line @typescript-eslint/unbound-method
normalizer: (args) => this.#instanceId + JSON.stringify(args)
normalizer: normalizer(this.#instanceId)
});
return memoized;
+30
View File
@@ -0,0 +1,30 @@
// Copyright 2017-2020 @polkadot/rpc-core authors & contributors
// SPDX-License-Identifier: Apache-2.0
import normalizer from './normalizer';
describe('normalizer', (): void => {
it('works when BigInt is in the data (object)', (): void => {
expect(
normalizer('instance')({ a: 'bar', b: 1234567890987654321n, c: 123 })
).toEqual('instance{"a":"bar","b":"1234567890987654321","c":123}');
});
it('works when BigInt is in the data (array)', (): void => {
expect(
normalizer('instance')(['bar', 1234567890987654321n, 123])
).toEqual('instance["bar","1234567890987654321",123]');
});
it('works when BigInt is in the data (single)', (): void => {
expect(
normalizer('instance')(1234567890987654321n)
).toEqual('instance"1234567890987654321"');
});
it('works when BigInt is in the data (nested)', (): void => {
expect(
normalizer('instance')({ a: 'bar', b: { foo: 1234567890987654321n }, c: 123 })
).toEqual('instance{"a":"bar","b":{"foo":"1234567890987654321"},"c":123}');
});
});
+13
View File
@@ -0,0 +1,13 @@
// Copyright 2017-2020 @polkadot/rpc-core authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { isBigInt } from '@polkadot/util';
export default function normalizer (instanceId: string): (value: unknown) => string {
return (value: unknown) =>
instanceId + JSON.stringify(value, (_, value: unknown) =>
isBigInt(value)
? value.toString()
: value
);
}
+9 -9
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/rpc-provider",
"version": "2.2.1",
"version": "2.4.1",
"description": "Transport providers for the API",
"main": "index.js",
"keywords": [
@@ -26,18 +26,18 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/rpc-provider#readme",
"dependencies": {
"@babel/runtime": "^7.11.2",
"@polkadot/metadata": "2.2.1",
"@polkadot/types": "2.2.1",
"@polkadot/util": "^3.5.1",
"@polkadot/util-crypto": "^3.5.1",
"@polkadot/x-fetch": "^0.3.2",
"@polkadot/x-ws": "^0.3.2",
"@babel/runtime": "^7.12.1",
"@polkadot/metadata": "^2.4.1",
"@polkadot/types": "^2.4.1",
"@polkadot/util": "^3.6.1",
"@polkadot/util-crypto": "^3.6.1",
"@polkadot/x-fetch": "^0.3.4",
"@polkadot/x-ws": "^0.3.4",
"bn.js": "^5.1.3",
"eventemitter3": "^4.0.7"
},
"devDependencies": {
"@polkadot/keyring": "^3.5.1",
"@polkadot/keyring": "^3.6.1",
"mock-socket": "^9.0.3",
"nock": "^13.0.4"
}
+6 -1
View File
@@ -150,7 +150,12 @@ export default class WsProvider implements ProviderInterface {
? new WS(this.#endpoints[this.#endpointIndex])
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - WS may be an instance of w3cwebsocket, which supports headers
: new WS(this.#endpoints[this.#endpointIndex], undefined, undefined, this.#headers);
: new WS(this.#endpoints[this.#endpointIndex], undefined, undefined, this.#headers, undefined, {
// default: true
fragmentOutgoingMessages: true,
// default: 16K
fragmentationThreshold: 256 * 1024
});
this.#websocket.onclose = this.#onSocketClose;
this.#websocket.onerror = this.#onSocketError;
+11 -11
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/typegen",
"version": "2.2.1",
"version": "2.4.1",
"description": "Type generation scripts",
"main": "index.js",
"bin": {
@@ -33,20 +33,20 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/typegen#readme",
"dependencies": {
"@babel/core": "^7.11.6",
"@babel/register": "^7.11.5",
"@babel/runtime": "^7.11.2",
"@polkadot/api": "2.2.1",
"@polkadot/metadata": "2.2.1",
"@polkadot/rpc-provider": "2.2.1",
"@polkadot/types": "2.2.1",
"@polkadot/util": "^3.5.1",
"@babel/core": "^7.12.3",
"@babel/register": "^7.12.1",
"@babel/runtime": "^7.12.1",
"@polkadot/api": "^2.4.1",
"@polkadot/metadata": "^2.4.1",
"@polkadot/rpc-provider": "^2.4.1",
"@polkadot/types": "^2.4.1",
"@polkadot/util": "^3.6.1",
"handlebars": "^4.7.6",
"websocket": "^1.0.32",
"yargs": "^16.0.3"
"yargs": "^16.1.0"
},
"devDependencies": {
"@types/websocket": "^1.0.1",
"@types/yargs": "^15.0.7"
"@types/yargs": "^15.0.9"
}
}
+5 -3
View File
@@ -9,7 +9,7 @@ import { TypeRegistry } from '@polkadot/types/create';
import * as defaultDefs from '@polkadot/types/interfaces/definitions';
import { stringCamelCase } from '@polkadot/util';
import { createImports, compareName, readTemplate, registerDefinitions, setImports, writeFile } from '../util';
import { createImports, compareName, formatType, readTemplate, registerDefinitions, setImports, writeFile } from '../util';
const template = readTemplate('consts');
const generateForMetaTemplate = Handlebars.compile(template);
@@ -34,12 +34,14 @@ function generateForMeta (meta: Metadata, dest: string, extraTypes: Record<strin
const items = constants
.sort(compareName)
.map(({ documentation, name, type }) => {
setImports(allDefs, imports, [type.toString()]);
const returnType = formatType(allDefs, type.toString(), imports);
setImports(allDefs, imports, [returnType]);
return {
docs: documentation,
name: stringCamelCase(name.toString()),
type: type.toString()
type: returnType
};
});
@@ -28,12 +28,12 @@ export function generateInterfaceTypes (importDefinitions: { [importPath: string
const imports = createImports(importDefinitions);
const definitions = imports.definitions;
const items: string[] = [];
// first we create imports for our known classes from the API
Object
.keys(primitiveClasses)
.filter((name): boolean => !!name.indexOf('Generic'))
.filter((name) => !name.includes('Generic'))
.forEach((primitiveName) => {
setImports(definitions, imports, [primitiveName]);
@@ -42,7 +42,14 @@ export function generateInterfaceTypes (importDefinitions: { [importPath: string
const existingTypes: Record<string, boolean> = {};
Object.entries(definitions).forEach(([, { types }]) => {
// ensure we have everything registered since we will get the definition
// form the available types (so any unknown should show after this)
Object.values(definitions).forEach(({ types }) => {
registry.register(types as Record<string, string>);
});
// create imports for everything that we have available
Object.values(definitions).forEach(({ types }) => {
setImports(definitions, imports, Object.keys(types));
const uniqueTypes = Object.keys(types).filter((type) => !existingTypes[type]);
+1 -1
View File
@@ -19,7 +19,7 @@ import { ModuleTypes } from '../util/imports';
// From a storage entry metadata, we return [args, returnType]
/** @internal */
function entrySignature (allDefs: Record<string, ModuleTypes>, registry: Registry, storageEntry: StorageEntryMetadataLatest, imports: TypeImports): [string, string] {
const format = (type: string): string => formatType(allDefs, type, imports);
const format = (type: string) => formatType(allDefs, type, imports);
const outputType = unwrapStorageType(storageEntry.type, storageEntry.modifier.isOptional);
if (storageEntry.type.isPlain) {
+2 -3
View File
@@ -17,11 +17,10 @@ const generateRpcTypesTemplate = Handlebars.compile(template);
/** @internal */
export function generateRpcTypes (importDefinitions: { [importPath: string]: Record<string, Definitions> }, dest: string): void {
writeFile(dest, (): string => {
const format = (type: string) => formatType(allDefs, type, imports);
const registry = new TypeRegistry();
const imports = createImports(importDefinitions);
const definitions = imports.definitions as Record<string, Definitions>;
const allDefs = Object.entries(importDefinitions).reduce((defs, [path, obj]) => {
return Object.entries(obj).reduce((defs, [key, value]) => ({ ...defs, [`${path}/${key}`]: value }), defs);
}, {});
@@ -73,7 +72,7 @@ export function generateRpcTypes (importDefinitions: { [importPath: string]: Rec
setImports(allDefs, imports, [param.type, ...similarTypes]);
return `${param.name}${param.isOptional ? '?' : ''}: ${similarTypes.join(' | ')}`;
return `${param.name}${param.isOptional ? '?' : ''}: ${similarTypes.map(format).join(' | ')}`;
});
type = formatType(allDefs, def.type, imports);
+3 -2
View File
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import fs from 'fs';
import path from 'path';
export function writeFile (dest: string, generator: () => string, noLog?: boolean): void {
!noLog && console.log(`${dest}\n\tGenerating`);
@@ -19,6 +20,6 @@ export function writeFile (dest: string, generator: () => string, noLog?: boolea
!noLog && console.log('');
}
export function readTemplate (path: string): string {
return fs.readFileSync(`${__dirname}/../templates/${path}.hbs`).toString();
export function readTemplate (template: string): string {
return fs.readFileSync(path.join(__dirname, `../templates/${template}.hbs`)).toString();
}
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/types-known",
"version": "2.2.1",
"version": "2.4.1",
"description": "A JavaScript wrapper for the Polkadot JsonRPC interface",
"main": "index.js",
"keywords": [
@@ -26,9 +26,9 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/types-known#readme",
"dependencies": {
"@babel/runtime": "^7.11.2",
"@polkadot/types": "2.2.1",
"@polkadot/util": "^3.5.1",
"@babel/runtime": "^7.12.1",
"@polkadot/types": "^2.4.1",
"@polkadot/util": "^3.6.1",
"bn.js": "^5.1.3"
},
"devDependencies": {
+9 -6
View File
@@ -12,7 +12,6 @@ import typesChain from './chain';
import typesModules from './modules';
import typesSpec from './spec';
import upgrades from './upgrades';
import warnings from './warnings';
// flatten a VersionedType[] into a Record<string, string>
/** @internal */
@@ -46,15 +45,18 @@ export function getSpecTypes ({ knownTypes }: Registry, chainName: Text | string
const _specName = specName.toString();
const _specVersion = bnToBn(specVersion).toNumber();
(warnings[_specName] || []).forEach((warning) => console.warn(`*** ${warning}`));
// The order here is always, based on -
// - spec then chain
// - typesBundle takes higher precedence
// - types is the final catch-all override
return {
...filterVersions(typesSpec[_specName], _specVersion),
...filterVersions(typesChain[_chainName], _specVersion),
...filterVersions(knownTypes.typesBundle?.spec?.[_specName]?.types, _specVersion),
...filterVersions(knownTypes.typesBundle?.chain?.[_chainName]?.types, _specVersion),
...(knownTypes.typesSpec?.[_specName] || {}),
...(knownTypes.typesChain?.[_chainName] || {})
...(knownTypes.typesChain?.[_chainName] || {}),
...(knownTypes.types || {})
};
}
@@ -78,10 +80,11 @@ export function getSpecAlias ({ knownTypes }: Registry, chainName: Text | string
const _chainName = chainName.toString();
const _specName = specName.toString();
// as per versions, first spec, then chain then finally non-versioned
return {
...(knownTypes.typesAlias || {}),
...(knownTypes.typesBundle?.spec?.[_specName]?.alias || {}),
...(knownTypes.typesBundle?.chain?.[_chainName]?.alias || {})
...(knownTypes.typesBundle?.chain?.[_chainName]?.alias || {}),
...(knownTypes.typesAlias || {})
};
}
+2
View File
@@ -5,6 +5,7 @@ import { OverrideVersionedType } from '@polkadot/types/types';
import centrifugeChain from './centrifuge-chain';
import kusama from './kusama';
import nodeTemplate from './node-template';
import polkadot from './polkadot';
import rococo from './rococo';
import westend from './westend';
@@ -13,6 +14,7 @@ import westend from './westend';
const typesSpec: Record<string, OverrideVersionedType[]> = {
'centrifuge-chain': centrifugeChain,
kusama,
'node-template': nodeTemplate,
polkadot,
rococo,
westend
@@ -0,0 +1,16 @@
// Copyright 2017-2020 @polkadot/types-known authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { OverrideVersionedType } from '@polkadot/types/types';
const versioned: OverrideVersionedType[] = [
{
minmax: [0, undefined],
types: {
Address: 'AccountId',
LookupSource: 'AccountId'
}
}
];
export default versioned;
+1 -1
View File
@@ -13,7 +13,7 @@ const upgrades: ChainUpgradesRaw = {
[1472960, 1052], [1475648, 1053], [1491596, 1054], [1574408, 1055], [2064961, 1058],
[2201991, 1062], [2671528, 2005], [2704202, 2007], [2728002, 2008], [2832534, 2011],
[2962294, 2012], [3240000, 2013], [3274408, 2015], [3323565, 2019], [3534175, 2022],
[3860281, 2023], [4143129, 2024]
[3860281, 2023], [4143129, 2024], [4401242, 2025]
]
};
@@ -9,7 +9,7 @@ const upgrades: ChainUpgradesRaw = {
[0, 0], [29231, 1], [188836, 5], [199405, 6], [214264, 7],
[244358, 8], [303079, 9], [314201, 10], [342400, 11], [443963, 12],
[528470, 13], [687751, 14], [746085, 15], [787923, 16], [799302, 17],
[1205128, 18], [1603423, 23], [1733218, 24]
[1205128, 18], [1603423, 23], [1733218, 24], [2005673, 25]
]
};
+2 -1
View File
@@ -9,7 +9,8 @@ const upgrades: ChainUpgradesRaw = {
[214356, 4], [392764, 7], [409740, 8], [809976, 20], [877581, 24],
[879238, 25], [889472, 26], [902937, 27], [932751, 28], [991142, 29],
[1030162, 31], [1119657, 32], [1199282, 33], [1342534, 34], [1392263, 35],
[1431703, 36], [1433369, 37], [1490972, 41], [2087397, 43], [2316688, 44]
[1431703, 36], [1433369, 37], [1490972, 41], [2087397, 43], [2316688, 44],
[2549864, 45]
]
};
-17
View File
@@ -1,17 +0,0 @@
// Copyright 2017-2020 @polkadot/types-known authors & contributors
// SPDX-License-Identifier: Apache-2.0
// Type overrides for specific spec types & versions as given in runtimeVersion
const warnings: Record<string, string[]> = {
'node-template': [
'',
'You are using the node-template, depending on your config and age of the template, you may',
'have some unexpected results without applying the correct config for your node type:',
'',
'- If you have trouble sending txs, apply https://polkadot.js.org/api/start/FAQ.html#i-cannot-send-transactions-from-my-node-template-based-chain',
'- If you have trouble parsing events, apply https://polkadot.js.org/api/start/FAQ.html#using-a-non-current-master-node-i-have-issues-parsing-events',
''
]
};
export default warnings;
+1 -64
View File
@@ -1,66 +1,3 @@
# @polkadot/types
Implementation of the types and their (de-)serialisation via SCALE codec.<br>
On the Rust side, the codec types and primitive types are implemented via the [parity-codec](https://github.com/paritytech/parity-codec).
## Codec types
These are the base types of the codec. They are typically not used directly, but rather inherited from to create specific types. They are the building blocks for declaring custom types:
| **Types** | |
| --- | --- |
| [[Compact]] | A compact length-encoding codec wrapper. Mostly used by other types to add length-prefixed encoding |
| [[Enum]] | A codec wrapper for an enum. Enums are encoded as a single byte, where the byte is a zero-indexed value |
| [[Int]] | A generic signed integer codec |
| [[Option]] | An Option is an optional field. The first byte indicates that there is a value to follow |
| [[Set]] | An Set is an array of string values, represented an an encoded type by a bitwise representation of the values |
| [[Struct]] | A Struct defines an Object with key-value pairs - where the values are Codec values. |
| [[Tuple]] | A Tuple defines an anonymous fixed-length array, where each element has its own type |
| [[Raw]] | A basic wrapper around Uint8Array. It will consume the full Uint8Array as passed to it |
| [[U8aFixed]] | A U8a that manages a a sequence of bytes up to the specified bitLength |
| [[UInt]] | A generic unsigned integer codec. It handles the encoding and decoding of Little Endian encoded numbers in Substrate |
| [[Vec]] | This manages codec arrays. Internally it keeps track of the length (as decoded) |
| [[VecAny]] | This manages codec arrays, assuming that the inputs are already of type Codec |
## Primitive types
These primitive types are available:
| **Types** | |
| --- | --- |
| [[AccountId]] | A wrapper around an AccountId/PublicKey representation |
| [[AccountIndex]] | A wrapper around an AccountIndex, which is a shortened, variable-length encoding for an Account |
| [[Address]] | A wrapper around an AccountId and/or AccountIndex that is encoded with a prefix |
| [[bool]] | Representation for a boolean value in the system |
| [[Bytes]] | A Bytes wrapper for `Vec<u8>` |
| [[Call]] | Extrinsic function descriptor, as defined in [the extrinsic format for a node](https://github.com/paritytech/wiki/blob/master/Extrinsic.md#the-extrinsic-format-for-node) |
| [[Event]] | Wrapper for the actual data that forms part of an [[Event]] |
| [[EventRecord]] | A record for an [[Event]] (as specified by [[Metadata]]) with the specific [[Phase]] of application |
| [[Extrinsic]] | Representation of an Extrinsic in the system |
| [[ExtrinsicEra]] | The era for an extrinsic, indicating either a mortal or immortal extrinsic |
| [[ExtrinsicPayload]] | A signing payload for an [[Extrinsic]]. For the final encoding, it is variable length based on the contents included |
| [[H160]] | Hash containing 160 bits (20 bytes), typically used in blocks, extrinsics and as a sane default |
| [[H256]] | Hash containing 256 bits (32 bytes), typically used in blocks, extrinsics and as a sane default |
| [[H512]] | Hash containing 512 bits (64 bytes), typically used for signatures |
| [[Hash]] | The default hash that is used accross the system. It is just a thin wrapper around [[H256]]
| [[i8]] | An 8-bit signed integer |
| [[i16]] | A 16-bit signed integer |
| [[i32]] | A 32-bit signed integer |
| [[i64]] | A 64-bit signed integer |
| [[i128]] | A 128-bit signed integer |
| [[i256]] | A 256-bit signed integer |
| [[Moment]] | A wrapper around seconds/timestamps. Internally the representation only has second precicion (aligning with Rust) |
| [[Null]] | Implements a type that does not contain anything (apart from `null`) |
| [[Signature]] | The default signature that is used accross the system |
| [[StorageData]] | Data retrieved via Storage queries and data for key-value pairs |
| [[StorageKey]] | A representation of a storage key (typically hashed) in the system |
| [[Text]] | This is a string wrapper, along with the length. |
| [[Type]] | This is a extended version of String, specifically to handle types |
| [[u8]] | An 8-bit unsigned integer |
| [[u16]] | A 16-bit unsigned integer |
| [[u32]] | A 32-bit unsigned integer |
| [[u64]] | A 64-bit unsigned integer |
| [[u128]] | A 128-bit unsigned integer |
| [[u256]] | A 256-bit unsigned integer |
Implementation of the types and their (de-)serialisation via SCALE codec. On the Rust side, the codec types and primitive types are implemented via the [parity-codec](https://github.com/paritytech/parity-codec).
+6 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/types",
"version": "2.2.1",
"version": "2.4.1",
"description": "Implementation of the Parity codec",
"main": "index.js",
"keywords": [
@@ -26,17 +26,17 @@
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/types#readme",
"dependencies": {
"@babel/runtime": "^7.11.2",
"@polkadot/metadata": "2.2.1",
"@polkadot/util": "^3.5.1",
"@polkadot/util-crypto": "^3.5.1",
"@babel/runtime": "^7.12.1",
"@polkadot/metadata": "^2.4.1",
"@polkadot/util": "^3.6.1",
"@polkadot/util-crypto": "^3.6.1",
"@types/bn.js": "^4.11.6",
"bn.js": "^5.1.3",
"memoizee": "^0.4.14",
"rxjs": "^6.6.3"
},
"devDependencies": {
"@polkadot/keyring": "^3.5.1",
"@polkadot/keyring": "^3.6.1",
"@types/memoizee": "^0.4.4"
}
}

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