Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions app/core/BackgroundBridge/BackgroundBridge.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/* eslint-disable import/no-commonjs */
import URL from 'url-parse';
import { JsonRpcEngine } from 'json-rpc-engine';
import {
createSelectedNetworkMiddleware,
METAMASK_DOMAIN,
} from '@metamask/selected-network-controller';
import EthQuery from '@metamask/eth-query';
import { JsonRpcEngine } from '@metamask/json-rpc-engine';
import MobilePortStream from '../MobilePortStream';
import { setupMultiplex } from '../../util/streams';
import {
Expand All @@ -16,7 +16,6 @@ import Engine from '../Engine';
import { createSanitizationMiddleware } from '../SanitizationMiddleware';
import Logger from '../../util/Logger';
import AppConstants from '../AppConstants';
import { createEngineStream } from 'json-rpc-middleware-stream';
import RemotePort from './RemotePort';
import WalletConnectPort from './WalletConnectPort';
import Port from './Port';
Expand All @@ -28,7 +27,8 @@ import { SubjectType } from '@metamask/permission-controller';

const createFilterMiddleware = require('@metamask/eth-json-rpc-filters');
const createSubscriptionManager = require('@metamask/eth-json-rpc-filters/subscriptionManager');
const { providerAsMiddleware } = require('@metamask/eth-json-rpc-middleware');
import { createEngineStream } from '@metamask/json-rpc-middleware-stream';
import { providerAsMiddleware } from '@metamask/eth-json-rpc-middleware';
const pump = require('pump');
// eslint-disable-next-line import/no-nodejs-modules
const EventEmitter = require('events').EventEmitter;
Expand Down Expand Up @@ -388,11 +388,7 @@ export class BackgroundBridge extends EventEmitter {

pump(outStream, providerStream, outStream, (err) => {
// handle any middleware cleanup
this.engine._middleware.forEach((mid) => {
if (mid.destroy && typeof mid.destroy === 'function') {
mid.destroy();
}
});
this.engine.destroy();
if (err) Logger.log('Error with provider stream conn', err);
});
}
Expand Down
35 changes: 21 additions & 14 deletions app/core/RPCMethods/RPCMethodMiddleware.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {
JsonRpcEngine,
JsonRpcFailure,
JsonRpcMiddleware,
import { JsonRpcEngine, JsonRpcMiddleware } from '@metamask/json-rpc-engine';
import type {
Json,
JsonRpcParams,
JsonRpcRequest,
JsonRpcResponse,
JsonRpcFailure,
JsonRpcSuccess,
} from 'json-rpc-engine';
} from '@metamask/utils8';
import { type JsonRpcError, providerErrors, rpcErrors } from '@metamask/rpc-errors';
import type { TransactionParams } from '@metamask/transaction-controller';
import { providerErrors, rpcErrors } from '@metamask/rpc-errors';
import Engine from '../Engine';
import { store } from '../../store';
import { getPermittedAccounts } from '../Permissions';
Expand Down Expand Up @@ -106,8 +107,8 @@ const jsonrpc = '2.0' as const;
* @throws If the given value is not a valid {@link JsonRpcSuccess} object.
*/
function assertIsJsonRpcSuccess(
response: JsonRpcResponse<unknown>,
): asserts response is JsonRpcSuccess<unknown> {
response: JsonRpcResponse<Json>,
): asserts response is JsonRpcSuccess<Json> {
if ('error' in response) {
throw new Error(`Response failed with error '${JSON.stringify('error')}'`);
} else if (!('result' in response)) {
Expand Down Expand Up @@ -208,8 +209,8 @@ async function callMiddleware({
middleware,
request,
}: {
middleware: JsonRpcMiddleware<unknown, unknown>;
request: JsonRpcRequest<unknown>;
middleware: JsonRpcMiddleware<JsonRpcParams, Json>;
request: JsonRpcRequest<JsonRpcParams>;
}) {
const engine = new JsonRpcEngine();
engine.push(middleware);
Expand Down Expand Up @@ -416,7 +417,7 @@ describe('getRpcMethodMiddleware', () => {
permissionController.createPermissionMiddleware({
origin: hostMock,
});
// @ts-expect-error JsonRpcId (number | string | void) doesn't match PS middleware's id, which is (string | number | null)
// @ts-expect-error TODO: Resolve mismatch for permission-controller json-rpc-engine eth-json-rpc-middleware
engine.push(permissionMiddleware);
const middleware = getRpcMethodMiddleware(getMinimalOptions());
engine.push(middleware);
Expand Down Expand Up @@ -1097,7 +1098,8 @@ describe('getRpcMethodMiddleware', () => {
it('returns a JSON-RPC error if an error is thrown when adding this transaction', async () => {
// Omit `from` and `chainId` here to skip validation for simplicity
// Downcast needed here because `from` is required by this type
const mockTransactionParameters = {} as TransactionParams;
const mockTransactionParameters = {} as (TransactionParams &
JsonRpcParams)[];
// Transaction fails before returning a result
mockAddTransaction.mockImplementation(async () => {
throw new Error('Failed to add transaction');
Expand All @@ -1120,12 +1122,17 @@ describe('getRpcMethodMiddleware', () => {
expect((response as JsonRpcFailure).error.message).toBe(
expectedError.message,
);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
expect(((response as JsonRpcFailure).error as JsonRpcError<any>).data.cause.message).toBe(
expectedError.message,
);
});

it('returns a JSON-RPC error if an error is thrown after approval', async () => {
// Omit `from` and `chainId` here to skip validation for simplicity
// Downcast needed here because `from` is required by this type
const mockTransactionParameters = {} as TransactionParams;
const mockTransactionParameters = {} as (TransactionParams &
JsonRpcParams)[];
setupGlobalState({
addTransactionResult: Promise.reject(
new Error('Failed to process transaction'),
Expand Down Expand Up @@ -1234,7 +1241,7 @@ describe('getRpcMethodMiddleware', () => {
jsonrpc,
id: 1,
method: 'personal_ecRecover',
params: [undefined, helloWorldSignature],
params: [undefined, helloWorldSignature] as JsonRpcParams,
};
const expectedError = rpcErrors.internal('Missing data parameter');

Expand Down
2 changes: 1 addition & 1 deletion app/core/RPCMethods/RPCMethodMiddleware.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Alert } from 'react-native';
import { getVersion } from 'react-native-device-info';
import { createAsyncMiddleware } from 'json-rpc-engine';
import { createAsyncMiddleware } from '@metamask/json-rpc-engine';
import { providerErrors, rpcErrors } from '@metamask/rpc-errors';
import {
EndFlowOptions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
JsonRpcEngine,
JsonRpcEngineEndCallback,
JsonRpcEngineNextCallback,
} from 'json-rpc-engine';
} from '@metamask/json-rpc-engine';
import {
Json,
JsonRpcParams,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { rpcErrors } from '@metamask/rpc-errors';
import type { JsonRpcMiddleware } from 'json-rpc-engine';
import type { JsonRpcMiddleware } from '@metamask/json-rpc-engine';
import type { Json, JsonRpcParams } from '@metamask/utils';
import { UNSUPPORTED_RPC_METHODS } from '../utils';

/**
* Creates a middleware that rejects explicitly unsupported RPC methods with the
* appropriate error.
*/
const createUnsupportedMethodMiddleware = (): JsonRpcMiddleware<
unknown,
void
JsonRpcParams,
Json
> =>
async function unsupportedMethodMiddleware(req, _res, next, end) {
if ((UNSUPPORTED_RPC_METHODS as Set<string>).has(req.method)) {
Expand Down
9 changes: 5 additions & 4 deletions app/core/RPCMethods/eth_sendTransaction.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// eslint-disable-next-line import/no-nodejs-modules
import { inspect } from 'util';
import type { JsonRpcRequest, PendingJsonRpcResponse } from 'json-rpc-engine';
import type { Json, JsonRpcRequest, PendingJsonRpcResponse } from '@metamask/utils';
import type {
TransactionParams,
TransactionController,
WalletDevice,
} from '@metamask/transaction-controller';
import eth_sendTransaction from './eth_sendTransaction';
import PPOMUtil from '../../lib/ppom/ppom-util';
import { JsonRpcParams } from '@metamask/eth-query';

jest.mock('../../core/Engine', () => ({
context: {
Expand Down Expand Up @@ -49,12 +50,12 @@ jest.mock('../../util/transaction-controller', () => ({
*/
function constructSendTransactionRequest(
params: unknown,
): JsonRpcRequest<unknown> & { method: 'eth_sendTransaction' } {
): JsonRpcRequest<JsonRpcParams> & { method: 'eth_sendTransaction' } {
return {
jsonrpc: '2.0',
id: 1,
method: 'eth_sendTransaction',
params,
params: params as JsonRpcParams,
};
}

Expand All @@ -63,7 +64,7 @@ function constructSendTransactionRequest(
*
* @returns A pending JSON-RPC response.
*/
function constructPendingJsonRpcResponse(): PendingJsonRpcResponse<unknown> {
function constructPendingJsonRpcResponse(): PendingJsonRpcResponse<Json> {
return {
jsonrpc: '2.0',
id: 1,
Expand Down
23 changes: 17 additions & 6 deletions app/core/RPCMethods/eth_sendTransaction.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { JsonRpcRequest, PendingJsonRpcResponse } from 'json-rpc-engine';
import type { Json, JsonRpcParams, JsonRpcRequest, PendingJsonRpcResponse } from '@metamask/utils';
import {
type TransactionParams,
TransactionController,
WalletDevice,
} from '@metamask/transaction-controller';
Expand Down Expand Up @@ -66,8 +67,8 @@ async function eth_sendTransaction({
validateAccountAndChainId,
}: {
hostname: string;
req: JsonRpcRequest<unknown> & { method: 'eth_sendTransaction' };
res: PendingJsonRpcResponse<unknown>;
req: JsonRpcRequest<JsonRpcParams> & { method: 'eth_sendTransaction' };
res: PendingJsonRpcResponse<Json>;
sendTransaction: TransactionController['addTransaction'];
validateAccountAndChainId: (args: {
from: string;
Expand All @@ -88,12 +89,22 @@ async function eth_sendTransaction({
message: `Invalid parameters: expected the first parameter to be an object`,
});
}
if (!hasProperty(transactionParameters, 'from') || typeof transactionParameters.from !== 'string') {
throw rpcErrors.invalidParams({
message: `Invalid parameters: expected the first parameter to have a 'from' property of type string`,
});
}
if (hasProperty(transactionParameters, 'chainId') && !['undefined', 'number'].includes(typeof transactionParameters.chainId)) {
throw rpcErrors.invalidParams({
message: `Invalid parameters: expected the first parameter to have a 'chainId' property of type number`,
});
}
await validateAccountAndChainId({
from: req.params[0].from,
chainId: req.params[0].chainId,
from: transactionParameters.from,
chainId: transactionParameters.chainId as number | undefined,
});

const { result, transactionMeta } = await sendTransaction(req.params[0], {
const { result, transactionMeta } = await sendTransaction(transactionParameters as TransactionParams, {
deviceConfirmedOn: WalletDevice.MM_MOBILE,
origin: hostname,
});
Expand Down
4 changes: 2 additions & 2 deletions app/core/RPCMethods/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { query } from '@metamask/controller-utils';
import Engine from '../Engine';
import { JsonRpcMiddleware } from '@metamask/json-rpc-engine';
import { selectHooks } from '@metamask/snaps-rpc-methods';
import { OptionalDataWithOptionalCause, rpcErrors } from '@metamask/rpc-errors';
import { JsonRpcMiddleware } from 'json-rpc-engine';
import { PermittedHandlerExport } from '@metamask/permission-controller';
import { Json, JsonRpcParams, hasProperty } from '@metamask/utils';
import EthQuery from '@metamask/eth-query';
Expand Down Expand Up @@ -76,7 +76,7 @@ export function makeMethodMiddlewareMaker<U>(
const makeMethodMiddleware = (hooks: Record<string, unknown>) => {
assertExpectedHook(hooks, expectedHookNames);

const methodMiddleware: JsonRpcMiddleware<JsonRpcParams, unknown> = async (
const methodMiddleware: JsonRpcMiddleware<JsonRpcParams, Json> = async (
req,
res,
next,
Expand Down
2 changes: 1 addition & 1 deletion app/core/RPCMethods/wallet_watchAsset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import {
} from '../../constants/error';
import { selectChainId } from '../../selectors/networkController';
import { isValidAddress } from 'ethereumjs-util';
import { JsonRpcRequest, PendingJsonRpcResponse } from 'json-rpc-engine';
import { toChecksumHexAddress } from '@metamask/controller-utils';
import { JsonRpcRequest, PendingJsonRpcResponse } from '@metamask/utils';

const wallet_watchAsset = async ({
req,
Expand Down
14 changes: 8 additions & 6 deletions app/core/SanitizationMiddleware.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { JsonRpcMiddleware, JsonRpcRequest } from 'json-rpc-engine';
import { JsonRpcMiddleware } from '@metamask/json-rpc-engine';
import type { TransactionParams } from '@metamask/transaction-controller';
import type { Json, JsonRpcParams, JsonRpcRequest } from '@metamask/utils8';
import { addHexPrefix } from 'ethereumjs-util';

// We use this to clean any custom params from the txParams
Expand Down Expand Up @@ -39,7 +41,7 @@ export const permittedKeys = [
* @param parameter - The parameter to sanitize.
* @returns The given parameter containing just permitted keys.
*/
function sanitizeRpcParameter(parameter: Record<PropertyKey, unknown>) {
function sanitizeRpcParameter(parameter: Record<PropertyKey, unknown>): TransactionParams {
return permittedKeys.reduce<Record<string, unknown>>((copy, permitted) => {
if (permitted in parameter) {
const value = parameter[permitted];
Expand All @@ -50,7 +52,7 @@ function sanitizeRpcParameter(parameter: Record<PropertyKey, unknown>) {
}
}
return copy;
}, {});
}, {}) as TransactionParams;
}

/**
Expand Down Expand Up @@ -80,12 +82,12 @@ function sanitize(value: unknown) {
* request along.
*/
export function createSanitizationMiddleware(): JsonRpcMiddleware<
unknown,
unknown
JsonRpcParams,
Json
> {
// TODO: Replace "any" with type
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (req: JsonRpcRequest<unknown>, _: any, next: () => any) => {
return (req: JsonRpcRequest<JsonRpcParams>, _: Json, next: () => any, _end: () => any) => {
if (!Array.isArray(req.params)) {
next();
return;
Expand Down
4 changes: 2 additions & 2 deletions app/core/Snaps/SnapBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {
createSwappableProxy,
createEventEmitterProxy,
} from '@metamask/swappable-obj-proxy';
import { JsonRpcEngine } from 'json-rpc-engine';
import { createEngineStream } from 'json-rpc-middleware-stream';
import { JsonRpcEngine } from '@metamask/json-rpc-engine';
import { createEngineStream } from '@metamask/json-rpc-middleware-stream';
import { NetworksChainId } from '@metamask/controller-utils';

import Engine from '../Engine';
Expand Down
2 changes: 1 addition & 1 deletion app/core/WalletConnect/extractApprovedAccounts.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Caveat, ValidPermission } from '@metamask/permission-controller';
import { Json } from 'json-rpc-engine';
import type { Json } from '@metamask/utils';

export const extractApprovedAccounts = (
accountPermission: // TODO: Replace "any" with type
Expand Down
8 changes: 4 additions & 4 deletions app/core/createTracingMiddleware/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { JsonRpcRequest, PendingJsonRpcResponse } from 'json-rpc-engine';
import type { Json, JsonRpcParams, JsonRpcRequest, PendingJsonRpcResponse } from '@metamask/utils';
import { default as createTracingMiddleware, MESSAGE_TYPE } from './index';

const REQUEST_MOCK = {
id: 'testId',
method: MESSAGE_TYPE.PERSONAL_SIGN,
} as JsonRpcRequest<unknown>;
const RESPONSE_MOCK = {} as PendingJsonRpcResponse<unknown>;
} as JsonRpcRequest<JsonRpcParams>;
const RESPONSE_MOCK = {} as PendingJsonRpcResponse<Json>;
const NEXT_MOCK = jest.fn();

jest.mock('../../util/trace', () => ({
Expand All @@ -14,7 +14,7 @@ jest.mock('../../util/trace', () => ({
}));

describe('createTracingMiddleware', () => {
let request: JsonRpcRequest<unknown> & { traceContext?: unknown };
let request: JsonRpcRequest<JsonRpcParams> & { traceContext?: unknown };
beforeEach(() => {
jest.clearAllMocks();
request = { ...REQUEST_MOCK };
Expand Down
6 changes: 3 additions & 3 deletions app/core/createTracingMiddleware/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { JsonRpcRequest, PendingJsonRpcResponse } from 'json-rpc-engine';
import type { Json, JsonRpcParams, JsonRpcRequest, PendingJsonRpcResponse } from '@metamask/utils';
import { trace, TraceName } from '../../util/trace';

export const MESSAGE_TYPE = {
Expand All @@ -19,8 +19,8 @@ const METHOD_TYPE_TO_TRACE_NAME: Record<string, TraceName> = {

export default function createTracingMiddleware() {
return async function tracingMiddleware(
req: JsonRpcRequest<unknown> & { traceContext?: unknown },
_res: PendingJsonRpcResponse<unknown>,
req: JsonRpcRequest<JsonRpcParams> & { traceContext?: unknown },
_res: PendingJsonRpcResponse<Json>,
next: () => void,
) {
const { id, method } = req;
Expand Down
Loading