Skip to content

Commit

Permalink
Hook up bond approval and Ledger signing
Browse files Browse the repository at this point in the history
  • Loading branch information
jurevans committed Jul 13, 2023
1 parent 2946257 commit 31bc8c4
Show file tree
Hide file tree
Showing 61 changed files with 3,565 additions and 270 deletions.
2 changes: 1 addition & 1 deletion apps/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@
"@anoma/storage": "0.1.0",
"@anoma/types": "0.1.0",
"@anoma/utils": "0.1.0",
"@anoma/ledger-namada": "0.0.1",
"@cosmjs/encoding": "^0.29.0",
"@ledgerhq/hw-transport": "^6.28.3",
"@ledgerhq/hw-transport-webhid": "^6.27.14",
"@ledgerhq/hw-transport-webusb": "^6.27.14",
"@zondax/ledger-namada": "^0.0.2",
"bignumber.js": "^9.1.1",
"borsh": "^0.7.0",
"buffer": "^6.0.3",
Expand Down
44 changes: 43 additions & 1 deletion apps/extension/src/Approvals/Approvals.components.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import styled, { createGlobalStyle } from "styled-components";
import styled, { createGlobalStyle, css } from "styled-components";

export const GlobalStyles = createGlobalStyle`
html, body {
Expand Down Expand Up @@ -93,3 +93,45 @@ export const ButtonContainer = styled.div`
display: flex;
flex-direction: row;
`;

export const Spinner = css`
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-top-color: ${(props) => props.theme.colors.primary.main};
border-radius: 50%;
animation: button-loading-spinner 1s ease infinite;
@keyframes button-loading-spinner {
from {
transform: rotate(0turn);
}
to {
transform: rotate(1turn);
}
}
}
`;

export const InfoHeader = styled.div`
display: flex;
align-items: center;
gap: 10px;
`;

export const InfoLoader = styled.div`
position: relative;
width: 20px;
height: 20px;
&::after {
width: 16px;
height: 16px;
border: 2px solid transparent;
${Spinner}
}
`;
21 changes: 18 additions & 3 deletions apps/extension/src/Approvals/Approvals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ApproveTransfer, ConfirmTransfer } from "./ApproveTransfer";
import { ApproveConnection } from "./ApproveConnection";
import { TopLevelRoute } from "Approvals/types";
import { ConfirmLedgerTransfer } from "./ApproveTransfer/ConfirmLedgerTransfer";
import { ApproveBond, ConfirmBond, ConfirmLedgerBond } from "./ApproveBond";

export enum Status {
Completed,
Expand All @@ -37,19 +38,33 @@ export const Approvals: React.FC = () => {
</TopSection>
<Routes>
<Route
path={TopLevelRoute.ApproveTx}
path={TopLevelRoute.ApproveTransfer}
element={
<ApproveTransfer setMsgId={setMsgId} setAddress={setAddress} />
}
/>
<Route
path={TopLevelRoute.ConfirmTx}
path={TopLevelRoute.ConfirmTransfer}
element={<ConfirmTransfer msgId={msgId} address={address} />}
/>
<Route
path={TopLevelRoute.ConfirmLedgerTx}
path={TopLevelRoute.ConfirmLedgerTransfer}
element={<ConfirmLedgerTransfer msgId={msgId} />}
/>
<Route
path={TopLevelRoute.ApproveBond}
element={
<ApproveBond setMsgId={setMsgId} setAddress={setAddress} />
}
/>
<Route
path={TopLevelRoute.ConfirmBond}
element={<ConfirmBond msgId={msgId} address={address} />}
/>
<Route
path={TopLevelRoute.ConfirmLedgerBond}
element={<ConfirmLedgerBond msgId={msgId} />}
/>

<Route
path={TopLevelRoute.ApproveConnection}
Expand Down
85 changes: 85 additions & 0 deletions apps/extension/src/Approvals/ApproveBond/ApproveBond.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { useNavigate } from "react-router-dom";
import { useEffect } from "react";

import { Button, ButtonVariant } from "@anoma/components";
import { shortenAddress } from "@anoma/utils";
import { AccountType, Tokens } from "@anoma/types";

import { useQuery } from "hooks";
import { Address } from "App/Accounts/AccountListing.components";
import {
ApprovalContainer,
ButtonContainer,
} from "Approvals/Approvals.components";
import { TopLevelRoute } from "Approvals/types";
import { Ports } from "router";
import { RejectTxMsg } from "background/approvals";
import { useRequester } from "hooks/useRequester";
import { closeCurrentTab } from "utils";

type Props = {
setMsgId: (msgId: string) => void;
setAddress: (address: string) => void;
};

export const ApproveBond: React.FC<Props> = ({ setAddress, setMsgId }) => {
const navigate = useNavigate();
const requester = useRequester();

const query = useQuery();
const type = query.get("type") || "";
const id = query.get("id") || "";
const amount = query.get("amount") || "";
const source = query.get("source") || "";
const tokenAddress = query.get("token") || "";
const tokenType =
Object.values(Tokens).find((token) => token.address === tokenAddress)
?.symbol || "";

useEffect(() => {
if (source) {
setAddress(source);
}
}, [source]);

const handleApproveClick = (): void => {
setMsgId(id);
if (type === AccountType.Ledger) {
return navigate(`${TopLevelRoute.ConfirmLedgerBond}`);
}
navigate(TopLevelRoute.ConfirmBond);
};

const handleReject = async (): Promise<void> => {
try {
// TODO: use executeUntil here!
await requester.sendMessage(Ports.Background, new RejectTxMsg(id));

// Close tab
await closeCurrentTab();
} catch (e) {
console.warn(e);
}
return;
};

return (
<ApprovalContainer>
<p>Approve this Bond?</p>
<p>Source:&nbsp;</p>
<Address>{shortenAddress(source)}</Address>
<p>
Amount: {amount} {tokenType}
</p>

<ButtonContainer>
<Button onClick={handleApproveClick} variant={ButtonVariant.Contained}>
Approve
</Button>
<Button onClick={handleReject} variant={ButtonVariant.Contained}>
Reject
</Button>
</ButtonContainer>
</ApprovalContainer>
);
};
104 changes: 104 additions & 0 deletions apps/extension/src/Approvals/ApproveBond/ConfirmBond.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";

import { Button, ButtonVariant, Input, InputVariants } from "@anoma/components";
import { shortenAddress } from "@anoma/utils";

import { Status } from "Approvals/Approvals";
import {
ApprovalContainer,
ButtonContainer,
InfoHeader,
InfoLoader,
} from "Approvals/Approvals.components";
import { Ports } from "router";
import { useRequester } from "hooks/useRequester";
import { SubmitApprovedBondMsg } from "background/approvals";
import { Address } from "App/Accounts/AccountListing.components";
import { closeCurrentTab } from "utils";

type Props = {
msgId: string;
address: string;
};

export const ConfirmBond: React.FC<Props> = ({ msgId, address }) => {
const navigate = useNavigate();
const requester = useRequester();
const [password, setPassword] = useState("");
const [error, setError] = useState<string>();
const [status, setStatus] = useState<Status>();
const [statusInfo, setStatusInfo] = useState<string>("");

const handleApproveBond = async (): Promise<void> => {
setStatus(Status.Pending);
try {
// TODO: use executeUntil here!
setStatusInfo("Decrypting keys and submitting transfer...");
await requester.sendMessage(
Ports.Background,
new SubmitApprovedBondMsg(msgId, address, password)
);
setStatus(Status.Completed);
} catch (e) {
setError("Unable to authenticate Tx!");
setStatus(Status.Failed);
}
setStatusInfo("");
setStatus(Status.Completed);
return;
};

useEffect(() => {
(async () => {
if (status === Status.Completed) {
await closeCurrentTab();
}
})();
}, [status]);

return (
<ApprovalContainer>
{status === Status.Pending && (
<InfoHeader>
<InfoLoader />
<p>{statusInfo}</p>
</InfoHeader>
)}
{status === Status.Failed && (
<p>
{error}
<br />
Try again
</p>
)}
{status !== (Status.Pending || Status.Completed) && (
<>
<div>
Decrypt keys for <Address>{shortenAddress(address)}</Address>
</div>
<Input
variant={InputVariants.Password}
label={"Password"}
onChangeCallback={(e) => setPassword(e.target.value)}
/>
<ButtonContainer>
<Button
onClick={handleApproveBond}
disabled={!password}
variant={ButtonVariant.Contained}
>
Authenticate
</Button>
<Button
onClick={() => navigate(-1)}
variant={ButtonVariant.Contained}
>
Back
</Button>
</ButtonContainer>
</>
)}
</ApprovalContainer>
);
};
Loading

0 comments on commit 31bc8c4

Please sign in to comment.