diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9b657fd1158..2688a9e67bb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,55 @@
## Current Main Branch
+## 7.2.0 - Jun 05, 2023
+### Added
+- [#6632](https://github.com/MetaMask/metamask-mobile/pull/6632): feat: add linea mainnet alert message
+- [#6496](https://github.com/MetaMask/metamask-mobile/pull/6496): feat(551): add Linea Mainnet
+- [#6494](https://github.com/MetaMask/metamask-mobile/pull/6494): feat: Update banner component to show/hide details section
+- [#6539](https://github.com/MetaMask/metamask-mobile/pull/6539): feat: [MC 0.5] Remove drawer and add remain options to settings tab
+- [#6378](https://github.com/MetaMask/metamask-mobile/pull/6378): feat: Add eth_sign friction
+- [#6534](https://github.com/MetaMask/metamask-mobile/pull/6534): feat(action): remove labels after issue closed
+- [#6570](https://github.com/MetaMask/metamask-mobile/pull/6570): feat: Translations for the disconnected account toast
+- [#6452](https://github.com/MetaMask/metamask-mobile/pull/6452): feat: [MC 0.5] - Add Account management actions
+- [#5591](https://github.com/MetaMask/metamask-mobile/pull/5591): feat: Custom Spend Allowance
+- [#6426](https://github.com/MetaMask/metamask-mobile/pull/6426): feat: Componentize ListItem
+- [#6514](https://github.com/MetaMask/metamask-mobile/pull/6514): feat: Componentize BottomSheetFooter
+- [#6466](https://github.com/MetaMask/metamask-mobile/pull/6466): feat: componentize BottomSheetHeader
+- [#6294](https://github.com/MetaMask/metamask-mobile/pull/6294): feat: [MC 0.5] - Activity view and Settings on the tab bar
+- [#6486](https://github.com/MetaMask/metamask-mobile/pull/6486): feat: Add disabled prop on base button
+
+### Changed
+- [#6612](https://github.com/MetaMask/metamask-mobile/pull/6612): chore: approve txn when gas estimation ready
+- [#6054](https://github.com/MetaMask/metamask-mobile/pull/6054): chore: Improve TagURL
+- [#6520](https://github.com/MetaMask/metamask-mobile/pull/6520): chore: improve variable name
+- [#6597](https://github.com/MetaMask/metamask-mobile/pull/6597): chore: rm unused prepareFullTransaction
+- [#6291](https://github.com/MetaMask/metamask-mobile/pull/6291): refactor: trigger transaction modals using approval requests
+- [#5751](https://github.com/MetaMask/metamask-mobile/pull/5751): chore: Keystone links
+- [#6541](https://github.com/MetaMask/metamask-mobile/pull/6541): chore: Delete an unused hook
+- [#6530](https://github.com/MetaMask/metamask-mobile/pull/6530): chore: pending review feedback for token details related changes
+- [#6401](https://github.com/MetaMask/metamask-mobile/pull/6401): refactor: handle watch asset accept and reject using ApprovalController only
+- [#6529](https://github.com/MetaMask/metamask-mobile/pull/6529): chore: adding english string for advanced settings eth_sign warning
+- [#6026](https://github.com/MetaMask/metamask-mobile/pull/6026): chore: Add toggle to enable/disable multi account balances fetching
+- [#6512](https://github.com/MetaMask/metamask-mobile/pull/6512): chore: upgrade to cocoapods 1.12.0
+- [#6487](https://github.com/MetaMask/metamask-mobile/pull/6487): chore: new Show test networks translation
+- [#6357](https://github.com/MetaMask/metamask-mobile/pull/6357): refactor: use approval controller for watch asset confirmation
+
+### Fixed
+- [#6549](https://github.com/MetaMask/metamask-mobile/pull/6549): fix: Networks text alignement
+- [#6634](https://github.com/MetaMask/metamask-mobile/pull/6634): fix: disable next button if custom input is invalid
+- [#6491](https://github.com/MetaMask/metamask-mobile/pull/6491): fix: refactor linea testnet implementation
+- [#6358](https://github.com/MetaMask/metamask-mobile/pull/6358): fix: No Warning appears when a Dapp sets a really high Fees for a tx, potentially loosing all user funds
+- [#6592](https://github.com/MetaMask/metamask-mobile/pull/6592): fix: Nonce too low error on Approve ERC20 and ERC721 transactions
+- [#6577](https://github.com/MetaMask/metamask-mobile/pull/6577): fix: onBoarding wizard horizontal alignment on step1 and on browser step
+- [#6598](https://github.com/MetaMask/metamask-mobile/pull/6598): fix: Hold to reveal Spanish copy
+- [#6523](https://github.com/MetaMask/metamask-mobile/pull/6523): fix: Network logo to represent first letter of network
+- [#6560](https://github.com/MetaMask/metamask-mobile/pull/6560): fix: asset page header transition
+- [#6473](https://github.com/MetaMask/metamask-mobile/pull/6473): fix: fix for swaps button displaying on unsupported networks
+- [#6464](https://github.com/MetaMask/metamask-mobile/pull/6464): fix: bug domain not shown on signature
+- [#6517](https://github.com/MetaMask/metamask-mobile/pull/6517): fix: remove duplicate ganache steps definitions
+- [#6299](https://github.com/MetaMask/metamask-mobile/pull/6299): fix: for from address balance shown for ERC20 transfers
+- [#6471](https://github.com/MetaMask/metamask-mobile/pull/6471): fix: Approve default ERC20
+
## 7.1.0 - Jun 20, 2023
- [#6334](https://github.com/MetaMask/metamask-mobile/pull/6334): feat: Aurora Token Detection
- [#6351](https://github.com/MetaMask/metamask-mobile/pull/6351): feat: use thunk to handle processed order side effects
diff --git a/android/app/build.gradle b/android/app/build.gradle
index ab5b848c8d6..c35e65edbc1 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -132,12 +132,13 @@ android {
compileSdkVersion rootProject.ext.compileSdkVersion
namespace"io.metamask"
+
defaultConfig {
- applicationId "io.metamask"
+ applicationId "io.metamask"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
- versionCode 1136
- versionName "7.1.0"
+ versionCode 1142
+ versionName "7.2.0"
testBuildType System.getProperty('testBuildType', 'debug')
missingDimensionStrategy 'react-native-camera', 'general'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
diff --git a/app/component-library/components-temp/CustomSpendCap/CustomInput/CustomInput.constants.ts b/app/component-library/components-temp/CustomSpendCap/CustomInput/CustomInput.constants.ts
index 0584b27380c..2364089e924 100644
--- a/app/component-library/components-temp/CustomSpendCap/CustomInput/CustomInput.constants.ts
+++ b/app/component-library/components-temp/CustomSpendCap/CustomInput/CustomInput.constants.ts
@@ -1,3 +1,4 @@
-const CUSTOM_INPUT_TEST_ID = 'custom-input-test-id';
-
-export default CUSTOM_INPUT_TEST_ID;
+export const CUSTOM_SPEND_CAP_INPUT_TEST_ID = 'custom-spend-cap-input-test-id';
+export const CUSTOM_SPEND_CAP_MAX_TEST_ID = 'custom-spend-cap-max-test-id';
+export const CUSTOM_SPEND_CAP_INPUT_INPUT_ID =
+ 'custom-spend-cap-input-input-id';
diff --git a/app/component-library/components-temp/CustomSpendCap/CustomInput/CustomInput.test.tsx b/app/component-library/components-temp/CustomSpendCap/CustomInput/CustomInput.test.tsx
index d5548f0386b..00e11f8fff7 100644
--- a/app/component-library/components-temp/CustomSpendCap/CustomInput/CustomInput.test.tsx
+++ b/app/component-library/components-temp/CustomSpendCap/CustomInput/CustomInput.test.tsx
@@ -6,6 +6,10 @@ import React from 'react';
import { TICKER } from '../CustomSpendCap.constants';
// Internal dependencies.
import CustomInput from './CustomInput';
+import {
+ CUSTOM_SPEND_CAP_INPUT_INPUT_ID,
+ CUSTOM_SPEND_CAP_MAX_TEST_ID,
+} from './CustomInput.constants';
import { CustomInputProps } from './CustomInput.types';
describe('CustomInput', () => {
@@ -19,6 +23,7 @@ describe('CustomInput', () => {
isEditDisabled: false,
setMaxSelected: jest.fn(),
setValue: jest.fn(),
+ tokenDecimal: 4,
};
});
@@ -28,4 +33,42 @@ describe('CustomInput', () => {
const component = renderComponent();
expect(component).toMatchSnapshot();
});
+
+ it('should call setMaxSelected when max button is pressed', () => {
+ const component = renderComponent();
+ component
+ .findWhere((node) => node.prop('testID') === CUSTOM_SPEND_CAP_MAX_TEST_ID)
+ .simulate('press');
+ expect(props.setMaxSelected).toHaveBeenCalled();
+ });
+
+ it('should update value if input is integer', () => {
+ const component = renderComponent();
+ component
+ .findWhere(
+ (node) => node.prop('testID') === CUSTOM_SPEND_CAP_INPUT_INPUT_ID,
+ )
+ .simulate('changeText', '123');
+ expect(props.setValue).toHaveBeenCalledWith('123');
+ });
+
+ it('should update value if input is decimal and decimal points are less than or equal to tokenDecimal', () => {
+ const component = renderComponent();
+ component
+ .findWhere(
+ (node) => node.prop('testID') === CUSTOM_SPEND_CAP_INPUT_INPUT_ID,
+ )
+ .simulate('changeText', '123.1234');
+ expect(props.setValue).toHaveBeenCalledWith('123.1234');
+ });
+
+ it('should not update value if input is decimal and decimal points are greater than tokenDecimal', () => {
+ const component = renderComponent();
+ component
+ .findWhere(
+ (node) => node.prop('testID') === CUSTOM_SPEND_CAP_INPUT_INPUT_ID,
+ )
+ .simulate('changeText', '123.1234567');
+ expect(props.setValue).not.toHaveBeenCalled();
+ });
});
diff --git a/app/component-library/components-temp/CustomSpendCap/CustomInput/CustomInput.tsx b/app/component-library/components-temp/CustomSpendCap/CustomInput/CustomInput.tsx
index 6e419bf8125..a2fb7c71a75 100644
--- a/app/component-library/components-temp/CustomSpendCap/CustomInput/CustomInput.tsx
+++ b/app/component-library/components-temp/CustomSpendCap/CustomInput/CustomInput.tsx
@@ -8,7 +8,11 @@ import { dotAndCommaDecimalFormatter } from '../../../../util/number';
import Text, { TextVariant } from '../../../components/Texts/Text';
// External dependencies.
import { useStyles } from '../../../hooks';
-import CUSTOM_INPUT_TEST_ID from './CustomInput.constants';
+import {
+ CUSTOM_SPEND_CAP_INPUT_INPUT_ID,
+ CUSTOM_SPEND_CAP_INPUT_TEST_ID,
+ CUSTOM_SPEND_CAP_MAX_TEST_ID,
+} from './CustomInput.constants';
import stylesheet from './CustomInput.styles';
// Internal dependencies.
import { CustomInputProps } from './CustomInput.types';
@@ -20,8 +24,15 @@ const CustomInput = ({
isInputGreaterThanBalance,
setValue,
isEditDisabled,
+ tokenDecimal,
}: CustomInputProps) => {
const handleUpdate = (text: string) => {
+ const decimalIndex = text.indexOf('.');
+ const fractionalLength = text.substring(decimalIndex + 1).length;
+
+ if (decimalIndex !== -1 && fractionalLength > Number(tokenDecimal)) {
+ return;
+ }
setValue(dotAndCommaDecimalFormatter(text));
};
@@ -49,11 +60,12 @@ const CustomInput = ({
backgroundColor: colors.background.alternative,
},
]}
- testID={CUSTOM_INPUT_TEST_ID}
+ testID={CUSTOM_SPEND_CAP_INPUT_TEST_ID}
>
{!isEditDisabled ? (
{!isEditDisabled && (
@@ -57,6 +58,7 @@ exports[`CustomInput should render correctly 1`] = `
"color": "#535A61",
}
}
+ testID="custom-spend-cap-max-test-id"
variant="sBodySM"
>
Max
diff --git a/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.stories.tsx b/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.stories.tsx
index 3f8b4d962c5..c4efb87a9d8 100644
--- a/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.stories.tsx
+++ b/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.stories.tsx
@@ -7,7 +7,6 @@ import CustomSpendCap from './CustomSpendCap';
// Internal dependencies.
import {
ACCOUNT_BALANCE,
- DAPP_DOMAIN,
DAPP_PROPOSED_VALUE,
INPUT_VALUE_CHANGED,
TICKER,
@@ -18,10 +17,11 @@ storiesOf('Component Library / CustomSpendCap', module).add('Default', () => (
ticker={TICKER}
accountBalance={ACCOUNT_BALANCE}
dappProposedValue={DAPP_PROPOSED_VALUE}
- domain={DAPP_DOMAIN}
onInputChanged={INPUT_VALUE_CHANGED}
isEditDisabled={false}
editValue={() => undefined}
tokenSpendValue={''}
+ toggleLearnMoreWebPage={() => undefined}
+ isInputValid={() => true}
/>
));
diff --git a/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.test.tsx b/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.test.tsx
index 0a564f89879..e8d612600c1 100644
--- a/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.test.tsx
+++ b/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.test.tsx
@@ -7,7 +7,6 @@ import CustomSpendCap from './CustomSpendCap';
import {
ACCOUNT_BALANCE,
CUSTOM_SPEND_CAP_TEST_ID,
- DAPP_DOMAIN,
DAPP_PROPOSED_VALUE,
INPUT_VALUE_CHANGED,
TICKER,
@@ -16,20 +15,22 @@ import {
import { CustomSpendCapProps } from './CustomSpendCap.types';
function RenderCustomSpendCap(
- tokenSpendValue: string,
+ tokenSpendValue = '',
isInputValid: () => boolean = () => true,
+ dappProposedValue: string = DAPP_PROPOSED_VALUE,
) {
return (
({})}
tokenSpendValue={tokenSpendValue}
isInputValid={isInputValid}
+ tokenDecimal={18}
+ toggleLearnMoreWebPage={() => undefined}
/>
);
}
@@ -63,7 +64,7 @@ describe('CustomSpendCap', () => {
expect(
await findByText(
- `Only enter a number that you're comfortable with ${DAPP_DOMAIN} accessing now or in the future. You can always increase the token limit later.`,
+ `Only enter a number that you're comfortable with the third party spending now or in the future. You can always increase the spending cap later. Learn more`,
),
).toBeDefined();
});
@@ -81,13 +82,15 @@ describe('CustomSpendCap', () => {
it('should render valid message if value is greater than account balance', async () => {
const valueGreaterThanBalance = '300';
- const valueDifference =
- Number(valueGreaterThanBalance) - Number(ACCOUNT_BALANCE);
- const { toJSON } = renderWithProvider(
+ const { findByText } = renderWithProvider(
RenderCustomSpendCap(valueGreaterThanBalance),
);
- expect(JSON.stringify(toJSON())).toMatch(`${valueDifference} ${TICKER}`);
+ expect(
+ await findByText(
+ 'This allows the third party to spend all your token balance until it reaches the cap or you revoke the spending cap. If this is not intended, consider setting a lower spending cap. Learn more',
+ ),
+ ).toBeDefined();
});
it('should call isInputValid with false if value is not a number', async () => {
@@ -103,4 +106,18 @@ describe('CustomSpendCap', () => {
expect(isInputValid).toHaveBeenCalledWith(true);
});
+
+ it('should render token spend value if present', async () => {
+ const inputtedSpendValue = '100';
+
+ const { findByText } = renderWithProvider(
+ RenderCustomSpendCap(
+ inputtedSpendValue,
+ isInputValid,
+ DAPP_PROPOSED_VALUE,
+ ),
+ );
+
+ expect(await findByText(`${inputtedSpendValue} ${TICKER}`)).toBeDefined();
+ });
});
diff --git a/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.tsx b/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.tsx
index a49675af402..a31ef5379d3 100644
--- a/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.tsx
+++ b/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.tsx
@@ -1,10 +1,10 @@
-import BigNumber from 'bignumber.js';
// Third party dependencies.
import React, { useEffect, useState } from 'react';
import { Pressable, View } from 'react-native';
import { strings } from '../../../../locales/i18n';
import InfoModal from '../../../components/UI/Swaps/components/InfoModal';
+import { TOKEN_APPROVAL_SPENDING_CAP } from '../../../constants/urls';
import formatNumber from '../../../util/formatNumber';
import { isNumber } from '../../../util/number';
import Button, { ButtonVariants } from '../../components/Buttons/Button';
@@ -22,12 +22,13 @@ const CustomSpendCap = ({
ticker,
dappProposedValue,
accountBalance,
- domain,
onInputChanged,
isEditDisabled,
editValue,
tokenSpendValue,
isInputValid,
+ tokenDecimal,
+ toggleLearnMoreWebPage,
}: CustomSpendCapProps) => {
const {
styles,
@@ -58,6 +59,11 @@ const CustomSpendCap = ({
isInputValid(!inputHasError);
}, [inputHasError, isInputValid]);
+ useEffect(() => {
+ const spendValue = tokenSpendValue || dappProposedValue;
+ setValue(spendValue);
+ }, [dappProposedValue, tokenSpendValue]);
+
const handleDefaultValue = () => {
setMaxSelected(false);
setValue(dappProposedValue);
@@ -65,18 +71,13 @@ const CustomSpendCap = ({
};
const handlePress = () => {
- if (isEditDisabled) editValue();
- handleDefaultValue();
+ isEditDisabled ? editValue() : handleDefaultValue();
};
useEffect(() => {
if (maxSelected) setValue(accountBalance);
}, [maxSelected, accountBalance]);
- const newValue = new BigNumber(value);
-
- const difference = newValue.minus(accountBalance).toFixed();
-
useEffect(() => {
if (Number(value) > Number(accountBalance))
return setInputValueHigherThanAccountBalance(true);
@@ -94,22 +95,11 @@ const CustomSpendCap = ({
);
const NO_SELECTED = strings(
- 'contract_allowance.custom_spend_cap.no_value_selected',
- { domain },
+ 'contract_allowance.custom_spend_cap.default_error_message',
);
- const INPUT_VALUE_GREATER_THAN_ACCOUNT_BALANCE = (
- <>
- {strings('contract_allowance.custom_spend_cap.this_contract_allows')}
-
- {` ${formatNumber(accountBalance)} ${ticker} `}
-
- {strings('contract_allowance.custom_spend_cap.from_your_current_balance')}
-
- {` ${formatNumber(difference)} ${ticker} `}
-
- {strings('contract_allowance.custom_spend_cap.future_tokens')}
- >
+ const INPUT_VALUE_GREATER_THAN_ACCOUNT_BALANCE = strings(
+ 'contract_allowance.custom_spend_cap.amount_greater_than_balance',
);
const INPUT_VALUE_LOWER_THAN_ACCOUNT_BALANCE = (
@@ -155,6 +145,9 @@ const CustomSpendCap = ({
message = INPUT_VALUE_LOWER_THAN_ACCOUNT_BALANCE;
}
+ const openLearnMore = () =>
+ toggleLearnMoreWebPage(TOKEN_APPROVAL_SPENDING_CAP);
+
return (
{isModalVisible ? (
@@ -168,10 +161,7 @@ const CustomSpendCap = ({
'contract_allowance.custom_spend_cap.info_modal_description_default',
)
: strings(
- 'contract_allowance.custom_spend_cap.no_value_selected',
- {
- domain,
- },
+ 'contract_allowance.custom_spend_cap.default_error_message',
)}
}
@@ -206,7 +196,9 @@ const CustomSpendCap = ({
label={
isEditDisabled
? strings('contract_allowance.custom_spend_cap.edit')
- : strings('contract_allowance.custom_spend_cap.use_default')
+ : strings(
+ 'contract_allowance.custom_spend_cap.use_site_suggestion',
+ )
}
/>
@@ -218,6 +210,7 @@ const CustomSpendCap = ({
setMaxSelected={setMaxSelected}
value={value}
isEditDisabled={isEditDisabled}
+ tokenDecimal={tokenDecimal}
/>
{value.length > 0 && inputHasError && (
@@ -228,7 +221,12 @@ const CustomSpendCap = ({
{!isEditDisabled && (
- {message}
+ {message}{' '}
+
)}
diff --git a/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.types.ts b/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.types.ts
index 8b4172c9ba1..f213eec1da0 100644
--- a/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.types.ts
+++ b/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.types.ts
@@ -2,7 +2,6 @@ export interface CustomSpendCapProps {
ticker: string;
dappProposedValue: string;
accountBalance: string;
- domain: string;
/**
* @param value - The value of the input field
*/
@@ -24,4 +23,12 @@ export interface CustomSpendCapProps {
* isInputValid - function to check if input is valid and has no errors
*/
isInputValid: (value: boolean) => boolean;
+ /**
+ * tokenDecimal - token decimal number
+ */
+ tokenDecimal?: number;
+ /**
+ * function to show learn more webpage
+ */
+ toggleLearnMoreWebPage: (url: string) => void;
}
diff --git a/app/component-library/components-temp/CustomSpendCap/__snapshots__/CustomSpendCap.test.tsx.snap b/app/component-library/components-temp/CustomSpendCap/__snapshots__/CustomSpendCap.test.tsx.snap
index dbc8c222dd1..775d44dfda2 100644
--- a/app/component-library/components-temp/CustomSpendCap/__snapshots__/CustomSpendCap.test.tsx.snap
+++ b/app/component-library/components-temp/CustomSpendCap/__snapshots__/CustomSpendCap.test.tsx.snap
@@ -40,7 +40,7 @@ exports[`CustomSpendCap should match snapshot 1`] = `
}
}
>
- Custom spending cap
+ Spending cap
- Use default
+ Use site suggestion
Max
@@ -196,7 +200,24 @@ exports[`CustomSpendCap should match snapshot 1`] = `
}
}
>
- Only enter a number that you're comfortable with Uniswap.org accessing now or in the future. You can always increase the token limit later.
+ This allows the third party to spend all your token balance until it reaches the cap or you revoke the spending cap. If this is not intended, consider setting a lower spending cap.
+
+
+ Learn more
+
diff --git a/app/components/UI/ApproveTransactionReview/ShowBlockExplorer/index.tsx b/app/components/UI/ApproveTransactionReview/ShowBlockExplorer/index.tsx
index fe653268da8..d9dd2ac7fab 100644
--- a/app/components/UI/ApproveTransactionReview/ShowBlockExplorer/index.tsx
+++ b/app/components/UI/ApproveTransactionReview/ShowBlockExplorer/index.tsx
@@ -1,17 +1,18 @@
import React, { useState } from 'react';
-import { View, StyleSheet, SafeAreaView } from 'react-native';
-import WebviewProgressBar from '../../../UI/WebviewProgressBar';
+import { SafeAreaView, StyleSheet, View } from 'react-native';
+import AntDesignIcon from 'react-native-vector-icons/AntDesign';
+import { WebView } from 'react-native-webview';
+
import Text, {
TextVariant,
} from '../../../../component-library/components/Texts/Text';
+import { RPC } from '../../../../constants/network';
import {
getEtherscanAddressUrl,
getEtherscanBaseUrl,
} from '../../../../util/etherscan';
import { findBlockExplorerForRpc } from '../../../../util/networks';
-import { WebView } from 'react-native-webview';
-import AntDesignIcon from 'react-native-vector-icons/AntDesign';
-import { RPC } from '../../../../constants/network';
+import WebviewProgressBar from '../../../UI/WebviewProgressBar';
const styles = StyleSheet.create({
progressBarWrapper: {
@@ -37,6 +38,7 @@ interface ShowBlockExplorerProps {
iconStyle?: any;
providerRpcTarget: string;
frequentRpcList: any[];
+ learnMoreURL?: string;
}
const ShowBlockExplorer = (props: ShowBlockExplorerProps) => {
@@ -49,17 +51,19 @@ const ShowBlockExplorer = (props: ShowBlockExplorerProps) => {
iconStyle,
providerRpcTarget,
frequentRpcList,
+ learnMoreURL,
} = props;
const [loading, setLoading] = useState(0);
const url =
- type === RPC
+ learnMoreURL ||
+ (type === RPC
? `${findBlockExplorerForRpc(
providerRpcTarget,
frequentRpcList,
)}/address/${address}`
- : getEtherscanAddressUrl(type, address);
+ : getEtherscanAddressUrl(type, address));
const title =
type === RPC
? new URL(findBlockExplorerForRpc(providerRpcTarget, frequentRpcList))
@@ -83,9 +87,11 @@ const ShowBlockExplorer = (props: ShowBlockExplorerProps) => {
return (
-
- {title}
-
+ {!learnMoreURL && (
+
+ {title}
+
+ )}
this.setState({ isReadyToApprove: false });
- customSpendInputValid = (value) => {
+ handleSetIsCustomSpendInputValid = (value) => {
this.setState({ isCustomSpendInputValid: value });
};
+ toggleLearnMoreWebPage = (url) => {
+ this.setState({
+ showBlockExplorerModal: !this.state.showBlockExplorerModal,
+ learnMoreURL: url,
+ });
+ };
+
+ handleCustomSpendOnInputChange = (value) => {
+ if (isNumber(value)) {
+ this.setState({
+ tokenSpendValue: value.replace(/[^0-9.]/g, ''),
+ });
+ }
+ };
+
renderDetails = () => {
const {
originalApproveAmount,
- host,
multiLayerL1FeeTotal,
token: {
tokenStandard,
@@ -728,20 +742,20 @@ class ApproveTransactionReview extends PureComponent {
tokenName || tokenSymbol || strings(`spend_limit_edition.nft`)
} (#${tokenValue})`;
- const isFirstScreenERC20 = tokenStandard === ERC20 && !tokenSpendValue;
-
- const isFinalScreenNonERC20 = isReadyToApprove || tokenStandard !== ERC20;
+ const isERC2OToken = tokenStandard === ERC20;
+ const isNonERC20Token = tokenStandard !== ERC20;
+ const isERC20SpendCapScreenWithoutValue = isERC2OToken && !tokenSpendValue;
const shouldDisableConfirmButton =
!fetchingUpdateDone ||
- isFirstScreenERC20 ||
+ isERC20SpendCapScreenWithoutValue ||
Boolean(gasError) ||
transactionConfirmed ||
- !isCustomSpendInputValid ||
- (isFinalScreenNonERC20 && !isGasEstimateStatusIn);
+ (!isCustomSpendInputValid && isERC2OToken) ||
+ (isNonERC20Token && !isGasEstimateStatusIn);
const confirmText =
- tokenStandard === ERC20 && !isReadyToApprove
+ isERC2OToken && !isReadyToApprove
? strings('transaction.next')
: strings('transactions.approve');
@@ -780,11 +794,9 @@ class ApproveTransactionReview extends PureComponent {
`spend_limit_edition.${
originIsDeeplink
? 'allow_to_address_access'
- : isReadyToApprove
- ? 'review_spend_cap'
: tokenStandard === ERC721 || tokenStandard === ERC1155
? 'allow_to_access'
- : 'set_spend_cap'
+ : 'spend_cap'
}`,
)}
@@ -797,7 +809,7 @@ class ApproveTransactionReview extends PureComponent {
{strings('spend_limit_edition.token')}
)}
- {tokenStandard === ERC20 && (
+ {isERC2OToken && (
<>
{tokenImage ? (
) : (
- tokenStandard === ERC20 && (
+ isERC2OToken && (
{
- if (isNumber(value)) {
- this.setState({
- tokenSpendValue: value.replace(/[^0-9.]/g, ''),
- });
- }
- }}
+ onInputChanged={this.handleCustomSpendOnInputChange}
+ isInputValid={this.handleSetIsCustomSpendInputValid}
/>
)
)}
- {((tokenStandard === ERC20 && isReadyToApprove) ||
+ {((isERC2OToken && isReadyToApprove) ||
tokenStandard === ERC721 ||
tokenStandard === ERC1155) && (
@@ -1043,13 +1050,14 @@ class ApproveTransactionReview extends PureComponent {
frequentRpcList,
providerRpcTarget,
} = this.props;
- const { showBlockExplorerModal, address } = this.state;
+ const { showBlockExplorerModal, address, learnMoreURL } = this.state;
const styles = this.getStyles();
const closeModal = () => {
- showVerifyContractDetails();
+ !learnMoreURL && showVerifyContractDetails();
this.setState({
showBlockExplorerModal: !showBlockExplorerModal,
+ learnMoreURL: null,
});
};
@@ -1063,6 +1071,7 @@ class ApproveTransactionReview extends PureComponent {
iconStyle={styles.icon}
providerRpcTarget={providerRpcTarget}
frequentRpcList={frequentRpcList}
+ learnMoreURL={learnMoreURL}
/>
);
};
diff --git a/app/components/UI/TransactionReview/TransactionReviewEIP1559Update/index.tsx b/app/components/UI/TransactionReview/TransactionReviewEIP1559Update/index.tsx
index 90394c83856..3686a8d5055 100644
--- a/app/components/UI/TransactionReview/TransactionReviewEIP1559Update/index.tsx
+++ b/app/components/UI/TransactionReview/TransactionReviewEIP1559Update/index.tsx
@@ -77,6 +77,7 @@ const TransactionReviewEIP1559Update = ({
transactionFeeFiat,
transactionTotalAmount,
transactionTotalAmountFiat,
+ suggestedGasLimit,
} = gasTransaction;
useEffect(() => {
@@ -84,7 +85,7 @@ const TransactionReviewEIP1559Update = ({
updateTransactionState(gasTransaction);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [gasEstimationReady, updateTransactionState]);
+ }, [gasEstimationReady, updateTransactionState, suggestedGasLimit]);
const openLinkAboutGas = useCallback(
() => Linking.openURL(AppConstants.URLS.WHY_TRANSACTION_TAKE_TIME),
diff --git a/app/components/Views/Approval/index.js b/app/components/Views/Approval/index.js
index 63554a5b1da..d3df5c0f5bf 100644
--- a/app/components/Views/Approval/index.js
+++ b/app/components/Views/Approval/index.js
@@ -340,7 +340,14 @@ class Approval extends PureComponent {
const { nonce } = transaction;
const { transactionConfirmed } = this.state;
if (transactionConfirmed) return;
- if (showCustomNonce && nonce) transaction.nonce = BNToHex(nonce);
+
+ if (showCustomNonce && nonce) {
+ transaction.nonce = BNToHex(nonce);
+ } else {
+ // If nonce is not set in transaction, TransactionController will set it to the next nonce
+ transaction.nonce = undefined;
+ }
+
this.setState({ transactionConfirmed: true });
try {
if (assetType === 'ETH') {
diff --git a/app/components/Views/Send/index.js b/app/components/Views/Send/index.js
index a6eef0a3cbc..babf8242593 100644
--- a/app/components/Views/Send/index.js
+++ b/app/components/Views/Send/index.js
@@ -177,11 +177,11 @@ class Send extends PureComponent {
/**
* Check if view is called with txMeta object for a deeplink
*/
- checkForDeeplinks() {
+ async checkForDeeplinks() {
const { route } = this.props;
const txMeta = route.params?.txMeta;
if (txMeta) {
- this.handleNewTxMeta(txMeta);
+ await this.handleNewTxMeta(txMeta);
} else {
this.mounted && this.setState({ ready: true });
}
@@ -218,7 +218,7 @@ class Send extends PureComponent {
dappTransactionModalVisible && toggleDappTransactionModal();
this.mounted = true;
await this.reset();
- this.checkForDeeplinks();
+ await this.checkForDeeplinks();
}
/**
@@ -379,6 +379,19 @@ class Send extends PureComponent {
if (gasPrice) {
newTxMeta.gasPrice = toBN(gas);
}
+
+ // if gas and gasPrice is not defined in the deeplink, we should define them
+ if (!gas && !gasPrice) {
+ const { gas, gasPrice } =
+ await Engine.context.TransactionController.estimateGas(
+ this.props.transaction,
+ );
+ newTxMeta = {
+ ...newTxMeta,
+ gas,
+ gasPrice,
+ };
+ }
// TODO: We should add here support for sending tokens
// or calling smart contract functions
}
diff --git a/app/constants/urls.ts b/app/constants/urls.ts
index fd1b6c054fa..aeb3816111c 100644
--- a/app/constants/urls.ts
+++ b/app/constants/urls.ts
@@ -12,6 +12,8 @@ export const LEARN_MORE_URL =
export const WHY_TRANSACTION_TAKE_TIME_URL =
'https://community.metamask.io/t/what-is-gas-why-do-transactions-take-so-long/3172';
+export const TOKEN_APPROVAL_SPENDING_CAP = `https://support.metamask.io/hc/en-us/articles/6055177143579-How-to-customize-token-approvals-with-a-spending-cap`;
+
// Policies
export const CONSENSYS_PRIVACY_POLICY = 'https://consensys.net/privacy-policy/';
diff --git a/app/core/Engine.ts b/app/core/Engine.ts
index 45a5f01e915..34e15175c84 100644
--- a/app/core/Engine.ts
+++ b/app/core/Engine.ts
@@ -40,6 +40,7 @@ import {
renderFromTokenMinimalUnit,
balanceToFiatNumber,
weiToFiatNumber,
+ toHexadecimal,
} from '../util/number';
import NotificationManager from './NotificationManager';
import Logger from '../util/Logger';
@@ -442,7 +443,7 @@ class Engine {
),
getAllState: () => store.getState(),
getCurrentChainId: () =>
- networkController.state.providerConfig.chainId,
+ toHexadecimal(networkController.state.providerConfig.chainId),
keyringController: {
signMessage: keyringController.signMessage.bind(keyringController),
signPersonalMessage:
diff --git a/bitrise.yml b/bitrise.yml
index 710b1014d19..71db0162f99 100644
--- a/bitrise.yml
+++ b/bitrise.yml
@@ -726,10 +726,10 @@ app:
PROJECT_LOCATION_IOS: ios
- opts:
is_expand: false
- VERSION_NAME: 7.1.0
+ VERSION_NAME: 7.2.0
- opts:
is_expand: false
- VERSION_NUMBER: 1136
+ VERSION_NUMBER: 1142
- opts:
is_expand: false
ANDROID_APK_LINK: ''
diff --git a/e2e/pages/Drawer/Settings/SecurityAndPrivacy/SecurityAndPrivacyView.js b/e2e/pages/Drawer/Settings/SecurityAndPrivacy/SecurityAndPrivacyView.js
index a21c515ae68..499e57c1a50 100644
--- a/e2e/pages/Drawer/Settings/SecurityAndPrivacy/SecurityAndPrivacyView.js
+++ b/e2e/pages/Drawer/Settings/SecurityAndPrivacy/SecurityAndPrivacyView.js
@@ -39,7 +39,7 @@ export default class SecurityAndPrivacy {
await TestHelpers.swipe(SECURITY_SETTINGS_SCROLL_ID, 'up', 'fast');
await TestHelpers.delay(1000);
} else {
- await TestHelpers.swipe(CHANGE_PASSWORD_TITLE_ID, 'up', 'fast', 0.9);
+ await TestHelpers.swipe(SECURITY_SETTINGS_SCROLL_ID, 'up', 'fast', 0.9);
}
//await TestHelpers.swipe(PRIVACY_MODE_SECTION_ID, 'up', 'fast');
}
diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj
index eac889178c5..9e7c2d6c73d 100644
--- a/ios/MetaMask.xcodeproj/project.pbxproj
+++ b/ios/MetaMask.xcodeproj/project.pbxproj
@@ -1039,7 +1039,7 @@
CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 1136;
+ CURRENT_PROJECT_VERSION = 1142;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 48XVW22RCG;
@@ -1072,7 +1072,7 @@
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
LLVM_LTO = YES;
- MARKETING_VERSION = 7.1.0;
+ MARKETING_VERSION = 7.2.0;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"$(inherited)",
@@ -1103,7 +1103,7 @@
CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 1136;
+ CURRENT_PROJECT_VERSION = 1142;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 48XVW22RCG;
ENABLE_BITCODE = NO;
@@ -1136,7 +1136,7 @@
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
LLVM_LTO = YES;
- MARKETING_VERSION = 7.1.0;
+ MARKETING_VERSION = 7.2.0;
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = (
"$(inherited)",
@@ -1246,7 +1246,7 @@
CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 1136;
+ CURRENT_PROJECT_VERSION = 1142;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 48XVW22RCG;
@@ -1282,7 +1282,7 @@
"\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 7.1.0;
+ MARKETING_VERSION = 7.2.0;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"$(inherited)",
@@ -1313,7 +1313,7 @@
CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 1136;
+ CURRENT_PROJECT_VERSION = 1142;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 48XVW22RCG;
ENABLE_BITCODE = NO;
@@ -1349,7 +1349,7 @@
"\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 7.1.0;
+ MARKETING_VERSION = 7.2.0;
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = (
"$(inherited)",
diff --git a/locales/languages/de.json b/locales/languages/de.json
index ef093a07d1e..ce3e1a29f63 100644
--- a/locales/languages/de.json
+++ b/locales/languages/de.json
@@ -2364,10 +2364,7 @@
"title": "Benutzerdefinierte Ausgabenobergrenze",
"use_default": "Standard",
"from_your_balance": "von ihrem aktuellen Guthaben verwenden.",
- "no_value_selected": "Geben Sie nur eine Nummer ein, auf die {{domain}} jetzt oder in Zukunft zugreifen kann. Sie können das die Token-Begrenzung später jederzeit ändern.",
"this_contract_allows": "Dieser Contract erlaubt es dieser Seite, aktuelles",
- "from_your_current_balance": "Guthaben auszugeben, zuzüglich dem,",
- "future_tokens": " das Sie in Zukunft haben könnten. Ihre Tokens könnten gefährdet sein.",
"info_modal_description_default": "Der Contract könnte Ihr gesamtes Token-Guthaben ohne weitere Benachrichtigung oder Zustimmung ausgeben. Schützen Sie sich, indem Sie eine niedrigere Ausgabenobergrenze festlegen.",
"set_spend_cap": "Ausgabenobergrenze festlegen",
"be_careful": "Sein Sie vorsichtig",
diff --git a/locales/languages/el.json b/locales/languages/el.json
index fdc336c37eb..f5b2f859849 100644
--- a/locales/languages/el.json
+++ b/locales/languages/el.json
@@ -2364,10 +2364,7 @@
"title": "Προσαρμοσμένο ανώτατο όριο δαπανών",
"use_default": "Χρήση προκαθορισμένου",
"from_your_balance": "από το τρέχον υπόλοιπό σας.",
- "no_value_selected": "Εισάγετε μόνο έναν αριθμό με τον οποίο αισθάνεστε άνετα να έχει πρόσβαση το {{domain}} τώρα ή στο μέλλον. Μπορείτε πάντα να αυξήσετε το όριο token αργότερα.",
"this_contract_allows": "Το συμβόλαιο αυτό επιτρέπει στον ιστότοπο να δαπανήσει",
- "from_your_current_balance": "από το τρέχον υπόλοιπό σας συν",
- "future_tokens": "αυτά που μπορεί να αποκτήσετε στο μέλλον. Τα tokens σας μπορεί να κινδυνεύουν.",
"info_modal_description_default": "Το συμβόλαιο μπορεί να ξοδέψει ολόκληρο το υπόλοιπο των token σας χωρίς περαιτέρω ειδοποίηση ή συγκατάθεση. Προστατέψτε τον εαυτό σας θέτοντας ένα χαμηλότερο όριο δαπανών.",
"set_spend_cap": "Ορίστε ένα ανώτατο όριο δαπανών",
"be_careful": "Να είστε προσεκτικοί",
diff --git a/locales/languages/en.json b/locales/languages/en.json
index 03970381548..83b21410a38 100644
--- a/locales/languages/en.json
+++ b/locales/languages/en.json
@@ -1096,8 +1096,7 @@
"approve": "Approve",
"allow_to_access": "Give permission to access your",
"allow_to_address_access": "Give this address access your",
- "set_spend_cap": "Set a spending cap for your",
- "review_spend_cap": "Review your spending cap",
+ "spend_cap": "Spending cap request for your",
"token": "token",
"nft": "NFT",
"you_trust_this_site": "By granting permission, you're allowing the following third party to access your funds.",
@@ -2361,18 +2360,18 @@
"custom_spend_cap": {
"max": "Max",
"edit": "Edit",
- "title": "Custom spending cap",
- "use_default": "Use default",
+ "title": "Spending cap",
+ "use_site_suggestion": "Use site suggestion",
"from_your_balance": "from your current balance.",
- "no_value_selected": "Only enter a number that you're comfortable with {{domain}} accessing now or in the future. You can always increase the token limit later.",
- "this_contract_allows": "This contract allows the site to spend",
- "from_your_current_balance": "from your current balance plus",
- "future_tokens": "you might have in the future. Your tokens may be at risk.",
- "info_modal_description_default": "The contract could spend your entire token balance without further notice or consent. Protect yourself by setting a lower spending cap.",
+ "default_error_message": "Only enter a number that you're comfortable with the third party spending now or in the future. You can always increase the spending cap later.",
+ "this_contract_allows": "This allows the third party to spend",
+ "amount_greater_than_balance": "This allows the third party to spend all your token balance until it reaches the cap or you revoke the spending cap. If this is not intended, consider setting a lower spending cap.",
+ "info_modal_description_default": "The third party could spend your entire token balance without further notice or consent. Protect yourself by setting a lower spending cap.",
"set_spend_cap": "Set a spending cap",
"be_careful": "Be careful",
"error_enter_number": "Error: Enter only numbers",
- "enter_number": "Enter a number here"
+ "enter_number": "Enter a number here",
+ "learn_more": "Learn more"
},
"token_allowance": {
"verify_third_party_details": "Verify third party details",
diff --git a/locales/languages/es.json b/locales/languages/es.json
index 0c3b00ff8dc..01d4a82e917 100644
--- a/locales/languages/es.json
+++ b/locales/languages/es.json
@@ -2364,10 +2364,7 @@
"title": "Límite de gasto personalizado",
"use_default": "Uso por defecto",
"from_your_balance": "de su saldo actual.",
- "no_value_selected": "Ingrese solo una cantidad que le parezca adecuada para que {{domain}} acceda ahora o en el futuro. Siempre puede aumentar el límite de tokens más tarde.",
"this_contract_allows": "Este contrato permite que el sitio gaste",
- "from_your_current_balance": "de su saldo actual más",
- "future_tokens": "lo que pueda tener en el futuro. Sus tokens pueden estar en riesgo.",
"info_modal_description_default": "El contrato podría gastar todo su saldo de tokens sin previo aviso o consentimiento. Protéjase estableciendo un límite de gasto más bajo.",
"set_spend_cap": "Establecer un límite de gasto",
"be_careful": "Sea cuidadoso",
diff --git a/locales/languages/fr.json b/locales/languages/fr.json
index e1f5d4624eb..11432088090 100644
--- a/locales/languages/fr.json
+++ b/locales/languages/fr.json
@@ -2364,10 +2364,7 @@
"title": "Plafond de dépenses personnalisé",
"use_default": "Utilisez la valeur par défaut",
"from_your_balance": "de votre solde actuel.",
- "no_value_selected": "Saisissez uniquement le nombre de jetons que vous êtes prêt à mettre à la disposition de {{domain}}, maintenant ou à l’avenir. Vous pourrez toujours augmenter la limite de jetons ultérieurement.",
"this_contract_allows": "Le contrat autorise le site à dépenser les",
- "from_your_current_balance": "que vous possédez actuellement ou que vous",
- "future_tokens": "pourrez posséder à l’avenir. Vous pourrez être la cible d’une arnaque.",
"info_modal_description_default": "L’autre partie au contrat pourrait dépenser l’ensemble de vos jetons sans préavis et sans demander votre consentement. Protégez vos fonds en abaissant le plafond des dépenses.",
"set_spend_cap": "Définissez un plafond de dépenses",
"be_careful": "Soyez prudent",
diff --git a/locales/languages/hi.json b/locales/languages/hi.json
index c9996f131b5..dd68651967f 100644
--- a/locales/languages/hi.json
+++ b/locales/languages/hi.json
@@ -2364,10 +2364,7 @@
"title": "कस्टम खर्च की सीमा",
"use_default": "डिफ़ॉल्ट उपयोग करें",
"from_your_balance": "आपके वर्तमान शेष से।",
- "no_value_selected": "केवल वही संख्या दर्ज करें जिसे {{domain}} आप अभी या भविष्य में एक्सेस करने में सहज हों। बाद में आप कभी भी टोकन की सीमा बढ़ा सकते हैं।",
"this_contract_allows": "यह अनुबंध साइट को खर्च करने की अनुमति देता है",
- "from_your_current_balance": "आपके वर्तमान शेष प्लस से",
- "future_tokens": "जो आपके पास भविष्य में हो सकता है। आपके टोकन जोखिम में हो सकते हैं।",
"info_modal_description_default": "यह अनुबंध बिना किसी पूर्व सूचना या सहमति के आपकी संपूर्ण टोकन शेष राशि को खर्च कर सकता है। खर्च की निम्न सीमा निर्धारित करके आप खुद को सुरक्षित रखें।",
"set_spend_cap": "खर्च की सीमा सेट करें",
"be_careful": "सावधान रहे",
diff --git a/locales/languages/id.json b/locales/languages/id.json
index 3061d13560e..09d8a3920d6 100644
--- a/locales/languages/id.json
+++ b/locales/languages/id.json
@@ -2364,10 +2364,7 @@
"title": "Batas pengeluaran khusus",
"use_default": "Gunakan default",
"from_your_balance": "dari saldo Anda saat ini.",
- "no_value_selected": "Hanya masukkan nomor yang nyaman untuk Anda akses {{domain}} sekarang atau di masa mendatang. Anda selalu dapat meningkatkan batas token nanti.",
"this_contract_allows": "Kontrak ini memungkinkan situs untuk menghabiskan",
- "from_your_current_balance": "dari saldo Anda saat ini, dan juga",
- "future_tokens": "yang mungkin Anda miliki di masa mendatang. Token Anda berpotensi mengalami risiko.",
"info_modal_description_default": "Kontrak dapat mempergunakan seluruh saldo token Anda tanpa pemberitahuan atau persetujuan lebih lanjut. Lindungi diri Anda dengan menetapkan batas pengeluaran yang lebih rendah.",
"set_spend_cap": "Atur batas pengeluaran",
"be_careful": "Berhati-hatilah",
diff --git a/locales/languages/ja.json b/locales/languages/ja.json
index 92376f419f6..c863d0974ee 100644
--- a/locales/languages/ja.json
+++ b/locales/languages/ja.json
@@ -2364,10 +2364,7 @@
"title": "カスタム使用上限",
"use_default": "既定値を使用",
"from_your_balance": "現在の残高から。",
- "no_value_selected": "現在または今後 {{domain}} がアクセスしても構わない額のみを入力してください。トークン上限は後でいつでも増額できます。",
"this_contract_allows": "このコントラクトは、サイトによる",
- "from_your_current_balance": "現在および今後の残高からの",
- "future_tokens": "使用を可能にします。トークンが危険にさらされる可能性があります。",
"info_modal_description_default": "このコントラクトは今後、通知や承諾なしにトークン残高全額を使用できます。使用限度をより低い金額に設定して、自分の身を守りましょう。",
"set_spend_cap": "使用上限を設定してください",
"be_careful": "ご注意ください",
diff --git a/locales/languages/ko.json b/locales/languages/ko.json
index 5a227e47350..490abe8e6f3 100644
--- a/locales/languages/ko.json
+++ b/locales/languages/ko.json
@@ -2364,10 +2364,7 @@
"title": "맞춤형 지출 한도",
"use_default": "기본값 사용",
"from_your_balance": "현재 잔액에서",
- "no_value_selected": "{{domain}}에서 현재나 추후 지출하기에 무리가 없는 금액만 입력하세요. 지출 한도는 나중에 언제든지 상향할 수 있습니다.",
"this_contract_allows": "이 계약은 사이트가",
- "from_your_current_balance": "현재 잔액 및",
- "future_tokens": "향후 자금에서 사용할 수 있도록 허용하는 것입니다. 보유 중인 토큰이 위험할 수 있습니다.",
"info_modal_description_default": "계약은 추가 통보나 동의 없이도 남은 토큰 전체를 사용할 수 있습니다. 보호를 위해 지출 한도를 낮추세요.",
"set_spend_cap": "지출 한도 설정",
"be_careful": "주의하세요",
diff --git a/locales/languages/pt.json b/locales/languages/pt.json
index 4f777fc7310..e9ff33cb782 100644
--- a/locales/languages/pt.json
+++ b/locales/languages/pt.json
@@ -2364,10 +2364,7 @@
"title": "Limite de gastos personalizado",
"use_default": "Usar o padrão",
"from_your_balance": "do seu saldo atual.",
- "no_value_selected": "Somente insira um número com o qual esteja confortável que {{domain}} acesse agora ou no futuro. Você pode aumentar a qualquer momento o limite de tokens.",
"this_contract_allows": "Esse contrato permite que o site gaste",
- "from_your_current_balance": "do seu saldo atual mais",
- "future_tokens": "o que você vier a ter no futuro. Seus tokens podem estar em risco.",
"info_modal_description_default": "O contrato poderia gastar todo o seu saldo de tokens sem aviso prévio nem consentimento. Proteja-se definindo um limite de gastos menor.",
"set_spend_cap": "Defina um limite de gastos",
"be_careful": "Tenha cuidado",
diff --git a/locales/languages/ru.json b/locales/languages/ru.json
index bbf939d421b..0e8a62b7ae0 100644
--- a/locales/languages/ru.json
+++ b/locales/languages/ru.json
@@ -2364,10 +2364,7 @@
"title": "Пользовательский лимит расходов",
"use_default": "Использовать значение по умолчанию",
"from_your_balance": "из вашего текущего баланса.",
- "no_value_selected": "Введите только то число в качестве лимита, которое вы разрешаете {{domain}}, использовать сейчас или в будущем. Вы всегда можете увеличить лимит токенов позже.",
"this_contract_allows": "Этот контракт позволяет сайту тратить",
- "from_your_current_balance": "из вашего текущего баланса плюс",
- "future_tokens": "то, что, возможно, у вас будет в будущем. Ваши токены могут оказаться под угрозой.",
"info_modal_description_default": "Контракт может потратить весь ваш баланс токенов без дополнительного уведомления или согласия. Защитите себя, установив более низкий лимит расходов.",
"set_spend_cap": "Установить лимит расходов",
"be_careful": "Будьте осторожны",
diff --git a/locales/languages/tl.json b/locales/languages/tl.json
index f553c3cca90..ff0b0ab09ec 100644
--- a/locales/languages/tl.json
+++ b/locales/languages/tl.json
@@ -2364,10 +2364,7 @@
"title": "Custom na limitasyon sa paggastos",
"use_default": "Gumamit ng default",
"from_your_balance": "mula sa iyong kasalukuyang balanse.",
- "no_value_selected": "Ilagay lamang ang numero na komportable ka sa {{domain}} na ina-access ngayon o sa hinaharap. Maaari mong palaging dagdagan ang limit ng token sa susunod.",
"this_contract_allows": "Ang kontratang ito ay nagpapahintulot sa site na gumastos",
- "from_your_current_balance": "mula sa iyong kasalukuyang balanse at",
- "future_tokens": "maaaring mayroon ka sa hinaharap. Maaaring nasa panganib ang iyong mga token.",
"info_modal_description_default": "Maaaring gastusin ng kontrata ang iyong buong balanse ng token nang walang karagdagang abiso o pahintulot. Protektahan ang iyong sarili sa pamamagitan ng pagtatakda ng mas mababang limitasyon sa paggastos.",
"set_spend_cap": "Magtakda ng limitasyon sa paggastos",
"be_careful": "Maging maingat",
diff --git a/locales/languages/tr.json b/locales/languages/tr.json
index 4b6a7c309f6..17c818b34de 100644
--- a/locales/languages/tr.json
+++ b/locales/languages/tr.json
@@ -2364,10 +2364,7 @@
"title": "Kişisel harcama üst limiti",
"use_default": "Güncel bakiyenizden",
"from_your_balance": "varsayılanı kulanın.",
- "no_value_selected": "Sadece şu anda ya da gelecekte {{domain}} erişimi konusunda rahat hissettiğiniz bir sayı girin. Token limitini daha sonra dilediğiniz zaman artırabilirsiniz.",
"this_contract_allows": "Bu sözleşme, sitenin geçerli bakiyenizden",
- "from_your_current_balance": "ve ayrıca gelecekte sahip olabileceğiniz bakiyelerden",
- "future_tokens": "harcama yapabilmesine izin verir. Tokenleriniz risk altında olabilir.",
"info_modal_description_default": "Sözleşme, başka herhangi bir uyarı ya da rıza olmaksızın tüm token bakiyenizi harcayabilir. Düşük bir harcama limiti belirleyerek kendinizi koruyun.",
"set_spend_cap": "Bir harcama limiti belirleyin",
"be_careful": "Dikkatli olun",
diff --git a/locales/languages/vi.json b/locales/languages/vi.json
index c190d51c06f..4e1f0d1490a 100644
--- a/locales/languages/vi.json
+++ b/locales/languages/vi.json
@@ -2364,10 +2364,7 @@
"title": "Hạn mức chi tiêu tùy chỉnh",
"use_default": "Sử dụng mặc định",
"from_your_balance": "từ số dư hiện tại của bạn.",
- "no_value_selected": "Chỉ nhập số mà bạn cảm thấy thoải mái khi truy cập {{domain}} ở hiện tại hoặc trong tương lai. Bạn luôn có thể tăng giới hạn token sau này.",
"this_contract_allows": "Hợp đồng này cho phép trang web chi tiêu",
- "from_your_current_balance": "từ số dư hiện tại của bạn, cộng với",
- "future_tokens": "số dư bạn có thể có trong tương lai. Token của bạn có thể gặp rủi ro.",
"info_modal_description_default": "Hợp đồng có thể chi tiêu toàn bộ số dư token của bạn mà không cần thông báo hoặc chấp thuận thêm. Hãy tự bảo vệ chính mình bằng cách đặt hạn mức chi tiêu thấp hơn.",
"set_spend_cap": "Đặt hạn mức chi tiêu",
"be_careful": "Hãy cẩn thận",
diff --git a/locales/languages/zh.json b/locales/languages/zh.json
index a29a4a86595..8ea9e4ef478 100644
--- a/locales/languages/zh.json
+++ b/locales/languages/zh.json
@@ -2364,10 +2364,7 @@
"title": "自定义支出上限",
"use_default": "使用默认值",
"from_your_balance": "从当前余额中。",
- "no_value_selected": "仅输入一个您觉得现在或将来可放心让{{domain}}访问的数字。以后,您可以随时提高代币上限。",
"this_contract_allows": "此合约允许网站",
- "from_your_current_balance": "从您当前的余额和",
- "future_tokens": "您将来可能拥有的余额中支出。您的代币可能存在风险。",
"info_modal_description_default": "合约可能会在没有进一步通知或同意的情况下支出您的全部代币余额。请设置较低的支出上限以保护自己。",
"set_spend_cap": "设置支出上限",
"be_careful": "请小心",
diff --git a/package.json b/package.json
index 936aab6b46e..6c29e6be1c1 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "metamask",
- "version": "7.1.0",
+ "version": "7.2.0",
"private": true,
"scripts": {
"audit:ci": "./scripts/yarn-audit.sh",
diff --git a/patches/@metamask+assets-controllers+5.0.0.patch b/patches/@metamask+assets-controllers+5.0.0.patch
index b54a4bc18c3..ff57e558f33 100644
--- a/patches/@metamask+assets-controllers+5.0.0.patch
+++ b/patches/@metamask+assets-controllers+5.0.0.patch
@@ -1,5 +1,5 @@
diff --git a/node_modules/@metamask/assets-controllers/dist/AccountTrackerController.js b/node_modules/@metamask/assets-controllers/dist/AccountTrackerController.js
-index 130e3dc..912c84c 100644
+index 130e3dc..2fd96bb 100644
--- a/node_modules/@metamask/assets-controllers/dist/AccountTrackerController.js
+++ b/node_modules/@metamask/assets-controllers/dist/AccountTrackerController.js
@@ -30,7 +30,7 @@ class AccountTrackerController extends base_controller_1.BaseController {
@@ -11,7 +11,7 @@ index 130e3dc..912c84c 100644
super(config, state);
this.mutex = new async_mutex_1.Mutex();
/**
-@@ -38,16 +38,26 @@ class AccountTrackerController extends base_controller_1.BaseController {
+@@ -38,16 +38,28 @@ class AccountTrackerController extends base_controller_1.BaseController {
*/
this.name = 'AccountTrackerController';
/**
@@ -29,6 +29,7 @@ index 130e3dc..912c84c 100644
+ if (!isMultiAccountBalancesEnabled) {
+ const selectedAddress = this.getSelectedAddress();
+ const balance = yield this.getBalanceFromChain(selectedAddress);
++ if (!balance) return;
+ accounts[selectedAddress] = { balance: (0, controller_utils_1.BNToHex)(balance) };
+ this.update({ accounts });
+ return;
@@ -39,11 +40,12 @@ index 130e3dc..912c84c 100644
- accounts[address] = { balance: (0, controller_utils_1.BNToHex)(balance) };
- }));
+ const balance = yield this.getBalanceFromChain(address);
++ if (!balance) continue;
+ accounts[address] = { balance: (0, controller_utils_1.BNToHex)(balance) };
}
this.update({ accounts });
});
-@@ -57,6 +67,8 @@ class AccountTrackerController extends base_controller_1.BaseController {
+@@ -57,6 +69,8 @@ class AccountTrackerController extends base_controller_1.BaseController {
this.defaultState = { accounts: {} };
this.initialize();
this.getIdentities = getIdentities;
@@ -52,7 +54,7 @@ index 130e3dc..912c84c 100644
onPreferencesStateChange(() => {
this.refresh();
});
-@@ -106,6 +118,22 @@ class AccountTrackerController extends base_controller_1.BaseController {
+@@ -106,6 +120,22 @@ class AccountTrackerController extends base_controller_1.BaseController {
}, this.config.interval);
});
}
@@ -65,7 +67,7 @@ index 130e3dc..912c84c 100644
+ */
+ getBalanceFromChain(address) {
+ return __awaiter(this, void 0, void 0, function* () {
-+ let balance = '0x0';
++ let balance;
+ yield (0, controller_utils_1.safelyExecuteWithTimeout)(() => __awaiter(this, void 0, void 0, function* () {
+ balance = yield (0, controller_utils_1.query)(this.ethQuery, 'getBalance', [address]);
+ }));
@@ -109,7 +111,7 @@ index 332c87d..b634fde 100644
* Enumerate assets assigned to an owner.
*
diff --git a/node_modules/@metamask/assets-controllers/dist/Standards/ERC20Standard.js b/node_modules/@metamask/assets-controllers/dist/Standards/ERC20Standard.js
-index 9ddbc28..ca00e3e 100644
+index 9ddbc28..b8fb35a 100644
--- a/node_modules/@metamask/assets-controllers/dist/Standards/ERC20Standard.js
+++ b/node_modules/@metamask/assets-controllers/dist/Standards/ERC20Standard.js
@@ -13,7 +13,13 @@ exports.ERC20Standard = void 0;