mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Adding user setting option for EIP-1559 V2 (#13242)
This commit is contained in:
parent
14704917c6
commit
88faef7e19
@ -933,6 +933,22 @@
|
|||||||
"enableAutoDetect": {
|
"enableAutoDetect": {
|
||||||
"message": " Enable Autodetect"
|
"message": " Enable Autodetect"
|
||||||
},
|
},
|
||||||
|
"enableEIP1559V2": {
|
||||||
|
"message": "Enable Enhanced Gas Fee UI"
|
||||||
|
},
|
||||||
|
"enableEIP1559V2AlertMessage": {
|
||||||
|
"message": "We've updated how gas fee estimation and customization works."
|
||||||
|
},
|
||||||
|
"enableEIP1559V2ButtonText": {
|
||||||
|
"message": "Turn on Enhanced Gas Fee UI in Settings"
|
||||||
|
},
|
||||||
|
"enableEIP1559V2Description": {
|
||||||
|
"message": "We've updated how gas estimation and customization works. Turn on if you'd like to use the new gas experience. $1",
|
||||||
|
"description": "$1 here is Learn More link"
|
||||||
|
},
|
||||||
|
"enableEIP1559V2Header": {
|
||||||
|
"message": "New gas experience"
|
||||||
|
},
|
||||||
"enableFromSettings": {
|
"enableFromSettings": {
|
||||||
"message": " Enable it from Settings."
|
"message": " Enable it from Settings."
|
||||||
},
|
},
|
||||||
|
@ -31,6 +31,7 @@ export default class AppStateController extends EventEmitter {
|
|||||||
recoveryPhraseReminderHasBeenShown: false,
|
recoveryPhraseReminderHasBeenShown: false,
|
||||||
recoveryPhraseReminderLastShown: new Date().getTime(),
|
recoveryPhraseReminderLastShown: new Date().getTime(),
|
||||||
collectiblesDetectionNoticeDismissed: false,
|
collectiblesDetectionNoticeDismissed: false,
|
||||||
|
enableEIP1559V2NoticeDismissed: false,
|
||||||
showTestnetMessageInDropdown: true,
|
showTestnetMessageInDropdown: true,
|
||||||
trezorModel: null,
|
trezorModel: null,
|
||||||
...initState,
|
...initState,
|
||||||
@ -270,4 +271,15 @@ export default class AppStateController extends EventEmitter {
|
|||||||
collectiblesDetectionNoticeDismissed,
|
collectiblesDetectionNoticeDismissed,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A setter for the `enableEIP1559V2NoticeDismissed` property
|
||||||
|
*
|
||||||
|
* @param enableEIP1559V2NoticeDismissed
|
||||||
|
*/
|
||||||
|
setEnableEIP1559V2NoticeDismissed(enableEIP1559V2NoticeDismissed) {
|
||||||
|
this.store.updateState({
|
||||||
|
enableEIP1559V2NoticeDismissed,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,6 +167,15 @@ export default class PreferencesController {
|
|||||||
this.store.updateState({ advancedGasFee: val });
|
this.store.updateState({ advancedGasFee: val });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for the `eip1559V2Enabled` property
|
||||||
|
*
|
||||||
|
* @param {object} val - holds the eip1559V2Enabled that the user set as experimental settings.
|
||||||
|
*/
|
||||||
|
setEIP1559V2Enabled(val) {
|
||||||
|
this.store.updateState({ eip1559V2Enabled: val });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add new methodData to state, to avoid requesting this information again through Infura
|
* Add new methodData to state, to avoid requesting this information again through Infura
|
||||||
*
|
*
|
||||||
|
@ -441,7 +441,8 @@ export default class TransactionController extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (eip1559Compatibility) {
|
if (eip1559Compatibility) {
|
||||||
if (process.env.EIP_1559_V2 && Boolean(advancedGasFeeDefaultValues)) {
|
const { eip1559V2Enabled } = this.preferencesStore.getState();
|
||||||
|
if (eip1559V2Enabled && Boolean(advancedGasFeeDefaultValues)) {
|
||||||
txMeta.userFeeLevel = CUSTOM_GAS_ESTIMATE;
|
txMeta.userFeeLevel = CUSTOM_GAS_ESTIMATE;
|
||||||
txMeta.txParams.maxFeePerGas = decGWEIToHexWEI(
|
txMeta.txParams.maxFeePerGas = decGWEIToHexWEI(
|
||||||
advancedGasFeeDefaultValues.maxBaseFee,
|
advancedGasFeeDefaultValues.maxBaseFee,
|
||||||
@ -458,7 +459,7 @@ export default class TransactionController extends EventEmitter {
|
|||||||
// then we set maxFeePerGas and maxPriorityFeePerGas to the suggested gasPrice.
|
// then we set maxFeePerGas and maxPriorityFeePerGas to the suggested gasPrice.
|
||||||
txMeta.txParams.maxFeePerGas = txMeta.txParams.gasPrice;
|
txMeta.txParams.maxFeePerGas = txMeta.txParams.gasPrice;
|
||||||
txMeta.txParams.maxPriorityFeePerGas = txMeta.txParams.gasPrice;
|
txMeta.txParams.maxPriorityFeePerGas = txMeta.txParams.gasPrice;
|
||||||
if (process.env.EIP_1559_V2) {
|
if (eip1559V2Enabled) {
|
||||||
txMeta.userFeeLevel = PRIORITY_LEVELS.DAPP_SUGGESTED;
|
txMeta.userFeeLevel = PRIORITY_LEVELS.DAPP_SUGGESTED;
|
||||||
} else {
|
} else {
|
||||||
txMeta.userFeeLevel = CUSTOM_GAS_ESTIMATE;
|
txMeta.userFeeLevel = CUSTOM_GAS_ESTIMATE;
|
||||||
@ -472,7 +473,7 @@ export default class TransactionController extends EventEmitter {
|
|||||||
txMeta.origin === 'metamask'
|
txMeta.origin === 'metamask'
|
||||||
) {
|
) {
|
||||||
txMeta.userFeeLevel = GAS_RECOMMENDATIONS.MEDIUM;
|
txMeta.userFeeLevel = GAS_RECOMMENDATIONS.MEDIUM;
|
||||||
} else if (process.env.EIP_1559_V2) {
|
} else if (eip1559V2Enabled) {
|
||||||
txMeta.userFeeLevel = PRIORITY_LEVELS.DAPP_SUGGESTED;
|
txMeta.userFeeLevel = PRIORITY_LEVELS.DAPP_SUGGESTED;
|
||||||
} else {
|
} else {
|
||||||
txMeta.userFeeLevel = CUSTOM_GAS_ESTIMATE;
|
txMeta.userFeeLevel = CUSTOM_GAS_ESTIMATE;
|
||||||
|
@ -1188,6 +1188,9 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
setAdvancedGasFee: preferencesController.setAdvancedGasFee.bind(
|
setAdvancedGasFee: preferencesController.setAdvancedGasFee.bind(
|
||||||
preferencesController,
|
preferencesController,
|
||||||
),
|
),
|
||||||
|
setEIP1559V2Enabled: preferencesController.setEIP1559V2Enabled.bind(
|
||||||
|
preferencesController,
|
||||||
|
),
|
||||||
|
|
||||||
// CollectiblesController
|
// CollectiblesController
|
||||||
addCollectible: collectiblesController.addCollectible.bind(
|
addCollectible: collectiblesController.addCollectible.bind(
|
||||||
@ -1246,6 +1249,9 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
setCollectiblesDetectionNoticeDismissed: appStateController.setCollectiblesDetectionNoticeDismissed.bind(
|
setCollectiblesDetectionNoticeDismissed: appStateController.setCollectiblesDetectionNoticeDismissed.bind(
|
||||||
appStateController,
|
appStateController,
|
||||||
),
|
),
|
||||||
|
setEnableEIP1559V2NoticeDismissed: appStateController.setEnableEIP1559V2NoticeDismissed.bind(
|
||||||
|
appStateController,
|
||||||
|
),
|
||||||
// EnsController
|
// EnsController
|
||||||
tryReverseResolveAddress: ensController.reverseResolveAddress.bind(
|
tryReverseResolveAddress: ensController.reverseResolveAddress.bind(
|
||||||
ensController,
|
ensController,
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
@import 'asset-list-item/asset-list-item';
|
@import 'asset-list-item/asset-list-item';
|
||||||
@import 'cancel-speedup-popover/index';
|
@import 'cancel-speedup-popover/index';
|
||||||
@import 'confirm-page-container/index';
|
@import 'confirm-page-container/index';
|
||||||
|
@import 'confirm-page-container/enableEIP1559V2-notice';
|
||||||
@import 'collectibles-items/index';
|
@import 'collectibles-items/index';
|
||||||
@import 'collectibles-tab/index';
|
@import 'collectibles-tab/index';
|
||||||
@import 'collectible-details/index';
|
@import 'collectible-details/index';
|
||||||
|
@ -11,6 +11,7 @@ describe('Confirm Page Container Content', () => {
|
|||||||
provider: {
|
provider: {
|
||||||
type: 'test',
|
type: 'test',
|
||||||
},
|
},
|
||||||
|
eip1559V2Enabled: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -41,8 +42,6 @@ describe('Confirm Page Container Content', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('render ConfirmPageContainer component with simulation error', async () => {
|
it('render ConfirmPageContainer component with simulation error', async () => {
|
||||||
process.env.EIP_1559_V2 = false;
|
|
||||||
|
|
||||||
const { queryByText, getByText } = renderWithProvider(
|
const { queryByText, getByText } = renderWithProvider(
|
||||||
<ConfirmPageContainerContent {...props} />,
|
<ConfirmPageContainerContent {...props} />,
|
||||||
store,
|
store,
|
||||||
|
@ -16,6 +16,7 @@ import AdvancedGasFeePopover from '../advanced-gas-fee-popover';
|
|||||||
import EditGasFeePopover from '../edit-gas-fee-popover/edit-gas-fee-popover';
|
import EditGasFeePopover from '../edit-gas-fee-popover/edit-gas-fee-popover';
|
||||||
import EditGasPopover from '../edit-gas-popover';
|
import EditGasPopover from '../edit-gas-popover';
|
||||||
|
|
||||||
|
import EnableEIP1559V2Notice from './enableEIP1559V2-notice';
|
||||||
import {
|
import {
|
||||||
ConfirmPageContainerHeader,
|
ConfirmPageContainerHeader,
|
||||||
ConfirmPageContainerContent,
|
ConfirmPageContainerContent,
|
||||||
@ -204,6 +205,7 @@ export default class ConfirmPageContainer extends Component {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<EnableEIP1559V2Notice isFirstAlert={!showAddToAddressDialog} />
|
||||||
{contentComponent || (
|
{contentComponent || (
|
||||||
<ConfirmPageContainerContent
|
<ConfirmPageContainerContent
|
||||||
action={action}
|
action={action}
|
||||||
|
@ -0,0 +1,94 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useHistory } from 'react-router-dom';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
|
import Box from '../../../ui/box';
|
||||||
|
import Dialog from '../../../ui/dialog';
|
||||||
|
import Typography from '../../../ui/typography/typography';
|
||||||
|
import {
|
||||||
|
COLORS,
|
||||||
|
TYPOGRAPHY,
|
||||||
|
TEXT_ALIGN,
|
||||||
|
FONT_WEIGHT,
|
||||||
|
DISPLAY,
|
||||||
|
} from '../../../../helpers/constants/design-system';
|
||||||
|
import { useI18nContext } from '../../../../hooks/useI18nContext';
|
||||||
|
import Button from '../../../ui/button';
|
||||||
|
import { EXPERIMENTAL_ROUTE } from '../../../../helpers/constants/routes';
|
||||||
|
import { setEnableEIP1559V2NoticeDismissed } from '../../../../store/actions';
|
||||||
|
import { getEnableEIP1559V2NoticeDismissed } from '../../../../ducks/metamask/metamask';
|
||||||
|
import { getEIP1559V2Enabled } from '../../../../selectors';
|
||||||
|
|
||||||
|
const EIP_1559_V2_ENABLED =
|
||||||
|
// This is a string in unit tests but is a boolean in the browser
|
||||||
|
process.env.EIP_1559_V2 === true || process.env.EIP_1559_V2 === 'true';
|
||||||
|
|
||||||
|
export default function EnableEIP1559V2Notice({ isFirstAlert }) {
|
||||||
|
const t = useI18nContext();
|
||||||
|
const history = useHistory();
|
||||||
|
const enableEIP1559V2NoticeDismissed = useSelector(
|
||||||
|
getEnableEIP1559V2NoticeDismissed,
|
||||||
|
);
|
||||||
|
const eip1559V2Enabled = useSelector(getEIP1559V2Enabled);
|
||||||
|
|
||||||
|
if (
|
||||||
|
!EIP_1559_V2_ENABLED ||
|
||||||
|
eip1559V2Enabled ||
|
||||||
|
enableEIP1559V2NoticeDismissed
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
margin={[0, 4, 4, 4]}
|
||||||
|
marginTop={isFirstAlert ? 4 : 0}
|
||||||
|
className="enableEIP1559V2-notice"
|
||||||
|
>
|
||||||
|
<Dialog type="message" className="enableEIP1559V2-notice__dialog">
|
||||||
|
<button
|
||||||
|
onClick={setEnableEIP1559V2NoticeDismissed}
|
||||||
|
className="enableEIP1559V2-notice__close-button"
|
||||||
|
data-testid="enableEIP1559V2-notice-close"
|
||||||
|
/>
|
||||||
|
<Box display={DISPLAY.FLEX}>
|
||||||
|
<Box paddingTop={2}>
|
||||||
|
<i style={{ fontSize: '1rem' }} className="fa fa-info-circle" />
|
||||||
|
</Box>
|
||||||
|
<Box paddingLeft={4}>
|
||||||
|
<Typography
|
||||||
|
color={COLORS.BLACK}
|
||||||
|
align={TEXT_ALIGN.LEFT}
|
||||||
|
variant={TYPOGRAPHY.H7}
|
||||||
|
fontWeight={FONT_WEIGHT.BOLD}
|
||||||
|
>
|
||||||
|
{t('enableEIP1559V2Header')}
|
||||||
|
</Typography>
|
||||||
|
<Typography
|
||||||
|
color={COLORS.BLACK}
|
||||||
|
align={TEXT_ALIGN.LEFT}
|
||||||
|
variant={TYPOGRAPHY.H7}
|
||||||
|
boxProps={{ marginBottom: 2 }}
|
||||||
|
>
|
||||||
|
{t('enableEIP1559V2AlertMessage')}
|
||||||
|
</Typography>
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
onClick={() => {
|
||||||
|
history.push(EXPERIMENTAL_ROUTE);
|
||||||
|
}}
|
||||||
|
className="enableEIP1559V2-notice__link"
|
||||||
|
>
|
||||||
|
{t('enableEIP1559V2ButtonText')}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Dialog>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnableEIP1559V2Notice.propTypes = {
|
||||||
|
isFirstAlert: PropTypes.bool,
|
||||||
|
};
|
@ -0,0 +1 @@
|
|||||||
|
export { default } from './enableEIP1559V2-notice';
|
@ -0,0 +1,33 @@
|
|||||||
|
.enableEIP1559V2-notice {
|
||||||
|
&__dialog {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__close-button {
|
||||||
|
background-color: transparent;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
position: absolute;
|
||||||
|
content: '\00D7';
|
||||||
|
font-size: 29px;
|
||||||
|
font-weight: 200;
|
||||||
|
color: var(--black);
|
||||||
|
background-color: transparent;
|
||||||
|
top: 0;
|
||||||
|
right: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.enableEIP1559V2-notice__link {
|
||||||
|
@include H7;
|
||||||
|
|
||||||
|
padding: 0;
|
||||||
|
justify-content: flex-start;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,7 @@ const render = ({ componentProps, contextProps } = {}) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
gasFeeEstimates: mockEstimates[GAS_ESTIMATE_TYPES.FEE_MARKET],
|
gasFeeEstimates: mockEstimates[GAS_ESTIMATE_TYPES.FEE_MARKET],
|
||||||
|
eip1559V2Enabled: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -47,14 +48,6 @@ const render = ({ componentProps, contextProps } = {}) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
describe('EditGasFeeButton', () => {
|
describe('EditGasFeeButton', () => {
|
||||||
beforeEach(() => {
|
|
||||||
process.env.EIP_1559_V2 = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
process.env.EIP_1559_V2 = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render edit link with text low if low gas estimates are selected', () => {
|
it('should render edit link with text low if low gas estimates are selected', () => {
|
||||||
render({ contextProps: { transaction: { userFeeLevel: 'low' } } });
|
render({ contextProps: { transaction: { userFeeLevel: 'low' } } });
|
||||||
expect(screen.queryByText('🐢')).toBeInTheDocument();
|
expect(screen.queryByText('🐢')).toBeInTheDocument();
|
||||||
|
@ -31,6 +31,7 @@ const render = ({ componentProps, contextProps } = {}) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
gasFeeEstimates: mockEstimates[GAS_ESTIMATE_TYPES.FEE_MARKET],
|
gasFeeEstimates: mockEstimates[GAS_ESTIMATE_TYPES.FEE_MARKET],
|
||||||
|
eip1559V2Enabled: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -50,14 +51,6 @@ const render = ({ componentProps, contextProps } = {}) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
describe('TransactionDetail', () => {
|
describe('TransactionDetail', () => {
|
||||||
beforeEach(() => {
|
|
||||||
process.env.EIP_1559_V2 = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
process.env.EIP_1559_V2 = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render edit link with text low if low gas estimates are selected', () => {
|
it('should render edit link with text low if low gas estimates are selected', () => {
|
||||||
render({ contextProps: { transaction: { userFeeLevel: 'low' } } });
|
render({ contextProps: { transaction: { userFeeLevel: 'low' } } });
|
||||||
expect(screen.queryByText('🐢')).toBeInTheDocument();
|
expect(screen.queryByText('🐢')).toBeInTheDocument();
|
||||||
|
@ -26,7 +26,10 @@ import {
|
|||||||
TransactionModalContextProvider,
|
TransactionModalContextProvider,
|
||||||
useTransactionModalContext,
|
useTransactionModalContext,
|
||||||
} from '../../../contexts/transaction-modal';
|
} from '../../../contexts/transaction-modal';
|
||||||
import { checkNetworkAndAccountSupports1559 } from '../../../selectors';
|
import {
|
||||||
|
checkNetworkAndAccountSupports1559,
|
||||||
|
getEIP1559V2Enabled,
|
||||||
|
} from '../../../selectors';
|
||||||
import { isLegacyTransaction } from '../../../helpers/utils/transactions.util';
|
import { isLegacyTransaction } from '../../../helpers/utils/transactions.util';
|
||||||
import { useMetricEvent } from '../../../hooks/useMetricEvent';
|
import { useMetricEvent } from '../../../hooks/useMetricEvent';
|
||||||
import Button from '../../ui/button';
|
import Button from '../../ui/button';
|
||||||
@ -280,14 +283,13 @@ const TransactionListItem = (props) => {
|
|||||||
const { transactionGroup } = props;
|
const { transactionGroup } = props;
|
||||||
const [editGasMode, setEditGasMode] = useState();
|
const [editGasMode, setEditGasMode] = useState();
|
||||||
const transaction = transactionGroup.primaryTransaction;
|
const transaction = transactionGroup.primaryTransaction;
|
||||||
const EIP_1559_V2_ENABLED =
|
const eip1559V2Enabled = useSelector(getEIP1559V2Enabled);
|
||||||
process.env.EIP_1559_V2 === true || process.env.EIP_1559_V2 === 'true';
|
|
||||||
|
|
||||||
const supportsEIP1559 =
|
const supportsEIP1559 =
|
||||||
useSelector(checkNetworkAndAccountSupports1559) &&
|
useSelector(checkNetworkAndAccountSupports1559) &&
|
||||||
!isLegacyTransaction(transaction?.txParams);
|
!isLegacyTransaction(transaction?.txParams);
|
||||||
|
|
||||||
const supportsEIP1559V2 = EIP_1559_V2_ENABLED && supportsEIP1559;
|
const supportsEIP1559V2 = eip1559V2Enabled && supportsEIP1559;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GasFeeContextProvider
|
<GasFeeContextProvider
|
||||||
|
@ -264,6 +264,10 @@ export function getCollectiblesDetectionNoticeDismissed(state) {
|
|||||||
return state.metamask.collectiblesDetectionNoticeDismissed;
|
return state.metamask.collectiblesDetectionNoticeDismissed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getEnableEIP1559V2NoticeDismissed(state) {
|
||||||
|
return state.metamask.enableEIP1559V2NoticeDismissed;
|
||||||
|
}
|
||||||
|
|
||||||
export const getCollectibles = (state) => {
|
export const getCollectibles = (state) => {
|
||||||
const {
|
const {
|
||||||
metamask: {
|
metamask: {
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
checkNetworkAndAccountSupports1559,
|
checkNetworkAndAccountSupports1559,
|
||||||
getCurrentCurrency,
|
getCurrentCurrency,
|
||||||
|
getEIP1559V2Enabled,
|
||||||
getSelectedAccount,
|
getSelectedAccount,
|
||||||
getShouldShowFiat,
|
getShouldShowFiat,
|
||||||
getPreferences,
|
getPreferences,
|
||||||
@ -96,6 +97,7 @@ export const HIGH_FEE_MARKET_ESTIMATE_RETURN_VALUE = {
|
|||||||
export const generateUseSelectorRouter = ({
|
export const generateUseSelectorRouter = ({
|
||||||
checkNetworkAndAccountSupports1559Response,
|
checkNetworkAndAccountSupports1559Response,
|
||||||
shouldShowFiat = true,
|
shouldShowFiat = true,
|
||||||
|
eip1559V2Enabled = false,
|
||||||
} = {}) => (selector) => {
|
} = {}) => (selector) => {
|
||||||
if (selector === getConversionRate) {
|
if (selector === getConversionRate) {
|
||||||
return MOCK_ETH_USD_CONVERSION_RATE;
|
return MOCK_ETH_USD_CONVERSION_RATE;
|
||||||
@ -135,6 +137,9 @@ export const generateUseSelectorRouter = ({
|
|||||||
if (selector === checkNetworkAndAccountSupports1559) {
|
if (selector === checkNetworkAndAccountSupports1559) {
|
||||||
return checkNetworkAndAccountSupports1559Response;
|
return checkNetworkAndAccountSupports1559Response;
|
||||||
}
|
}
|
||||||
|
if (selector === getEIP1559V2Enabled) {
|
||||||
|
return eip1559V2Enabled;
|
||||||
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import { GAS_FORM_ERRORS } from '../../helpers/constants/gas';
|
|||||||
import {
|
import {
|
||||||
checkNetworkAndAccountSupports1559,
|
checkNetworkAndAccountSupports1559,
|
||||||
getAdvancedInlineGasShown,
|
getAdvancedInlineGasShown,
|
||||||
|
getEIP1559V2Enabled,
|
||||||
} from '../../selectors';
|
} from '../../selectors';
|
||||||
import { hexToDecimal } from '../../helpers/utils/conversions.util';
|
import { hexToDecimal } from '../../helpers/utils/conversions.util';
|
||||||
import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
|
import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
|
||||||
@ -93,15 +94,13 @@ export function useGasFeeInputs(
|
|||||||
minimumGasLimit = '0x5208',
|
minimumGasLimit = '0x5208',
|
||||||
editGasMode = EDIT_GAS_MODES.MODIFY_IN_PLACE,
|
editGasMode = EDIT_GAS_MODES.MODIFY_IN_PLACE,
|
||||||
) {
|
) {
|
||||||
const EIP_1559_V2_ENABLED =
|
const eip1559V2Enabled = useSelector(getEIP1559V2Enabled);
|
||||||
// This is a string in unit tests but is a boolean in the browser
|
|
||||||
process.env.EIP_1559_V2 === true || process.env.EIP_1559_V2 === 'true';
|
|
||||||
|
|
||||||
const supportsEIP1559 =
|
const supportsEIP1559 =
|
||||||
useSelector(checkNetworkAndAccountSupports1559) &&
|
useSelector(checkNetworkAndAccountSupports1559) &&
|
||||||
!isLegacyTransaction(transaction?.txParams);
|
!isLegacyTransaction(transaction?.txParams);
|
||||||
|
|
||||||
const supportsEIP1559V2 = supportsEIP1559 && EIP_1559_V2_ENABLED;
|
const supportsEIP1559V2 = supportsEIP1559 && eip1559V2Enabled;
|
||||||
|
|
||||||
// We need the gas estimates from the GasFeeController in the background.
|
// We need the gas estimates from the GasFeeController in the background.
|
||||||
// Calling this hooks initiates polling for new gas estimates and returns the
|
// Calling this hooks initiates polling for new gas estimates and returns the
|
||||||
|
@ -324,13 +324,9 @@ describe('useGasFeeInputs', () => {
|
|||||||
useSelector.mockImplementation(
|
useSelector.mockImplementation(
|
||||||
generateUseSelectorRouter({
|
generateUseSelectorRouter({
|
||||||
checkNetworkAndAccountSupports1559Response: true,
|
checkNetworkAndAccountSupports1559Response: true,
|
||||||
|
eip1559V2Enabled: true,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
process.env.EIP_1559_V2 = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
process.env.EIP_1559_V2 = false;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('return true for fee_market transaction type', () => {
|
it('return true for fee_market transaction type', () => {
|
||||||
|
@ -35,6 +35,7 @@ import {
|
|||||||
getRpcPrefsForCurrentProvider,
|
getRpcPrefsForCurrentProvider,
|
||||||
getIsMultiLayerFeeNetwork,
|
getIsMultiLayerFeeNetwork,
|
||||||
checkNetworkAndAccountSupports1559,
|
checkNetworkAndAccountSupports1559,
|
||||||
|
getEIP1559V2Enabled,
|
||||||
} from '../../selectors';
|
} from '../../selectors';
|
||||||
import { useApproveTransaction } from '../../hooks/useApproveTransaction';
|
import { useApproveTransaction } from '../../hooks/useApproveTransaction';
|
||||||
import { currentNetworkTxListSelector } from '../../selectors/transactions';
|
import { currentNetworkTxListSelector } from '../../selectors/transactions';
|
||||||
@ -50,10 +51,6 @@ const isAddressLedgerByFromAddress = (address) => (state) => {
|
|||||||
return isAddressLedger(state, address);
|
return isAddressLedger(state, address);
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line prefer-destructuring
|
|
||||||
const EIP_1559_V2_ENABLED =
|
|
||||||
process.env.EIP_1559_V2 === true || process.env.EIP_1559_V2 === 'true';
|
|
||||||
|
|
||||||
export default function ConfirmApprove() {
|
export default function ConfirmApprove() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { id: paramsTransactionId } = useParams();
|
const { id: paramsTransactionId } = useParams();
|
||||||
@ -89,8 +86,8 @@ export default function ConfirmApprove() {
|
|||||||
hexTransactionTotal,
|
hexTransactionTotal,
|
||||||
} = useSelector((state) => transactionFeeSelector(state, transaction));
|
} = useSelector((state) => transactionFeeSelector(state, transaction));
|
||||||
|
|
||||||
const supportsEIP1559V2 =
|
const eip1559V2Enabled = useSelector(getEIP1559V2Enabled);
|
||||||
EIP_1559_V2_ENABLED && networkAndAccountSupports1559;
|
const supportsEIP1559V2 = eip1559V2Enabled && networkAndAccountSupports1559;
|
||||||
|
|
||||||
const currentToken = (tokens &&
|
const currentToken = (tokens &&
|
||||||
tokens.find(({ address }) =>
|
tokens.find(({ address }) =>
|
||||||
|
@ -63,10 +63,6 @@ import { MIN_GAS_LIMIT_DEC } from '../send/send.constants';
|
|||||||
|
|
||||||
import TransactionAlerts from './transaction-alerts';
|
import TransactionAlerts from './transaction-alerts';
|
||||||
|
|
||||||
// eslint-disable-next-line prefer-destructuring
|
|
||||||
const EIP_1559_V2_ENABLED =
|
|
||||||
process.env.EIP_1559_V2 === true || process.env.EIP_1559_V2 === 'true';
|
|
||||||
|
|
||||||
const renderHeartBeatIfNotInTest = () =>
|
const renderHeartBeatIfNotInTest = () =>
|
||||||
process.env.IN_TEST ? null : <LoadingHeartBeat />;
|
process.env.IN_TEST ? null : <LoadingHeartBeat />;
|
||||||
|
|
||||||
@ -147,6 +143,7 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
supportsEIP1559: PropTypes.bool,
|
supportsEIP1559: PropTypes.bool,
|
||||||
hardwareWalletRequiresConnection: PropTypes.bool,
|
hardwareWalletRequiresConnection: PropTypes.bool,
|
||||||
isMultiLayerFeeNetwork: PropTypes.bool,
|
isMultiLayerFeeNetwork: PropTypes.bool,
|
||||||
|
eip1559V2Enabled: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -974,7 +971,7 @@ export default class ConfirmTransactionBase extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
supportsEIP1559V2 =
|
supportsEIP1559V2 =
|
||||||
EIP_1559_V2_ENABLED &&
|
this.props.eip1559V2Enabled &&
|
||||||
this.props.supportsEIP1559 &&
|
this.props.supportsEIP1559 &&
|
||||||
!isLegacyTransaction(this.props.txData);
|
!isLegacyTransaction(this.props.txData);
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ import {
|
|||||||
getUseTokenDetection,
|
getUseTokenDetection,
|
||||||
getTokenList,
|
getTokenList,
|
||||||
getIsMultiLayerFeeNetwork,
|
getIsMultiLayerFeeNetwork,
|
||||||
|
getEIP1559V2Enabled,
|
||||||
} from '../../selectors';
|
} from '../../selectors';
|
||||||
import { getMostRecentOverviewPage } from '../../ducks/history/history';
|
import { getMostRecentOverviewPage } from '../../ducks/history/history';
|
||||||
import {
|
import {
|
||||||
@ -197,6 +198,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const isMultiLayerFeeNetwork = getIsMultiLayerFeeNetwork(state);
|
const isMultiLayerFeeNetwork = getIsMultiLayerFeeNetwork(state);
|
||||||
|
const eip1559V2Enabled = getEIP1559V2Enabled(state);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
balance,
|
balance,
|
||||||
@ -248,6 +250,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
hardwareWalletRequiresConnection,
|
hardwareWalletRequiresConnection,
|
||||||
isMultiLayerFeeNetwork,
|
isMultiLayerFeeNetwork,
|
||||||
chainId,
|
chainId,
|
||||||
|
eip1559V2Enabled,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -14,7 +14,9 @@ export default class ExperimentalTab extends PureComponent {
|
|||||||
useCollectibleDetection: PropTypes.bool,
|
useCollectibleDetection: PropTypes.bool,
|
||||||
setUseCollectibleDetection: PropTypes.func,
|
setUseCollectibleDetection: PropTypes.func,
|
||||||
setOpenSeaEnabled: PropTypes.func,
|
setOpenSeaEnabled: PropTypes.func,
|
||||||
openSeaEnabled: PropTypes.func,
|
openSeaEnabled: PropTypes.bool,
|
||||||
|
eip1559V2Enabled: PropTypes.bool,
|
||||||
|
setEIP1559V2Enabled: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
renderTokenDetectionToggle() {
|
renderTokenDetectionToggle() {
|
||||||
@ -134,12 +136,63 @@ export default class ExperimentalTab extends PureComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderEIP1559V2EnabledToggle() {
|
||||||
|
const EIP_1559_V2_ENABLED =
|
||||||
|
// This is a string in unit tests but is a boolean in the browser
|
||||||
|
process.env.EIP_1559_V2 === true || process.env.EIP_1559_V2 === 'true';
|
||||||
|
if (!EIP_1559_V2_ENABLED) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const { t } = this.context;
|
||||||
|
const { eip1559V2Enabled, setEIP1559V2Enabled } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="settings-page__content-row">
|
||||||
|
<div className="settings-page__content-item">
|
||||||
|
<span>{t('enableEIP1559V2')}</span>
|
||||||
|
<div className="settings-page__content-description">
|
||||||
|
{t('enableEIP1559V2Description', [
|
||||||
|
<a
|
||||||
|
key="eip_page_link"
|
||||||
|
href="https://metamask.io/1559.html"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
{t('learnMoreUpperCase')}
|
||||||
|
</a>,
|
||||||
|
])}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="settings-page__content-item">
|
||||||
|
<div className="settings-page__content-item-col">
|
||||||
|
<ToggleButton
|
||||||
|
value={eip1559V2Enabled}
|
||||||
|
onToggle={(value) => {
|
||||||
|
this.context.metricsEvent({
|
||||||
|
eventOpts: {
|
||||||
|
category: 'Settings',
|
||||||
|
action: 'Enabled/Disable OpenSea',
|
||||||
|
name: 'Enabled/Disable OpenSea',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
setEIP1559V2Enabled(!value);
|
||||||
|
}}
|
||||||
|
offLabel={t('off')}
|
||||||
|
onLabel={t('on')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="settings-page__body">
|
<div className="settings-page__body">
|
||||||
{this.renderTokenDetectionToggle()}
|
{this.renderTokenDetectionToggle()}
|
||||||
{this.renderOpenSeaEnabledToggle()}
|
{this.renderOpenSeaEnabledToggle()}
|
||||||
{this.renderCollectibleDetectionToggle()}
|
{this.renderCollectibleDetectionToggle()}
|
||||||
|
{this.renderEIP1559V2EnabledToggle()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,13 @@ import {
|
|||||||
setUseTokenDetection,
|
setUseTokenDetection,
|
||||||
setUseCollectibleDetection,
|
setUseCollectibleDetection,
|
||||||
setOpenSeaEnabled,
|
setOpenSeaEnabled,
|
||||||
|
setEIP1559V2Enabled,
|
||||||
} from '../../../store/actions';
|
} from '../../../store/actions';
|
||||||
import {
|
import {
|
||||||
getUseTokenDetection,
|
getUseTokenDetection,
|
||||||
getUseCollectibleDetection,
|
getUseCollectibleDetection,
|
||||||
getOpenSeaEnabled,
|
getOpenSeaEnabled,
|
||||||
|
getEIP1559V2Enabled,
|
||||||
} from '../../../selectors';
|
} from '../../../selectors';
|
||||||
import ExperimentalTab from './experimental-tab.component';
|
import ExperimentalTab from './experimental-tab.component';
|
||||||
|
|
||||||
@ -18,6 +20,7 @@ const mapStateToProps = (state) => {
|
|||||||
useTokenDetection: getUseTokenDetection(state),
|
useTokenDetection: getUseTokenDetection(state),
|
||||||
useCollectibleDetection: getUseCollectibleDetection(state),
|
useCollectibleDetection: getUseCollectibleDetection(state),
|
||||||
openSeaEnabled: getOpenSeaEnabled(state),
|
openSeaEnabled: getOpenSeaEnabled(state),
|
||||||
|
eip1559V2Enabled: getEIP1559V2Enabled(state),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -27,6 +30,7 @@ const mapDispatchToProps = (dispatch) => {
|
|||||||
setUseCollectibleDetection: (val) =>
|
setUseCollectibleDetection: (val) =>
|
||||||
dispatch(setUseCollectibleDetection(val)),
|
dispatch(setUseCollectibleDetection(val)),
|
||||||
setOpenSeaEnabled: (val) => dispatch(setOpenSeaEnabled(val)),
|
setOpenSeaEnabled: (val) => dispatch(setOpenSeaEnabled(val)),
|
||||||
|
setEIP1559V2Enabled: (val) => dispatch(setEIP1559V2Enabled(val)),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -205,6 +205,10 @@
|
|||||||
|
|
||||||
color: var(--dusty-gray);
|
color: var(--dusty-gray);
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--Blue-500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__content-item-col {
|
&__content-item-col {
|
||||||
|
@ -14,6 +14,7 @@ import { MAINNET_CHAIN_ID } from '../../../../shared/constants/network';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
checkNetworkAndAccountSupports1559,
|
checkNetworkAndAccountSupports1559,
|
||||||
|
getEIP1559V2Enabled,
|
||||||
getPreferences,
|
getPreferences,
|
||||||
getSelectedAccount,
|
getSelectedAccount,
|
||||||
} from '../../../selectors';
|
} from '../../../selectors';
|
||||||
@ -133,7 +134,6 @@ describe('FeeCard', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('renders the component with EIP-1559 V2 enabled', () => {
|
it('renders the component with EIP-1559 V2 enabled', () => {
|
||||||
process.env.EIP_1559_V2 = true;
|
|
||||||
useGasFeeEstimates.mockImplementation(() => ({ gasFeeEstimates: {} }));
|
useGasFeeEstimates.mockImplementation(() => ({ gasFeeEstimates: {} }));
|
||||||
useSelector.mockImplementation((selector) => {
|
useSelector.mockImplementation((selector) => {
|
||||||
if (selector === getPreferences) {
|
if (selector === getPreferences) {
|
||||||
@ -141,6 +141,9 @@ describe('FeeCard', () => {
|
|||||||
useNativeCurrencyAsPrimaryCurrency: true,
|
useNativeCurrencyAsPrimaryCurrency: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (selector === getEIP1559V2Enabled) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (selector === getSelectedAccount) {
|
if (selector === getSelectedAccount) {
|
||||||
return {
|
return {
|
||||||
balance: '0x440aa47cc2556',
|
balance: '0x440aa47cc2556',
|
||||||
@ -180,6 +183,5 @@ describe('FeeCard', () => {
|
|||||||
expect(
|
expect(
|
||||||
document.querySelector('.fee-card__top-bordered-row'),
|
document.querySelector('.fee-card__top-bordered-row'),
|
||||||
).toMatchSnapshot();
|
).toMatchSnapshot();
|
||||||
process.env.EIP_1559_V2 = false;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -46,6 +46,7 @@ import {
|
|||||||
isHardwareWallet,
|
isHardwareWallet,
|
||||||
getHardwareWalletType,
|
getHardwareWalletType,
|
||||||
checkNetworkAndAccountSupports1559,
|
checkNetworkAndAccountSupports1559,
|
||||||
|
getEIP1559V2Enabled,
|
||||||
} from '../../../selectors';
|
} from '../../../selectors';
|
||||||
import { getNativeCurrency, getTokens } from '../../../ducks/metamask/metamask';
|
import { getNativeCurrency, getTokens } from '../../../ducks/metamask/metamask';
|
||||||
|
|
||||||
@ -103,15 +104,12 @@ import CountdownTimer from '../countdown-timer';
|
|||||||
import SwapsFooter from '../swaps-footer';
|
import SwapsFooter from '../swaps-footer';
|
||||||
import ViewQuotePriceDifference from './view-quote-price-difference';
|
import ViewQuotePriceDifference from './view-quote-price-difference';
|
||||||
|
|
||||||
// eslint-disable-next-line prefer-destructuring
|
|
||||||
const EIP_1559_V2_ENABLED =
|
|
||||||
process.env.EIP_1559_V2 === true || process.env.EIP_1559_V2 === 'true';
|
|
||||||
|
|
||||||
export default function ViewQuote() {
|
export default function ViewQuote() {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const t = useContext(I18nContext);
|
const t = useContext(I18nContext);
|
||||||
const metaMetricsEvent = useContext(MetaMetricsContext);
|
const metaMetricsEvent = useContext(MetaMetricsContext);
|
||||||
|
const eip1559V2Enabled = useSelector(getEIP1559V2Enabled);
|
||||||
|
|
||||||
const [dispatchedSafeRefetch, setDispatchedSafeRefetch] = useState(false);
|
const [dispatchedSafeRefetch, setDispatchedSafeRefetch] = useState(false);
|
||||||
const [submitClicked, setSubmitClicked] = useState(false);
|
const [submitClicked, setSubmitClicked] = useState(false);
|
||||||
@ -689,8 +687,7 @@ export default function ViewQuote() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const supportsEIP1559V2 =
|
const supportsEIP1559V2 = eip1559V2Enabled && networkAndAccountSupports1559;
|
||||||
EIP_1559_V2_ENABLED && networkAndAccountSupports1559;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GasFeeContextProvider
|
<GasFeeContextProvider
|
||||||
|
@ -816,6 +816,10 @@ export function getAdvancedGasFeeValues(state) {
|
|||||||
return state.metamask.advancedGasFee;
|
return state.metamask.advancedGasFee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getEIP1559V2Enabled(state) {
|
||||||
|
return state.metamask.eip1559V2Enabled;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To check if the user has set advanced gas fee settings as default with a non empty maxBaseFee and priotityFee.
|
* To check if the user has set advanced gas fee settings as default with a non empty maxBaseFee and priotityFee.
|
||||||
*
|
*
|
||||||
|
@ -2256,6 +2256,18 @@ export function setAdvancedGasFee(val) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setEIP1559V2Enabled(val) {
|
||||||
|
return async (dispatch) => {
|
||||||
|
dispatch(showLoadingIndication());
|
||||||
|
log.debug(`background.setEIP1559V2Enabled`);
|
||||||
|
try {
|
||||||
|
await promisifiedBackground.setEIP1559V2Enabled(val);
|
||||||
|
} finally {
|
||||||
|
dispatch(hideLoadingIndication());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function setIpfsGateway(val) {
|
export function setIpfsGateway(val) {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
dispatch(showLoadingIndication());
|
dispatch(showLoadingIndication());
|
||||||
@ -3100,6 +3112,10 @@ export function setCollectiblesDetectionNoticeDismissed() {
|
|||||||
return promisifiedBackground.setCollectiblesDetectionNoticeDismissed(true);
|
return promisifiedBackground.setCollectiblesDetectionNoticeDismissed(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setEnableEIP1559V2NoticeDismissed() {
|
||||||
|
return promisifiedBackground.setEnableEIP1559V2NoticeDismissed(true);
|
||||||
|
}
|
||||||
|
|
||||||
// QR Hardware Wallets
|
// QR Hardware Wallets
|
||||||
export async function submitQRHardwareCryptoHDKey(cbor) {
|
export async function submitQRHardwareCryptoHDKey(cbor) {
|
||||||
await promisifiedBackground.submitQRHardwareCryptoHDKey(cbor);
|
await promisifiedBackground.submitQRHardwareCryptoHDKey(cbor);
|
||||||
|
Loading…
Reference in New Issue
Block a user