mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
add method to detect EIP 1559 support (#11369)
This commit is contained in:
parent
a1d7271ed7
commit
23a859826f
@ -30,6 +30,9 @@ describe('DetectTokensController', function () {
|
|||||||
'0x7e57e2',
|
'0x7e57e2',
|
||||||
'0xbc86727e770de68b1060c91f6bb6945c73e10388',
|
'0xbc86727e770de68b1060c91f6bb6945c73e10388',
|
||||||
]);
|
]);
|
||||||
|
sandbox
|
||||||
|
.stub(network, 'getLatestBlock')
|
||||||
|
.callsFake(() => Promise.resolve({}));
|
||||||
sandbox
|
sandbox
|
||||||
.stub(preferences, '_detectIsERC721')
|
.stub(preferences, '_detectIsERC721')
|
||||||
.returns(Promise.resolve(false));
|
.returns(Promise.resolve(false));
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { strict as assert } from 'assert';
|
import { strict as assert } from 'assert';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import { getNetworkDisplayName } from './util';
|
import { getNetworkDisplayName } from './util';
|
||||||
import NetworkController from './network';
|
import NetworkController, { NETWORK_EVENTS } from './network';
|
||||||
|
|
||||||
describe('NetworkController', function () {
|
describe('NetworkController', function () {
|
||||||
describe('controller', function () {
|
describe('controller', function () {
|
||||||
let networkController;
|
let networkController;
|
||||||
|
let getLatestBlockStub;
|
||||||
|
let setProviderTypeAndWait;
|
||||||
const noop = () => undefined;
|
const noop = () => undefined;
|
||||||
const networkControllerProviderConfig = {
|
const networkControllerProviderConfig = {
|
||||||
getAccounts: noop,
|
getAccounts: noop,
|
||||||
@ -13,7 +15,21 @@ describe('NetworkController', function () {
|
|||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
networkController = new NetworkController();
|
networkController = new NetworkController();
|
||||||
|
getLatestBlockStub = sinon
|
||||||
|
.stub(networkController, 'getLatestBlock')
|
||||||
|
.callsFake(() => Promise.resolve({}));
|
||||||
networkController.setInfuraProjectId('foo');
|
networkController.setInfuraProjectId('foo');
|
||||||
|
setProviderTypeAndWait = () =>
|
||||||
|
new Promise((resolve) => {
|
||||||
|
networkController.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
networkController.setProviderType('mainnet');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
getLatestBlockStub.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#provider', function () {
|
describe('#provider', function () {
|
||||||
@ -67,6 +83,59 @@ describe('NetworkController', function () {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#getEIP1559Compatibility', function () {
|
||||||
|
it('should return false when baseFeePerGas is not in the block header', async function () {
|
||||||
|
networkController.initializeProvider(networkControllerProviderConfig);
|
||||||
|
const supportsEIP1559 = await networkController.getEIP1559Compatibility();
|
||||||
|
assert.equal(supportsEIP1559, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true when baseFeePerGas is in block header', async function () {
|
||||||
|
networkController.initializeProvider(networkControllerProviderConfig);
|
||||||
|
getLatestBlockStub.callsFake(() =>
|
||||||
|
Promise.resolve({ baseFeePerGas: '0xa ' }),
|
||||||
|
);
|
||||||
|
const supportsEIP1559 = await networkController.getEIP1559Compatibility();
|
||||||
|
assert.equal(supportsEIP1559, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should store EIP1559 support in state to reduce calls to getLatestBlock', async function () {
|
||||||
|
networkController.initializeProvider(networkControllerProviderConfig);
|
||||||
|
getLatestBlockStub.callsFake(() =>
|
||||||
|
Promise.resolve({ baseFeePerGas: '0xa ' }),
|
||||||
|
);
|
||||||
|
await networkController.getEIP1559Compatibility();
|
||||||
|
const supportsEIP1559 = await networkController.getEIP1559Compatibility();
|
||||||
|
assert.equal(getLatestBlockStub.calledOnce, true);
|
||||||
|
assert.equal(supportsEIP1559, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should clear stored EIP1559 support when changing networks', async function () {
|
||||||
|
networkController.initializeProvider(networkControllerProviderConfig);
|
||||||
|
networkController.consoleThis = true;
|
||||||
|
getLatestBlockStub.callsFake(() =>
|
||||||
|
Promise.resolve({ baseFeePerGas: '0xa ' }),
|
||||||
|
);
|
||||||
|
await networkController.getEIP1559Compatibility();
|
||||||
|
assert.equal(
|
||||||
|
networkController.networkDetails.getState().EIPS[1559],
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
getLatestBlockStub.callsFake(() => Promise.resolve({}));
|
||||||
|
await setProviderTypeAndWait('mainnet');
|
||||||
|
assert.equal(
|
||||||
|
networkController.networkDetails.getState().EIPS[1559],
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
await networkController.getEIP1559Compatibility();
|
||||||
|
assert.equal(
|
||||||
|
networkController.networkDetails.getState().EIPS[1559],
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
assert.equal(getLatestBlockStub.calledTwice, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('utils', function () {
|
describe('utils', function () {
|
||||||
|
@ -51,6 +51,10 @@ const defaultProviderConfig = {
|
|||||||
...defaultProviderConfigOpts,
|
...defaultProviderConfigOpts,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const defaultNetworkDetailsState = {
|
||||||
|
EIPS: { 1559: undefined },
|
||||||
|
};
|
||||||
|
|
||||||
export const NETWORK_EVENTS = {
|
export const NETWORK_EVENTS = {
|
||||||
// Fired after the actively selected network is changed
|
// Fired after the actively selected network is changed
|
||||||
NETWORK_DID_CHANGE: 'networkDidChange',
|
NETWORK_DID_CHANGE: 'networkDidChange',
|
||||||
@ -74,10 +78,21 @@ export default class NetworkController extends EventEmitter {
|
|||||||
this.providerStore.getState(),
|
this.providerStore.getState(),
|
||||||
);
|
);
|
||||||
this.networkStore = new ObservableStore('loading');
|
this.networkStore = new ObservableStore('loading');
|
||||||
|
// We need to keep track of a few details about the current network
|
||||||
|
// Ideally we'd merge this.networkStore with this new store, but doing so
|
||||||
|
// will require a decent sized refactor of how we're accessing network
|
||||||
|
// state. Currently this is only used for detecting EIP 1559 support but
|
||||||
|
// can be extended to track other network details.
|
||||||
|
this.networkDetails = new ObservableStore(
|
||||||
|
opts.networkDetails || {
|
||||||
|
...defaultNetworkDetailsState,
|
||||||
|
},
|
||||||
|
);
|
||||||
this.store = new ComposedStore({
|
this.store = new ComposedStore({
|
||||||
provider: this.providerStore,
|
provider: this.providerStore,
|
||||||
previousProviderStore: this.previousProviderStore,
|
previousProviderStore: this.previousProviderStore,
|
||||||
network: this.networkStore,
|
network: this.networkStore,
|
||||||
|
networkDetails: this.networkDetails,
|
||||||
});
|
});
|
||||||
|
|
||||||
// provider and block tracker
|
// provider and block tracker
|
||||||
@ -120,6 +135,42 @@ export default class NetworkController extends EventEmitter {
|
|||||||
return { provider, blockTracker };
|
return { provider, blockTracker };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to return the latest block for the current network
|
||||||
|
* @returns {Object} Block header
|
||||||
|
*/
|
||||||
|
getLatestBlock() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const { provider } = this.getProviderAndBlockTracker();
|
||||||
|
const ethQuery = new EthQuery(provider);
|
||||||
|
ethQuery.sendAsync(
|
||||||
|
{ method: 'eth_getBlockByNumber', params: ['latest', false] },
|
||||||
|
(err, block) => {
|
||||||
|
if (err) {
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
return resolve(block);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to check if the block header contains fields that indicate EIP 1559
|
||||||
|
* support (baseFeePerGas).
|
||||||
|
* @returns {Promise<boolean>} true if current network supports EIP 1559
|
||||||
|
*/
|
||||||
|
async getEIP1559Compatibility() {
|
||||||
|
const { EIPS } = this.networkDetails.getState();
|
||||||
|
if (EIPS[1559] !== undefined) {
|
||||||
|
return EIPS[1559];
|
||||||
|
}
|
||||||
|
const latestBlock = await this.getLatestBlock();
|
||||||
|
const supportsEIP1559 = latestBlock.baseFeePerGas !== undefined;
|
||||||
|
this.setNetworkEIPSupport(1559, supportsEIP1559);
|
||||||
|
return supportsEIP1559;
|
||||||
|
}
|
||||||
|
|
||||||
verifyNetwork() {
|
verifyNetwork() {
|
||||||
// Check network when restoring connectivity:
|
// Check network when restoring connectivity:
|
||||||
if (this.isNetworkLoading()) {
|
if (this.isNetworkLoading()) {
|
||||||
@ -135,6 +186,26 @@ export default class NetworkController extends EventEmitter {
|
|||||||
this.networkStore.putState(network);
|
this.networkStore.putState(network);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set EIP support indication in the networkDetails store
|
||||||
|
* @param {number} EIPNumber - The number of the EIP to mark support for
|
||||||
|
* @param {boolean} isSupported - True if the EIP is supported
|
||||||
|
*/
|
||||||
|
setNetworkEIPSupport(EIPNumber, isSupported) {
|
||||||
|
this.networkDetails.updateState({
|
||||||
|
EIPS: {
|
||||||
|
[EIPNumber]: isSupported,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset EIP support to default (no support)
|
||||||
|
*/
|
||||||
|
clearNetworkDetails() {
|
||||||
|
this.networkDetails.putState({ ...defaultNetworkDetailsState });
|
||||||
|
}
|
||||||
|
|
||||||
isNetworkLoading() {
|
isNetworkLoading() {
|
||||||
return this.getNetworkState() === 'loading';
|
return this.getNetworkState() === 'loading';
|
||||||
}
|
}
|
||||||
@ -154,6 +225,8 @@ export default class NetworkController extends EventEmitter {
|
|||||||
'NetworkController - lookupNetwork aborted due to missing chainId',
|
'NetworkController - lookupNetwork aborted due to missing chainId',
|
||||||
);
|
);
|
||||||
this.setNetworkState('loading');
|
this.setNetworkState('loading');
|
||||||
|
// keep network details in sync with network state
|
||||||
|
this.clearNetworkDetails();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,10 +247,14 @@ export default class NetworkController extends EventEmitter {
|
|||||||
if (initialNetwork === currentNetwork) {
|
if (initialNetwork === currentNetwork) {
|
||||||
if (err) {
|
if (err) {
|
||||||
this.setNetworkState('loading');
|
this.setNetworkState('loading');
|
||||||
|
// keep network details in sync with network state
|
||||||
|
this.clearNetworkDetails();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setNetworkState(networkVersion);
|
this.setNetworkState(networkVersion);
|
||||||
|
// look up EIP-1559 support
|
||||||
|
this.getEIP1559Compatibility();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -298,9 +375,15 @@ export default class NetworkController extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_switchNetwork(opts) {
|
_switchNetwork(opts) {
|
||||||
|
// Indicate to subscribers that network is about to change
|
||||||
this.emit(NETWORK_EVENTS.NETWORK_WILL_CHANGE);
|
this.emit(NETWORK_EVENTS.NETWORK_WILL_CHANGE);
|
||||||
|
// Set loading state
|
||||||
this.setNetworkState('loading');
|
this.setNetworkState('loading');
|
||||||
|
// Reset network details
|
||||||
|
this.clearNetworkDetails();
|
||||||
|
// Configure the provider appropriately
|
||||||
this._configureProvider(opts);
|
this._configureProvider(opts);
|
||||||
|
// Notify subscribers that network has changed
|
||||||
this.emit(NETWORK_EVENTS.NETWORK_DID_CHANGE, opts.type);
|
this.emit(NETWORK_EVENTS.NETWORK_DID_CHANGE, opts.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,9 @@ describe('preferences controller', function () {
|
|||||||
network.initializeProvider(networkControllerProviderConfig);
|
network.initializeProvider(networkControllerProviderConfig);
|
||||||
provider = network.getProviderAndBlockTracker().provider;
|
provider = network.getProviderAndBlockTracker().provider;
|
||||||
|
|
||||||
|
sandbox
|
||||||
|
.stub(network, 'getLatestBlock')
|
||||||
|
.callsFake(() => Promise.resolve({}));
|
||||||
sandbox.stub(network, 'getCurrentChainId').callsFake(() => currentChainId);
|
sandbox.stub(network, 'getCurrentChainId').callsFake(() => currentChainId);
|
||||||
sandbox
|
sandbox
|
||||||
.stub(network, 'getProviderConfig')
|
.stub(network, 'getProviderConfig')
|
||||||
|
@ -21,6 +21,11 @@ const firstTimeState = {
|
|||||||
rpcUrl: 'http://localhost:8545',
|
rpcUrl: 'http://localhost:8545',
|
||||||
chainId: '0x539',
|
chainId: '0x539',
|
||||||
},
|
},
|
||||||
|
networkDetails: {
|
||||||
|
EIPS: {
|
||||||
|
1559: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -238,3 +238,7 @@ export function getSendToAccounts(state) {
|
|||||||
export function getUnapprovedTxs(state) {
|
export function getUnapprovedTxs(state) {
|
||||||
return state.metamask.unapprovedTxs;
|
return state.metamask.unapprovedTxs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isEIP1559Network(state) {
|
||||||
|
return state.metamask.networkDetails.EIPS[1559] === true;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user