1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-12 12:47:14 +01:00
metamask-extension/app/scripts/controllers/preferences.js

538 lines
16 KiB
JavaScript
Raw Normal View History

import { ObservableStore } from '@metamask/obs-store';
import { normalize as normalizeAddress } from 'eth-sig-util';
import { IPFS_DEFAULT_GATEWAY_URL } from '../../../shared/constants/network';
import { LedgerTransportTypes } from '../../../shared/constants/hardware-wallets';
import { ThemeType } from '../../../shared/constants/preferences';
2021-02-26 16:40:25 +01:00
import { NETWORK_EVENTS } from './network';
export default class PreferencesController {
2018-04-18 20:41:39 +02:00
/**
*
* @typedef {object} PreferencesController
* @param {object} opts - Overrides the defaults for the initial state of this.store
* @property {object} store The stored object containing a users preferences, stored in local storage
* @property {boolean} store.useBlockie The users preference for blockie identicons within the UI
Add advanced setting to enable editing nonce on confirmation screens (#7089) * Add UseNonce toggle * Get the toggle actually working and dispatching * Display nonce field on confirmation page * Remove console.log * Add placeholder * Set customNonceValue * Add nonce key/value to txParams * remove customNonceValue from component state * Use translation file and existing CSS class * Use existing TextField component * Remove console.log * Fix lint nits * Okay this sorta works? * Move nonce toggle to advanced tab * Set min to 0 * Wrap value in Number() * Add customNonceMap * Update custom nonce translation * Update styles * Reset CustomNonce * Fix lint * Get tests passing * Add customNonceValue to defaults * Fix test * Fix comments * Update tests * Use camel case * Ensure custom nonce can only be whole number * Correct font size for custom nonce input * UX improvements for custom nonce feature * Fix advanced-tab-component tests for custom nonce changes * Update title of nonce toggle in settings * Remove unused locale message * Cast custom nonce to string in confirm-transaction-base.component * Handle string conversion and invalid values for custom nonces in handler * Don't call getNonceLock in tx controller if there is a custom nonce * Set nonce details for cases where nonce is customized * Fix incorrectly use value for deciding whether to getnoncelock in approveTransaction * Default nonceLock to empty object in approveTransaction * Reapply use on nonceLock in cases where customNonceValue in approveTransaction. * Show warning message if custom nonce is higher than MetaMask's next nonce * Fix e2e test failure caused by custom nonce and 3box toggle conflict * Update nonce warning message to include the suggested nonce * Handle nextNonce comparison and update logic in lifecycle * Default nonce field to suggested nonce * Clear custom nonce on reject or confirm * Fix bug where nonces are not shown in tx list on self sent transactions * Ensure custom nonce is reset after tx is created in background * Convert customNonceValue to number in approve tranasction controller * Lint fix * Call getNextNonce after updating custom nonce
2019-09-27 06:30:36 +02:00
* @property {boolean} store.useNonceField The users preference for nonce field within the UI
* @property {object} store.featureFlags A key-boolean map, where keys refer to features and booleans to whether the
2019-02-25 20:10:13 +01:00
* user wishes to see that feature.
*
* Feature flags can be set by the global function `setPreference(feature, enabled)`, and so should not expose any sensitive behavior.
* @property {object} store.knownMethodData Contains all data methods known by the user
* @property {string} store.currentLocale The preferred language locale key
* @property {string} store.selectedAddress A hex string that matches the currently selected address in the app
2018-04-18 20:41:39 +02:00
*/
2020-11-03 00:41:28 +01:00
constructor(opts = {}) {
const initState = {
useBlockie: false,
Add advanced setting to enable editing nonce on confirmation screens (#7089) * Add UseNonce toggle * Get the toggle actually working and dispatching * Display nonce field on confirmation page * Remove console.log * Add placeholder * Set customNonceValue * Add nonce key/value to txParams * remove customNonceValue from component state * Use translation file and existing CSS class * Use existing TextField component * Remove console.log * Fix lint nits * Okay this sorta works? * Move nonce toggle to advanced tab * Set min to 0 * Wrap value in Number() * Add customNonceMap * Update custom nonce translation * Update styles * Reset CustomNonce * Fix lint * Get tests passing * Add customNonceValue to defaults * Fix test * Fix comments * Update tests * Use camel case * Ensure custom nonce can only be whole number * Correct font size for custom nonce input * UX improvements for custom nonce feature * Fix advanced-tab-component tests for custom nonce changes * Update title of nonce toggle in settings * Remove unused locale message * Cast custom nonce to string in confirm-transaction-base.component * Handle string conversion and invalid values for custom nonces in handler * Don't call getNonceLock in tx controller if there is a custom nonce * Set nonce details for cases where nonce is customized * Fix incorrectly use value for deciding whether to getnoncelock in approveTransaction * Default nonceLock to empty object in approveTransaction * Reapply use on nonceLock in cases where customNonceValue in approveTransaction. * Show warning message if custom nonce is higher than MetaMask's next nonce * Fix e2e test failure caused by custom nonce and 3box toggle conflict * Update nonce warning message to include the suggested nonce * Handle nextNonce comparison and update logic in lifecycle * Default nonce field to suggested nonce * Clear custom nonce on reject or confirm * Fix bug where nonces are not shown in tx list on self sent transactions * Ensure custom nonce is reset after tx is created in background * Convert customNonceValue to number in approve tranasction controller * Lint fix * Call getNextNonce after updating custom nonce
2019-09-27 06:30:36 +02:00
useNonceField: false,
usePhishDetect: true,
dismissSeedBackUpReminder: false,
disabledRpcMethodPreferences: {
eth_sign: false,
},
useMultiAccountBalanceChecker: true,
// set to true means the dynamic list from the API is being used
// set to false will be using the static list from contract-metadata
useTokenDetection: false,
useNftDetection: false,
useCurrencyRateCheck: true,
openSeaEnabled: false,
advancedGasFee: null,
2019-02-25 20:10:13 +01:00
// WARNING: Do not use feature flags for security-sensitive things.
// Feature flag toggling is available in the global namespace
// for convenient testing of pre-release features, and should never
// perform sensitive operations.
featureFlags: {
showIncomingTransactions: true,
},
knownMethodData: {},
currentLocale: opts.initLangCode,
identities: {},
lostIdentities: {},
forgottenPassword: false,
preferences: {
autoLockTimeLimit: undefined,
showFiatInTestnets: false,
Implement Network Switcher designs (#12260) * Show test networks toggle button in settings/advanced tab. Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Apply toggle testnet settings and show/hide testnets when on/off Add localhost to testnet. Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Lint fixes. Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Show add network button Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Open full screen when add network is called. Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Show custonm rpc before testnet rpcs lint fixes. Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Test cases for network dropdown. Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Test cases for toggle test networks in advanced tab component. Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Lint fixes. Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Fix Locales. Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * E2E Tests: Custom RPC is now called Add Network Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Lint fix Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * E2E: When Add Network button is clicked, wait for the full screen window to be visible Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * findVisibleElement should use a class. i.e start with a dot Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Hide Dropdown when Add Netwok is clicked. Only show full screen if it's not already showing. E2E tests passing. Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Lint fixes Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Fix tests for jest Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Testnets are not being shown by default anymore, tests should use Mainnet instead. Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Import Button from ui Change selector name to getShowTestnetworks Fix button to show full width Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Fix e2e tests Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Remove localhost from INFURA provider types. Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Fix errors in Advanced Tab Component tests Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Lint fixes Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Fix unit tests for advanced tab component. Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Remove deleted elements from e2e tests Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Make sure all tests passed. Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com> * Lint fixes Signed-off-by: Akintayo A. Olusegun <akintayo.segun@gmail.com>
2021-10-28 21:31:05 +02:00
showTestNetworks: false,
useNativeCurrencyAsPrimaryCurrency: true,
hideZeroBalanceTokens: false,
},
// ENS decentralized website resolution
ipfsGateway: IPFS_DEFAULT_GATEWAY_URL,
infuraBlocked: null,
Connect Ledger via WebHID (#12411) * Connect ledger via webhid if that option is available * Explicitly setting preference for webhid * Use ledgerTransportType enum instead of booleans for ledger live and webhid preferences * Use single setLEdgerTransport preference methods and property * Temp * Lint fix * Unit test fix * Remove async keyword from setLedgerTransportPreference function definition in preferences controller * Fix ledgelive setting toggle logic * Migrate useLedgerLive preference property to ledgerTransportType * Use shared constants for ledger transport type enums * Use constant for ledger usb vendor id * Use correct property to check if ledgerLive preference is set when deciding whether to ask for webhid connection * Update eth-ledger-bridge-keyring to v0.9.0 * Only show ledger live transaction helper messages if using ledger live * Only show ledger live part of tutorial if ledger live setting is on * Fix ledger related prop type errors * Explicitly use u2f enum instead of empty string as a transport type; default transport type to webhid if available; use constants for u2f and webhid * Cleanup * Wrap ledger webhid device request in try/catch * Clean up * Lint fix * Ensure user can easily connect their ledger wallet when they need to. * Fix locales * Fix/improve locales changes * Remove unused isFirefox property from confirm-transaction-base.container.js * Disable transaction and message signing confirmation if ledger webhid requires connection * Ensure translation keys for ledger connection options in settings dropdown can be properly detected by verify-locales * Drop .component from ledger-instruction-field file name * Move renderLedgerLiveStep to module scope * Remove ledgerLive from function and message names in ledger-instruction-field * Wrap ledger connection logic in ledger-instruction-field in try catch * Clean up signature-request.component.js * Check whether the signing address, and not the selected address, is a ledger account in singature-request.container * Ensure ledger instructions and webhid connection button are shown on signature-request-original signatures * Improve webhid selection handling in select-ledger-transport-type onChange handler * Move metamask redux focused ledger selectors to metamask duck * Lint fix * Use async await in checkWebHidStatusRef.current * Remove unnecessary use of ref in ledger-instruction-field.js * Lint fix * Remove unnecessary try/catch in ledger-instruction-field.js * Check if from address, not selected address, is from a ledger account in confirm-approve * Move findKeyringForAddress to metamask duck * Fix typo in function name * Ensure isEqualCaseInsensitive handles possible differences in address casing * Fix Learn More link size in advanced settings tab * Update app/scripts/migrations/066.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Update ui/pages/settings/advanced-tab/advanced-tab.component.test.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Add jsdoc comments for new selectors * Use jest.spyOn for mocking navigator in ledger webhid migration tests * Use LEDGER_TRANSPORT_TYPES values to set proptype of ledgerTransportType * Use LEDGER_TRANSPORT_TYPES values to set proptype of ledgerTransportType * Fix font size of link in ledger connection description in advanced settings * Fix return type in setLedgerTransportPreference comment * Clean up connectHardware code for webhid connection in actions.js * Update app/scripts/migrations/066.test.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Update ui/ducks/metamask/metamask.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Add migration test for when useLedgerLive is true in a browser that supports webhid * Lint fix * Fix inline-link size Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-10-21 21:17:03 +02:00
ledgerTransportType: window.navigator.hid
? LedgerTransportTypes.webhid
: LedgerTransportTypes.u2f,
transactionSecurityCheckEnabled: false,
theme: ThemeType.os,
2020-11-03 00:41:28 +01:00
...opts.initState,
};
2018-06-04 23:21:46 +02:00
this.network = opts.network;
this.store = new ObservableStore(initState);
this.store.setMaxListeners(13);
this.openPopup = opts.openPopup;
this.tokenListController = opts.tokenListController;
this._subscribeToInfuraAvailability();
2019-02-25 20:10:13 +01:00
global.setPreference = (key, value) => {
return this.setFeatureFlag(key, value);
};
}
// PUBLIC METHODS
/**
* Sets the {@code forgottenPassword} state property
*
* @param {boolean} forgottenPassword - whether or not the user has forgotten their password
*/
2020-11-03 00:41:28 +01:00
setPasswordForgotten(forgottenPassword) {
this.store.updateState({ forgottenPassword });
}
2018-04-18 20:41:39 +02:00
/**
* Setter for the `useBlockie` property
*
* @param {boolean} val - Whether or not the user prefers blockie indicators
2018-04-18 20:41:39 +02:00
*/
2020-11-03 00:41:28 +01:00
setUseBlockie(val) {
this.store.updateState({ useBlockie: val });
2017-11-24 02:33:44 +01:00
}
Add advanced setting to enable editing nonce on confirmation screens (#7089) * Add UseNonce toggle * Get the toggle actually working and dispatching * Display nonce field on confirmation page * Remove console.log * Add placeholder * Set customNonceValue * Add nonce key/value to txParams * remove customNonceValue from component state * Use translation file and existing CSS class * Use existing TextField component * Remove console.log * Fix lint nits * Okay this sorta works? * Move nonce toggle to advanced tab * Set min to 0 * Wrap value in Number() * Add customNonceMap * Update custom nonce translation * Update styles * Reset CustomNonce * Fix lint * Get tests passing * Add customNonceValue to defaults * Fix test * Fix comments * Update tests * Use camel case * Ensure custom nonce can only be whole number * Correct font size for custom nonce input * UX improvements for custom nonce feature * Fix advanced-tab-component tests for custom nonce changes * Update title of nonce toggle in settings * Remove unused locale message * Cast custom nonce to string in confirm-transaction-base.component * Handle string conversion and invalid values for custom nonces in handler * Don't call getNonceLock in tx controller if there is a custom nonce * Set nonce details for cases where nonce is customized * Fix incorrectly use value for deciding whether to getnoncelock in approveTransaction * Default nonceLock to empty object in approveTransaction * Reapply use on nonceLock in cases where customNonceValue in approveTransaction. * Show warning message if custom nonce is higher than MetaMask's next nonce * Fix e2e test failure caused by custom nonce and 3box toggle conflict * Update nonce warning message to include the suggested nonce * Handle nextNonce comparison and update logic in lifecycle * Default nonce field to suggested nonce * Clear custom nonce on reject or confirm * Fix bug where nonces are not shown in tx list on self sent transactions * Ensure custom nonce is reset after tx is created in background * Convert customNonceValue to number in approve tranasction controller * Lint fix * Call getNextNonce after updating custom nonce
2019-09-27 06:30:36 +02:00
/**
* Setter for the `useNonceField` property
*
* @param {boolean} val - Whether or not the user prefers to set nonce
Add advanced setting to enable editing nonce on confirmation screens (#7089) * Add UseNonce toggle * Get the toggle actually working and dispatching * Display nonce field on confirmation page * Remove console.log * Add placeholder * Set customNonceValue * Add nonce key/value to txParams * remove customNonceValue from component state * Use translation file and existing CSS class * Use existing TextField component * Remove console.log * Fix lint nits * Okay this sorta works? * Move nonce toggle to advanced tab * Set min to 0 * Wrap value in Number() * Add customNonceMap * Update custom nonce translation * Update styles * Reset CustomNonce * Fix lint * Get tests passing * Add customNonceValue to defaults * Fix test * Fix comments * Update tests * Use camel case * Ensure custom nonce can only be whole number * Correct font size for custom nonce input * UX improvements for custom nonce feature * Fix advanced-tab-component tests for custom nonce changes * Update title of nonce toggle in settings * Remove unused locale message * Cast custom nonce to string in confirm-transaction-base.component * Handle string conversion and invalid values for custom nonces in handler * Don't call getNonceLock in tx controller if there is a custom nonce * Set nonce details for cases where nonce is customized * Fix incorrectly use value for deciding whether to getnoncelock in approveTransaction * Default nonceLock to empty object in approveTransaction * Reapply use on nonceLock in cases where customNonceValue in approveTransaction. * Show warning message if custom nonce is higher than MetaMask's next nonce * Fix e2e test failure caused by custom nonce and 3box toggle conflict * Update nonce warning message to include the suggested nonce * Handle nextNonce comparison and update logic in lifecycle * Default nonce field to suggested nonce * Clear custom nonce on reject or confirm * Fix bug where nonces are not shown in tx list on self sent transactions * Ensure custom nonce is reset after tx is created in background * Convert customNonceValue to number in approve tranasction controller * Lint fix * Call getNextNonce after updating custom nonce
2019-09-27 06:30:36 +02:00
*/
2020-11-03 00:41:28 +01:00
setUseNonceField(val) {
this.store.updateState({ useNonceField: val });
Add advanced setting to enable editing nonce on confirmation screens (#7089) * Add UseNonce toggle * Get the toggle actually working and dispatching * Display nonce field on confirmation page * Remove console.log * Add placeholder * Set customNonceValue * Add nonce key/value to txParams * remove customNonceValue from component state * Use translation file and existing CSS class * Use existing TextField component * Remove console.log * Fix lint nits * Okay this sorta works? * Move nonce toggle to advanced tab * Set min to 0 * Wrap value in Number() * Add customNonceMap * Update custom nonce translation * Update styles * Reset CustomNonce * Fix lint * Get tests passing * Add customNonceValue to defaults * Fix test * Fix comments * Update tests * Use camel case * Ensure custom nonce can only be whole number * Correct font size for custom nonce input * UX improvements for custom nonce feature * Fix advanced-tab-component tests for custom nonce changes * Update title of nonce toggle in settings * Remove unused locale message * Cast custom nonce to string in confirm-transaction-base.component * Handle string conversion and invalid values for custom nonces in handler * Don't call getNonceLock in tx controller if there is a custom nonce * Set nonce details for cases where nonce is customized * Fix incorrectly use value for deciding whether to getnoncelock in approveTransaction * Default nonceLock to empty object in approveTransaction * Reapply use on nonceLock in cases where customNonceValue in approveTransaction. * Show warning message if custom nonce is higher than MetaMask's next nonce * Fix e2e test failure caused by custom nonce and 3box toggle conflict * Update nonce warning message to include the suggested nonce * Handle nextNonce comparison and update logic in lifecycle * Default nonce field to suggested nonce * Clear custom nonce on reject or confirm * Fix bug where nonces are not shown in tx list on self sent transactions * Ensure custom nonce is reset after tx is created in background * Convert customNonceValue to number in approve tranasction controller * Lint fix * Call getNextNonce after updating custom nonce
2019-09-27 06:30:36 +02:00
}
/**
* Setter for the `usePhishDetect` property
*
* @param {boolean} val - Whether or not the user prefers phishing domain protection
*/
2020-11-03 00:41:28 +01:00
setUsePhishDetect(val) {
this.store.updateState({ usePhishDetect: val });
}
/**
* Setter for the `useMultiAccountBalanceChecker` property
*
* @param {boolean} val - Whether or not the user prefers to turn off/on all security settings
*/
setUseMultiAccountBalanceChecker(val) {
this.store.updateState({ useMultiAccountBalanceChecker: val });
}
/**
* Setter for the `useTokenDetection` property
*
* @param {boolean} val - Whether or not the user prefers to use the static token list or dynamic token list from the API
*/
setUseTokenDetection(val) {
this.store.updateState({ useTokenDetection: val });
this.tokenListController.updatePreventPollingOnNetworkRestart(!val);
if (val) {
this.tokenListController.start();
} else {
this.tokenListController.clearingTokenListData();
this.tokenListController.stop();
}
}
/**
* Setter for the `useNftDetection` property
*
* @param {boolean} useNftDetection - Whether or not the user prefers to autodetect NFTs.
*/
setUseNftDetection(useNftDetection) {
this.store.updateState({ useNftDetection });
}
/**
* Setter for the `useCurrencyRateCheck` property
*
* @param {boolean} val - Whether or not the user prefers to use currency rate check for ETH and tokens.
*/
setUseCurrencyRateCheck(val) {
this.store.updateState({ useCurrencyRateCheck: val });
}
/**
* Setter for the `openSeaEnabled` property
*
* @param {boolean} openSeaEnabled - Whether or not the user prefers to use the OpenSea API for NFTs data.
*/
setOpenSeaEnabled(openSeaEnabled) {
this.store.updateState({
openSeaEnabled,
});
}
/**
* Setter for the `advancedGasFee` property
*
* @param {object} val - holds the maxBaseFee and PriorityFee that the user set as default advanced settings.
*/
setAdvancedGasFee(val) {
this.store.updateState({ advancedGasFee: val });
}
/**
* Setter for the `theme` property
*
* @param {string} val - 'default' or 'dark' value based on the mode selected by user.
*/
setTheme(val) {
this.store.updateState({ theme: val });
}
/**
* Setter for the `transactionSecurityCheckEnabled` property
*
* @param transactionSecurityCheckEnabled
*/
setTransactionSecurityCheckEnabled(transactionSecurityCheckEnabled) {
this.store.updateState({
transactionSecurityCheckEnabled,
});
}
/**
* Add new methodData to state, to avoid requesting this information again through Infura
*
* @param {string} fourBytePrefix - Four-byte method signature
* @param {string} methodData - Corresponding data method
*/
2020-11-03 00:41:28 +01:00
addKnownMethodData(fourBytePrefix, methodData) {
const { knownMethodData } = this.store.getState();
knownMethodData[fourBytePrefix] = methodData;
this.store.updateState({ knownMethodData });
}
2018-04-18 20:41:39 +02:00
/**
* Setter for the `currentLocale` property
*
* @param {string} key - he preferred language locale key
2018-04-18 20:41:39 +02:00
*/
2020-11-03 00:41:28 +01:00
setCurrentLocale(key) {
const textDirection = ['ar', 'dv', 'fa', 'he', 'ku'].includes(key)
? 'rtl'
: 'auto';
this.store.updateState({
currentLocale: key,
textDirection,
});
return textDirection;
2018-03-16 01:29:45 +01:00
}
/**
* Updates identities to only include specified addresses. Removes identities
* not included in addresses array
*
* @param {string[]} addresses - An array of hex addresses
*/
2020-11-03 00:41:28 +01:00
setAddresses(addresses) {
const oldIdentities = this.store.getState().identities;
2018-07-27 22:05:12 +02:00
const identities = addresses.reduce((ids, address, index) => {
const oldId = oldIdentities[address] || {};
ids[address] = { name: `Account ${index + 1}`, address, ...oldId };
return ids;
}, {});
this.store.updateState({ identities });
}
2018-07-11 06:20:40 +02:00
/**
* Removes an address from state
*
* @param {string} address - A hex address
* @returns {string} the address that was removed
2018-07-11 06:20:40 +02:00
*/
2020-11-03 00:41:28 +01:00
removeAddress(address) {
const { identities } = this.store.getState();
2018-07-11 06:20:40 +02:00
if (!identities[address]) {
throw new Error(`${address} can't be deleted cause it was not found`);
2018-07-11 06:20:40 +02:00
}
delete identities[address];
this.store.updateState({ identities });
2018-07-11 06:20:40 +02:00
// If the selected account is no longer valid,
// select an arbitrary other account:
if (address === this.getSelectedAddress()) {
const [selected] = Object.keys(identities);
this.setSelectedAddress(selected);
2018-07-11 06:20:40 +02:00
}
return address;
2018-07-11 06:20:40 +02:00
}
/**
* Adds addresses to the identities object without removing identities
*
* @param {string[]} addresses - An array of hex addresses
*/
2020-11-03 00:41:28 +01:00
addAddresses(addresses) {
const { identities } = this.store.getState();
addresses.forEach((address) => {
// skip if already exists
if (identities[address]) {
return;
}
// add missing identity
const identityCount = Object.keys(identities).length;
identities[address] = { name: `Account ${identityCount + 1}`, address };
});
this.store.updateState({ identities });
}
/**
* Synchronizes identity entries with known accounts.
* Removes any unknown identities, and returns the resulting selected address.
*
* @param {Array<string>} addresses - known to the vault.
* @returns {Promise<string>} selectedAddress the selected address.
*/
2020-11-03 00:41:28 +01:00
syncAddresses(addresses) {
if (!Array.isArray(addresses) || addresses.length === 0) {
2021-06-29 00:38:20 +02:00
throw new Error('Expected non-empty array of addresses. Error #11201');
}
const { identities, lostIdentities } = this.store.getState();
const newlyLost = {};
Object.keys(identities).forEach((identity) => {
if (!addresses.includes(identity)) {
newlyLost[identity] = identities[identity];
delete identities[identity];
}
});
2018-06-04 23:21:46 +02:00
// Identities are no longer present.
if (Object.keys(newlyLost).length > 0) {
// store lost accounts
2020-07-21 23:10:45 +02:00
Object.keys(newlyLost).forEach((key) => {
lostIdentities[key] = newlyLost[key];
});
2018-06-04 23:21:46 +02:00
}
this.store.updateState({ identities, lostIdentities });
this.addAddresses(addresses);
2018-06-05 00:18:12 +02:00
// If the selected account is no longer valid,
// select an arbitrary other account:
let selected = this.getSelectedAddress();
if (!addresses.includes(selected)) {
[selected] = addresses;
this.setSelectedAddress(selected);
}
return selected;
}
2018-04-18 20:41:39 +02:00
/**
* Setter for the `selectedAddress` property
*
* @param {string} _address - A new hex address for an account
2018-04-18 20:41:39 +02:00
*/
2020-11-03 00:41:28 +01:00
setSelectedAddress(_address) {
const address = normalizeAddress(_address);
Fix order of accounts in `eth_accounts` response (#8342) * Fix order of accounts in `eth_accounts` response The accounts returned by `eth_accounts` were in a fixed order - the order in which the keyring returned them - rather than ordered with the selected account first. The accounts returned by the `accountsChanged` event were ordered with the selected account first, but the same order wasn't used for `eth_accounts`. We needed to store additional state in order to determine the correct account order correctly on all dapps. We had only been storing the current selected account, but since we also need to determine the primary account per dapp (i.e. the last "selected" account among the accounts exposed to that dapp), that wasn't enough. A `lastSelected` property has been added to each identity in the preferences controller to keep track of the last selected time. This property is set to the current time (in milliseconds) whenever a new selection is made. The accounts returned with `accountsChanged` and by `eth_accounts` are both ordered by this property. The `updatePermittedAccounts` function was merged with the internal methods for responding to account selection, to keep things simpler. It wasn't called externally anyway, so it wasn't needed in the public API. * Remove caveat update upon change in selected account The order of accounts in the caveat isn't meaningful, so the caveat doesn't need to be updated when the accounts get re-ordered. * Emit event regardless of account order Now that we're no longer relying upon the caveat for the account order, we also have no way of knowing if a particular account selection resulted in a change in order or not. The notification is now emitted whenever an exposed account is selected - even if the order stayed the same. The inpage provider currently caches the account order, so it can be relied upon to ignore these redundant events. We were already emiting redundant `accountsChanged` events in some cases anyway.
2020-04-16 20:20:01 +02:00
const { identities } = this.store.getState();
const selectedIdentity = identities[address];
Fix order of accounts in `eth_accounts` response (#8342) * Fix order of accounts in `eth_accounts` response The accounts returned by `eth_accounts` were in a fixed order - the order in which the keyring returned them - rather than ordered with the selected account first. The accounts returned by the `accountsChanged` event were ordered with the selected account first, but the same order wasn't used for `eth_accounts`. We needed to store additional state in order to determine the correct account order correctly on all dapps. We had only been storing the current selected account, but since we also need to determine the primary account per dapp (i.e. the last "selected" account among the accounts exposed to that dapp), that wasn't enough. A `lastSelected` property has been added to each identity in the preferences controller to keep track of the last selected time. This property is set to the current time (in milliseconds) whenever a new selection is made. The accounts returned with `accountsChanged` and by `eth_accounts` are both ordered by this property. The `updatePermittedAccounts` function was merged with the internal methods for responding to account selection, to keep things simpler. It wasn't called externally anyway, so it wasn't needed in the public API. * Remove caveat update upon change in selected account The order of accounts in the caveat isn't meaningful, so the caveat doesn't need to be updated when the accounts get re-ordered. * Emit event regardless of account order Now that we're no longer relying upon the caveat for the account order, we also have no way of knowing if a particular account selection resulted in a change in order or not. The notification is now emitted whenever an exposed account is selected - even if the order stayed the same. The inpage provider currently caches the account order, so it can be relied upon to ignore these redundant events. We were already emiting redundant `accountsChanged` events in some cases anyway.
2020-04-16 20:20:01 +02:00
if (!selectedIdentity) {
throw new Error(`Identity for '${address} not found`);
Fix order of accounts in `eth_accounts` response (#8342) * Fix order of accounts in `eth_accounts` response The accounts returned by `eth_accounts` were in a fixed order - the order in which the keyring returned them - rather than ordered with the selected account first. The accounts returned by the `accountsChanged` event were ordered with the selected account first, but the same order wasn't used for `eth_accounts`. We needed to store additional state in order to determine the correct account order correctly on all dapps. We had only been storing the current selected account, but since we also need to determine the primary account per dapp (i.e. the last "selected" account among the accounts exposed to that dapp), that wasn't enough. A `lastSelected` property has been added to each identity in the preferences controller to keep track of the last selected time. This property is set to the current time (in milliseconds) whenever a new selection is made. The accounts returned with `accountsChanged` and by `eth_accounts` are both ordered by this property. The `updatePermittedAccounts` function was merged with the internal methods for responding to account selection, to keep things simpler. It wasn't called externally anyway, so it wasn't needed in the public API. * Remove caveat update upon change in selected account The order of accounts in the caveat isn't meaningful, so the caveat doesn't need to be updated when the accounts get re-ordered. * Emit event regardless of account order Now that we're no longer relying upon the caveat for the account order, we also have no way of knowing if a particular account selection resulted in a change in order or not. The notification is now emitted whenever an exposed account is selected - even if the order stayed the same. The inpage provider currently caches the account order, so it can be relied upon to ignore these redundant events. We were already emiting redundant `accountsChanged` events in some cases anyway.
2020-04-16 20:20:01 +02:00
}
selectedIdentity.lastSelected = Date.now();
this.store.updateState({ identities, selectedAddress: address });
}
/**
* Getter for the `selectedAddress` property
*
* @returns {string} The hex address for the currently selected account
*/
2020-11-03 00:41:28 +01:00
getSelectedAddress() {
return this.store.getState().selectedAddress;
}
/**
* Sets a custom label for an account
*
* @param {string} account - the account to set a label for
* @param {string} label - the custom label for the account
* @returns {Promise<string>}
*/
async setAccountLabel(account, label) {
if (!account) {
2020-11-03 00:41:28 +01:00
throw new Error(
`setAccountLabel requires a valid address, got ${String(account)}`,
);
}
const address = normalizeAddress(account);
const { identities } = this.store.getState();
identities[address] = identities[address] || {};
identities[address].name = label;
this.store.updateState({ identities });
return label;
}
2018-04-18 20:41:39 +02:00
/**
* Updates the `featureFlags` property, which is an object. One property within that object will be set to a boolean.
*
* @param {string} feature - A key that corresponds to a UI feature.
* @param {boolean} activated - Indicates whether or not the UI feature should be displayed
* @returns {Promise<object>} Promises a new object; the updated featureFlags object.
2018-04-18 20:41:39 +02:00
*/
async setFeatureFlag(feature, activated) {
const currentFeatureFlags = this.store.getState().featureFlags;
2017-11-14 17:04:55 +01:00
const updatedFeatureFlags = {
...currentFeatureFlags,
[feature]: activated,
};
2017-11-14 17:04:55 +01:00
this.store.updateState({ featureFlags: updatedFeatureFlags });
2017-11-16 20:28:59 +01:00
return updatedFeatureFlags;
2017-11-14 17:04:55 +01:00
}
/**
* Updates the `preferences` property, which is an object. These are user-controlled features
* found in the settings page.
*
* @param {string} preference - The preference to enable or disable.
* @param {boolean} value - Indicates whether or not the preference should be enabled or disabled.
* @returns {Promise<object>} Promises a new object; the updated preferences object.
*/
async setPreference(preference, value) {
const currentPreferences = this.getPreferences();
const updatedPreferences = {
...currentPreferences,
[preference]: value,
};
this.store.updateState({ preferences: updatedPreferences });
return updatedPreferences;
}
/**
* A getter for the `preferences` property
*
* @returns {object} A key-boolean map of user-selected preferences.
*/
2020-11-03 00:41:28 +01:00
getPreferences() {
return this.store.getState().preferences;
}
/**
* A getter for the `ipfsGateway` property
*
* @returns {string} The current IPFS gateway domain
*/
2020-11-03 00:41:28 +01:00
getIpfsGateway() {
return this.store.getState().ipfsGateway;
}
/**
* A setter for the `ipfsGateway` property
*
* @param {string} domain - The new IPFS gateway domain
* @returns {Promise<string>} A promise of the update IPFS gateway domain
*/
async setIpfsGateway(domain) {
this.store.updateState({ ipfsGateway: domain });
return domain;
}
2021-04-26 20:05:48 +02:00
/**
* A setter for the `ledgerTransportType` property.
*
Connect Ledger via WebHID (#12411) * Connect ledger via webhid if that option is available * Explicitly setting preference for webhid * Use ledgerTransportType enum instead of booleans for ledger live and webhid preferences * Use single setLEdgerTransport preference methods and property * Temp * Lint fix * Unit test fix * Remove async keyword from setLedgerTransportPreference function definition in preferences controller * Fix ledgelive setting toggle logic * Migrate useLedgerLive preference property to ledgerTransportType * Use shared constants for ledger transport type enums * Use constant for ledger usb vendor id * Use correct property to check if ledgerLive preference is set when deciding whether to ask for webhid connection * Update eth-ledger-bridge-keyring to v0.9.0 * Only show ledger live transaction helper messages if using ledger live * Only show ledger live part of tutorial if ledger live setting is on * Fix ledger related prop type errors * Explicitly use u2f enum instead of empty string as a transport type; default transport type to webhid if available; use constants for u2f and webhid * Cleanup * Wrap ledger webhid device request in try/catch * Clean up * Lint fix * Ensure user can easily connect their ledger wallet when they need to. * Fix locales * Fix/improve locales changes * Remove unused isFirefox property from confirm-transaction-base.container.js * Disable transaction and message signing confirmation if ledger webhid requires connection * Ensure translation keys for ledger connection options in settings dropdown can be properly detected by verify-locales * Drop .component from ledger-instruction-field file name * Move renderLedgerLiveStep to module scope * Remove ledgerLive from function and message names in ledger-instruction-field * Wrap ledger connection logic in ledger-instruction-field in try catch * Clean up signature-request.component.js * Check whether the signing address, and not the selected address, is a ledger account in singature-request.container * Ensure ledger instructions and webhid connection button are shown on signature-request-original signatures * Improve webhid selection handling in select-ledger-transport-type onChange handler * Move metamask redux focused ledger selectors to metamask duck * Lint fix * Use async await in checkWebHidStatusRef.current * Remove unnecessary use of ref in ledger-instruction-field.js * Lint fix * Remove unnecessary try/catch in ledger-instruction-field.js * Check if from address, not selected address, is from a ledger account in confirm-approve * Move findKeyringForAddress to metamask duck * Fix typo in function name * Ensure isEqualCaseInsensitive handles possible differences in address casing * Fix Learn More link size in advanced settings tab * Update app/scripts/migrations/066.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Update ui/pages/settings/advanced-tab/advanced-tab.component.test.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Add jsdoc comments for new selectors * Use jest.spyOn for mocking navigator in ledger webhid migration tests * Use LEDGER_TRANSPORT_TYPES values to set proptype of ledgerTransportType * Use LEDGER_TRANSPORT_TYPES values to set proptype of ledgerTransportType * Fix font size of link in ledger connection description in advanced settings * Fix return type in setLedgerTransportPreference comment * Clean up connectHardware code for webhid connection in actions.js * Update app/scripts/migrations/066.test.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Update ui/ducks/metamask/metamask.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Add migration test for when useLedgerLive is true in a browser that supports webhid * Lint fix * Fix inline-link size Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-10-21 21:17:03 +02:00
* @param {string} ledgerTransportType - Either 'ledgerLive', 'webhid' or 'u2f'
* @returns {string} The transport type that was set.
2021-04-26 20:05:48 +02:00
*/
Connect Ledger via WebHID (#12411) * Connect ledger via webhid if that option is available * Explicitly setting preference for webhid * Use ledgerTransportType enum instead of booleans for ledger live and webhid preferences * Use single setLEdgerTransport preference methods and property * Temp * Lint fix * Unit test fix * Remove async keyword from setLedgerTransportPreference function definition in preferences controller * Fix ledgelive setting toggle logic * Migrate useLedgerLive preference property to ledgerTransportType * Use shared constants for ledger transport type enums * Use constant for ledger usb vendor id * Use correct property to check if ledgerLive preference is set when deciding whether to ask for webhid connection * Update eth-ledger-bridge-keyring to v0.9.0 * Only show ledger live transaction helper messages if using ledger live * Only show ledger live part of tutorial if ledger live setting is on * Fix ledger related prop type errors * Explicitly use u2f enum instead of empty string as a transport type; default transport type to webhid if available; use constants for u2f and webhid * Cleanup * Wrap ledger webhid device request in try/catch * Clean up * Lint fix * Ensure user can easily connect their ledger wallet when they need to. * Fix locales * Fix/improve locales changes * Remove unused isFirefox property from confirm-transaction-base.container.js * Disable transaction and message signing confirmation if ledger webhid requires connection * Ensure translation keys for ledger connection options in settings dropdown can be properly detected by verify-locales * Drop .component from ledger-instruction-field file name * Move renderLedgerLiveStep to module scope * Remove ledgerLive from function and message names in ledger-instruction-field * Wrap ledger connection logic in ledger-instruction-field in try catch * Clean up signature-request.component.js * Check whether the signing address, and not the selected address, is a ledger account in singature-request.container * Ensure ledger instructions and webhid connection button are shown on signature-request-original signatures * Improve webhid selection handling in select-ledger-transport-type onChange handler * Move metamask redux focused ledger selectors to metamask duck * Lint fix * Use async await in checkWebHidStatusRef.current * Remove unnecessary use of ref in ledger-instruction-field.js * Lint fix * Remove unnecessary try/catch in ledger-instruction-field.js * Check if from address, not selected address, is from a ledger account in confirm-approve * Move findKeyringForAddress to metamask duck * Fix typo in function name * Ensure isEqualCaseInsensitive handles possible differences in address casing * Fix Learn More link size in advanced settings tab * Update app/scripts/migrations/066.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Update ui/pages/settings/advanced-tab/advanced-tab.component.test.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Add jsdoc comments for new selectors * Use jest.spyOn for mocking navigator in ledger webhid migration tests * Use LEDGER_TRANSPORT_TYPES values to set proptype of ledgerTransportType * Use LEDGER_TRANSPORT_TYPES values to set proptype of ledgerTransportType * Fix font size of link in ledger connection description in advanced settings * Fix return type in setLedgerTransportPreference comment * Clean up connectHardware code for webhid connection in actions.js * Update app/scripts/migrations/066.test.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Update ui/ducks/metamask/metamask.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Add migration test for when useLedgerLive is true in a browser that supports webhid * Lint fix * Fix inline-link size Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-10-21 21:17:03 +02:00
setLedgerTransportPreference(ledgerTransportType) {
this.store.updateState({ ledgerTransportType });
return ledgerTransportType;
2021-04-26 20:05:48 +02:00
}
/**
* A getter for the `ledgerTransportType` property.
*
* @returns {string} The current preferred Ledger transport type.
2021-04-26 20:05:48 +02:00
*/
Connect Ledger via WebHID (#12411) * Connect ledger via webhid if that option is available * Explicitly setting preference for webhid * Use ledgerTransportType enum instead of booleans for ledger live and webhid preferences * Use single setLEdgerTransport preference methods and property * Temp * Lint fix * Unit test fix * Remove async keyword from setLedgerTransportPreference function definition in preferences controller * Fix ledgelive setting toggle logic * Migrate useLedgerLive preference property to ledgerTransportType * Use shared constants for ledger transport type enums * Use constant for ledger usb vendor id * Use correct property to check if ledgerLive preference is set when deciding whether to ask for webhid connection * Update eth-ledger-bridge-keyring to v0.9.0 * Only show ledger live transaction helper messages if using ledger live * Only show ledger live part of tutorial if ledger live setting is on * Fix ledger related prop type errors * Explicitly use u2f enum instead of empty string as a transport type; default transport type to webhid if available; use constants for u2f and webhid * Cleanup * Wrap ledger webhid device request in try/catch * Clean up * Lint fix * Ensure user can easily connect their ledger wallet when they need to. * Fix locales * Fix/improve locales changes * Remove unused isFirefox property from confirm-transaction-base.container.js * Disable transaction and message signing confirmation if ledger webhid requires connection * Ensure translation keys for ledger connection options in settings dropdown can be properly detected by verify-locales * Drop .component from ledger-instruction-field file name * Move renderLedgerLiveStep to module scope * Remove ledgerLive from function and message names in ledger-instruction-field * Wrap ledger connection logic in ledger-instruction-field in try catch * Clean up signature-request.component.js * Check whether the signing address, and not the selected address, is a ledger account in singature-request.container * Ensure ledger instructions and webhid connection button are shown on signature-request-original signatures * Improve webhid selection handling in select-ledger-transport-type onChange handler * Move metamask redux focused ledger selectors to metamask duck * Lint fix * Use async await in checkWebHidStatusRef.current * Remove unnecessary use of ref in ledger-instruction-field.js * Lint fix * Remove unnecessary try/catch in ledger-instruction-field.js * Check if from address, not selected address, is from a ledger account in confirm-approve * Move findKeyringForAddress to metamask duck * Fix typo in function name * Ensure isEqualCaseInsensitive handles possible differences in address casing * Fix Learn More link size in advanced settings tab * Update app/scripts/migrations/066.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Update ui/pages/settings/advanced-tab/advanced-tab.component.test.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Add jsdoc comments for new selectors * Use jest.spyOn for mocking navigator in ledger webhid migration tests * Use LEDGER_TRANSPORT_TYPES values to set proptype of ledgerTransportType * Use LEDGER_TRANSPORT_TYPES values to set proptype of ledgerTransportType * Fix font size of link in ledger connection description in advanced settings * Fix return type in setLedgerTransportPreference comment * Clean up connectHardware code for webhid connection in actions.js * Update app/scripts/migrations/066.test.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Update ui/ducks/metamask/metamask.js Co-authored-by: Mark Stacey <markjstacey@gmail.com> * Add migration test for when useLedgerLive is true in a browser that supports webhid * Lint fix * Fix inline-link size Co-authored-by: Mark Stacey <markjstacey@gmail.com>
2021-10-21 21:17:03 +02:00
getLedgerTransportPreference() {
return this.store.getState().ledgerTransportType;
2021-04-26 20:05:48 +02:00
}
/**
* A setter for the user preference to dismiss the seed phrase backup reminder
*
* @param {bool} dismissSeedBackUpReminder - User preference for dismissing the back up reminder.
*/
async setDismissSeedBackUpReminder(dismissSeedBackUpReminder) {
await this.store.updateState({
dismissSeedBackUpReminder,
});
}
/**
* A setter for the user preference to enable/disable rpc methods
*
* @param {string} methodName - The RPC method name to change the setting of
* @param {bool} isEnabled - true to enable the rpc method
*/
async setDisabledRpcMethodPreference(methodName, isEnabled) {
const currentRpcMethodPreferences =
this.store.getState().disabledRpcMethodPreferences;
const updatedRpcMethodPreferences = {
...currentRpcMethodPreferences,
[methodName]: isEnabled,
};
this.store.updateState({
disabledRpcMethodPreferences: updatedRpcMethodPreferences,
});
}
getRpcMethodPreferences() {
return this.store.getState().disabledRpcMethodPreferences;
}
//
// PRIVATE METHODS
//
2018-08-07 00:28:47 +02:00
_subscribeToInfuraAvailability() {
this.network.on(NETWORK_EVENTS.INFURA_IS_BLOCKED, () => {
this._setInfuraBlocked(true);
});
this.network.on(NETWORK_EVENTS.INFURA_IS_UNBLOCKED, () => {
this._setInfuraBlocked(false);
});
}
/**
*
* A setter for the `infuraBlocked` property
*
* @param {boolean} isBlocked - Bool indicating whether Infura is blocked
*/
_setInfuraBlocked(isBlocked) {
const { infuraBlocked } = this.store.getState();
if (infuraBlocked === isBlocked) {
return;
}
this.store.updateState({ infuraBlocked: isBlocked });
}
}