fix: My Wallet page

- download qr code
- ui inconsistencies fixed

---
Reviewed-by @schowdhuri
This commit is contained in:
Ahmed Bouhuolia 2022-06-02 18:10:38 +02:00 committed by GitHub
parent b40fe25930
commit ec2193b460
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 353 additions and 66 deletions

View File

@ -56,6 +56,7 @@
"@types/lodash": "^4.14.182", "@types/lodash": "^4.14.182",
"@types/react": "<18.0.0", "@types/react": "<18.0.0",
"@types/react-dom": "<18.0.0", "@types/react-dom": "<18.0.0",
"@types/qrcode": "^1.4.2",
"@typescript-eslint/eslint-plugin": "5.12.1", "@typescript-eslint/eslint-plugin": "5.12.1",
"@typescript-eslint/parser": "^5.19.0", "@typescript-eslint/parser": "^5.19.0",
"@vitejs/plugin-react": "^1.3.0", "@vitejs/plugin-react": "^1.3.0",
@ -96,6 +97,7 @@
"joi": "^17.6.0", "joi": "^17.6.0",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"qrcode": "^1.5.0",
"react": "<18.0.0", "react": "<18.0.0",
"react-dom": "<18.0.0", "react-dom": "<18.0.0",
"react-intl": "^5.24.8", "react-intl": "^5.24.8",

View File

@ -16,6 +16,9 @@
import fsPromises from "fs/promises"; import fsPromises from "fs/promises";
import { ipcMain, dialog } from "electron"; 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 type { DownloadBackupInput } from "@src/types";
import { IpcChannels } from "@src/types"; import { IpcChannels } from "@src/types";
@ -56,4 +59,33 @@ export function registerHavenoHandlers() {
const zipFile = files.filePaths[0]; const zipFile = files.filePaths[0];
return new Uint8Array(await fsPromises.readFile(zipFile)); 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;
}
);
}
);
} }

View File

@ -27,6 +27,7 @@ export enum IpcChannels {
// haveno // haveno
DownloadBackup = "haveno:downloadBackup", DownloadBackup = "haveno:downloadBackup",
RestoreBackup = "haveno:restoreBackup", RestoreBackup = "haveno:restoreBackup",
DownloadQRCode = "haveno:downloadQRCode",
// others // others
VerifyAuthToken = "verifyAuthToken", VerifyAuthToken = "verifyAuthToken",

View File

@ -26,6 +26,9 @@ export const haveno = {
getBackupData: async (): Promise<Uint8Array> => getBackupData: async (): Promise<Uint8Array> =>
ipcRenderer.invoke(IpcChannels.RestoreBackup), ipcRenderer.invoke(IpcChannels.RestoreBackup),
downloadQRCode: async (qrCode: string): Promise<void> =>
ipcRenderer.invoke(IpcChannels.DownloadQRCode, qrCode),
}; };
exposeInMainWorld("haveno", haveno); exposeInMainWorld("haveno", haveno);

View File

@ -0,0 +1 @@
export * from "./DetailItemCard";

View File

@ -45,14 +45,14 @@ const useStyles = createStyles((theme, _params, getRef) => {
paddingRight: 0, paddingRight: 0,
textTransform: "uppercase", textTransform: "uppercase",
"&:first-child": { "&:first-of-type": {
marginLeft: 0, marginLeft: 0,
}, },
"&:last-child": { "&:last-child": {
marginRight: 0, marginRight: 0,
}, },
[`&.${tabActiveRef}`]: { [`&.${tabActiveRef}`]: {
borderBottomColor: theme.primaryColor, borderBottomColor: theme.colors.blue[6],
color: theme.colors.dark[9], color: theme.colors.dark[9],
}, },
}, },

View 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],
},
}));

View File

@ -16,3 +16,4 @@
export * from "./Heading"; export * from "./Heading";
export * from "./Text"; export * from "./Text";
export * from "./Anchor";

View File

@ -17,20 +17,17 @@
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import QRCode from "react-qr-code"; import QRCode from "react-qr-code";
import type { OpenConfirmModal } from "@mantine/modals/lib/context"; import type { OpenConfirmModal } from "@mantine/modals/lib/context";
import { showNotification } from "@mantine/notifications";
import { useModals } from "@mantine/modals"; import { useModals } from "@mantine/modals";
import { useClipboard } from "@mantine/hooks"; import { useClipboard } from "@mantine/hooks";
import { import { Box, createStyles, Group, SimpleGrid, Skeleton } from "@mantine/core";
Anchor,
Box,
createStyles,
Group,
SimpleGrid,
Skeleton,
} from "@mantine/core";
import { DetailItem } from "@atoms/DetailItem"; import { DetailItem } from "@atoms/DetailItem";
import { Button } from "@atoms/Buttons"; import { Button } from "@atoms/Buttons";
import { Anchor } from "@atoms/Typography";
import { DetailItemCard } from "@atoms/DetailItemCard";
import { LangKeys } from "@constants/lang"; import { LangKeys } from "@constants/lang";
import { DetailItemCard } from "@atoms/DetailItemCard/DetailItemCard"; import { useSetDownloadQRCode } from "@hooks/haveno/useSetDownloadQRCode";
import { Modals } from "@constants/modals";
interface AddressCardProps { interface AddressCardProps {
label?: string; label?: string;
@ -49,17 +46,34 @@ export function AddressCard({
}: AddressCardProps) { }: AddressCardProps) {
const modals = useModals(); const modals = useModals();
const { classes } = useStyles(); const { classes } = useStyles();
const { formatMessage } = useIntl();
const { mutateAsync: downloadQRCode } = useSetDownloadQRCode();
const clipboard = useClipboard({ timeout: COPY_TEXT_TIMEOUT }); const clipboard = useClipboard({ timeout: COPY_TEXT_TIMEOUT });
const handleCopyClick = () => { const handleCopyClick = () => {
clipboard.copy(address); 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 handleQRClick = () => {
const modalId = modals.openModal({ const modalId = modals.openModal({
id: Modals.QRCodeAddress,
children: ( children: (
<AddressCardQRModalContent <AddressCardQRModalContent
address={address} address={address}
onQRDownloadClick={handleQRDownloadClick}
onReturnClick={() => modals.closeModal(modalId)} onReturnClick={() => modals.closeModal(modalId)}
/> />
), ),
@ -137,7 +151,7 @@ export function AddressCardSkeleton({
interface AddressCardQRModalContentProps { interface AddressCardQRModalContentProps {
address: string; address: string;
onQRDownloadClick?: () => void; onQRDownloadClick?: (address: string) => void;
onReturnClick?: () => void; onReturnClick?: () => void;
} }
@ -149,10 +163,16 @@ function AddressCardQRModalContent({
const { classes } = useStyles(); const { classes } = useStyles();
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
const handleQRDownloadClick = () => {
onQRDownloadClick && onQRDownloadClick(address);
};
return ( return (
<Box> <Box className={classes.qrModalRoot}>
<DetailItem <DetailItem
classNames={{ content: classes.qrModalAddress }} classNames={{
content: classes.qrModalAddress,
label: classes.qrModalAddressLabel,
}}
label={formatMessage({ label={formatMessage({
id: LangKeys.MyWalletQRModalPrimaryAddress, id: LangKeys.MyWalletQRModalPrimaryAddress,
defaultMessage: "Primary Address", defaultMessage: "Primary Address",
@ -173,7 +193,7 @@ function AddressCardQRModalContent({
/> />
</Button> </Button>
<Button onClick={onQRDownloadClick}> <Button onClick={handleQRDownloadClick}>
<FormattedMessage <FormattedMessage
id={LangKeys.MyWalletQRModalDownloadQRBtn} id={LangKeys.MyWalletQRModalDownloadQRBtn}
defaultMessage="Download QR" defaultMessage="Download QR"
@ -197,11 +217,18 @@ const useStyles = createStyles((theme) => ({
addressBtns: { addressBtns: {
marginLeft: "auto", marginLeft: "auto",
}, },
qrModalRoot: {
padding: "1.5rem",
},
qrRoot: { qrRoot: {
marginTop: theme.spacing.xl, marginTop: theme.spacing.xl * 1.5,
marginBottom: theme.spacing.xl * 1.5,
textAlign: "center", textAlign: "center",
}, },
qrModalAddress: { qrModalAddress: {
fontSize: theme.fontSizes.lg, fontSize: theme.fontSizes.lg,
}, },
qrModalAddressLabel: {
fontSize: theme.fontSizes.xs,
},
})); }));

View File

@ -44,12 +44,12 @@ exports[`molecules::AddressCard > renders without exploding 1`] = `
class="mantine-Group-root mantine-Group-child mantine-ze53qg" class="mantine-Group-root mantine-Group-child mantine-ze53qg"
> >
<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"
> >
Copy Copy
</a> </a>
<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 QR
</a> </a>

View File

@ -64,7 +64,7 @@ export function WalletTransactions({ data }: WalletTransactionsProps) {
const useStyles = createStyles(() => ({ const useStyles = createStyles(() => ({
root: { root: {
"tbody tr td:first-child": { "tbody tr td:first-of-type": {
paddingLeft: 0, paddingLeft: 0,
}, },
"tbody tr td:last-child": { "tbody tr td:last-child": {

View File

@ -33,22 +33,32 @@ export function MyWalletMoneroBalanceContent() {
<MoneroBalance> <MoneroBalance>
<MoneroBalance.Detail <MoneroBalance.Detail
label={formatMessage({ label={formatMessage({
id: LangKeys.MyWalletMoneroAvaliableBalance, id: LangKeys.MyWalletMoneroTotalBalance,
defaultMessage: "Avaliable Balance", defaultMessage: "Total Balance",
})} })}
data-testid="avaliable-balance" data-testid="total-balance"
> >
<Currency value={balanceInfo.balance} /> <Currency value={balanceInfo.total} />
</MoneroBalance.Detail> </MoneroBalance.Detail>
<MoneroBalance.Detail <MoneroBalance.Detail
label={formatMessage({ label={formatMessage({
id: LangKeys.MyWalletMoneroReserveredFunds, id: LangKeys.MyWalletMoneroAvailableBalance,
defaultMessage: "Reservered Funds", 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>
<MoneroBalance.Detail <MoneroBalance.Detail

View File

@ -26,8 +26,8 @@ export function MyWalletMeneroBalanceSkeleton() {
<MoneroBalance> <MoneroBalance>
<MoneroBalance.Detail <MoneroBalance.Detail
label={formatMessage({ label={formatMessage({
id: LangKeys.MyWalletMoneroAvaliableBalance, id: LangKeys.MyWalletMoneroTotalBalance,
defaultMessage: "Avaliable Balance", defaultMessage: "Total Balance",
})} })}
> >
<Skeleton height={8} radius="xl" mt={6} /> <Skeleton height={8} radius="xl" mt={6} />
@ -35,8 +35,17 @@ export function MyWalletMeneroBalanceSkeleton() {
<MoneroBalance.Detail <MoneroBalance.Detail
label={formatMessage({ label={formatMessage({
id: LangKeys.MyWalletMoneroReserveredFunds, id: LangKeys.MyWalletMoneroAvailableBalance,
defaultMessage: "Reservered Funds", 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} /> <Skeleton height={8} radius="xl" mt={6} />

View File

@ -28,9 +28,10 @@ describe("organisms::MyWalletMoneroBalance", () => {
data: { data: {
balance: MoneroBalance.balance, balance: MoneroBalance.balance,
lockedBalance: MoneroBalance.lockedBalance, lockedBalance: MoneroBalance.lockedBalance,
reservedOfferBalance: MoneroBalance.reserverdBalance, reservedBalance: MoneroBalance.reservedBalance,
reservedTradeBalance: MoneroBalance.reserverdBalance,
unlockedBalance: MoneroBalance.unlockedBalance, unlockedBalance: MoneroBalance.unlockedBalance,
total: MoneroBalance.total,
availableBalance: MoneroBalance.availableBalance,
}, },
}), }),
})); }));
@ -46,28 +47,30 @@ describe("organisms::MyWalletMoneroBalance", () => {
unmount(); 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( const { unmount } = render(
<AppProviders> <AppProviders>
<MyWalletMoneroBalance /> <MyWalletMoneroBalance />
</AppProviders> </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("locked-funds")).toBeInTheDocument();
expect(screen.queryByTestId("reserverd-funds")).toBeInTheDocument(); expect(screen.queryByTestId("reserved-funds")).toBeInTheDocument();
unmount(); 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( const { unmount } = render(
<AppProviders> <AppProviders>
<MyWalletMoneroBalance /> <MyWalletMoneroBalance />
</AppProviders> </AppProviders>
); );
expect(screen.queryByTestId("avaliable-balance")).toHaveTextContent( expect(screen.queryByTestId("total-balance")).toHaveTextContent("1,000.1");
"835,120.34017" expect(screen.queryByTestId("available-balance")).toHaveTextContent(
"8,000.65"
); );
expect(screen.queryByTestId("reserverd-funds")).toHaveTextContent( expect(screen.queryByTestId("reserved-funds")).toHaveTextContent(
"74,610.1236" "74,610.1236"
); );
expect(screen.queryByTestId("locked-funds")).toHaveTextContent( expect(screen.queryByTestId("locked-funds")).toHaveTextContent(
@ -79,7 +82,9 @@ describe("organisms::MyWalletMoneroBalance", () => {
const MoneroBalance = { const MoneroBalance = {
balance: 835120.34017, balance: 835120.34017,
reserverdBalance: 74610.1236, reservedBalance: 74610.1236,
lockedBalance: 90371.161239, lockedBalance: 90371.161239,
unlockedBalance: 0, unlockedBalance: 0,
total: 1000.1,
availableBalance: 8000.65,
}; };

View File

@ -43,27 +43,42 @@ exports[`organisms::MyWalletMoneroBalance > renders without exploding 1`] = `
> >
<div <div
class="mantine-Stack-root mantine-DetailItem-root mantine-Group-child mantine-2d5onn" class="mantine-Stack-root mantine-DetailItem-root mantine-Group-child mantine-2d5onn"
data-testid="avaliable-balance" data-testid="total-balance"
> >
<div <div
class="mantine-Text-root mantine-DetailItem-label mantine-10gsq91" class="mantine-Text-root mantine-DetailItem-label mantine-10gsq91"
> >
Avaliable Balance Total Balance
</div> </div>
<div <div
class="mantine-Text-root mantine-DetailItem-content mantine-oat2gy" class="mantine-Text-root mantine-DetailItem-content mantine-oat2gy"
> >
835,120.34017 1,000.10
</div> </div>
</div> </div>
<div <div
class="mantine-Stack-root mantine-DetailItem-root mantine-Group-child mantine-2d5onn" class="mantine-Stack-root mantine-DetailItem-root mantine-Group-child mantine-2d5onn"
data-testid="reserverd-funds" data-testid="available-balance"
> >
<div <div
class="mantine-Text-root mantine-DetailItem-label mantine-10gsq91" 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>
<div <div
class="mantine-Text-root mantine-DetailItem-content mantine-oat2gy" class="mantine-Text-root mantine-DetailItem-content mantine-oat2gy"

View File

@ -47,7 +47,7 @@ exports[`organisms::MyWalletMeneroBalanceSkeleton > renders without exploding 1`
<div <div
class="mantine-Text-root mantine-DetailItem-label mantine-10gsq91" class="mantine-Text-root mantine-DetailItem-label mantine-10gsq91"
> >
Avaliable Balance Total Balance
</div> </div>
<div <div
class="mantine-Text-root mantine-DetailItem-content mantine-oat2gy" class="mantine-Text-root mantine-DetailItem-content mantine-oat2gy"
@ -63,7 +63,23 @@ exports[`organisms::MyWalletMeneroBalanceSkeleton > renders without exploding 1`
<div <div
class="mantine-Text-root mantine-DetailItem-label mantine-10gsq91" 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>
<div <div
class="mantine-Text-root mantine-DetailItem-content mantine-oat2gy" class="mantine-Text-root mantine-DetailItem-content mantine-oat2gy"

View File

@ -28,12 +28,12 @@ exports[`organisms::MyWalletPrimaryAddress > renders without exploding 1`] = `
class="mantine-Group-root mantine-Group-child mantine-ze53qg" class="mantine-Group-root mantine-Group-child mantine-ze53qg"
> >
<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"
> >
Copy Copy
</a> </a>
<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 QR
</a> </a>

View File

@ -77,7 +77,7 @@ export function MyWalletSendForm() {
return ( return (
<form onSubmit={form.onSubmit(handleFormSubmit)}> <form onSubmit={form.onSubmit(handleFormSubmit)}>
<Stack spacing="xl"> <Stack spacing="xl" mt="md">
<SimpleGrid cols={2}> <SimpleGrid cols={2}>
<TextInput <TextInput
id="amount" id="amount"

View File

@ -3,7 +3,7 @@
exports[`organisms::MyWalletMoneroBalance > renders without exploding. 1`] = ` exports[`organisms::MyWalletMoneroBalance > renders without exploding. 1`] = `
<DocumentFragment> <DocumentFragment>
<table <table
class="mantine-Table-root mantine-16jrhzw" class="mantine-Table-root mantine-u2os4d"
> >
<tbody> <tbody>
<tr> <tr>

View File

@ -59,14 +59,16 @@ export enum LangKeys {
AddressCardCopyBtn = "accountCard.copyButton", AddressCardCopyBtn = "accountCard.copyButton",
AddressCardCopiedBtn = "accountCard.copiedButton", AddressCardCopiedBtn = "accountCard.copiedButton",
AddressCardQRBtn = "accountCard.qrButton", AddressCardQRBtn = "accountCard.qrButton",
AddressCardQRCodeSavedSuccessNotif = "accountCode.qrCodeSavedSuccessfully.notification",
MyWalletSendFieldAmount = "myWallet.send.amountField", MyWalletSendFieldAmount = "myWallet.send.amountField",
MyWalletSendFieldPaymentId = "myWallet.send.paymentIdField", MyWalletSendFieldPaymentId = "myWallet.send.paymentIdField",
MyWalletSendFieldPaymentIdPlaceholder = "myWallet.send.paymentIdFieldPlaceholder", MyWalletSendFieldPaymentIdPlaceholder = "myWallet.send.paymentIdFieldPlaceholder",
MyWalletSendFieldAddress = "myWallet.send.addressField", MyWalletSendFieldAddress = "myWallet.send.addressField",
MyWalletSendFieldAddressPlaceholder = "myWallet.send.addressFieldPlaceholder", MyWalletSendFieldAddressPlaceholder = "myWallet.send.addressFieldPlaceholder",
MyWalletReceiveTitle = "myWallet.receive.receiveTitle", MyWalletReceiveTitle = "myWallet.receive.receiveTitle",
MyWalletMoneroAvaliableBalance = "myWallet.monero.avaliableBalance", MyWalletMoneroTotalBalance = "myWallet.monero.totalBalance",
MyWalletMoneroReserveredFunds = "myWallet.monero.reserveredFunds", MyWalletMoneroAvailableBalance = "myWallet.monero.availableBalance",
MyWalletMoneroReservedFunds = "myWallet.monero.reservedFunds",
MyWalletMoneroLockedFunds = "myWallet.monero.lockedFunds", MyWalletMoneroLockedFunds = "myWallet.monero.lockedFunds",
MyWalletTabTransactions = "myWallet.transactionsTab", MyWalletTabTransactions = "myWallet.transactionsTab",
MyWalletTabSend = "myWallet.sendTab", MyWalletTabSend = "myWallet.sendTab",

View File

@ -69,13 +69,16 @@ const LangPackEN: { [key in LangKeys]: string } = {
[LangKeys.AddressCardCopyBtn]: "Copy", [LangKeys.AddressCardCopyBtn]: "Copy",
[LangKeys.AddressCardCopiedBtn]: "Copied", [LangKeys.AddressCardCopiedBtn]: "Copied",
[LangKeys.AddressCardQRBtn]: "QR", [LangKeys.AddressCardQRBtn]: "QR",
[LangKeys.AddressCardQRCodeSavedSuccessNotif]:
"The QR code has been saved successfully.",
[LangKeys.MyWalletSendFieldAmount]: "Amount", [LangKeys.MyWalletSendFieldAmount]: "Amount",
[LangKeys.MyWalletSendFieldAddress]: "Address", [LangKeys.MyWalletSendFieldAddress]: "Address",
[LangKeys.MyWalletSendFieldAddressPlaceholder]: "Paste in address here...", [LangKeys.MyWalletSendFieldAddressPlaceholder]: "Paste in address here...",
[LangKeys.MyWalletSendFieldPaymentId]: "Payment ID", [LangKeys.MyWalletSendFieldPaymentId]: "Payment ID",
[LangKeys.MyWalletSendFieldPaymentIdPlaceholder]: "Type", [LangKeys.MyWalletSendFieldPaymentIdPlaceholder]: "Type",
[LangKeys.MyWalletMoneroAvaliableBalance]: "Avaliable Balance", [LangKeys.MyWalletMoneroTotalBalance]: "Total Balance",
[LangKeys.MyWalletMoneroReserveredFunds]: "Reservered Funds", [LangKeys.MyWalletMoneroAvailableBalance]: "Available Balance",
[LangKeys.MyWalletMoneroReservedFunds]: "Reserved Funds",
[LangKeys.MyWalletMoneroLockedFunds]: "Locked Funds", [LangKeys.MyWalletMoneroLockedFunds]: "Locked Funds",
[LangKeys.MyWalletTabTransactions]: "Transactions", [LangKeys.MyWalletTabTransactions]: "Transactions",
[LangKeys.MyWalletTabSend]: "Send", [LangKeys.MyWalletTabSend]: "Send",

View File

@ -69,13 +69,16 @@ const LangPackES: { [key in LangKeys]: string } = {
[LangKeys.AddressCardCopyBtn]: "Dupdo", [LangKeys.AddressCardCopyBtn]: "Dupdo",
[LangKeys.AddressCardCopiedBtn]: "Copiada", [LangKeys.AddressCardCopiedBtn]: "Copiada",
[LangKeys.AddressCardQRBtn]: "QR", [LangKeys.AddressCardQRBtn]: "QR",
[LangKeys.AddressCardQRCodeSavedSuccessNotif]:
"El código QR se ha guardado correctamente.",
[LangKeys.MyWalletSendFieldAmount]: "Monto", [LangKeys.MyWalletSendFieldAmount]: "Monto",
[LangKeys.MyWalletSendFieldAddress]: "Dirección", [LangKeys.MyWalletSendFieldAddress]: "Dirección",
[LangKeys.MyWalletSendFieldAddressPlaceholder]: "Pegue la dirección aquí...", [LangKeys.MyWalletSendFieldAddressPlaceholder]: "Pegue la dirección aquí...",
[LangKeys.MyWalletSendFieldPaymentId]: "ID de pago", [LangKeys.MyWalletSendFieldPaymentId]: "ID de pago",
[LangKeys.MyWalletSendFieldPaymentIdPlaceholder]: "Tipo", [LangKeys.MyWalletSendFieldPaymentIdPlaceholder]: "Tipo",
[LangKeys.MyWalletMoneroAvaliableBalance]: "Saldo disponible", [LangKeys.MyWalletMoneroTotalBalance]: "Balance total",
[LangKeys.MyWalletMoneroReserveredFunds]: "Fondos Reservados", [LangKeys.MyWalletMoneroAvailableBalance]: "Saldo disponible",
[LangKeys.MyWalletMoneroReservedFunds]: "Fondos Reservados",
[LangKeys.MyWalletMoneroLockedFunds]: "Fondos bloqueados", [LangKeys.MyWalletMoneroLockedFunds]: "Fondos bloqueados",
[LangKeys.MyWalletTabTransactions]: "Transactions", [LangKeys.MyWalletTabTransactions]: "Transactions",
[LangKeys.MyWalletTabSend]: "Enviar", [LangKeys.MyWalletTabSend]: "Enviar",

View 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",
}

View File

@ -24,6 +24,9 @@ interface BalanceInfo {
lockedBalance: number; lockedBalance: number;
reservedOfferBalance: number; reservedOfferBalance: number;
reservedTradeBalance: number; reservedTradeBalance: number;
availableBalance: number;
reservedBalance: number;
total: number;
} }
export function useBalances() { export function useBalances() {
@ -33,12 +36,25 @@ export function useBalances() {
const xmrBalances = await client.getBalances(); const xmrBalances = await client.getBalances();
const balances = xmrBalances.toObject(); 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 { return {
balance: parseFloat(balances.balance), balance,
unlockedBalance: parseFloat(balances.unlockedBalance), unlockedBalance,
lockedBalance: parseFloat(balances.lockedBalance), lockedBalance,
reservedOfferBalance: parseFloat(balances.reservedOfferBalance), reservedOfferBalance,
reservedTradeBalance: parseFloat(balances.reservedTradeBalance), reservedTradeBalance,
availableBalance,
reservedBalance,
total,
}; };
}); });
} }

View 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);
});
}

View File

@ -3343,6 +3343,13 @@
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== 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": "@types/qs@^6.2.31", "@types/qs@^6.9.5":
version "6.9.7" version "6.9.7"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" 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" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
camelcase@^5.3.1: camelcase@^5.0.0, camelcase@^5.3.1:
version "5.3.1" version "5.3.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
@ -5184,6 +5191,15 @@ cli-truncate@^2.1.0:
slice-ansi "^3.0.0" slice-ansi "^3.0.0"
string-width "^4.2.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: cliui@^7.0.2:
version "7.0.4" version "7.0.4"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" 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" decamelize "^1.1.0"
map-obj "^1.0.0" map-obj "^1.0.0"
decamelize@^1.1.0: decamelize@^1.1.0, decamelize@^1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
@ -6030,6 +6046,11 @@ diffie-hellman@^5.0.0:
miller-rabin "^4.0.0" miller-rabin "^4.0.0"
randombytes "^2.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: dir-compare@^2.4.0:
version "2.4.0" version "2.4.0"
resolved "https://registry.yarnpkg.com/dir-compare/-/dir-compare-2.4.0.tgz#785c41dc5f645b34343a4eafc50b79bac7f11631" 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" "@emotion/weak-memoize" "0.2.5"
hoist-non-react-statics "^3.3.0" 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: encodeurl@^1.0.2, encodeurl@~1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 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" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== 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" version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 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" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-6.0.0.tgz#ca9e5d2aa48db0228a52c419c3308e87720da821"
integrity sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg== 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: pnp-webpack-plugin@1.6.4:
version "1.6.4" version "1.6.4"
resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149" 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" resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f"
integrity sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8= 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: qs@6.9.7:
version "6.9.7" version "6.9.7"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" 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" 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== 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: resolve-from@5.0.0, resolve-from@^5.0.0:
version "5.0.0" version "5.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" 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-string "^1.0.5"
is-symbol "^1.0.3" 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: which@^1.2.9:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
@ -13992,6 +14043,15 @@ worker-rpc@^0.1.0:
dependencies: dependencies:
microevent.ts "~0.1.1" 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: wrap-ansi@^7.0.0:
version "7.0.0" version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 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" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== 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: yargs-parser@^20.2.2, yargs-parser@^20.2.3, yargs-parser@^20.2.9:
version "20.2.9" version "20.2.9"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" 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" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35"
integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg== 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: yargs@^16.2.0:
version "16.2.0" version "16.2.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"