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:
@@ -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());
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
);
|
||||
|
||||
@@ -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}`);
|
||||
}
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user