Skip to content

Commit

Permalink
Merge pull request #223 from getAlby/feat/multi-entry
Browse files Browse the repository at this point in the history
Feat: multi entry
  • Loading branch information
rolznz authored Jan 19, 2024
2 parents 61b6dd4 + 73c4b75 commit 113dad0
Show file tree
Hide file tree
Showing 11 changed files with 132 additions and 97 deletions.
5 changes: 3 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"[go]": {
"editor.defaultFormatter": "golang.go"
},
"editor.formatOnSave": true
}
"editor.formatOnSave": true,
"go.buildTags": "http,wails"
}
31 changes: 14 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ Connect applications like [Damus](https://damus.io/) or [Amethyst](https://linkt

## Supported Backends

- [Alby](https://getalby.com) (see: alby.go)
- LND (see: lnd.go)
- Breez (see: breez.go)
- want more? please open an issue.

## Installation
Expand All @@ -27,35 +27,32 @@ To get a new random Nostr key use `openssl rand -hex 32` or similar.

## Development

### Server (LND)
### 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 .` or `gow -e=go,mod,html,css run .` using [gow](https://github.com/mitranim/gow)
3. `go run .`

### Server (Alby Wallet API)

Generate a new OAuth client for <http://localhost:8080> from the [Alby developer portal](https://getalby.com/developer) and set `ALBY_CLIENT_ID` and `ALBY_CLIENT_SECRET` in your .env file.

### React Frontend (LND)
### React Frontend (HTTP mode)

Go to `/frontend`

1. `cp .env.example .env.local`
2. `yarn install`
3. `yarn dev`
1. `yarn install`
2. `yarn dev`

### React Frontend (Alby Wallet API)
### Wails (Backend + Frontend)

Follow standard LND instructions. After logging in, you will be redirected to the wrong port (8080), so manually re-open <http://localhost:5173>.
`unset GTK_PATH && wails dev -tags "wails"`

### Wails (Backend + Frontend)
_If you get a blank screen the first load, close the window and start the app again_

#### Wails Production build

`unset GTK_PATH && wails dev`
`wails build -tags "wails"`

### Build and run locally
### Build and run locally (HTTP mode)

`mkdir tmp`
`go build -o main`
Expand All @@ -64,7 +61,7 @@ Follow standard LND instructions. After logging in, you will be redirected to th
`cd tmp`
`./main`

### Run dockerfile locally
### Run dockerfile locally (HTTP mode)

`docker build . -t nwc-local`

Expand Down
6 changes: 1 addition & 5 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,18 @@ const (
LNDBackendType = "LND"
BreezBackendType = "BREEZ"
CookieName = "alby_nwc_session"

WailsAppType = "WAILS"
HttpAppType = "HTTP"
)

type Config struct {
// These config can be set either by .env or the database config table.
// database config always takes preference.
db.Config
NostrSecretKey string `envconfig:"NOSTR_PRIVKEY"`
CookieSecret string `envconfig:"COOKIE_SECRET" required:"true"`
CookieSecret string `envconfig:"COOKIE_SECRET"`
CookieDomain string `envconfig:"COOKIE_DOMAIN"`
ClientPubkey string `envconfig:"CLIENT_NOSTR_PUBKEY"`
Relay string `envconfig:"RELAY" default:"wss://relay.getalby.com/v1"`
PublicRelay string `envconfig:"PUBLIC_RELAY"`
AppType string `envconfig:"APP_TYPE" default:"HTTP"`
LNDCertFile string `envconfig:"LND_CERT_FILE"`
LNDMacaroonFile string `envconfig:"LND_MACAROON_FILE"`
BreezWorkdir string `envconfig:"BREEZ_WORK_DIR" default:".breez"`
Expand Down
2 changes: 0 additions & 2 deletions frontend/.env.example

This file was deleted.

2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
"type": "module",
"scripts": {
"dev": "vite",
"dev:wails": "VITE_NWC_APP_TYPE=WAILS vite",
"build": "tsc && vite build",
"build:wails": "tsc && VITE_NWC_APP_TYPE=WAILS vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
Expand Down
7 changes: 3 additions & 4 deletions frontend/src/utils/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ export const request = async <T>(
...args: Parameters<typeof fetch>
): Promise<T | undefined> => {
try {
const appType = import.meta.env.VITE_NWC_APP_TYPE || "HTTP";
// TODO: can we use a different request file at build time so no conditional / env variable is needed?
switch (import.meta.env.VITE_APP_TYPE) {
switch (appType) {
case "WAILS": {
const res = await WailsRequestRouter(
args[0].toString(),
Expand Down Expand Up @@ -43,9 +44,7 @@ export const request = async <T>(
return body;
}
default:
throw new Error(
"Unsupported app type: " + import.meta.env.VITE_APP_TYPE
);
throw new Error("Unsupported app type: " + appType);
}
} catch (error) {
console.error("Failed to fetch", error);
Expand Down
87 changes: 24 additions & 63 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,17 @@ import (
"context"
"database/sql"
"errors"
"fmt"
"net/http"
"os"
"os/signal"
"strings"
"sync"
"time"

echologrus "github.com/davrux/echo-logrus/v4"
"github.com/getAlby/nostr-wallet-connect/migrations"
"github.com/getAlby/nostr-wallet-connect/models/db"
"github.com/glebarez/sqlite"
"github.com/joho/godotenv"
"github.com/kelseyhightower/envconfig"
"github.com/labstack/echo/v4"
"github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip19"
log "github.com/sirupsen/logrus"
Expand All @@ -31,8 +27,8 @@ import (
gormtrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/gorm.io/gorm.v1"
)

func main() {

// TODO: move to service.go
func NewService(ctx context.Context) *Service {
// Load config from environment variables / .env file
godotenv.Load(".env")
cfg := &Config{}
Expand Down Expand Up @@ -122,13 +118,16 @@ func main() {
}

log.Infof("Starting nostr-wallet-connect. npub: %s hex: %s", npub, identityPubkey)
ctx := context.Background()
ctx, _ = signal.NotifyContext(ctx, os.Interrupt)

var wg sync.WaitGroup
wg.Add(1)

svc := &Service{
cfg: cfg,
db: db,
ctx: ctx,
wg: &wg,
}

err = svc.setupDbConfig()
Expand All @@ -148,59 +147,10 @@ func main() {
logger.SetLevel(log.InfoLevel)
svc.Logger = logger

var wg sync.WaitGroup
wg.Add(1)
// TODO: can we move these into two separate entrypoint files?
switch cfg.AppType {
case WailsAppType:
err := svc.launchLNBackend()
if err != nil {
// LN backend not needed immediately, just log errors
svc.Logger.Warnf("Failed to launch LN backend: %v", err)
}
go func() {
app := NewApp(svc)
LaunchWailsApp(app)
wg.Done()
svc.Logger.Info("Wails app exited")
}()
case HttpAppType:
// using echo
echologrus.Logger = logger
e := echo.New()

// Alby backend only supported in HTTP app type
if svc.cfg.LNBackendType == AlbyBackendType {
oauthService, err := NewAlbyOauthService(svc, e)
if err != nil {
svc.Logger.Fatal(err)
}
svc.lnClient = oauthService
} else {
err := svc.launchLNBackend()
if err != nil {
// LN backend not needed immediately, just log errors
svc.Logger.Warnf("Failed to launch LN backend: %v", err)
}
}

//register shared routes
svc.RegisterSharedRoutes(e)
//start Echo server
go func() {
if err := e.Start(fmt.Sprintf(":%v", svc.cfg.Port)); err != nil && err != http.ErrServerClosed {
e.Logger.Fatal("shutting down the server")
}
//handle graceful shutdown
<-ctx.Done()
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
e.Shutdown(ctx)
svc.Logger.Info("Echo server exited")
wg.Done()
}()
default:
svc.Logger.Fatalf("Unknown app type: %s", cfg.AppType)
err = svc.launchLNBackend()
if err != nil {
// LN backend not needed immediately, just log errors
svc.Logger.Warnf("Failed to launch LN backend: %v", err)
}

go func() {
Expand All @@ -209,7 +159,9 @@ func main() {

relay, err := nostr.RelayConnect(ctx, cfg.Relay, nostr.WithNoticeHandler(svc.noticeHandler))
if err != nil {
svc.Logger.Fatal(err)
svc.Logger.Errorf("Failed to connect to relay: %v", err)
wg.Done()
return
}

//publish event with NIP-47 info
Expand Down Expand Up @@ -239,14 +191,23 @@ func main() {
//err being nil means that the context was canceled and we should exit the program.
break
}
svc.Logger.Info("Disconnecting from relay...")
err = relay.Close()
if err != nil {
svc.Logger.Error(err)
}
svc.Logger.Info("Graceful shutdown completed. Goodbye.")
if svc.lnClient != nil {
svc.Logger.Info("Shutting down LN backend...")
err = svc.lnClient.Shutdown()
if err != nil {
svc.Logger.Error(err)
}
}
svc.Logger.Info("Relay subroutine ended")
wg.Done()
}()
wg.Wait()

return svc
}

func (svc *Service) setupDbConfig() error {
Expand Down
51 changes: 51 additions & 0 deletions main_http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//go:build !wails || http
// +build !wails http

// (http tag above is simply to fix go language server issue and is not needed to build the app)

package main

import (
"context"
"fmt"
"net/http"
"time"

echologrus "github.com/davrux/echo-logrus/v4"
"github.com/labstack/echo/v4"
log "github.com/sirupsen/logrus"
)

// ignore this warning: we use build tags
// this function will only be executed if no wails tag is set
func main() {
log.Info("NWC Starting in HTTP mode")
ctx := context.Background()
svc := NewService(ctx)

if svc.cfg.CookieSecret == "" {
svc.Logger.Fatalf("required key COOKIE_SECRET missing value")
}

echologrus.Logger = svc.Logger
e := echo.New()

//register shared routes
svc.RegisterSharedRoutes(e)
//start Echo server
go func() {
if err := e.Start(fmt.Sprintf(":%v", svc.cfg.Port)); err != nil && err != http.ErrServerClosed {
e.Logger.Fatalf("shutting down the server: %v", err)
}
}()
//handle graceful shutdown
<-svc.ctx.Done()
svc.Logger.Infof("Shutting down echo server...")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
e.Shutdown(ctx)
svc.Logger.Info("Echo server exited")
svc.Logger.Info("Waiting for service to exit...")
svc.wg.Wait()
svc.Logger.Info("Service exited")
}
29 changes: 29 additions & 0 deletions main_wails.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//go:build wails
// +build wails

package main

import (
"context"

log "github.com/sirupsen/logrus"
)

// ignore this warning: we use build tags
// this function will only be executed if the wails tag is set
func main() {
log.Info("NWC Starting in WAILS mode")
ctx, cancel := context.WithCancel(context.Background())
svc := NewService(ctx)

app := NewApp(svc)
LaunchWailsApp(app)
svc.Logger.Info("Wails app exited")

svc.Logger.Info("Cancelling service context...")
// cancel the service context
cancel()
svc.Logger.Info("Waiting for service to exit...")
svc.wg.Wait()
svc.Logger.Info("Service exited")
}
Loading

0 comments on commit 113dad0

Please sign in to comment.