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',
|
||||
'0xbc86727e770de68b1060c91f6bb6945c73e10388',
|
||||
]);
|
||||
sandbox
|
||||
.stub(network, 'getLatestBlock')
|
||||
.callsFake(() => Promise.resolve({}));
|
||||
sandbox
|
||||
.stub(preferences, '_detectIsERC721')
|
||||
.returns(Promise.resolve(false));
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import sinon from 'sinon';
|
||||
import { getNetworkDisplayName } from './util';
|
||||
import NetworkController from './network';
|
||||
import NetworkController, { NETWORK_EVENTS } from './network';
|
||||
|
||||
describe('NetworkController', function () {
|
||||
describe('controller', function () {
|
||||
let networkController;
|
||||
let getLatestBlockStub;
|
||||
let setProviderTypeAndWait;
|
||||
const noop = () => undefined;
|
||||
const networkControllerProviderConfig = {
|
||||
getAccounts: noop,
|
||||
@ -13,7 +15,21 @@ describe('NetworkController', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
networkController = new NetworkController();
|
||||
getLatestBlockStub = sinon
|
||||
.stub(networkController, 'getLatestBlock')
|
||||
.callsFake(() => Promise.resolve({}));
|
||||
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 () {
|
||||
@ -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 () {
|
||||
|
@ -51,6 +51,10 @@ const defaultProviderConfig = {
|
||||
...defaultProviderConfigOpts,
|
||||
};
|
||||
|
||||
const defaultNetworkDetailsState = {
|
||||
EIPS: { 1559: undefined },
|
||||
};
|
||||
|
||||
export const NETWORK_EVENTS = {
|
||||
// Fired after the actively selected network is changed
|
||||
NETWORK_DID_CHANGE: 'networkDidChange',
|
||||
@ -74,10 +78,21 @@ export default class NetworkController extends EventEmitter {
|
||||
this.providerStore.getState(),
|
||||
);
|
||||
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({
|
||||
provider: this.providerStore,
|
||||
previousProviderStore: this.previousProviderStore,
|
||||
network: this.networkStore,
|
||||
networkDetails: this.networkDetails,
|
||||
});
|
||||
|
||||
// provider and block tracker
|
||||
@ -120,6 +135,42 @@ export default class NetworkController extends EventEmitter {
|
||||
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() {
|
||||
// Check network when restoring connectivity:
|
||||
if (this.isNetworkLoading()) {
|
||||
@ -135,6 +186,26 @@ export default class NetworkController extends EventEmitter {
|
||||
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() {
|
||||
return this.getNetworkState() === 'loading';
|
||||
}
|
||||
@ -154,6 +225,8 @@ export default class NetworkController extends EventEmitter {
|
||||
'NetworkController - lookupNetwork aborted due to missing chainId',
|
||||
);
|
||||
this.setNetworkState('loading');
|
||||
// keep network details in sync with network state
|
||||
this.clearNetworkDetails();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -174,10 +247,14 @@ export default class NetworkController extends EventEmitter {
|
||||
if (initialNetwork === currentNetwork) {
|
||||
if (err) {
|
||||
this.setNetworkState('loading');
|
||||
// keep network details in sync with network state
|
||||
this.clearNetworkDetails();
|
||||
return;
|
||||
}
|
||||
|
||||
this.setNetworkState(networkVersion);
|
||||
// look up EIP-1559 support
|
||||
this.getEIP1559Compatibility();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -298,9 +375,15 @@ export default class NetworkController extends EventEmitter {
|
||||
}
|
||||
|
||||
_switchNetwork(opts) {
|
||||
// Indicate to subscribers that network is about to change
|
||||
this.emit(NETWORK_EVENTS.NETWORK_WILL_CHANGE);
|
||||
// Set loading state
|
||||
this.setNetworkState('loading');
|
||||
// Reset network details
|
||||
this.clearNetworkDetails();
|
||||
// Configure the provider appropriately
|
||||
this._configureProvider(opts);
|
||||
// Notify subscribers that network has changed
|
||||
this.emit(NETWORK_EVENTS.NETWORK_DID_CHANGE, opts.type);
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,9 @@ describe('preferences controller', function () {
|
||||
network.initializeProvider(networkControllerProviderConfig);
|
||||
provider = network.getProviderAndBlockTracker().provider;
|
||||
|
||||
sandbox
|
||||
.stub(network, 'getLatestBlock')
|
||||
.callsFake(() => Promise.resolve({}));
|
||||
sandbox.stub(network, 'getCurrentChainId').callsFake(() => currentChainId);
|
||||
sandbox
|
||||
.stub(network, 'getProviderConfig')
|
||||
|
@ -21,6 +21,11 @@ const firstTimeState = {
|
||||
rpcUrl: 'http://localhost:8545',
|
||||
chainId: '0x539',
|
||||
},
|
||||
networkDetails: {
|
||||
EIPS: {
|
||||
1559: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -238,3 +238,7 @@ export function getSendToAccounts(state) {
|
||||
export function getUnapprovedTxs(state) {
|
||||
return state.metamask.unapprovedTxs;
|
||||
}
|
||||
|
||||
export function isEIP1559Network(state) {
|
||||
return state.metamask.networkDetails.EIPS[1559] === true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user