eth-json-rpc-middleware@8.0.0 (#10738)

We're bumping from `^6` to `^8`. All imports are now named, and they have been updated. This is a breaking change, in that support for `eth_signTransaction` is added in `^8.0.0`. We do not support this method in our UI, so our middleware stack has been instrumented to reject.

In addition, there are some non-breaking behavioral changes in this version that reviewers should be aware of, see the [7.0.0 release](https://github.com/MetaMask/eth-json-rpc-middleware/releases).
feature/default_network_editable
Erik Marks 3 years ago committed by GitHub
parent 7cf4a16a63
commit b3963daaab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      app/scripts/controllers/network/createInfuraClient.js
  2. 16
      app/scripts/controllers/network/createJsonRpcClient.js
  3. 5
      app/scripts/controllers/network/createMetamaskMiddleware.js
  4. 2
      app/scripts/controllers/network/network.js
  5. 2
      app/scripts/controllers/threebox.js
  6. 7
      app/scripts/lib/rpc-method-middleware/createMethodMiddleware.js
  7. 2
      app/scripts/metamask-controller.js
  8. 2
      package.json
  9. 10
      shared/constants/network.js
  10. 64
      test/e2e/tests/provider-api.spec.js
  11. 8
      test/e2e/webdriver/driver.js
  12. 7
      test/stub/provider.js
  13. 22
      yarn.lock

@ -1,10 +1,13 @@
import { createScaffoldMiddleware, mergeMiddleware } from 'json-rpc-engine'; import { createScaffoldMiddleware, mergeMiddleware } from 'json-rpc-engine';
import createBlockRefMiddleware from 'eth-json-rpc-middleware/block-ref'; import {
import createRetryOnEmptyMiddleware from 'eth-json-rpc-middleware/retryOnEmpty'; createBlockRefMiddleware,
import createBlockCacheMiddleware from 'eth-json-rpc-middleware/block-cache'; createRetryOnEmptyMiddleware,
import createInflightCacheMiddleware from 'eth-json-rpc-middleware/inflight-cache'; createBlockCacheMiddleware,
import createBlockTrackerInspectorMiddleware from 'eth-json-rpc-middleware/block-tracker-inspector'; createInflightCacheMiddleware,
import providerFromMiddleware from 'eth-json-rpc-middleware/providerFromMiddleware'; createBlockTrackerInspectorMiddleware,
providerFromMiddleware,
} from 'eth-json-rpc-middleware';
import createInfuraMiddleware from 'eth-json-rpc-infura'; import createInfuraMiddleware from 'eth-json-rpc-infura';
import { PollingBlockTracker } from 'eth-block-tracker'; import { PollingBlockTracker } from 'eth-block-tracker';

@ -1,10 +1,12 @@
import { createAsyncMiddleware, mergeMiddleware } from 'json-rpc-engine'; import { createAsyncMiddleware, mergeMiddleware } from 'json-rpc-engine';
import createFetchMiddleware from 'eth-json-rpc-middleware/fetch'; import {
import createBlockRefRewriteMiddleware from 'eth-json-rpc-middleware/block-ref-rewrite'; createFetchMiddleware,
import createBlockCacheMiddleware from 'eth-json-rpc-middleware/block-cache'; createBlockRefRewriteMiddleware,
import createInflightMiddleware from 'eth-json-rpc-middleware/inflight-cache'; createBlockCacheMiddleware,
import createBlockTrackerInspectorMiddleware from 'eth-json-rpc-middleware/block-tracker-inspector'; createInflightCacheMiddleware,
import providerFromMiddleware from 'eth-json-rpc-middleware/providerFromMiddleware'; createBlockTrackerInspectorMiddleware,
providerFromMiddleware,
} from 'eth-json-rpc-middleware';
import { PollingBlockTracker } from 'eth-block-tracker'; import { PollingBlockTracker } from 'eth-block-tracker';
import { SECOND } from '../../../../shared/constants/time'; import { SECOND } from '../../../../shared/constants/time';
@ -27,7 +29,7 @@ export default function createJsonRpcClient({ rpcUrl, chainId }) {
createChainIdMiddleware(chainId), createChainIdMiddleware(chainId),
createBlockRefRewriteMiddleware({ blockTracker }), createBlockRefRewriteMiddleware({ blockTracker }),
createBlockCacheMiddleware({ blockTracker }), createBlockCacheMiddleware({ blockTracker }),
createInflightMiddleware(), createInflightCacheMiddleware(),
createBlockTrackerInspectorMiddleware({ blockTracker }), createBlockTrackerInspectorMiddleware({ blockTracker }),
fetchMiddleware, fetchMiddleware,
]); ]);

@ -1,5 +1,5 @@
import { createScaffoldMiddleware, mergeMiddleware } from 'json-rpc-engine'; import { createScaffoldMiddleware, mergeMiddleware } from 'json-rpc-engine';
import createWalletSubprovider from 'eth-json-rpc-middleware/wallet'; import { createWalletMiddleware } from 'eth-json-rpc-middleware';
import { import {
createPendingNonceMiddleware, createPendingNonceMiddleware,
createPendingTxMiddleware, createPendingTxMiddleware,
@ -21,11 +21,10 @@ export default function createMetamaskMiddleware({
}) { }) {
const metamaskMiddleware = mergeMiddleware([ const metamaskMiddleware = mergeMiddleware([
createScaffoldMiddleware({ createScaffoldMiddleware({
// staticSubprovider
eth_syncing: false, eth_syncing: false,
web3_clientVersion: `MetaMask/v${version}`, web3_clientVersion: `MetaMask/v${version}`,
}), }),
createWalletSubprovider({ createWalletMiddleware({
getAccounts, getAccounts,
processTransaction, processTransaction,
processEthSignMessage, processEthSignMessage,

@ -2,7 +2,7 @@ import { strict as assert } from 'assert';
import EventEmitter from 'events'; import EventEmitter from 'events';
import { ComposedStore, ObservableStore } from '@metamask/obs-store'; import { ComposedStore, ObservableStore } from '@metamask/obs-store';
import { JsonRpcEngine } from 'json-rpc-engine'; import { JsonRpcEngine } from 'json-rpc-engine';
import providerFromEngine from 'eth-json-rpc-middleware/providerFromEngine'; import { providerFromEngine } from 'eth-json-rpc-middleware';
import log from 'loglevel'; import log from 'loglevel';
import { import {
createSwappableProxy, createSwappableProxy,

@ -8,7 +8,7 @@ const Box = process.env.IN_TEST
import log from 'loglevel'; import log from 'loglevel';
import { JsonRpcEngine } from 'json-rpc-engine'; import { JsonRpcEngine } from 'json-rpc-engine';
import providerFromEngine from 'eth-json-rpc-middleware/providerFromEngine'; import { providerFromEngine } from 'eth-json-rpc-middleware';
import Migrator from '../lib/migrator'; import Migrator from '../lib/migrator';
import migrations from '../migrations'; import migrations from '../migrations';
import createOriginMiddleware from '../lib/createOriginMiddleware'; import createOriginMiddleware from '../lib/createOriginMiddleware';

@ -1,3 +1,5 @@
import { ethErrors } from 'eth-rpc-errors';
import { UNSUPPORTED_RPC_METHODS } from '../../../../shared/constants/network';
import handlers from './handlers'; import handlers from './handlers';
const handlerMap = handlers.reduce((map, handler) => { const handlerMap = handlers.reduce((map, handler) => {
@ -26,6 +28,11 @@ const handlerMap = handlers.reduce((map, handler) => {
*/ */
export default function createMethodMiddleware(opts) { export default function createMethodMiddleware(opts) {
return function methodMiddleware(req, res, next, end) { return function methodMiddleware(req, res, next, end) {
// Reject unsupported methods.
if (UNSUPPORTED_RPC_METHODS.has(req.method)) {
return end(ethErrors.rpc.methodNotSupported());
}
if (handlerMap.has(req.method)) { if (handlerMap.has(req.method)) {
return handlerMap.get(req.method)(req, res, next, end, opts); return handlerMap.get(req.method)(req, res, next, end, opts);
} }

@ -7,7 +7,7 @@ import { debounce } from 'lodash';
import createEngineStream from 'json-rpc-middleware-stream/engineStream'; import createEngineStream from 'json-rpc-middleware-stream/engineStream';
import createFilterMiddleware from 'eth-json-rpc-filters'; import createFilterMiddleware from 'eth-json-rpc-filters';
import createSubscriptionManager from 'eth-json-rpc-filters/subscriptionManager'; import createSubscriptionManager from 'eth-json-rpc-filters/subscriptionManager';
import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware'; import { providerAsMiddleware } from 'eth-json-rpc-middleware';
import KeyringController from 'eth-keyring-controller'; import KeyringController from 'eth-keyring-controller';
import { Mutex } from 'await-semaphore'; import { Mutex } from 'await-semaphore';
import { stripHexPrefix } from 'ethereumjs-util'; import { stripHexPrefix } from 'ethereumjs-util';

@ -135,7 +135,7 @@
"eth-ens-namehash": "^2.0.8", "eth-ens-namehash": "^2.0.8",
"eth-json-rpc-filters": "^4.2.1", "eth-json-rpc-filters": "^4.2.1",
"eth-json-rpc-infura": "^5.1.0", "eth-json-rpc-infura": "^5.1.0",
"eth-json-rpc-middleware": "^6.0.0", "eth-json-rpc-middleware": "^8.0.0",
"eth-keyring-controller": "^6.2.0", "eth-keyring-controller": "^6.2.0",
"eth-method-registry": "^2.0.0", "eth-method-registry": "^2.0.0",
"eth-lattice-keyring": "^0.3.0", "eth-lattice-keyring": "^0.3.0",

@ -161,3 +161,13 @@ export const CHAIN_ID_TO_GAS_LIMIT_BUFFER_MAP = {
[OPTIMISM_CHAIN_ID]: 1, [OPTIMISM_CHAIN_ID]: 1,
[OPTIMISM_TESTNET_CHAIN_ID]: 1, [OPTIMISM_TESTNET_CHAIN_ID]: 1,
}; };
/**
* Ethereum JSON-RPC methods that are known to exist but that we intentionally
* do not support.
*/
export const UNSUPPORTED_RPC_METHODS = new Set([
// This is implemented later in our middleware stack – specifically, in
// eth-json-rpc-middleware – but our UI does not support it.
'eth_signTransaction',
]);

@ -1,17 +1,19 @@
const { strict: assert } = require('assert'); const { strict: assert } = require('assert');
const { errorCodes } = require('eth-rpc-errors');
const { withFixtures } = require('../helpers'); const { withFixtures } = require('../helpers');
describe('MetaMask', function () { describe('MetaMask', function () {
const ganacheOptions = {
accounts: [
{
secretKey:
'0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC',
balance: 25000000000000000000,
},
],
};
it('provider should inform dapp when switching networks', async function () { it('provider should inform dapp when switching networks', async function () {
const ganacheOptions = {
accounts: [
{
secretKey:
'0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC',
balance: 25000000000000000000,
},
],
};
await withFixtures( await withFixtures(
{ {
dapp: true, dapp: true,
@ -62,4 +64,48 @@ describe('MetaMask', function () {
}, },
); );
}); });
it('should reject unsupported methods', async function () {
await withFixtures(
{
dapp: true,
failOnConsoleError: false,
fixtures: 'connected-state',
ganacheOptions,
title: this.test.title,
},
async ({ driver }) => {
await driver.navigate();
await driver.fill('#password', 'correct horse battery staple');
await driver.press('#password', driver.Key.ENTER);
await driver.openNewPage('http://127.0.0.1:8080/');
for (const unsupportedMethod of ['eth_signTransaction']) {
assert.equal(
await driver.executeAsyncScript(`
const webDriverCallback = arguments[arguments.length - 1];
window.ethereum.request({ method: '${unsupportedMethod}' })
.then(() => {
console.error('The unsupported method "${unsupportedMethod}" was not rejected.');
webDriverCallback(false);
})
.catch((error) => {
if (error.code === ${errorCodes.rpc.methodNotSupported}) {
webDriverCallback(true);
}
console.error(
'The unsupported method "${unsupportedMethod}" was rejected with an unexpected error.',
error,
);
webDriverCallback(false);
})
`),
true,
`The unsupported method "${unsupportedMethod}" should be rejected by the provider.`,
);
}
},
);
});
}); });

@ -29,6 +29,10 @@ function wrapElementWithAPI(element, driver) {
return element; return element;
} }
/**
* For Selenium WebDriver API documentation, see:
* https://www.selenium.dev/selenium/docs/api/javascript/module/selenium-webdriver/index_exports_WebDriver.html
*/
class Driver { class Driver {
/** /**
* @param {!ThenableWebDriver} driver - A {@code WebDriver} instance * @param {!ThenableWebDriver} driver - A {@code WebDriver} instance
@ -49,6 +53,10 @@ class Driver {
}; };
} }
async executeAsyncScript(script, ...args) {
return this.driver.executeAsyncScript(script, args);
}
async executeScript(script, ...args) { async executeScript(script, ...args) {
return this.driver.executeScript(script, args); return this.driver.executeScript(script, args);
} }

@ -1,6 +1,5 @@
import { JsonRpcEngine } from 'json-rpc-engine'; import { JsonRpcEngine, createScaffoldMiddleware } from 'json-rpc-engine';
import scaffoldMiddleware from 'eth-json-rpc-middleware/scaffold'; import { providerAsMiddleware } from 'eth-json-rpc-middleware';
import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware';
import GanacheCore from 'ganache-core'; import GanacheCore from 'ganache-core';
export function getTestSeed() { export function getTestSeed() {
@ -45,7 +44,7 @@ export function providerFromEngine(engine) {
export function createTestProviderTools(opts = {}) { export function createTestProviderTools(opts = {}) {
const engine = createEngineForTestData(); const engine = createEngineForTestData();
// handle provided hooks // handle provided hooks
engine.push(scaffoldMiddleware(opts.scaffold || {})); engine.push(createScaffoldMiddleware(opts.scaffold || {}));
// handle block tracker methods // handle block tracker methods
engine.push( engine.push(
providerAsMiddleware( providerAsMiddleware(

@ -12971,6 +12971,21 @@ eth-json-rpc-middleware@^6.0.0:
pify "^3.0.0" pify "^3.0.0"
safe-event-emitter "^1.0.1" safe-event-emitter "^1.0.1"
eth-json-rpc-middleware@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-8.0.0.tgz#d2a50a5fceca996ddc9d6775d53cf7e341500a88"
integrity sha512-G0693ZsEXzERrvE6mb2fevDvSE2gs1ClqFnh/r6/RUYq3y1uzK/5klRsfQvQPCGM9q2FEBKxWYdbIjMZAXWcDQ==
dependencies:
"@metamask/safe-event-emitter" "^2.0.0"
btoa "^1.2.1"
clone "^2.1.1"
eth-rpc-errors "^4.0.3"
eth-sig-util "^1.4.2"
json-rpc-engine "^6.1.0"
json-stable-stringify "^1.0.1"
node-fetch "^2.6.1"
pify "^3.0.0"
eth-keyring-controller@^6.1.0, eth-keyring-controller@^6.2.0, eth-keyring-controller@^6.2.1: eth-keyring-controller@^6.1.0, eth-keyring-controller@^6.2.0, eth-keyring-controller@^6.2.1:
version "6.2.1" version "6.2.1"
resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-6.2.1.tgz#61901071fc74059ed37cb5ae93870fdcae6e3781" resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-6.2.1.tgz#61901071fc74059ed37cb5ae93870fdcae6e3781"
@ -13062,6 +13077,13 @@ eth-rpc-errors@^4.0.0, eth-rpc-errors@^4.0.2:
dependencies: dependencies:
fast-safe-stringify "^2.0.6" fast-safe-stringify "^2.0.6"
eth-rpc-errors@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/eth-rpc-errors/-/eth-rpc-errors-4.0.3.tgz#6ddb6190a4bf360afda82790bb7d9d5e724f423a"
integrity sha512-Z3ymjopaoft7JDoxZcEb3pwdGh7yiYMhOwm2doUt6ASXlMavpNlK6Cre0+IMl2VSGyEU9rkiperQhp5iRxn5Pg==
dependencies:
fast-safe-stringify "^2.0.6"
eth-sig-util@^1.4.2: eth-sig-util@^1.4.2:
version "1.4.2" version "1.4.2"
resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210"

Loading…
Cancel
Save