Cleanup decode errors (#1567)

* Cleanup decode errors

* Expand RPC error message

* Extract RPC createSignature method

* Flatten formatError

* Formatting

* Update test string match
This commit is contained in:
Jaco Greeff
2019-11-13 22:18:07 +01:00
committed by GitHub
parent f86aebf7e1
commit 921e329d18
4 changed files with 20 additions and 38 deletions
+13 -29
View File
@@ -33,6 +33,15 @@ const EMPTY_META = {
}
};
// utility method to create a nicely-formatted error
function createErrorMessage ({ method, params, type }: RpcMethod, error: Error): string {
const inputs = params.map(({ isOptional, name, type }): string =>
`${name}${isOptional ? '?' : ''}: ${type}`
).join(', ');
return `${method}(${inputs}): ${type}:: ${error.message}`;
}
/**
* @name Rpc
* @summary The API may use a HTTP or WebSockets provider.
@@ -97,27 +106,6 @@ export default class Rpc implements RpcInterface {
this.createInterfaces(jsonrpc, userRpc);
}
/**
* @name signature
* @summary Returns a string representation of the method with inputs and outputs.
* @description
* Formats the name, inputs and outputs into a human-readable string. This contains the input parameter names input types and output type.
*
* @example
* <BR>
*
* ```javascript
* import Api from '@polkadot/rpc-core';
*
* Api.signature({ name: 'test_method', params: [ { name: 'dest', type: 'Address' } ], type: 'Address' }); // => test_method (dest: Address): Address
* ```
*/
public static signature ({ method, params, type }: RpcMethod): string {
const inputs = params.map(({ name, type }): string => `${name}: ${type}`).join(', ');
return `${method} (${inputs}): ${type}`;
}
/**
* @description Manually disconnect from the attached provider
*/
@@ -125,10 +113,6 @@ export default class Rpc implements RpcInterface {
this.provider.disconnect();
}
private createErrorMessage (method: RpcMethod, error: Error): string {
return `${Rpc.signature(method)}:: ${error.message}`;
}
private createInterfaces<Section extends keyof RpcInterface> (interfaces: Record<string, RpcSection>, userBare: UserRpc): void {
// these are the base keys (i.e. part of jsonrpc)
this.sections.push(...Object.keys(interfaces));
@@ -207,7 +191,7 @@ export default class Rpc implements RpcInterface {
),
map(([params, result]): any => this.formatOutput(method, params, result)),
catchError((error): any => {
const message = this.createErrorMessage(method, error);
const message = createErrorMessage(method, error);
// don't scare with old nodes, this is handled transparently
rpcName !== 'rpc_methods' && l.error(message);
@@ -249,7 +233,7 @@ export default class Rpc implements RpcInterface {
// Have at least an empty promise, as used in the unsubscribe
let subscriptionPromise: Promise<number | void> = Promise.resolve();
const errorHandler = (error: Error): void => {
const message = this.createErrorMessage(method, error);
const message = createErrorMessage(method, error);
l.error(message);
@@ -261,7 +245,7 @@ export default class Rpc implements RpcInterface {
const paramsJson = params.map((param): AnyJson => param.toJSON());
const update = (error?: Error, result?: any): void => {
if (error) {
l.error(this.createErrorMessage(method, error));
l.error(createErrorMessage(method, error));
return;
}
@@ -294,7 +278,7 @@ export default class Rpc implements RpcInterface {
? this.provider.unsubscribe(subType, unsubName, subscriptionId)
: Promise.resolve(false)
)
.catch((error: Error): void => l.error(this.createErrorMessage(method, error)));
.catch((error: Error): void => l.error(createErrorMessage(method, error)));
};
}).pipe(drr());
};
+1 -1
View File
@@ -43,7 +43,7 @@ describe('methodSend', (): void => {
method().subscribe(
(): void => {},
(error: Error): void => {
expect(error.message).toMatch(/blah \(foo: Bytes\): Bytes/);
expect(error.message).toMatch(/blah\(foo: Bytes\): Bytes/);
done();
}
);
+4 -1
View File
@@ -52,9 +52,12 @@ export default class RpcCoder {
private checkError (error?: JsonRpcResponseBaseError): void {
if (error) {
const { code, data, message } = error;
// We need some sort of cut-off here since these can be very large and
// very nested, pick a number and trim the result display to it
const _data = isUndefined(data)
? ''
: `: ${isString(data) ? data : JSON.stringify(data)}`.substr(0, 22);
: `: ${isString(data) ? data : JSON.stringify(data)}`.substr(0, 35);
throw new Error(`${code}: ${message}${_data}`);
}
+2 -7
View File
@@ -21,12 +21,7 @@ export default function decodeU8a (u8a: Uint8Array, _types: Constructor[] | { [i
}
const Type = types[0];
const value = new Type(u8a);
try {
const value = new Type(u8a);
return [value].concat(decodeU8a(u8a.subarray(value.encodedLength), types.slice(1)));
} catch (error) {
throw new Error(`U8a: failed on '${Type.name}':: ${error.message}`);
}
return [value].concat(decodeU8a(u8a.subarray(value.encodedLength), types.slice(1)));
}