Skip to content

feat: add setting to dismiss prompt to enable smart contract #31609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Apr 9, 2025
6 changes: 6 additions & 0 deletions app/_locales/en/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions app/_locales/en_GB/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions app/scripts/controllers/preferences-controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,7 @@ describe('preferences controller', () => {
hideZeroBalanceTokens: false,
petnamesEnabled: true,
shouldShowAggregatedBalancePopover: true,
dismissSmartAccountSuggestionEnabled: false,
featureNotificationsEnabled: false,
showConfirmationAdvancedDetails: false,
showMultiRpcModal: false,
Expand Down Expand Up @@ -736,6 +737,7 @@ describe('preferences controller', () => {
petnamesEnabled: true,
privacyMode: false,
shouldShowAggregatedBalancePopover: true,
dismissSmartAccountSuggestionEnabled: false,
featureNotificationsEnabled: false,
showConfirmationAdvancedDetails: true,
showMultiRpcModal: false,
Expand Down
2 changes: 2 additions & 0 deletions app/scripts/controllers/preferences-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export type Preferences = {
};
tokenNetworkFilter: Record<string, boolean>;
shouldShowAggregatedBalancePopover: boolean;
dismissSmartAccountSuggestionEnabled: boolean;
};

// Omitting properties that already exist in the PreferencesState, as part of the preferences property.
Expand Down Expand Up @@ -201,6 +202,7 @@ export const getDefaultPreferencesControllerState =
showMultiRpcModal: false,
privacyMode: false,
shouldShowAggregatedBalancePopover: true, // by default user should see popover;
dismissSmartAccountSuggestionEnabled: false,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have the accountUpgradeDisabledChains also, should this be combined into that?

Do we also want to display those in the settings UI?

Copy link
Contributor Author

@jpuri jpuri Apr 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep I was also thinking about re-using this - and I think this will be more a user level thing and not account level, additionally it will reflect across the app

tokenSortConfig: {
key: 'tokenFiatAmount',
order: 'dsc',
Expand Down
39 changes: 39 additions & 0 deletions app/scripts/lib/transaction/eip5792.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ describe('EIP-5792', () => {
Parameters<typeof processSendCalls>[0]['validateSecurity']
>;

let getDismissSmartAccountSuggestionEnabledMock: jest.MockedFn<() => boolean>;

let messenger: EIP5792Messenger;

beforeEach(() => {
Expand All @@ -100,6 +102,7 @@ describe('EIP-5792', () => {
getNetworkClientByIdMock = jest.fn();
getDisabledAccountUpgradeChainsMock = jest.fn();
validateSecurityMock = jest.fn();
getDismissSmartAccountSuggestionEnabledMock = jest.fn();

messenger = new Messenger();

Expand Down Expand Up @@ -133,6 +136,8 @@ describe('EIP-5792', () => {
addTransactionBatch: addTransactionBatchMock,
getDisabledAccountUpgradeChains: getDisabledAccountUpgradeChainsMock,
validateSecurity: validateSecurityMock,
getDismissSmartAccountSuggestionEnabled:
getDismissSmartAccountSuggestionEnabledMock,
},
messenger,
SEND_CALLS_MOCK,
Expand All @@ -157,6 +162,8 @@ describe('EIP-5792', () => {
getDisabledAccountUpgradeChains:
getDisabledAccountUpgradeChainsMock,
validateSecurity: validateSecurityMock,
getDismissSmartAccountSuggestionEnabled:
getDismissSmartAccountSuggestionEnabledMock,
},
messenger,
SEND_CALLS_MOCK,
Expand All @@ -173,6 +180,8 @@ describe('EIP-5792', () => {
getDisabledAccountUpgradeChains:
getDisabledAccountUpgradeChainsMock,
validateSecurity: validateSecurityMock,
getDismissSmartAccountSuggestionEnabled:
getDismissSmartAccountSuggestionEnabledMock,
},
messenger,
{ ...SEND_CALLS_MOCK, version: '2.0' },
Expand All @@ -189,6 +198,8 @@ describe('EIP-5792', () => {
getDisabledAccountUpgradeChains:
getDisabledAccountUpgradeChainsMock,
validateSecurity: validateSecurityMock,
getDismissSmartAccountSuggestionEnabled:
getDismissSmartAccountSuggestionEnabledMock,
},
messenger,
{ ...SEND_CALLS_MOCK, chainId: CHAIN_ID_2_MOCK },
Expand All @@ -209,6 +220,30 @@ describe('EIP-5792', () => {
getDisabledAccountUpgradeChains:
getDisabledAccountUpgradeChainsMock,
validateSecurity: validateSecurityMock,
getDismissSmartAccountSuggestionEnabled:
getDismissSmartAccountSuggestionEnabledMock,
},
messenger,
SEND_CALLS_MOCK,
REQUEST_MOCK,
),
).rejects.toThrow(
`EIP-5792 is not supported for this chain and account - Chain ID: ${CHAIN_ID_MOCK}, Account: ${SEND_CALLS_MOCK.from}`,
);
});

it('throws if user enabled preference to dismiss option to upgrade account', async () => {
getDismissSmartAccountSuggestionEnabledMock.mockReturnValue(true);

await expect(
processSendCalls(
{
addTransactionBatch: addTransactionBatchMock,
getDisabledAccountUpgradeChains:
getDisabledAccountUpgradeChainsMock,
validateSecurity: validateSecurityMock,
getDismissSmartAccountSuggestionEnabled:
getDismissSmartAccountSuggestionEnabledMock,
},
messenger,
SEND_CALLS_MOCK,
Expand All @@ -227,6 +262,8 @@ describe('EIP-5792', () => {
getDisabledAccountUpgradeChains:
getDisabledAccountUpgradeChainsMock,
validateSecurity: validateSecurityMock,
getDismissSmartAccountSuggestionEnabled:
getDismissSmartAccountSuggestionEnabledMock,
},
messenger,
{
Expand All @@ -250,6 +287,8 @@ describe('EIP-5792', () => {
getDisabledAccountUpgradeChains:
getDisabledAccountUpgradeChainsMock,
validateSecurity: validateSecurityMock,
getDismissSmartAccountSuggestionEnabled:
getDismissSmartAccountSuggestionEnabledMock,
},
messenger,
{
Expand Down
24 changes: 20 additions & 4 deletions app/scripts/lib/transaction/eip5792.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export async function processSendCalls(
request: ValidateSecurityRequest,
chainId: Hex,
) => Promise<void>;
getDismissSmartAccountSuggestionEnabled: () => boolean;
},
messenger: EIP5792Messenger,
params: SendCalls,
Expand All @@ -46,6 +47,7 @@ export async function processSendCalls(
addTransactionBatch,
getDisabledAccountUpgradeChains,
validateSecurity: validateSecurityHook,
getDismissSmartAccountSuggestionEnabled,
} = hooks;

const { calls, from } = params;
Expand All @@ -58,8 +60,15 @@ export async function processSendCalls(
).configuration.chainId;

const disabledChains = getDisabledAccountUpgradeChains();

validateSendCalls(params, dappChainId, disabledChains);
const dismissSmartAccountSuggestionEnabled =
getDismissSmartAccountSuggestionEnabled();

validateSendCalls(
params,
dappChainId,
disabledChains,
dismissSmartAccountSuggestionEnabled,
);

const securityAlertId = generateSecurityAlertId();
const validateSecurity = validateSecurityHook.bind(null, securityAlertId);
Expand Down Expand Up @@ -127,11 +136,17 @@ function validateSendCalls(
sendCalls: SendCalls,
dappChainId: Hex,
disabledChains: Hex[],
dismissSmartAccountSuggestionEnabled: boolean,
) {
validateSendCallsVersion(sendCalls);
validateSendCallsChainId(sendCalls, dappChainId);
validateCapabilities(sendCalls);
validateUserDisabled(sendCalls, disabledChains, dappChainId);
validateUserDisabled(
sendCalls,
disabledChains,
dappChainId,
dismissSmartAccountSuggestionEnabled,
);
}

function validateSendCallsVersion(sendCalls: SendCalls) {
Expand Down Expand Up @@ -188,11 +203,12 @@ function validateUserDisabled(
sendCalls: SendCalls,
disabledChains: Hex[],
dappChainId: Hex,
dismissSmartAccountSuggestionEnabled: boolean,
) {
const { from } = sendCalls;
const isDisabled = disabledChains.includes(dappChainId);

if (isDisabled) {
if (isDisabled || dismissSmartAccountSuggestionEnabled) {
throw rpcErrors.methodNotSupported(
`EIP-5792 is not supported for this chain and account - Chain ID: ${dappChainId}, Account: ${from}`,
);
Expand Down
3 changes: 3 additions & 0 deletions app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -2008,6 +2008,9 @@ export default class MetamaskController extends EventEmitter {
updateSecurityAlertResponse:
this.updateSecurityAlertResponse.bind(this),
}),
getDismissSmartAccountSuggestionEnabled: () =>
this.preferencesController.state.preferences
.dismissSmartAccountSuggestionEnabled,
},
this.controllerMessenger,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,74 @@ exports[`AdvancedTab Component should match snapshot 1`] = `
</div>
</div>
</div>
<div
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
data-testid="advanced-setting-dismiss-smart-account-suggestion-enabled"
>
<div
class="settings-page__content-item"
>
<span>

Dismiss "Switch to Smart Account" suggestion
</span>
<div
class="settings-page__content-description"
>
Turn this on to no longer see the "Switch to Smart Account" suggestion on any account. Smart accounts unlocks faster transactions, lower network fees and more flexibility on payment for those.
</div>
</div>
<div
class="settings-page__content-item-col"
>
<label
class="toggle-button toggle-button--off"
tabindex="0"
>
<div
style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;"
>
<div
style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(133, 139, 154);"
>
<div
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;"
/>
<div
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 1;"
/>
</div>
<div
style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;"
>
<div
style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: var(--shadow-size-xs) var(--color-shadow-default); border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(255, 255, 255); left: 3px;"
/>
</div>
<input
data-testid="settings-page-dismiss-smart-account-suggestion-enabled-toggle"
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;"
type="checkbox"
value="false"
/>
</div>
<div
class="toggle-button__status"
>
<span
class="toggle-button__label-off"
>
Off
</span>
<span
class="toggle-button__label-on"
>
On
</span>
</div>
</label>
</div>
</div>
<div
class="mm-box settings-page__content-row mm-box--display-flex mm-box--gap-4 mm-box--flex-direction-row mm-box--justify-content-space-between"
data-testid="advanced-setting-enable-smart-transactions"
Expand Down
43 changes: 43 additions & 0 deletions ui/pages/settings/advanced-tab/advanced-tab.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ export default class AdvancedTab extends PureComponent {
setShowExtensionInFullSizeView: PropTypes.func.isRequired,
manageInstitutionalWallets: PropTypes.bool,
setManageInstitutionalWallets: PropTypes.func.isRequired,
dismissSmartAccountSuggestionEnabled: PropTypes.bool.isRequired,
setDismissSmartAccountSuggestionEnabled: PropTypes.func.isRequired,
};

state = {
Expand Down Expand Up @@ -205,6 +207,46 @@ export default class AdvancedTab extends PureComponent {
);
}

renderToggleDismissSmartAccountSuggestion() {
const { t } = this.context;
const {
dismissSmartAccountSuggestionEnabled,
setDismissSmartAccountSuggestionEnabled,
} = this.props;

return (
<Box
ref={this.settingsRefs[2]}
className="settings-page__content-row"
data-testid="advanced-setting-dismiss-smart-account-suggestion-enabled"
display={Display.Flex}
flexDirection={FlexDirection.Row}
justifyContent={JustifyContent.spaceBetween}
gap={4}
>
<div className="settings-page__content-item">
<span> {t('dismissSmartAccountSuggestionEnabledTitle')}</span>
<div className="settings-page__content-description">
{t('dismissSmartAccountSuggestionEnabledDescription')}
</div>
</div>

<div className="settings-page__content-item-col">
<ToggleButton
value={dismissSmartAccountSuggestionEnabled}
onToggle={(oldValue) => {
const newValue = !oldValue;
setDismissSmartAccountSuggestionEnabled(newValue);
}}
offLabel={t('off')}
onLabel={t('on')}
dataTestId="settings-page-dismiss-smart-account-suggestion-enabled-toggle"
/>
</div>
</Box>
);
}

renderToggleStxOptIn() {
const { t } = this.context;
const { smartTransactionsEnabled, setSmartTransactionsEnabled } =
Expand Down Expand Up @@ -593,6 +635,7 @@ export default class AdvancedTab extends PureComponent {
) : null}
{this.renderStateLogs()}
{this.renderResetAccount()}
{this.renderToggleDismissSmartAccountSuggestion()}
{this.renderToggleStxOptIn()}
{this.renderHexDataOptIn()}
{this.renderShowConversionInTestnets()}
Expand Down
Loading
Loading