Skip to content

Commit

Permalink
add inner error to errors on send 6300 (#6350)
Browse files Browse the repository at this point in the history
* add inner error to errors on send

* update snapshot

* test coverage

* update changelog
  • Loading branch information
Alex authored Aug 15, 2023
1 parent a4cae6f commit 622174c
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 4 deletions.
4 changes: 4 additions & 0 deletions packages/web3-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,7 @@ Documentation:
- Added minimum support of web3.extend function

## [Unreleased]

### Fixed

- Fixed rpc errors not being sent as an inner error when using the `send` method on request manager (#6300).
1 change: 0 additions & 1 deletion packages/web3-core/src/web3_request_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ export class Web3RequestManager<
ResponseType = Web3APIReturnType<API, Method>,
>(request: Web3APIRequest<API, Method>): Promise<ResponseType> {
const response = await this._sendRequest<Method, ResponseType>(request);

if (jsonRpc.isResponseWithResult(response)) {
return response.result;
}
Expand Down
30 changes: 30 additions & 0 deletions packages/web3-core/test/unit/web3_request_manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
VersionNotSupportedError,
RpcError,
ResourceUnavailableError,
ResponseError,
} from 'web3-errors';
import HttpProvider from 'web3-providers-http';
import WSProvider from 'web3-providers-ws';
Expand Down Expand Up @@ -598,6 +599,35 @@ describe('Web3RequestManager', () => {
expect(myProvider.request).toHaveBeenCalledTimes(1);
expect(myProvider.request).toHaveBeenCalledWith(payload, expect.any(Function));
});
it('should reject and include inner error when send method errors with an error property', async () => {
const rpcErrorResponse = {
id: 1,
jsonrpc: '2.0' as JsonRpcIdentifier,
error: {
code: 4001,
message: 'MetaMask Tx Signature: User denied transaction signature.',
},
};
const manager = new Web3RequestManager(undefined, true);
const myProvider = {
request: jest.fn().mockImplementation(async () => {
return Promise.resolve(successResponse.result);
}),
} as any;

jest.spyOn(manager, 'provider', 'get').mockReturnValue(myProvider);
// use any as a way to test private method '_sendRequest'
jest.spyOn(manager as any, '_sendRequest').mockReturnValue(rpcErrorResponse);
let err;
try {
await manager.send(request);
} catch (error: any) {
err = error;
} finally {
expect(err).toBeInstanceOf(ResponseError);
expect(err.innerError).toEqual(rpcErrorResponse.error);
}
});
});

describe('web3-provider', () => {
Expand Down
9 changes: 8 additions & 1 deletion packages/web3-errors/src/errors/response_errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ export class ResponseError<ErrorType = unknown, RequestType = unknown> extends B
}

this.request = request;
let errorOrErrors: JsonRpcError | JsonRpcError[] | undefined;
if (`error` in response) {
errorOrErrors = response.error as JsonRpcError;
} else if (response instanceof Array) {
errorOrErrors = response.map(r => r.error) as JsonRpcError[];
}

this.innerError = errorOrErrors as Error | Error[] | undefined;
}

public toJSON() {
Expand All @@ -84,7 +92,6 @@ export class InvalidResponseError<ErrorType = unknown, RequestType = unknown> ex
) {
super(result, undefined, request);
this.code = ERR_INVALID_RESPONSE;

let errorOrErrors: JsonRpcError | JsonRpcError[] | undefined;
if (`error` in result) {
errorOrErrors = result.error as JsonRpcError;
Expand Down
52 changes: 50 additions & 2 deletions packages/web3-errors/test/unit/__snapshots__/errors.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,14 @@ Object {
"a": "10",
"b": "20",
},
"innerError": undefined,
"innerError": Object {
"code": 123,
"data": Object {
"a": "10",
"b": "20",
},
"message": "error message",
},
"message": "Returned error: error message",
"name": "ResponseError",
"request": undefined,
Expand All @@ -267,13 +274,54 @@ exports[`errors ResponseError should have valid json structure without data 1`]
Object {
"code": 100,
"data": undefined,
"innerError": undefined,
"innerError": Object {
"code": 123,
"data": undefined,
"message": "error message",
},
"message": "Returned error: error message",
"name": "ResponseError",
"request": undefined,
}
`;

exports[`errors ResponseError should include the array of inner errors 1`] = `
Object {
"code": 100,
"data": Array [
Object {
"a": "10",
"b": "20",
},
Object {
"c": "30",
"d": "40",
},
],
"innerError": Array [
Object {
"code": 123,
"data": Object {
"a": "10",
"b": "20",
},
"message": "error message",
},
Object {
"code": 124,
"data": Object {
"c": "30",
"d": "40",
},
"message": "error message",
},
],
"message": "Returned error: error message,error message",
"name": "ResponseError",
"request": undefined,
}
`;

exports[`errors RevertInstructionError should have valid json structure 1`] = `
Object {
"code": 401,
Expand Down
17 changes: 17 additions & 0 deletions packages/web3-errors/test/unit/errors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,23 @@ describe('errors', () => {
}).toJSON(),
).toMatchSnapshot();
});

it('should include the array of inner errors', () => {
expect(
new responseErrors.ResponseError([
{
id: 1,
jsonrpc: '2.0',
error: { code: 123, message: 'error message', data: { a: '10', b: '20' } },
},
{
id: 2,
jsonrpc: '2.0',
error: { code: 124, message: 'error message', data: { c: '30', d: '40' } },
},
]).toJSON(),
).toMatchSnapshot();
});
});

describe('InvalidResponseError', () => {
Expand Down

0 comments on commit 622174c

Please sign in to comment.