Split interface creation (#50)
* Split interface creation * Lint fixes * Update @polkadot dependencies
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/api-format",
|
||||
"version": "0.6.12",
|
||||
"version": "0.7.0",
|
||||
"description": "Input/Output formatters for JsonRPC exchange",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
@@ -30,11 +30,11 @@
|
||||
"test": "echo \"Tests only available from root wrapper\""
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/api-jsonrpc": "^0.6.12"
|
||||
"@polkadot/api-jsonrpc": "^0.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polkadot/primitives-json": "^0.4.6",
|
||||
"@polkadot/util": "^0.11.1",
|
||||
"@polkadot/primitives-json": "^0.4.10",
|
||||
"@polkadot/util": "^0.13.1",
|
||||
"babel-runtime": "^6.26.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/api-jsonrpc",
|
||||
"version": "0.6.12",
|
||||
"version": "0.7.0",
|
||||
"description": "Method definitions for the Polkadot RPC layer",
|
||||
"main": "index.js",
|
||||
"engines": {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { InterfaceDefinition } from './types';
|
||||
import type { InterfaceDefinitions } from './types';
|
||||
|
||||
const chain = require('./chain');
|
||||
const state = require('./state');
|
||||
@@ -14,4 +14,4 @@ const state = require('./state');
|
||||
module.exports = ({
|
||||
chain,
|
||||
state
|
||||
}: { [string]: InterfaceDefinition });
|
||||
}: InterfaceDefinitions);
|
||||
|
||||
@@ -22,8 +22,14 @@ export type InterfaceMethodDefinition = {
|
||||
output: InterfaceOutputType
|
||||
};
|
||||
|
||||
export type InterfaceTypes = 'chain' | 'state';
|
||||
|
||||
export type InterfaceDefinition = {
|
||||
methods: {
|
||||
[string]: InterfaceMethodDefinition
|
||||
}
|
||||
};
|
||||
|
||||
export type InterfaceDefinitions = {
|
||||
[InterfaceTypes]: InterfaceDefinition
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/api-provider",
|
||||
"version": "0.6.12",
|
||||
"version": "0.7.0",
|
||||
"description": "Transport providers for the API",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
@@ -34,7 +34,7 @@
|
||||
"nock": "^9.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polkadot/util": "^0.11.1",
|
||||
"@polkadot/util": "^0.13.1",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
"websocket": "^1.0.25"
|
||||
|
||||
@@ -24,6 +24,7 @@ module.exports = class JsonRpcCoder {
|
||||
|
||||
throw new Error(`[${code}]: ${message}`);
|
||||
}
|
||||
|
||||
assert(!isUndefined(response.result), 'No result found in JsonRpc response');
|
||||
|
||||
return response.result;
|
||||
|
||||
@@ -207,28 +207,16 @@ describe('Ws', () => {
|
||||
});
|
||||
|
||||
describe('queued', () => {
|
||||
let sendPromise;
|
||||
|
||||
beforeEach(() => {
|
||||
ws = createWs([{
|
||||
it('sends messages when connected', () => {
|
||||
const ws = createWs([{
|
||||
id: 1,
|
||||
method: 'test_queue',
|
||||
reply: {
|
||||
result: 'ok'
|
||||
}
|
||||
}], false);
|
||||
sendPromise = ws.send('test_queue', []);
|
||||
});
|
||||
const sendPromise = ws.send('test_queue', []);
|
||||
|
||||
it('sends messages when connected', () => {
|
||||
ws.connect();
|
||||
|
||||
return sendPromise.then((result) => {
|
||||
expect(result).toEqual('ok');
|
||||
});
|
||||
});
|
||||
|
||||
it('sends messages when connected (errors)', () => {
|
||||
ws.connect();
|
||||
|
||||
return sendPromise.then((result) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@polkadot/api",
|
||||
"version": "0.6.12",
|
||||
"version": "0.7.0",
|
||||
"description": "A JavaScript wrapper for the Polkadot JsonRPC interface",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
@@ -30,10 +30,10 @@
|
||||
"test": "echo \"Tests only available from root wrapper\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@polkadot/api-format": "^0.6.12",
|
||||
"@polkadot/api-jsonrpc": "^0.6.12",
|
||||
"@polkadot/api-provider": "^0.6.12",
|
||||
"@polkadot/util": "^0.11.1",
|
||||
"@polkadot/api-format": "^0.7.0",
|
||||
"@polkadot/api-jsonrpc": "^0.7.0",
|
||||
"@polkadot/api-provider": "^0.7.0",
|
||||
"@polkadot/util": "^0.13.1",
|
||||
"babel-runtime": "^6.26.0"
|
||||
}
|
||||
}
|
||||
|
||||
+6
-47
@@ -4,63 +4,22 @@
|
||||
// @flow
|
||||
|
||||
import type { ProviderInterface } from '@polkadot/api-provider/types';
|
||||
import type { InterfaceDefinition } from '@polkadot/api-jsonrpc/types';
|
||||
import type { ApiInterface, ApiInterface$Section } from './types';
|
||||
|
||||
const { formatInputs, formatOutput } = require('@polkadot/api-format');
|
||||
const interfaces = require('@polkadot/api-jsonrpc');
|
||||
const assert = require('@polkadot/util/assert');
|
||||
const ExtError = require('@polkadot/util/ext/error');
|
||||
const isFunction = require('@polkadot/util/is/function');
|
||||
const jsonrpcSignature = require('@polkadot/util/jsonrpc/signature');
|
||||
|
||||
const createInterface = require('./create/interface');
|
||||
|
||||
module.exports = class Api implements ApiInterface {
|
||||
_provider: ProviderInterface;
|
||||
_chainInterface: ApiInterface$Section;
|
||||
_stateInterface: ApiInterface$Section;
|
||||
chain: ApiInterface$Section;
|
||||
state: ApiInterface$Section;
|
||||
|
||||
constructor (provider: ProviderInterface) {
|
||||
assert(provider && isFunction(provider.send), 'Expected Provider');
|
||||
|
||||
this._provider = provider;
|
||||
|
||||
this._chainInterface = this._createInterface(interfaces, 'chain');
|
||||
this._stateInterface = this._createInterface(interfaces, 'state');
|
||||
}
|
||||
|
||||
// flowlint-next-line unsafe-getters-setters:off
|
||||
get chain (): ApiInterface$Section {
|
||||
return this._chainInterface;
|
||||
}
|
||||
|
||||
// flowlint-next-line unsafe-getters-setters:off
|
||||
get state (): ApiInterface$Section {
|
||||
return this._stateInterface;
|
||||
}
|
||||
|
||||
_createInterface (definitions: { [string]: InterfaceDefinition }, section: string): ApiInterface$Section {
|
||||
const definition = definitions[section];
|
||||
|
||||
return Object
|
||||
.keys(definition.methods)
|
||||
.reduce((container, method: string) => {
|
||||
const { inputs, output } = definition.methods[method];
|
||||
const rpcName = `${section}_${method}`;
|
||||
|
||||
container[method] = async (..._params: Array<mixed>): Promise<mixed> => {
|
||||
try {
|
||||
assert(inputs.length === _params.length, `${inputs.length} params expected, found ${_params.length} instead`);
|
||||
|
||||
const params = formatInputs(inputs, _params);
|
||||
const result = await this._provider.send(rpcName, params);
|
||||
|
||||
return formatOutput(output, result);
|
||||
} catch (error) {
|
||||
throw new ExtError(`${jsonrpcSignature(rpcName, inputs, output)}:: ${error.message}`, (error: ExtError).code);
|
||||
}
|
||||
};
|
||||
|
||||
return container;
|
||||
}, {});
|
||||
this.chain = createInterface(provider, interfaces.chain, 'chain');
|
||||
this.state = createInterface(provider, interfaces.state, 'state');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
const isFunction = require('@polkadot/util/is/function');
|
||||
|
||||
const Api = require('./api');
|
||||
|
||||
describe('Api', () => {
|
||||
@@ -25,81 +23,17 @@ describe('Api', () => {
|
||||
sendSpy.mockRestore();
|
||||
});
|
||||
|
||||
describe('constructor', () => {
|
||||
it('requires a provider with a send method', () => {
|
||||
expect(
|
||||
() => new Api({})
|
||||
).toThrow(/Expected Provider/);
|
||||
});
|
||||
|
||||
it('sets up the chain interface', () => {
|
||||
expect(api.chain).toBeDefined();
|
||||
});
|
||||
|
||||
it('sets up the state interface', () => {
|
||||
expect(api.state).toBeDefined();
|
||||
});
|
||||
it('requires a provider with a send method', () => {
|
||||
expect(
|
||||
() => new Api({})
|
||||
).toThrow(/Expected Provider/);
|
||||
});
|
||||
|
||||
describe('_createInterface', () => {
|
||||
let container;
|
||||
it('sets up the chain interface', () => {
|
||||
expect(api.chain).toBeDefined();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
container = api._createInterface({
|
||||
test: {
|
||||
methods: {
|
||||
blah: {
|
||||
inputs: [
|
||||
{ name: 'foo', type: 'Address' }
|
||||
],
|
||||
output: { type: 'Address' }
|
||||
},
|
||||
bleh: {
|
||||
inputs: [],
|
||||
output: { type: 'Address' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 'test');
|
||||
});
|
||||
|
||||
describe('method expansion', () => {
|
||||
it('adds the specified methods to the interface', () => {
|
||||
expect(Object.keys(container)).toEqual(['blah', 'bleh']);
|
||||
});
|
||||
|
||||
it('had function calls for the attached methods', () => {
|
||||
expect(isFunction(container.blah)).toEqual(true);
|
||||
expect(isFunction(container.bleh)).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('calling', () => {
|
||||
it('wraps errors with the call signature', () => {
|
||||
return container
|
||||
.blah()
|
||||
.catch((error) => {
|
||||
expect(error.message).toMatch(/test_blah \(foo: Address\): Address/);
|
||||
});
|
||||
});
|
||||
|
||||
it('checks for mismatched parameters', () => {
|
||||
return container
|
||||
.bleh(1)
|
||||
.catch((error) => {
|
||||
expect(error.message).toMatch(/0 params expected, found 1 instead/);
|
||||
});
|
||||
});
|
||||
|
||||
it('calls the provider with the correct parameters', () => {
|
||||
return container
|
||||
.blah('0x123')
|
||||
.then(() => {
|
||||
expect(provider.send).toHaveBeenCalledWith('test_blah', [
|
||||
'0x0123'
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
it('sets up the state interface', () => {
|
||||
expect(api.state).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
// @flow
|
||||
|
||||
import type { InterfaceDefinition } from '@polkadot/api-jsonrpc/types';
|
||||
import type { ProviderInterface } from '@polkadot/api-provider/types';
|
||||
import type { ApiInterface$Section } from '../types';
|
||||
|
||||
const { formatInputs, formatOutput } = require('@polkadot/api-format');
|
||||
const assert = require('@polkadot/util/assert');
|
||||
const ExtError = require('@polkadot/util/ext/error');
|
||||
const jsonrpcSignature = require('@polkadot/util/jsonrpc/signature');
|
||||
|
||||
module.exports = function createInterface (provider: ProviderInterface, definition: InterfaceDefinition, section: string): ApiInterface$Section {
|
||||
return Object
|
||||
.keys(definition.methods)
|
||||
.reduce((container, method: string) => {
|
||||
const { inputs, output } = definition.methods[method];
|
||||
const rpcName = `${section}_${method}`;
|
||||
|
||||
container[method] = async (..._params: Array<mixed>): Promise<mixed> => {
|
||||
try {
|
||||
assert(inputs.length === _params.length, `${inputs.length} params expected, found ${_params.length} instead`);
|
||||
|
||||
const params = formatInputs(inputs, _params);
|
||||
const result = await provider.send(rpcName, params);
|
||||
|
||||
return formatOutput(output, result);
|
||||
} catch (error) {
|
||||
throw new ExtError(`${jsonrpcSignature(rpcName, inputs, output)}:: ${error.message}`, (error: ExtError).code);
|
||||
}
|
||||
};
|
||||
|
||||
return container;
|
||||
}, ({}: $Shape<ApiInterface$Section>));
|
||||
};
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright 2017-2018 Jaco Greeff
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the ISC license. See the LICENSE file for details.
|
||||
|
||||
const isFunction = require('@polkadot/util/is/function');
|
||||
|
||||
const createInterface = require('./interface');
|
||||
|
||||
describe('createInterface', () => {
|
||||
let container;
|
||||
let provider;
|
||||
|
||||
beforeEach(() => {
|
||||
const definition = {
|
||||
methods: {
|
||||
blah: {
|
||||
inputs: [
|
||||
{ name: 'foo', type: 'Address' }
|
||||
],
|
||||
output: { type: 'Address' }
|
||||
},
|
||||
bleh: {
|
||||
inputs: [],
|
||||
output: { type: 'Address' }
|
||||
}
|
||||
}
|
||||
};
|
||||
provider = {
|
||||
send: jest.fn((method, params) => {
|
||||
return Promise.resolve(params[0]);
|
||||
})
|
||||
};
|
||||
container = createInterface(provider, definition, 'test');
|
||||
});
|
||||
|
||||
describe('method expansion', () => {
|
||||
it('adds the specified methods to the interface', () => {
|
||||
expect(Object.keys(container)).toEqual(['blah', 'bleh']);
|
||||
});
|
||||
|
||||
it('had function calls for the attached methods', () => {
|
||||
expect(isFunction(container.blah)).toEqual(true);
|
||||
expect(isFunction(container.bleh)).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('calling', () => {
|
||||
it('wraps errors with the call signature', () => {
|
||||
return container
|
||||
.blah()
|
||||
.catch((error) => {
|
||||
expect(error.message).toMatch(/test_blah \(foo: Address\): Address/);
|
||||
});
|
||||
});
|
||||
|
||||
it('checks for mismatched parameters', () => {
|
||||
return container
|
||||
.bleh(1)
|
||||
.catch((error) => {
|
||||
expect(error.message).toMatch(/0 params expected, found 1 instead/);
|
||||
});
|
||||
});
|
||||
|
||||
it('calls the provider with the correct parameters', () => {
|
||||
return container
|
||||
.blah('0x123')
|
||||
.then(() => {
|
||||
expect(provider.send).toHaveBeenCalledWith('test_blah', [
|
||||
'0x0123'
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user