Skip to content

Commit

Permalink
feat: add channel alerts in send and receive pages (#286)
Browse files Browse the repository at this point in the history
* chore: add channel alerts in send and receive pages

* chore: change send alert title

* chore: check amount being entered

* chore: check if amount > 80% of total spendable/receivable

* chore: add alerts to wallet screen

* fix: decrease opacity on disabled checklist items

* fix: check channel management for alerts on wallet page

---------

Co-authored-by: Roland Bewick <roland.bewick@gmail.com>
  • Loading branch information
im-adithya and rolznz authored Jul 19, 2024
1 parent dfa8e44 commit e4f595b
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 17 deletions.
3 changes: 2 additions & 1 deletion frontend/src/screens/wallet/OnboardingChecklist.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ function ChecklistItem({
<div
className={cn(
"flex flex-col p-3 relative group rounded-lg",
!checked && !disabled && "hover:bg-muted"
!checked && !disabled && "hover:bg-muted",
disabled && "opacity-50"
)}
>
{!checked && !disabled && (
Expand Down
25 changes: 24 additions & 1 deletion frontend/src/screens/wallet/Receive.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import confetti from "canvas-confetti";
import { ArrowDown, CircleCheck, CopyIcon } from "lucide-react";
import { AlertTriangle, ArrowDown, CircleCheck, CopyIcon } from "lucide-react";
import React from "react";
import { Link } from "react-router-dom";
import AppHeader from "src/components/AppHeader";
import Loading from "src/components/Loading";
import QRCode from "src/components/QRCode";
import {
Alert,
AlertDescription,
AlertTitle,
} from "src/components/ui/alert.tsx";
import { Button } from "src/components/ui/button";
import {
Card,
Expand Down Expand Up @@ -52,6 +57,10 @@ export default function Receive() {
}
}, [invoiceData, toast]);

if (!balances) {
return <Loading />;
}

const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
if (!csrf) {
Expand Down Expand Up @@ -118,6 +127,20 @@ export default function Receive() {
title="Receive"
description="Create a lightning invoice that can be paid by any bitcoin lightning wallet"
/>
{hasChannelManagement &&
parseInt(amount || "0") * 1000 >=
0.8 * balances.lightning.totalReceivable && (
<Alert>
<AlertTriangle className="h-4 w-4" />
<AlertTitle>Low receiving capacity</AlertTitle>
<AlertDescription>
You likely won't be able to receive payments until you{" "}
<Link className="underline" to="/channels/incoming">
increase your receiving capacity.
</Link>
</AlertDescription>
</Alert>
)}
<div className="flex gap-12 w-full">
<div className="w-full max-w-lg">
{transaction ? (
Expand Down
52 changes: 39 additions & 13 deletions frontend/src/screens/wallet/Send.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import { Invoice } from "@getalby/lightning-tools";
import { ArrowUp, CircleCheck, ClipboardPaste, CopyIcon } from "lucide-react";
import {
AlertTriangle,
ArrowUp,
CircleCheck,
ClipboardPaste,
CopyIcon,
} from "lucide-react";
import React from "react";
import { Link } from "react-router-dom";
import AppHeader from "src/components/AppHeader";
import Loading from "src/components/Loading";
import {
Alert,
AlertDescription,
AlertTitle,
} from "src/components/ui/alert.tsx";
import { Button } from "src/components/ui/button";
import {
Card,
Expand All @@ -17,6 +28,7 @@ import { Label } from "src/components/ui/label";
import { LoadingButton } from "src/components/ui/loading-button";
import { useToast } from "src/components/ui/use-toast";
import { useBalances } from "src/hooks/useBalances";
import { useChannels } from "src/hooks/useChannels";
import { useCSRF } from "src/hooks/useCSRF";
import { useInfo } from "src/hooks/useInfo";
import { copyToClipboard } from "src/lib/clipboard";
Expand All @@ -26,23 +38,25 @@ import { request } from "src/utils/request";
export default function Send() {
const { hasChannelManagement } = useInfo();
const { data: balances } = useBalances();
const { data: channels } = useChannels();
const { data: csrf } = useCSRF();
const { toast } = useToast();
const [isLoading, setLoading] = React.useState(false);
const [invoice, setInvoice] = React.useState("");
const [invoiceDetails, setInvoiceDetails] = React.useState<Invoice | null>(
null
);
const [payResponse, setPayResponse] =
React.useState<PayInvoiceResponse | null>(null);
const [paymentDone, setPaymentDone] = React.useState(false);
const [showConfirmation, setShowConfirmation] = React.useState(false);

if (!balances) {
if (!balances || !channels) {
return <Loading />;
}

const handleContinue = () => {
try {
new Invoice({ pr: invoice });
setShowConfirmation(true);
setInvoiceDetails(new Invoice({ pr: invoice }));
} catch (error) {
toast({
variant: "destructive",
Expand Down Expand Up @@ -84,7 +98,7 @@ export default function Send() {
title: "Failed to send: " + e,
});
setInvoice("");
setShowConfirmation(false);
setInvoiceDetails(null);
console.error(e);
}
setLoading(false);
Expand All @@ -106,6 +120,20 @@ export default function Send() {
title="Send"
description="Pay a lightning invoice created by any bitcoin lightning wallet"
/>
{hasChannelManagement &&
(invoiceDetails?.satoshi || 0) * 1000 >=
0.8 * balances.lightning.totalSpendable && (
<Alert>
<AlertTriangle className="h-4 w-4" />
<AlertTitle>Low spending balance</AlertTitle>
<AlertDescription>
You won't be able to make payments until you{" "}
<Link className="underline" to="/channels/outgoing">
increase your spending balance.
</Link>
</AlertDescription>
</Alert>
)}
<div className="flex gap-12 w-full">
<div className="w-full max-w-lg">
{paymentDone ? (
Expand All @@ -130,7 +158,7 @@ export default function Send() {
className="mt-4 w-full"
onClick={() => {
setPaymentDone(false);
setShowConfirmation(false);
setInvoiceDetails(null);
setPayResponse(null);
setInvoice("");
}}
Expand All @@ -151,15 +179,13 @@ export default function Send() {
</>
)}
</>
) : showConfirmation ? (
) : invoiceDetails ? (
<form onSubmit={handleSubmit} className="grid gap-5">
<div className="">
<p className="text-lg mb-5">Payment Details</p>
<p className="font-bold">
{new Invoice({ pr: invoice }).satoshi} sats
</p>
<p className="font-bold">{invoiceDetails.satoshi} sats</p>
<p className="text-muted-foreground">
{new Invoice({ pr: invoice }).description}
{invoiceDetails.description}
</p>
</div>
<div className="flex gap-5">
Expand All @@ -172,7 +198,7 @@ export default function Send() {
Confirm Payment
</LoadingButton>
<Button
onClick={() => setShowConfirmation(false)}
onClick={() => setInvoiceDetails(null)}
variant="secondary"
>
Back
Expand Down
38 changes: 36 additions & 2 deletions frontend/src/screens/wallet/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
import { ArrowDownIcon, ArrowUpIcon, CreditCard } from "lucide-react";
import {
AlertTriangle,
ArrowDownIcon,
ArrowUpIcon,
CreditCard,
} from "lucide-react";
import { Link } from "react-router-dom";
import AppHeader from "src/components/AppHeader";
import BreezRedeem from "src/components/BreezRedeem";
import ExternalLink from "src/components/ExternalLink";
import Loading from "src/components/Loading";
import TransactionsList from "src/components/TransactionsList";
import {
Alert,
AlertDescription,
AlertTitle,
} from "src/components/ui/alert.tsx";
import { Button } from "src/components/ui/button";
import { useBalances } from "src/hooks/useBalances";
import { useInfo } from "src/hooks/useInfo";

function Wallet() {
const { data: info } = useInfo();
const { data: info, hasChannelManagement } = useInfo();
const { data: balances } = useBalances();

if (!info || !balances) {
Expand All @@ -20,6 +30,30 @@ function Wallet() {
return (
<>
<AppHeader title="Wallet" description="" />
{hasChannelManagement && !balances.lightning.totalSpendable && (
<Alert>
<AlertTriangle className="h-4 w-4" />
<AlertTitle>Low spending balance</AlertTitle>
<AlertDescription>
You won't be able to make payments until you{" "}
<Link className="underline" to="/channels/outgoing">
increase your spending balance.
</Link>
</AlertDescription>
</Alert>
)}
{hasChannelManagement && !balances.lightning.totalReceivable && (
<Alert>
<AlertTriangle className="h-4 w-4" />
<AlertTitle>Low receiving capacity</AlertTitle>
<AlertDescription>
You won't be able to receive payments until you{" "}
<Link className="underline" to="/channels/incoming">
increase your receiving capacity.
</Link>
</AlertDescription>
</Alert>
)}
<BreezRedeem />
<div className="flex flex-col lg:flex-row justify-between lg:items-center gap-5">
<div className="text-5xl font-semibold balance sensitive ph-no-capture">
Expand Down

0 comments on commit e4f595b

Please sign in to comment.