Git Product home page Git Product logo

hub's Introduction

Alby Hub

This is a self-sovereign, self-custodial, single-user rewrite of the original Nostr Wallet Connect app. ❗This version is not backwards compatible with the original app - it requires a fresh database and connections to be re-added

This application allows you to control your Lightning node or wallet from any other application that supports NWC. Connect apps like Damus or Amethyst to your node. There are many more available on https://nwc.dev/.

Specification: NIP-47

The application can run in two modes:

  • Wails (Desktop app): Mac (arm64), Windows (amd64), Linux (amd64)
  • HTTP (Web app): Docker, Linux (amd64)

Ideally the app runs 24/7 (on a node, VPS or always-online desktop/laptop machine) so it can be connected to a lightning address and receive online payments.

Supported Backends

  • LND
  • Breez
  • Greenlight
  • LDK
  • Phoenixd
  • Cashu
  • want more? please open an issue.

Installation

Requirements

The application has no runtime dependencies. (simple Go executable).

As data storage SQLite is used.

$ cp .env.example .env
# edit the config for your needs
vim .env

Development

Required Software

  • Go
  • Node
  • NPM
  • Yarn

Server (HTTP mode)

  1. Create a Lightning Polar setup with two LND nodes and uncomment the Polar LND section in your .env file.

  2. Compile the frontend or run touch frontend/dist/tmp to ensure there are embeddable files available.

  3. go run cmd/http/main.go

React Frontend (HTTP mode)

Go to /frontend

  1. yarn install
  2. yarn dev

Wails (Backend + Frontend)

Make sure to have wails installed and all platform-specific dependencies installed (see wails doctor)

$ wails dev -tags "wails"

If you get a blank screen, try running in your normal terminal (outside of vscode, and make sure HTTP frontend is not running)

Wails Production build

$ wails build -tags "wails"

Build and run locally (HTTP mode)

$ mkdir tmp
$ go build -o main cmd/http/main.go
$ cp main tmp
$ cp .env tmp
$ cd tmp
$ ./main

Run dockerfile locally (HTTP mode)

$ docker build . -t nwc-local --progress=plain
$ docker run -v $(pwd)/.data/docker:/data -e WORK_DIR='/data' -p 8080:8080 nwc-local

Testing

$ go test ./...

Test matching regular expression

$ go test ./... -run TestHandleGetInfoEvent

Profiling

The application supports both the Go pprof library and the DataDog profiler.

Go pprof

To enable Go pprof, set the GO_PROFILER_ADDR environment variable to the address you want the profiler to be available on (e.g. localhost:6060).

Now, you should be able to access the pprof web interface at http://localhost:6060/debug/pprof.

You can use the go tool pprof command to collect and inspect the profiling data. For example, to profile the application for 30 seconds and then open the pprof web UI, run:

go tool pprof -http=localhost:8081 -seconds=30 http://localhost:6060/debug/pprof/profile

For more information on the Go pprof library, see the official documentation.

DataDog profiler

To enable the DataDog profiler, set the DD_PROFILER_ENABLED environment variable to true.

Make sure to specify the required DataDog configuration environment variables as well.

For more information refer to:

Versioning

$ go run -ldflags="-X 'github.com/getAlby/hub/version.Tag=v0.6.0'" cmd/http/main.go

Windows

Breez SDK requires gcc to build the Breez bindings. Run choco install mingw and copy the breez SDK bindings file into the root of this directory (from your go installation directory) as per the Breez SDK instructions. ALSO copy the bindings file into the output directory alongside the .exe in order to run it.

Optional configuration parameters

The following configuration options can be set as environment variables or in a .env file

  • NOSTR_PRIVKEY: the private key of this service. Should be a securely randomly generated 32 byte hex string.
  • CLIENT_NOSTR_PUBKEY: if set, this service will only listen to events authored by this public key. You can set this to your own nostr public key.
  • RELAY: default: "wss://relay.getalby.com/v1"
  • JWT_SECRET: a randomly generated secret string. (only needed in http mode)
  • DATABASE_URI: a sqlite filename. Default: $XDG_DATA_HOME/albyhub/nwc.db
  • PORT: the port on which the app should listen on (default: 8080)
  • WORK_DIR: directory to store NWC data files. Default: $XDG_DATA_HOME/albyhub
  • LOG_LEVEL: log level for the application. Higher is more verbose. Default: 4 (info)

Node-specific backend parameters

  • ENABLE_ADVANCED_SETUP: set to false to force a specific backend type (combined with backend parameters below)

LND Backend parameters

Currently only LND can be configured via env. Other node types must be configured via the UI.

To configure via env, the following parameters must be provided:

  • LN_BACKEND_TYPE: LND
  • LND_ADDRESS: the LND gRPC address, eg. localhost:10009 (used with the LND backend)
  • LND_CERT_FILE: the location where LND's tls.cert file can be found (used with the LND backend)
  • LND_MACAROON_FILE: the location where LND's admin.macaroon file can be found (used with the LND backend)

LDK Backend parameters

  • LDK_ESPLORA_SERVER: If using the mainnet (bitcoin) network, Recommended to use your own LDK esplora server (The public blockstream one is very slow and can cause onchain syncing and issues with opening channels)

LDK Network Configuration

Mutinynet
  • MEMPOOL_API=https://mutinynet.com/api
  • LDK_NETWORK=signet
  • LDK_ESPLORA_SERVER=https://mutinynet.com/api
  • LDK_GOSSIP_SOURCE=https://rgs.mutinynet.com/snapshot
Testnet (Not recommended - try Mutinynet)
  • MEMPOOL_API=https://mempool.space/testnet/api
  • LDK_NETWORK=testnet
  • LDK_ESPLORA_SERVER=https://mempool.space/testnet/api
  • LDK_GOSSIP_SOURCE=https://rapidsync.lightningdevkit.org/testnet/snapshot

Phoenixd

See Phoenixd

Alby OAuth

Create an OAuth client at the Alby Developer Portal and set your ALBY_OAUTH_CLIENT_ID and ALBY_OAUTH_CLIENT_SECRET in your .env. If not running locally, you'll also need to change your BASE_URL.

If running the React app locally, OAuth redirects will not work locally if running the react app you will need to manually change the port to 5173. Login in Wails mode is not yet supported

Getting Started with Mutinynet

Follow the steps to integrate Mutinynet with your NWC Next setup:

  1. Configure your environment with the Mutinynet LDK parameters

  2. Proceed as described in the Development section to run the frontend and backend

  3. Navigate to channels/outgoing, copy your On-Chain Address, then visit the Mutinynet Faucet to deposit sats. Ensure the transaction confirms on mempool.space

  4. Your On-chain balance will update under /channels

Opening a channel from Mutinynet

  1. To create a channel, use the Mutinynet Faucet by entering your desired Channel Capacity and Amount to Push

  2. Locate your Node ID. In the Wallet click on the status on the top right "online". This shows the node ID or look in the NWC Next logs. Then input this in the Connection String field on the faucet page to request a Lightning Channel

{"level":"info","msg":"Connected to LDK node","nodeId":"<your node ID>","time":"<timestamp>"}
  1. After the transaction confirms, the new channel will appear in the Channels section

Opening a Channel in NWC Next

  1. From the Channels interface (/channels), select "Open a Channel" and opt for "Custom Channel."

  2. Enter the pubkey of the Faucet Lightning Node (omit host and port details) available on the Mutinynet Faucet page.

  3. Specify a channel capacity greater than 25,000 sats, confirm the action, and return to the Channels page to view your newly established channel.

Application deeplink options

/apps/new deeplink options

Clients can use a deeplink to allow the user to add a new connection. Depending on the client this URL has different query options:

NWC created secret

The default option is that the NWC app creates a secret and the user uses the nostr wallet connect URL string to enable the client application.

Query parameter options
  • name: the name of the client app

Example:

/apps/new?name=myapp

Client created secret

If the client creates the secret the client only needs to share the public key of that secret for authorization. The user authorized that pubkey and no sensitivate data needs to be shared.

Query parameter options for /new
  • name: the name of the client app
  • pubkey: the public key of the client's secret for the user to authorize
  • return_to: (optional) if a return_to URL is provided the user will be redirected to that URL after authorization. The lud16, relay and pubkey query parameters will be added to the URL.
  • expires_at (optional) connection cannot be used after this date. Unix timestamp in seconds.
  • max_amount (optional) maximum amount in sats that can be sent per renewal period
  • budget_renewal (optional) reset the budget at the end of the given budget renewal. Can be never (default), daily, weekly, monthly, yearly
  • request_methods (optional) url encoded, space separated list of request types that you need permission for: pay_invoice (default), get_balance (see NIP47). For example: ..&request_methods=pay_invoice%20get_balance
  • notification_types (optional) url encoded, space separated list of notification types that you need permission for: For example: ..&notification_types=payment_received%20payment_sent
  • isolated (optional) makes an isolated app connection with its own balance and only access to its own transaction list. e.g. &isolated=true. If using this option, you should not pass any custom request methods or notification types, nor set a budget or expiry.

Example:

/apps/new?name=myapp&pubkey=47c5a21...&return_to=https://example.com

Web-flow: client created secret

Web clients can open a new prompt popup to load the authorization page. Once the user has authorized the app connection a nwc:success message is sent to the opening page (using postMessage) to indicate that the connection is authorized. See the initNWC() function in the alby-js-sdk

Example:

import { webln } from "alby-js-sdk";
const nwc = new webln.NWC();
// initNWC opens a prompt with /apps/new?c=myapp&pubkey=xxxx
// the promise resolves once the user has authorized the connection (when the `nwc:success` message is received) and the popup is closed automatically
// the promise rejects if the user cancels by closing the prompt popup
await nwc.initNWC({ name: "myapp" });

Help

If you need help contact [email protected] or reach out on Nostr: npub1getal6ykt05fsz5nqu4uld09nfj3y3qxmv8crys4aeut53unfvlqr80nfm You can also visit the chat of our Community on Telegram.

⚡️Donations

Want to support the work on Alby?

Support the Alby team ⚡️[email protected] You can also contribute to our bounty program: ⚡️[email protected]

NIP-47 Supported Methods

✅ NIP-47 info event

expiration tag in requests

LND

get_info

get_balance

pay_invoice

  • ⚠️ amount not supported (for amountless invoices)
  • ⚠️ PAYMENT_FAILED error code not supported

pay_keysend

  • ⚠️ PAYMENT_FAILED error code not supported

make_invoice

lookup_invoice

  • ⚠️ NOT_FOUND error code not supported

list_transactions

  • ⚠️ from and until in request not supported
  • ⚠️ failed payments will not be returned

multi_pay_invoice

  • ⚠️ amount not supported (for amountless invoices)
  • ⚠️ PAYMENT_FAILED error code not supported

multi_pay_keysend

  • ⚠️ PAYMENT_FAILED error code not supported

Breez

(Supported methods coming soon)

Node Distributions

Run NWC on your own node!

NOTE: the below links are for the original version of NWC

Deploy it yourself

From the release

Quick start (Linux)

Go to the Quick start script which you can run as a service.

Manual (Linux)

Download and run the executable.

Have a look at the configuration options

wget https://getalby.com/install/hub/server-linux-x86_64.tar.bz2
tar -xvjf server-linux-x86_64.tar.bz2

# run Alby Hub and done!
./bin/albyhub

Fly.io

Make sure to have the fly command line tools installed

wget https://getalby.com/install/hub/fly.toml
fly launch
fly apps open

Or manually:

  • update app = 'nwc' on line 6 to a unique name in fly.toml e.g. app = 'nwc-john-doe-1234'
  • run fly launch
    • press 'y' to copy configuration to the new app and then hit enter
    • press 'n' to tweak the settings and then hit enter
    • wait for the deployment to succeed, it should give you a URL like https://nwc-john-doe-1234.fly.dev

Update Fly App

  • run fly deploy

View logs

Main application logs

  • fly logs

LDK logs:

  • fly machine exec "tail -100 data/ldk/logs/ldk_node_latest.log"

Docker

From Alby's Container Registry

Tested on Linux only

docker run -v ~/.local/share/albyhub:/data -e WORK_DIR='/data' -p 8080:8080 ghcr.io/getalby/hub:latest

Build the image locally

docker run -v ~/.local/share/albyhub:/data -e WORK_DIR='/data' -p 8080:8080 $(docker build -q .)

Docker Compose

In this repository. Or manually download the docker-compose.yml file and then run:

docker compose up

From source

  • install go (e.g. using snap)
  • install build-essential
  • install yarn
  • run (cd frontend && yarn install
  • run (cd frontend && yarn build:http)
  • run go run cmd/http/main.go

Render.com

Deploy to Render

hub's People

Contributors

anishyadavv avatar believethehype avatar benthecarman avatar bitkarrot avatar bumi avatar dependabot[bot] avatar fishcakeday avatar frnandu avatar im-adithya avatar itstomekk avatar jankoegel avatar jsahagun91 avatar kiwiidb avatar mattn avatar moritzka avatar pavanjoshi914 avatar r3drun3 avatar rdmitr avatar reneaaron avatar rolznz avatar stackingsaunter avatar vuittont60 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

hub's Issues

Use JSON logging

Many places in the code we log with %v. These should be changed to use .WithFields(logrus.Fields{"field1", value1})

Greenlight: close channel

we need to be able to close channels to redeem onchain funds

This needs to be implemented in glalby first, and then we can consume them in nwc through glalby-go

Cannot setup new LDK node if ldk directory already exists

Storage is saved for the current LDK node and cannot be used with a different mnemonic. Either the old ldk folder needs to be removed, or we could generate a folder name based off a short hash of the mnemonic

Ideally eventually we manage all storage in one place for easier backup/restore.

Add extra API endpoints to make it easier to debug things

I would like to do things as a developer for things that are not already exposed in the UI without creating a complex UI such as:

  • probing routes without paying (SendPaymentProbes and SendSpontaneousPaymentProbes)
  • list peers
  • retrieve last 1000 lines of logs from the app TBC
  • retrieve last 1000 lines of logs from the LDK node TBC

These should be implemented the same way as our current http endpoints (like to list channels or get the onchain balance)

The UI should be as minimal as possible (or non-existent if we could e.g. do it through browser devtools - would need to confirm that works in Wails mode)

We only need to expose functions that are not already exposed (e.g. ListChannels already exists - we just need to update it to return all channel info and then we can inspect the response in the network tab) TBC: this will not work in Wails mode

(TBC) Add NIP-47 Supported Methods for Breez

In the README we should show support for each connector.

Currently Breez is experimental - this is only worth doing if we are able to enable Breez for a large number of users.

Edit permissions

Currently it is not possible to edit and update the permissions after a connection is created.

It should be possible to update the budget.

I am not sure about changing the features because that might break the app?

Add a way to reset the LDK router

Sometimes the LDK router gets stuck and we want to reset it as a last resort.

Consume getAlby/ldk-node#10 and put a button to execute the function on a very simple settings page (don't worry about styling or linking to the page from anywhere for now)

Add call to sign messages

For some use cases we need the signMessage call (like in webln)
It should be possible to pass an arbitrary message which is then signed by the node's key.

this should be exposed through NWC similar to the other handle_* calls.

Add a way to change password

All user config keys need to be decrypted with the previous unlock password and updated with the new lock password

Design UI/UX for handling channel closures

Apart from sending a notification to the user, we should also have some UI shown to the user next time they visit Alby Hub.

  • What happened - which channel was closed? was it a force close?
  • That your funds will be redeemed to onchain (are they redeemed yet or still pending?)
  • What to do now? open a new channel?

Migrate funds from LNDHub account

As per https://www.figma.com/file/LWaf8UXzxJoup53LLzc4Na/NWC-flow?type=whiteboard&node-id=1-1150&t=7zfArGZYS2jc7LX9-0

  1. Alby passes credentials to NWC as part of the link when the user is redirected to the hosted NWC instance OR NWC does a standard OAuth flow in the app.
  2. Check if the user has enough funds to migrate. If not, take them to the standard new channel wizard
  3. Show details and fees about channel to be opened, with a button to open the channel
  4. (optional) waiting for the first channel (not needed with 0-conf channels)
  5. Success page

This flow requires opening the channel via lightning invoice - need to make a decision on what we support from: Alby-specific node, 0-conf LSP options, buy liquidity with Deezy?

Don't die on invalid input

currently NWC crashes when an invalid input is sent (e.g. an invalid invoice)

this should be handled gracefully with a proper error reply

2024-02-17T13:53:04.401 app[0806274c635638] ams [info] panic: runtime error: slice bounds out of range [:-1]

2024-02-17T13:53:04.401 app[0806274c635638] ams [info] goroutine 19415 [running]:

2024-02-17T13:53:04.401 app[0806274c635638] ams [info] github.com/nbd-wtf/ln-decodepay.Decodepay({0xc0009b5320, 0x3})

2024-02-17T13:53:04.401 app[0806274c635638] ams [info] /go/pkg/mod/github.com/nbd-wtf/[email protected]/decodepay.go:20 +0xb1a

2024-02-17T13:53:04.402 app[0806274c635638] ams [info] main.(*Service).HandlePayInvoiceEvent(0xc0003cc340, {0x177c578, 0xc00034bb00}, 0xc000cd0ff0, 0xc000122b60, 0xc0000dbb20)

2024-02-17T13:53:04.402 app[0806274c635638] ams [info] /build/handle_payment_request.go:29 +0x2de

2024-02-17T13:53:04.402 app[0806274c635638] ams [info] main.(*Service).HandleEvent(0xc0003cc340, {0x177c578?, 0xc00034bb00}, 0xc0004f4510, 0xc0001e3e88)

2024-02-17T13:53:04.402 app[0806274c635638] ams [info] /build/service.go:480 +0x2472

2024-02-17T13:53:04.402 app[0806274c635638] ams [info] created by main.(*Service).StartSubscription.func1 in goroutine 18916

2024-02-17T13:53:04.403 app[0806274c635638] ams [info] /build/service.go:175 +0xaf 

Expand balance HTTP endpoint

balances are complex :) we have:

  • pending onchain balance
  • confirmed onchain balance
  • lightning balance
    • sendable amount
    • receivable amount

Similar to the get onchain balance endpoint we should have a balance endpoint that returns the different balances.

In the first step we can add the total onchain balance and the spendable onchain balance to the existing endpoint.

Logger issues: LND and Breez

Use Logger consistently in LND, currently only few methods use it.

Add Logger to BreezService, we only use a logger for the listener but not in the methods.

Move code out of root folder into separate packages

There are limitations with the current structure:

  • unable to have separate entry points in a cmd folder (so we use build tags)
  • unable to put tests in a separate package because they use code from the root folder
  • everything is highly coupled with the service object

Use more standard data directory for wails

We should use the OS-provided user profile data directory rather than a .data file in the directory where the app is run (which is problematic when updating / running from a different location etc)

Add healthcheck endpoint

The healthcheck should report if the nwc wallet is fully functioning and can be used internally (on the NWC UI) to show the status in the UI and externally to monitor the app.

  • connected to the relay
  • relay responds to some message
  • node is running
  • node can probe a route

Make a decision on primary node type

It is inefficient to manage all node types - we need to choose one and make the best experience around it. Fork the current code at this point so we can keep a reference and possibly re-add node types in the future when we have more bandwidth.

To confirm: we still support LND node type since it is easiest for users running their own Start9/Umbrel to run NWC.

Implement backup

Currently the user has no option to "download" backup of the connections and the wallet data.
We should allow the user to download a dump of the SQLite database.

Fix dark mode

Priority: Very low

Some components are using #000000 or don't have dark classes at all. Have to fix those.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.