Skip to content

Commit

Permalink
feat: ✨ privacy settings (#37)
Browse files Browse the repository at this point in the history
* feat: ✨ privacy configs

* chore: 🔧 chat polling speed

* refactor: ♻️ chat state

* chore: 🔧 move config to cookie
  • Loading branch information
apotdevin authored May 11, 2020
1 parent ef5c2d1 commit 3d29616
Show file tree
Hide file tree
Showing 53 changed files with 662 additions and 432 deletions.
12 changes: 11 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ module.exports = {
parserOptions: {
ecmaFeatures: { jsx: true },
},
env: {
browser: true,
amd: true,
node: true,
},
plugins: ['react', 'jest', 'import', 'prettier'],
settings: {
react: {
Expand Down Expand Up @@ -37,7 +42,12 @@ module.exports = {
'import/no-unresolved': 'off',
camelcase: 'off',
'@typescript-eslint/camelcase': 'off',
'prettier/prettier': 'error',
'react/prop-types': 'off',
'prettier/prettier': [
'error',
{
endOfLine: 'auto',
},
],
},
};
7 changes: 2 additions & 5 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
}
"editor.formatOnSave": true
}
127 changes: 109 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
# **ThunderHub - Lightning Node Manager**

![Home Screenshot](./docs/Home.png)
![Home Screenshot](/docs/Home.png)
[![license](https://img.shields.io/github/license/DAVFoundation/captain-n3m0.svg?style=flat-square)](https://github.com/DAVFoundation/captain-n3m0/blob/master/LICENSE)

## Table Of Contents

- [Introduction](#introduction)
- [Integrations](#integrations)
- [Features](#features)
- [Installation](#installation)
- [Development](#development)
- [Docker deployment](#docker)

## Introduction

ThunderHub is an **open-source** LND node manager where you can manage and monitor your node on any device or browser. It allows you to take control of the lightning network with a simple and intuitive UX and the most up-to-date tech stack.

### Integrations

**BTCPay Server**
ThunderHub is currently integrated into BTCPay for easier deployment. If you already have a BTCPay server and want to add ThunderHub or even want to start a BTCPay server from zero, be sure to check out this [tutorial](https://apotdevin.com/blog/thunderhub-btcpay)

**Raspiblitz**
For Raspiblitz users you can also get ThunderHub running by following this [gist](https://gist.github.com/openoms/8ba963915c786ce01892f2c9fa2707bc)

### Tech Stack

This repository consists of a **NextJS** server that handles both the backend **Graphql Server** and the frontend **React App**.
This repository consists of a **NextJS** server that handles both the backend **Graphql Server** and the frontend **React App**. ThunderHub connects to your Lightning Network node by using the gRPC ports.

- NextJS
- ReactJS
Expand Down Expand Up @@ -50,7 +60,7 @@ This repository consists of a **NextJS** server that handles both the backend **
- Send and Receive Bitcoin payments.
- Decode lightning payment requests.
- Open and close channels.
- Balance your channels through circular payments. ([Check out the Tutorial](https://medium.com/coinmonks/lightning-network-channel-balancing-with-thunderhub-972b41bf9243))
- Balance your channels through circular payments. ([Check out the Tutorial](https://apotdevin.com/blog/thunderhub-balancing))
- Update your all your channels fees or individual ones.
- Backup, verify and recover all your channels.
- Sign and verify messages.
Expand All @@ -70,54 +80,135 @@ This repository consists of a **NextJS** server that handles both the backend **

### Deployment

- Docker images for easier deployment (WIP)
- Docker images for easier deployment

### Future Features

- Channel health/recommendations view
- Loop In and Out to provide liquidity or remove it from your channels.
- Integration with HodlHodl
- Storefront interface

## **Requirements**

- Yarn/npm installed
- Node installed (Version 12.16.0 or higher)

**Older Versions of Node**
Earlier versions of Node can be used if you replace the following commands:

```js
//Yarn
yarn start -> yarn start:compatible
yarn dev -> yarn dev:compatible

//NPM
npm start -> npm start:compatible
npm run dev -> npm run dev:compatible
```

**HodlHodl integration will not work with older versions of Node!**

## Config

You can define some environment variables that ThunderHub can start with. To do this create a `.env` file in the root directory with the following parameters:

```js
THEME = 'dark' | 'light'; // Default: 'dark'
CURRENCY = 'sat' | 'btc' | 'eur' | 'usd'; // Default: 'sat'
FETCH_PRICES = true | false // Default: true
FETCH_FEES = true | false // Default: true
HODL_KEY='[Key provided by HodlHodl]' //Default: ''
BASE_PATH='[Base path where you want to have thunderhub running i.e. '/btcpay']' //Default: '/'
```

### Fetching prices and fees

ThunderHub fetches fiat prices from [Blockchain.com](https://blockchain.info/ticker)'s api and bitcoin on chain fees from [Earn.com](https://bitcoinfees.earn.com/api/v1/fees/recommended)'s api.

If you want to deactivate these requests you can set `FETCH_PRICES=false` and `FETCH_FEES=false` in your `.env` file or manually change them inside the settings view of ThunderHub.

### Running on different base path

Adding a BASE_PATH will run the ThunderHub server on a different base path.
For example:

- default base path of `/` runs ThunderHub on `http://localhost:3000`
- base path of `/thub` runs ThunderHub on `http://localhost:3000/thub`

To run on a base path, ThunderHub needs to be behind a proxy with the following configuration (NGINX example):

```nginx
location /thub/ {
rewrite ^/thub(.*)$ $1 break;
proxy_pass http://localhost:3000/;
}
```

## Installation

To run ThunderHub you first need to clone this repository.

```javascript
```js
git clone https://github.com/apotdevin/thunderhub.git
```

### **Requirements**
After cloning the repository run `yarn` or `npm install` to get all the necessary modules installed.

- Node installed
- Yarn installed

After cloning the repository run `yarn` to get all the necessary modules installed.

After `yarn` has finished installing all the dependencies you can proceed to build and run the app with the following commands.
After all the dependencies have finished installing, you can proceed to build and run the app with the following commands.

```javascript
//Yarn
yarn build
yarn start

//NPM
npm run build
npm start
```

This will start the server on port 3000, so just head to `localhost:3000` to see the app running.
This will start the server on port 3000, so just go to `localhost:3000` to see the app running.

#### HodlHodl Integration
If you want to specify a different port (for example port `4000`) run with:

To be able to use the HodlHodl integration create a `.env` file in the root folder with `HODL_KEY='[YOUR API KEY]'` and replace `[YOUR API KEY]` with the one that HodlHodl provides you.
```js
// Yarn
yarn start -p 4000

// NPM
npm start -p 4000
```

## Development

If you want to develop on ThunderHub and want hot reloading when you do changes, use the following commands:

```javascript
```js
//Yarn
yarn dev

//NPM
npm run dev
```

#### Storybook

You can also get storybook running for quicker component development.

```javascript
```js
//Yarn
yarn storybook

//NPM
npm run storybook
```

## Docker

ThunderHub also provides docker images for easier deployment. [Docker Hub](https://hub.docker.com/repository/docker/apotdevin/thunderhub)

To get ThunderHub running with docker follow these steps:

1. `docker pull apotdevin/thunderhub:v0.5.5` (Or the latest version you find)
2. `docker run --rm -it -p 3000:3000/tcp apotdevin/thunderhub:v0.5.5`

You can now go to `localhost:3000` to see your running instance of ThunderHub
6 changes: 5 additions & 1 deletion next.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint @typescript-eslint/no-var-requires: 0 */
require('dotenv').config();
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
Expand All @@ -17,6 +18,9 @@ module.exports = withBundleAnalyzer({
apiBaseUrl: `${process.env.API_BASE_URL || ''}/api/v1`,
basePath: process.env.BASE_PATH || '',
npmVersion: process.env.npm_package_version || '0.0.0',
trustNeeded: process.env.TRUST || false,
defaultTheme: process.env.THEME || 'dark',
defaultCurrency: process.env.CURRENCY || 'sat',
fetchPrices: process.env.FETCH_PRICES === 'true' ? true : false,
fetchFees: process.env.FETCH_FEES === 'true' ? true : false,
},
});
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
"main": "index.js",
"scripts": {
"dev": "cross-env NODE_OPTIONS='--insecure-http-parser' next",
"dev:compatible": "next",
"build": "next build",
"start": "cross-env NODE_OPTIONS='--insecure-http-parser' next start",
"start:compatible": "next start",
"lint": "eslint */**/*.{js,ts,tsx} --quiet --fix",
"prettier": "prettier --write **/*.{ts,tsx,js,css,html}",
"release": "standard-version",
Expand All @@ -33,6 +35,7 @@
"apollo-boost": "^0.4.7",
"apollo-server-micro": "^2.12.0",
"base64url": "^3.0.1",
"cookie": "^0.4.1",
"crypto-js": "^4.0.0",
"date-fns": "^2.12.0",
"dotenv": "^8.2.0",
Expand All @@ -42,6 +45,7 @@
"graphql-tag": "^2.10.3",
"intersection-observer": "^0.10.0",
"isomorphic-unfetch": "^3.0.0",
"js-cookie": "^2.2.1",
"ln-service": "^48.0.5",
"lodash.debounce": "^4.0.8",
"lodash.groupby": "^4.6.0",
Expand Down
58 changes: 35 additions & 23 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import App from 'next/app';
import React from 'react';
import * as React from 'react';
import { ContextProvider } from '../src/context/ContextProvider';
import { ThemeProvider } from 'styled-components';
import { useSettings } from '../src/context/SettingsContext';
import { useConfigState, ConfigProvider } from '../src/context/ConfigContext';
import { ModalProvider, BaseModalBackground } from 'styled-react-modal';
import { GlobalStyles } from '../src/styles/GlobalStyle';
import { Header } from '../src/layouts/header/Header';
Expand All @@ -20,11 +19,12 @@ import { PageWrapper, HeaderBodyWrapper } from '../src/layouts/Layout.styled';
import { useStatusState } from '../src/context/StatusContext';
import { ChatFetcher } from '../src/components/chat/ChatFetcher';
import { ChatInit } from '../src/components/chat/ChatInit';
import { parseCookies } from '../src/utils/cookies';

toast.configure({ draggable: false, pauseOnFocusLoss: false });

const Wrapper: React.FC = ({ children }) => {
const { theme } = useSettings();
const { theme } = useConfigState();
const { pathname } = useRouter();
const { connected } = useStatusState();

Expand Down Expand Up @@ -63,24 +63,36 @@ const Wrapper: React.FC = ({ children }) => {
);
};

class MyApp extends App<any> {
render() {
const { Component, pageProps, apollo } = this.props;
return (
<>
<Head>
<title>ThunderHub - Lightning Node Manager</title>
</Head>
<ApolloProvider client={apollo}>
<ContextProvider>
<Wrapper>
<Component {...pageProps} />
</Wrapper>
</ContextProvider>
</ApolloProvider>
</>
);
const App = ({ Component, pageProps, apollo, initialConfig }: any) => (
<>
<Head>
<title>ThunderHub - Lightning Node Manager</title>
</Head>
<ApolloProvider client={apollo}>
<ConfigProvider initialConfig={initialConfig}>
<ContextProvider>
<Wrapper>
<Component {...pageProps} />
</Wrapper>
</ContextProvider>
</ConfigProvider>
</ApolloProvider>
</>
);

App.getInitialProps = async props => {
const cookies = parseCookies(props.ctx.req);
if (!cookies?.config) {
return { initialConfig: {} };
}
try {
const config = JSON.parse(cookies.config);
return {
initialConfig: config,
};
} catch (error) {
return { initialConfig: {} };
}
}
};

export default withApollo(MyApp);
export default withApollo(App);
4 changes: 2 additions & 2 deletions pages/channels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
ColorButton,
} from '../src/components/generic/Styled';
import { useAccount } from '../src/context/AccountContext';
import { useSettings } from '../src/context/SettingsContext';
import { useConfigState } from '../src/context/ConfigContext';
import { textColorMap } from '../src/styles/Themes';
import { useGetChannelAmountInfoQuery } from '../src/generated/graphql';

Expand All @@ -22,7 +22,7 @@ const ChannelView = () => {
closed: 0,
});

const { theme } = useSettings();
const { theme } = useConfigState();
const { auth } = useAccount();

const { data } = useGetChannelAmountInfoQuery({
Expand Down
2 changes: 1 addition & 1 deletion pages/fees.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const FeesView = () => {
? toast.success('Fees Updated')
: toast.error('Error updating fees');
},
refetchQueries: ['GetChannelFees'],
refetchQueries: ['ChannelFees'],
});

if (loading || !data || !data.getChannelFees) {
Expand Down
4 changes: 2 additions & 2 deletions pages/forwards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { getErrorContent } from '../src/utils/error';
import { LoadingCard } from '../src/components/loading/LoadingCard';
import { ForwardCard } from '../src/views/forwards/ForwardsCard';
import { textColorMap } from '../src/styles/Themes';
import { useSettings } from '../src/context/SettingsContext';
import { useConfigState } from '../src/context/ConfigContext';
import { ForwardBox } from '../src/views/home/reports/forwardReport';
import { useGetForwardsQuery } from '../src/generated/graphql';

Expand All @@ -28,7 +28,7 @@ const ForwardsView = () => {
const [time, setTime] = useState('week');
const [indexOpen, setIndexOpen] = useState(0);

const { theme } = useSettings();
const { theme } = useConfigState();
const { auth } = useAccount();

const { loading, data } = useGetForwardsQuery({
Expand Down
Loading

0 comments on commit 3d29616

Please sign in to comment.