Skip to content

Commit

Permalink
Merge branch 'feat/wails-v2' into argon2
Browse files Browse the repository at this point in the history
  • Loading branch information
rolznz committed Feb 1, 2024
2 parents 3ca6b8d + d121ac3 commit 90b7228
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 87 deletions.
55 changes: 44 additions & 11 deletions breez.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ func (BreezListener) OnEvent(e breez_sdk.BreezEvent) {
}

func NewBreezService(mnemonic, apiKey, inviteCode, workDir string) (result LNClient, err error) {
if mnemonic == "" || apiKey == "" || inviteCode == "" || workDir == "" {
return nil, errors.New("One or more required breez configuration are missing")
}

//create dir if not exists
newpath := filepath.Join(".", workDir)
err = os.MkdirAll(newpath, os.ModePerm)
Expand Down Expand Up @@ -181,7 +185,26 @@ func (bs *BreezService) LookupInvoice(ctx context.Context, senderPubkey string,
}

func (bs *BreezService) ListTransactions(ctx context.Context, senderPubkey string, from, until, limit, offset uint64, unpaid bool, invoiceType string) (transactions []Nip47Transaction, err error) {
payments, err := bs.svc.ListPayments(breez_sdk.ListPaymentsRequest{})

request := breez_sdk.ListPaymentsRequest{}
if limit > 0 {
limit32 := uint32(limit)
request.Limit = &limit32
}
if offset > 0 {
offset32 := uint32(offset)
request.Offset = &offset32
}
if from > 0 {
from64 := int64(from)
request.FromTimestamp = &from64
}
if until > 0 {
until64 := int64(until)
request.ToTimestamp = &until64
}

payments, err := bs.svc.ListPayments(request)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -225,15 +248,25 @@ func breezPaymentToTransaction(payment *breez_sdk.Payment) (*Nip47Transaction, e
txType = "incoming"
}

paymentRequest, err := decodepay.Decodepay(strings.ToLower(lnDetails.Data.Bolt11))
if err != nil {
log.Printf("Failed to decode bolt11 invoice: %v", payment)
return nil, err
}
createdAt := payment.PaymentTime
var expiresAt *int64
description := lnDetails.Data.Label
descriptionHash := ""

if lnDetails.Data.Bolt11 != "" {
// TODO: Breez should provide these details so we don't need to manually decode the invoice
paymentRequest, err := decodepay.Decodepay(strings.ToLower(lnDetails.Data.Bolt11))
if err != nil {
log.Printf("Failed to decode bolt11 invoice: %v", payment)
return nil, err
}

createdAt := int64(paymentRequest.CreatedAt)
expiresAtUnix := time.UnixMilli(int64(paymentRequest.CreatedAt) * 1000).Add(time.Duration(paymentRequest.Expiry) * time.Second).Unix()
expiresAt := &expiresAtUnix
createdAt = int64(paymentRequest.CreatedAt)
expiresAtUnix := time.UnixMilli(int64(paymentRequest.CreatedAt) * 1000).Add(time.Duration(paymentRequest.Expiry) * time.Second).Unix()
expiresAt = &expiresAtUnix
description = paymentRequest.Description
descriptionHash = paymentRequest.DescriptionHash
}

tx := &Nip47Transaction{
Type: txType,
Expand All @@ -245,8 +278,8 @@ func breezPaymentToTransaction(payment *breez_sdk.Payment) (*Nip47Transaction, e
CreatedAt: createdAt,
ExpiresAt: expiresAt,
Metadata: nil,
Description: paymentRequest.Description,
DescriptionHash: paymentRequest.DescriptionHash,
Description: description,
DescriptionHash: descriptionHash,
}
if payment.Status == breez_sdk.PaymentStatusComplete {
settledAt := payment.PaymentTime
Expand Down
38 changes: 25 additions & 13 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"

"github.com/getAlby/nostr-wallet-connect/models/db"
"github.com/sirupsen/logrus"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
Expand All @@ -19,6 +20,7 @@ const (
type AppConfig struct {
Relay string `envconfig:"RELAY" default:"wss://relay.getalby.com/v1"`
LNBackendType string `envconfig:"LN_BACKEND_TYPE"`
LNDAddress string `envconfig:"LND_ADDRESS"`
LNDCertFile string `envconfig:"LND_CERT_FILE"`
LNDMacaroonFile string `envconfig:"LND_MACAROON_FILE"`
Workdir string `envconfig:"WORK_DIR" default:".data"`
Expand All @@ -33,31 +35,38 @@ type Config struct {
NostrSecretKey string
NostrPublicKey string
db *gorm.DB
logger *logrus.Logger
}

func (cfg *Config) Init(db *gorm.DB, env *AppConfig) {
func (cfg *Config) Init(db *gorm.DB, env *AppConfig, logger *logrus.Logger) {
cfg.db = db
cfg.Env = env
cfg.logger = logger

if cfg.Env.Relay != "" {
cfg.SetUpdate("Relay", cfg.Env.Relay, "")
}
if cfg.Env.LNBackendType != "" {
cfg.SetUpdate("LNBackendType", cfg.Env.LNBackendType, "")
}
if cfg.Env.LNDAddress != "" {
cfg.SetUpdate("LNDAddress", cfg.Env.LNDAddress, "")
}
if cfg.Env.LNDCertFile != "" {
certBytes, err := os.ReadFile(cfg.Env.LNDCertFile)
if err != nil {
certHex := hex.EncodeToString(certBytes)
cfg.SetUpdate("LNDCertHex", certHex, "")
logger.Fatalf("Failed to read LND cert file: %v", err)
}
certHex := hex.EncodeToString(certBytes)
cfg.SetUpdate("LNDCertHex", certHex, "")
}
if cfg.Env.LNDMacaroonFile != "" {
macBytes, err := os.ReadFile(cfg.Env.LNDMacaroonFile)
if err != nil {
macHex := hex.EncodeToString(macBytes)
cfg.SetUpdate("LNDMacaroonHex", macHex, "")
logger.Fatalf("Failed to read LND macaroon file: %v", err)
}
macHex := hex.EncodeToString(macBytes)
cfg.SetUpdate("LNDMacaroonHex", macHex, "")
}
// set the cookie secret to the one from the env
// if no cookie secret is configured we create a random one and store it in the DB
Expand Down Expand Up @@ -86,33 +95,36 @@ func (cfg *Config) Get(key string, encryptionKey string) (string, error) {
return value, nil
}

func (cfg *Config) set(key string, value string, clauses clause.OnConflict, encryptionKey string) bool {
func (cfg *Config) set(key string, value string, clauses clause.OnConflict, encryptionKey string) {
if encryptionKey != "" {
encrypted, err := AesGcmEncrypt(value, encryptionKey)
if err == nil {
value = encrypted
if err != nil {
cfg.logger.Fatalf("Failed to encrypt: %v", err)
}
value = encrypted
}
userConfig := db.UserConfig{Key: key, Value: value, Encrypted: encryptionKey != ""}
result := cfg.db.Clauses(clauses).Create(&userConfig)

return result.Error == nil
if result.Error != nil {
cfg.logger.Fatalf("Failed to save key to config: %v", result.Error)
}
}

func (cfg *Config) SetIgnore(key string, value string, encryptionKey string) bool {
func (cfg *Config) SetIgnore(key string, value string, encryptionKey string) {
clauses := clause.OnConflict{
Columns: []clause.Column{{Name: "key"}},
DoNothing: true,
}
return cfg.set(key, value, clauses, encryptionKey)
cfg.set(key, value, clauses, encryptionKey)
}

func (cfg *Config) SetUpdate(key string, value string, encryptionKey string) bool {
func (cfg *Config) SetUpdate(key string, value string, encryptionKey string) {
clauses := clause.OnConflict{
Columns: []clause.Column{{Name: "key"}},
DoUpdates: clause.AssignmentColumns([]string{"value"}),
}
return cfg.set(key, value, clauses, encryptionKey)
cfg.set(key, value, clauses, encryptionKey)
}

func randomHex(n int) (string, error) {
Expand Down
1 change: 0 additions & 1 deletion frontend/src/components/redirects/StartRedirect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export function StartRedirect({ children }: React.PropsWithChildren) {
const location = useLocation();
const navigate = useNavigate();

// TODO: re-add login redirect: https://github.com/getAlby/nostr-wallet-connect/commit/59b041886098dda4ff38191e3dd704ec36360673
React.useEffect(() => {
if (!info || (info.setupCompleted && !info.running)) {
return;
Expand Down
4 changes: 4 additions & 0 deletions lnd.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,10 @@ func makePreimageHex() ([]byte, error) {
}

func NewLNDService(svc *Service, lndAddress, lndCertHex, lndMacaroonHex string) (result LNClient, err error) {
if lndAddress == "" || lndCertHex == "" || lndMacaroonHex == "" {
return nil, errors.New("One or more required LND configuration are missing")
}

lndClient, err := lnd.NewLNDclient(lnd.LNDoptions{
Address: lndAddress,
CertHex: lndCertHex,
Expand Down
51 changes: 12 additions & 39 deletions service.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"encoding/json"
"fmt"
"strings"
"sync"
"time"

Expand All @@ -29,13 +28,12 @@ import (

type Service struct {
// config from .env only. Fetch dynamic config from db
cfg *Config
db *gorm.DB
lnClient LNClient
ReceivedEOS bool
Logger *logrus.Logger
ctx context.Context
wg *sync.WaitGroup
cfg *Config
db *gorm.DB
lnClient LNClient
Logger *logrus.Logger
ctx context.Context
wg *sync.WaitGroup
}

// TODO: move to service.go
Expand Down Expand Up @@ -95,7 +93,7 @@ func NewService(ctx context.Context) (*Service, error) {
ctx, _ = signal.NotifyContext(ctx, os.Interrupt)

cfg := &Config{}
cfg.Init(db, appConfig)
cfg.Init(db, appConfig, logger)

var wg sync.WaitGroup
svc := &Service{
Expand Down Expand Up @@ -131,7 +129,6 @@ func (svc *Service) launchLNBackend(encryptionKey string) error {
LNDAddress, _ := svc.cfg.Get("LNDAddress", encryptionKey)
LNDCertHex, _ := svc.cfg.Get("LNDCertHex", encryptionKey)
LNDMacaroonHex, _ := svc.cfg.Get("LNDMacaroonHex", encryptionKey)

lnClient, err = NewLNDService(svc, LNDAddress, LNDCertHex, LNDMacaroonHex)
case lndBackend:
BreezMnemonic, _ := svc.cfg.Get("BreezMnemonic", encryptionKey)
Expand Down Expand Up @@ -165,12 +162,11 @@ func (svc *Service) noticeHandler(notice string) {

func (svc *Service) StartSubscription(ctx context.Context, sub *nostr.Subscription) error {
go func() {
// block till EOS is received
<-sub.EndOfStoredEvents
svc.ReceivedEOS = true
svc.Logger.Info("Received EOS")
}()

go func() {
// loop through incoming events
for event := range sub.Events {
go func(event *nostr.Event) {
resp, err := svc.HandleEvent(ctx, event)
Expand Down Expand Up @@ -255,10 +251,6 @@ func (svc *Service) StartSubscription(ctx context.Context, sub *nostr.Subscripti
}

func (svc *Service) HandleEvent(ctx context.Context, event *nostr.Event) (result *nostr.Event, err error) {
//don't process historical events
if !svc.ReceivedEOS {
return nil, nil
}
svc.Logger.WithFields(logrus.Fields{
"eventId": event.ID,
"eventKind": event.Kind,
Expand Down Expand Up @@ -371,13 +363,9 @@ func (svc *Service) createResponse(initialEvent *nostr.Event, content interface{

func (svc *Service) GetMethods(app *App) []string {
appPermissions := []AppPermission{}
findPermissionsResult := svc.db.Find(&appPermissions, &AppPermission{
svc.db.Find(&appPermissions, &AppPermission{
AppId: app.ID,
})
if findPermissionsResult.RowsAffected == 0 {
// No permissions created for this app. It can do anything
return strings.Split(NIP_47_CAPABILITIES, ",")
}
requestMethods := make([]string, 0, len(appPermissions))
for _, appPermission := range appPermissions {
requestMethods = append(requestMethods, appPermission.RequestMethod)
Expand All @@ -386,24 +374,9 @@ func (svc *Service) GetMethods(app *App) []string {
}

func (svc *Service) hasPermission(app *App, event *nostr.Event, requestMethod string, amount int64) (result bool, code string, message string) {
// find all permissions for the app
appPermissions := []AppPermission{}
findPermissionsResult := svc.db.Find(&appPermissions, &AppPermission{
AppId: app.ID,
})
if findPermissionsResult.RowsAffected == 0 {
// No permissions created for this app. It can do anything
svc.Logger.WithFields(logrus.Fields{
"eventId": event.ID,
"requestMethod": requestMethod,
"appId": app.ID,
"pubkey": app.NostrPubkey,
}).Info("No permissions found for app")
return true, "", ""
}

appPermission := AppPermission{}
findPermissionResult := findPermissionsResult.Limit(1).Find(&appPermission, &AppPermission{
findPermissionResult := svc.db.Find(&appPermission, &AppPermission{
AppId: app.ID,
RequestMethod: requestMethod,
})
if findPermissionResult.RowsAffected == 0 {
Expand Down
30 changes: 7 additions & 23 deletions service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,6 @@ func TestHandleEvent(t *testing.T) {
ctx := context.TODO()
svc, _ := createTestService(t)
defer os.Remove(testDB)
//test not yet receivedEOS
res, err := svc.HandleEvent(ctx, &nostr.Event{
Kind: NIP_47_REQUEST_KIND,
})
assert.Nil(t, res)
assert.Nil(t, err)
//now signal that we are ready to receive events
svc.ReceivedEOS = true

senderPrivkey := nostr.GeneratePrivateKey()
senderPubkey, err := nostr.GetPublicKey(senderPrivkey)
Expand All @@ -166,7 +158,7 @@ func TestHandleEvent(t *testing.T) {
assert.NoError(t, err)
payload, err := nip04.Encrypt(nip47PayJson, ss)
assert.NoError(t, err)
res, err = svc.HandleEvent(ctx, &nostr.Event{
res, err := svc.HandleEvent(ctx, &nostr.Event{
ID: "test_event_1",
Kind: NIP_47_REQUEST_KIND,
PubKey: senderPubkey,
Expand All @@ -185,15 +177,6 @@ func TestHandleEvent(t *testing.T) {
app := App{Name: "test", NostrPubkey: senderPubkey}
err = svc.db.Save(&app).Error
assert.NoError(t, err)
//test old payload
res, err = svc.HandleEvent(ctx, &nostr.Event{
ID: "test_event_2",
Kind: NIP_47_REQUEST_KIND,
PubKey: senderPubkey,
Content: payload,
})
assert.NoError(t, err)
assert.NotNil(t, res)
//test new payload
newPayload, err := nip04.Encrypt(nip47PayJson, ss)
assert.NoError(t, err)
Expand All @@ -212,7 +195,9 @@ func TestHandleEvent(t *testing.T) {
}
err = json.Unmarshal([]byte(decrypted), received)
assert.NoError(t, err)
assert.Equal(t, received.Result.(*Nip47PayResponse).Preimage, "123preimage")
// this app has no permission
assert.Equal(t, received.Error.Code, NIP_47_ERROR_RESTRICTED)

malformedPayload, err := nip04.Encrypt(nip47PayJsonNoInvoice, ss)
assert.NoError(t, err)
res, err = svc.HandleEvent(ctx, &nostr.Event{
Expand Down Expand Up @@ -646,10 +631,9 @@ func createTestService(t *testing.T) (svc *Service, ln LNClient) {
NostrSecretKey: sk,
NostrPublicKey: pk,
},
db: gormDb,
lnClient: ln,
ReceivedEOS: false,
Logger: logger,
db: gormDb,
lnClient: ln,
Logger: logger,
}, ln
}

Expand Down

0 comments on commit 90b7228

Please sign in to comment.