mirror of
https://github.com/apotdevin/thunderhub.git
synced 2025-02-21 14:04:03 +01:00
chore: 🔧 more bar types in channel view
This commit is contained in:
parent
bb90fbfe50
commit
9c657a416a
10 changed files with 165 additions and 63 deletions
|
@ -1,12 +1,13 @@
|
|||
import React, { useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { ChevronRight, X } from 'react-feather';
|
||||
import { ChevronRight, ChevronUp, ChevronDown } from 'react-feather';
|
||||
import { useAccountState } from 'src/context/AccountContext';
|
||||
import { useChannelFeesQuery } from 'src/graphql/queries/__generated__/getChannelFees.generated';
|
||||
import { useUpdateFeesMutation } from 'src/graphql/mutations/__generated__/updateFees.generated';
|
||||
import { InputWithDeco } from 'src/components/input/InputWithDeco';
|
||||
import { GridWrapper } from 'src/components/gridWrapper/GridWrapper';
|
||||
import { withApollo } from 'config/client';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
Card,
|
||||
CardWithTitle,
|
||||
|
@ -21,7 +22,10 @@ import { LoadingCard } from '../src/components/loading/LoadingCard';
|
|||
import { FeeCard } from '../src/views/fees/FeeCard';
|
||||
import { SecureButton } from '../src/components/buttons/secureButton/SecureButton';
|
||||
import { AdminSwitch } from '../src/components/adminSwitch/AdminSwitch';
|
||||
import { ColorButton } from '../src/components/buttons/colorButton/ColorButton';
|
||||
|
||||
const WithPointer = styled.div`
|
||||
cursor: pointer;
|
||||
`;
|
||||
|
||||
const FeesView = () => {
|
||||
const [indexOpen, setIndexOpen] = useState(0);
|
||||
|
@ -58,26 +62,28 @@ const FeesView = () => {
|
|||
<CardWithTitle>
|
||||
<SubTitle>Update Channel Fees</SubTitle>
|
||||
<Card>
|
||||
<SingleLine>
|
||||
<Sub4Title>Channel Fees</Sub4Title>
|
||||
<ColorButton onClick={() => setIsEdit(prev => !prev)}>
|
||||
{isEdit ? <X size={18} /> : 'Update'}
|
||||
</ColorButton>
|
||||
</SingleLine>
|
||||
<WithPointer>
|
||||
<SingleLine onClick={() => setIsEdit(prev => !prev)}>
|
||||
<Sub4Title>Channel Fees</Sub4Title>
|
||||
{isEdit ? <ChevronUp /> : <ChevronDown />}
|
||||
</SingleLine>
|
||||
</WithPointer>
|
||||
{isEdit && (
|
||||
<>
|
||||
<Separation />
|
||||
<InputWithDeco
|
||||
title={'BaseFee'}
|
||||
placeholder={'Sats'}
|
||||
placeholder={'sats'}
|
||||
amount={baseFee}
|
||||
override={'sat'}
|
||||
inputType={'number'}
|
||||
inputCallback={value => setBaseFee(Number(value))}
|
||||
/>
|
||||
<InputWithDeco
|
||||
title={'Fee Rate'}
|
||||
placeholder={'MilliSats/Million'}
|
||||
placeholder={'msats/million'}
|
||||
amount={feeRate / 1000}
|
||||
override={'sat'}
|
||||
inputType={'number'}
|
||||
inputCallback={value => setFeeRate(Number(value))}
|
||||
/>
|
||||
|
|
|
@ -29,6 +29,10 @@ export const ProgressBar = styled.div<ProgressBar>`
|
|||
return chartColors.orange;
|
||||
case 4:
|
||||
return progressBackground;
|
||||
case 5:
|
||||
return chartColors.orange2;
|
||||
case 6:
|
||||
return chartColors.darkyellow;
|
||||
default:
|
||||
return chartColors.purple;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ type InputWithDecoProps = {
|
|||
title: string;
|
||||
noInput?: boolean;
|
||||
amount?: number;
|
||||
override?: string;
|
||||
customAmount?: string;
|
||||
color?: string;
|
||||
placeholder?: string;
|
||||
|
@ -49,6 +50,7 @@ type InputWithDecoProps = {
|
|||
export const InputWithDeco: React.FC<InputWithDecoProps> = ({
|
||||
title,
|
||||
amount,
|
||||
override,
|
||||
customAmount,
|
||||
children,
|
||||
placeholder,
|
||||
|
@ -65,7 +67,11 @@ export const InputWithDeco: React.FC<InputWithDecoProps> = ({
|
|||
<InputTitle>{title}</InputTitle>
|
||||
{showAmount && (
|
||||
<AmountText>
|
||||
{customAmount ? customAmount : <Price amount={amount} />}
|
||||
{customAmount ? (
|
||||
customAmount
|
||||
) : (
|
||||
<Price amount={amount} override={override} />
|
||||
)}
|
||||
</AmountText>
|
||||
)}
|
||||
</InputTitleRow>
|
||||
|
|
|
@ -12,10 +12,12 @@ type PriceProps = {
|
|||
export const Price = ({
|
||||
amount,
|
||||
breakNumber = false,
|
||||
override,
|
||||
}: {
|
||||
amount: number | string;
|
||||
breakNumber?: boolean;
|
||||
}) => {
|
||||
override?: string;
|
||||
}): JSX.Element => {
|
||||
const { currency, displayValues } = useConfigState();
|
||||
const { prices, dontShow } = usePriceState();
|
||||
|
||||
|
@ -42,12 +44,13 @@ export const Price = ({
|
|||
};
|
||||
}
|
||||
|
||||
return <>{getValue({ amount, ...priceProps, breakNumber })}</>;
|
||||
return <>{getValue({ amount, ...priceProps, breakNumber, override })}</>;
|
||||
};
|
||||
|
||||
interface GetPriceProps {
|
||||
amount: number | string;
|
||||
breakNumber?: boolean;
|
||||
override?: string;
|
||||
}
|
||||
|
||||
export const getPrice = (
|
||||
|
@ -57,7 +60,7 @@ export const getPrice = (
|
|||
dontShow: boolean;
|
||||
prices?: { [key: string]: { last: number; symbol: string } };
|
||||
}
|
||||
) => ({ amount, breakNumber = false }: GetPriceProps): string => {
|
||||
) => ({ amount, breakNumber = false, override }: GetPriceProps): string => {
|
||||
const { prices, dontShow } = priceContext;
|
||||
|
||||
if (!displayValues) {
|
||||
|
@ -83,5 +86,5 @@ export const getPrice = (
|
|||
};
|
||||
}
|
||||
|
||||
return getValue({ amount, ...priceProps, breakNumber });
|
||||
return getValue({ amount, ...priceProps, breakNumber, override });
|
||||
};
|
||||
|
|
|
@ -6,8 +6,8 @@ const themeTypes = ['dark', 'light'];
|
|||
const currencyTypes = ['sat', 'btc', 'EUR', 'USD'];
|
||||
|
||||
export type channelBarStyleTypes = 'normal' | 'compact' | 'ultracompact';
|
||||
export type channelBarTypeTypes = 'balance' | 'details' | 'partner';
|
||||
export type channelSortTypes = 'none' | 'local' | 'balance';
|
||||
export type channelBarTypeTypes = 'balance' | 'fees' | 'size' | 'proportional';
|
||||
export type channelSortTypes = 'none' | 'local' | 'balance' | 'feeRate';
|
||||
export type sortDirectionTypes = 'increase' | 'decrease';
|
||||
|
||||
type State = {
|
||||
|
|
|
@ -16,6 +16,7 @@ interface GetNumberProps {
|
|||
symbol: string;
|
||||
currency: string;
|
||||
breakNumber?: boolean;
|
||||
override?: string;
|
||||
}
|
||||
|
||||
export const getValue = ({
|
||||
|
@ -24,7 +25,9 @@ export const getValue = ({
|
|||
symbol,
|
||||
currency,
|
||||
breakNumber,
|
||||
override,
|
||||
}: GetNumberProps): string => {
|
||||
const correctCurrency = override || currency;
|
||||
let value = 0;
|
||||
if (typeof amount === 'string') {
|
||||
value = Number(amount);
|
||||
|
@ -32,14 +35,14 @@ export const getValue = ({
|
|||
value = amount;
|
||||
}
|
||||
|
||||
if (currency === 'btc') {
|
||||
if (correctCurrency === 'btc') {
|
||||
if (!value) return 'â‚¿0.0';
|
||||
const amountInBtc = value / 100000000;
|
||||
const rounded = Math.round(amountInBtc * 10000) / 10000;
|
||||
|
||||
return `â‚¿${rounded}`;
|
||||
}
|
||||
if (currency === 'sat') {
|
||||
if (correctCurrency === 'sat') {
|
||||
const breakAmount = breakNumber
|
||||
? getValueString(value)
|
||||
: numeral(value).format('0,0.[000]');
|
||||
|
|
|
@ -66,7 +66,7 @@ interface ChannelCardProps {
|
|||
biggestRateFee: number;
|
||||
}
|
||||
|
||||
export const ChannelCard = ({
|
||||
export const ChannelCard: React.FC<ChannelCardProps> = ({
|
||||
channelInfo,
|
||||
index,
|
||||
setIndexOpen,
|
||||
|
@ -76,7 +76,7 @@ export const ChannelCard = ({
|
|||
mostChannels,
|
||||
biggestBaseFee,
|
||||
biggestRateFee,
|
||||
}: ChannelCardProps) => {
|
||||
}) => {
|
||||
const { channelBarType, channelBarStyle } = useConfigState();
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
|
||||
|
@ -133,6 +133,9 @@ export const ChannelCard = ({
|
|||
const remoteReserve = format({ amount: remote_reserve });
|
||||
const nodeCapacity = format({ amount: partnerNodeCapacity });
|
||||
|
||||
const baseFee = format({ amount: base_fee / 1000, override: 'sat' });
|
||||
const feeRate = format({ amount: fee_rate, override: 'sat' });
|
||||
|
||||
const handleClick = () => {
|
||||
if (indexOpen === index) {
|
||||
setIndexOpen(0);
|
||||
|
@ -150,8 +153,8 @@ export const ChannelCard = ({
|
|||
'Last Update:',
|
||||
`${getDateDif(updated_at)} ago (${getFormatDate(updated_at)})`
|
||||
)}
|
||||
{renderLine('Base Fee:', `${base_fee} msats`)}
|
||||
{renderLine('Fee Rate:', `${fee_rate} sats/Msats`)}
|
||||
{renderLine('Base Fee:', baseFee)}
|
||||
{renderLine('Fee Rate:', `${feeRate}/million`)}
|
||||
{renderLine('CTLV Delta:', cltv_delta)}
|
||||
</>
|
||||
) : (
|
||||
|
@ -205,28 +208,79 @@ export const ChannelCard = ({
|
|||
|
||||
const renderBars = () => {
|
||||
switch (channelBarType) {
|
||||
case 'partner':
|
||||
case 'fees':
|
||||
return (
|
||||
<ChannelStatsColumn>
|
||||
<ProgressBar
|
||||
order={0}
|
||||
percent={getBar(Number(partnerNodeCapacity), biggestPartner)}
|
||||
/>
|
||||
<ProgressBar
|
||||
order={3}
|
||||
percent={getBar(channel_count, mostChannels)}
|
||||
/>
|
||||
<ProgressBar order={1} percent={getBar(base_fee, biggestBaseFee)} />
|
||||
<ProgressBar order={2} percent={getBar(fee_rate, biggestRateFee)} />
|
||||
<ChannelStatsLine>
|
||||
<ProgressBar
|
||||
order={3}
|
||||
percent={getBar(fee_rate, biggestRateFee)}
|
||||
/>
|
||||
<ProgressBar
|
||||
order={4}
|
||||
percent={getBar(biggestRateFee - fee_rate, biggestRateFee)}
|
||||
/>
|
||||
</ChannelStatsLine>
|
||||
<ChannelStatsLine>
|
||||
<ProgressBar
|
||||
order={1}
|
||||
percent={getBar(base_fee, biggestBaseFee)}
|
||||
/>
|
||||
<ProgressBar
|
||||
order={4}
|
||||
percent={getBar(biggestBaseFee - base_fee, biggestBaseFee)}
|
||||
/>
|
||||
</ChannelStatsLine>
|
||||
</ChannelStatsColumn>
|
||||
);
|
||||
case 'details':
|
||||
case 'size':
|
||||
return (
|
||||
<ChannelStatsColumn>
|
||||
<ProgressBar order={0} percent={getBar(local_balance, biggest)} />
|
||||
<ProgressBar order={1} percent={getBar(remote_balance, biggest)} />
|
||||
<ProgressBar order={2} percent={getBar(received, biggest)} />
|
||||
<ProgressBar order={3} percent={getBar(sent, biggest)} />
|
||||
<ChannelStatsLine>
|
||||
<ProgressBar
|
||||
order={0}
|
||||
percent={getBar(Number(partnerNodeCapacity), biggestPartner)}
|
||||
/>
|
||||
<ProgressBar
|
||||
order={4}
|
||||
percent={getBar(
|
||||
biggestPartner - Number(partnerNodeCapacity),
|
||||
biggestPartner
|
||||
)}
|
||||
/>
|
||||
</ChannelStatsLine>
|
||||
<ChannelStatsLine>
|
||||
<ProgressBar
|
||||
order={6}
|
||||
percent={getBar(channel_count, mostChannels)}
|
||||
/>
|
||||
<ProgressBar
|
||||
order={4}
|
||||
percent={getBar(mostChannels - channel_count, mostChannels)}
|
||||
/>
|
||||
</ChannelStatsLine>
|
||||
</ChannelStatsColumn>
|
||||
);
|
||||
case 'proportional':
|
||||
return (
|
||||
<ChannelStatsColumn>
|
||||
<ChannelStatsLine>
|
||||
<ProgressBar order={1} percent={getBar(local_balance, biggest)} />
|
||||
<ProgressBar
|
||||
order={4}
|
||||
percent={getBar(biggest - local_balance, biggest)}
|
||||
/>
|
||||
</ChannelStatsLine>
|
||||
<ChannelStatsLine>
|
||||
<ProgressBar
|
||||
order={2}
|
||||
percent={getBar(remote_balance, biggest)}
|
||||
/>
|
||||
<ProgressBar
|
||||
order={4}
|
||||
percent={getBar(biggest - remote_balance, biggest)}
|
||||
/>
|
||||
</ChannelStatsLine>
|
||||
</ChannelStatsColumn>
|
||||
);
|
||||
default:
|
||||
|
@ -253,16 +307,27 @@ export const ChannelCard = ({
|
|||
|
||||
const renderBarsInfo = () => {
|
||||
switch (channelBarType) {
|
||||
case 'partner':
|
||||
case 'fees':
|
||||
return (
|
||||
<>
|
||||
<div>{`Partner Fee Rate: ${feeRate}/million`}</div>
|
||||
<div>{`Partner Base Fee: ${baseFee}`}</div>
|
||||
</>
|
||||
);
|
||||
case 'size':
|
||||
return (
|
||||
<>
|
||||
<div>{`Partner Capacity: ${nodeCapacity}`}</div>
|
||||
<div>{`Partner Channels: ${channel_count}`}</div>
|
||||
<div>{`Partner Base Fee: ${base_fee} msats`}</div>
|
||||
<div>{`Partner Fee Rate: ${fee_rate} sats/Msats`}</div>
|
||||
</>
|
||||
);
|
||||
case 'details':
|
||||
case 'proportional':
|
||||
return (
|
||||
<>
|
||||
<div>{`Local Balance: ${formatLocal}`}</div>
|
||||
<div>{`Remote Balance: ${formatRemote}`}</div>
|
||||
</>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<>
|
||||
|
|
|
@ -71,16 +71,22 @@ export const ChannelManage = () => {
|
|||
Balance
|
||||
</SingleButton>
|
||||
<SingleButton
|
||||
selected={channelBarType === 'details'}
|
||||
onClick={() => changeType('details')}
|
||||
selected={channelBarType === 'proportional'}
|
||||
onClick={() => changeType('proportional')}
|
||||
>
|
||||
Proportional
|
||||
</SingleButton>
|
||||
<SingleButton
|
||||
selected={channelBarType === 'partner'}
|
||||
onClick={() => changeType('partner')}
|
||||
selected={channelBarType === 'size'}
|
||||
onClick={() => changeType('size')}
|
||||
>
|
||||
Partner
|
||||
Partner Size
|
||||
</SingleButton>
|
||||
<SingleButton
|
||||
selected={channelBarType === 'fees'}
|
||||
onClick={() => changeType('fees')}
|
||||
>
|
||||
Partner Fees
|
||||
</SingleButton>
|
||||
</MultiButton>
|
||||
</MarginLine>
|
||||
|
@ -105,6 +111,12 @@ export const ChannelManage = () => {
|
|||
>
|
||||
Balance
|
||||
</SingleButton>
|
||||
<SingleButton
|
||||
selected={channelSort === 'feeRate'}
|
||||
onClick={() => changeSort('feeRate')}
|
||||
>
|
||||
Fee Rate
|
||||
</SingleButton>
|
||||
</MultiButton>
|
||||
</MarginLine>
|
||||
{channelSort !== 'none' && (
|
||||
|
|
|
@ -10,7 +10,7 @@ import { getErrorContent } from '../../../utils/error';
|
|||
import { LoadingCard } from '../../../components/loading/LoadingCard';
|
||||
import { ChannelCard } from './ChannelCard';
|
||||
|
||||
export const Channels = () => {
|
||||
export const Channels: React.FC = () => {
|
||||
const { sortDirection, channelSort } = useConfigState();
|
||||
const [indexOpen, setIndexOpen] = useState(0);
|
||||
|
||||
|
@ -35,19 +35,13 @@ export const Channels = () => {
|
|||
|
||||
for (let i = 0; i < data.getChannels.length; i++) {
|
||||
const channel = data.getChannels[i];
|
||||
const {
|
||||
local_balance,
|
||||
remote_balance,
|
||||
sent,
|
||||
received,
|
||||
partner_node_info = {},
|
||||
} = channel;
|
||||
const { local_balance, remote_balance, partner_node_info = {} } = channel;
|
||||
|
||||
const { capacity, channel_count, base_fee, fee_rate } = partner_node_info;
|
||||
const partner = Number(capacity) || 0;
|
||||
const channels = Number(channel_count) || 0;
|
||||
|
||||
const max = Math.max(local_balance, remote_balance, sent, received);
|
||||
const max = Math.max(local_balance, remote_balance);
|
||||
|
||||
if (max > biggest) {
|
||||
biggest = max;
|
||||
|
@ -78,6 +72,13 @@ export const Channels = () => {
|
|||
);
|
||||
return sortDirection === 'increase' ? newArray : newArray.reverse();
|
||||
}
|
||||
case 'feeRate': {
|
||||
const newArray = sortBy(
|
||||
data.getChannels,
|
||||
channel => channel.partner_node_info.fee_rate
|
||||
);
|
||||
return sortDirection === 'increase' ? newArray : newArray.reverse();
|
||||
}
|
||||
default:
|
||||
return data.getChannels;
|
||||
}
|
||||
|
@ -95,8 +96,8 @@ export const Channels = () => {
|
|||
biggest={biggest}
|
||||
biggestPartner={biggestPartner}
|
||||
mostChannels={mostChannels}
|
||||
biggestBaseFee={biggestBaseFee}
|
||||
biggestRateFee={biggestRateFee}
|
||||
biggestBaseFee={Math.max(biggestBaseFee, 100000)}
|
||||
biggestRateFee={Math.max(biggestRateFee, 2000)}
|
||||
/>
|
||||
))}
|
||||
</Card>
|
||||
|
|
|
@ -28,12 +28,12 @@ interface FeeCardProps {
|
|||
indexOpen: number;
|
||||
}
|
||||
|
||||
export const FeeCard = ({
|
||||
export const FeeCard: React.FC<FeeCardProps> = ({
|
||||
channelInfo,
|
||||
index,
|
||||
setIndexOpen,
|
||||
indexOpen,
|
||||
}: FeeCardProps) => {
|
||||
}) => {
|
||||
const [newBaseFee, setBaseFee] = useState(0);
|
||||
const [newFeeRate, setFeeRate] = useState(0);
|
||||
|
||||
|
@ -78,15 +78,17 @@ export const FeeCard = ({
|
|||
<AdminSwitch>
|
||||
<InputWithDeco
|
||||
title={'BaseFee'}
|
||||
placeholder={'Sats'}
|
||||
placeholder={'sats'}
|
||||
amount={newBaseFee}
|
||||
override={'sat'}
|
||||
inputType={'number'}
|
||||
inputCallback={value => setBaseFee(Number(value))}
|
||||
/>
|
||||
<InputWithDeco
|
||||
title={'Fee Rate'}
|
||||
placeholder={'MilliSats/Million'}
|
||||
placeholder={'msats/million'}
|
||||
amount={newFeeRate / 1000}
|
||||
override={'sat'}
|
||||
inputType={'number'}
|
||||
inputCallback={value => setFeeRate(Number(value))}
|
||||
/>
|
||||
|
|
Loading…
Add table
Reference in a new issue