mirror of
https://github.com/haveno-dex/haveno-ui.git
synced 2024-10-01 07:35:39 -04:00
fix: My Wallet page
- download qr code - ui inconsistencies fixed --- Reviewed-by @schowdhuri
This commit is contained in:
parent
b40fe25930
commit
ec2193b460
@ -56,6 +56,7 @@
|
||||
"@types/lodash": "^4.14.182",
|
||||
"@types/react": "<18.0.0",
|
||||
"@types/react-dom": "<18.0.0",
|
||||
"@types/qrcode": "^1.4.2",
|
||||
"@typescript-eslint/eslint-plugin": "5.12.1",
|
||||
"@typescript-eslint/parser": "^5.19.0",
|
||||
"@vitejs/plugin-react": "^1.3.0",
|
||||
@ -96,6 +97,7 @@
|
||||
"joi": "^17.6.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"lodash": "^4.17.21",
|
||||
"qrcode": "^1.5.0",
|
||||
"react": "<18.0.0",
|
||||
"react-dom": "<18.0.0",
|
||||
"react-intl": "^5.24.8",
|
||||
|
@ -16,6 +16,9 @@
|
||||
|
||||
import fsPromises from "fs/promises";
|
||||
import { ipcMain, dialog } from "electron";
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
import QRCode from "qrcode/lib/server";
|
||||
import type { DownloadBackupInput } from "@src/types";
|
||||
import { IpcChannels } from "@src/types";
|
||||
|
||||
@ -56,4 +59,33 @@ export function registerHavenoHandlers() {
|
||||
const zipFile = files.filePaths[0];
|
||||
return new Uint8Array(await fsPromises.readFile(zipFile));
|
||||
});
|
||||
|
||||
ipcMain.handle(
|
||||
IpcChannels.DownloadQRCode,
|
||||
async (_, code: string): Promise<void> => {
|
||||
const file = await dialog.showSaveDialog({
|
||||
defaultPath: "qr-code",
|
||||
filters: [
|
||||
{
|
||||
extensions: ["png"],
|
||||
name: "*",
|
||||
},
|
||||
],
|
||||
properties: ["createDirectory", "dontAddToRecent"],
|
||||
});
|
||||
if (!file?.filePath) {
|
||||
return;
|
||||
}
|
||||
QRCode.toFile(
|
||||
file.filePath,
|
||||
code,
|
||||
{
|
||||
width: 500,
|
||||
},
|
||||
(err: Error) => {
|
||||
if (err) throw err;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ export enum IpcChannels {
|
||||
// haveno
|
||||
DownloadBackup = "haveno:downloadBackup",
|
||||
RestoreBackup = "haveno:restoreBackup",
|
||||
DownloadQRCode = "haveno:downloadQRCode",
|
||||
|
||||
// others
|
||||
VerifyAuthToken = "verifyAuthToken",
|
||||
|
@ -26,6 +26,9 @@ export const haveno = {
|
||||
|
||||
getBackupData: async (): Promise<Uint8Array> =>
|
||||
ipcRenderer.invoke(IpcChannels.RestoreBackup),
|
||||
|
||||
downloadQRCode: async (qrCode: string): Promise<void> =>
|
||||
ipcRenderer.invoke(IpcChannels.DownloadQRCode, qrCode),
|
||||
};
|
||||
|
||||
exposeInMainWorld("haveno", haveno);
|
||||
|
@ -0,0 +1 @@
|
||||
export * from "./DetailItemCard";
|
@ -45,14 +45,14 @@ const useStyles = createStyles((theme, _params, getRef) => {
|
||||
paddingRight: 0,
|
||||
textTransform: "uppercase",
|
||||
|
||||
"&:first-child": {
|
||||
"&:first-of-type": {
|
||||
marginLeft: 0,
|
||||
},
|
||||
"&:last-child": {
|
||||
marginRight: 0,
|
||||
},
|
||||
[`&.${tabActiveRef}`]: {
|
||||
borderBottomColor: theme.primaryColor,
|
||||
borderBottomColor: theme.colors.blue[6],
|
||||
color: theme.colors.dark[9],
|
||||
},
|
||||
},
|
||||
|
14
packages/renderer/src/components/atoms/Typography/Anchor.tsx
Normal file
14
packages/renderer/src/components/atoms/Typography/Anchor.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
import { Anchor as MAnchor, createStyles } from "@mantine/core";
|
||||
import type { AnchorProps as MAnchorProps } from "@mantine/core";
|
||||
|
||||
export function Anchor(props: MAnchorProps<"a">) {
|
||||
const { classes, cx } = useStyles();
|
||||
|
||||
return <MAnchor {...props} className={cx(props.className, classes.anchor)} />;
|
||||
}
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
anchor: {
|
||||
color: theme.colors.blue[6],
|
||||
},
|
||||
}));
|
@ -16,3 +16,4 @@
|
||||
|
||||
export * from "./Heading";
|
||||
export * from "./Text";
|
||||
export * from "./Anchor";
|
||||
|
@ -17,20 +17,17 @@
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import QRCode from "react-qr-code";
|
||||
import type { OpenConfirmModal } from "@mantine/modals/lib/context";
|
||||
import { showNotification } from "@mantine/notifications";
|
||||
import { useModals } from "@mantine/modals";
|
||||
import { useClipboard } from "@mantine/hooks";
|
||||
import {
|
||||
Anchor,
|
||||
Box,
|
||||
createStyles,
|
||||
Group,
|
||||
SimpleGrid,
|
||||
Skeleton,
|
||||
} from "@mantine/core";
|
||||
import { Box, createStyles, Group, SimpleGrid, Skeleton } from "@mantine/core";
|
||||
import { DetailItem } from "@atoms/DetailItem";
|
||||
import { Button } from "@atoms/Buttons";
|
||||
import { Anchor } from "@atoms/Typography";
|
||||
import { DetailItemCard } from "@atoms/DetailItemCard";
|
||||
import { LangKeys } from "@constants/lang";
|
||||
import { DetailItemCard } from "@atoms/DetailItemCard/DetailItemCard";
|
||||
import { useSetDownloadQRCode } from "@hooks/haveno/useSetDownloadQRCode";
|
||||
import { Modals } from "@constants/modals";
|
||||
|
||||
interface AddressCardProps {
|
||||
label?: string;
|
||||
@ -49,17 +46,34 @@ export function AddressCard({
|
||||
}: AddressCardProps) {
|
||||
const modals = useModals();
|
||||
const { classes } = useStyles();
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const { mutateAsync: downloadQRCode } = useSetDownloadQRCode();
|
||||
|
||||
const clipboard = useClipboard({ timeout: COPY_TEXT_TIMEOUT });
|
||||
|
||||
const handleCopyClick = () => {
|
||||
clipboard.copy(address);
|
||||
};
|
||||
const handleQRDownloadClick = (addressCode: string) => {
|
||||
downloadQRCode(addressCode).then(() => {
|
||||
showNotification({
|
||||
color: "green",
|
||||
message: formatMessage({
|
||||
id: LangKeys.AddressCardQRCodeSavedSuccessNotif,
|
||||
defaultMessage: "The QR code has been saved successfully.",
|
||||
}),
|
||||
});
|
||||
modals.closeModal(Modals.QRCodeAddress);
|
||||
});
|
||||
};
|
||||
const handleQRClick = () => {
|
||||
const modalId = modals.openModal({
|
||||
id: Modals.QRCodeAddress,
|
||||
children: (
|
||||
<AddressCardQRModalContent
|
||||
address={address}
|
||||
onQRDownloadClick={handleQRDownloadClick}
|
||||
onReturnClick={() => modals.closeModal(modalId)}
|
||||
/>
|
||||
),
|
||||
@ -137,7 +151,7 @@ export function AddressCardSkeleton({
|
||||
|
||||
interface AddressCardQRModalContentProps {
|
||||
address: string;
|
||||
onQRDownloadClick?: () => void;
|
||||
onQRDownloadClick?: (address: string) => void;
|
||||
onReturnClick?: () => void;
|
||||
}
|
||||
|
||||
@ -149,10 +163,16 @@ function AddressCardQRModalContent({
|
||||
const { classes } = useStyles();
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const handleQRDownloadClick = () => {
|
||||
onQRDownloadClick && onQRDownloadClick(address);
|
||||
};
|
||||
return (
|
||||
<Box>
|
||||
<Box className={classes.qrModalRoot}>
|
||||
<DetailItem
|
||||
classNames={{ content: classes.qrModalAddress }}
|
||||
classNames={{
|
||||
content: classes.qrModalAddress,
|
||||
label: classes.qrModalAddressLabel,
|
||||
}}
|
||||
label={formatMessage({
|
||||
id: LangKeys.MyWalletQRModalPrimaryAddress,
|
||||
defaultMessage: "Primary Address",
|
||||
@ -173,7 +193,7 @@ function AddressCardQRModalContent({
|
||||
/>
|
||||
</Button>
|
||||
|
||||
<Button onClick={onQRDownloadClick}>
|
||||
<Button onClick={handleQRDownloadClick}>
|
||||
<FormattedMessage
|
||||
id={LangKeys.MyWalletQRModalDownloadQRBtn}
|
||||
defaultMessage="Download QR"
|
||||
@ -197,11 +217,18 @@ const useStyles = createStyles((theme) => ({
|
||||
addressBtns: {
|
||||
marginLeft: "auto",
|
||||
},
|
||||
qrModalRoot: {
|
||||
padding: "1.5rem",
|
||||
},
|
||||
qrRoot: {
|
||||
marginTop: theme.spacing.xl,
|
||||
marginTop: theme.spacing.xl * 1.5,
|
||||
marginBottom: theme.spacing.xl * 1.5,
|
||||
textAlign: "center",
|
||||
},
|
||||
qrModalAddress: {
|
||||
fontSize: theme.fontSizes.lg,
|
||||
},
|
||||
qrModalAddressLabel: {
|
||||
fontSize: theme.fontSizes.xs,
|
||||
},
|
||||
}));
|
||||
|
@ -44,12 +44,12 @@ exports[`molecules::AddressCard > renders without exploding 1`] = `
|
||||
class="mantine-Group-root mantine-Group-child mantine-ze53qg"
|
||||
>
|
||||
<a
|
||||
class="mantine-Text-root mantine-Anchor-root mantine-Group-child mantine-16zvpw1"
|
||||
class="mantine-Text-root mantine-Anchor-root mantine-Group-child mantine-1yvb6qd"
|
||||
>
|
||||
Copy
|
||||
</a>
|
||||
<a
|
||||
class="mantine-Text-root mantine-Anchor-root mantine-Group-child mantine-16zvpw1"
|
||||
class="mantine-Text-root mantine-Anchor-root mantine-Group-child mantine-1yvb6qd"
|
||||
>
|
||||
QR
|
||||
</a>
|
||||
|
@ -64,7 +64,7 @@ export function WalletTransactions({ data }: WalletTransactionsProps) {
|
||||
|
||||
const useStyles = createStyles(() => ({
|
||||
root: {
|
||||
"tbody tr td:first-child": {
|
||||
"tbody tr td:first-of-type": {
|
||||
paddingLeft: 0,
|
||||
},
|
||||
"tbody tr td:last-child": {
|
||||
|
@ -33,22 +33,32 @@ export function MyWalletMoneroBalanceContent() {
|
||||
<MoneroBalance>
|
||||
<MoneroBalance.Detail
|
||||
label={formatMessage({
|
||||
id: LangKeys.MyWalletMoneroAvaliableBalance,
|
||||
defaultMessage: "Avaliable Balance",
|
||||
id: LangKeys.MyWalletMoneroTotalBalance,
|
||||
defaultMessage: "Total Balance",
|
||||
})}
|
||||
data-testid="avaliable-balance"
|
||||
data-testid="total-balance"
|
||||
>
|
||||
<Currency value={balanceInfo.balance} />
|
||||
<Currency value={balanceInfo.total} />
|
||||
</MoneroBalance.Detail>
|
||||
|
||||
<MoneroBalance.Detail
|
||||
label={formatMessage({
|
||||
id: LangKeys.MyWalletMoneroReserveredFunds,
|
||||
defaultMessage: "Reservered Funds",
|
||||
id: LangKeys.MyWalletMoneroAvailableBalance,
|
||||
defaultMessage: "Available Balance",
|
||||
})}
|
||||
data-testid="reserverd-funds"
|
||||
data-testid="available-balance"
|
||||
>
|
||||
<Currency value={balanceInfo.reservedOfferBalance || 0} />
|
||||
<Currency value={balanceInfo.availableBalance || 0} />
|
||||
</MoneroBalance.Detail>
|
||||
|
||||
<MoneroBalance.Detail
|
||||
label={formatMessage({
|
||||
id: LangKeys.MyWalletMoneroReservedFunds,
|
||||
defaultMessage: "Reserved Funds",
|
||||
})}
|
||||
data-testid="reserved-funds"
|
||||
>
|
||||
<Currency value={balanceInfo.reservedBalance || 0} />
|
||||
</MoneroBalance.Detail>
|
||||
|
||||
<MoneroBalance.Detail
|
||||
|
@ -26,8 +26,8 @@ export function MyWalletMeneroBalanceSkeleton() {
|
||||
<MoneroBalance>
|
||||
<MoneroBalance.Detail
|
||||
label={formatMessage({
|
||||
id: LangKeys.MyWalletMoneroAvaliableBalance,
|
||||
defaultMessage: "Avaliable Balance",
|
||||
id: LangKeys.MyWalletMoneroTotalBalance,
|
||||
defaultMessage: "Total Balance",
|
||||
})}
|
||||
>
|
||||
<Skeleton height={8} radius="xl" mt={6} />
|
||||
@ -35,8 +35,17 @@ export function MyWalletMeneroBalanceSkeleton() {
|
||||
|
||||
<MoneroBalance.Detail
|
||||
label={formatMessage({
|
||||
id: LangKeys.MyWalletMoneroReserveredFunds,
|
||||
defaultMessage: "Reservered Funds",
|
||||
id: LangKeys.MyWalletMoneroAvailableBalance,
|
||||
defaultMessage: "Available Balance",
|
||||
})}
|
||||
>
|
||||
<Skeleton height={8} radius="xl" mt={6} />
|
||||
</MoneroBalance.Detail>
|
||||
|
||||
<MoneroBalance.Detail
|
||||
label={formatMessage({
|
||||
id: LangKeys.MyWalletMoneroReservedFunds,
|
||||
defaultMessage: "Reserved Funds",
|
||||
})}
|
||||
>
|
||||
<Skeleton height={8} radius="xl" mt={6} />
|
||||
|
@ -28,9 +28,10 @@ describe("organisms::MyWalletMoneroBalance", () => {
|
||||
data: {
|
||||
balance: MoneroBalance.balance,
|
||||
lockedBalance: MoneroBalance.lockedBalance,
|
||||
reservedOfferBalance: MoneroBalance.reserverdBalance,
|
||||
reservedTradeBalance: MoneroBalance.reserverdBalance,
|
||||
reservedBalance: MoneroBalance.reservedBalance,
|
||||
unlockedBalance: MoneroBalance.unlockedBalance,
|
||||
total: MoneroBalance.total,
|
||||
availableBalance: MoneroBalance.availableBalance,
|
||||
},
|
||||
}),
|
||||
}));
|
||||
@ -46,28 +47,30 @@ describe("organisms::MyWalletMoneroBalance", () => {
|
||||
unmount();
|
||||
});
|
||||
|
||||
it("contains avaliable balance, reservered funds and locked funds details", () => {
|
||||
it("contains total, available balance, reserved funds and locked funds details", () => {
|
||||
const { unmount } = render(
|
||||
<AppProviders>
|
||||
<MyWalletMoneroBalance />
|
||||
</AppProviders>
|
||||
);
|
||||
expect(screen.queryByTestId("avaliable-balance")).toBeInTheDocument();
|
||||
expect(screen.queryByTestId("total-balance")).toBeInTheDocument();
|
||||
expect(screen.queryByTestId("available-balance")).toBeInTheDocument();
|
||||
expect(screen.queryByTestId("locked-funds")).toBeInTheDocument();
|
||||
expect(screen.queryByTestId("reserverd-funds")).toBeInTheDocument();
|
||||
expect(screen.queryByTestId("reserved-funds")).toBeInTheDocument();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it("contains avaliable balance, reservered funds and locked funds details", () => {
|
||||
it("contains total. available balance, reserved funds and locked funds details values.", () => {
|
||||
const { unmount } = render(
|
||||
<AppProviders>
|
||||
<MyWalletMoneroBalance />
|
||||
</AppProviders>
|
||||
);
|
||||
expect(screen.queryByTestId("avaliable-balance")).toHaveTextContent(
|
||||
"835,120.34017"
|
||||
expect(screen.queryByTestId("total-balance")).toHaveTextContent("1,000.1");
|
||||
expect(screen.queryByTestId("available-balance")).toHaveTextContent(
|
||||
"8,000.65"
|
||||
);
|
||||
expect(screen.queryByTestId("reserverd-funds")).toHaveTextContent(
|
||||
expect(screen.queryByTestId("reserved-funds")).toHaveTextContent(
|
||||
"74,610.1236"
|
||||
);
|
||||
expect(screen.queryByTestId("locked-funds")).toHaveTextContent(
|
||||
@ -79,7 +82,9 @@ describe("organisms::MyWalletMoneroBalance", () => {
|
||||
|
||||
const MoneroBalance = {
|
||||
balance: 835120.34017,
|
||||
reserverdBalance: 74610.1236,
|
||||
reservedBalance: 74610.1236,
|
||||
lockedBalance: 90371.161239,
|
||||
unlockedBalance: 0,
|
||||
total: 1000.1,
|
||||
availableBalance: 8000.65,
|
||||
};
|
||||
|
@ -43,27 +43,42 @@ exports[`organisms::MyWalletMoneroBalance > renders without exploding 1`] = `
|
||||
>
|
||||
<div
|
||||
class="mantine-Stack-root mantine-DetailItem-root mantine-Group-child mantine-2d5onn"
|
||||
data-testid="avaliable-balance"
|
||||
data-testid="total-balance"
|
||||
>
|
||||
<div
|
||||
class="mantine-Text-root mantine-DetailItem-label mantine-10gsq91"
|
||||
>
|
||||
Avaliable Balance
|
||||
Total Balance
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Text-root mantine-DetailItem-content mantine-oat2gy"
|
||||
>
|
||||
835,120.34017
|
||||
1,000.10
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Stack-root mantine-DetailItem-root mantine-Group-child mantine-2d5onn"
|
||||
data-testid="reserverd-funds"
|
||||
data-testid="available-balance"
|
||||
>
|
||||
<div
|
||||
class="mantine-Text-root mantine-DetailItem-label mantine-10gsq91"
|
||||
>
|
||||
Reservered Funds
|
||||
Available Balance
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Text-root mantine-DetailItem-content mantine-oat2gy"
|
||||
>
|
||||
8,000.65
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Stack-root mantine-DetailItem-root mantine-Group-child mantine-2d5onn"
|
||||
data-testid="reserved-funds"
|
||||
>
|
||||
<div
|
||||
class="mantine-Text-root mantine-DetailItem-label mantine-10gsq91"
|
||||
>
|
||||
Reserved Funds
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Text-root mantine-DetailItem-content mantine-oat2gy"
|
||||
|
@ -47,7 +47,7 @@ exports[`organisms::MyWalletMeneroBalanceSkeleton > renders without exploding 1`
|
||||
<div
|
||||
class="mantine-Text-root mantine-DetailItem-label mantine-10gsq91"
|
||||
>
|
||||
Avaliable Balance
|
||||
Total Balance
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Text-root mantine-DetailItem-content mantine-oat2gy"
|
||||
@ -63,7 +63,23 @@ exports[`organisms::MyWalletMeneroBalanceSkeleton > renders without exploding 1`
|
||||
<div
|
||||
class="mantine-Text-root mantine-DetailItem-label mantine-10gsq91"
|
||||
>
|
||||
Reservered Funds
|
||||
Available Balance
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Text-root mantine-DetailItem-content mantine-oat2gy"
|
||||
>
|
||||
<div
|
||||
class="mantine-Skeleton-root mantine-Skeleton-visible mantine-12edv24"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Stack-root mantine-DetailItem-root mantine-Group-child mantine-2d5onn"
|
||||
>
|
||||
<div
|
||||
class="mantine-Text-root mantine-DetailItem-label mantine-10gsq91"
|
||||
>
|
||||
Reserved Funds
|
||||
</div>
|
||||
<div
|
||||
class="mantine-Text-root mantine-DetailItem-content mantine-oat2gy"
|
||||
|
@ -28,12 +28,12 @@ exports[`organisms::MyWalletPrimaryAddress > renders without exploding 1`] = `
|
||||
class="mantine-Group-root mantine-Group-child mantine-ze53qg"
|
||||
>
|
||||
<a
|
||||
class="mantine-Text-root mantine-Anchor-root mantine-Group-child mantine-16zvpw1"
|
||||
class="mantine-Text-root mantine-Anchor-root mantine-Group-child mantine-1yvb6qd"
|
||||
>
|
||||
Copy
|
||||
</a>
|
||||
<a
|
||||
class="mantine-Text-root mantine-Anchor-root mantine-Group-child mantine-16zvpw1"
|
||||
class="mantine-Text-root mantine-Anchor-root mantine-Group-child mantine-1yvb6qd"
|
||||
>
|
||||
QR
|
||||
</a>
|
||||
|
@ -77,7 +77,7 @@ export function MyWalletSendForm() {
|
||||
|
||||
return (
|
||||
<form onSubmit={form.onSubmit(handleFormSubmit)}>
|
||||
<Stack spacing="xl">
|
||||
<Stack spacing="xl" mt="md">
|
||||
<SimpleGrid cols={2}>
|
||||
<TextInput
|
||||
id="amount"
|
||||
|
@ -3,7 +3,7 @@
|
||||
exports[`organisms::MyWalletMoneroBalance > renders without exploding. 1`] = `
|
||||
<DocumentFragment>
|
||||
<table
|
||||
class="mantine-Table-root mantine-16jrhzw"
|
||||
class="mantine-Table-root mantine-u2os4d"
|
||||
>
|
||||
<tbody>
|
||||
<tr>
|
||||
|
@ -59,14 +59,16 @@ export enum LangKeys {
|
||||
AddressCardCopyBtn = "accountCard.copyButton",
|
||||
AddressCardCopiedBtn = "accountCard.copiedButton",
|
||||
AddressCardQRBtn = "accountCard.qrButton",
|
||||
AddressCardQRCodeSavedSuccessNotif = "accountCode.qrCodeSavedSuccessfully.notification",
|
||||
MyWalletSendFieldAmount = "myWallet.send.amountField",
|
||||
MyWalletSendFieldPaymentId = "myWallet.send.paymentIdField",
|
||||
MyWalletSendFieldPaymentIdPlaceholder = "myWallet.send.paymentIdFieldPlaceholder",
|
||||
MyWalletSendFieldAddress = "myWallet.send.addressField",
|
||||
MyWalletSendFieldAddressPlaceholder = "myWallet.send.addressFieldPlaceholder",
|
||||
MyWalletReceiveTitle = "myWallet.receive.receiveTitle",
|
||||
MyWalletMoneroAvaliableBalance = "myWallet.monero.avaliableBalance",
|
||||
MyWalletMoneroReserveredFunds = "myWallet.monero.reserveredFunds",
|
||||
MyWalletMoneroTotalBalance = "myWallet.monero.totalBalance",
|
||||
MyWalletMoneroAvailableBalance = "myWallet.monero.availableBalance",
|
||||
MyWalletMoneroReservedFunds = "myWallet.monero.reservedFunds",
|
||||
MyWalletMoneroLockedFunds = "myWallet.monero.lockedFunds",
|
||||
MyWalletTabTransactions = "myWallet.transactionsTab",
|
||||
MyWalletTabSend = "myWallet.sendTab",
|
||||
|
@ -69,13 +69,16 @@ const LangPackEN: { [key in LangKeys]: string } = {
|
||||
[LangKeys.AddressCardCopyBtn]: "Copy",
|
||||
[LangKeys.AddressCardCopiedBtn]: "Copied",
|
||||
[LangKeys.AddressCardQRBtn]: "QR",
|
||||
[LangKeys.AddressCardQRCodeSavedSuccessNotif]:
|
||||
"The QR code has been saved successfully.",
|
||||
[LangKeys.MyWalletSendFieldAmount]: "Amount",
|
||||
[LangKeys.MyWalletSendFieldAddress]: "Address",
|
||||
[LangKeys.MyWalletSendFieldAddressPlaceholder]: "Paste in address here...",
|
||||
[LangKeys.MyWalletSendFieldPaymentId]: "Payment ID",
|
||||
[LangKeys.MyWalletSendFieldPaymentIdPlaceholder]: "Type",
|
||||
[LangKeys.MyWalletMoneroAvaliableBalance]: "Avaliable Balance",
|
||||
[LangKeys.MyWalletMoneroReserveredFunds]: "Reservered Funds",
|
||||
[LangKeys.MyWalletMoneroTotalBalance]: "Total Balance",
|
||||
[LangKeys.MyWalletMoneroAvailableBalance]: "Available Balance",
|
||||
[LangKeys.MyWalletMoneroReservedFunds]: "Reserved Funds",
|
||||
[LangKeys.MyWalletMoneroLockedFunds]: "Locked Funds",
|
||||
[LangKeys.MyWalletTabTransactions]: "Transactions",
|
||||
[LangKeys.MyWalletTabSend]: "Send",
|
||||
|
@ -69,13 +69,16 @@ const LangPackES: { [key in LangKeys]: string } = {
|
||||
[LangKeys.AddressCardCopyBtn]: "Dupdo",
|
||||
[LangKeys.AddressCardCopiedBtn]: "Copiada",
|
||||
[LangKeys.AddressCardQRBtn]: "QR",
|
||||
[LangKeys.AddressCardQRCodeSavedSuccessNotif]:
|
||||
"El código QR se ha guardado correctamente.",
|
||||
[LangKeys.MyWalletSendFieldAmount]: "Monto",
|
||||
[LangKeys.MyWalletSendFieldAddress]: "Dirección",
|
||||
[LangKeys.MyWalletSendFieldAddressPlaceholder]: "Pegue la dirección aquí...",
|
||||
[LangKeys.MyWalletSendFieldPaymentId]: "ID de pago",
|
||||
[LangKeys.MyWalletSendFieldPaymentIdPlaceholder]: "Tipo",
|
||||
[LangKeys.MyWalletMoneroAvaliableBalance]: "Saldo disponible",
|
||||
[LangKeys.MyWalletMoneroReserveredFunds]: "Fondos Reservados",
|
||||
[LangKeys.MyWalletMoneroTotalBalance]: "Balance total",
|
||||
[LangKeys.MyWalletMoneroAvailableBalance]: "Saldo disponible",
|
||||
[LangKeys.MyWalletMoneroReservedFunds]: "Fondos Reservados",
|
||||
[LangKeys.MyWalletMoneroLockedFunds]: "Fondos bloqueados",
|
||||
[LangKeys.MyWalletTabTransactions]: "Transactions",
|
||||
[LangKeys.MyWalletTabSend]: "Enviar",
|
||||
|
19
packages/renderer/src/constants/modals.ts
Normal file
19
packages/renderer/src/constants/modals.ts
Normal file
@ -0,0 +1,19 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
export enum Modals {
|
||||
QRCodeAddress = "QRCodeAddress",
|
||||
}
|
@ -24,6 +24,9 @@ interface BalanceInfo {
|
||||
lockedBalance: number;
|
||||
reservedOfferBalance: number;
|
||||
reservedTradeBalance: number;
|
||||
availableBalance: number;
|
||||
reservedBalance: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export function useBalances() {
|
||||
@ -33,12 +36,25 @@ export function useBalances() {
|
||||
const xmrBalances = await client.getBalances();
|
||||
const balances = xmrBalances.toObject();
|
||||
|
||||
const balance = parseFloat(balances.balance);
|
||||
const unlockedBalance = parseFloat(balances.unlockedBalance);
|
||||
const lockedBalance = parseFloat(balances.lockedBalance);
|
||||
const reservedOfferBalance = parseFloat(balances.reservedOfferBalance);
|
||||
const reservedTradeBalance = parseFloat(balances.reservedTradeBalance);
|
||||
|
||||
const availableBalance = unlockedBalance;
|
||||
const reservedBalance = reservedOfferBalance + reservedTradeBalance;
|
||||
const total = availableBalance + lockedBalance + reservedBalance;
|
||||
|
||||
return {
|
||||
balance: parseFloat(balances.balance),
|
||||
unlockedBalance: parseFloat(balances.unlockedBalance),
|
||||
lockedBalance: parseFloat(balances.lockedBalance),
|
||||
reservedOfferBalance: parseFloat(balances.reservedOfferBalance),
|
||||
reservedTradeBalance: parseFloat(balances.reservedTradeBalance),
|
||||
balance,
|
||||
unlockedBalance,
|
||||
lockedBalance,
|
||||
reservedOfferBalance,
|
||||
reservedTradeBalance,
|
||||
availableBalance,
|
||||
reservedBalance,
|
||||
total,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
23
packages/renderer/src/hooks/haveno/useSetDownloadQRCode.ts
Normal file
23
packages/renderer/src/hooks/haveno/useSetDownloadQRCode.ts
Normal file
@ -0,0 +1,23 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { useMutation } from "react-query";
|
||||
|
||||
export function useSetDownloadQRCode() {
|
||||
return useMutation(async (code: string) => {
|
||||
await window.haveno.downloadQRCode(code);
|
||||
});
|
||||
}
|
91
yarn.lock
91
yarn.lock
@ -3343,6 +3343,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
|
||||
integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
|
||||
|
||||
"@types/qrcode@^1.4.2":
|
||||
version "1.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/qrcode/-/qrcode-1.4.2.tgz#7d7142d6fa9921f195db342ed08b539181546c74"
|
||||
integrity sha512-7uNT9L4WQTNJejHTSTdaJhfBSCN73xtXaHFyBJ8TSwiLhe4PRuTue7Iph0s2nG9R/ifUaSnGhLUOZavlBEqDWQ==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/qs@^6.2.31", "@types/qs@^6.9.5":
|
||||
version "6.9.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
|
||||
@ -4948,7 +4955,7 @@ camelcase@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
|
||||
integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
|
||||
|
||||
camelcase@^5.3.1:
|
||||
camelcase@^5.0.0, camelcase@^5.3.1:
|
||||
version "5.3.1"
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
||||
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||
@ -5184,6 +5191,15 @@ cli-truncate@^2.1.0:
|
||||
slice-ansi "^3.0.0"
|
||||
string-width "^4.2.0"
|
||||
|
||||
cliui@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
|
||||
integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
|
||||
dependencies:
|
||||
string-width "^4.2.0"
|
||||
strip-ansi "^6.0.0"
|
||||
wrap-ansi "^6.2.0"
|
||||
|
||||
cliui@^7.0.2:
|
||||
version "7.0.4"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
|
||||
@ -5867,7 +5883,7 @@ decamelize-keys@^1.1.0:
|
||||
decamelize "^1.1.0"
|
||||
map-obj "^1.0.0"
|
||||
|
||||
decamelize@^1.1.0:
|
||||
decamelize@^1.1.0, decamelize@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
|
||||
@ -6030,6 +6046,11 @@ diffie-hellman@^5.0.0:
|
||||
miller-rabin "^4.0.0"
|
||||
randombytes "^2.0.0"
|
||||
|
||||
dijkstrajs@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.2.tgz#2e48c0d3b825462afe75ab4ad5e829c8ece36257"
|
||||
integrity sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==
|
||||
|
||||
dir-compare@^2.4.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/dir-compare/-/dir-compare-2.4.0.tgz#785c41dc5f645b34343a4eafc50b79bac7f11631"
|
||||
@ -6399,6 +6420,11 @@ emotion-theming@^10.0.27:
|
||||
"@emotion/weak-memoize" "0.2.5"
|
||||
hoist-non-react-statics "^3.3.0"
|
||||
|
||||
encode-utf8@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda"
|
||||
integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==
|
||||
|
||||
encodeurl@^1.0.2, encodeurl@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||
@ -7611,7 +7637,7 @@ gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2:
|
||||
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
|
||||
|
||||
get-caller-file@^2.0.5:
|
||||
get-caller-file@^2.0.1, get-caller-file@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
@ -10869,6 +10895,11 @@ pngjs@6.0.0:
|
||||
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-6.0.0.tgz#ca9e5d2aa48db0228a52c419c3308e87720da821"
|
||||
integrity sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==
|
||||
|
||||
pngjs@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb"
|
||||
integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==
|
||||
|
||||
pnp-webpack-plugin@1.6.4:
|
||||
version "1.6.4"
|
||||
resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149"
|
||||
@ -11221,6 +11252,16 @@ qr.js@0.0.0:
|
||||
resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f"
|
||||
integrity sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8=
|
||||
|
||||
qrcode@^1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.5.0.tgz#95abb8a91fdafd86f8190f2836abbfc500c72d1b"
|
||||
integrity sha512-9MgRpgVc+/+47dFvQeD6U2s0Z92EsKzcHogtum4QB+UNd025WOJSHvn/hjk9xmzj7Stj95CyUAs31mrjxliEsQ==
|
||||
dependencies:
|
||||
dijkstrajs "^1.0.1"
|
||||
encode-utf8 "^1.0.3"
|
||||
pngjs "^5.0.0"
|
||||
yargs "^15.3.1"
|
||||
|
||||
qs@6.9.7:
|
||||
version "6.9.7"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe"
|
||||
@ -11862,6 +11903,11 @@ require-from-string@^2.0.2:
|
||||
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
|
||||
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
|
||||
|
||||
require-main-filename@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
|
||||
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
|
||||
|
||||
resolve-from@5.0.0, resolve-from@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
|
||||
@ -13933,6 +13979,11 @@ which-boxed-primitive@^1.0.2:
|
||||
is-string "^1.0.5"
|
||||
is-symbol "^1.0.3"
|
||||
|
||||
which-module@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
|
||||
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
|
||||
|
||||
which@^1.2.9:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
||||
@ -13992,6 +14043,15 @@ worker-rpc@^0.1.0:
|
||||
dependencies:
|
||||
microevent.ts "~0.1.1"
|
||||
|
||||
wrap-ansi@^6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
|
||||
integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrap-ansi@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||
@ -14110,6 +14170,14 @@ yaml@^1.10.0, yaml@^1.7.2:
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
||||
|
||||
yargs-parser@^18.1.2:
|
||||
version "18.1.3"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
|
||||
integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
|
||||
dependencies:
|
||||
camelcase "^5.0.0"
|
||||
decamelize "^1.2.0"
|
||||
|
||||
yargs-parser@^20.2.2, yargs-parser@^20.2.3, yargs-parser@^20.2.9:
|
||||
version "20.2.9"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
|
||||
@ -14120,6 +14188,23 @@ yargs-parser@^21.0.0:
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35"
|
||||
integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==
|
||||
|
||||
yargs@^15.3.1:
|
||||
version "15.4.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
|
||||
integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
|
||||
dependencies:
|
||||
cliui "^6.0.0"
|
||||
decamelize "^1.2.0"
|
||||
find-up "^4.1.0"
|
||||
get-caller-file "^2.0.1"
|
||||
require-directory "^2.1.1"
|
||||
require-main-filename "^2.0.0"
|
||||
set-blocking "^2.0.0"
|
||||
string-width "^4.2.0"
|
||||
which-module "^2.0.0"
|
||||
y18n "^4.0.0"
|
||||
yargs-parser "^18.1.2"
|
||||
|
||||
yargs@^16.2.0:
|
||||
version "16.2.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
|
||||
|
Loading…
Reference in New Issue
Block a user