remove transfer alby hosted balance + new designs for node table (#1058)

* feat: update ui for balance cards in node page

* chore: lower icons size

* feat: remove hosted balance card and transfer funds

* fix: remove /api/alby/drain

* chore: change variable name

* fix: remove migrateChannel variable

* chore: minor stylings

* fix: remove canMigrateFunds

* chore: text size for channels table

* chore: update copy in firstChannel

* fix: update copy to mention fee credits

* fix: remove albyBalance check from useOnboardingData

* fix: fee credits copy, add link to fee credits guide

* chore: improve channels cards stying

---------

Co-authored-by: Roland Bewick <roland.bewick@gmail.com>
This commit is contained in:
Pavan Joshi 2025-03-05 12:23:26 +05:30 committed by GitHub
parent d10641aee4
commit cf01b485ed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 97 additions and 360 deletions

View file

@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"io"
"math"
"net/http"
"regexp"
"slices"
@ -31,7 +30,6 @@ import (
"github.com/getAlby/hub/logger"
"github.com/getAlby/hub/nip47/permissions"
"github.com/getAlby/hub/service/keys"
"github.com/getAlby/hub/transactions"
"github.com/getAlby/hub/utils"
"github.com/getAlby/hub/version"
)
@ -485,45 +483,6 @@ func (svc *albyOAuthService) GetBalance(ctx context.Context) (*AlbyBalance, erro
return balance, nil
}
func (svc *albyOAuthService) DrainSharedWallet(ctx context.Context, lnClient lnclient.LNClient) error {
balance, err := svc.GetBalance(ctx)
if err != nil {
logger.Logger.WithError(err).Error("Failed to fetch shared balance")
return err
}
balanceSat := float64(balance.Balance)
amountSat := int64(math.Floor(
balanceSat- // Alby shared node balance in sats
(balanceSat*(8.0/1000.0))- // Alby service fee (0.8%)
(balanceSat*0.01))) - // Maximum potential routing fees (1%)
10 // Alby fee reserve (10 sats)
if amountSat < 1 {
return errors.New("not enough balance remaining")
}
// limit the maximum to 1M sats to ensure the funds can easily be migrated
// the user can migrate more if they still have sats left over
amountSat = min(amountSat, 1_000_000)
amount := uint64(amountSat * 1000)
logger.Logger.WithField("amount", amount).WithError(err).Error("Draining Alby shared wallet funds")
transaction, err := transactions.NewTransactionsService(svc.db, svc.eventPublisher).MakeInvoice(ctx, amount, "Send shared wallet funds to Alby Hub", "", 120, nil, lnClient, nil, nil)
if err != nil {
logger.Logger.WithField("amount", amount).WithError(err).Error("Failed to make invoice")
return err
}
err = svc.SendPayment(ctx, transaction.PaymentRequest)
if err != nil {
logger.Logger.WithField("amount", amount).WithError(err).Error("Failed to pay invoice from shared node")
return err
}
return nil
}
func (svc *albyOAuthService) SendPayment(ctx context.Context, invoice string) error {
token, err := svc.fetchUserToken(ctx)
if err != nil {

View file

@ -21,7 +21,6 @@ type AlbyOAuthService interface {
GetBalance(ctx context.Context) (*AlbyBalance, error)
GetMe(ctx context.Context) (*AlbyMe, error)
SendPayment(ctx context.Context, invoice string) error
DrainSharedWallet(ctx context.Context, lnClient lnclient.LNClient) error
UnlinkAccount(ctx context.Context) error
RequestAutoChannel(ctx context.Context, lnClient lnclient.LNClient, isPublic bool) (*AutoChannelResponse, error)
GetVssAuthToken(ctx context.Context, nodeIdentifier string) (string, error)

View file

@ -1,69 +0,0 @@
import React from "react";
import { ButtonProps, LoadingButton } from "src/components/ui/loading-button";
import { useToast } from "src/components/ui/use-toast";
import { AlbyBalance, Channel } from "src/types";
import { request } from "src/utils/request";
type TransferFundsButtonProps = {
channels: Channel[] | undefined;
albyBalance: AlbyBalance;
onTransferComplete: () => Promise<unknown>;
} & ButtonProps;
export function TransferFundsButton({
channels,
albyBalance,
onTransferComplete,
children,
...props
}: TransferFundsButtonProps) {
const [loading, setLoading] = React.useState(false);
const { toast } = useToast();
return (
<LoadingButton
loading={loading}
onClick={async () => {
if (!albyBalance) {
return;
}
if (
!channels?.some(
(channel) => channel.remoteBalance / 1000 > albyBalance.sats
)
) {
toast({
title: "Please increase your receiving capacity first",
});
return;
}
setLoading(true);
try {
await request("/api/alby/drain", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
await onTransferComplete();
toast({
title:
"🎉 Funds from Alby shared wallet transferred to your Alby Hub!",
});
} catch (error) {
console.error(error);
toast({
variant: "destructive",
description: "Something went wrong: " + error,
});
} finally {
setLoading(false);
}
}}
{...props}
>
{children}
</LoadingButton>
);
}

View file

@ -10,6 +10,7 @@ import {
CardTitle,
} from "src/components/ui/card";
import { Progress } from "src/components/ui/progress.tsx";
import { Separator } from "src/components/ui/separator";
import {
Tooltip,
TooltipContent,
@ -32,8 +33,10 @@ export function ChannelsCards({ channels, nodes }: ChannelsCardsProps) {
return (
<>
<Card>
<CardHeader className="w-full pb-4">Channels</CardHeader>
<div className="flex flex-col gap-4 slashed-zero p-4">
<CardHeader className="w-full pb-2 text-2xl font-semibold">
Channels
</CardHeader>
<CardContent>
{channels
.sort((a, b) =>
a.localBalance + a.remoteBalance >
@ -41,7 +44,7 @@ export function ChannelsCards({ channels, nodes }: ChannelsCardsProps) {
? -1
: 1
)
.map((channel) => {
.map((channel, index) => {
const node = nodes?.find(
(n) => n.public_key === channel.remotePubkey
);
@ -50,16 +53,22 @@ export function ChannelsCards({ channels, nodes }: ChannelsCardsProps) {
return (
<>
{index > 0 && <Separator className="mt-6 -mb-2" />}
<div className="flex flex-col items-start w-full">
<CardTitle className="w-full">
<div className="flex items-center justify-between">
<div className="flex-1 whitespace-nowrap text-ellipsis font-semibold overflow-hidden">
{alias}
<CardHeader className="pb-4 px-0 w-full">
<CardTitle className="w-full">
<div className="flex items-center justify-between">
<div className="flex-1 whitespace-nowrap text-ellipsis font-semibold truncate leading-normal">
{alias}
</div>
<ChannelDropdownMenu
alias={alias}
channel={channel}
/>
</div>
<ChannelDropdownMenu alias={alias} channel={channel} />
</div>
</CardTitle>
<CardDescription className="w-full flex flex-col gap-4 mt-4">
</CardTitle>
</CardHeader>
<CardDescription className="w-full flex flex-col gap-4">
<div className="flex w-full justify-between items-center">
<p className="text-muted-foreground font-medium">
Status
@ -152,46 +161,45 @@ export function ChannelsCards({ channels, nodes }: ChannelsCardsProps) {
sats
</p>
</div>
<div className="flex justify-between items-center">
<p className="text-muted-foreground font-medium text-sm">
Spending
</p>
<p className="text-muted-foreground font-medium text-sm">
Receiving
</p>
</div>
<div className="flex gap-2 items-center">
<div className="flex-1 relative">
<Progress
value={
(channel.localSpendableBalance / capacity) * 100
}
className="h-6 absolute"
/>
<div className="flex flex-row w-full justify-between px-2 text-xs items-center h-6 mix-blend-exclusion text-white">
<span
title={
channel.localSpendableBalance / 1000 + " sats"
}
>
{formatAmount(channel.localSpendableBalance)} sats
</span>
<span
title={channel.remoteBalance / 1000 + " sats"}
>
{formatAmount(channel.remoteBalance)} sats
</span>
</div>
</div>
<ChannelWarning channel={channel} />
</div>
</CardDescription>
</div>
<CardContent className="p-0">
<div className="flex justify-between items-center">
<p className="text-muted-foreground font-medium text-sm">
Spending
</p>
<p className="text-muted-foreground font-medium text-sm">
Receiving
</p>
</div>
<div className="flex gap-2 items-center mt-2">
<div className="flex-1 relative">
<Progress
value={
(channel.localSpendableBalance / capacity) * 100
}
className="h-6 absolute"
/>
<div className="flex flex-row w-full justify-between px-2 text-xs items-center h-6 mix-blend-exclusion text-white">
<span
title={
channel.localSpendableBalance / 1000 + " sats"
}
>
{formatAmount(channel.localSpendableBalance)} sats
</span>
<span title={channel.remoteBalance / 1000 + " sats"}>
{formatAmount(channel.remoteBalance)} sats
</span>
</div>
</div>
<ChannelWarning channel={channel} />
</div>
</CardContent>
</>
);
})}
</div>
</CardContent>
</Card>
</>
);

View file

@ -40,7 +40,7 @@ export function ChannelsTable({ channels, nodes }: ChannelsTableProps) {
return (
<Card>
<CardHeader>
<CardTitle>Channels</CardTitle>
<CardTitle className="text-2xl">Channels</CardTitle>
</CardHeader>
<CardContent>
<Table>

View file

@ -1,7 +1,6 @@
// src/hooks/useOnboardingData.ts
import { SUPPORT_ALBY_CONNECTION_NAME } from "src/constants";
import { useAlbyBalance } from "src/hooks/useAlbyBalance";
import { useAlbyMe } from "src/hooks/useAlbyMe";
import { useApps } from "src/hooks/useApps";
import { useChannels } from "src/hooks/useChannels";
@ -23,7 +22,6 @@ interface UseOnboardingDataResponse {
}
export const useOnboardingData = (): UseOnboardingDataResponse => {
const { data: albyBalance } = useAlbyBalance();
const { data: albyMe } = useAlbyMe();
const { data: apps } = useApps();
const { data: channels } = useChannels();
@ -37,7 +35,7 @@ export const useOnboardingData = (): UseOnboardingDataResponse => {
!info ||
!nodeConnectionInfo ||
!transactions ||
(info.albyAccountConnected && (!albyMe || !albyBalance));
(info.albyAccountConnected && !albyMe);
if (isLoading) {
return { isLoading: true, checklistItems: [] };

View file

@ -5,7 +5,6 @@ import {
CopyIcon,
ExternalLinkIcon,
Heart,
Hotel,
HourglassIcon,
InfoIcon,
LinkIcon,
@ -21,7 +20,6 @@ import { ChannelsTable } from "src/components/channels/ChannelsTable.tsx";
import EmptyState from "src/components/EmptyState.tsx";
import ExternalLink from "src/components/ExternalLink";
import FormattedFiatAmount from "src/components/FormattedFiatAmount";
import { TransferFundsButton } from "src/components/TransferFundsButton";
import {
Alert,
AlertDescription,
@ -31,7 +29,6 @@ import { Button } from "src/components/ui/button.tsx";
import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
} from "src/components/ui/card.tsx";
@ -63,11 +60,7 @@ import {
TooltipTrigger,
} from "src/components/ui/tooltip.tsx";
import { useToast } from "src/components/ui/use-toast.ts";
import {
ALBY_HIDE_HOSTED_BALANCE_BELOW as ALBY_HIDE_HOSTED_BALANCE_LIMIT,
ONCHAIN_DUST_SATS,
} from "src/constants.ts";
import { useAlbyBalance } from "src/hooks/useAlbyBalance.ts";
import { ONCHAIN_DUST_SATS } from "src/constants.ts";
import { useBalances } from "src/hooks/useBalances.ts";
import { useChannels } from "src/hooks/useChannels";
import { useIsDesktop } from "src/hooks/useMediaQuery.ts";
@ -82,10 +75,9 @@ import { request } from "src/utils/request";
export default function Channels() {
useSyncWallet();
const { data: channels, mutate: reloadChannels } = useChannels();
const { data: channels } = useChannels();
const { data: nodeConnectionInfo } = useNodeConnectionInfo();
const { data: balances, mutate: reloadBalances } = useBalances();
const { data: albyBalance, mutate: reloadAlbyBalance } = useAlbyBalance();
const { data: balances } = useBalances();
const navigate = useNavigate();
const [nodes, setNodes] = React.useState<Node[]>([]);
const [swapInAmount, setSwapInAmount] = React.useState("");
@ -161,9 +153,6 @@ export default function Channels() {
}, channels[0]);
}
const showHostedBalance =
albyBalance && albyBalance.sats > ALBY_HIDE_HOSTED_BALANCE_LIMIT;
return (
<>
<AppHeader
@ -456,53 +445,20 @@ export default function Channels() {
<div
className={cn("flex flex-col sm:flex-row flex-wrap gap-3 slashed-zero")}
>
{showHostedBalance && (
<Card className="flex flex-col">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">
Alby Hosted Balance
</CardTitle>
<Hotel className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent className="flex-grow">
<div className="text-2xl font-bold">
{new Intl.NumberFormat().format(albyBalance.sats)} sats
</div>
<FormattedFiatAmount amount={albyBalance.sats} />
</CardContent>
<CardFooter className="flex justify-end space-x-1">
<TransferFundsButton
variant="outline"
channels={channels}
albyBalance={albyBalance}
onTransferComplete={() =>
Promise.all([
reloadAlbyBalance(),
reloadBalances(),
reloadChannels(),
])
}
>
Transfer
</TransferFundsButton>
</CardFooter>
</Card>
)}
<Card className="flex flex-1 sm:flex-[2] flex-col">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="font-semibold">Lightning</CardTitle>
<ZapIcon className="h-4 w-4 text-muted-foreground" />
<CardTitle className="font-semibold text-2xl">Lightning</CardTitle>
<ZapIcon className="h-6 w-6 text-muted-foreground" />
</CardHeader>
<CardContent className="flex flex-col sm:flex-row pl-0 flex-wrap">
<div className="flex flex-col flex-1">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2 pr-0">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-1 pr-0">
<CardTitle className="text-sm font-medium">
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<div className="flex flex-row gap-1 items-center justify-start text-sm text-secondary-foreground">
<div className="flex flex-row gap-1 items-center justify-start text-sm font-medium">
Spending Balance
<InfoIcon className="h-3 w-3 shrink-0 text-muted-foreground" />
</div>
@ -525,7 +481,7 @@ export default function Channels() {
)}
{balances && (
<>
<div className="text-2xl font-bold balance sensitive">
<div className="text-xl font-medium balance sensitive mb-1">
{new Intl.NumberFormat().format(
Math.floor(balances.lightning.totalSpendable / 1000)
)}{" "}
@ -539,12 +495,12 @@ export default function Channels() {
</CardContent>
</div>
<div className="flex flex-col flex-1">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2 pr-0">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-1 pr-0">
<CardTitle className="text-sm font-medium">
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<div className="flex flex-row gap-1 items-center justify-start text-sm text-secondary-foreground">
<div className="flex flex-row gap-1 items-center justify-start text-sm font-medium">
Receive Limit
<InfoIcon className="h-3 w-3 shrink-0 text-muted-foreground" />
</div>
@ -561,7 +517,7 @@ export default function Channels() {
<CardContent className="flex-grow pb-0">
{balances && (
<>
<div className="text-2xl font-bold balance sensitive">
<div className="text-xl font-medium balance sensitive mb-1">
{new Intl.NumberFormat().format(
Math.floor(balances.lightning.totalReceivable / 1000)
)}{" "}
@ -578,16 +534,16 @@ export default function Channels() {
</Card>
<Card className="flex flex-1 flex-col">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="font-semibold">On-Chain</CardTitle>
<LinkIcon className="h-4 w-4 text-muted-foreground" />
<CardTitle className="text-2xl font-semibold">On-Chain</CardTitle>
<LinkIcon className="h-6 w-6 text-muted-foreground" />
</CardHeader>
<CardContent className="flex-grow">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2 pl-0">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-1 pl-0">
<CardTitle className="text-sm font-medium">
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<div className="flex flex-row gap-1 items-center text-sm text-secondary-foreground">
<div className="flex flex-row gap-1 items-center text-sm font-medium">
Balance
<InfoIcon className="h-3 w-3 shrink-0 text-muted-foreground" />
</div>
@ -610,11 +566,11 @@ export default function Channels() {
</div>
</div>
)}
<div className="text-2xl balance sensitive">
<div>
{balances && (
<>
<div className="balance sensitive flex gap-2">
<span className="text-2xl font-bold">
<div className="mb-1">
<span className="text-xl font-medium balance sensitive mb-1 mr-1">
{new Intl.NumberFormat().format(
Math.floor(balances.onchain.spendable)
)}{" "}
@ -639,7 +595,10 @@ export default function Channels() {
</TooltipProvider>
)}
</div>
<FormattedFiatAmount amount={balances.onchain.spendable} />
<FormattedFiatAmount
amount={balances.onchain.spendable}
className="mb-1"
/>
{balances &&
balances.onchain.spendable !== balances.onchain.total && (
<p className="text-xs text-muted-foreground animate-pulse">

View file

@ -19,10 +19,7 @@ import { request } from "src/utils/request";
import { MempoolAlert } from "src/components/MempoolAlert";
import { PayLightningInvoice } from "src/components/PayLightningInvoice";
import {
ALBY_HIDE_HOSTED_BALANCE_BELOW,
ALBY_MIN_HOSTED_BALANCE_FOR_FIRST_CHANNEL,
} from "src/constants";
import { ALBY_MIN_HOSTED_BALANCE_FOR_FIRST_CHANNEL } from "src/constants";
export function FirstChannel() {
const { data: info } = useInfo();
@ -92,9 +89,6 @@ export function FirstChannel() {
albyBalance &&
albyBalance.sats >= ALBY_MIN_HOSTED_BALANCE_FOR_FIRST_CHANNEL;
const canMigrateFunds =
albyBalance && albyBalance.sats >= ALBY_HIDE_HOSTED_BALANCE_BELOW;
return (
<>
<AppHeader
@ -142,15 +136,22 @@ export function FirstChannel() {
{canPayForFirstChannel ? (
<>
<p>
Your Alby hosted balance currently holds{" "}
You currently have{" "}
<span className="font-medium text-foreground sensitive slashed-zero">
{new Intl.NumberFormat().format(albyBalance?.sats)} sats
</span>
.
{new Intl.NumberFormat().format(albyBalance?.sats)} Alby fee
credits.
</span>{" "}
<Link
to="https://guides.getalby.com/user-guide/alby-account-and-browser-extension/alby-account/faqs-alby-account/what-are-fee-credits-in-my-alby-account"
target="_blank"
className="underline"
>
Learn more
</Link>
</p>
<p>
Those funds will be used to open your first lightning channel
and then migrated to your Hub spending balance.
These fee credits will be applied to open your first Lightning
channel.
</p>
</>
) : (
@ -204,7 +205,6 @@ export function FirstChannel() {
)}
<LoadingButton loading={isLoading} onClick={openChannel}>
Open Channel
{canMigrateFunds && <> and Transfer Funds</>}
</LoadingButton>
</div>
</>

View file

@ -1,58 +1,9 @@
import React from "react";
import { Link } from "react-router-dom";
import ExternalLink from "src/components/ExternalLink";
import TwoColumnLayoutHeader from "src/components/TwoColumnLayoutHeader";
import { Button } from "src/components/ui/button";
import { useToast } from "src/components/ui/use-toast";
import { ALBY_HIDE_HOSTED_BALANCE_BELOW } from "src/constants";
import { useAlbyBalance } from "src/hooks/useAlbyBalance";
import { request } from "src/utils/request";
export function OpenedFirstChannel() {
const { data: albyBalance, mutate: reloadAlbyBalance } = useAlbyBalance();
const [hasTransferredFunds, setTransferredFunds] = React.useState(false);
const { toast } = useToast();
// automatically drain Alby balance into new channel if possible
// TODO: remove this code once all Alby users have migrated to Alby Hub
React.useEffect(() => {
(async () => {
if (!albyBalance || albyBalance.sats < ALBY_HIDE_HOSTED_BALANCE_BELOW) {
return;
}
if (hasTransferredFunds && albyBalance.sats > 100_000) {
// do not transfer all funds in one go in case the user still has a large number of sats
// left over - only transfer if the user has ~1% remaining.
// A maximum of 1M sats will be transferred in the first request.
return;
}
try {
await request("/api/alby/drain", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
await reloadAlbyBalance();
// This may run multiple times (to drain the final 1%), but we should only show a toast once
setTransferredFunds((current) => {
if (!current) {
toast({
description:
"🎉 Funds from Alby shared wallet transferred to your Alby Hub!",
});
}
return true;
});
} catch (error) {
console.error("Failed to transfer any alby shared wallet funds", error);
}
})();
}, [albyBalance, hasTransferredFunds, reloadAlbyBalance, toast]);
return (
<div className="flex flex-col justify-center gap-5 p-5 max-w-md items-stretch">
<TwoColumnLayoutHeader

View file

@ -1,7 +1,6 @@
import {
AlertTriangle,
ArrowDownIcon,
ArrowLeftRight,
ArrowUpIcon,
CreditCard,
} from "lucide-react";
@ -12,79 +11,34 @@ import ExternalLink from "src/components/ExternalLink";
import FormattedFiatAmount from "src/components/FormattedFiatAmount";
import Loading from "src/components/Loading";
import TransactionsList from "src/components/TransactionsList";
import { TransferFundsButton } from "src/components/TransferFundsButton";
import {
Alert,
AlertDescription,
AlertTitle,
} from "src/components/ui/alert.tsx";
import { Button, LinkButton } from "src/components/ui/button";
import { ALBY_HIDE_HOSTED_BALANCE_BELOW as ALBY_HIDE_HOSTED_BALANCE_LIMIT } from "src/constants.ts";
import { useAlbyBalance } from "src/hooks/useAlbyBalance";
import { Button } from "src/components/ui/button";
import { useBalances } from "src/hooks/useBalances";
import { useChannels } from "src/hooks/useChannels";
import { useInfo } from "src/hooks/useInfo";
import { useTransactions } from "src/hooks/useTransactions";
function Wallet() {
const { data: info, hasChannelManagement } = useInfo();
const { data: balances, mutate: reloadBalances } = useBalances();
const { data: balances } = useBalances();
const { data: channels } = useChannels();
const { data: albyBalance, mutate: reloadAlbyBalance } = useAlbyBalance();
const { mutate: reloadTransactions } = useTransactions();
if (!info || !balances) {
return <Loading />;
}
const showMigrateCard =
albyBalance && albyBalance.sats > ALBY_HIDE_HOSTED_BALANCE_LIMIT;
const needsChannels = hasChannelManagement && channels && channels.length < 1;
return (
<>
<AppHeader title="Wallet" description="" />
{showMigrateCard && (
<div className="flex flex-1 items-center justify-center rounded-lg border border-dashed shadow-sm p-8">
<div className="flex flex-col items-center gap-1 text-center max-w-md">
<ArrowLeftRight className="w-10 h-10 text-primary-background" />
<h3 className="mt-4 text-lg font-semibold">
You still have{" "}
<span className="font-bold slashed-zero sensitive">
{new Intl.NumberFormat().format(albyBalance.sats)}
</span>{" "}
sats in your Alby shared wallet
</h3>
<p className="text-sm text-muted-foreground mb-4">
Transfer funds from your Alby hosted balance.
</p>
{needsChannels ? (
<LinkButton to="/channels/first">Transfer Funds</LinkButton>
) : (
<TransferFundsButton
channels={channels}
albyBalance={albyBalance}
onTransferComplete={() =>
Promise.all([
reloadAlbyBalance(),
reloadBalances(),
reloadTransactions(),
])
}
>
Transfer Funds
</TransferFundsButton>
)}
</div>
</div>
)}
{hasChannelManagement &&
!!channels?.length &&
channels?.every(
(channel) =>
channel.localBalance < channel.unspendablePunishmentReserve * 1000
) &&
!showMigrateCard && (
) && (
<Alert>
<AlertTriangle className="h-4 w-4" />
<AlertTitle>Channel Reserves Unmet</AlertTitle>
@ -99,8 +53,7 @@ function Wallet() {
)}
{hasChannelManagement &&
!!channels?.length &&
!balances.lightning.totalReceivable &&
!showMigrateCard && (
!balances.lightning.totalReceivable && (
<Alert>
<AlertTriangle className="h-4 w-4" />
<AlertTitle>Low receiving capacity</AlertTitle>
@ -112,7 +65,7 @@ function Wallet() {
</AlertDescription>
</Alert>
)}
{hasChannelManagement && !channels?.length && !showMigrateCard && (
{hasChannelManagement && !channels?.length && (
<Alert>
<AlertTriangle className="h-4 w-4" />
<AlertTitle>Open Your First Channel</AlertTitle>

View file

@ -33,7 +33,6 @@ func (albyHttpSvc *AlbyHttpService) RegisterSharedRoutes(restrictedApiGroup *ech
restrictedApiGroup.GET("/alby/me", albyHttpSvc.albyMeHandler)
restrictedApiGroup.GET("/alby/balance", albyHttpSvc.albyBalanceHandler)
restrictedApiGroup.POST("/alby/pay", albyHttpSvc.albyPayHandler)
restrictedApiGroup.POST("/alby/drain", albyHttpSvc.albyDrainHandler)
restrictedApiGroup.POST("/alby/link-account", albyHttpSvc.albyLinkAccountHandler)
restrictedApiGroup.POST("/alby/auto-channel", albyHttpSvc.autoChannelHandler)
restrictedApiGroup.POST("/alby/unlink-account", albyHttpSvc.unlinkHandler)
@ -172,20 +171,6 @@ func (albyHttpSvc *AlbyHttpService) albyPayHandler(c echo.Context) error {
return c.NoContent(http.StatusNoContent)
}
func (albyHttpSvc *AlbyHttpService) albyDrainHandler(c echo.Context) error {
err := albyHttpSvc.albyOAuthSvc.DrainSharedWallet(c.Request().Context(), albyHttpSvc.svc.GetLNClient())
if err != nil {
logger.Logger.WithError(err).Error("Failed to drain shared wallet")
return c.JSON(http.StatusInternalServerError, ErrorResponse{
Message: fmt.Sprintf("Failed to drain shared wallet: %s", err.Error()),
})
}
return c.NoContent(http.StatusNoContent)
}
func (albyHttpSvc *AlbyHttpService) albyLinkAccountHandler(c echo.Context) error {
var linkAccountRequest alby.AlbyLinkAccountRequest
if err := c.Bind(&linkAccountRequest); err != nil {

View file

@ -341,12 +341,6 @@ func (app *WailsApp) WailsRequestRouter(route string, method string, body string
return WailsRequestRouterResponse{Body: &alby.AlbyBalanceResponse{
Sats: balance.Balance,
}, Error: ""}
case "/api/alby/drain":
err := app.svc.GetAlbyOAuthSvc().DrainSharedWallet(ctx, app.svc.GetLNClient())
if err != nil {
return WailsRequestRouterResponse{Body: nil, Error: err.Error()}
}
return WailsRequestRouterResponse{Body: nil, Error: ""}
case "/api/alby/unlink-account":
err := app.svc.GetAlbyOAuthSvc().UnlinkAccount(ctx)
if err != nil {