diff --git a/packages/assets-controllers/src/AssetsContractController.ts b/packages/assets-controllers/src/AssetsContractController.ts index 06e72dce348..24871c48a6c 100644 --- a/packages/assets-controllers/src/AssetsContractController.ts +++ b/packages/assets-controllers/src/AssetsContractController.ts @@ -198,7 +198,6 @@ export class AssetsContractController extends BaseControllerV1< throw new Error(MISSING_PROVIDER_ERROR); } - // @ts-expect-error TODO: remove this annotation once the `Eip1193Provider` class is released return new Web3Provider(provider); } diff --git a/packages/eth-json-rpc-provider/package.json b/packages/eth-json-rpc-provider/package.json index d70068c4fe1..107378b6156 100644 --- a/packages/eth-json-rpc-provider/package.json +++ b/packages/eth-json-rpc-provider/package.json @@ -47,13 +47,19 @@ }, "dependencies": { "@metamask/json-rpc-engine": "^9.0.0", + "@metamask/rpc-errors": "^6.2.1", "@metamask/safe-event-emitter": "^3.0.0", - "@metamask/utils": "^8.3.0" + "@metamask/utils": "^8.3.0", + "uuid": "^8.3.2" }, "devDependencies": { + "@ethersproject/providers": "^5.7.0", "@metamask/auto-changelog": "^3.4.4", + "@metamask/eth-query": "^4.0.0", + "@metamask/ethjs-query": "^0.5.3", "@types/jest": "^27.4.1", "deepmerge": "^4.2.2", + "ethers": "^6.12.0", "jest": "^27.5.1", "jest-it-up": "^2.0.2", "ts-jest": "^27.1.4", diff --git a/packages/eth-json-rpc-provider/src/provider-from-engine.test.ts b/packages/eth-json-rpc-provider/src/provider-from-engine.test.ts index 0abdc989c3e..ca90a1deac1 100644 --- a/packages/eth-json-rpc-provider/src/provider-from-engine.test.ts +++ b/packages/eth-json-rpc-provider/src/provider-from-engine.test.ts @@ -1,5 +1,5 @@ import { JsonRpcEngine } from '@metamask/json-rpc-engine'; -import { promisify } from 'util'; +import { providerErrors } from '@metamask/rpc-errors'; import { providerFromEngine } from './provider-from-engine'; @@ -11,33 +11,36 @@ describe('providerFromEngine', () => { end(); }); const provider = providerFromEngine(engine); - const promisifiedSendAsync = promisify(provider.sendAsync); const exampleRequest = { id: 1, jsonrpc: '2.0' as const, method: 'test', }; - const response = await promisifiedSendAsync(exampleRequest); + const response = await provider.request(exampleRequest); - expect(response.result).toBe(42); + expect(response).toBe(42); }); it('handle a failed request', async () => { const engine = new JsonRpcEngine(); - engine.push((_req, _res, _next, _end) => { - throw new Error('Test error'); + engine.push((_req, _res, _next, end) => { + end( + providerErrors.custom({ + code: 1001, + message: 'Test error', + }), + ); }); const provider = providerFromEngine(engine); - const promisifiedSendAsync = promisify(provider.sendAsync); const exampleRequest = { id: 1, jsonrpc: '2.0' as const, method: 'test', }; - await expect(async () => - promisifiedSendAsync(exampleRequest), - ).rejects.toThrow('Test error'); + await expect(async () => provider.request(exampleRequest)).rejects.toThrow( + 'Test error', + ); }); }); diff --git a/packages/eth-json-rpc-provider/src/provider-from-middleware.test.ts b/packages/eth-json-rpc-provider/src/provider-from-middleware.test.ts index 4bae4202ef2..c3e73d31530 100644 --- a/packages/eth-json-rpc-provider/src/provider-from-middleware.test.ts +++ b/packages/eth-json-rpc-provider/src/provider-from-middleware.test.ts @@ -1,5 +1,5 @@ import type { JsonRpcMiddleware } from '@metamask/json-rpc-engine'; -import { promisify } from 'util'; +import { providerErrors } from '@metamask/rpc-errors'; import { providerFromMiddleware } from './provider-from-middleware'; @@ -12,32 +12,34 @@ describe('providerFromMiddleware', () => { end(); }; const provider = providerFromMiddleware(middleware); - const promisifiedSendAsync = promisify(provider.sendAsync); const exampleRequest = { id: 1, jsonrpc: '2.0' as const, method: 'test', }; - const response = await promisifiedSendAsync(exampleRequest); + const response = await provider.request(exampleRequest); - expect(response.result).toBe(42); + expect(response).toBe(42); }); it('handle a failed request', async () => { - const middleware = () => { - throw new Error('Test error'); - }; - const provider = providerFromMiddleware(middleware); - const promisifiedSendAsync = promisify(provider.sendAsync); + const provider = providerFromMiddleware((_req, _res, _next, end) => { + end( + providerErrors.custom({ + code: 1001, + message: 'Test error', + }), + ); + }); const exampleRequest = { id: 1, jsonrpc: '2.0' as const, method: 'test', }; - await expect(async () => - promisifiedSendAsync(exampleRequest), - ).rejects.toThrow('Test error'); + await expect(async () => provider.request(exampleRequest)).rejects.toThrow( + 'Test error', + ); }); }); diff --git a/packages/eth-json-rpc-provider/src/safe-event-emitter-provider.test.ts b/packages/eth-json-rpc-provider/src/safe-event-emitter-provider.test.ts index 9d683deb07e..dfab3eaa086 100644 --- a/packages/eth-json-rpc-provider/src/safe-event-emitter-provider.test.ts +++ b/packages/eth-json-rpc-provider/src/safe-event-emitter-provider.test.ts @@ -1,7 +1,38 @@ +import { Web3Provider } from '@ethersproject/providers'; +import EthQuery from '@metamask/eth-query'; +import EthJsQuery from '@metamask/ethjs-query'; import { JsonRpcEngine } from '@metamask/json-rpc-engine'; +import { providerErrors } from '@metamask/rpc-errors'; +import { type JsonRpcRequest, type Json } from '@metamask/utils'; +import { BrowserProvider } from 'ethers'; import { promisify } from 'util'; +import * as uuid from 'uuid'; -import { SafeEventEmitterProvider } from './safe-event-emitter-provider'; +import { + SafeEventEmitterProvider, + convertEip1193RequestToJsonRpcRequest, +} from './safe-event-emitter-provider'; + +jest.mock('uuid'); + +/** + * Creates a mock JSON-RPC engine that returns a predefined response for a specific method. + * + * @param method - The RPC method to mock. + * @param response - The response to return for the mocked method. + * @returns A JSON-RPC engine instance with the mocked method. + */ +function createMockEngine(method: string, response: Json) { + const engine = new JsonRpcEngine(); + engine.push((req, res, next, end) => { + if (req.method === method) { + res.result = response; + return end(); + } + return next(); + }); + return engine; +} describe('SafeEventEmitterProvider', () => { describe('constructor', () => { @@ -30,10 +61,187 @@ describe('SafeEventEmitterProvider', () => { }); }); + it('returns the correct block number with @metamask/eth-query', async () => { + const provider = new SafeEventEmitterProvider({ + engine: createMockEngine('eth_blockNumber', 42), + }); + const ethQuery = new EthQuery(provider); + + ethQuery.sendAsync({ method: 'eth_blockNumber' }, (_error, response) => { + expect(response).toBe(42); + }); + }); + + it('returns the correct block number with @metamask/ethjs-query', async () => { + const provider = new SafeEventEmitterProvider({ + engine: createMockEngine('eth_blockNumber', 42), + }); + const ethJsQuery = new EthJsQuery(provider); + + const response = await ethJsQuery.blockNumber(); + + expect(response.toNumber()).toBe(42); + }); + + it('returns the correct block number with Web3Provider', async () => { + const provider = new SafeEventEmitterProvider({ + engine: createMockEngine('eth_blockNumber', 42), + }); + const web3Provider = new Web3Provider(provider); + + const response = await web3Provider.send('eth_blockNumber', []); + + expect(response).toBe(42); + }); + + it('returns the correct block number with BrowserProvider', async () => { + const provider = new SafeEventEmitterProvider({ + engine: createMockEngine('eth_blockNumber', 42), + }); + const browserProvider = new BrowserProvider(provider); + + const response = await browserProvider.send('eth_blockNumber', []); + + expect(response).toBe(42); + }); + + describe('request', () => { + it('handles a successful JSON-RPC object request', async () => { + const engine = new JsonRpcEngine(); + let req: JsonRpcRequest | undefined; + engine.push((_req, res, _next, end) => { + req = _req; + res.result = 42; + end(); + }); + const provider = new SafeEventEmitterProvider({ engine }); + const exampleRequest = { + id: 1, + jsonrpc: '2.0' as const, + method: 'test', + params: { + param1: 'value1', + param2: 'value2', + }, + }; + + const result = await provider.request(exampleRequest); + + expect(req).toStrictEqual({ + id: 1, + jsonrpc: '2.0' as const, + method: 'test', + params: { + param1: 'value1', + param2: 'value2', + }, + }); + expect(result).toBe(42); + }); + + it('handles a successful EIP-1193 object request', async () => { + const engine = new JsonRpcEngine(); + let req: JsonRpcRequest | undefined; + engine.push((_req, res, _next, end) => { + req = _req; + res.result = 42; + end(); + }); + const provider = new SafeEventEmitterProvider({ engine }); + const exampleRequest = { + method: 'test', + params: { + param1: 'value1', + param2: 'value2', + }, + }; + jest.spyOn(uuid, 'v4').mockReturnValueOnce('mock-id'); + + const result = await provider.request(exampleRequest); + + expect(req).toStrictEqual({ + id: 'mock-id', + jsonrpc: '2.0' as const, + method: 'test', + params: { + param1: 'value1', + param2: 'value2', + }, + }); + expect(result).toBe(42); + }); + + it('handles a failure with a non-JSON-RPC error', async () => { + const engine = new JsonRpcEngine(); + engine.push((_req, _res, _next, end) => { + end( + providerErrors.custom({ + code: 1001, + message: 'Test error', + data: { + cause: 'Test cause', + }, + }), + ); + }); + const provider = new SafeEventEmitterProvider({ engine }); + const exampleRequest = { + id: 1, + jsonrpc: '2.0' as const, + method: 'test', + }; + + await expect(async () => + provider.request(exampleRequest), + ).rejects.toThrow( + expect.objectContaining({ + code: 1001, + message: 'Test error', + data: { cause: 'Test cause' }, + stack: expect.stringContaining( + 'safe-event-emitter-provider.test.ts:', + ), + }), + ); + }); + + it('handles a failure with a JSON-RPC error', async () => { + const engine = new JsonRpcEngine(); + engine.push(() => { + throw new Error('Test error'); + }); + const provider = new SafeEventEmitterProvider({ engine }); + const exampleRequest = { + id: 1, + jsonrpc: '2.0' as const, + method: 'test', + }; + + await expect(async () => + provider.request(exampleRequest), + ).rejects.toThrow( + expect.objectContaining({ + code: -32603, + message: 'Internal JSON-RPC error.', + data: { + cause: expect.objectContaining({ + stack: expect.stringContaining( + 'safe-event-emitter-provider.test.ts:', + ), + message: 'Test error', + }), + }, + }), + ); + }); + }); + describe('sendAsync', () => { - it('handles a successful request', async () => { + it('handles a successful JSON-RPC object request', async () => { const engine = new JsonRpcEngine(); + let req: JsonRpcRequest | undefined; engine.push((_req, res, _next, end) => { + req = _req; res.result = 42; end(); }); @@ -43,10 +251,56 @@ describe('SafeEventEmitterProvider', () => { id: 1, jsonrpc: '2.0' as const, method: 'test', + params: { + param1: 'value1', + param2: 'value2', + }, }; const response = await promisifiedSendAsync(exampleRequest); + expect(req).toStrictEqual({ + id: 1, + jsonrpc: '2.0' as const, + method: 'test', + params: { + param1: 'value1', + param2: 'value2', + }, + }); + expect(response.result).toBe(42); + }); + + it('handles a successful EIP-1193 object request', async () => { + const engine = new JsonRpcEngine(); + let req: JsonRpcRequest | undefined; + engine.push((_req, res, _next, end) => { + req = _req; + res.result = 42; + end(); + }); + const provider = new SafeEventEmitterProvider({ engine }); + const promisifiedSendAsync = promisify(provider.sendAsync); + const exampleRequest = { + method: 'test', + params: { + param1: 'value1', + param2: 'value2', + }, + }; + jest.spyOn(uuid, 'v4').mockReturnValueOnce('mock-id'); + + const response = await promisifiedSendAsync(exampleRequest); + + expect(req).toStrictEqual({ + id: 'mock-id', + jsonrpc: '2.0' as const, + method: 'test', + params: { + param1: 'value1', + param2: 'value2', + }, + }); expect(response.result).toBe(42); }); @@ -84,9 +338,11 @@ describe('SafeEventEmitterProvider', () => { expect(() => (provider.send as any)(exampleRequest)).toThrow(''); }); - it('handles a successful request', async () => { + it('handles a successful JSON-RPC object request', async () => { const engine = new JsonRpcEngine(); + let req: JsonRpcRequest | undefined; engine.push((_req, res, _next, end) => { + req = _req; res.result = 42; end(); }); @@ -96,10 +352,56 @@ describe('SafeEventEmitterProvider', () => { id: 1, jsonrpc: '2.0' as const, method: 'test', + params: { + param1: 'value1', + param2: 'value2', + }, + }; + + const response = await promisifiedSend(exampleRequest); + + expect(req).toStrictEqual({ + id: 1, + jsonrpc: '2.0' as const, + method: 'test', + params: { + param1: 'value1', + param2: 'value2', + }, + }); + expect(response.result).toBe(42); + }); + + it('handles a successful EIP-1193 object request', async () => { + const engine = new JsonRpcEngine(); + let req: JsonRpcRequest | undefined; + engine.push((_req, res, _next, end) => { + req = _req; + res.result = 42; + end(); + }); + const provider = new SafeEventEmitterProvider({ engine }); + const promisifiedSend = promisify(provider.send); + const exampleRequest = { + method: 'test', + params: { + param1: 'value1', + param2: 'value2', + }, }; + jest.spyOn(uuid, 'v4').mockReturnValueOnce('mock-id'); const response = await promisifiedSend(exampleRequest); + expect(req).toStrictEqual({ + id: 'mock-id', + jsonrpc: '2.0' as const, + method: 'test', + params: { + param1: 'value1', + param2: 'value2', + }, + }); expect(response.result).toBe(42); }); @@ -122,3 +424,94 @@ describe('SafeEventEmitterProvider', () => { }); }); }); + +describe('convertEip1193RequestToJsonRpcRequest', () => { + it('generates a unique id if id is not provided', () => { + jest.spyOn(uuid, 'v4').mockReturnValueOnce('mock-id'); + const eip1193Request = { + method: 'test', + params: { param1: 'value1', param2: 'value2' }, + }; + + const jsonRpcRequest = + convertEip1193RequestToJsonRpcRequest(eip1193Request); + + expect(jsonRpcRequest).toStrictEqual({ + id: 'mock-id', + jsonrpc: '2.0', + method: 'test', + params: { param1: 'value1', param2: 'value2' }, + }); + }); + + it('uses the provided id if id is provided', () => { + const eip1193Request = { + id: '123', + method: 'test', + params: { param1: 'value1', param2: 'value2' }, + }; + const jsonRpcRequest = + convertEip1193RequestToJsonRpcRequest(eip1193Request); + + expect(jsonRpcRequest).toStrictEqual({ + id: '123', + jsonrpc: '2.0', + method: 'test', + params: { param1: 'value1', param2: 'value2' }, + }); + }); + + it('uses the default jsonrpc version if not provided', () => { + jest.spyOn(uuid, 'v4').mockReturnValueOnce('mock-id'); + const eip1193Request = { + method: 'test', + params: { param1: 'value1', param2: 'value2' }, + }; + + const jsonRpcRequest = + convertEip1193RequestToJsonRpcRequest(eip1193Request); + + expect(jsonRpcRequest).toStrictEqual({ + id: 'mock-id', + jsonrpc: '2.0', + method: 'test', + params: { param1: 'value1', param2: 'value2' }, + }); + }); + + it('uses the provided jsonrpc version if provided', () => { + jest.spyOn(uuid, 'v4').mockReturnValueOnce('mock-id'); + const eip1193Request = { + jsonrpc: '2.0' as const, + method: 'test', + params: { param1: 'value1', param2: 'value2' }, + }; + + const jsonRpcRequest = + convertEip1193RequestToJsonRpcRequest(eip1193Request); + + expect(jsonRpcRequest).toStrictEqual({ + id: 'mock-id', + jsonrpc: '2.0', + method: 'test', + params: { param1: 'value1', param2: 'value2' }, + }); + }); + + it('uses an empty object as params if not provided', () => { + jest.spyOn(uuid, 'v4').mockReturnValueOnce('mock-id'); + const eip1193Request = { + method: 'test', + }; + + const jsonRpcRequest = + convertEip1193RequestToJsonRpcRequest(eip1193Request); + + expect(jsonRpcRequest).toStrictEqual({ + id: 'mock-id', + jsonrpc: '2.0', + method: 'test', + params: {}, + }); + }); +}); diff --git a/packages/eth-json-rpc-provider/src/safe-event-emitter-provider.ts b/packages/eth-json-rpc-provider/src/safe-event-emitter-provider.ts index 42798e4c7a9..5bb562f8584 100644 --- a/packages/eth-json-rpc-provider/src/safe-event-emitter-provider.ts +++ b/packages/eth-json-rpc-provider/src/safe-event-emitter-provider.ts @@ -1,6 +1,49 @@ import type { JsonRpcEngine } from '@metamask/json-rpc-engine'; +import { JsonRpcError } from '@metamask/rpc-errors'; import SafeEventEmitter from '@metamask/safe-event-emitter'; -import type { JsonRpcRequest } from '@metamask/utils'; +import type { + Json, + JsonRpcId, + JsonRpcParams, + JsonRpcRequest, + JsonRpcVersion2, +} from '@metamask/utils'; +import { v4 as uuidV4 } from 'uuid'; + +/** + * A JSON-RPC request conforming to the EIP-1193 specification. + */ +type Eip1193Request = { + id?: JsonRpcId; + jsonrpc?: JsonRpcVersion2; + method: string; + params?: Params; +}; + +/** + * Converts an EIP-1193 request to a JSON-RPC request. + * + * @param eip1193Request - The EIP-1193 request to convert. + * @returns The corresponding JSON-RPC request. + */ +export function convertEip1193RequestToJsonRpcRequest< + Params extends JsonRpcParams, +>( + eip1193Request: Eip1193Request, +): JsonRpcRequest> { + const { + id = uuidV4(), + jsonrpc = '2.0', + method, + params = {}, + } = eip1193Request; + return { + id, + jsonrpc, + method, + params, + }; +} /** * An Ethereum provider. @@ -31,30 +74,67 @@ export class SafeEventEmitterProvider extends SafeEventEmitter { /** * Send a provider request asynchronously. * - * @param req - The request to send. + * @param eip1193Request - The request to send. + * @returns The JSON-RPC response. + */ + async request( + eip1193Request: Eip1193Request, + ): Promise { + const jsonRpcRequest = + convertEip1193RequestToJsonRpcRequest(eip1193Request); + const response = await this.#engine.handle< + Params | Record, + Result + >(jsonRpcRequest); + + if ('result' in response) { + return response.result; + } + + const error = new JsonRpcError( + response.error.code, + response.error.message, + response.error.data, + ); + if ('stack' in response.error) { + error.stack = response.error.stack; + } + throw error; + } + + /** + * Send a provider request asynchronously. + * + * This method serves the same purpose as `request`. It only exists for + * legacy reasons. + * + * @param eip1193Request - The request to send. * @param callback - A function that is called upon the success or failure of the request. + * @deprecated Please use `request` instead. */ - sendAsync = ( - req: JsonRpcRequest, + sendAsync = ( + eip1193Request: Eip1193Request, // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any callback: (error: unknown, providerRes?: any) => void, ) => { - this.#engine.handle(req, callback); + const jsonRpcRequest = + convertEip1193RequestToJsonRpcRequest(eip1193Request); + this.#engine.handle(jsonRpcRequest, callback); }; /** * Send a provider request asynchronously. * - * This method serves the same purpose as `sendAsync`. It only exists for + * This method serves the same purpose as `request`. It only exists for * legacy reasons. * - * @deprecated Use `sendAsync` instead. - * @param req - The request to send. + * @param eip1193Request - The request to send. * @param callback - A function that is called upon the success or failure of the request. + * @deprecated Please use `request` instead. */ - send = ( - req: JsonRpcRequest, + send = ( + eip1193Request: Eip1193Request, // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any callback: (error: unknown, providerRes?: any) => void, @@ -62,6 +142,8 @@ export class SafeEventEmitterProvider extends SafeEventEmitter { if (typeof callback !== 'function') { throw new Error('Must provide callback to "send" method.'); } - this.#engine.handle(req, callback); + const jsonRpcRequest = + convertEip1193RequestToJsonRpcRequest(eip1193Request); + this.#engine.handle(jsonRpcRequest, callback); }; } diff --git a/tests/fake-provider.ts b/tests/fake-provider.ts index 9ba5c541cf6..4e76a4136f4 100644 --- a/tests/fake-provider.ts +++ b/tests/fake-provider.ts @@ -1,11 +1,27 @@ import { SafeEventEmitterProvider } from '@metamask/eth-json-rpc-provider'; import { JsonRpcEngine } from '@metamask/json-rpc-engine'; -import type { JsonRpcRequest, JsonRpcResponse } from '@metamask/utils'; +import type { + Json, + JsonRpcId, + JsonRpcParams, + JsonRpcResponse, + JsonRpcVersion2, +} from '@metamask/utils'; import { inspect, isDeepStrictEqual } from 'util'; // Store this in case it gets stubbed later const originalSetTimeout = global.setTimeout; +/** + * A JSON-RPC request conforming to the EIP-1193 specification. + */ +type Eip1193Request = { + id?: JsonRpcId; + jsonrpc?: JsonRpcVersion2; + method: string; + params?: Params; +}; + /** * Represents the type of the `response` property in a fake provider stub. */ @@ -15,23 +31,23 @@ export type FakeProviderResponse = { result: any } | { error: string }; /** * An object that allows specifying the behavior of a specific invocation of - * `sendAsync`. The `method` always identifies the stub, but the behavior - * may be specified multiple ways: `sendAsync` can either return a promise or + * `request`. The `method` always identifies the stub, but the behavior + * may be specified multiple ways: `request` can either return a promise or * throw an error, and if it returns a promise, that promise can either be * resolved with a response object or reject with an error. * * @property request - Looks for a request matching these specifications. * @property request.method - The RPC method to which this stub will be matched. * @property request.params - The params to which this stub will be matched. - * @property response - Instructs `sendAsync` to return a promise that resolves + * @property response - Instructs `request` to return a promise that resolves * with a response object. * @property response.result - Specifies a successful response, with this as the * `result`. * @property response.error - Specifies an error response, with this as the * `error`. - * @property error - Instructs `sendAsync` to return a promise that rejects with + * @property error - Instructs `request` to return a promise that rejects with * this error. - * @property implementation - Allows overriding `sendAsync` entirely. Useful if + * @property implementation - Allows overriding `request` entirely. Useful if * you want it to throw an error. * @property delay - The amount of time that will pass after the callback is * called with the response. @@ -69,7 +85,7 @@ export type FakeProviderStub = { * The set of options that the FakeProvider constructor takes. * * @property stubs - A set of objects that allow specifying the behavior - * of specific invocations of `sendAsync` matching a `method`. + * of specific invocations of `request` matching a `method`. */ type FakeProviderEngineOptions = { stubs?: FakeProviderStub[]; @@ -98,7 +114,7 @@ export class FakeProvider extends SafeEventEmitterProvider { * * @param options - The options. * @param options.stubs - A set of objects that allow specifying the behavior - * of specific invocations of `sendAsync` matching a `method`. + * of specific invocations of `request` matching a `method`. */ constructor({ stubs = [] }: FakeProviderEngineOptions = {}) { super({ engine: new JsonRpcEngine() }); @@ -107,8 +123,22 @@ export class FakeProvider extends SafeEventEmitterProvider { this.calledStubs = []; } - sendAsync = ( - payload: JsonRpcRequest, + request = ( + payload: Eip1193Request, + ): Promise => { + return new Promise((resolve, reject) => { + this.#handleSend(payload, (error, providerRes) => { + if (error) { + reject(error); + } else { + resolve(providerRes.result); + } + }); + }); + }; + + sendAsync = ( + payload: Eip1193Request, // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any callback: (error: unknown, providerRes?: any) => void, @@ -116,8 +146,8 @@ export class FakeProvider extends SafeEventEmitterProvider { return this.#handleSend(payload, callback); }; - send = ( - req: JsonRpcRequest, + send = ( + req: Eip1193Request, // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any callback: (error: unknown, providerRes?: any) => void, @@ -125,8 +155,8 @@ export class FakeProvider extends SafeEventEmitterProvider { return this.#handleSend(req, callback); }; - #handleSend( - req: JsonRpcRequest, + #handleSend( + req: Eip1193Request, // TODO: Replace `any` with type // eslint-disable-next-line @typescript-eslint/no-explicit-any callback: (error: unknown, providerRes?: any) => void, diff --git a/types/ethjs-query.d.ts b/types/ethjs-query.d.ts new file mode 100644 index 00000000000..5a960b3a7d4 --- /dev/null +++ b/types/ethjs-query.d.ts @@ -0,0 +1 @@ +declare module '@metamask/ethjs-query'; diff --git a/yarn.lock b/yarn.lock index 579fabb2079..8ce4548dc70 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2772,17 +2772,23 @@ __metadata: version: 0.0.0-use.local resolution: "@metamask/eth-json-rpc-provider@workspace:packages/eth-json-rpc-provider" dependencies: + "@ethersproject/providers": "npm:^5.7.0" "@metamask/auto-changelog": "npm:^3.4.4" + "@metamask/eth-query": "npm:^4.0.0" + "@metamask/ethjs-query": "npm:^0.5.3" "@metamask/json-rpc-engine": "npm:^9.0.0" + "@metamask/rpc-errors": "npm:^6.2.1" "@metamask/safe-event-emitter": "npm:^3.0.0" "@metamask/utils": "npm:^8.3.0" "@types/jest": "npm:^27.4.1" deepmerge: "npm:^4.2.2" + ethers: "npm:^6.12.0" jest: "npm:^27.5.1" jest-it-up: "npm:^2.0.2" ts-jest: "npm:^27.1.4" typedoc: "npm:^0.24.8" typescript: "npm:~4.9.5" + uuid: "npm:^8.3.2" languageName: unknown linkType: soft @@ -2865,6 +2871,20 @@ __metadata: languageName: node linkType: hard +"@metamask/ethjs-format@npm:^0.2.9": + version: 0.2.9 + resolution: "@metamask/ethjs-format@npm:0.2.9" + dependencies: + "@metamask/ethjs-util": "npm:^0.2.0" + bn.js: "npm:4.11.6" + ethjs-schema: "npm:0.2.1" + is-hex-prefixed: "npm:1.0.0" + number-to-bn: "npm:1.7.0" + strip-hex-prefix: "npm:1.0.0" + checksum: 10/704c2d1079c3bf03701d5cf94d04db85e05db21552a80136474efc88cc55718bef6b546f74e0949808459f52b3fb8ee891fc2329e5812e50e89581440972b3b7 + languageName: node + linkType: hard + "@metamask/ethjs-format@npm:^0.3.0": version: 0.3.0 resolution: "@metamask/ethjs-format@npm:0.3.0" @@ -2892,6 +2912,18 @@ __metadata: languageName: node linkType: hard +"@metamask/ethjs-query@npm:^0.5.3": + version: 0.5.3 + resolution: "@metamask/ethjs-query@npm:0.5.3" + dependencies: + "@metamask/ethjs-format": "npm:^0.2.9" + "@metamask/ethjs-rpc": "npm:0.3.0 || ^0.3.2" + babel-runtime: "npm:^6.26.0" + promise-to-callback: "npm:^1.0.0" + checksum: 10/a82eb2503bee0e513ecc4cb07a89c921f23b922ce788f13ad6c9307b41a88fded76e5f7bdb8f42e6620300a4af6cf502a242e4a2d1c445f970946e581c285617 + languageName: node + linkType: hard + "@metamask/ethjs-query@npm:^0.7.1": version: 0.7.1 resolution: "@metamask/ethjs-query@npm:0.7.1" @@ -2905,6 +2937,15 @@ __metadata: languageName: node linkType: hard +"@metamask/ethjs-rpc@npm:0.3.0 || ^0.3.2": + version: 0.3.2 + resolution: "@metamask/ethjs-rpc@npm:0.3.2" + dependencies: + promise-to-callback: "npm:^1.0.0" + checksum: 10/adee368325f43693379e30f3ab73f46eacdf96587f48428b723e64cd19aa22dca7d307f793f0760019911f4123b7bb5f3a3fcc031ec490da23a4b98335487c8f + languageName: node + linkType: hard + "@metamask/ethjs-rpc@npm:^0.4.0": version: 0.4.0 resolution: "@metamask/ethjs-rpc@npm:0.4.0" @@ -2928,6 +2969,16 @@ __metadata: languageName: node linkType: hard +"@metamask/ethjs-util@npm:^0.2.0": + version: 0.2.0 + resolution: "@metamask/ethjs-util@npm:0.2.0" + dependencies: + is-hex-prefixed: "npm:1.0.0" + strip-hex-prefix: "npm:1.0.0" + checksum: 10/63d091e2853afca937fba68fbecd5f5bc0baa5214c162becf9d5266e4049c216848d09d0140ac22d0d0d8c9166236c9795ca73eef6f675210ae5d582d9807c53 + languageName: node + linkType: hard + "@metamask/ethjs-util@npm:^0.3.0": version: 0.3.0 resolution: "@metamask/ethjs-util@npm:0.3.0" @@ -5455,6 +5506,16 @@ __metadata: languageName: node linkType: hard +"babel-runtime@npm:^6.26.0": + version: 6.26.0 + resolution: "babel-runtime@npm:6.26.0" + dependencies: + core-js: "npm:^2.4.0" + regenerator-runtime: "npm:^0.11.0" + checksum: 10/2cdf0f083b9598a43cdb11cbf1e7060584079a9a2230f06aec997ba81e887ef17fdcb5ad813a484ee099e06d2de0cea832bdd3011c06325acb284284c754ee8f + languageName: node + linkType: hard + "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" @@ -6179,6 +6240,13 @@ __metadata: languageName: node linkType: hard +"core-js@npm:^2.4.0": + version: 2.6.12 + resolution: "core-js@npm:2.6.12" + checksum: 10/7c624eb00a59c74c769d5d80f751f3bf1fc6201205b6562f27286ad5e00bbca1483f2f7eb0c2854b86f526ef5c7dc958b45f2ff536f8a31b8e9cb1a13a96efca + languageName: node + linkType: hard + "cosmiconfig@npm:^7.1.0": version: 7.1.0 resolution: "cosmiconfig@npm:7.1.0" @@ -7399,8 +7467,8 @@ __metadata: linkType: hard "ethers@npm:^6.12.0": - version: 6.12.1 - resolution: "ethers@npm:6.12.1" + version: 6.13.0 + resolution: "ethers@npm:6.13.0" dependencies: "@adraffy/ens-normalize": "npm:1.10.1" "@noble/curves": "npm:1.2.0" @@ -7409,7 +7477,7 @@ __metadata: aes-js: "npm:4.0.0-beta.5" tslib: "npm:2.4.0" ws: "npm:8.5.0" - checksum: 10/2995766164292b531499764d319d753b1f4e1cd7ddb4f26c6557a26e42947d5642a4b3bbeace0b8bb398b909dc22fafa4f52d5190a9bb8180bebf2dd3d4d48a9 + checksum: 10/390918da6955d6b9fcb9a57198ba4864df677e08fc478fbb7a74a02fd5ce0ca1b647782e0ae94c4cf056a205ebb86c64751a3712ffbc426fd53f11167f8cd4fe languageName: node linkType: hard @@ -9972,15 +10040,6 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^6.0.0": - version: 6.0.0 - resolution: "lru-cache@npm:6.0.0" - dependencies: - yallist: "npm:^4.0.0" - checksum: 10/fc1fe2ee205f7c8855fa0f34c1ab0bcf14b6229e35579ec1fd1079f31d6fc8ef8eb6fd17f2f4d99788d7e339f50e047555551ebd5e434dda503696e7c6591825 - languageName: node - linkType: hard - "lunr@npm:^2.3.9": version: 2.3.9 resolution: "lunr@npm:2.3.9" @@ -11245,6 +11304,13 @@ __metadata: languageName: node linkType: hard +"regenerator-runtime@npm:^0.11.0": + version: 0.11.1 + resolution: "regenerator-runtime@npm:0.11.1" + checksum: 10/64e62d78594c227e7d5269811bca9e4aa6451332adaae8c79a30cab0fa98733b1ad90bdb9d038095c340c6fad3b414a49a8d9e0b6b424ab7ff8f94f35704f8a2 + languageName: node + linkType: hard + "regenerator-runtime@npm:^0.14.0": version: 0.14.1 resolution: "regenerator-runtime@npm:0.14.1" @@ -11603,13 +11669,11 @@ __metadata: linkType: hard "semver@npm:7.x, semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.3.2, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": - version: 7.6.0 - resolution: "semver@npm:7.6.0" - dependencies: - lru-cache: "npm:^6.0.0" + version: 7.6.2 + resolution: "semver@npm:7.6.2" bin: semver: bin/semver.js - checksum: 10/1b41018df2d8aca5a1db4729985e8e20428c650daea60fcd16e926e9383217d00f574fab92d79612771884a98d2ee2a1973f49d630829a8d54d6570defe62535 + checksum: 10/296b17d027f57a87ef645e9c725bff4865a38dfc9caf29b26aa084b85820972fbe7372caea1ba6857162fa990702c6d9c1d82297cecb72d56c78ab29070d2ca2 languageName: node linkType: hard