Skip to content

Commit

Permalink
Visualize channel reserve capacity
Browse files Browse the repository at this point in the history
  • Loading branch information
kaloudis committed Nov 10, 2024
1 parent 3147881 commit 035bd1c
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 6 deletions.
4 changes: 3 additions & 1 deletion components/BalanceSlider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ChannelItem } from '../components/Channels/ChannelItem';
interface BalanceSliderProps {
localBalance: string | number;
remoteBalance: string | number;
reserveBalance: string | number;
list?: boolean;
}

Expand All @@ -13,12 +14,13 @@ export default class BalanceSlider extends React.Component<
{}
> {
render() {
const { localBalance, remoteBalance } = this.props;
const { localBalance, remoteBalance, reserveBalance } = this.props;
return (
<View style={styles.slider}>
<ChannelItem
inbound={remoteBalance}
outbound={localBalance}
reserve={reserveBalance}
noBorder
hideLabels
/>
Expand Down
19 changes: 17 additions & 2 deletions components/Channels/BalanceBar.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import React from 'react';
import { View } from 'react-native';
import { Row } from '../layout/Row';
import { themeColor } from '../../utils/ThemeUtils';
import { themeColor, hexAverage } from '../../utils/ThemeUtils';

export function BalanceBar({
left,
center = 0,
right,
offline,
percentOfLargest,
showProportionally = true
}: {
left: number;
center: number;
right: number;
offline: boolean;
// How big is this channel relative to the largest channel
// A float from 0.0 -> 1.0, 1 being the largest channel
percentOfLargest: number;
showProportionally: boolean;
}) {
const total = left + right;
const total = left + center + right;

// If we're supposed to show proportionally set the miniumum to 20% of the width
// Otherwise take the full width
Expand All @@ -35,6 +37,19 @@ export function BalanceBar({
marginRight: 1
}}
/>
<View
style={{
height: 8,
flex: center / total,
backgroundColor: offline
? '#C6C7C9'
: hexAverage([
themeColor('outbound'),
themeColor('inbound')
]),
marginRight: 1
}}
/>
<View
style={{
height: 8,
Expand Down
3 changes: 3 additions & 0 deletions components/Channels/ChannelItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export function ChannelItem({
secondTitle,
inbound,
outbound,
reserve = 0,
largestTotal,
status,
pendingHTLCs,
Expand All @@ -35,6 +36,7 @@ export function ChannelItem({
secondTitle?: string;
inbound: string | number;
outbound: string | number;
reserve?: string | number;
largestTotal?: number;
status?: Status;
pendingHTLCs?: boolean;
Expand Down Expand Up @@ -129,6 +131,7 @@ export function ChannelItem({
<Row style={{ marginTop: 15, marginBottom: 15 }}>
<BalanceBar
left={lurkerMode ? 50 : Number(outbound)}
center={lurkerMode ? 0 : Number(reserve)}
right={lurkerMode ? 50 : Number(inbound)}
offline={isOffline}
percentOfLargest={percentOfLargest}
Expand Down
2 changes: 2 additions & 0 deletions components/HopPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export default class ChannelPicker extends React.Component<
title={item.displayName}
inbound={item.remoteBalance}
outbound={item.localBalance}
reserve={item.totalReserveBalance}
largestTotal={largestChannelSats}
selected={selected}
/>
Expand All @@ -159,6 +160,7 @@ export default class ChannelPicker extends React.Component<
title={item.displayName}
inbound={item.remoteBalance}
outbound={item.localBalance}
reserve={item.totalReserveBalance}
selected={selected}
/>
</TouchableHighlight>
Expand Down
13 changes: 13 additions & 0 deletions components/KeyValue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ interface KeyValueProps {
keyValue: string;
value?: any;
color?: string;
indicatorColor?: string;
sensitive?: boolean;
infoText?: string | Array<string>;
infoLink?: string;
Expand All @@ -40,6 +41,7 @@ export default class KeyValue extends React.Component<KeyValueProps, {}> {
keyValue,
value,
color,
indicatorColor,
sensitive,
infoText,
infoLink,
Expand All @@ -63,6 +65,17 @@ export default class KeyValue extends React.Component<KeyValueProps, {}> {
const rtl = false;
const KeyBase = (
<Body>
{indicatorColor && (
<View
style={{
width: 12,
height: 12,
borderRadius: 12 / 2,
backgroundColor: indicatorColor,
marginRight: 7
}}
></View>
)}
<Text
style={{
color:
Expand Down
31 changes: 29 additions & 2 deletions models/Channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,18 +95,21 @@ export default class Channel extends BaseModel {

@computed
public get localBalance(): string {
return this.to_us
const totalLocalBalance = this.to_us
? (Number(this.to_us) / 1000).toString()
: this.to_us_msat
? (Number(this.to_us_msat) / 1000).toString()
: this.msatoshi_to_us
? (Number(this.msatoshi_to_us) / 1000).toString()
: this.local_balance || '0';
return (
Number(totalLocalBalance) - Number(this.localReserveBalance)
).toString();
}

@computed
public get remoteBalance(): string {
return this.total
const totalRemoteBalance = this.total
? ((Number(this.total) - Number(this.to_us)) / 1000).toString()
: this.total_msat
? (
Expand All @@ -119,6 +122,30 @@ export default class Channel extends BaseModel {
1000
).toString()
: this.remote_balance || '0';
return (
Number(totalRemoteBalance) - Number(this.remoteReserveBalance)
).toString();
}

@computed
public get localReserveBalance(): string {
return this.local_chan_reserve_sat
? Number(this.local_chan_reserve_sat).toString()
: '0';
}

@computed
public get remoteReserveBalance(): string {
return this.remote_chan_reserve_sat
? Number(this.remote_chan_reserve_sat).toString()
: '0';
}

@computed
public get totalReserveBalance(): string {
return (
Number(this.localReserveBalance) + Number(this.remoteReserveBalance)
).toString();
}

/** Channel id
Expand Down
29 changes: 29 additions & 0 deletions utils/ThemeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,3 +440,32 @@ export function isLightTheme() {
var L = 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2];
return L > 0.179;
}

const padToTwo = (numberString: string) => {
if (numberString.length < 2) {
numberString = '0' + numberString;
}
return numberString;
};

export const hexAverage = (args: string[] = []) => {
return args
.reduce(
function (previousValue, currentValue) {
// @ts-ignore:next-line
return currentValue
.replace(/^#/, '')
.match(/.{2}/g)
.map(function (value, index) {
return previousValue[index] + parseInt(value, 16);
});
},
[0, 0, 0]
)
.reduce(function (previousValue, currentValue) {
return (
previousValue +
padToTwo(Math.floor(currentValue / args.length).toString(16))
);
}, '#');
};
13 changes: 12 additions & 1 deletion views/Channels/Channel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import TextInput from '../../components/TextInput';
import PrivacyUtils from '../../utils/PrivacyUtils';
import BackendUtils from '../../utils/BackendUtils';
import { localeString } from '../../utils/LocaleUtils';
import { themeColor } from '../../utils/ThemeUtils';
import { themeColor, hexAverage } from '../../utils/ThemeUtils';
import UrlUtils from '../../utils/UrlUtils';
import { getPhoto } from '../../utils/PhotoUtils';

Expand Down Expand Up @@ -230,6 +230,7 @@ export default class ChannelView extends React.Component<
channel_point,
commit_weight,
localBalance,
totalReserveBalance,
commit_fee,
csv_delay,
total_satoshis_received,
Expand Down Expand Up @@ -277,6 +278,11 @@ export default class ChannelView extends React.Component<

const peerDisplay = PrivacyUtils.sensitiveValue(displayName, 8);

const reserveColor = hexAverage([
themeColor('outbound'),
themeColor('inbound')
]);

const EditFees = () => (
<TouchableOpacity
onPress={() => navigation.navigate('SetFees', { channel })}
Expand Down Expand Up @@ -358,6 +364,7 @@ export default class ChannelView extends React.Component<
<BalanceSlider
localBalance={lurkerMode ? 50 : localBalance}
remoteBalance={lurkerMode ? 50 : remoteBalance}
reserveBalance={lurkerMode ? 50 : totalReserveBalance}
/>
<Text
style={{ ...styles.status, color: themeColor('text') }}
Expand Down Expand Up @@ -572,12 +579,14 @@ export default class ChannelView extends React.Component<
value={
<Amount sats={localBalance} sensitive toggleable />
}
indicatorColor={themeColor('outbound')}
/>
<KeyValue
keyValue={localeString('views.Channel.Total.inbound')}
value={
<Amount sats={remoteBalance} sensitive toggleable />
}
indicatorColor={themeColor('inbound')}
/>
{unsettled_balance && (
<KeyValue
Expand Down Expand Up @@ -621,6 +630,7 @@ export default class ChannelView extends React.Component<
'views.Channel.localReserve.info'
)}
infoLink="https://bitcoin.design/guide/how-it-works/liquidity/#what-is-a-channel-reserve"
indicatorColor={reserveColor}
/>
)}
{!!remote_chan_reserve_sat && (
Expand All @@ -639,6 +649,7 @@ export default class ChannelView extends React.Component<
'views.Channel.remoteReserve.info'
)}
infoLink="https://bitcoin.design/guide/how-it-works/liquidity/#what-is-a-channel-reserve"
indicatorColor={reserveColor}
/>
)}
{capacity && (
Expand Down
2 changes: 2 additions & 0 deletions views/Channels/ChannelsPane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ export default class ChannelsPane extends React.PureComponent<ChannelsProps> {
pendingHTLCs={item?.pending_htlcs?.length > 0}
inbound={item.remoteBalance}
outbound={item.localBalance}
reserve={item.totalReserveBalance}
largestTotal={largestChannelSats}
/>
</TouchableHighlight>
Expand All @@ -139,6 +140,7 @@ export default class ChannelsPane extends React.PureComponent<ChannelsProps> {
title={item.displayName}
inbound={item.remoteBalance}
outbound={item.localBalance}
reserve={item.totalReserveBalance}
status={getStatus()}
pendingHTLCs={item?.pending_htlcs?.length > 0}
pendingTimelock={
Expand Down

0 comments on commit 035bd1c

Please sign in to comment.