Skip to content
This repository has been archived by the owner on Mar 14, 2024. It is now read-only.

Commit

Permalink
[fees]: Add bos fees command
Browse files Browse the repository at this point in the history
Fixes #115
  • Loading branch information
niteshbalusu11 committed Sep 23, 2022
1 parent 040beb0 commit b85e179
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 31 deletions.
16 changes: 8 additions & 8 deletions src/client/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,21 +164,21 @@ const commands: Commands = [
name: 'Fees',
value: 'Fees',
description: 'Show and adjust outbound fee rates',
longDescription: `List out fee rates, fix problems with routing policies, set out fees
longDescription: `List out fee rates, fix problems with routing policies, set out fees.
When setting fee, if channels pending, will wait for confirm to set
When setting fee, if channels pending, will wait for confirm to set.
Set-fee-rate can use formulas: https://formulajs.info/functions/
Set-fee-rate can use formulas: https://formulajs.info/functions/.
Specify PERCENT(0.00) to set the fee as a fraction of routed amount
Specify PERCENT(0.00) to set the fee as a fraction of routed amount.
Specify BIPS() to set the fee as parts per thousand
Specify BIPS() to set the fee as parts per thousand.
You can use INBOUND and OUTBOUND in formulas for IF formulas
You can use INBOUND and OUTBOUND in formulas for IF formulas.
You can use INBOUND_FEE_RATE to mirror an inbound fee
You can use INBOUND_FEE_RATE to mirror an inbound fee.
You can use FEE_RATE_OF_<PUBKEY> to reference other node rates`,
You can use FEE_RATE_OF_<PUBKEY> to reference other node rates.`,
flags: {
set_cltv_delta: 'SetCltvDelta',
set_fee_rate: 'SetFeeRate',
Expand Down
20 changes: 20 additions & 0 deletions src/client/output/FeesOutput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import { StandardTableOutput } from '~client/standard_components/app-components';

// Renders the output of the bos fees command

type Props = {
data: {
rows: string[][];
};
};

const FeesOutput = ({ data }: Props) => {
return (
<div style={{ marginTop: '30px' }}>
{!!data ? <StandardTableOutput data={data} tableId="feesOutput" /> : <h2>No Output to display</h2>}
</div>
);
};

export default FeesOutput;
2 changes: 2 additions & 0 deletions src/client/output/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import ChartFeesEarnedOutput from './ChartFeesEarnedOutput';
import ChartFeesPaidOutput from './ChartFeesPaidOutput';
import ChartPaymentsReceivedOutput from './ChartPaymentsReceivedOutput';
import ClosedOutput from './ClosedOutput';
import FeesOutput from './FeesOutput';
import FindOutput from './FindOutput';
import ForwardsOutput from './ForwardsOutput';
import OpenOutput from './OpenOutput';
Expand All @@ -24,6 +25,7 @@ export {
ChartFeesPaidOutput,
ChartPaymentsReceivedOutput,
ClosedOutput,
FeesOutput,
FindOutput,
ForwardsOutput,
OpenOutput,
Expand Down
70 changes: 51 additions & 19 deletions src/client/pages/commands/Fees.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
import * as types from '~shared/types';

import { Button, CssBaseline, IconButton, Stack, TextField } from '@mui/material';
import React, { useState } from 'react';
import { StandardHomeButtonLink, StartFlexBox, SubmitButton } from '~client/standard_components/app-components';
import commands, { globalCommands } from '../../commands';

import DeleteIcon from '@mui/icons-material/Delete';
import { FeesOutput } from '~client/output';
import Head from 'next/head';
import { PeersAndTagsList } from '~client/standard_components/lndboss';
import { axiosPostWithAlert } from '~client/utils/axios';

const FeesCommand = commands.find(n => n.value === 'Fees');

/*
Renders the bos fees command
POST call to the NestJs process to get fees information
*/

const styles = {
form: {
marginLeft: '50px',
marginTop: '100px',
width: '700px',
width: '800px',
},
textField: {
width: '500px',
marginTop: '10px',
},
h4: {
marginTop: '0px',
Expand All @@ -37,10 +46,10 @@ const styles = {

const Fees = () => {
const [cltvDelta, setCltvDelta] = useState(undefined);
const [data, setData] = useState(undefined);
const [feeRate, setFeeRate] = useState(undefined);
const [formValues, setFormValues] = useState([{ node: '' }]);
const [node, setNode] = useState(undefined);
const [formValues, setFormValues] = useState([{ to: '' }]);
const [peer, setPeer] = useState(undefined);

const handeNodeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setNode(event.target.value);
Expand All @@ -62,7 +71,30 @@ const Fees = () => {
};

const addFormFields = () => {
setFormValues([...formValues, { to: '' }]);
setFormValues([...formValues, { node: '' }]);
};

const handleChange = (i: number, e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const newFormValues = [...formValues];
newFormValues[i][e.target.name] = e.target.value;
setFormValues(newFormValues);
};

// ============================================================================

const fetchData = async () => {
const query: types.commandFees = {
node,
cltv_delta: Number(cltvDelta),
fee_rate: feeRate,
to: formValues.map(n => n.node),
};

const result = await axiosPostWithAlert({ path: 'fees', postBody: query });

if (!!result) {
setData(result);
}
};

return (
Expand All @@ -79,7 +111,7 @@ const Fees = () => {

<TextField
type="text"
placeholder="Fee Rate"
placeholder="Fee Rate (Optional)"
label={FeesCommand.flags.set_fee_rate}
id={FeesCommand.flags.set_fee_rate}
onChange={handleFeeRateChange}
Expand All @@ -88,31 +120,28 @@ const Fees = () => {

<TextField
type="text"
placeholder="Cltv Delta"
placeholder="Cltv Delta (Optional)"
label={FeesCommand.flags.set_cltv_delta}
id={FeesCommand.flags.set_cltv_delta}
onChange={handleCltvDeltaChange}
style={styles.textField}
/>

{/* <PeersAndTagsList
setPeer={setOutPeer}
label={FeesCommand.flags.to}
placeholder={`${FeesCommand.flags.to} (Set fees to key/tag)`}
id={FeesCommand.flags.to}
/> */}

<>
<Button href="#text-buttons" onClick={() => addFormFields()} style={styles.button}>
Add +
</Button>
{formValues.map((element, index) => (
<div key={index}>
<PeersAndTagsList
setPeer={setPeer}
label={FeesCommand.flags.to}
placeholder={`${FeesCommand.flags.to} (Set fees to key/tag)`}
id={`to-${index}`}
<TextField
type="text"
label="To"
name="node"
placeholder="Peer key/alias/tag to set fees"
value={element.node || ''}
onChange={e => handleChange(index, e)}
style={styles.textField}
id={`key-${index}`}
/>
{!!index ? (
<IconButton aria-label="delete" onClick={() => removeFormFields(index)} style={styles.iconButton}>
Expand All @@ -131,6 +160,9 @@ const Fees = () => {
onChange={handeNodeChange}
style={styles.textField}
/>

<SubmitButton onClick={fetchData}>Run Command</SubmitButton>
{!!data ? <FeesOutput data={data.result}></FeesOutput> : null}
</Stack>
</StartFlexBox>
</CssBaseline>
Expand Down
8 changes: 5 additions & 3 deletions src/server/commands/fees/fees_command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,20 @@ import { readFile } from 'fs';
}
*/
type Args = {
args: types.feesCommand;
args: types.commandFees;
lnd: AuthenticatedLnd;
logger: Logger;
};
const feesCommand = async ({ args, lnd, logger }: Args) => {
const toArray = !!args.to ? args.to.filter((n: string) => !!n) : [];

const result = await adjustFees({
lnd,
logger,
cltv_delta: args.cltv_delta,
cltv_delta: args.cltv_delta || undefined,
fee_rate: args.fee_rate,
fs: { getFile: readFile },
to: args.to || [],
to: toArray,
});

return { result };
Expand Down
2 changes: 1 addition & 1 deletion src/shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export type commandClosed = {
node: string;
};

export type feesCommand = {
export type commandFees = {
cltv_delta: number;
fee_rate: string;
node: string;
Expand Down
28 changes: 28 additions & 0 deletions tests/client/fees.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { expect, test } from '@playwright/test';
import { removeAccessToken, setAccessToken } from '../utils/setAccessToken';

import { testConstants } from '../utils/constants';

test.describe('Test the Fees command client page', async () => {
test.beforeEach(async ({ page }) => {
await setAccessToken({ page });
});

test('test the Fees command page and input values', async ({ page }) => {
await page.goto(testConstants.commandsPage);
await page.click('#Fees');
await expect(page).toHaveTitle('Fees');

await page.type('#node', 'testnode1');

await page.click('text=run command');
await page.waitForTimeout(1000);

await expect(page.locator('#feesOutput')).toBeVisible();
await page.click('text=home');
});

test.afterEach(async ({ page }) => {
await removeAccessToken({ page });
});
});

0 comments on commit b85e179

Please sign in to comment.