mirror of
https://github.com/apotdevin/thunderhub.git
synced 2024-11-19 01:40:03 +01:00
chore: account balances changes (#344)
This commit is contained in:
parent
02e2a14d0c
commit
b74ad8ab6d
@ -5,6 +5,7 @@ import { NextPageContext } from 'next';
|
||||
import { getProps } from 'src/utils/ssr';
|
||||
import { MempoolReport } from 'src/views/home/reports/mempool';
|
||||
import { LiquidityGraph } from 'src/views/home/reports/liquidReport/LiquidityGraph';
|
||||
import { AccountButtons } from 'src/views/home/account/AccountButtons';
|
||||
import { NetworkInfo } from '../src/views/home/networkInfo/NetworkInfo';
|
||||
import { AccountInfo } from '../src/views/home/account/AccountInfo';
|
||||
import { QuickActions } from '../src/views/home/quickActions/QuickActions';
|
||||
@ -16,6 +17,7 @@ const HomeView = () => (
|
||||
<>
|
||||
<Version />
|
||||
<AccountInfo />
|
||||
<AccountButtons />
|
||||
<ConnectCard />
|
||||
<QuickActions />
|
||||
<FlowBox />
|
||||
|
@ -128,6 +128,7 @@ export const channelTypes = gql`
|
||||
is_active: Boolean!
|
||||
is_closing: Boolean!
|
||||
is_opening: Boolean!
|
||||
is_timelocked: Boolean!
|
||||
local_balance: Int!
|
||||
local_reserve: Int!
|
||||
partner_public_key: String!
|
||||
@ -139,5 +140,7 @@ export const channelTypes = gql`
|
||||
transaction_id: String!
|
||||
transaction_vout: Int!
|
||||
partner_node_info: Node!
|
||||
timelock_blocks: Int
|
||||
timelock_expiration: Int
|
||||
}
|
||||
`;
|
||||
|
@ -150,7 +150,7 @@ export const nodeResolvers = {
|
||||
|
||||
const closing =
|
||||
pending_channels
|
||||
.filter(p => p.is_closing)
|
||||
.filter(p => p.is_timelocked)
|
||||
.reduce((p, c) => p + c.local_balance, 0) || 0;
|
||||
|
||||
return closing || 0;
|
||||
|
@ -546,6 +546,7 @@ export const getPendingChannelsResponse = {
|
||||
is_active: true,
|
||||
is_closing: true,
|
||||
is_opening: true,
|
||||
is_timelocked: true,
|
||||
is_partner_initiated: true,
|
||||
local_balance: 1000,
|
||||
local_reserve: 1000,
|
||||
@ -576,6 +577,7 @@ export const getPendingChannelsResponse = {
|
||||
is_active: true,
|
||||
is_closing: true,
|
||||
is_opening: true,
|
||||
is_timelocked: true,
|
||||
is_partner_initiated: true,
|
||||
local_balance: 1000,
|
||||
local_reserve: 1000,
|
||||
@ -606,6 +608,7 @@ export const getPendingChannelsResponse = {
|
||||
is_active: true,
|
||||
is_closing: true,
|
||||
is_opening: true,
|
||||
is_timelocked: true,
|
||||
is_partner_initiated: true,
|
||||
local_balance: 1000,
|
||||
local_reserve: 1000,
|
||||
|
@ -157,6 +157,7 @@ export type PendingChannelType = {
|
||||
is_active: boolean;
|
||||
is_closing: boolean;
|
||||
is_opening: boolean;
|
||||
is_timelocked: boolean;
|
||||
local_balance: number;
|
||||
local_reserve: number;
|
||||
partner_public_key: string;
|
||||
@ -167,6 +168,8 @@ export type PendingChannelType = {
|
||||
transaction_fee: number;
|
||||
transaction_id: string;
|
||||
transaction_vout: number;
|
||||
timelock_blocks?: number;
|
||||
timelock_expiration?: number;
|
||||
};
|
||||
|
||||
export type GetPendingChannelsType = { pending_channels: PendingChannelType[] };
|
||||
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||
import styled, { css } from 'styled-components';
|
||||
import { ChevronRight } from 'react-feather';
|
||||
import ScaleLoader from 'react-spinners/ScaleLoader';
|
||||
import { ThemeSet } from 'styled-theming';
|
||||
import {
|
||||
textColor,
|
||||
colorButtonBackground,
|
||||
@ -72,11 +73,13 @@ interface BorderProps {
|
||||
borderColor?: string;
|
||||
selected?: boolean;
|
||||
withBorder?: boolean;
|
||||
backgroundColor?: string | ThemeSet;
|
||||
}
|
||||
|
||||
const BorderButton = styled(GeneralButton)<BorderProps>`
|
||||
${({ selected }) => selected && 'font-weight: 800'};
|
||||
background-color: ${colorButtonBackground};
|
||||
background-color: ${({ backgroundColor }) =>
|
||||
backgroundColor || colorButtonBackground};
|
||||
color: ${textColor};
|
||||
border: 1px solid
|
||||
${({ borderColor, selected, withBorder }) =>
|
||||
@ -127,6 +130,7 @@ export interface ColorButtonProps {
|
||||
fullWidth?: boolean;
|
||||
mobileFullWidth?: boolean;
|
||||
width?: string;
|
||||
backgroundColor?: string | ThemeSet;
|
||||
}
|
||||
|
||||
export const ColorButton: React.FC<ColorButtonProps> = ({
|
||||
@ -143,6 +147,7 @@ export const ColorButton: React.FC<ColorButtonProps> = ({
|
||||
mobileFullWidth,
|
||||
width,
|
||||
onClick,
|
||||
backgroundColor,
|
||||
}) => {
|
||||
if (disabled && !loading) {
|
||||
return (
|
||||
@ -184,6 +189,7 @@ export const ColorButton: React.FC<ColorButtonProps> = ({
|
||||
fullWidth={fullWidth}
|
||||
mobileFullWidth={mobileFullWidth}
|
||||
buttonWidth={width}
|
||||
backgroundColor={backgroundColor}
|
||||
>
|
||||
{children}
|
||||
{arrow && renderArrow()}
|
||||
|
@ -7,7 +7,7 @@ const defaultOptions = {}
|
||||
export type GetPendingChannelsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type GetPendingChannelsQuery = { __typename?: 'Query', getPendingChannels?: Types.Maybe<Array<Types.Maybe<{ __typename?: 'pendingChannelType', close_transaction_id?: Types.Maybe<string>, is_active: boolean, is_closing: boolean, is_opening: boolean, local_balance: number, local_reserve: number, partner_public_key: string, received: number, remote_balance: number, remote_reserve: number, sent: number, transaction_fee?: Types.Maybe<number>, transaction_id: string, transaction_vout: number, partner_node_info: { __typename?: 'Node', node: { __typename?: 'nodeType', alias: string, capacity?: Types.Maybe<string>, channel_count?: Types.Maybe<number>, color?: Types.Maybe<string>, updated_at?: Types.Maybe<string> } } }>>> };
|
||||
export type GetPendingChannelsQuery = { __typename?: 'Query', getPendingChannels?: Types.Maybe<Array<Types.Maybe<{ __typename?: 'pendingChannelType', close_transaction_id?: Types.Maybe<string>, is_active: boolean, is_closing: boolean, is_opening: boolean, is_timelocked: boolean, local_balance: number, local_reserve: number, timelock_blocks?: Types.Maybe<number>, timelock_expiration?: Types.Maybe<number>, partner_public_key: string, received: number, remote_balance: number, remote_reserve: number, sent: number, transaction_fee?: Types.Maybe<number>, transaction_id: string, transaction_vout: number, partner_node_info: { __typename?: 'Node', node: { __typename?: 'nodeType', alias: string, capacity?: Types.Maybe<string>, channel_count?: Types.Maybe<number>, color?: Types.Maybe<string>, updated_at?: Types.Maybe<string> } } }>>> };
|
||||
|
||||
|
||||
export const GetPendingChannelsDocument = gql`
|
||||
@ -17,8 +17,11 @@ export const GetPendingChannelsDocument = gql`
|
||||
is_active
|
||||
is_closing
|
||||
is_opening
|
||||
is_timelocked
|
||||
local_balance
|
||||
local_reserve
|
||||
timelock_blocks
|
||||
timelock_expiration
|
||||
partner_public_key
|
||||
received
|
||||
remote_balance
|
||||
|
@ -778,6 +778,7 @@ Object {
|
||||
"is_active": true,
|
||||
"is_closing": true,
|
||||
"is_opening": true,
|
||||
"is_timelocked": true,
|
||||
"local_balance": 1000,
|
||||
"local_reserve": 1000,
|
||||
"partner_node_info": Object {
|
||||
@ -794,6 +795,8 @@ Object {
|
||||
"remote_balance": 1000,
|
||||
"remote_reserve": 1000,
|
||||
"sent": 1000,
|
||||
"timelock_blocks": null,
|
||||
"timelock_expiration": 1000,
|
||||
"transaction_fee": 1000,
|
||||
"transaction_id": "string",
|
||||
"transaction_vout": 1000,
|
||||
@ -803,6 +806,7 @@ Object {
|
||||
"is_active": true,
|
||||
"is_closing": true,
|
||||
"is_opening": true,
|
||||
"is_timelocked": true,
|
||||
"local_balance": 1000,
|
||||
"local_reserve": 1000,
|
||||
"partner_node_info": Object {
|
||||
@ -819,6 +823,8 @@ Object {
|
||||
"remote_balance": 1000,
|
||||
"remote_reserve": 1000,
|
||||
"sent": 1000,
|
||||
"timelock_blocks": null,
|
||||
"timelock_expiration": 1000,
|
||||
"transaction_fee": 1000,
|
||||
"transaction_id": "string",
|
||||
"transaction_vout": 1000,
|
||||
@ -828,6 +834,7 @@ Object {
|
||||
"is_active": true,
|
||||
"is_closing": true,
|
||||
"is_opening": true,
|
||||
"is_timelocked": true,
|
||||
"local_balance": 1000,
|
||||
"local_reserve": 1000,
|
||||
"partner_node_info": Object {
|
||||
@ -844,6 +851,8 @@ Object {
|
||||
"remote_balance": 1000,
|
||||
"remote_reserve": 1000,
|
||||
"sent": 1000,
|
||||
"timelock_blocks": null,
|
||||
"timelock_expiration": 1000,
|
||||
"transaction_fee": 1000,
|
||||
"transaction_id": "string",
|
||||
"transaction_vout": 1000,
|
||||
|
@ -7,8 +7,11 @@ export const GET_PENDING_CHANNELS = gql`
|
||||
is_active
|
||||
is_closing
|
||||
is_opening
|
||||
is_timelocked
|
||||
local_balance
|
||||
local_reserve
|
||||
timelock_blocks
|
||||
timelock_expiration
|
||||
partner_public_key
|
||||
received
|
||||
remote_balance
|
||||
|
@ -1124,6 +1124,7 @@ export type PendingChannelType = {
|
||||
is_active: Scalars['Boolean'];
|
||||
is_closing: Scalars['Boolean'];
|
||||
is_opening: Scalars['Boolean'];
|
||||
is_timelocked: Scalars['Boolean'];
|
||||
local_balance: Scalars['Int'];
|
||||
local_reserve: Scalars['Int'];
|
||||
partner_node_info: Node;
|
||||
@ -1132,6 +1133,8 @@ export type PendingChannelType = {
|
||||
remote_balance: Scalars['Int'];
|
||||
remote_reserve: Scalars['Int'];
|
||||
sent: Scalars['Int'];
|
||||
timelock_blocks?: Maybe<Scalars['Int']>;
|
||||
timelock_expiration?: Maybe<Scalars['Int']>;
|
||||
transaction_fee?: Maybe<Scalars['Int']>;
|
||||
transaction_id: Scalars['String'];
|
||||
transaction_vout: Scalars['Int'];
|
||||
|
@ -6,6 +6,7 @@ import { getPrice, Price } from 'src/components/price/Price';
|
||||
import { addEllipsis, renderLine } from 'src/components/generic/helpers';
|
||||
import { useNodeInfo } from 'src/hooks/UseNodeInfo';
|
||||
import { useNodeBalances } from 'src/hooks/UseNodeBalances';
|
||||
import Big from 'big.js';
|
||||
import { unSelectedNavButton } from '../../../styles/Themes';
|
||||
import {
|
||||
Separation,
|
||||
@ -85,6 +86,14 @@ export const NodeInfo = ({ isOpen, isBurger }: NodeInfoProps) => {
|
||||
const formatCCB = format({ amount: lightning.confirmed });
|
||||
const formatPCB = format({ amount: lightning.pending });
|
||||
|
||||
const totalChain = new Big(onchain.confirmed).add(onchain.pending).toString();
|
||||
const totalLightning = new Big(lightning.confirmed)
|
||||
.add(lightning.pending)
|
||||
.toString();
|
||||
|
||||
const chainPending = Number(onchain.pending) + Number(onchain.closing);
|
||||
const channelPending = Number(lightning.pending);
|
||||
|
||||
if (!alias) return null;
|
||||
|
||||
if (isBurger) {
|
||||
@ -105,33 +114,17 @@ export const NodeInfo = ({ isOpen, isBurger }: NodeInfoProps) => {
|
||||
<SingleLine>
|
||||
<Zap
|
||||
size={18}
|
||||
color={Number(lightning.pending) === 0 ? '#FFD300' : '#652EC7'}
|
||||
fill={Number(lightning.pending) === 0 ? '#FFD300' : '#652EC7'}
|
||||
color={channelPending === 0 ? '#FFD300' : '#652EC7'}
|
||||
fill={channelPending === 0 ? '#FFD300' : '#652EC7'}
|
||||
/>
|
||||
{Number(lightning.pending) > 0 ? (
|
||||
<>
|
||||
{formatCCB}
|
||||
{' / '}
|
||||
{formatPCB}
|
||||
</>
|
||||
) : (
|
||||
<Price amount={lightning.confirmed} />
|
||||
)}
|
||||
<Price amount={totalLightning} />
|
||||
</SingleLine>
|
||||
<SingleLine>
|
||||
<Anchor
|
||||
size={18}
|
||||
color={Number(onchain.pending) === 0 ? '#FFD300' : '#652EC7'}
|
||||
color={chainPending === 0 ? '#FFD300' : '#652EC7'}
|
||||
/>
|
||||
{Number(onchain.pending) > 0 ? (
|
||||
<>
|
||||
{formatCB}
|
||||
{' / '}
|
||||
{formatPB}
|
||||
</>
|
||||
) : (
|
||||
<Price amount={onchain.confirmed} />
|
||||
)}
|
||||
<Price amount={totalChain} />
|
||||
</SingleLine>
|
||||
</>
|
||||
);
|
||||
@ -147,7 +140,7 @@ export const NodeInfo = ({ isOpen, isBurger }: NodeInfoProps) => {
|
||||
strokeWidth={'0'}
|
||||
fill={syncedToChain ? '#95de64' : '#ff7875'}
|
||||
/>
|
||||
{(Number(lightning.pending) > 0 || Number(onchain.pending) > 0) && (
|
||||
{(channelPending > 0 || chainPending > 0) && (
|
||||
<div>
|
||||
<Circle size={18} fill={'#652EC7'} strokeWidth={'0'} />
|
||||
</div>
|
||||
@ -155,13 +148,13 @@ export const NodeInfo = ({ isOpen, isBurger }: NodeInfoProps) => {
|
||||
<Margin>
|
||||
<Zap
|
||||
size={18}
|
||||
fill={Number(lightning.pending) === 0 ? '#FFD300' : '#652EC7'}
|
||||
color={Number(lightning.pending) === 0 ? '#FFD300' : '#652EC7'}
|
||||
fill={channelPending === 0 ? '#FFD300' : '#652EC7'}
|
||||
color={channelPending === 0 ? '#FFD300' : '#652EC7'}
|
||||
/>
|
||||
</Margin>
|
||||
<Anchor
|
||||
size={18}
|
||||
color={Number(onchain.pending) === 0 ? '#FFD300' : '#652EC7'}
|
||||
color={chainPending === 0 ? '#FFD300' : '#652EC7'}
|
||||
/>
|
||||
</div>
|
||||
<div data-tip data-for="full_node_tip">
|
||||
@ -197,20 +190,12 @@ export const NodeInfo = ({ isOpen, isBurger }: NodeInfoProps) => {
|
||||
</Title>
|
||||
<Separation lineColor={unSelectedNavButton} />
|
||||
<Balance data-tip data-for="balance_tip">
|
||||
<Zap
|
||||
size={18}
|
||||
color={Number(lightning.pending) === 0 ? '#FFD300' : '#652EC7'}
|
||||
/>
|
||||
<Price amount={lightning.confirmed} />
|
||||
{/* <AnimatedNumber amount={channelBalance} /> */}
|
||||
<Zap size={18} color={channelPending === 0 ? '#FFD300' : '#652EC7'} />
|
||||
<Price amount={totalLightning} />
|
||||
</Balance>
|
||||
<Balance data-tip data-for="chain_balance_tip">
|
||||
<Anchor
|
||||
size={18}
|
||||
color={Number(onchain.pending) === 0 ? '#FFD300' : '#652EC7'}
|
||||
/>
|
||||
<Price amount={onchain.confirmed} />
|
||||
{/* <AnimatedNumber amount={chainBalance} /> */}
|
||||
<Anchor size={18} color={chainPending === 0 ? '#FFD300' : '#652EC7'} />
|
||||
<Price amount={totalChain} />
|
||||
</Balance>
|
||||
<Balance
|
||||
data-tip
|
||||
|
@ -1,12 +1,5 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Sun,
|
||||
Moon,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Icon,
|
||||
Star,
|
||||
} from 'react-feather';
|
||||
import React, { FC, SVGAttributes } from 'react';
|
||||
import { Sun, Moon, ChevronLeft, ChevronRight, Star } from 'react-feather';
|
||||
import styled from 'styled-components';
|
||||
import { SatoshiSymbol } from 'src/components/satoshi/Satoshi';
|
||||
import { Separation, SingleLine } from '../../../components/generic/Styled';
|
||||
@ -22,6 +15,14 @@ import {
|
||||
} from '../../../styles/Themes';
|
||||
import { usePriceState } from '../../../context/PriceContext';
|
||||
|
||||
// Icon import from react-feather is not working
|
||||
// TODO: recheck if the type is available
|
||||
type IconProps = SVGAttributes<SVGElement> & {
|
||||
color?: string;
|
||||
size?: string | number;
|
||||
};
|
||||
type Icon = FC<IconProps>;
|
||||
|
||||
const SelectedIcon = styled.div<{ selected: boolean }>`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@ -59,7 +60,7 @@ const BurgerPadding = styled(SingleLine)`
|
||||
margin: 16px 0;
|
||||
`;
|
||||
|
||||
const currencyArray = ['sat', 'btc', 'EUR', 'USD'];
|
||||
const currencyArray = ['sat', 'btc', 'fiat'];
|
||||
const currencyNoFiatArray = ['sat', 'btc'];
|
||||
|
||||
const themeArray = ['light', 'dark', 'night'];
|
||||
@ -67,8 +68,7 @@ const themeArray = ['light', 'dark', 'night'];
|
||||
const currencyMap: { [key: string]: string } = {
|
||||
sat: 'S',
|
||||
btc: '₿',
|
||||
EUR: '€',
|
||||
USD: '$',
|
||||
fiat: 'F',
|
||||
};
|
||||
const currencyNoFiatMap: { [key: string]: string } = {
|
||||
sat: 'S',
|
||||
|
@ -178,7 +178,7 @@ export const chatSentBubbleColor = theme('mode', {
|
||||
// BUTTON COLORS
|
||||
// ---------------------------------------
|
||||
export const colorButtonBackground = theme('mode', {
|
||||
light: themeColors.grey,
|
||||
light: themeColors.grey2,
|
||||
dark: themeColors.blue7,
|
||||
night: '#0a0a0a',
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import ReactTooltip from 'react-tooltip';
|
||||
import { PendingChannelType } from 'src/graphql/types';
|
||||
import { getPercent } from '../../../utils/helpers';
|
||||
import { blockToTime, getPercent } from '../../../utils/helpers';
|
||||
import {
|
||||
Progress,
|
||||
ProgressBar,
|
||||
@ -63,6 +63,9 @@ export const PendingCard = ({
|
||||
transaction_id,
|
||||
transaction_vout,
|
||||
partner_node_info,
|
||||
is_timelocked,
|
||||
timelock_blocks,
|
||||
timelock_expiration,
|
||||
} = channelInfo;
|
||||
|
||||
const {
|
||||
@ -101,10 +104,31 @@ export const PendingCard = ({
|
||||
<DarkSubTitle>Partner node not found</DarkSubTitle>
|
||||
);
|
||||
|
||||
const renderTimelock = () => {
|
||||
if (!is_timelocked) return null;
|
||||
return (
|
||||
<>
|
||||
{renderLine(
|
||||
'Total locked time',
|
||||
`${blockToTime(
|
||||
timelock_expiration || 0
|
||||
)} (${timelock_expiration} blocks)`
|
||||
)}
|
||||
{renderLine(
|
||||
'Pending locked time',
|
||||
`${blockToTime(timelock_blocks || 0)} (${timelock_blocks} blocks)`
|
||||
)}
|
||||
<Separation />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const renderDetails = () => {
|
||||
return (
|
||||
<>
|
||||
<Separation />
|
||||
{renderLine('Force Closed', is_timelocked ? 'Yes' : 'No')}
|
||||
{renderTimelock()}
|
||||
{renderLine('State:', is_active ? 'Active' : 'Inactive')}
|
||||
{renderLine('Status:', is_opening ? 'Opening' : 'Closing')}
|
||||
{renderLine('Local Balance:', local_balance)}
|
||||
|
102
src/views/home/account/AccountButtons.tsx
Normal file
102
src/views/home/account/AccountButtons.tsx
Normal file
@ -0,0 +1,102 @@
|
||||
import { useState } from 'react';
|
||||
import { Anchor, X, Zap } from 'react-feather';
|
||||
import { ColorButton } from 'src/components/buttons/colorButton/ColorButton';
|
||||
import { Card } from 'src/components/generic/Styled';
|
||||
import { mediaWidths } from 'src/styles/Themes';
|
||||
import styled from 'styled-components';
|
||||
import { CreateInvoiceCard } from './createInvoice/CreateInvoice';
|
||||
import { PayCard } from './pay/Payment';
|
||||
import { ReceiveOnChainCard } from './receiveOnChain/ReceiveOnChain';
|
||||
import { SendOnChainCard } from './sendOnChain/SendOnChain';
|
||||
|
||||
const SECTION_COLOR = '#FFD300';
|
||||
|
||||
const S = {
|
||||
grid: styled.div`
|
||||
display: grid;
|
||||
grid-gap: 8px;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
margin-bottom: 32px;
|
||||
|
||||
@media (${mediaWidths.mobile}) {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
`,
|
||||
};
|
||||
|
||||
export const AccountButtons = () => {
|
||||
const [state, setState] = useState<string>('none');
|
||||
|
||||
const renderContent = () => {
|
||||
switch (state) {
|
||||
case 'send_ln':
|
||||
return <PayCard setOpen={() => setState('none')} />;
|
||||
case 'receive_ln':
|
||||
return <CreateInvoiceCard color={SECTION_COLOR} />;
|
||||
case 'send_chain':
|
||||
return <SendOnChainCard setOpen={() => setState('none')} />;
|
||||
case 'receive_chain':
|
||||
return <ReceiveOnChainCard />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<S.grid>
|
||||
<ColorButton
|
||||
withBorder={state === 'send_ln'}
|
||||
onClick={() => setState(state === 'send_ln' ? 'none' : 'send_ln')}
|
||||
>
|
||||
{state === 'send_ln' ? (
|
||||
<X size={18} color={SECTION_COLOR} />
|
||||
) : (
|
||||
<Zap size={18} color={SECTION_COLOR} />
|
||||
)}
|
||||
Send
|
||||
</ColorButton>
|
||||
<ColorButton
|
||||
withBorder={state === 'receive_ln'}
|
||||
onClick={() =>
|
||||
setState(state === 'receive_ln' ? 'none' : 'receive_ln')
|
||||
}
|
||||
>
|
||||
{state === 'receive_ln' ? (
|
||||
<X size={18} color={SECTION_COLOR} />
|
||||
) : (
|
||||
<Zap size={18} color={SECTION_COLOR} />
|
||||
)}
|
||||
Receive
|
||||
</ColorButton>
|
||||
<ColorButton
|
||||
withBorder={state === 'send_chain'}
|
||||
onClick={() =>
|
||||
setState(state === 'send_chain' ? 'none' : 'send_chain')
|
||||
}
|
||||
>
|
||||
{state === 'send_chain' ? (
|
||||
<X size={18} color={SECTION_COLOR} />
|
||||
) : (
|
||||
<Anchor size={18} color={SECTION_COLOR} />
|
||||
)}
|
||||
Send
|
||||
</ColorButton>
|
||||
<ColorButton
|
||||
withBorder={state === 'receive_chain'}
|
||||
onClick={() =>
|
||||
setState(state === 'receive_chain' ? 'none' : 'receive_chain')
|
||||
}
|
||||
>
|
||||
{state === 'receive_chain' ? (
|
||||
<X size={18} color={SECTION_COLOR} />
|
||||
) : (
|
||||
<Anchor size={18} color={SECTION_COLOR} />
|
||||
)}
|
||||
Receive
|
||||
</ColorButton>
|
||||
</S.grid>
|
||||
{state !== 'none' && <Card>{renderContent()}</Card>}
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,11 +1,9 @@
|
||||
import React, { useState } from 'react';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Zap, Anchor, Pocket, HelpCircle, X } from 'react-feather';
|
||||
import { ColorButton } from 'src/components/buttons/colorButton/ColorButton';
|
||||
import ReactTooltip from 'react-tooltip';
|
||||
import { renderLine } from 'src/components/generic/helpers';
|
||||
import { Zap, Anchor, Pocket } from 'react-feather';
|
||||
import { useNodeBalances } from 'src/hooks/UseNodeBalances';
|
||||
import Big from 'big.js';
|
||||
import { renderLine } from 'src/components/generic/helpers';
|
||||
import {
|
||||
Card,
|
||||
CardWithTitle,
|
||||
@ -13,13 +11,22 @@ import {
|
||||
Separation,
|
||||
DarkSubTitle,
|
||||
ResponsiveLine,
|
||||
SingleLine,
|
||||
} from '../../../components/generic/Styled';
|
||||
import { Price } from '../../../components/price/Price';
|
||||
import { mediaWidths } from '../../../styles/Themes';
|
||||
import { ReceiveOnChainCard } from './receiveOnChain/ReceiveOnChain';
|
||||
import { SendOnChainCard } from './sendOnChain/SendOnChain';
|
||||
import { PayCard } from './pay/Payment';
|
||||
import { CreateInvoiceCard } from './createInvoice/CreateInvoice';
|
||||
|
||||
const S = {
|
||||
grid: styled.div`
|
||||
display: grid;
|
||||
grid-gap: 16px;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
|
||||
@media (${mediaWidths.mobile}) {
|
||||
display: block;
|
||||
}
|
||||
`,
|
||||
};
|
||||
|
||||
const Tile = styled.div`
|
||||
display: flex;
|
||||
@ -36,25 +43,14 @@ const Tile = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
const AccountButtonWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@media (${mediaWidths.mobile}) {
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
}
|
||||
`;
|
||||
|
||||
const sectionColor = '#FFD300';
|
||||
|
||||
export const AccountInfo = () => {
|
||||
const [state, setState] = useState<string>('none');
|
||||
|
||||
const { onchain, lightning } = useNodeBalances();
|
||||
|
||||
const totalAmount = new Big(onchain.confirmed)
|
||||
.add(onchain.pending)
|
||||
.add(onchain.closing)
|
||||
.add(lightning.confirmed)
|
||||
.add(lightning.pending)
|
||||
.toString();
|
||||
@ -64,126 +60,18 @@ export const AccountInfo = () => {
|
||||
.add(lightning.pending)
|
||||
.toString();
|
||||
|
||||
const chainBalance = Number(onchain.confirmed);
|
||||
const chainPending = Number(onchain.pending);
|
||||
const channelBalance = Number(lightning.confirmed);
|
||||
const activeLightning = new Big(lightning.active)
|
||||
.sub(lightning.commit)
|
||||
.toString();
|
||||
|
||||
const inactiveLightning = new Big(lightning.confirmed)
|
||||
.sub(lightning.active)
|
||||
.add(lightning.commit)
|
||||
.toString();
|
||||
|
||||
const chainPending = Number(onchain.pending) + Number(onchain.closing);
|
||||
const channelPending = Number(lightning.pending);
|
||||
|
||||
const renderContent = () => {
|
||||
switch (state) {
|
||||
case 'send_ln':
|
||||
return <PayCard setOpen={() => setState('none')} />;
|
||||
case 'receive_ln':
|
||||
return <CreateInvoiceCard color={sectionColor} />;
|
||||
case 'send_chain':
|
||||
return <SendOnChainCard setOpen={() => setState('none')} />;
|
||||
case 'receive_chain':
|
||||
return <ReceiveOnChainCard />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const getTitle = () => {
|
||||
switch (state) {
|
||||
case 'send_ln':
|
||||
return 'Send Sats over Lightning';
|
||||
case 'receive_ln':
|
||||
return 'Receive Sats over Lightning';
|
||||
case 'send_chain':
|
||||
return 'Send To On Chain Address';
|
||||
case 'receive_chain':
|
||||
return 'Create Address to Receive';
|
||||
default:
|
||||
return 'Your Accounts';
|
||||
}
|
||||
};
|
||||
|
||||
const showLn =
|
||||
state === 'send_ln' || state === 'receive_ln' || state === 'none';
|
||||
const showChain =
|
||||
state === 'send_chain' || state === 'receive_chain' || state === 'none';
|
||||
|
||||
const renderBalances = (current: number, pending: number, key: string) => (
|
||||
<>
|
||||
<Tile>
|
||||
<DarkSubTitle>Pending Balance</DarkSubTitle>
|
||||
<div>
|
||||
<Price amount={pending} />
|
||||
</div>
|
||||
</Tile>
|
||||
<Tile data-tip data-for={key}>
|
||||
<DarkSubTitle>
|
||||
Total Balance{pending > 0 && <HelpCircle size={12} />}
|
||||
</DarkSubTitle>
|
||||
<div>
|
||||
<Price amount={current + pending} />
|
||||
</div>
|
||||
</Tile>
|
||||
<ReactTooltip id={key} effect={'solid'} place={'bottom'}>
|
||||
{renderLine('Total', <Price amount={current + pending} />)}
|
||||
<Separation withMargin={'8px 0'} />
|
||||
{renderLine('Current', <Price amount={current} />)}
|
||||
{renderLine('Pending', <Price amount={pending} />)}
|
||||
</ReactTooltip>
|
||||
</>
|
||||
);
|
||||
|
||||
const renderButtons = (send: string, receive: string) => (
|
||||
<AccountButtonWrapper>
|
||||
<ColorButton
|
||||
fullWidth={true}
|
||||
withMargin={'0 0 2px'}
|
||||
mobileMargin={'8px 4px 0 0'}
|
||||
onClick={() => setState(send)}
|
||||
>
|
||||
Send
|
||||
</ColorButton>
|
||||
<ColorButton
|
||||
fullWidth={true}
|
||||
withMargin={'2px 0 0'}
|
||||
mobileMargin={'8px 0 0 4px'}
|
||||
onClick={() => setState(receive)}
|
||||
>
|
||||
Receive
|
||||
</ColorButton>
|
||||
</AccountButtonWrapper>
|
||||
);
|
||||
|
||||
const renderLnAccount = () => (
|
||||
<ResponsiveLine>
|
||||
<Zap size={18} color={channelPending === 0 ? sectionColor : '#652EC7'} />
|
||||
<Tile startTile={true}>
|
||||
<DarkSubTitle>Account</DarkSubTitle>
|
||||
<div>Lightning</div>
|
||||
</Tile>
|
||||
{renderBalances(channelBalance, channelPending, 'lightning')}
|
||||
{showLn && showChain && renderButtons('send_ln', 'receive_ln')}
|
||||
{showLn && !showChain && (
|
||||
<ColorButton onClick={() => setState('none')}>
|
||||
<X size={18} />
|
||||
</ColorButton>
|
||||
)}
|
||||
</ResponsiveLine>
|
||||
);
|
||||
|
||||
const renderChainAccount = () => (
|
||||
<ResponsiveLine>
|
||||
<Anchor size={18} color={chainPending === 0 ? sectionColor : '#652EC7'} />
|
||||
<Tile startTile={true}>
|
||||
<DarkSubTitle>Account</DarkSubTitle>
|
||||
<div>Bitcoin</div>
|
||||
</Tile>
|
||||
{renderBalances(chainBalance, chainPending, 'onchain')}
|
||||
{showLn && showChain && renderButtons('send_chain', 'receive_chain')}
|
||||
{!showLn && showChain && (
|
||||
<ColorButton onClick={() => setState('none')}>
|
||||
<X size={18} />
|
||||
</ColorButton>
|
||||
)}
|
||||
</ResponsiveLine>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<CardWithTitle>
|
||||
@ -219,16 +107,38 @@ export const AccountInfo = () => {
|
||||
</ResponsiveLine>
|
||||
</Card>
|
||||
</CardWithTitle>
|
||||
<CardWithTitle>
|
||||
<SubTitle>{getTitle()}</SubTitle>
|
||||
<Card>
|
||||
{showLn && renderLnAccount()}
|
||||
{showLn && <Separation />}
|
||||
{showChain && renderChainAccount()}
|
||||
{!showLn && showChain && <Separation />}
|
||||
{renderContent()}
|
||||
</Card>
|
||||
</CardWithTitle>
|
||||
<S.grid>
|
||||
<CardWithTitle>
|
||||
<Card>
|
||||
<SingleLine>
|
||||
<Zap
|
||||
size={18}
|
||||
color={channelPending === 0 ? sectionColor : '#652EC7'}
|
||||
/>
|
||||
<SubTitle>Lightning</SubTitle>
|
||||
</SingleLine>
|
||||
<Separation />
|
||||
{renderLine('Available', <Price amount={activeLightning} />)}
|
||||
{renderLine('Not Available', <Price amount={inactiveLightning} />)}
|
||||
{renderLine('Pending', <Price amount={lightning.pending} />)}
|
||||
</Card>
|
||||
</CardWithTitle>
|
||||
<CardWithTitle>
|
||||
<Card>
|
||||
<SingleLine>
|
||||
<Anchor
|
||||
size={18}
|
||||
color={chainPending === 0 ? sectionColor : '#652EC7'}
|
||||
/>
|
||||
<SubTitle>Bitcoin</SubTitle>
|
||||
</SingleLine>
|
||||
<Separation />
|
||||
{renderLine('Available', <Price amount={onchain.confirmed} />)}
|
||||
{renderLine('Pending', <Price amount={onchain.pending} />)}
|
||||
{renderLine('Force Closures', <Price amount={onchain.closing} />)}
|
||||
</Card>
|
||||
</CardWithTitle>
|
||||
</S.grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user