Skip to content

Commit

Permalink
fix: hardware wallet integration
Browse files Browse the repository at this point in the history
  • Loading branch information
AngelCastilloB committed Oct 8, 2024
1 parent bc8ad2c commit 7084b04
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 102 deletions.
2 changes: 2 additions & 0 deletions packages/nami/src/api/extension/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,8 @@ export const displayUnit = (
quantity: bigint | number | string,
decimals = 6,
) => {
if (quantity === undefined) return 0;

return Number.parseInt(quantity.toString()) / 10 ** decimals;
};

Expand Down
56 changes: 4 additions & 52 deletions packages/nami/src/api/extension/wallet.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import { Cardano } from '@cardano-sdk/core';
import { firstValueFrom } from 'rxjs';

import {
// ERROR,
TX,
} from '../../config/config';
import { TX } from '../../config/config';

import {
// signTxHW,
submitTx,
} from '.';
import { submitTx } from '.';

import type { OutsideHandlesContextValue } from '../../ui';
import type { Serialization } from '@cardano-sdk/core';
Expand Down Expand Up @@ -38,9 +32,7 @@ export const buildTx = async ({
invalidHereafter: Cardano.Slot(tip.slot + TX.invalid_hereafter),
});

const transaction = txBuilder.build();

return transaction;
return txBuilder.build();
};

export const signAndSubmit = async ({
Expand All @@ -57,45 +49,5 @@ export const signAndSubmit = async ({
withSignTxConfirmation(async () => {
const { cbor: signedTx } = await tx.sign();

const txHash = await submitTx(signedTx, inMemoryWallet);

return txHash;
return await submitTx(signedTx, inMemoryWallet);
}, password);

export const signAndSubmitHW = async (
tx: Serialization.Transaction,
{
keyHashes,
account,
hw,
partialSign,
}: Readonly<{ keyHashes: any; account: any; hw: any; partialSign?: boolean }>,
) => {
console.log(tx, {
keyHashes,
account,
hw,
partialSign,
});
return '';
// const witnessSet = await signTxHW(
// tx.toCbor(),
// keyHashes,
// account,
// hw,
// partialSign,
// );

// const transaction = new Serialization.Transaction(
// tx.body(),
// witnessSet,
// tx.auxiliaryData(),
// );

// try {
// const txHash = await submitTx(transaction.toCbor());
// return txHash;
// } catch {
// throw ERROR.submit;
// }
};
35 changes: 19 additions & 16 deletions packages/nami/src/ui/app/components/confirmModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ import {

import { MdUsb } from 'react-icons/md';

import { indexToHw, initHW, isHW } from '../../../api/extension';
import { ERROR, HW } from '../../../config/config';
import { ERROR } from '../../../config/config';
import { WalletType } from '@cardano-sdk/web-extension';
import { Events } from "../../../features/analytics/events";
import type { Wallet } from '@lace/cardano';

interface Props {
ready: boolean;
Expand All @@ -33,10 +35,13 @@ interface Props {
onCloseBtn: () => void;
title: React.ReactNode;
info: React.ReactNode;
walletType: WalletType;
connectHW: (device: USBDevice) => Promise<Wallet.HardwareWalletConnection>;
}

const ConfirmModal = React.forwardRef<unknown, Props>(
({ ready, onConfirm, sign, onCloseBtn, title, info, setPassword }, ref) => {
({ ready, onConfirm, sign, onCloseBtn, title, info, setPassword, walletType, connectHW }, ref) => {

const {
isOpen: isOpenNormal,
onOpen: onOpenNormal,
Expand All @@ -54,13 +59,12 @@ const ConfirmModal = React.forwardRef<unknown, Props>(
onCloseBtn,
title,
info,
walletType,
connectHW
};
const [hw, setHw] = React.useState('');

React.useImperativeHandle(ref, () => ({
openModal(accountIndex) {
if (isHW(accountIndex)) {
setHw(indexToHw(accountIndex));
openModal() {
if (walletType === WalletType.Ledger || walletType === WalletType.Trezor) {
onOpenHW();
} else {
onOpenNormal();
Expand All @@ -78,7 +82,6 @@ const ConfirmModal = React.forwardRef<unknown, Props>(
props={props}
isOpen={isOpenHW}
onClose={onCloseHW}
hw={hw}
/>
<ConfirmModalNormal
props={props}
Expand Down Expand Up @@ -206,18 +209,18 @@ const ConfirmModalNormal = ({ props, isOpen, onClose, setPassword }) => {
);
};

const ConfirmModalHw = ({ props, isOpen, onClose, hw }) => {
const ConfirmModalHw = ({ props, isOpen, onClose }) => {
const [waitReady, setWaitReady] = React.useState(true);
const [error, setError] = React.useState('');

const confirmHandler = async () => {
if (props.ready === false || !waitReady) return;
setWaitReady(false);
try {
setWaitReady(false);
const appAda = await initHW({ device: hw.device, id: hw.id });
const signedMessage = await props.sign(null, { ...hw, appAda });
const signedMessage = await props.sign(null);
await props.onConfirm(true, signedMessage);
} catch (e) {
console.error(e);
if (e === ERROR.submit) props.onConfirm(false, e);
else setError('An error occured');
}
Expand Down Expand Up @@ -255,7 +258,7 @@ const ConfirmModalHw = ({ props, isOpen, onClose, hw }) => {
display="flex"
alignItems="center"
justifyContent="center"
background={hw.device == HW.ledger ? 'blue.400' : 'green.400'}
background={props.walletType === WalletType.Ledger ? 'blue.400' : 'green.400'}
rounded="xl"
py={2}
width="70%"
Expand All @@ -264,9 +267,9 @@ const ConfirmModalHw = ({ props, isOpen, onClose, hw }) => {
<Icon as={MdUsb} boxSize={5} mr={2} />
<Box fontSize="sm">
{waitReady
? `Connect ${hw.device == HW.ledger ? 'Ledger' : 'Trezor'}`
? `Connect ${props.walletType}`
: `Waiting for ${
hw.device == HW.ledger ? 'Ledger' : 'Trezor'
props.walletType
}`}
</Box>
</Box>
Expand Down
11 changes: 10 additions & 1 deletion packages/nami/src/ui/app/components/transactionBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ const TransactionBuilder = React.forwardRef<unknown, undefined>(
initializeCollateralTx: initializeCollateral,
collateralFee,
inMemoryWallet,
walletType,
cardanoCoin,
buildDelegation,
setSelectedStakePool,
Expand All @@ -117,7 +118,8 @@ const TransactionBuilder = React.forwardRef<unknown, undefined>(
withSignTxConfirmation,
resetDelegationState,
hasNoFunds,
openExternalLink
openExternalLink,
connectHW,
} = useOutsideHandles();
const { initDelegation, stakeRegistration } = useDelegation({
inMemoryWallet,
Expand Down Expand Up @@ -250,6 +252,8 @@ const TransactionBuilder = React.forwardRef<unknown, undefined>(
setData({ pool: { ...poolDefaultValue } });
resetDelegationState();
}}
walletType={walletType}
connectHW={connectHW}
setPassword={setPassword}
ready={!isBuildingTx && data.pool.state === PoolStates.DONE}
title="Delegate your funds"
Expand Down Expand Up @@ -423,6 +427,8 @@ const TransactionBuilder = React.forwardRef<unknown, undefined>(
setData({ pool: { ...poolDefaultValue } });
resetDelegationState();
}}
walletType={walletType}
connectHW={connectHW}
setPassword={setPassword}
ready={!isBuildingTx}
title="Stake deregistration"
Expand Down Expand Up @@ -519,6 +525,9 @@ const TransactionBuilder = React.forwardRef<unknown, undefined>(
<Icon as={FaRegFileCode} mr="2" /> <Box>Collateral</Box>
</Box>
}
walletType={walletType}
connectHW={connectHW}
setPassword={setPassword}
sign={async password => {
await submitCollateral(password);
}}
Expand Down
11 changes: 8 additions & 3 deletions packages/nami/src/ui/app/pages/dapp-connector/signData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ import { useCaptureEvent } from '../../../../features/analytics/hooks';
import Account from '../../components/account';
import ConfirmModal from '../../components/confirmModal';
import { Scrollbars } from '../../components/scrollbar';

import type { UseAccount } from '../../../../adapters/account';
import type { DappConnector } from '../../../../features/outside-handles-provider';
import {
DappConnector,
useOutsideHandles,
} from '../../../../features/outside-handles-provider';

interface Props {
dappConnector: DappConnector;
Expand All @@ -45,6 +47,8 @@ export const SignData = ({ dappConnector, account }: Readonly<Props>) => {
setPayload(payloadUtf8);
};

const { walletType } = useOutsideHandles();

const signDataMsg = useMemo(() => {
const result: JSX.Element[] = [];
for (const line of payload.split(/\r?\n/)) {
Expand Down Expand Up @@ -224,9 +228,10 @@ export const SignData = ({ dappConnector, account }: Readonly<Props>) => {
)}
<ConfirmModal
ref={ref}
walletType={walletType}
sign={async password => {
try {
return await request?.sign(password);
return await request?.sign(password ?? '');
} catch (error) {
if (
error instanceof Wallet.KeyManagement.errors.AuthenticationError
Expand Down
17 changes: 4 additions & 13 deletions packages/nami/src/ui/app/pages/dapp-connector/signTx.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export const SignTx = ({
const [dappInfo, setDappInfo] = React.useState<Wallet.DappInfo>();

const capture = useCaptureEvent();
const { cardanoCoin } = useOutsideHandles();
const { cardanoCoin, walletType } = useOutsideHandles();
const ref = React.useRef();
const [collateral, setCollateral] = React.useState<Wallet.Cardano.Utxo>();
const [fee, setFee] = React.useState('0');
Expand Down Expand Up @@ -507,21 +507,12 @@ export const SignTx = ({
/>
<ConfirmModal
ref={ref}
walletType={walletType}
onCloseBtn={() => {
capture(Events.DappConnectorDappTxCancelClick);
}}
sign={async (password, hw) => {
if (hw) {
// TODO: add hw sign support
// return await signTxHW(
// request.data.tx,
// keyHashes.key,
// account,
// hw,
// request.data.partialSign,
// );
}
return await request?.sign(password);
sign={async password => {
return request?.sign(password ?? '');
}}
onConfirm={async (status, signedTx) => {
if (status) {
Expand Down
26 changes: 9 additions & 17 deletions packages/nami/src/ui/app/pages/send.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const Send = ({
}: Props) => {
const capture = useCaptureEvent();
const isMounted = useIsMounted();
const { cardanoCoin } = useOutsideHandles();
const { cardanoCoin, walletType, connectHW } = useOutsideHandles();
const [address, setAddress] = [
useStoreState(state => state.globalModel.sendStore.address),
useStoreActions(actions => actions.globalModel.sendStore.setAddress),
Expand Down Expand Up @@ -604,6 +604,8 @@ const Send = ({
</Box>
<AssetsModal ref={assetsModalRef} />
<ConfirmModal
connectHW={connectHW}
walletType={walletType}
title={'Confirm transaction'}
info={
<Box
Expand Down Expand Up @@ -700,22 +702,12 @@ const Send = ({
ref={ref}
sign={async (password, hw) => {
capture(Events.SendTransactionConfirmationConfirmClick);
if (hw) {
if (hw.device === HW.trezor) {
return createTab(TAB.trezorTx, `?tx=${tx}`);
}
return await signAndSubmitHW(txDes, {
keyHashes: [paymentKeyHash],
account: account.current,
hw,
});
} else
return await signAndSubmit({
tx,
password,
withSignTxConfirmation,
inMemoryWallet,
});
return await signAndSubmit({
tx,
password,
withSignTxConfirmation,
inMemoryWallet,
});
}}
onConfirm={async (status, signedTx) => {
if (status === true) {
Expand Down

0 comments on commit 7084b04

Please sign in to comment.