Compare commits

...
38 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
78 changed files with 1271 additions and 937 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
+24 -1
View File
@@ -1,8 +1,31 @@
# CHANGELOG
## 2.4.1 Oct 26, 2020
Upgrade priority: Low. No breaking changes, however it does move `api-contract` forward with additional features.
Contributed:
- Add support for both `{i,u}256` types on contracts (Thanks to https://github.com/seanyoung)
Changes:
- Add `.keysAt` & `.entriesAt` to query maps at a specific blockHash
- Adjust ordering of type injection, any `types: { ... }` definitions not have precedence
- Correctly format Tuples in both RPC and const definitions as part of type generation
- Add node-template to known types (tracking inside API), remove warnings for the spec
- Add initial implementation for new Substrate `MultiAddress` type
- Add `api.derive.chain.subscribeNewBlocks` for full block retrievals
- Contracts identifiers to `.{exec, read}('name', ...)` now matches on both snake_case and camelCase (consistency)
- Cleanup contracts serialization for messages to allow both to and from
- Add deserialization of contract events against the ABI
- Adjust contracts metadata parsing to be future-proof with type retrievals
- Add tests for Solang into contracts, re-organize layout per type
## 2.3.1 Oct 19, 2020
Upgrade priority: Low. Recommended for `api-contracts` developers and those using large messages via Node.js WS.
Upgrade priority: Low. Recommended for `api-contract` developers and those using large messages via Node.js WS.
Contributed:
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>
+4 -4
View File
@@ -27,11 +27,11 @@
"@babel/core": "^7.12.3",
"@babel/register": "^7.12.1",
"@babel/runtime": "^7.12.1",
"@polkadot/dev": "^0.58.3",
"@polkadot/ts": "^0.3.49",
"@polkadot/dev": "^0.59.6",
"@polkadot/ts": "^0.3.51",
"@polkadot/typegen": "workspace:packages/typegen",
"@types/jest": "^26.0.14",
"@types/jest": "^26.0.15",
"copyfiles": "^2.4.0"
},
"version": "2.3.1"
"version": "2.4.1"
}
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-contract",
"version": "2.3.1",
"version": "2.4.1",
"description": "Interfaces for interacting with contracts and contract ABIs",
"main": "index.js",
"keywords": [
@@ -27,9 +27,9 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-contract#readme",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@polkadot/api": "2.3.1",
"@polkadot/rpc-core": "2.3.1",
"@polkadot/types": "2.3.1",
"@polkadot/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 -72
View File
@@ -7,84 +7,27 @@ import * as testContracts from '../test/contracts';
const abis: Record<string, any> = { ...testContracts };
function compareInterface (name: string, messageIds: string[]): void {
try {
const inkAbi = new Abi(abis[name]);
expect(inkAbi.messages.map(({ identifier }) => identifier)).toEqual(messageIds);
} catch (error) {
console.error(error);
throw error;
interface JSONAbi {
spec: {
messages: {
name: string[] | string
}[]
}
}
describe('Abi', (): void => {
describe('construction', (): void => {
it('initializes from a contract ABI (flipper)', (): void => {
compareInterface('flipper', ['flip', 'get']);
});
Object.entries(abis).forEach(([abiName, abi]) => {
it(`initializes from a contract ABI (${abiName})`, (): void => {
try {
const messageIds = (abi as JSONAbi).spec.messages.map(({ name }) => Array.isArray(name) ? name[0] : name);
const inkAbi = new Abi(abis[abiName]);
it('initializes from a contract ABI (incrementer)', (): void => {
compareInterface('incrementer', ['inc', 'get']);
});
expect(inkAbi.messages.map(({ identifier }) => identifier)).toEqual(messageIds);
} catch (error) {
console.error(error);
it('initializes from a contract ABI (erc20)', (): void => {
compareInterface('erc20', [
'total_supply',
'balance_of',
'allowance',
'transfer',
'approve',
'transfer_from'
]);
});
it('initializes from a contract ABI (delegator)', (): void => {
compareInterface('delegator', [
'get',
'change',
'switch'
]);
});
it('initializes from a contract ABI (dns)', (): void => {
compareInterface('dns', [
'register',
'set_address',
'transfer',
'get_address'
]);
});
it('initializes from a contract ABI (erc721)', (): void => {
compareInterface('erc721', [
'balance_of',
'owner_of',
'get_approved',
'is_approved_for_all',
'set_approval_for_all',
'approve',
'transfer',
'transfer_from',
'mint',
'burn'
]);
});
it('initializes from a contract ABI (multisig_plain)', (): void => {
compareInterface('multisigPlain', [
'add_owner',
'remove_owner',
'replace_owner',
'change_requirement',
'submit_transaction',
'cancel_transaction',
'confirm_transaction',
'revoke_confirmation',
'invoke_transaction',
'eval_transaction'
]);
throw error;
}
});
});
});
+110 -16
View File
@@ -1,11 +1,11 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { AnyJson } from '@polkadot/types/types';
import { ChainProperties, ContractConstructorSpec, ContractMessageSpec, ContractProject } from '@polkadot/types/interfaces';
import { AbiConstructor, AbiMessage, AbiMessageParam } from './types';
import { AnyJson, Codec, CodecArg } from '@polkadot/types/types';
import { ChainProperties, ContractConstructorSpec, ContractEventSpec, ContractMessageSpec, ContractMessageParamSpec, ContractProject } from '@polkadot/types/interfaces';
import { AbiConstructor, AbiEvent, AbiMessage, AbiParam, DecodedEvent, DecodedMessage } from './types';
import { assert, isNumber, isObject, isString, stringCamelCase } from '@polkadot/util';
import { assert, compactAddLength, compactStripLength, isNumber, isObject, isString, stringCamelCase, u8aConcat, u8aToHex } from '@polkadot/util';
import MetaRegistry from './MetaRegistry';
@@ -13,7 +13,7 @@ function findMessage <T extends AbiMessage> (list: T[], messageOrId: T | string
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)}`);
@@ -22,6 +22,8 @@ function findMessage <T extends AbiMessage> (list: T[], messageOrId: T | string
}
export default class Abi {
readonly #events: AbiEvent[];
public readonly constructors: AbiConstructor[];
public readonly json: AnyJson;
@@ -45,25 +47,56 @@ export default class Abi {
this.registry.setMetaTypes(this.project.types);
this.project.types.forEach((_, index) => this.registry.getMetaTypeDef(this.registry.createType('SiLookupTypeId', index + 1)));
this.project.types.forEach((_, index) =>
this.registry.getMetaTypeDef({ type: this.registry.createType('SiLookupTypeId', index + 1) })
);
this.constructors = this.project.spec.constructors.map((spec: ContractConstructorSpec, index) =>
this.#createBase(spec, index, {
this.#createMessage(spec, index, {
isConstructor: true
})
);
this.#events = this.project.spec.events.map((spec: ContractEventSpec, index) =>
this.#createEvent(spec, index)
);
this.messages = this.project.spec.messages.map((spec: ContractMessageSpec, index): AbiMessage => {
const typeSpec = spec.returnType.unwrapOr(null);
return this.#createBase(spec, index, {
return this.#createMessage(spec, index, {
isMutating: spec.mutates.isTrue,
isPayable: spec.payable.isTrue,
returnType: typeSpec
? this.registry.getMetaTypeDef(typeSpec.type)
? this.registry.getMetaTypeDef(typeSpec)
: null
});
});
}
/**
* Warning: Unstable API, bound to change
*/
public decodeEvent (data: Uint8Array): DecodedEvent {
const index = data[0];
const event = this.#events[index];
assert(event, `Unable to find event with index ${index}`);
return event.fromU8a(data.subarray(1));
}
/**
* Warning: Unstable API, bound to change
*/
public decodeConstructor (data: Uint8Array): DecodedMessage {
return this.#decodeMessage('message', this.constructors, data);
}
/**
* Warning: Unstable API, bound to change
*/
public decodeMessage (data: Uint8Array): DecodedMessage {
return this.#decodeMessage('message', this.messages, data);
}
public findConstructor (constructorOrId: AbiConstructor | string | number): AbiConstructor {
return findMessage(this.constructors, constructorOrId);
}
@@ -72,15 +105,14 @@ export default class Abi {
return findMessage(this.messages, messageOrId);
}
#createBase = (spec: ContractMessageSpec | ContractConstructorSpec, index: number, add: Partial<AbiMessage> = {}): AbiMessage => {
const identifier = spec.name.toString();
const args = spec.args.map((arg, index): AbiMessageParam => {
#createArgs = (args: ContractMessageParamSpec[], spec: unknown): AbiParam[] => {
return args.map((arg, index): AbiParam => {
try {
assert(isObject(arg.type), 'Invalid type definition found');
return {
name: stringCamelCase(arg.name.toString()),
type: this.registry.getMetaTypeDef(arg.type.type)
type: this.registry.getMetaTypeDef(arg.type)
};
} catch (error) {
console.error(`Error expanding argument ${index} in ${JSON.stringify(spec)}`);
@@ -88,14 +120,76 @@ export default class Abi {
throw error;
}
});
}
return {
#createEvent = (spec: ContractEventSpec, index: number): AbiEvent => {
const args = this.#createArgs(spec.args, spec);
const event = {
args,
docs: spec.docs.map((doc) => doc.toString()),
fromU8a: (data: Uint8Array): DecodedEvent => ({
args: this.#decodeArgs(args, data),
event
}),
identifier: spec.name.toString(),
index
};
return event;
}
#createMessage = (spec: ContractMessageSpec | ContractConstructorSpec, index: number, add: Partial<AbiMessage> = {}): AbiMessage => {
const args = this.#createArgs(spec.args, spec);
const message = {
...add,
args,
docs: spec.docs.map((doc) => doc.toString()),
identifier,
fromU8a: (data: Uint8Array): DecodedMessage => ({
args: this.#decodeArgs(args, data),
message
}),
identifier: spec.name.toString(),
index,
selector: spec.selector
selector: spec.selector,
toU8a: (params: CodecArg[]) =>
this.#encodeArgs(spec, args, params)
};
return message;
}
#decodeArgs = (args: AbiParam[], data: Uint8Array): Codec[] => {
// for decoding we expect the input to be just the arg data, no selectors
// no length added (this allows use with events as well)
let offset = 0;
return args.map(({ type }): Codec => {
const value = this.registry.createType(type.type as 'Text', data.subarray(offset));
offset += value.encodedLength;
return value;
});
}
#decodeMessage = (type: 'constructor' | 'message', list: AbiMessage[], data: Uint8Array): DecodedMessage => {
const [, trimmed] = compactStripLength(data);
const selector = trimmed.subarray(0, 4);
const message = list.find((m) => m.selector.eq(selector));
assert(message, `Unable to find ${type} with selector ${u8aToHex(selector)}`);
return message.fromU8a(trimmed.subarray(4));
}
#encodeArgs = ({ name, selector }: ContractMessageSpec | ContractConstructorSpec, args: AbiParam[], data: CodecArg[]): Uint8Array => {
assert(data.length === args.length, `Expected ${args.length} arguments to contract message '${name.toString()}', found ${data.length}`);
return compactAddLength(
u8aConcat(
this.registry.createType('ContractSelector', selector).toU8a(),
...args.map(({ type }, index) => this.registry.createType(type.type as 'Text', data[index]).toU8a())
)
);
}
}
+14 -46
View File
@@ -7,60 +7,28 @@ import path from 'path';
import Abi from './Abi';
import * as testContracts from '../test/contracts';
import * as userContracts from '../test/contracts/user';
const abis: Record<string, any> = { ...testContracts };
const userAbis: Record<string, any> = { ...userContracts };
function compareTypes (name: string): void {
const abi = new Abi(abis[name] || userAbis[name]);
try {
const cmpPath = path.join(__dirname, `../test/compare/${name}.test.json`);
if (!fs.existsSync(cmpPath)) {
fs.writeFileSync(cmpPath, JSON.stringify(abi.registry.metaTypeDefs, null, 2), { flag: 'w' });
}
// eslint-disable-next-line @typescript-eslint/no-var-requires
expect(abi.registry.metaTypeDefs).toEqual(require(cmpPath));
} catch (error) {
console.error(JSON.stringify(abi.registry.metaTypeDefs));
throw error;
}
}
describe('MetaRegistry', (): void => {
describe('types', (): void => {
it('initializes from a contract ABI (flipper)', (): void => {
compareTypes('flipper');
});
Object.keys(abis).forEach((abiName) => {
it(`initializes from a contract ABI (${abiName})`, (): void => {
const abi = new Abi(abis[abiName]);
it('initializes from a contract ABI (incrementer)', (): void => {
compareTypes('incrementer');
});
try {
const cmpPath = path.join(__dirname, `../test/compare/${abiName}.test.json`);
it('initializes from a contract ABI (erc20)', (): void => {
compareTypes('erc20');
});
if (!fs.existsSync(cmpPath)) {
fs.writeFileSync(cmpPath, JSON.stringify(abi.registry.metaTypeDefs, null, 2), { flag: 'w' });
}
it('initializes from a contract ABI (dns)', (): void => {
compareTypes('dns');
});
// eslint-disable-next-line @typescript-eslint/no-var-requires
expect(abi.registry.metaTypeDefs).toEqual(require(cmpPath));
} catch (error) {
console.error(JSON.stringify(abi.registry.metaTypeDefs));
it('initializes from a contract ABI (erc721)', (): void => {
compareTypes('erc721');
});
it('initializes from a contract ABI (multisig_plain)', (): void => {
compareTypes('multisigPlain');
});
});
describe('user ABIs', (): void => {
it('initializes from a contract ABI (withString)', (): void => {
compareTypes('withString');
throw error;
}
});
});
+38 -19
View File
@@ -1,12 +1,17 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { ChainProperties, SiField, SiLookupTypeId, SiType, SiTypeDefArray, SiTypeDefVariant, SiTypeDefSequence, SiTypeDefTuple, SiVariant } from '@polkadot/types/interfaces';
import { ContractDisplayName, ChainProperties, SiField, SiLookupTypeId, SiType, SiTypeDefArray, SiTypeDefVariant, SiTypeDefSequence, SiTypeDefTuple, SiVariant } from '@polkadot/types/interfaces';
import { InterfaceTypes, TypeDef, TypeDefInfo } from '@polkadot/types/types';
import { assert, isUndefined } from '@polkadot/util';
import { TypeRegistry, withTypeString } from '@polkadot/types';
interface PartialTypeSpec {
readonly type: SiLookupTypeId;
readonly displayName?: ContractDisplayName;
}
// convert the offset into project-specific, index-1
export function getRegistryOffset (id: SiLookupTypeId): number {
return id.toNumber() - 1;
@@ -34,24 +39,38 @@ export default class MetaRegistry extends TypeRegistry {
this.#siTypes = metaTypes;
}
public getMetaTypeDef (id: SiLookupTypeId): TypeDef {
const offset = getRegistryOffset(id);
public getMetaTypeDef (typeSpec: PartialTypeSpec): TypeDef {
const offset = getRegistryOffset(typeSpec.type);
let typeDef = this.metaTypeDefs[offset];
if (!typeDef) {
typeDef = this.#extract(this.#getMetaType(id), id);
typeDef = this.#extract(this.#getMetaType(typeSpec.type), typeSpec.type);
this.metaTypeDefs[offset] = typeDef;
}
// Here we protect against the following cases
// - No displayName present, these are generally known primitives
// - displayName === type, these generate circular references
// - displayName Option & type Option<...something...>
if (typeDef.displayName && !(typeDef.type === typeDef.displayName || typeDef.type.startsWith(`${typeDef.displayName}<`))) {
this.register({ [typeDef.displayName]: typeDef.type });
if (typeSpec.displayName && typeSpec.displayName.length) {
const displayName = typeSpec.displayName[typeSpec.displayName.length - 1].toString();
if (!typeDef.type.startsWith(displayName)) {
typeDef = {
...typeDef,
displayName,
type: ['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;
}
@@ -98,7 +117,7 @@ export default class MetaRegistry extends TypeRegistry {
: {}
),
...(type.params.length > 0
? { params: type.params.map((id) => this.getMetaTypeDef(id)) }
? { params: type.params.map((type) => this.getMetaTypeDef({ type })) }
: {}
),
...typeDef
@@ -111,7 +130,7 @@ export default class MetaRegistry extends TypeRegistry {
return {
info: TypeDefInfo.VecFixed,
length: length.toNumber(),
sub: this.getMetaTypeDef(type)
sub: this.getMetaTypeDef({ type })
};
}
@@ -135,7 +154,7 @@ export default class MetaRegistry extends TypeRegistry {
const sub = fields.map(({ name, type }) => {
return {
...this.getMetaTypeDef(type),
...this.getMetaTypeDef({ type }),
...(name.isSome ? { name: name.unwrap().toString() } : {})
};
});
@@ -166,16 +185,16 @@ export default class MetaRegistry extends TypeRegistry {
return {
info: TypeDefInfo.Vec,
sub: this.getMetaTypeDef(type)
sub: this.getMetaTypeDef({ type })
};
}
#extractTuple = (ids: SiTypeDefTuple): Omit<TypeDef, 'type'> => {
return ids.length === 1
? this.getMetaTypeDef(ids[0])
? this.getMetaTypeDef({ type: ids[0] })
: {
info: TypeDefInfo.Tuple,
sub: ids.map((id) => this.getMetaTypeDef(id))
sub: ids.map((type) => this.getMetaTypeDef({ type }))
};
}
@@ -186,14 +205,14 @@ export default class MetaRegistry extends TypeRegistry {
if (specialVariant === 'Option') {
return {
info: TypeDefInfo.Option,
sub: this.getMetaTypeDef(params[0])
sub: this.getMetaTypeDef({ type: params[0] })
};
} else if (specialVariant === 'Result') {
return {
info: TypeDefInfo.Result,
sub: params.map((param, index) => ({
sub: params.map((type, index) => ({
name: ['Ok', 'Error'][index],
...this.getMetaTypeDef(param)
...this.getMetaTypeDef({ type })
}))
};
}
+2 -2
View File
@@ -14,7 +14,7 @@ import ApiBase from '@polkadot/api/base';
import { isUndefined, stringCamelCase } from '@polkadot/util';
import Abi from '../Abi';
import { applyOnEvent, encodeMessage } from '../util';
import { applyOnEvent } from '../util';
import Base from './Base';
import Contract from './Contract';
@@ -54,7 +54,7 @@ export default class Blueprint<ApiType extends ApiTypes> extends Base<ApiType> {
#deploy = (constructorOrId: AbiConstructor | string| number, endowment: BigInt | string | number | BN, gasLimit: BigInt | string | number | BN, params: CodecArg[]): SubmittableExtrinsic<ApiType, BlueprintSubmittableResult<ApiType>> => {
return this.api.tx.contracts
.instantiate(endowment, gasLimit, this.codeHash, encodeMessage(this.registry, this.abi.findConstructor(constructorOrId), params))
.instantiate(endowment, gasLimit, this.codeHash, this.abi.findConstructor(constructorOrId).toU8a(params))
.withResultTransform((result: ISubmittableResult) =>
new BlueprintSubmittableResult(result, applyOnEvent(result, 'Instantiated', (record: EventRecord) =>
new Contract<ApiType>(this.api, this.abi, record.event.data[1] as AccountId, this._decorateMethod)
+5 -5
View File
@@ -6,7 +6,7 @@ import { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
import { AccountId, ContractExecResult } from '@polkadot/types/interfaces';
import { AnyJson, CodecArg } from '@polkadot/types/types';
import { AbiMessage, ContractCallOutcome } from '../types';
import { ContractCallResult, ContractRead, MapMessageExec, MapMessageRead } from './types';
import { ContractRead, MapMessageExec, MapMessageRead } from './types';
import BN from 'bn.js';
import { map } from 'rxjs/operators';
@@ -14,7 +14,7 @@ import ApiBase from '@polkadot/api/base';
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';
const ERROR_NO_CALL = 'Your node does not expose the contracts.call RPC. This is most probably due to a runtime configuration.';
@@ -69,7 +69,7 @@ export default class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
}
#exec = (messageOrId: AbiMessage | string | number, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, params: CodecArg[]): SubmittableExtrinsic<ApiType> => {
return this.api.tx.contracts.call(this.address, value, this.#getGas(gasLimit), encodeMessage(this.registry, this.abi.findMessage(messageOrId), params));
return this.api.tx.contracts.call(this.address, value, this.#getGas(gasLimit), this.abi.findMessage(messageOrId).toU8a(params));
}
#read = (messageOrId: AbiMessage | string | number, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, params: CodecArg[]): ContractRead<ApiType> => {
@@ -79,11 +79,11 @@ export default class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
return {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
send: this._decorateMethod((origin: string | AccountId | Uint8Array): ContractCallResult<'rpc'> =>
send: this._decorateMethod((origin: string | AccountId | Uint8Array) =>
this.api.rx.rpc.contracts.call({
dest: this.address,
gasLimit: this.#getGas(gasLimit),
inputData: encodeMessage(this.registry, message, params),
inputData: message.toU8a(params),
origin,
value
}).pipe(
+5 -12
View File
@@ -1,7 +1,6 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { SubmittableResult } from '@polkadot/api';
import { ApiTypes, ObsInnerType } from '@polkadot/api/types';
import { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
import { AccountId } from '@polkadot/types/interfaces';
@@ -11,20 +10,14 @@ import { ContractCallOutcome } from '../types';
import BN from 'bn.js';
import { Observable } from 'rxjs';
type ContractCallTypes = 'tx' | 'rpc';
type ContractCallResultSubscription<ApiType extends ApiTypes, CallType extends ContractCallTypes> = ApiType extends 'rxjs'
? Observable<ContractCallResult<CallType>>
: Promise<ObsInnerType<ContractCallResult<CallType>>>;
type ContractCallResult<ApiType extends ApiTypes, T> = ApiType extends 'rxjs'
? Observable<Observable<T>>
: Promise<ObsInnerType<Observable<T>>>;
export interface ContractRead<ApiType extends ApiTypes> {
send (account: string | AccountId | Uint8Array): ContractCallResultSubscription<ApiType, 'rpc'>;
send (account: string | AccountId | Uint8Array): ContractCallResult<ApiType, ContractCallOutcome>;
}
export type ContractCallResult<CallType extends ContractCallTypes> = CallType extends 'rpc'
? Observable<ContractCallOutcome>
: Observable<SubmittableResult>;
export interface MapConstructorExec<ApiType extends ApiTypes> {
[message: string]: (endowment: BigInt | string | number | BN, gasLimit: BigInt | string | number | BN, ...params: CodecArg[]) => SubmittableExtrinsic<ApiType>;
}
@@ -34,5 +27,5 @@ export interface MapMessageExec<ApiType extends ApiTypes> {
}
export interface MapMessageRead<ApiType extends ApiTypes> {
[message: string]: (origin: AccountId | string | Uint8Array, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, ...params: CodecArg[]) => ContractCallResultSubscription<ApiType, 'rpc'>;
[message: string]: (origin: AccountId | string | Uint8Array, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, ...params: CodecArg[]) => ContractCallResult<ApiType, ContractCallOutcome>;
}
+24 -4
View File
@@ -3,7 +3,7 @@
import { ApiTypes } from '@polkadot/api/types';
import { ContractExecResult, ContractSelector } from '@polkadot/types/interfaces';
import { Codec, TypeDef } from '@polkadot/types/types';
import { Codec, CodecArg, TypeDef } from '@polkadot/types/types';
import ApiBase from '@polkadot/api/base';
import Abi from './Abi';
@@ -16,14 +16,23 @@ export interface ContractBase<ApiType extends ApiTypes> {
messages: AbiMessage[];
}
export interface AbiMessageParam {
export interface AbiParam {
name: string;
type: TypeDef;
}
export interface AbiMessage {
args: AbiMessageParam[];
export interface AbiEvent {
args: AbiParam[];
docs: string[];
fromU8a: (data: Uint8Array) => DecodedEvent;
identifier: string;
index: number;
}
export interface AbiMessage {
args: AbiParam[];
docs: string[];
fromU8a: (data: Uint8Array) => DecodedMessage;
identifier: string;
index: number;
isConstructor?: boolean;
@@ -31,6 +40,7 @@ export interface AbiMessage {
isPayable?: boolean;
returnType?: TypeDef | null;
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: 'ContractSelector' })
));
return compactAddLength(new Clazz(registry, message.args.reduce((r: Record<string, CodecArg>, { name }, index): Record<string, CodecArg> => {
r[name] = params[index];
return r;
}, { __selector: message.selector })).toU8a());
}
@@ -0,0 +1,31 @@
[
{
"displayName": "AccountId",
"namespace": "ink_env::types",
"info": 6,
"type": "AccountId"
},
{
"info": 12,
"length": 32,
"sub": {
"info": 6,
"type": "u8"
},
"type": "[u8;32]"
},
{
"info": 6,
"type": "u8"
},
{
"info": 6,
"type": "i32"
},
{
"displayName": "Hash",
"namespace": "ink_env::types",
"info": 6,
"type": "Hash"
}
]
@@ -0,0 +1,6 @@
[
{
"info": 6,
"type": "u256"
}
]
@@ -1,10 +1,6 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as delegator } from './delegator.json';
export { default as dns } from './dns.json';
export { default as erc20 } from './erc20.json';
export { default as erc721 } from './erc721.json';
export { default as flipper } from './flipper.json';
export { default as incrementer } from './incrementer.json';
export { default as multisigPlain } from './multisig_plain.json';
export * from './ink';
export * from './solang';
export * from './user';
@@ -0,0 +1,10 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as delegator } from './delegator.json';
export { default as dns } from './dns.json';
export { default as erc20 } from './erc20.json';
export { default as erc721 } from './erc721.json';
export { default as flipper } from './flipper.json';
export { default as incrementer } from './incrementer.json';
export { default as multisigPlain } from './multisig_plain.json';
@@ -0,0 +1,4 @@
// Copyright 2017-2020 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as ints256 } from './ints256.json';
@@ -0,0 +1,113 @@
{
"contract": {
"authors": [
"Sean Young <sean@mess.org>"
],
"description": "Test 256 bits types",
"name": "ints256",
"version": "0.0.1"
},
"metadataVersion": "0.1.0",
"source": {
"compiler": "solang 0.1.4",
"hash": "0xa85fb5c61a09d71dce84c15a8bd87e6f4eafac498a1aec3869e8cf7ea4389697",
"language": "Solidity 0.1.4"
},
"spec": {
"constructors": [
{
"args": [],
"docs": [
""
],
"name": "new",
"selector": "0x861731d5"
}
],
"events": [],
"messages": [
{
"args": [
{
"name": "a",
"type": {
"display_name": [
"u256"
],
"type": 1
}
},
{
"name": "b",
"type": {
"display_name": [
"u256"
],
"type": 1
}
}
],
"docs": [
"Multiply two 256 bit values\n\n"
],
"mutates": false,
"name": "multiply",
"payable": false,
"return_type": {
"display_name": [
"u256"
],
"type": 1
},
"selector": "0x165c4a16"
},
{
"args": [
{
"name": "a",
"type": {
"display_name": [
"u256"
],
"type": 1
}
},
{
"name": "b",
"type": {
"display_name": [
"u256"
],
"type": 1
}
}
],
"docs": [
"Add two 256 bit values\n\n"
],
"mutates": false,
"name": "add",
"payable": false,
"return_type": {
"display_name": [
"u256"
],
"type": 1
},
"selector": "0x771602f7"
}
]
},
"storage": {
"struct": {
"fields": []
}
},
"types": [
{
"def": {
"primitive": "u256"
}
}
]
}
@@ -0,0 +1,13 @@
/// @title Test 256 bits types
/// @author Sean Young <sean@mess.org>
contract ints256 {
/// Multiply two 256 bit values
function multiply(uint256 a, uint256 b) public pure returns (uint256) {
return a * b;
}
/// Add two 256 bit values
function add(uint256 a, uint256 b) public pure returns (uint256) {
return a + b;
}
}
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api-derive",
"version": "2.3.1",
"version": "2.4.1",
"description": "Common functions used across Polkadot, derived from RPC calls and storage queries.",
"main": "index.js",
"keywords": [
@@ -28,10 +28,10 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-derive#readme",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@polkadot/api": "2.3.1",
"@polkadot/rpc-core": "2.3.1",
"@polkadot/rpc-provider": "2.3.1",
"@polkadot/types": "2.3.1",
"@polkadot/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",
+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';
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/api",
"version": "2.3.1",
"version": "2.4.1",
"description": "Promise and RxJS wrappers around the Polkadot JS RPC",
"main": "index.js",
"keywords": [
@@ -27,13 +27,13 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api#readme",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@polkadot/api-derive": "2.3.1",
"@polkadot/api-derive": "^2.4.1",
"@polkadot/keyring": "^3.6.1",
"@polkadot/metadata": "2.3.1",
"@polkadot/rpc-core": "2.3.1",
"@polkadot/rpc-provider": "2.3.1",
"@polkadot/types": "2.3.1",
"@polkadot/types-known": "2.3.1",
"@polkadot/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",
+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][] =>
+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>;
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/metadata",
"version": "2.3.1",
"version": "2.4.1",
"description": "Helpers to extract information from runtime metadata",
"main": "index.js",
"publishConfig": {
@@ -27,8 +27,8 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/type-metadata#readme",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@polkadot/types": "2.3.1",
"@polkadot/types-known": "2.3.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"
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/rpc-core",
"version": "2.3.1",
"version": "2.4.1",
"description": "A JavaScript wrapper for the Polkadot JsonRPC interface",
"main": "index.js",
"keywords": [
@@ -27,9 +27,9 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/rpc-core#readme",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@polkadot/metadata": "2.3.1",
"@polkadot/rpc-provider": "2.3.1",
"@polkadot/types": "2.3.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"
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/rpc-provider",
"version": "2.3.1",
"version": "2.4.1",
"description": "Transport providers for the API",
"main": "index.js",
"keywords": [
@@ -27,12 +27,12 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/rpc-provider#readme",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@polkadot/metadata": "2.3.1",
"@polkadot/types": "2.3.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.3",
"@polkadot/x-ws": "^0.3.3",
"@polkadot/x-fetch": "^0.3.4",
"@polkadot/x-ws": "^0.3.4",
"bn.js": "^5.1.3",
"eventemitter3": "^4.0.7"
},
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/typegen",
"version": "2.3.1",
"version": "2.4.1",
"description": "Type generation scripts",
"main": "index.js",
"bin": {
@@ -36,10 +36,10 @@
"@babel/core": "^7.12.3",
"@babel/register": "^7.12.1",
"@babel/runtime": "^7.12.1",
"@polkadot/api": "2.3.1",
"@polkadot/metadata": "2.3.1",
"@polkadot/rpc-provider": "2.3.1",
"@polkadot/types": "2.3.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",
+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();
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/types-known",
"version": "2.3.1",
"version": "2.4.1",
"description": "A JavaScript wrapper for the Polkadot JsonRPC interface",
"main": "index.js",
"keywords": [
@@ -27,7 +27,7 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/types-known#readme",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@polkadot/types": "2.3.1",
"@polkadot/types": "^2.4.1",
"@polkadot/util": "^3.6.1",
"bn.js": "^5.1.3"
},
+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;
-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/docs/api/FAQ#i-cannot-send-transactions-from-my-node-template-based-chain',
'- If you have trouble parsing events, apply https://polkadot.js.org/docs/api/FAQ#using-a-non-current-master-node-i-have-issues-parsing-events',
''
]
};
export default warnings;
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@polkadot/types",
"version": "2.3.1",
"version": "2.4.1",
"description": "Implementation of the Parity codec",
"main": "index.js",
"keywords": [
@@ -27,7 +27,7 @@
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/types#readme",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@polkadot/metadata": "2.3.1",
"@polkadot/metadata": "^2.4.1",
"@polkadot/util": "^3.6.1",
"@polkadot/util-crypto": "^3.6.1",
"@types/bn.js": "^4.11.6",
+4 -1
View File
@@ -36,7 +36,7 @@ import { ProxyAnnouncement, ProxyDefinition, ProxyType } from '@polkadot/types/i
import { AccountStatus, AccountValidity } from '@polkadot/types/interfaces/purchase';
import { ActiveRecovery, RecoveryConfig } from '@polkadot/types/interfaces/recovery';
import { RpcMethods } from '@polkadot/types/interfaces/rpc';
import { AccountId, AccountIdOf, AccountIndex, Address, AssetId, Balance, BalanceOf, Block, BlockNumber, Call, CallHash, CallHashOf, ChangesTrieConfiguration, Consensus, ConsensusEngineId, Digest, DigestItem, ExtrinsicsWeight, Fixed128, Fixed64, FixedI128, FixedI64, FixedU128, FixedU64, GenericAddress, H160, H256, H512, Hash, Header, I32F32, Index, Justification, KeyTypeId, KeyValue, LockIdentifier, LookupSource, LookupTarget, ModuleId, Moment, OpaqueCall, Origin, OriginCaller, PalletVersion, PalletsOrigin, Pays, PerU16, Perbill, Percent, Permill, Perquintill, Phantom, PhantomData, PreRuntime, Releases, RuntimeDbWeight, Seal, SealV0, SignedBlock, StorageData, TransactionPriority, U32F32, ValidatorId, Weight, WeightMultiplier } from '@polkadot/types/interfaces/runtime';
import { AccountId, AccountIdOf, AccountIndex, Address, AssetId, Balance, BalanceOf, Block, BlockNumber, Call, CallHash, CallHashOf, ChangesTrieConfiguration, Consensus, ConsensusEngineId, Digest, DigestItem, ExtrinsicsWeight, Fixed128, Fixed64, FixedI128, FixedI64, FixedU128, FixedU64, GenericAddress, H160, H256, H512, Hash, Header, I32F32, Index, Justification, KeyTypeId, KeyValue, LockIdentifier, LookupSource, LookupTarget, ModuleId, Moment, MultiAddress, OpaqueCall, Origin, OriginCaller, PalletVersion, PalletsOrigin, Pays, PerU16, Perbill, Percent, Permill, Perquintill, Phantom, PhantomData, PreRuntime, Releases, RuntimeDbWeight, Seal, SealV0, SignedBlock, StorageData, TransactionPriority, U32F32, ValidatorId, Weight, WeightMultiplier } from '@polkadot/types/interfaces/runtime';
import { SiField, SiLookupTypeId, SiPath, SiType, SiTypeDef, SiTypeDefArray, SiTypeDefComposite, SiTypeDefPrimitive, SiTypeDefSequence, SiTypeDefTuple, SiTypeDefVariant, SiVariant } from '@polkadot/types/interfaces/scaleInfo';
import { Period, Priority, SchedulePeriod, SchedulePriority, Scheduled, ScheduledTo254, TaskAddress } from '@polkadot/types/interfaces/scheduler';
import { FullIdentification, IdentificationTuple, Keys, MembershipProof, SessionIndex, SessionKeys1, SessionKeys2, SessionKeys3, SessionKeys4, SessionKeys5, SessionKeys6, ValidatorCount } from '@polkadot/types/interfaces/session';
@@ -280,6 +280,9 @@ declare module '@polkadot/types/types/registry' {
ModuleId: ModuleId;
'Option<ModuleId>': Option<ModuleId>;
'Vec<ModuleId>': Vec<ModuleId>;
MultiAddress: MultiAddress;
'Option<MultiAddress>': Option<MultiAddress>;
'Vec<MultiAddress>': Vec<MultiAddress>;
Moment: Moment;
'Compact<Moment>': Compact<Moment>;
'Option<Moment>': Option<Moment>;
@@ -0,0 +1,44 @@
// Copyright 2017-2020 @polkadot/types authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { Registry } from '../types';
import { isString, u8aConcat } from '@polkadot/util';
import { decodeAddress } from '@polkadot/util-crypto';
import Enum from '../codec/Enum';
export default class MultiAddress extends Enum {
constructor (registry: Registry, value?: unknown) {
super(registry, {
Id: 'AccountId',
Index: 'Compact<AccountIndex>',
Raw: 'Bytes',
// eslint-disable-next-line sort-keys
Address32: 'H256',
// eslint-disable-next-line sort-keys
Address20: 'H160'
}, MultiAddress._decodeMultiAddress(value as string));
}
private static _decodeMultiAddress (value?: unknown): unknown {
if (isString(value)) {
try {
const u8a = decodeAddress(value.toString());
return u8aConcat(new Uint8Array(u8a.length <= 8 ? 1 : 0), u8a);
} catch (error) {
// ignore, not a valid ss58 address
}
}
return value;
}
/**
* @description Returns the string representation of the value
*/
public toString (): string {
return this.value.toString();
}
}
+1
View File
@@ -10,4 +10,5 @@ export { default as GenericCall } from './Call';
export { default as GenericConsensusEngineId } from './ConsensusEngineId';
export { default as GenericEvent } from './Event';
export { default as GenericLookupSource } from './LookupSource';
export { default as GenericMultiAddress } from './MultiAddress';
export { default as GenericVote } from './Vote';
@@ -81,6 +81,7 @@ export default {
LookupSource: 'GenericLookupSource',
LookupTarget: 'AccountId',
ModuleId: 'LockIdentifier',
MultiAddress: 'GenericMultiAddress',
Moment: 'u64',
OpaqueCall: 'Bytes',
Origin: 'DoNotConstruct<Origin>',
@@ -3,7 +3,7 @@
import { ITuple } from '@polkadot/types/types';
import { Compact, Enum, Int, Struct, U8aFixed, UInt, Vec } from '@polkadot/types/codec';
import { GenericAccountId, GenericAccountIndex, GenericBlock, GenericCall, GenericConsensusEngineId, GenericLookupSource } from '@polkadot/types/generic';
import { GenericAccountId, GenericAccountIndex, GenericBlock, GenericCall, GenericConsensusEngineId, GenericLookupSource, GenericMultiAddress } from '@polkadot/types/generic';
import { Bytes, DoNotConstruct, Null, StorageKey, u16, u32, u64, u8 } from '@polkadot/types/primitive';
import { AuthorityId } from '@polkadot/types/interfaces/consensus';
import { Signature } from '@polkadot/types/interfaces/extrinsics';
@@ -158,6 +158,9 @@ export interface ModuleId extends LockIdentifier {}
/** @name Moment */
export interface Moment extends u64 {}
/** @name MultiAddress */
export interface MultiAddress extends GenericMultiAddress {}
/** @name OpaqueCall */
export interface OpaqueCall extends Bytes {}
@@ -41,7 +41,7 @@ export default {
variants: 'Vec<SiVariant>'
},
SiTypeDefPrimitive: {
_enum: ['Bool', 'Char', 'Str', 'U8', 'U16', 'U32', 'U64', 'U128', 'I8', 'I16', 'I32', 'I64', 'I128']
_enum: ['Bool', 'Char', 'Str', 'U8', 'U16', 'U32', 'U64', 'U128', 'U256', 'I8', 'I16', 'I32', 'I64', 'I128', 'I256']
},
SiTypeDefSequence: {
type: 'SiLookupTypeId'
@@ -60,11 +60,13 @@ export interface SiTypeDefPrimitive extends Enum {
readonly isU32: boolean;
readonly isU64: boolean;
readonly isU128: boolean;
readonly isU256: boolean;
readonly isI8: boolean;
readonly isI16: boolean;
readonly isI32: boolean;
readonly isI64: boolean;
readonly isI128: boolean;
readonly isI256: boolean;
}
/** @name SiTypeDefSequence */
+548 -577
View File
File diff suppressed because it is too large Load Diff