Skip to content

Commit

Permalink
multi: Add ledger ui.
Browse files Browse the repository at this point in the history
Copy trezor elements and apply to ledger where possible.
  • Loading branch information
JoeGruffins committed Sep 25, 2023
1 parent 1c7be16 commit 36a2091
Show file tree
Hide file tree
Showing 57 changed files with 804 additions and 140 deletions.
7 changes: 5 additions & 2 deletions app/actions/DaemonActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { stopNotifcations } from "./NotificationActions";
import { saveSettings, updateStateSettingsChanged } from "./SettingsActions";
import { rescanCancel, showCantCloseModal } from "./ControlActions";
import { enableTrezor } from "./TrezorActions";
import { enableLedger } from "./LedgerActions";
import {
DEX_LOGOUT_ATTEMPT,
DEX_LOGOUT_SUCCESS,
Expand Down Expand Up @@ -309,7 +310,7 @@ export const removeWallet = (selectedWallet) => (dispatch) => {
// selectedWallet = {
// label: newWalletName,
// value: {
// wallet: newWalletName, isWatchingOnly, isTrezor, isNew,
// wallet: newWalletName, isWatchingOnly, isTrezor, isLedger, isNew
// network: isTestNet ? "testnet" : "mainnet"
// }
// }
Expand All @@ -336,7 +337,8 @@ export const createWallet = (selectedWallet) => (dispatch, getState) =>
dispatch({
isWatchingOnly: selectedWallet.value.isWatchingOnly,
createNewWallet: selectedWallet.value.isNew,
isTrezor: selectedWallet.value.istrezor,
isTrezor: selectedWallet.value.isTrezor,
isLedger: selectedWallet.value.isLedger,
type: WALLETCREATED
});
dispatch(setSelectedWallet(selectedWallet));
Expand Down Expand Up @@ -509,6 +511,7 @@ export const startWallet =
confirmDexSeed
});
selectedWallet.value.isTrezor && dispatch(enableTrezor());
selectedWallet.value.isLedger && dispatch(enableLedger());
await dispatch(getVersionServiceAttempt());
await dispatch(openWalletAttempt("", false, selectedWallet));
return discoverAccountsComplete;
Expand Down
21 changes: 6 additions & 15 deletions app/actions/LedgerActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
const coin = "decred";

import * as selectors from "selectors";
import * as cfgConstants from "constants/config";

export const LDG_LEDGER_ENABLED = "LDG_LEDGER_ENABLED";
export const LDG_WALLET_CLOSED = "LDG_WALLET_CLOSED";
Expand All @@ -26,18 +25,7 @@ export const LDG_WALLET_CLOSED = "LDG_WALLET_CLOSED";
// enableLedger only sets a value in the config. Ledger connections are made
// per action then dropped.
export const enableLedger = () => (dispatch, getState) => {
const walletName = selectors.getWalletName(getState());

if (walletName) {
const config = wallet.getWalletCfg(
selectors.isTestNet(getState()),
walletName
);
config.set(cfgConstants.LEDGER, true);
}

dispatch({ type: LDG_LEDGER_ENABLED });

connect()(dispatch, getState);
};

Expand Down Expand Up @@ -143,13 +131,16 @@ export const LDG_GETWALLETCREATIONMASTERPUBKEY_SUCCESS =
"LDG_GETWALLETCREATIONMASTERPUBKEY_SUCCESS";

export const getWalletCreationMasterPubKey =
() => async (dispatch /*, getState*/) => {
() => async (dispatch, getState) => {
dispatch({ type: LDG_GETWALLETCREATIONMASTERPUBKEY_ATTEMPT });
// TODO: Enable on mainnet.
const isTestnet = true;
const isTestnet = selectors.isTestNet(getState());
if (!isTestnet) {
throw "disabled on mainnet";
}
try {
const payload = await getPubKey(isTestnet);
const hdpk = ledgerHelpers.fixPubKeyChecksum(payload);
const hdpk = ledgerHelpers.fixPubKeyChecksum(payload, isTestnet);
dispatch({ type: LDG_GETWALLETCREATIONMASTERPUBKEY_SUCCESS });
return hdpk;
} catch (error) {
Expand Down
11 changes: 0 additions & 11 deletions app/actions/TrezorActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
addressPath
} from "helpers/trezor";
import { publishTransactionAttempt } from "./ControlActions";
import * as cfgConstants from "constants/config";
import {
MODEL1_DECRED_HOMESCREEN,
MODELT_DECRED_HOMESCREEN
Expand Down Expand Up @@ -49,16 +48,6 @@ export const TRZ_TREZOR_ENABLED = "TRZ_TREZOR_ENABLED";
// enableTrezor attepts to start a connection with connect if none exist and
// connect to a trezor device.
export const enableTrezor = () => (dispatch, getState) => {
const walletName = selectors.getWalletName(getState());

if (walletName) {
const config = wallet.getWalletCfg(
selectors.isTestNet(getState()),
walletName
);
config.set(cfgConstants.TREZOR, true);
}

dispatch({ type: TRZ_TREZOR_ENABLED });

if (!setListeners) {
Expand Down
12 changes: 10 additions & 2 deletions app/actions/WalletLoaderActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
getBestBlockHeightAttempt
} from "./ClientActions";
import { WALLETREMOVED_FAILED } from "./DaemonActions";
import { isTestNet, trezorDevice } from "selectors";
import { isTestNet, trezorDevice, ledgerDevice } from "selectors";
import { walletrpc as api } from "middleware/walletrpc/api_pb";
import { push as pushHistory } from "connected-react-router";
import { stopNotifcations } from "./NotificationActions";
Expand All @@ -28,6 +28,7 @@ import * as cfgConstants from "constants/config";
import { RESCAN_PROGRESS } from "./ControlActions";
import { stopAccountMixer } from "./AccountMixerActions";
import { TRZ_WALLET_CLOSED } from "actions/TrezorActions";
import { LDG_WALLET_CLOSED } from "actions/LedgerActions";
import { saveSettings, updateStateSettingsChanged } from "./SettingsActions";

const { SyncNotificationType } = api;
Expand Down Expand Up @@ -156,7 +157,7 @@ export const CREATEWATCHONLYWALLET_FAILED = "CREATEWATCHONLYWALLET_FAILED";
export const CREATEWATCHONLYWALLET_SUCCESS = "CREATEWATCHONLYWALLET_SUCCESS";

export const createWatchOnlyWalletRequest =
(extendedPubKey, pubPass = "") =>
(extendedPubKey, isLedger, isTrezor, pubPass = "") =>
(dispatch, getState) =>
new Promise((resolve, reject) => {
dispatch({ type: CREATEWATCHONLYWALLET_ATTEMPT });
Expand All @@ -172,6 +173,12 @@ export const createWatchOnlyWalletRequest =
} = getState();
const config = wallet.getWalletCfg(isTestNet(getState()), walletName);
config.set(cfgConstants.IS_WATCH_ONLY, true);
if (isTrezor) {
config.set(cfgConstants.TREZOR, true);
}
if (isLedger) {
config.set(cfgConstants.LEDGER, true);
}
config.delete(cfgConstants.DISCOVER_ACCOUNTS);
wallet.setIsWatchingOnly(true);
dispatch({ response: {}, type: CREATEWATCHONLYWALLET_SUCCESS });
Expand Down Expand Up @@ -269,6 +276,7 @@ const finalCloseWallet = () => async (dispatch, getState) => {
await wallet.stopWallet();
dispatch({ type: CLOSEWALLET_SUCCESS });
if (trezorDevice(getState())) dispatch({ type: TRZ_WALLET_CLOSED });
if (ledgerDevice(getState())) dispatch({ type: LDG_WALLET_CLOSED });
dispatch(pushHistory("/getstarted/initial"));
} catch (error) {
dispatch({ error, type: CLOSEWALLET_FAILED });
Expand Down
2 changes: 2 additions & 0 deletions app/components/SideBar/MenuLinks/Links.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const LN_KEY = "ln";
export const DEX_KEY = "dex";
export const TICKETS_KEY = "tickets";
export const GOV_KEY = "governance";
export const PRIV_KEY = "privacy";

export const linkList = [
{
Expand Down Expand Up @@ -48,6 +49,7 @@ export const linkList = [
path: "/privacy",
link: <T id="sidebar.link.privacy" m="Privacy and Security" />,
icon: "securitycntr",
key: PRIV_KEY,
ariaLabel: "Privacy"
},
{
Expand Down
17 changes: 14 additions & 3 deletions app/components/SideBar/MenuLinks/hooks.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { useEffect, useState, useMemo } from "react";
import { useSelector } from "react-redux";
import * as sel from "selectors";
import { linkList, LN_KEY, DEX_KEY, TICKETS_KEY, GOV_KEY } from "./Links";
import {
linkList,
LN_KEY,
DEX_KEY,
TICKETS_KEY,
GOV_KEY,
PRIV_KEY
} from "./Links";
import { useHistory } from "react-router-dom";
import { cloneDeep } from "fp";

Expand All @@ -10,6 +17,7 @@ export function useMenuLinks() {
const sidebarOnBottom = useSelector(sel.sidebarOnBottom);
const expandSideBar = useSelector(sel.expandSideBar);
const isTrezor = useSelector(sel.isTrezor);
const isLedger = useSelector(sel.isLedger);
const lnEnabled = useSelector(sel.lnEnabled);

const newActiveVoteProposalsCount = useSelector(
Expand Down Expand Up @@ -47,19 +55,22 @@ export function useMenuLinks() {
links = links.filter((l) => l.key !== LN_KEY);
}
// TODO: Enable ticket purchacing for Trezor.
if (isTrezor) {
if (isTrezor || isLedger) {
links = links.filter(
(l) => l.key !== DEX_KEY && l.key !== TICKETS_KEY && l.key !== GOV_KEY
);
}
if (isLedger) {
links = links.filter((l) => l.key !== PRIV_KEY);
}
return links.map((link) => ({
...link,
notifProp: link.notifProp?.reduce(
(acc, np) => acc + (notifProps[np] || 0),
0
)
}));
}, [notifProps, isTrezor, lnEnabled]);
}, [notifProps, isTrezor, lnEnabled, isLedger]);

const [activeTabIndex, setActiveTabIndex] = useState(-1);
const history = useHistory();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ const SendTransactionButton = ({
unsignedTransaction,
isSendingTransaction,
isTrezor,
isLedger,
onAttemptSignTransaction,
onAttemptSignTransactionTrezor
onAttemptSignTransactionTrezor,
onAttemptSignTransactionLedger
} = useSendTransactionButton();

const signTransaction = (privpass) => {
Expand All @@ -31,6 +33,12 @@ const SendTransactionButton = ({
onSubmit?.();
};

const signTransactionLedger = () => {
if (disabled) return;
onAttemptSignTransactionLedger?.(unsignedTransaction);
onSubmit?.();
};

if (isTrezor) {
return (
<KeyBlueButton
Expand All @@ -40,6 +48,15 @@ const SendTransactionButton = ({
{buttonLabel ? buttonLabel : <T id="send.sendBtn" m="Send" />}
</KeyBlueButton>
);
} else if (isLedger) {
return (
<KeyBlueButton
onClick={signTransactionLedger}
disabled={disabled || isSendingTransaction}
loading={isSendingTransaction}>
{buttonLabel ? buttonLabel : <T id="send.sendBtn" m="Send" />}
</KeyBlueButton>
);
} else {
return (
<PassphraseModalButton
Expand Down
8 changes: 7 additions & 1 deletion app/components/buttons/SendTransactionButton/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,32 @@ import { useDispatch, useSelector } from "react-redux";
import * as sel from "selectors";
import * as ca from "actions/ControlActions";
import * as tza from "actions/TrezorActions";
import * as ldgr from "actions/LedgerActions";

export function useSendTransactionButton() {
const unsignedTransaction = useSelector(sel.unsignedTransaction);
const constructTxResponse = useSelector(sel.constructTxResponse);
const isSendingTransaction = useSelector(sel.isSendingTransaction);
const isTrezor = useSelector(sel.isTrezor);
const isLedger = useSelector(sel.isLedger);

const dispatch = useDispatch();
const onAttemptSignTransaction = (passphrase, rawTx, acct) => {
dispatch(ca.signTransactionAttempt(passphrase, rawTx, acct));
};
const onAttemptSignTransactionTrezor = (rawUnsigTx, constructTxResponse) =>
dispatch(tza.signTransactionAttemptTrezor(rawUnsigTx, constructTxResponse));
const onAttemptSignTransactionLedger = (rawUnsigTx) =>
dispatch(ldgr.signTransactionAttemptLedger(rawUnsigTx));

return {
unsignedTransaction,
constructTxResponse,
isSendingTransaction,
isTrezor,
isLedger,
onAttemptSignTransaction,
onAttemptSignTransactionTrezor
onAttemptSignTransactionTrezor,
onAttemptSignTransactionLedger
};
}
7 changes: 5 additions & 2 deletions app/components/shared/SendTransaction/Form.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const Form = ({
unsignedRawTx,
isWatchingOnly,
isTrezor,
isLedger,
insuficientFunds,
styles,
hideDetails,
Expand Down Expand Up @@ -71,7 +72,9 @@ const Form = ({
<T id="send.insuficient.funds" m="Insufficient funds" />
</div>
)}
{((isTrezor && isWatchingOnly) || !isWatchingOnly) &&
{((isTrezor && isWatchingOnly) ||
(isLedger && isWatchingOnly) ||
!isWatchingOnly) &&
(getRunningIndicator ? (
<Tooltip
contentClassName={styles.disabledTooltip}
Expand Down Expand Up @@ -144,7 +147,7 @@ const Form = ({
</div>
</div>
</div>
{unsignedRawTx && isWatchingOnly && !isTrezor && (
{unsignedRawTx && isWatchingOnly && !isTrezor && !isLedger && (
<UnsignedTx
title={<T id="send.unsignedRawTxTite" m="Unsigned Raw Transaction:" />}
tx={unsignedRawTx}
Expand Down
2 changes: 2 additions & 0 deletions app/components/shared/SendTransaction/SendTransaction.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const SendTransaction = ({
totalSpent,
notMixedAccounts,
isTrezor,
isLedger,
isWatchingOnly,
isConstructingTransaction,
attemptConstructTransaction,
Expand Down Expand Up @@ -394,6 +395,7 @@ const SendTransaction = ({
willEnter,
isWatchingOnly,
isTrezor,
isLedger,
insuficientFunds,
styles,
hideDetails,
Expand Down
2 changes: 2 additions & 0 deletions app/components/shared/SendTransaction/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export function useSendTransaction() {
shallowEqual
);
const isTrezor = useSelector(sel.isTrezor);
const isLedger = useSelector(sel.isLedger);
const isWatchingOnly = useSelector(sel.isWatchingOnly);
const isConstructingTransaction = useSelector(sel.isConstructingTransaction);
const constructTxRequestAttempt = useSelector(sel.constructTxRequestAttempt);
Expand Down Expand Up @@ -61,6 +62,7 @@ export function useSendTransaction() {
totalSpent,
notMixedAccounts,
isTrezor,
isLedger,
isWatchingOnly,
isConstructingTransaction,
attemptConstructTransaction,
Expand Down
Loading

0 comments on commit 36a2091

Please sign in to comment.