1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-27 04:46:10 +01:00
metamask-extension/ui/ducks/app/app.js
Dan J Miller 904dad256f 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-11-04 11:48:52 -07:00

390 lines
8.6 KiB
JavaScript

import { WEBHID_CONNECTED_STATUSES } from '../../../shared/constants/hardware-wallets';
import * as actionConstants from '../../store/actionConstants';
// actionConstants
const SET_THREEBOX_LAST_UPDATED = 'metamask/app/SET_THREEBOX_LAST_UPDATED';
export default function reduceApp(state = {}, action) {
// default state
const appState = {
shouldClose: false,
menuOpen: false,
modal: {
open: false,
modalState: {
name: null,
props: {},
},
previousModalState: {
name: null,
},
},
alertOpen: false,
alertMessage: null,
qrCodeData: null,
networkDropdownOpen: false,
accountDetail: {
subview: 'transactions',
},
// Used to display loading indicator
isLoading: false,
// Used to display error text
warning: null,
buyView: {},
isMouseUser: false,
defaultHdPaths: {
trezor: `m/44'/60'/0'/0`,
ledger: `m/44'/60'/0'/0/0`,
},
networksTabSelectedRpcUrl: '',
networksTabIsInAddMode: false,
loadingMethodData: false,
show3BoxModalAfterImport: false,
threeBoxLastUpdated: null,
requestAccountTabs: {},
openMetaMaskTabs: {},
currentWindowTab: {},
showWhatsNewPopup: true,
singleExceptions: {
testKey: null,
},
gasLoadingAnimationIsShowing: false,
ledgerWebHidConnectedStatus: WEBHID_CONNECTED_STATUSES.UNKNOWN,
...state,
};
switch (action.type) {
// dropdown methods
case actionConstants.NETWORK_DROPDOWN_OPEN:
return {
...appState,
networkDropdownOpen: true,
};
case actionConstants.NETWORK_DROPDOWN_CLOSE:
return {
...appState,
networkDropdownOpen: false,
};
// alert methods
case actionConstants.ALERT_OPEN:
return {
...appState,
alertOpen: true,
alertMessage: action.value,
};
case actionConstants.ALERT_CLOSE:
return {
...appState,
alertOpen: false,
alertMessage: null,
};
// qr scanner methods
case actionConstants.QR_CODE_DETECTED:
return {
...appState,
qrCodeData: action.value,
};
// modal methods:
case actionConstants.MODAL_OPEN: {
const { name, ...modalProps } = action.payload;
return {
...appState,
modal: {
open: true,
modalState: {
name,
props: { ...modalProps },
},
previousModalState: { ...appState.modal.modalState },
},
};
}
case actionConstants.MODAL_CLOSE:
return {
...appState,
modal: Object.assign(
appState.modal,
{ open: false },
{ modalState: { name: null, props: {} } },
{ previousModalState: appState.modal.modalState },
),
};
case actionConstants.CLEAR_ACCOUNT_DETAILS:
return {
...appState,
accountDetail: {},
};
case actionConstants.FORGOT_PASSWORD:
return {
...appState,
forgottenPassword: action.value,
};
case actionConstants.SHOW_SEND_TOKEN_PAGE:
return {
...appState,
warning: null,
};
case actionConstants.LOCK_METAMASK:
return {
...appState,
warning: null,
};
// accounts
case actionConstants.GO_HOME:
return {
...appState,
accountDetail: {
subview: 'transactions',
accountExport: 'none',
privateKey: '',
},
warning: null,
};
case actionConstants.SHOW_ACCOUNT_DETAIL:
return {
...appState,
forgottenPassword: appState.forgottenPassword
? !appState.forgottenPassword
: null,
accountDetail: {
subview: 'transactions',
accountExport: 'none',
privateKey: '',
},
};
case actionConstants.SHOW_ACCOUNTS_PAGE:
return {
...appState,
isLoading: false,
warning: null,
scrollToBottom: false,
forgottenPassword: false,
};
case actionConstants.SHOW_CONF_TX_PAGE:
return {
...appState,
txId: action.id,
warning: null,
isLoading: false,
};
case actionConstants.COMPLETED_TX:
if (action.value.unconfirmedActionsCount > 0) {
return {
...appState,
txId: null,
warning: null,
};
}
return {
...appState,
// indicate notification should close
shouldClose: true,
warning: null,
txId: null,
accountDetail: {
subview: 'transactions',
},
};
case actionConstants.TRANSACTION_ERROR:
return {
...appState,
};
case actionConstants.UNLOCK_FAILED:
return {
...appState,
warning: action.value || 'Incorrect password. Try again.',
};
case actionConstants.UNLOCK_SUCCEEDED:
return {
...appState,
warning: '',
};
case actionConstants.SET_HARDWARE_WALLET_DEFAULT_HD_PATH: {
const { device, path } = action.value;
const newDefaults = { ...appState.defaultHdPaths };
newDefaults[device] = path;
return {
...appState,
defaultHdPaths: newDefaults,
};
}
case actionConstants.SHOW_LOADING:
return {
...appState,
isLoading: true,
loadingMessage: action.value,
};
case actionConstants.HIDE_LOADING:
return {
...appState,
isLoading: false,
};
case actionConstants.DISPLAY_WARNING:
return {
...appState,
warning: action.value,
isLoading: false,
};
case actionConstants.HIDE_WARNING:
return {
...appState,
warning: undefined,
};
case actionConstants.SHOW_PRIVATE_KEY:
return {
...appState,
accountDetail: {
subview: 'export',
accountExport: 'completed',
privateKey: action.value,
},
};
case actionConstants.SET_MOUSE_USER_STATE:
return {
...appState,
isMouseUser: action.value,
};
case actionConstants.SET_SELECTED_SETTINGS_RPC_URL:
return {
...appState,
networksTabSelectedRpcUrl: action.value,
};
case actionConstants.SET_NETWORKS_TAB_ADD_MODE:
return {
...appState,
networksTabIsInAddMode: action.value,
};
case actionConstants.LOADING_METHOD_DATA_STARTED:
return {
...appState,
loadingMethodData: true,
};
case actionConstants.LOADING_METHOD_DATA_FINISHED:
return {
...appState,
loadingMethodData: false,
};
case SET_THREEBOX_LAST_UPDATED:
return {
...appState,
threeBoxLastUpdated: action.value,
};
case actionConstants.SET_REQUEST_ACCOUNT_TABS:
return {
...appState,
requestAccountTabs: action.value,
};
case actionConstants.SET_OPEN_METAMASK_TAB_IDS:
return {
...appState,
openMetaMaskTabs: action.value,
};
case actionConstants.SET_CURRENT_WINDOW_TAB:
return {
...appState,
currentWindowTab: action.value,
};
case actionConstants.HIDE_WHATS_NEW_POPUP:
return {
...appState,
showWhatsNewPopup: false,
};
case actionConstants.CAPTURE_SINGLE_EXCEPTION:
return {
...appState,
singleExceptions: {
...appState.singleExceptions,
[action.value]: null,
},
};
case actionConstants.TOGGLE_GAS_LOADING_ANIMATION:
return {
...appState,
gasLoadingAnimationIsShowing: action.value,
};
case actionConstants.SET_WEBHID_CONNECTED_STATUS:
return {
...appState,
ledgerWebHidConnectedStatus: action.value,
};
default:
return appState;
}
}
// Action Creators
export function setThreeBoxLastUpdated(lastUpdated) {
return {
type: SET_THREEBOX_LAST_UPDATED,
value: lastUpdated,
};
}
export function hideWhatsNewPopup() {
return {
type: actionConstants.HIDE_WHATS_NEW_POPUP,
};
}
export function toggleGasLoadingAnimation(value) {
return { type: actionConstants.TOGGLE_GAS_LOADING_ANIMATION, value };
}
export function setLedgerWebHidConnectedStatus(value) {
return { type: actionConstants.SET_WEBHID_CONNECTED_STATUS, value };
}
// Selectors
export function getQrCodeData(state) {
return state.appState.qrCodeData;
}
export function getGasLoadingAnimationIsShowing(state) {
return state.appState.gasLoadingAnimationIsShowing;
}
export function getLedgerWebHidConnectedStatus(state) {
return state.appState.ledgerWebHidConnectedStatus;
}