Skip to content

Commit f8d1066

Browse files
committed
refactor: Rewrite retryOnEmpty
1 parent 172f1e5 commit f8d1066

File tree

3 files changed

+32
-57
lines changed

3 files changed

+32
-57
lines changed

packages/eth-json-rpc-middleware/src/retryOnEmpty.test.ts

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
import { errorCodes, providerErrors, rpcErrors } from '@metamask/rpc-errors';
1+
import { providerErrors, rpcErrors } from '@metamask/rpc-errors';
22
import type { Json, JsonRpcParams, JsonRpcRequest } from '@metamask/utils';
33

44
import { createRetryOnEmptyMiddleware } from '.';
55
import type { ProviderRequestStub } from '../test/util/helpers';
66
import {
77
createMockParamsWithBlockParamAt,
88
createMockParamsWithoutBlockParamAt,
9-
createSimpleFinalMiddleware,
109
createStubForBlockNumberRequest,
1110
expectProviderRequestNotToHaveBeenMade,
1211
requestMatches,
1312
stubProviderRequests,
1413
createProviderAndBlockTracker,
1514
createEngine,
1615
createRequest,
16+
createFinalMiddlewareWithDefaultResult,
1717
} from '../test/util/helpers';
1818

1919
const originalSetTimeout = globalThis.setTimeout;
@@ -100,18 +100,14 @@ describe('createRetryOnEmptyMiddleware', () => {
100100
}),
101101
]);
102102

103-
const responsePromise = engine.handle(request);
103+
const resultPromise = engine.handle(request);
104104
await waitForRequestToBeRetried({
105105
requestSpy,
106106
request,
107107
numberOfTimes: 10,
108108
});
109109

110-
expect(await responsePromise).toStrictEqual({
111-
id: 1,
112-
jsonrpc: '2.0',
113-
result: 'something',
114-
});
110+
expect(await resultPromise).toBe('something');
115111
});
116112

117113
it('returns an error if the request is still unsuccessful after 10 retries', async () => {
@@ -141,26 +137,20 @@ describe('createRetryOnEmptyMiddleware', () => {
141137
}),
142138
]);
143139

144-
const responsePromise = engine.handle(request);
140+
const resultPromise = engine.handle(request);
145141
await waitForRequestToBeRetried({
146142
requestSpy,
147143
request,
148144
numberOfTimes: 10,
149145
});
150146

151-
expect(await responsePromise).toMatchObject({
152-
error: expect.objectContaining({
153-
data: expect.objectContaining({
154-
cause: expect.objectContaining({
155-
message: 'RetryOnEmptyMiddleware - retries exhausted',
156-
}),
157-
}),
158-
}),
159-
});
147+
await expect(resultPromise).rejects.toThrow(
148+
new Error('RetryOnEmptyMiddleware - retries exhausted'),
149+
);
160150
});
161151

162152
it('does not proceed to the next middleware after making a request through the provider', async () => {
163-
const finalMiddleware = createSimpleFinalMiddleware();
153+
const finalMiddleware = createFinalMiddlewareWithDefaultResult();
164154

165155
const engine = createEngine(
166156
createRetryOnEmptyMiddleware({
@@ -219,7 +209,7 @@ describe('createRetryOnEmptyMiddleware', () => {
219209
});
220210

221211
it('proceeds to the next middleware', async () => {
222-
const finalMiddleware = createSimpleFinalMiddleware();
212+
const finalMiddleware = createFinalMiddlewareWithDefaultResult();
223213

224214
const engine = createEngine(
225215
createRetryOnEmptyMiddleware({
@@ -276,7 +266,7 @@ describe('createRetryOnEmptyMiddleware', () => {
276266
});
277267

278268
it('proceeds to the next middleware', async () => {
279-
const finalMiddleware = createSimpleFinalMiddleware();
269+
const finalMiddleware = createFinalMiddlewareWithDefaultResult();
280270

281271
const engine = createEngine(
282272
createRetryOnEmptyMiddleware({
@@ -334,7 +324,7 @@ describe('createRetryOnEmptyMiddleware', () => {
334324
});
335325

336326
it('proceeds to the next middleware', async () => {
337-
const finalMiddleware = createSimpleFinalMiddleware();
327+
const finalMiddleware = createFinalMiddlewareWithDefaultResult();
338328

339329
const engine = createEngine(
340330
createRetryOnEmptyMiddleware({
@@ -389,7 +379,7 @@ describe('createRetryOnEmptyMiddleware', () => {
389379
});
390380

391381
it('proceeds to the next middleware', async () => {
392-
const finalMiddleware = createSimpleFinalMiddleware();
382+
const finalMiddleware = createFinalMiddlewareWithDefaultResult();
393383

394384
const engine = createEngine(
395385
createRetryOnEmptyMiddleware({
@@ -437,7 +427,7 @@ describe('createRetryOnEmptyMiddleware', () => {
437427
});
438428

439429
it('proceeds to the next middleware', async () => {
440-
const finalMiddleware = createSimpleFinalMiddleware();
430+
const finalMiddleware = createFinalMiddlewareWithDefaultResult();
441431

442432
const engine = createEngine(
443433
createRetryOnEmptyMiddleware({
@@ -478,13 +468,11 @@ describe('createRetryOnEmptyMiddleware', () => {
478468
},
479469
},
480470
]);
481-
const responsePromise = engine.handle(request);
482-
expect(await responsePromise).toMatchObject({
483-
error: expect.objectContaining({
484-
code: errorCodes.rpc.invalidInput,
485-
message: 'execution reverted',
486-
}),
487-
});
471+
472+
const resultPromise = engine.handle(request);
473+
await expect(resultPromise).rejects.toThrow(
474+
rpcErrors.invalidInput('execution reverted'),
475+
);
488476
});
489477
});
490478
});

packages/eth-json-rpc-middleware/src/retryOnEmpty.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import type { PollingBlockTracker } from '@metamask/eth-block-tracker';
22
import type { InternalProvider } from '@metamask/eth-json-rpc-provider';
3-
import type { JsonRpcMiddleware } from '@metamask/json-rpc-engine';
4-
import { createAsyncMiddleware } from '@metamask/json-rpc-engine';
5-
import type { Json, JsonRpcParams } from '@metamask/utils';
6-
import { klona } from 'klona/full';
3+
import type { JsonRpcMiddleware } from '@metamask/json-rpc-engine/v2';
4+
import type { Json, JsonRpcParams, JsonRpcRequest } from '@metamask/utils';
5+
import { klona } from 'klona';
76

87
import { projectLogger, createModuleLogger } from './logging-utils';
98
import type { Block } from './types';
@@ -41,7 +40,7 @@ export function createRetryOnEmptyMiddleware({
4140
}: {
4241
provider?: InternalProvider;
4342
blockTracker?: PollingBlockTracker;
44-
} = {}): JsonRpcMiddleware<JsonRpcParams, Json> {
43+
} = {}): JsonRpcMiddleware<JsonRpcRequest, Json> {
4544
if (!provider) {
4645
throw Error(
4746
'RetryOnEmptyMiddleware - mandatory "provider" option is missing.',
@@ -54,16 +53,18 @@ export function createRetryOnEmptyMiddleware({
5453
);
5554
}
5655

57-
return createAsyncMiddleware(async (req, res, next) => {
58-
const blockRefIndex: number | undefined = blockTagParamIndex(req.method);
56+
return async ({ request, next }) => {
57+
const blockRefIndex: number | undefined = blockTagParamIndex(
58+
request.method,
59+
);
5960
// skip if method does not include blockRef
6061
if (blockRefIndex === undefined) {
6162
return next();
6263
}
6364
// skip if not exact block references
6465
let blockRef: string | undefined =
65-
Array.isArray(req.params) && req.params[blockRefIndex]
66-
? (req.params[blockRefIndex] as string)
66+
Array.isArray(request.params) && request.params[blockRefIndex]
67+
? (request.params[blockRefIndex] as string)
6768
: undefined;
6869
// omitted blockRef implies "latest"
6970
if (blockRef === undefined) {
@@ -102,7 +103,7 @@ export function createRetryOnEmptyMiddleware({
102103
);
103104

104105
// create child request with specific block-ref
105-
const childRequest = klona(req);
106+
const childRequest = klona(request);
106107
// attempt child request until non-empty response is received
107108
const childResult = await retry(10, async () => {
108109
log('Performing request %o', childRequest);
@@ -122,10 +123,8 @@ export function createRetryOnEmptyMiddleware({
122123
return attemptResult;
123124
});
124125
log('Copying result %o', childResult);
125-
// copy child result onto original response
126-
res.result = childResult;
127-
return undefined;
128-
});
126+
return childResult;
127+
};
129128
}
130129

131130
/**

packages/eth-json-rpc-middleware/test/util/helpers.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -120,18 +120,6 @@ export function createEngine(
120120
});
121121
}
122122

123-
/**
124-
* Creates a middleware function that just ends the request, but is also a Jest
125-
* mock function so that you can make assertions on it.
126-
*
127-
* @returns The created middleware, as a mock function.
128-
*/
129-
export function createSimpleFinalMiddleware() {
130-
return jest.fn((_req, _res, _next, end) => {
131-
end();
132-
});
133-
}
134-
135123
/**
136124
* Some JSON-RPC endpoints take a "block" param (example: `eth_blockNumber`)
137125
* which can optionally be left out. Additionally, the endpoint may support some

0 commit comments

Comments
 (0)