1
0
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:
Dan J Miller 2023-05-15 19:58:28 -02:30 committed by GitHub
commit 42197a35d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 451 additions and 104 deletions

View File

@ -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

View File

@ -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,6 +2559,9 @@ describe('NetworkController', () => {
describe('when the type in the provider configuration is "rpc"', () => {
describe('if both net_version and eth_getBlockByNumber respond successfully', () => {
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(
{
@ -2575,7 +2579,9 @@ describe('NetworkController', () => {
request: {
method: 'net_version',
},
response: SUCCESSFUL_NET_VERSION_RESPONSE,
response: {
result: networkId,
},
},
{
request: {
@ -2592,7 +2598,9 @@ describe('NetworkController', () => {
await controller.initializeProvider();
},
});
expect(controller.store.getState().networkStatus).toBe('unknown');
expect(controller.store.getState().networkStatus).toBe(
'unknown',
);
await waitForStateChanges({
controller,
@ -2627,7 +2635,7 @@ describe('NetworkController', () => {
method: 'net_version',
},
response: {
result: '42',
result: networkId,
},
},
{
@ -2657,10 +2665,12 @@ describe('NetworkController', () => {
},
});
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(

View File

@ -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) {

View File

@ -1,6 +1,6 @@
{
"name": "metamask-crx",
"version": "10.30.2",
"version": "10.30.3",
"private": true,
"repository": {
"type": "git",