Move to lerna repo (#19)

* Pull api-* packages into lerna repo

* Bootstrap with hoist

* Update jest alias config

* Add api-jsonrpc

* Pull in jsonrpc

* Update badges

* Don't hoist, use workspaces

* .eslintrc to root

* Cleanups, build from root

* Shorthand commands

* Update to @polkadot/dev 0.9.1

* Update description
This commit is contained in:
Jaco Greeff
2017-11-28 18:03:48 +01:00
committed by GitHub
parent bf6880d5b0
commit e8ccc9aa79
64 changed files with 2378 additions and 136 deletions

1
.eslintignore Normal file
View File

@@ -0,0 +1 @@
**/build/*

View File

@@ -2,6 +2,7 @@
.*/build/.*
[include]
./node_modules/@polkadot/dev/flow-typed
[libs]
@@ -9,3 +10,7 @@
esproposal.decorators=ignore
module.ignore_non_literal_requires=true
unsafe.enable_getters_and_setters=true
module.name_mapper='^@polkadot/api-format\(.*\)$' -> '<PROJECT_ROOT>/packages/api-format/src\1'
module.name_mapper='^@polkadot/api-jsonrpc\(.*\)$' -> '<PROJECT_ROOT>/packages/api-jsonrpc/src\1'
module.name_mapper='^@polkadot/api-provider\(.*\)$' -> '<PROJECT_ROOT>/packages/api-provider/src\1'
module.name_mapper='^@polkadot/jsonrpc\(.*\)$' -> '<PROJECT_ROOT>/packages/api-jsonrpc/src\1'

1
.gitignore vendored
View File

@@ -7,6 +7,7 @@ tmp/
.env.development.local
.env.test.local
.env.production.local
lerna-debug.log*
npm-debug.log*
yarn-debug.log*
yarn-error.log*

View File

@@ -1,21 +1 @@
coverage
scripts
src
test
tmp
.babelrc
.coveralls.yml
.editorconfig
.eslintrc.json
.flowconfig
.gitignore
.istanbul.yml
.travis.yml
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

View File

@@ -6,8 +6,10 @@ cache:
directories:
- node_modules
before_install:
- npm install -g yarn --cache-min 999999999
- npm install --global yarn --cache-min 999999999
- npm install --global lerna
install:
- yarn
- yarn install
- lerna bootstrap
script:
- yarn run polkadot-dev-build-travis
- yarn polkadot-dev-build-travis

View File

@@ -1,40 +1,22 @@
![ISC](https://img.shields.io/badge/license-ISC-lightgrey.svg)
[![npm (scoped)](https://img.shields.io/npm/v/@polkadot/api.svg)](https://www.npmjs.com/package/@polkadot/api)
[![Build Status](https://travis-ci.org/polkadot-js/api.svg?branch=master)](https://travis-ci.org/polkadot-js/api)
[![Coverage Status](https://coveralls.io/repos/github/polkadot-js/api/badge.svg?branch=master)](https://coveralls.io/github/polkadot-js/api?branch=master)
[![Greenkeeper badge](https://badges.greenkeeper.io/polkadot-js/api.svg)](https://greenkeeper.io/)
[![Dependency Status](https://david-dm.org/polkadot-js/api.svg)](https://david-dm.org/polkadot-js/api)
[![devDependency Status](https://david-dm.org/polkadot-js/api/dev-status.svg)](https://david-dm.org/polkadot-js/api#info=devDependencies)
# @polkadot/api
# @polkadot/client
Warning - currently this does not actually do all that much, it is an attempt to put into code some thoughts about how to maintain the endpoints. This library provides a clean wrapper around all the methods exposed by a Polkadot network client. Methods are auto-generated for the [JsonRPC interface definitions](https://github.com/polkadot-js/jsonrpc).
This library provides a clean wrapper around all the methods exposed by a Polkadot network client.
## Usage
It is split up into a number of internal packages -
Installation -
- [@polkadot/api](packages/api/) The API library
- [@polkadot/api-format](packages/api-format/) Input and output formatters
- [@polkadot/api-jsonrpc](packages/api-jsonrpc/) Interface definitions for RPC
- [@polkadot/api-provider](packages/api-provider/) Transport providers
```
npm install --save @polkadot/api
```
## Contributing
Initialisation -
```js
import Api from '@polkadot/api';
import HttpProvider from '@polkadot/api-provider/http';
const provider = new HttpProvider('http://127.0.0.1:9933');
const api = new Api(provider);
```
Making calls -
```js
api.chain
.getHeader('0x1234567890')
.then((header) => console.log(header))
.catch((error) => console.error(error));
```
## Available methods
For a list of currently exposed methods, see the [@polkadot/jsonrpc](https://github.com/polkadot-js/jsonrpc#readme) repository.
- Make sure you have [Lerna](https://lernajs.io/) installed, `yarn install -g lerna`
- Bootstrap the dependencies, `lerna bootstrap`
- Make any changes in the relevant package, on master merges new versions will be published automatically

View File

@@ -1 +1,9 @@
module.exports = require('@polkadot/dev/jest.config');
const config = require('@polkadot/dev/jest.config');
module.exports = Object.assign({}, config, {
moduleNameMapper: {
'@polkadot/api-format(.*)$': '<rootDir>/packages/api-format/src/$1',
'@polkadot/api-jsonrpc(.*)$': '<rootDir>/packages/api-jsonrpc/src/$1',
'@polkadot/api-provider(.*)$': '<rootDir>/packages/api-provider/src/$1'
}
});

14
lerna.json Normal file
View File

@@ -0,0 +1,14 @@
{
"lerna": "2.5.1",
"npmClient": "yarn",
"useWorkspaces": true,
"command": {
"publish": {
"allowBranch": "master"
}
},
"packages": [
"packages/*"
],
"version": "0.5.0"
}

View File

@@ -1,20 +1,13 @@
{
"name": "@polkadot/api",
"version": "0.4.14",
"description": "A JavaScript wrapper for the Polkadot JsonRPC interface",
"main": "index.js",
"keywords": [
"Polkadot",
"JsonRPC"
],
"name": "@polkadot/api-wrapper",
"version": "0.5.0",
"description": "Non-published, see packages/",
"keywords": [],
"author": "Jaco Greeff <jacogr@gmail.com>",
"license": "ISC",
"private": true,
"engines": {
"node": ">=6.4"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"
"node": ">=8.0"
},
"repository": {
"type": "git",
@@ -25,18 +18,16 @@
},
"homepage": "https://github.com/polkadot-js/api#readme",
"scripts": {
"build": "polkadot-dev-build-babel",
"check": "eslint src && flow check",
"test": "jest --coverage src"
"build": "yarn polkadot-dev-build-babel",
"check": "yarn eslint packages && yarn flow check",
"test": "yarn jest --coverage packages"
},
"devDependencies": {
"@polkadot/dev": "^0.8.1"
"@polkadot/dev": "^0.9.1",
"lerna": "^2.5.1"
},
"dependencies": {
"@polkadot/api-format": "^0.3.7",
"@polkadot/api-provider": "^0.1.6",
"@polkadot/jsonrpc": "^0.3.9",
"@polkadot/util": "^0.5.10",
"babel-runtime": "^6.26.0"
}
"dependencies": {},
"workspaces": [
"packages/*"
]
}

View File

@@ -0,0 +1,15 @@
ISC License (ISC)
Copyright 2017 Jaco Greeff <jacogr@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

View File

@@ -0,0 +1,14 @@
[![Dependency Status](https://david-dm.org/polkadot-js/api.svg?path=packages/api-format)](https://david-dm.org/polkadot-js/api?path=packages/api-format)
[![devDependency Status](https://david-dm.org/polkadot-js/api/dev-status.svg?path=packages/api-format)](https://david-dm.org/polkadot-js/api?path=packages/api-format#info=devDependencies)
# @polkadot/api-format
Formatters that are used by the application API interface, taking care of transparently formatting parameters (inputs) and the results (output) for requests made over the client RPC interfaces.
## Usage
Installation -
```
npm install --save @polkadot/api-format
```

View File

@@ -0,0 +1,40 @@
{
"name": "@polkadot/api-format",
"version": "0.5.0",
"description": "Input/Output formatters for JsonRPC exchange",
"main": "index.js",
"keywords": [
"Polkadot",
"JsonRPC"
],
"author": "Jaco Greeff <jacogr@gmail.com>",
"license": "ISC",
"engines": {
"node": ">=6.4"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"
},
"repository": {
"type": "git",
"url": "git+https://github.com/polkadot-js/api.git"
},
"bugs": {
"url": "https://github.com/polkadot-js/api/issues"
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-format#readme",
"scripts": {
"build": "polkadot-dev-build-babel",
"check": "eslint src && flow check",
"test": "echo \"Tests only available from root wrapper\""
},
"devDependencies": {
"@polkadot/api-jsonrpc": "^0.5.0",
"@polkadot/dev": "^0.9.1"
},
"dependencies": {
"@polkadot/util": "^0.5.15",
"babel-runtime": "^6.26.0"
}
}

View File

@@ -0,0 +1,10 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
const formatInputs = require('./input');
const formatOutput = require('./output');
module.exports = {
formatInputs,
formatOutput
};

View File

@@ -0,0 +1,10 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
const { formatH160 } = require('./hex');
// TODO: Currently the format assumes 160-bit values (like Ethereum)
// this will probably change along the way as things get firmed up
module.exports = function format (value: ?string): string {
return formatH160(value);
};

View File

@@ -0,0 +1,13 @@
// ISC, Copyright 2017 Jaco Greeff
const format = require('./address');
describe('input/address', () => {
describe('format', () => {
it('pads to H160 value', () => {
expect(
format('0x1234567890')
).toEqual('0x0000000000000000000000000000001234567890');
});
});
});

View File

@@ -0,0 +1,33 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
const { hexAddPrefix, hexHasPrefix, hexStripPrefix } = require('@polkadot/util/hex');
const H64_ZERO: string = '00000000000000000000000000000000';
const H128_ZERO: string = `${H64_ZERO}${H64_ZERO}`;
const H256_ZERO: string = `${H128_ZERO}${H128_ZERO}`;
// const H512_ZERO: string = `${H256_ZERO}${H256_ZERO}`;
function leftHexPad (value: ?string, bitLength: number): string {
const length = 2 * bitLength / 8;
if (hexHasPrefix(value)) {
value = hexStripPrefix(value);
}
return hexAddPrefix(`${H256_ZERO}${value || ''}`.slice(-length));
}
function formatH160 (value: ?string): string {
return leftHexPad(value, 160);
}
function formatH256 (value: ?string): string {
return leftHexPad(value, 256);
}
module.exports = {
leftHexPad,
formatH160,
formatH256
};

View File

@@ -0,0 +1,53 @@
// ISC, Copyright 2017 Jaco Greeff
const { leftHexPad, formatH160, formatH256 } = require('./hex');
describe('input/hex', () => {
describe('leftHexPad', () => {
it('padds to the required length', () => {
expect(
leftHexPad('0x123', 16)
).toEqual('0x0123');
});
it('padds to the required length (no prefix)', () => {
expect(
leftHexPad('123', 16)
).toEqual('0x0123');
});
it('pads null values correctly', () => {
expect(
leftHexPad(null, 16)
).toEqual('0x0000');
});
});
describe('formatH160', () => {
it('pads to 40 bytes', () => {
expect(
formatH160('0x1234567890')
).toEqual('0x0000000000000000000000000000001234567890');
});
it('pads null values correctly', () => {
expect(
formatH160(null)
).toMatch(/^0x(00){20,}$/);
});
});
describe('formatH256', () => {
it('pads to 64 bytes', () => {
expect(
formatH256('0x1234567890')
).toEqual('0x0000000000000000000000000000000000000000000000000000001234567890');
});
it('pads null values correctly', () => {
expect(
formatH256(null)
).toMatch(/^0x(00){32,}$/);
});
});
});

View File

@@ -0,0 +1,24 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
import type { FormatInputType, InterfaceInputType } from '@polkadot/api-jsonrpc/types';
import type { FormatterFunction } from '../types';
const formatAddress = require('./address');
const { formatH256 } = require('./hex');
const formatNoop = require('../noop');
const util = require('../util');
const formatters: { [FormatInputType]: FormatterFunction } = {
'Address': formatAddress,
'CallData': formatNoop,
'H256': formatH256,
'HeaderHash': formatH256,
'String': formatNoop
};
module.exports = function format (inputs: Array<InterfaceInputType>, values: Array<any>): Array<any> {
const types = inputs.map(({ type }) => type);
return util.formatArray(formatters, types, values);
};

View File

@@ -0,0 +1,22 @@
// ISC, Copyright 2017 Jaco Greeff
const format = require('./index');
describe('input', () => {
describe('format', () => {
it('formats each value in an array', () => {
expect(
format(
[
{ name: 'foo', type: 'Address' },
{ name: 'bar', type: 'H256' }
],
['0x1234', '0xabcd']
)
).toEqual([
'0x0000000000000000000000000000000000001234',
'0x000000000000000000000000000000000000000000000000000000000000abcd'
]);
});
});
});

View File

@@ -0,0 +1,6 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
module.exports = function format (value: any): any {
return value;
};

View File

@@ -0,0 +1,13 @@
// ISC, Copyright 2017 Jaco Greeff
const format = require('./noop');
describe('noop', () => {
it('returns input value as output value', () => {
const input = { 'some': 'object' };
expect(
format(input)
).toEqual(input);
});
});

View File

@@ -0,0 +1,18 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
import type { FormatOutputType, InterfaceOutputType } from '@polkadot/api-jsonrpc/types';
import type { FormatterFunction } from '../types';
const formatNoop = require('../noop');
const util = require('../util');
const formatters: { [FormatOutputType]: FormatterFunction } = {
'Header': formatNoop,
'OutData': formatNoop,
'StorageData': formatNoop
};
module.exports = function format (output: InterfaceOutputType, value: any): any {
return util.format(formatters, output.type, value);
};

View File

@@ -0,0 +1,13 @@
// ISC, Copyright 2017 Jaco Greeff
const format = require('./index');
describe('output', () => {
describe('format', () => {
it('formats the value', () => {
expect(
format('Header', 'test')
).toEqual('test');
});
});
});

View File

@@ -0,0 +1,4 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
export type FormatterFunction = (value: any) => any;

View File

@@ -0,0 +1,49 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
import type { FormatterFunction } from './types';
const { isUndefined } = require('@polkadot/util/is');
const formatNoop = require('./noop');
const arrayTypeRegex = /\[\]$/;
function format (formatters: { [any]: FormatterFunction }, type: string, value: any): any {
const isArrayType: boolean = arrayTypeRegex.test(type);
const formatter: FormatterFunction = isArrayType
? formatters[type.replace(arrayTypeRegex, '')]
: formatters[type];
if (isUndefined(formatter)) {
console.warn(`Unable to find default formatter for '${type}', falling back to noop`);
return formatNoop(value);
}
if (isArrayType && !Array.isArray(value)) {
throw new Error(`Unable to format non-array '${value}' as '${type}'`);
}
try {
if (isArrayType) {
return (value: Array<any>).map((value) => formatter(value));
} else {
return formatter(value);
}
} catch (error) {
throw new Error(`Error formatting '${value}' as '${type}'': ${error.message}`);
}
}
function formatArray (formatters: { [any]: FormatterFunction }, types: Array<string>, values: Array<any>): Array<any> {
return types.map((type, index) => {
const value = values[index];
return format(formatters, type, value);
});
}
module.exports = {
format,
formatArray
};

View File

@@ -0,0 +1,86 @@
// ISC, Copyright 2017 Jaco Greeff
/* global jest */
const { format, formatArray } = require('./util');
const formatNoop = require('./noop');
describe('util', () => {
let formatters;
let noopSpy;
let warnSpy;
beforeEach(() => {
noopSpy = jest.fn(formatNoop);
warnSpy = jest.spyOn(console, 'warn');
formatters = {
'Address': noopSpy,
'Address[]': noopSpy,
'Exception': () => {
throw new Error('something went wrong');
}
};
});
afterEach(() => {
noopSpy.mockRestore();
warnSpy.mockRestore();
});
describe('format', () => {
it('formats unknown types with a fallback', () => {
expect(
format(formatters, 'Unknown', 'test')
).toEqual('test');
});
it('logs a warning with unknown types', () => {
format(formatters, 'Unknown', 'test');
expect(warnSpy).toHaveBeenCalledWith("Unable to find default formatter for 'Unknown', falling back to noop");
});
it('wraps exceptions with the type', () => {
expect(
() => format(formatters, 'Exception', 'test')
).toThrow(/Error formatting 'test' as 'Exception'/);
});
describe('primitives', () => {
it('formats known types using the supplied formatter', () => {
format(formatters, 'Address', '0xaddress');
expect(noopSpy).toHaveBeenCalledWith('0xaddress');
});
});
describe('primitive[]', () => {
it('throws exception with array type, but non-array value', () => {
expect(
() => format(formatters, 'Address[]', 'not-an-array')
).toThrow(/Unable to format non-array/);
});
it('formats using the primitive type', () => {
format(formatters, 'Address[]', ['0x123', '0x234']);
expect(noopSpy).toHaveBeenCalledWith('0x123');
expect(noopSpy).toHaveBeenCalledWith('0x234');
});
it('returns formatted values as arrays', () => {
expect(
format(formatters, 'Address[]', ['0x123', '0x234'])
).toEqual(['0x123', '0x234']);
});
});
});
describe('formatArray', () => {
it('formats each value in an array', () => {
expect(
formatArray(formatters, ['Unknown', 'Unknown'], ['test', 'blah'])
).toEqual(['test', 'blah']);
});
});
});

View File

@@ -0,0 +1,15 @@
ISC License (ISC)
Copyright 2017 Jaco Greeff <jacogr@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

View File

@@ -0,0 +1,23 @@
[![Dependency Status](https://david-dm.org/polkadot-js/api.svg?path=packages/api-jsonrpc)](https://david-dm.org/polkadot-js/api?path=packages/api-jsonrpc)
[![devDependency Status](https://david-dm.org/polkadot-js/api/dev-status.svg?path=packages/api-jsonrpc)](https://david-dm.org/polkadot-js/api?path=packages/api-jsonrpc#info=devDependencies)
# @polkadot/api-jsonrpc
A defintion of all the methods exposed in a general Polkadot client application. These are used not only to provide a comprehensive code-generated document of the available methods, but are also used in the API to auto-generate endpoints with the required type-checking.
## Usage
Installation -
```
npm install --save @polkadot/api-jsonrpc
```
For a list of currently exposed methods, see the [method documentation](docs/README.md).
## Adding methods
As methods are added, simply adding the name, inputs & output will prepare it for use.
- Add the method to the correct file in [src/rpc/](src/rpc/) (Input/Output types as cross-referenced from the canonical implementation and match one-to-one)
- Should a new type be required, add it to the type list, [src/types.js](src/types.js) (Required for flow type checking)

View File

@@ -0,0 +1,7 @@
# Available interfaces
Exposes the definition for the RPC endpoints for a Polkadot client node
- [chain](chain.md) Methods to retrieve chain data.
- [state](state.md) Query the state and state storage.

View File

@@ -0,0 +1,17 @@
# chain
Methods to retrieve chain data.
- [getHeader](#getheader) Retrieves the header for a specific block.
## getHeader
Retrieves the header for a specific block.
```js
chain_getHeader (hash: HeaderHash): Header
```
Given a block header specified by `hash`, return the full block `Header` information.

View File

@@ -0,0 +1,31 @@
# state
Query the state and state storage.
- [call](#call) Perform a call to a builtin on the chain.
- [getStorage](#getstorage) Retrieves the storage for an address.
## call
Perform a call to a builtin on the chain.
```js
chain_call (address: Address, method: String, data: CallData, block: HeaderHash): OutData
```
Calls a `method` at a specific `address`, passing the encoded `data`. The query is executed at the block specified by `block`.
## getStorage
Retrieves the storage for an address.
```js
chain_getStorage (address: Address, key: H256, block: HeaderHash): StorageData
```
Retrieves the storage `key` at a specific `address`, executing the query at a specific `block`.

View File

@@ -0,0 +1,38 @@
{
"name": "@polkadot/api-jsonrpc",
"version": "0.5.0",
"description": "Method definitions for the Polkadot RPC layer",
"main": "index.js",
"engines": {
"node": ">=6.4"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"
},
"repository": {
"type": "git",
"url": "git+https://github.com/polkadot-js/api.git"
},
"keywords": [
"Polkadot",
"JsonRPC"
],
"author": "Jaco Greeff <jacogr@gmail.com>",
"license": "ISC",
"bugs": {
"url": "https://github.com/polkadot-js/api/issues"
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-jsonrpc#readme",
"scripts": {
"build": "polkadot-dev-build-babel && polkadot-dev-build-docs",
"check": "eslint src && flow check",
"test": "echo \"Tests only available from root wrapper\""
},
"devDependencies": {
"@polkadot/dev": "^0.9.1"
},
"dependencies": {
"babel-runtime": "^6.26.0"
}
}

View File

@@ -0,0 +1,21 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
import type { InterfaceMethodDefinition } from '../types';
/**
@name getHeader
@signature chain_getHeader (hash: HeaderHash): Header
@summary Retrieves the header for a specific block.
@description
Given a block header specified by `hash`, return the full block `Header` information.
*/
module.exports = ({
inputs: [
{
name: 'hash',
type: 'HeaderHash'
}
],
output: { type: 'Header' }
}: InterfaceMethodDefinition);

View File

@@ -0,0 +1,15 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
import type { InterfaceDefinition } from '../types';
const getHeader = require('./getHeader');
/**
@summary Methods to retrieve chain data.
*/
module.exports = ({
methods: {
getHeader
}
}: InterfaceDefinition);

View File

@@ -0,0 +1,15 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
import type { InterfaceDefinition } from './types';
const chain = require('./chain');
const state = require('./state');
/**
@summary Exposes the definition for the RPC endpoints for a Polkadot client node
*/
module.exports = ({
chain,
state
}: { [string]: InterfaceDefinition });

View File

@@ -0,0 +1,10 @@
// ISC, Copyright 2017 Jaco Greeff
const interfaces = require('./index');
describe('jsonrpc', () => {
it('exports the available interfaces', () => {
expect(interfaces).toBeDefined();
expect(Object.keys(interfaces).length).toBeGreaterThan(0);
});
});

View File

@@ -0,0 +1,35 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
import type { InterfaceMethodDefinition } from '../types';
/**
@name call
@signature chain_call (address: Address, method: String, data: CallData, block: HeaderHash): OutData
@summary Perform a call to a builtin on the chain.
@description
Calls a `method` at a specific `address`, passing the encoded `data`. The query is executed at the block specified by `block`.
*/
module.exports = ({
inputs: [
{
name: 'address',
type: 'Address'
},
{
name: 'method',
type: 'String'
},
{
name: 'data',
type: 'CallData'
},
{
name: 'block',
type: 'HeaderHash'
}
],
output: {
type: 'OutData'
}
}: InterfaceMethodDefinition);

View File

@@ -0,0 +1,31 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
import type { InterfaceMethodDefinition } from '../types';
/**
@name getStorage
@signature chain_getStorage (address: Address, key: H256, block: HeaderHash): StorageData
@summary Retrieves the storage for an address.
@description
Retrieves the storage `key` at a specific `address`, executing the query at a specific `block`.
*/
module.exports = ({
inputs: [
{
name: 'address',
type: 'Address'
},
{
name: 'key',
type: 'H256'
},
{
name: 'block',
type: 'HeaderHash'
}
],
output: {
type: 'StorageData'
}
}: InterfaceMethodDefinition);

View File

@@ -0,0 +1,17 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
import type { InterfaceDefinition } from '../types';
const call = require('./call');
const getStorage = require('./getStorage');
/**
@summary Query the state and state storage.
*/
module.exports = ({
methods: {
call,
getStorage
}
}: InterfaceDefinition);

View File

@@ -0,0 +1,27 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
export type FormatInputType = 'Address' | 'CallData' | 'H256' | 'HeaderHash' | 'String';
export type FormatOutputType = 'Header' | 'OutData' | 'StorageData';
export type InterfaceInputType = {
name: string,
type: FormatInputType
};
export type InterfaceOutputType = {
type: FormatOutputType
};
export type InterfaceMethodDefinition = {
deprecated?: boolean,
inputs: Array<InterfaceInputType>,
output: InterfaceOutputType
};
export type InterfaceDefinition = {
methods: {
[string]: InterfaceMethodDefinition
}
};

View File

@@ -0,0 +1,15 @@
ISC License (ISC)
Copyright 2017 Jaco Greeff <jacogr@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

View File

@@ -0,0 +1,25 @@
[![Dependency Status](https://david-dm.org/polkadot-js/api.svg?path=packages/api-provider)](https://david-dm.org/polkadot-js/api?path=packages/api-provider)
[![devDependency Status](https://david-dm.org/polkadot-js/api/dev-status.svg?path=packages/api-provider)](https://david-dm.org/polkadot-js/api?path=packages/api-provider#info=devDependencies)
# @polkadot/api-provider
Generic transport providers to handle the transport of method calls to and from Polkadot clients from applications interacting with it. Generally, unless you are operating at a low-level and taking care of encoding and decoding of parameters/results, it won't be directly used. API interfaces building on top these providers can support various transports with the same underlying interfaces.
## Usage
Installation -
```
npm install --save @polkadot/api-provider
```
Initialisation -
```js
import HttpProvider from '@polkadot/api-provider/http';
const provider = new HttpProvider('http://127.0.0.1:9933');
const version = await provider.send('client_version', []);
console.log('clientVersion', version);
```

View File

@@ -0,0 +1,42 @@
{
"name": "@polkadot/api-provider",
"version": "0.5.0",
"description": "Transport providers for the API",
"main": "index.js",
"keywords": [
"Polkadot",
"JsonRPC"
],
"author": "Jaco Greeff <jacogr@gmail.com>",
"license": "ISC",
"engines": {
"node": ">=6.4"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"
},
"repository": {
"type": "git",
"url": "git+https://github.com/polkadot-js/api.git"
},
"bugs": {
"url": "https://github.com/polkadot-js/api/issues"
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api-provider#readme",
"scripts": {
"build": "polkadot-dev-build-babel",
"check": "eslint src && flow check",
"test": "echo \"Tests only available from root wrapper\""
},
"devDependencies": {
"@polkadot/dev": "^0.9.1",
"mock-socket": "^7.1.0",
"nock": "^9.1.0"
},
"dependencies": {
"@polkadot/util": "^0.5.15",
"babel-runtime": "^6.26.0",
"isomorphic-fetch": "^2.2.1"
}
}

View File

@@ -0,0 +1,39 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
import type { ProviderInterface } from '../types';
require('./polyfill');
const JsonRpcCoder = require('../jsonRpcCoder');
module.exports = class HttpProvider extends JsonRpcCoder implements ProviderInterface {
_endpoint: string;
constructor (endpoint: string) {
super();
this._endpoint = endpoint;
}
async send (method: string, params: Array<any>): Promise<any> {
const body = this.encodeJson(method, params);
const response = await fetch(this._endpoint, {
body,
headers: {
'Accept': 'application/json',
'Content-Length': `${body.length}`,
'Content-Type': 'application/json'
},
method: 'POST'
});
if (!response.ok) {
throw new Error(`[${response.status}]: ${response.statusText}`);
}
const result = await response.json();
return this.decodeResponse(result);
}
};

View File

@@ -0,0 +1,97 @@
// ISC, Copyright 2017 Jaco Greeff
/* global jest */
const { mockHttp, TEST_HTTP_URL } = require('../../test/mockHttp');
const Http = require('./index');
describe('Http', () => {
let http;
let mock;
let encodeSpy;
let decodeSpy;
beforeEach(() => {
http = new Http(TEST_HTTP_URL);
encodeSpy = jest.spyOn(http, 'encodeJson');
decodeSpy = jest.spyOn(http, 'decodeResponse');
});
afterEach(() => {
encodeSpy.mockRestore();
decodeSpy.mockRestore();
mock.done();
});
describe('send', () => {
it('encodes requests', () => {
mock = mockHttp([{
method: 'test_encoding',
reply: {
result: 'ok'
}
}]);
return http
.send('test_encoding', ['param'])
.then((result) => {
expect(encodeSpy).toHaveBeenCalledWith('test_encoding', ['param']);
});
});
it('decodes responses', () => {
mock = mockHttp([{
method: 'test_encoding',
reply: {
result: 'ok'
}
}]);
return http
.send('test_encoding', ['param'])
.then((result) => {
expect(decodeSpy).toHaveBeenCalledWith({
id: 1,
jsonrpc: '2.0',
result: 'ok'
});
});
});
it('passes the body through correctly', () => {
mock = mockHttp([{
method: 'test_body',
reply: {
result: 'ok'
}
}]);
return http
.send('test_body', ['param'])
.then((result) => {
expect(mock.body['test_body']).toEqual({
id: 1,
jsonrpc: '2.0',
method: 'test_body',
params: ['param']
});
});
});
it('throws error when !response.ok', () => {
mock = mockHttp([{
code: 500,
method: 'test_error'
}]);
return http
.send('test_error', [])
.catch((error) => {
expect(error.message).toMatch(/\[500\]: Internal Server/);
});
});
});
});

View File

@@ -0,0 +1,6 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
if (typeof fetch === 'undefined') {
require('isomorphic-fetch');
}

View File

@@ -0,0 +1,24 @@
// ISC, Copyright 2017 Jaco Greeff
describe('http/polyfill', () => {
let origFetch;
beforeEach(() => {
origFetch = global.fetch;
global.fetch = null;
});
afterEach(() => {
global.fetch = origFetch;
});
it('polyfills with no exceptions (without fetch)', () => {
expect(require('./polyfill')).toBeDefined();
});
it('polyfills with no exceptions (with fetch)', () => {
global.fetch = () => true;
expect(require('./polyfill')).toBeDefined();
});
});

View File

@@ -0,0 +1,10 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
const Http = require('./http');
const Ws = require('./ws');
module.exports = {
Http,
Ws
};

View File

@@ -0,0 +1,55 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
import type { JsonRpcRequest, JsonRpcResponse } from './types';
const { isNumber, isUndefined } = require('@polkadot/util/is');
module.exports = class JsonRpcCoder {
_id: number = 0;
decodeResponse (response: JsonRpcResponse): any {
if (!response) {
throw new Error('Empty response object received');
}
if (response.jsonrpc !== '2.0') {
throw new Error('Invalid jsonrpc field in decoded object');
}
if (!isNumber(response.id)) {
throw new Error('Invalid id field in decoded object');
}
if (response.error) {
const { code, message } = response.error;
throw new Error(`[${code}]: ${message}`);
}
if (isUndefined(response.result)) {
throw new Error('No result found in JsonRpc response');
}
return response.result;
}
encodeObject (method: string, params: Array<any>): JsonRpcRequest {
return {
id: ++this._id,
jsonrpc: '2.0',
method,
params
};
}
encodeJson (method: string, params: Array<any>): string {
return JSON.stringify(
this.encodeObject(method, params)
);
}
get id (): number {
return this._id;
}
};

View File

@@ -0,0 +1,77 @@
// ISC, Copyright 2017 Jaco Greeff
const JsonRpcCoder = require('./jsonRpcCoder');
describe('JsonRpcCoder', () => {
let coder;
beforeEach(() => {
coder = new JsonRpcCoder();
});
describe('id', () => {
it('starts with id === 0 (nothing sent)', () => {
expect(coder.id).toEqual(0);
});
});
describe('decodeResponse', () => {
it('expects a non-empty input object', () => {
expect(
() => coder.decodeResponse()
).toThrow(/Empty response/);
});
it('expects a valid jsonrpc field', () => {
expect(
() => coder.decodeResponse({})
).toThrow(/Invalid jsonrpc/);
});
it('expects a valid id field', () => {
expect(
() => coder.decodeResponse({ jsonrpc: '2.0' })
).toThrow(/Invalid id/);
});
it('expects a valid result field', () => {
expect(
() => coder.decodeResponse({ id: 1, jsonrpc: '2.0' })
).toThrow(/No result/);
});
it('throws any error found', () => {
expect(
() => coder.decodeResponse({ id: 1, jsonrpc: '2.0', error: { code: 123, message: 'test error' } })
).toThrow(/\[123\]: test error/);
});
it('returns the result', () => {
expect(
coder.decodeResponse({ id: 1, jsonrpc: '2.0', result: 'some result' })
).toEqual('some result');
});
});
describe('encodeObject', () => {
it('encodes a valid JsonRPC object', () => {
expect(
coder.encodeObject('method', 'params')
).toEqual({
id: 1,
jsonrpc: '2.0',
method: 'method',
params: 'params'
});
expect(coder.id).toEqual(1);
});
});
describe('encodeJson', () => {
it('encodes a valid JsonRPC JSON string', () => {
expect(
coder.encodeJson('method', 'params')
).toEqual('{"id":1,"jsonrpc":"2.0","method":"method","params":"params"}');
});
});
});

View File

@@ -0,0 +1,26 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
export type JsonRpcObject = {
id: number;
jsonrpc: '2.0';
};
export type JsonRpcRequest = JsonRpcObject & {
method: string;
params: Array<any>;
};
export type JsonRpcResponseBase = {
error?: {
code: number,
message: string
};
result?: any;
}
export type JsonRpcResponse = JsonRpcObject & JsonRpcResponseBase;
export interface ProviderInterface {
send (method: string, params: Array<any>): Promise<any>;
}

View File

@@ -0,0 +1,101 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
import type { JsonRpcResponse, ProviderInterface } from '../types';
type AwaitingType = {
callback: (error: ?Error, result: any) => void
};
type WsMessageType = {
data: any
};
const JsonRpcCoder = require('../jsonRpcCoder');
module.exports = class WsProvider extends JsonRpcCoder implements ProviderInterface {
_autoConnect: boolean = true;
_endpoint: string;
_handlers: { [number]: AwaitingType } = {};
_websocket: WebSocket;
constructor (endpoint: string, autoConnect: boolean = true) {
super();
this._endpoint = endpoint;
this._autoConnect = autoConnect;
if (autoConnect) {
this.connect();
}
}
connect = () => {
this._handlers = {};
this._websocket = new WebSocket(this._endpoint);
this._websocket.onclose = this._onClose;
this._websocket.onerror = this._onError;
this._websocket.onmessage = this._onMessage;
this._websocket.onopen = this._onOpen;
}
_onClose = () => {
// console.log('disconnected from', this._endpoint);
if (this._autoConnect) {
setTimeout(this.connect, 1000);
}
}
_onError = (error: Event) => {
console.error(error);
}
_onOpen = () => {
// console.log('connected to', this._endpoint);
}
_onMessage = (message: WsMessageType) => {
const response: JsonRpcResponse = JSON.parse(message.data);
const handler = this._handlers[response.id];
if (!handler) {
console.error(`Unable to find handler for id=${response.id}`);
return;
}
try {
const result = this.decodeResponse(response);
handler.callback(null, result);
} catch (error) {
handler.callback(error);
}
delete this._handlers[response.id];
}
send (method: string, params: Array<any>): Promise<any> {
return new Promise((resolve, reject) => {
try {
this._websocket.send(
this.encodeObject(method, params)
);
this._handlers[this.id] = {
callback: (error: ?Error, result: any) => {
if (error) {
reject(error);
} else {
resolve(result);
}
}
};
} catch (error) {
reject(error);
}
});
}
};

View File

@@ -0,0 +1,195 @@
// ISC, Copyright 2017 Jaco Greeff
/* global jest */
const { mockWs, TEST_WS_URL } = require('../../test/mockWs');
const { isUndefined } = require('@polkadot/util/is');
const Ws = require('./index');
let ws;
let mock;
let encodeSpy;
let decodeSpy;
function createWs (requests, autoConnect) {
mock = autoConnect || isUndefined(autoConnect)
? mockWs(requests)
: null;
ws = new Ws(TEST_WS_URL, autoConnect);
encodeSpy = jest.spyOn(ws, 'encodeObject');
decodeSpy = jest.spyOn(ws, 'decodeResponse');
return ws;
}
describe('Ws', () => {
afterEach(() => {
encodeSpy.mockRestore();
decodeSpy.mockRestore();
if (mock) {
mock.done();
}
});
describe('websocket', () => {
let errorSpy;
beforeEach(() => {
ws = createWs([]);
errorSpy = jest.spyOn(console, 'error');
});
afterEach(() => {
errorSpy.mockRestore();
});
it('sets up the on* handlers', () => {
expect(ws._websocket.onclose[0]).toEqual(ws._onClose);
expect(ws._websocket.onerror[0]).toEqual(ws._onError);
expect(ws._websocket.onmessage[0]).toEqual(ws._onMessage);
expect(ws._websocket.onopen[0]).toEqual(ws._onOpen);
});
describe('_onClose', () => {
beforeEach(() => {
jest.useFakeTimers();
});
afterEach(() => {
jest.useRealTimers();
});
it('reconnects after delay', () => {
ws.connect = jest.fn();
ws._onClose();
expect(ws.connect).not.toHaveBeenCalled();
jest.runAllTimers();
expect(ws.connect).toHaveBeenCalled();
});
it('does not reconnect when autoConnect false', () => {
mock.done();
ws = createWs([], false);
ws.connect = jest.fn();
ws._onClose();
expect(ws.connect).not.toHaveBeenCalled();
jest.runAllTimers();
expect(ws.connect).not.toHaveBeenCalled();
});
});
describe('_onError', () => {
it('logs the error', () => {
ws._onError('test error');
expect(errorSpy).toHaveBeenCalledWith('test error');
});
});
describe('_onMessage', () => {
it('fails with log when handler not found', () => {
ws._onMessage({ data: '{"id":2}' });
expect(errorSpy).toHaveBeenCalledWith('Unable to find handler for id=2');
});
});
});
describe('send', () => {
it('handles internal errors', () => {
ws = createWs([], false);
return ws
.send('test_encoding', ['param'])
.catch((error) => {
expect(error).toBeDefined();
});
});
it('encodes requests', () => {
ws = createWs([{
id: 1,
method: 'test_encoding',
reply: {
result: 'ok'
}
}]);
return ws
.send('test_encoding', ['param'])
.then((result) => {
expect(encodeSpy).toHaveBeenCalledWith('test_encoding', ['param']);
});
});
it('decodes responses', () => {
ws = createWs([{
id: 1,
method: 'test_encoding',
reply: {
result: 'ok'
}
}]);
return ws
.send('test_encoding', ['param'])
.then((result) => {
expect(decodeSpy).toHaveBeenCalledWith({
id: 1,
jsonrpc: '2.0',
result: 'ok'
});
});
});
it('passes the body through correctly', () => {
ws = createWs([{
id: 1,
method: 'test_body',
reply: {
result: 'ok'
}
}]);
return ws
.send('test_body', ['param'])
.then((result) => {
expect(mock.body['test_body']).toEqual({
id: 1,
jsonrpc: '2.0',
method: 'test_body',
params: ['param']
});
});
});
it('throws error when !response.ok', () => {
ws = createWs([{
id: 1,
error: {
code: 666,
message: 'error'
}
}]);
return ws
.send('test_error', [])
.catch((error) => {
expect(error.message).toMatch(/\[666\]: error/);
});
});
});
});

View File

@@ -0,0 +1,25 @@
// ISC, Copyright 2017 Jaco Greeff
const nock = require('nock');
const TEST_HTTP_URL = 'http://localhost:9944';
function mockHttp (requests) {
nock.cleanAll();
return requests.reduce((scope, request, index) => {
return scope
.post('/')
.reply(request.code || 200, (uri, body) => {
scope.body = scope.body || {};
scope.body[request.method] = body;
return Object.assign({ id: body.id, jsonrpc: '2.0' }, request.reply || {});
});
}, nock(TEST_HTTP_URL));
}
module.exports = {
TEST_HTTP_URL,
mockHttp
};

View File

@@ -0,0 +1,50 @@
// ISC, Copyright 2017 Jaco Greeff
const { Server } = require('mock-socket');
const TEST_WS_URL = 'ws://localhost:9955';
let server;
function mockWs (requests) {
server = new Server(TEST_WS_URL);
let requestCount = 0;
server.on('message', (body) => {
const request = requests[requestCount];
const result = request.reply;
const response = request.error
? {
id: request.id,
jsonrpc: '2.0',
error: {
code: request.error.code,
message: request.error.message
}
}
: {
id: request.id,
jsonrpc: '2.0',
result: result.result
};
scope.body[request.method] = body;
requestCount++;
server.send(JSON.stringify(response));
});
const scope = {
body: {},
requests: 0,
server,
done: () => server.stop()
};
return scope;
}
module.exports = {
TEST_WS_URL,
mockWs
};

15
packages/api/LICENSE Normal file
View File

@@ -0,0 +1,15 @@
ISC License (ISC)
Copyright 2017 Jaco Greeff <jacogr@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

37
packages/api/README.md Normal file
View File

@@ -0,0 +1,37 @@
[![Dependency Status](https://david-dm.org/polkadot-js/api.svg?path=packages/api)](https://david-dm.org/polkadot-js/api?path=packages/api)
[![devDependency Status](https://david-dm.org/polkadot-js/api/dev-status.svg?path=packages/api)](https://david-dm.org/polkadot-js/api?path=packages/api#info=devDependencies)
# @polkadot/api
Warning - currently this does not actually do all that much, it is an attempt to put into code some thoughts about how to maintain the endpoints. This library provides a clean wrapper around all the methods exposed by a Polkadot network client. Methods are auto-generated for the [JsonRPC interface definitions](https://github.com/polkadot-js/api/packages/api-jsonrpc).
## Usage
Installation -
```
npm install --save @polkadot/api
```
Initialisation -
```js
import Api from '@polkadot/api';
import HttpProvider from '@polkadot/api-provider/http';
const provider = new HttpProvider('http://127.0.0.1:9933');
const api = new Api(provider);
```
Making calls -
```js
api.chain
.getHeader('0x1234567890')
.then((header) => console.log(header))
.catch((error) => console.error(error));
```
## Available methods
For a list of currently exposed methods, see the [@polkadot/api-jsonrpc](https://github.com/polkadot-js/api/packages/api-jsonrpc#readme) repository.

42
packages/api/package.json Normal file
View File

@@ -0,0 +1,42 @@
{
"name": "@polkadot/api",
"version": "0.5.0",
"description": "A JavaScript wrapper for the Polkadot JsonRPC interface",
"main": "index.js",
"keywords": [
"Polkadot",
"JsonRPC"
],
"author": "Jaco Greeff <jacogr@gmail.com>",
"license": "ISC",
"engines": {
"node": ">=6.4"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"
},
"repository": {
"type": "git",
"url": "git+https://github.com/polkadot-js/api.git"
},
"bugs": {
"url": "https://github.com/polkadot-js/api/issues"
},
"homepage": "https://github.com/polkadot-js/api/tree/master/packages/api#readme",
"scripts": {
"build": "polkadot-dev-build-babel",
"check": "eslint src && flow check",
"test": "echo \"Tests only available from root wrapper\""
},
"devDependencies": {
"@polkadot/dev": "^0.9.1"
},
"dependencies": {
"@polkadot/api-format": "^0.5.0",
"@polkadot/api-jsonrpc": "^0.5.0",
"@polkadot/api-provider": "^0.5.0",
"@polkadot/util": "^0.5.15",
"babel-runtime": "^6.26.0"
}
}

View File

@@ -2,11 +2,11 @@
// @flow
import type { ProviderInterface } from '@polkadot/api-provider/types';
import type { InterfaceDefinition } from '@polkadot/jsonrpc/types';
import type { InterfaceDefinition } from '@polkadot/api-jsonrpc/types';
import type { ApiInterface } from './types';
const { formatInputs, formatOutput } = require('@polkadot/api-format');
const interfaces = require('@polkadot/jsonrpc');
const interfaces = require('@polkadot/api-jsonrpc');
const isFunction = require('@polkadot/util/is/function');
const jsonrpcSignature = require('@polkadot/util/jsonrpc/signature');

760
yarn.lock

File diff suppressed because it is too large Load Diff