Skip to content

Commit

Permalink
feat(appwalletKey): add GetBIP32ChildKey
Browse files Browse the repository at this point in the history
  • Loading branch information
frnandu committed Oct 14, 2024
1 parent c3deb33 commit 83de003
Show file tree
Hide file tree
Showing 12 changed files with 135 additions and 24 deletions.
15 changes: 13 additions & 2 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api

import (
"context"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -29,6 +30,7 @@ import (
"github.com/getAlby/hub/service/keys"
"github.com/getAlby/hub/utils"
"github.com/getAlby/hub/version"
"github.com/nbd-wtf/go-nostr"
)

type api struct {
Expand Down Expand Up @@ -98,12 +100,21 @@ func (api *api) CreateApp(createAppRequest *CreateAppRequest) (*CreateAppRespons
return nil, err
}

appWalletKey, err := api.keys.GetBIP32ChildKey(uint32(app.ID))
if err != nil {
fmt.Println("error creating child key: ", err)
return nil, err
}
fmt.Println("!+!+!+!+!+!+!+ app secret key: ", hex.EncodeToString(appWalletKey.Serialize()))
appWalletPubKey, _ := nostr.GetPublicKey(hex.EncodeToString(appWalletKey.Serialize()))
fmt.Println("!+!+!+!+!+!+!+ app public key: ", appWalletPubKey)

if createAppRequest.ReturnTo != "" {
returnToUrl, err := url.Parse(createAppRequest.ReturnTo)
if err == nil {
query := returnToUrl.Query()
query.Add("relay", relayUrl)
query.Add("pubkey", api.keys.GetNostrPublicKey())
query.Add("pubkey", appWalletPubKey)
if lightningAddress != "" && !app.Isolated {
query.Add("lud16", lightningAddress)
}
Expand All @@ -116,7 +127,7 @@ func (api *api) CreateApp(createAppRequest *CreateAppRequest) (*CreateAppRespons
if lightningAddress != "" && !app.Isolated {
lud16 = fmt.Sprintf("&lud16=%s", lightningAddress)
}
responseBody.PairingUri = fmt.Sprintf("nostr+walletconnect://%s?relay=%s&secret=%s%s", api.keys.GetNostrPublicKey(), relayUrl, pairingSecretKey, lud16)
responseBody.PairingUri = fmt.Sprintf("nostr+walletconnect://%s?relay=%s&secret=%s%s", appWalletPubKey, relayUrl, pairingSecretKey, lud16)
return responseBody, nil
}

Expand Down
2 changes: 1 addition & 1 deletion db/db_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (svc *dbService) CreateApp(name string, pubkey string, maxAmountSat uint64,
}
}

app := App{Name: name, NostrPubkey: pairingPublicKey, Isolated: isolated, Metadata: datatypes.JSON(metadataBytes)}
app := App{Name: name, NostrPubkey: pairingPublicKey, walletChildIdx: 2, Isolated: isolated, Metadata: datatypes.JSON(metadataBytes)}

err := svc.db.Transaction(func(tx *gorm.DB) error {
err := tx.Save(&app).Error
Expand Down
26 changes: 26 additions & 0 deletions db/migrations/202410141503_wallet_child_idx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package migrations

import (
_ "embed"

"github.com/go-gormigrate/gormigrate/v2"
"gorm.io/gorm"
)

var _202410141503_wallet_child_idx = &gormigrate.Migration{
ID: "202410141503_wallet_child_idx",
Migrate: func(tx *gorm.DB) error {

if err := tx.Exec(`
ALTER TABLE apps ADD COLUMN wallet_child_idx INTEGER;
CREATE UNIQUE INDEX idx_wallet_child_idx ON apps (wallet_child_idx);
`).Error; err != nil {
return err
}

return nil
},
Rollback: func(tx *gorm.DB) error {
return nil
},
}
1 change: 1 addition & 0 deletions db/migrations/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func Migrate(gormDB *gorm.DB) error {
_202408061737_add_boostagrams_and_use_json,
_202408191242_transaction_failure_reason,
_202408291715_app_metadata,
_202410141503_wallet_child_idx,
})

return m.Migrate()
Expand Down
17 changes: 9 additions & 8 deletions db/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ type UserConfig struct {
}

type App struct {
ID uint
Name string `validate:"required"`
Description string
NostrPubkey string `validate:"required"`
CreatedAt time.Time
UpdatedAt time.Time
Isolated bool
Metadata datatypes.JSON
ID uint
Name string `validate:"required"`
Description string
NostrPubkey string `validate:"required"`
walletChildIdx uint `validate:"required"`
CreatedAt time.Time
UpdatedAt time.Time
Isolated bool
Metadata datatypes.JSON
}

type AppPermission struct {
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ require (
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/DataDog/datadog-go/v5 v5.3.0 // indirect
github.com/DataDog/gostackparse v0.7.0 // indirect
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
Expand Down Expand Up @@ -168,6 +170,7 @@ require (
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tkrajina/go-reflector v0.5.6 // indirect
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 // indirect
github.com/tyler-smith/go-bip32 v1.0.0 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ github.com/DataDog/gostackparse v0.7.0 h1:i7dLkXHvYzHV308hnkvVGDL3BR4FWl7IsXNPz/
github.com/DataDog/gostackparse v0.7.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM=
github.com/DataDog/sketches-go v1.4.5 h1:ki7VfeNz7IcNafq7yI/j5U/YCkO3LJiMDtXz9OMQbyE=
github.com/DataDog/sketches-go v1.4.5/go.mod h1:7Y8GN8Jf66DLyDhc94zuWA3uHEt/7ttt8jHOBWWrSOg=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e h1:ahyvB3q25YnZWly5Gq1ekg6jcmWaGj/vG/MhF4aisoc=
github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:kGUqhHd//musdITWjFvNTHn90WG9bMLBEPQZ17Cmlpw=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec h1:1Qb69mGp/UtRPn422BH4/Y4Q3SLUrD9KHuDkm8iodFc=
github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec/go.mod h1:CD8UlnlLDiqb36L110uqiP2iSflVjx9g/3U9hCI4q2U=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
Expand Down Expand Up @@ -106,6 +110,7 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cmars/basen v0.0.0-20150613233007-fe3947df716e/go.mod h1:P13beTBKr5Q18lJe1rIoLUqjM+CB1zYrRg44ZqGuQSA=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
Expand Down Expand Up @@ -601,6 +606,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.1.5-0.20170601210322-f6abca593680/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
Expand Down Expand Up @@ -634,6 +640,8 @@ github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQ
github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk=
github.com/tyler-smith/go-bip32 v1.0.0 h1:sDR9juArbUgX+bO/iblgZnMPeWY1KZMUC2AFUJdv5KE=
github.com/tyler-smith/go-bip32 v1.0.0/go.mod h1:onot+eHknzV4BVPwrzqY5OoVpyCvnwD7lMawL5aQupE=
github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
Expand Down Expand Up @@ -720,6 +728,7 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/crypto v0.0.0-20170613210332-850760c427c5/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
Expand Down Expand Up @@ -947,6 +956,7 @@ gotest.tools/v3 v3.3.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM=
modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk=
modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA=
Expand Down
30 changes: 22 additions & 8 deletions nip47/event_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package nip47

import (
"context"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -75,7 +76,7 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
Message: fmt.Sprintf("Failed to save nostr event: %s", err.Error()),
},
}
resp, err := svc.CreateResponse(event, nip47Response, nostr.Tags{}, ss)
resp, err := svc.CreateResponse(event, nip47Response, nostr.Tags{}, ss, svc.keys.GetNostrSecretKey())
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"requestEventNostrId": event.ID,
Expand All @@ -87,9 +88,11 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
}

app := db.App{}

err = svc.db.First(&app, &db.App{
NostrPubkey: event.PubKey,
}).Error

if err != nil {
logger.Logger.WithFields(logrus.Fields{
"nostrPubkey": event.PubKey,
Expand All @@ -101,7 +104,7 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
Message: "The public key does not have a wallet connected.",
},
}
resp, err := svc.CreateResponse(event, nip47Response, nostr.Tags{}, ss)
resp, err := svc.CreateResponse(event, nip47Response, nostr.Tags{}, ss, appWalletPrivKey)

Check failure on line 107 in nip47/event_handler.go

View workflow job for this annotation

GitHub Actions / build

undefined: appWalletPrivKey

Check failure on line 107 in nip47/event_handler.go

View workflow job for this annotation

GitHub Actions / build (x86_64, linux-amd64, x86_64-unknown-linux-gnu, ubuntu-20.04)

undefined: appWalletPrivKey

Check failure on line 107 in nip47/event_handler.go

View workflow job for this annotation

GitHub Actions / build (armv6, arm-unknown-linux-gnueabihf, ubuntu-20.04)

undefined: appWalletPrivKey

Check failure on line 107 in nip47/event_handler.go

View workflow job for this annotation

GitHub Actions / build (aarch64, linux-aarch64, aarch64-unknown-linux-gnu, ubuntu-20.04)

undefined: appWalletPrivKey
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"requestEventNostrId": event.ID,
Expand Down Expand Up @@ -133,7 +136,7 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
Message: fmt.Sprintf("Failed to save app to nostr event: %s", err.Error()),
},
}
resp, err := svc.CreateResponse(event, nip47Response, nostr.Tags{}, ss)
resp, err := svc.CreateResponse(event, nip47Response, nostr.Tags{}, ss, svc.keys.GetNostrSecretKey())
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"requestEventNostrId": event.ID,
Expand All @@ -159,8 +162,17 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
"appId": app.ID,
}).Debug("App found for nostr event")

appWalletPrivKeyBip32, err := svc.keys.GetBIP32ChildKey(uint32(app.ID))
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"appId": app.ID,
}).WithError(err).Error("error deriving child key")
return
}
appWalletPrivKey, _ := nostr.GetPublicKey(hex.EncodeToString(appWalletPrivKeyBip32.Serialize()))

//to be extra safe, decrypt using the key found from the app
ss, err = nip04.ComputeSharedSecret(app.NostrPubkey, svc.keys.GetNostrSecretKey())
ss, err = nip04.ComputeSharedSecret(app.NostrPubkey, appWalletPrivKey)
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"requestEventNostrId": event.ID,
Expand Down Expand Up @@ -225,7 +237,7 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
// TODO: replace with a channel
// TODO: update all previous occurences of svc.publishResponseEvent to also use the channel
publishResponse := func(nip47Response *models.Response, tags nostr.Tags) {
resp, err := svc.CreateResponse(event, nip47Response, tags, ss)
resp, err := svc.CreateResponse(event, nip47Response, tags, ss, appWalletPrivKey)
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"requestEventNostrId": event.ID,
Expand Down Expand Up @@ -356,7 +368,7 @@ func (svc *nip47Service) HandleEvent(ctx context.Context, relay nostrmodels.Rela
}
}

func (svc *nip47Service) CreateResponse(initialEvent *nostr.Event, content interface{}, tags nostr.Tags, ss []byte) (result *nostr.Event, err error) {
func (svc *nip47Service) CreateResponse(initialEvent *nostr.Event, content interface{}, tags nostr.Tags, ss []byte, walletPrivKey string) (result *nostr.Event, err error) {
payloadBytes, err := json.Marshal(content)
if err != nil {
return nil, err
Expand All @@ -369,14 +381,16 @@ func (svc *nip47Service) CreateResponse(initialEvent *nostr.Event, content inter
allTags := nostr.Tags{[]string{"p", initialEvent.PubKey}, []string{"e", initialEvent.ID}}
allTags = append(allTags, tags...)

appWalletPubKey, _ := nostr.GetPublicKey(walletPrivKey)

resp := &nostr.Event{
PubKey: svc.keys.GetNostrPublicKey(),
PubKey: appWalletPubKey,
CreatedAt: nostr.Now(),
Kind: models.RESPONSE_KIND,
Tags: allTags,
Content: msg,
}
err = resp.Sign(svc.keys.GetNostrSecretKey())
err = resp.Sign(walletPrivKey)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion nip47/event_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func TestCreateResponse(t *testing.T) {

nip47svc := NewNip47Service(svc.DB, svc.Cfg, svc.Keys, svc.EventPublisher)

res, err := nip47svc.CreateResponse(reqEvent, nip47Response, nostr.Tags{}, ss)
res, err := nip47svc.CreateResponse(reqEvent, nip47Response, nostr.Tags{}, ss, svc.Keys.GetNostrSecretKey())
assert.NoError(t, err)
assert.Equal(t, reqPubkey, res.Tags.GetFirst([]string{"p"}).Value())
assert.Equal(t, reqEvent.ID, res.Tags.GetFirst([]string{"e"}).Value())
Expand Down
19 changes: 16 additions & 3 deletions nip47/notifications/nip47_notifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package notifications

import (
"context"
"encoding/hex"
"encoding/json"

"github.com/getAlby/hub/config"
Expand Down Expand Up @@ -108,7 +109,17 @@ func (notifier *Nip47Notifier) notifySubscriber(ctx context.Context, app *db.App
"appId": app.ID,
}).Debug("Notifying subscriber")

ss, err := nip04.ComputeSharedSecret(app.NostrPubkey, notifier.keys.GetNostrSecretKey())
appWalletPrivKeyBIP32, err := notifier.keys.GetBIP32ChildKey(uint32(app.ID))
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"notification": notification,
"appId": app.ID,
}).WithError(err).Error("error derivingchild key")
return
}
appWalletPrivKey := hex.EncodeToString(appWalletPrivKeyBIP32.Serialize())

ss, err := nip04.ComputeSharedSecret(app.NostrPubkey, appWalletPrivKey)
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"notification": notification,
Expand Down Expand Up @@ -137,14 +148,16 @@ func (notifier *Nip47Notifier) notifySubscriber(ctx context.Context, app *db.App
allTags := nostr.Tags{[]string{"p", app.NostrPubkey}}
allTags = append(allTags, tags...)

appWalletPubKey, _ := nostr.GetPublicKey(appWalletPrivKey)

event := &nostr.Event{
PubKey: notifier.keys.GetNostrPublicKey(),
PubKey: appWalletPubKey,
CreatedAt: nostr.Now(),
Kind: models.NOTIFICATION_KIND,
Tags: allTags,
Content: msg,
}
err = event.Sign(notifier.keys.GetNostrSecretKey())
err = event.Sign(appWalletPrivKey)
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"notification": notification,
Expand Down
32 changes: 32 additions & 0 deletions service/keys/keys.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package keys

import (
"encoding/hex"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/getAlby/hub/config"
"github.com/getAlby/hub/logger"
"github.com/nbd-wtf/go-nostr"
"github.com/tyler-smith/go-bip32"
)

type Keys interface {
Expand All @@ -12,6 +16,8 @@ type Keys interface {
GetNostrPublicKey() string
// Wallet Service Nostr secret key
GetNostrSecretKey() string
// GetBIP32ChildKey derives a BIP32 child key from the nostrSecretKey given a child key index
GetBIP32ChildKey(childIndex uint32) (*btcec.PrivateKey, error)
}

type keys struct {
Expand Down Expand Up @@ -51,3 +57,29 @@ func (keys *keys) GetNostrPublicKey() string {
func (keys *keys) GetNostrSecretKey() string {
return keys.nostrSecretKey
}

func (keys *keys) GetBIP32ChildKey(childIndex uint32) (*btcec.PrivateKey, error) {
// Convert nostrSecretKey to btcec private key
privKeyBytes, err := hex.DecodeString(keys.nostrSecretKey)
if err != nil {
return nil, err
}
privKey, _ := btcec.PrivKeyFromBytes(privKeyBytes)

// Create a BIP32 master key from the private key
masterKey, err := bip32.NewMasterKey(privKey.Serialize())
if err != nil {
return nil, err
}

// Derive child key
childKey, err := masterKey.NewChildKey(childIndex)
if err != nil {
return nil, err
}

// Convert child key to btcec private key
childPrivKey, _ := btcec.PrivKeyFromBytes(childKey.Key)

return childPrivKey, nil
}
Loading

0 comments on commit 83de003

Please sign in to comment.