mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
Merge pull request #19159 from MetaMask/Version-v10.30.3
Version v10.30.3 RC
This commit is contained in:
commit
42197a35d9
@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [10.30.3]
|
||||
### Fixed
|
||||
- Restore support for chains that return hex or number responses to `net_version` ([#19156](https://github.com/MetaMask/metamask-extension/pull/19156))
|
||||
|
||||
## [10.30.2]
|
||||
### Changed
|
||||
- Improve `eth_signTypedData_v4` validation ([#19110](https://github.com/MetaMask/metamask-extension/pull/19110))
|
||||
@ -3718,7 +3722,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Uncategorized
|
||||
- Added the ability to restore accounts from seed words.
|
||||
|
||||
[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.30.2...HEAD
|
||||
[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.30.3...HEAD
|
||||
[10.30.3]: https://github.com/MetaMask/metamask-extension/compare/v10.30.2...v10.30.3
|
||||
[10.30.2]: https://github.com/MetaMask/metamask-extension/compare/v10.30.1...v10.30.2
|
||||
[10.30.1]: https://github.com/MetaMask/metamask-extension/compare/v10.30.0...v10.30.1
|
||||
[10.30.0]: https://github.com/MetaMask/metamask-extension/compare/v10.29.0...v10.30.0
|
||||
|
@ -3,6 +3,7 @@ import assert from 'assert';
|
||||
import { get } from 'lodash';
|
||||
import { v4 } from 'uuid';
|
||||
import nock from 'nock';
|
||||
import { toHex } from '@metamask/controller-utils';
|
||||
import { ControllerMessenger } from '@metamask/base-controller';
|
||||
import { SafeEventEmitterProvider } from '@metamask/eth-json-rpc-provider';
|
||||
import { when, resetAllWhenMocks } from 'jest-when';
|
||||
@ -2558,109 +2559,118 @@ describe('NetworkController', () => {
|
||||
|
||||
describe('when the type in the provider configuration is "rpc"', () => {
|
||||
describe('if both net_version and eth_getBlockByNumber respond successfully', () => {
|
||||
it('stores the fact the network is available', async () => {
|
||||
await withController(
|
||||
{
|
||||
state: {
|
||||
provider: {
|
||||
type: 'rpc',
|
||||
rpcUrl: 'https://mock-rpc-url',
|
||||
chainId: '0x1337',
|
||||
},
|
||||
},
|
||||
},
|
||||
async ({ controller }) => {
|
||||
const fakeProvider = buildFakeProvider([
|
||||
const validNetworkIds = [12345, '12345', toHex(12345)];
|
||||
for (const networkId of validNetworkIds) {
|
||||
describe(`with a network id of '${networkId}'`, () => {
|
||||
it('stores the fact the network is available', async () => {
|
||||
await withController(
|
||||
{
|
||||
request: {
|
||||
method: 'net_version',
|
||||
state: {
|
||||
provider: {
|
||||
type: 'rpc',
|
||||
rpcUrl: 'https://mock-rpc-url',
|
||||
chainId: '0x1337',
|
||||
},
|
||||
},
|
||||
response: SUCCESSFUL_NET_VERSION_RESPONSE,
|
||||
},
|
||||
{
|
||||
request: {
|
||||
method: 'eth_getBlockByNumber',
|
||||
},
|
||||
response: SUCCESSFUL_ETH_GET_BLOCK_BY_NUMBER_RESPONSE,
|
||||
},
|
||||
]);
|
||||
const fakeNetworkClient = buildFakeClient(fakeProvider);
|
||||
mockCreateNetworkClient().mockReturnValue(fakeNetworkClient);
|
||||
await withoutCallingLookupNetwork({
|
||||
controller,
|
||||
operation: async () => {
|
||||
await controller.initializeProvider();
|
||||
},
|
||||
});
|
||||
expect(controller.store.getState().networkStatus).toBe('unknown');
|
||||
async ({ controller }) => {
|
||||
const fakeProvider = buildFakeProvider([
|
||||
{
|
||||
request: {
|
||||
method: 'net_version',
|
||||
},
|
||||
response: {
|
||||
result: networkId,
|
||||
},
|
||||
},
|
||||
{
|
||||
request: {
|
||||
method: 'eth_getBlockByNumber',
|
||||
},
|
||||
response: SUCCESSFUL_ETH_GET_BLOCK_BY_NUMBER_RESPONSE,
|
||||
},
|
||||
]);
|
||||
const fakeNetworkClient = buildFakeClient(fakeProvider);
|
||||
mockCreateNetworkClient().mockReturnValue(fakeNetworkClient);
|
||||
await withoutCallingLookupNetwork({
|
||||
controller,
|
||||
operation: async () => {
|
||||
await controller.initializeProvider();
|
||||
},
|
||||
});
|
||||
expect(controller.store.getState().networkStatus).toBe(
|
||||
'unknown',
|
||||
);
|
||||
|
||||
await waitForStateChanges({
|
||||
controller,
|
||||
propertyPath: ['networkStatus'],
|
||||
operation: async () => {
|
||||
await controller.lookupNetwork();
|
||||
},
|
||||
});
|
||||
await waitForStateChanges({
|
||||
controller,
|
||||
propertyPath: ['networkStatus'],
|
||||
operation: async () => {
|
||||
await controller.lookupNetwork();
|
||||
},
|
||||
});
|
||||
|
||||
expect(controller.store.getState().networkStatus).toBe(
|
||||
'available',
|
||||
expect(controller.store.getState().networkStatus).toBe(
|
||||
'available',
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('stores the ID of the network', async () => {
|
||||
await withController(
|
||||
{
|
||||
state: {
|
||||
provider: {
|
||||
type: 'rpc',
|
||||
rpcUrl: 'https://mock-rpc-url',
|
||||
chainId: '0x1337',
|
||||
},
|
||||
},
|
||||
},
|
||||
async ({ controller }) => {
|
||||
const fakeProvider = buildFakeProvider([
|
||||
it('stores the ID of the network', async () => {
|
||||
await withController(
|
||||
{
|
||||
request: {
|
||||
method: 'net_version',
|
||||
},
|
||||
response: {
|
||||
result: '42',
|
||||
state: {
|
||||
provider: {
|
||||
type: 'rpc',
|
||||
rpcUrl: 'https://mock-rpc-url',
|
||||
chainId: '0x1337',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
request: {
|
||||
method: 'eth_getBlockByNumber',
|
||||
},
|
||||
response: {
|
||||
result: POST_1559_BLOCK,
|
||||
},
|
||||
},
|
||||
]);
|
||||
const fakeNetworkClient = buildFakeClient(fakeProvider);
|
||||
mockCreateNetworkClient().mockReturnValue(fakeNetworkClient);
|
||||
await withoutCallingLookupNetwork({
|
||||
controller,
|
||||
operation: async () => {
|
||||
await controller.initializeProvider();
|
||||
},
|
||||
});
|
||||
expect(controller.store.getState().networkId).toBe(null);
|
||||
async ({ controller }) => {
|
||||
const fakeProvider = buildFakeProvider([
|
||||
{
|
||||
request: {
|
||||
method: 'net_version',
|
||||
},
|
||||
response: {
|
||||
result: networkId,
|
||||
},
|
||||
},
|
||||
{
|
||||
request: {
|
||||
method: 'eth_getBlockByNumber',
|
||||
},
|
||||
response: {
|
||||
result: POST_1559_BLOCK,
|
||||
},
|
||||
},
|
||||
]);
|
||||
const fakeNetworkClient = buildFakeClient(fakeProvider);
|
||||
mockCreateNetworkClient().mockReturnValue(fakeNetworkClient);
|
||||
await withoutCallingLookupNetwork({
|
||||
controller,
|
||||
operation: async () => {
|
||||
await controller.initializeProvider();
|
||||
},
|
||||
});
|
||||
expect(controller.store.getState().networkId).toBe(null);
|
||||
|
||||
await waitForStateChanges({
|
||||
controller,
|
||||
propertyPath: ['networkId'],
|
||||
operation: async () => {
|
||||
await controller.lookupNetwork();
|
||||
},
|
||||
});
|
||||
await waitForStateChanges({
|
||||
controller,
|
||||
propertyPath: ['networkId'],
|
||||
operation: async () => {
|
||||
await controller.lookupNetwork();
|
||||
},
|
||||
});
|
||||
|
||||
expect(controller.store.getState().networkId).toBe('42');
|
||||
},
|
||||
);
|
||||
});
|
||||
expect(controller.store.getState().networkId).toBe('12345');
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
it('stores the fact that the network supports EIP-1559 when baseFeePerGas is in the block header', async () => {
|
||||
await withController(
|
||||
@ -3203,6 +3213,332 @@ describe('NetworkController', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('if the request for eth_getBlockByNumber responds successfully, but the request for net_version returns an invalid network ID', () => {
|
||||
it('stores the network status as unknown', async () => {
|
||||
await withController(
|
||||
{
|
||||
state: {
|
||||
provider: {
|
||||
type: 'rpc',
|
||||
rpcUrl: 'https://mock-rpc-url',
|
||||
chainId: '0x1337',
|
||||
},
|
||||
},
|
||||
},
|
||||
async ({ controller }) => {
|
||||
const fakeProvider = buildFakeProvider([
|
||||
{
|
||||
request: {
|
||||
method: 'net_version',
|
||||
},
|
||||
response: SUCCESSFUL_NET_VERSION_RESPONSE,
|
||||
},
|
||||
{
|
||||
request: {
|
||||
method: 'eth_getBlockByNumber',
|
||||
},
|
||||
response: SUCCESSFUL_ETH_GET_BLOCK_BY_NUMBER_RESPONSE,
|
||||
},
|
||||
{
|
||||
request: {
|
||||
method: 'net_version',
|
||||
},
|
||||
response: {
|
||||
result: 'invalid',
|
||||
},
|
||||
},
|
||||
{
|
||||
request: {
|
||||
method: 'eth_getBlockByNumber',
|
||||
},
|
||||
response: SUCCESSFUL_ETH_GET_BLOCK_BY_NUMBER_RESPONSE,
|
||||
},
|
||||
]);
|
||||
const fakeNetworkClient = buildFakeClient(fakeProvider);
|
||||
mockCreateNetworkClient().mockReturnValue(fakeNetworkClient);
|
||||
await waitForStateChanges({
|
||||
controller,
|
||||
propertyPath: ['networkStatus'],
|
||||
operation: async () => {
|
||||
await controller.initializeProvider();
|
||||
},
|
||||
});
|
||||
expect(controller.store.getState().networkStatus).toBe(
|
||||
'available',
|
||||
);
|
||||
|
||||
await waitForStateChanges({
|
||||
controller,
|
||||
propertyPath: ['networkStatus'],
|
||||
operation: async () => {
|
||||
await controller.lookupNetwork();
|
||||
},
|
||||
});
|
||||
|
||||
expect(controller.store.getState().networkStatus).toBe('unknown');
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('clears the ID of the network from state', async () => {
|
||||
await withController(
|
||||
{
|
||||
state: {
|
||||
provider: {
|
||||
type: 'rpc',
|
||||
rpcUrl: 'https://mock-rpc-url',
|
||||
chainId: '0x1337',
|
||||
},
|
||||
},
|
||||
},
|
||||
async ({ controller }) => {
|
||||
const fakeProvider = buildFakeProvider([
|
||||
{
|
||||
request: {
|
||||
method: 'net_version',
|
||||
},
|
||||
response: {
|
||||
result: '42',
|
||||
},
|
||||
},
|
||||
{
|
||||
request: {
|
||||
method: 'eth_getBlockByNumber',
|
||||
},
|
||||
response: SUCCESSFUL_ETH_GET_BLOCK_BY_NUMBER_RESPONSE,
|
||||
},
|
||||
{
|
||||
request: {
|
||||
method: 'net_version',
|
||||
},
|
||||
response: {
|
||||
result: 'invalid',
|
||||
},
|
||||
},
|
||||
{
|
||||
request: {
|
||||
method: 'eth_getBlockByNumber',
|
||||
},
|
||||
response: SUCCESSFUL_ETH_GET_BLOCK_BY_NUMBER_RESPONSE,
|
||||
},
|
||||
]);
|
||||
const fakeNetworkClient = buildFakeClient(fakeProvider);
|
||||
mockCreateNetworkClient().mockReturnValue(fakeNetworkClient);
|
||||
await waitForStateChanges({
|
||||
controller,
|
||||
propertyPath: ['networkStatus'],
|
||||
operation: async () => {
|
||||
await controller.initializeProvider();
|
||||
},
|
||||
});
|
||||
expect(controller.store.getState().networkId).toBe('42');
|
||||
|
||||
await waitForStateChanges({
|
||||
controller,
|
||||
propertyPath: ['networkId'],
|
||||
operation: async () => {
|
||||
await controller.lookupNetwork();
|
||||
},
|
||||
});
|
||||
|
||||
expect(controller.store.getState().networkId).toBeNull();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('clears whether the network supports EIP-1559 from state along with any other network details', async () => {
|
||||
await withController(
|
||||
{
|
||||
state: {
|
||||
provider: {
|
||||
type: 'rpc',
|
||||
rpcUrl: 'https://mock-rpc-url',
|
||||
chainId: '0x1337',
|
||||
},
|
||||
networkDetails: {
|
||||
EIPS: {
|
||||
1559: true,
|
||||
},
|
||||
other: 'details',
|
||||
},
|
||||
},
|
||||
},
|
||||
async ({ controller }) => {
|
||||
const fakeProvider = buildFakeProvider([
|
||||
{
|
||||
request: {
|
||||
method: 'net_version',
|
||||
},
|
||||
response: SUCCESSFUL_NET_VERSION_RESPONSE,
|
||||
},
|
||||
{
|
||||
request: {
|
||||
method: 'eth_getBlockByNumber',
|
||||
},
|
||||
response: {
|
||||
result: PRE_1559_BLOCK,
|
||||
},
|
||||
},
|
||||
{
|
||||
request: {
|
||||
method: 'net_version',
|
||||
},
|
||||
response: {
|
||||
result: 'invalid',
|
||||
},
|
||||
},
|
||||
{
|
||||
request: {
|
||||
method: 'eth_getBlockByNumber',
|
||||
},
|
||||
response: {
|
||||
result: POST_1559_BLOCK,
|
||||
},
|
||||
},
|
||||
]);
|
||||
const fakeNetworkClient = buildFakeClient(fakeProvider);
|
||||
mockCreateNetworkClient().mockReturnValue(fakeNetworkClient);
|
||||
await waitForStateChanges({
|
||||
controller,
|
||||
propertyPath: ['networkStatus'],
|
||||
operation: async () => {
|
||||
await controller.initializeProvider();
|
||||
},
|
||||
});
|
||||
expect(controller.store.getState().networkDetails).toStrictEqual({
|
||||
EIPS: {
|
||||
1559: false,
|
||||
},
|
||||
other: 'details',
|
||||
});
|
||||
|
||||
await waitForStateChanges({
|
||||
controller,
|
||||
propertyPath: ['networkDetails'],
|
||||
operation: async () => {
|
||||
await controller.lookupNetwork();
|
||||
},
|
||||
});
|
||||
|
||||
expect(controller.store.getState().networkDetails).toStrictEqual({
|
||||
EIPS: {
|
||||
1559: undefined,
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('does not emit infuraIsBlocked', async () => {
|
||||
const { unrestrictedMessenger, restrictedMessenger } =
|
||||
buildMessengerGroup();
|
||||
|
||||
await withController(
|
||||
{
|
||||
messenger: restrictedMessenger,
|
||||
state: {
|
||||
provider: {
|
||||
type: 'rpc',
|
||||
rpcUrl: 'https://mock-rpc-url',
|
||||
chainId: '0x1337',
|
||||
},
|
||||
},
|
||||
},
|
||||
async ({ controller }) => {
|
||||
const fakeProvider = buildFakeProvider([
|
||||
{
|
||||
request: {
|
||||
method: 'net_version',
|
||||
},
|
||||
response: {
|
||||
result: 'invalid',
|
||||
},
|
||||
},
|
||||
{
|
||||
request: {
|
||||
method: 'eth_getBlockByNumber',
|
||||
},
|
||||
response: SUCCESSFUL_ETH_GET_BLOCK_BY_NUMBER_RESPONSE,
|
||||
},
|
||||
]);
|
||||
const fakeNetworkClient = buildFakeClient(fakeProvider);
|
||||
mockCreateNetworkClient().mockReturnValue(fakeNetworkClient);
|
||||
await withoutCallingLookupNetwork({
|
||||
controller,
|
||||
operation: async () => {
|
||||
await controller.initializeProvider();
|
||||
},
|
||||
});
|
||||
|
||||
const promiseForNoInfuraIsBlockedEvents = waitForPublishedEvents({
|
||||
messenger: unrestrictedMessenger,
|
||||
eventType: NetworkControllerEventType.InfuraIsBlocked,
|
||||
count: 0,
|
||||
operation: async () => {
|
||||
await controller.lookupNetwork();
|
||||
},
|
||||
});
|
||||
|
||||
expect(await promiseForNoInfuraIsBlockedEvents).toBeTruthy();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('emits infuraIsUnblocked', async () => {
|
||||
const { unrestrictedMessenger, restrictedMessenger } =
|
||||
buildMessengerGroup();
|
||||
|
||||
await withController(
|
||||
{
|
||||
messenger: restrictedMessenger,
|
||||
state: {
|
||||
provider: {
|
||||
type: 'rpc',
|
||||
rpcUrl: 'https://mock-rpc-url',
|
||||
chainId: '0x1337',
|
||||
},
|
||||
},
|
||||
},
|
||||
async ({ controller }) => {
|
||||
const fakeProvider = buildFakeProvider([
|
||||
{
|
||||
request: {
|
||||
method: 'net_version',
|
||||
},
|
||||
response: {
|
||||
result: 'invalid',
|
||||
},
|
||||
},
|
||||
{
|
||||
request: {
|
||||
method: 'eth_getBlockByNumber',
|
||||
},
|
||||
response: SUCCESSFUL_ETH_GET_BLOCK_BY_NUMBER_RESPONSE,
|
||||
},
|
||||
]);
|
||||
const fakeNetworkClient = buildFakeClient(fakeProvider);
|
||||
mockCreateNetworkClient().mockReturnValue(fakeNetworkClient);
|
||||
await withoutCallingLookupNetwork({
|
||||
controller,
|
||||
operation: async () => {
|
||||
await controller.initializeProvider();
|
||||
},
|
||||
});
|
||||
|
||||
const infuraIsUnblocked = await waitForPublishedEvents({
|
||||
messenger: unrestrictedMessenger,
|
||||
eventType: NetworkControllerEventType.InfuraIsUnblocked,
|
||||
operation: async () => {
|
||||
await controller.lookupNetwork();
|
||||
},
|
||||
});
|
||||
|
||||
expect(infuraIsUnblocked).toBeTruthy();
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('if the request for net_version responds successfully, but the request for eth_getBlockByNumber responds with a generic error', () => {
|
||||
it('stores the fact that the network is unavailable', async () => {
|
||||
await withController(
|
||||
|
@ -10,10 +10,11 @@ import {
|
||||
import EthQuery from 'eth-query';
|
||||
import { RestrictedControllerMessenger } from '@metamask/base-controller';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { Hex, isPlainObject } from '@metamask/utils';
|
||||
import { Hex, isPlainObject, isStrictHexString } from '@metamask/utils';
|
||||
import { errorCodes } from 'eth-rpc-errors';
|
||||
import { SafeEventEmitterProvider } from '@metamask/eth-json-rpc-provider';
|
||||
import { PollingBlockTracker } from 'eth-block-tracker';
|
||||
import { hexToDecimal } from '../../../../shared/modules/conversion.utils';
|
||||
import {
|
||||
INFURA_PROVIDER_TYPES,
|
||||
INFURA_BLOCKED_KEY,
|
||||
@ -301,16 +302,22 @@ function isErrorWithCode(error: unknown): error is { code: string | number } {
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the given value is a network ID, i.e., that it is a decimal
|
||||
* number represented as a string.
|
||||
* Convert the given value into a valid network ID. The ID is accepted
|
||||
* as either a number, a decimal string, or a 0x-prefixed hex string.
|
||||
*
|
||||
* @param value - The value to check.
|
||||
* @param value - The network ID to convert, in an unknown format.
|
||||
* @returns A valid network ID (as a decimal string)
|
||||
* @throws If the given value cannot be safely parsed.
|
||||
*/
|
||||
function assertNetworkId(value: any): asserts value is NetworkId {
|
||||
assert(
|
||||
/^\d+$/u.test(value) && !Number.isNaN(Number(value)),
|
||||
'value is not a number',
|
||||
);
|
||||
function convertNetworkId(value: unknown): NetworkId {
|
||||
if (typeof value === 'number' && !Number.isNaN(value)) {
|
||||
return `${value}`;
|
||||
} else if (isStrictHexString(value)) {
|
||||
return hexToDecimal(value) as NetworkId;
|
||||
} else if (typeof value === 'string' && /^\d+$/u.test(value)) {
|
||||
return value as NetworkId;
|
||||
}
|
||||
throw new Error(`Cannot parse as a valid network ID: '${value}'`);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -619,8 +626,7 @@ export class NetworkController extends EventEmitter {
|
||||
this.#determineEIP1559Compatibility(provider),
|
||||
]);
|
||||
const possibleNetworkId = results[0];
|
||||
assertNetworkId(possibleNetworkId);
|
||||
networkId = possibleNetworkId;
|
||||
networkId = convertNetworkId(possibleNetworkId);
|
||||
supportsEIP1559 = results[1];
|
||||
networkStatus = NetworkStatus.Available;
|
||||
} catch (error) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "metamask-crx",
|
||||
"version": "10.30.2",
|
||||
"version": "10.30.3",
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
Loading…
Reference in New Issue
Block a user