uri.go raw

   1  package nwc
   2  
   3  import (
   4  	"errors"
   5  	"net/url"
   6  
   7  	"next.orly.dev/pkg/lol/chk"
   8  	"next.orly.dev/pkg/nostr/crypto/encryption"
   9  	"next.orly.dev/pkg/nostr/interfaces/signer/p8k"
  10  	"next.orly.dev/pkg/nostr/encoders/hex"
  11  	"next.orly.dev/pkg/nostr/interfaces/signer"
  12  )
  13  
  14  type ConnectionParams struct {
  15  	clientSecretKey signer.I
  16  	walletPublicKey []byte
  17  	conversationKey []byte
  18  	relay           string
  19  }
  20  
  21  // GetWalletPublicKey returns the wallet public key from the ConnectionParams.
  22  func (c *ConnectionParams) GetWalletPublicKey() []byte {
  23  	return c.walletPublicKey
  24  }
  25  
  26  // GetConversationKey returns the conversation key from the ConnectionParams.
  27  func (c *ConnectionParams) GetConversationKey() []byte {
  28  	return c.conversationKey
  29  }
  30  
  31  func ParseConnectionURI(nwcUri string) (parts *ConnectionParams, err error) {
  32  	var p *url.URL
  33  	if p, err = url.Parse(nwcUri); chk.E(err) {
  34  		return
  35  	}
  36  	if p == nil {
  37  		err = errors.New("invalid uri")
  38  		return
  39  	}
  40  	parts = &ConnectionParams{}
  41  	if p.Scheme != "nostr+walletconnect" {
  42  		err = errors.New("incorrect scheme")
  43  		return
  44  	}
  45  	if parts.walletPublicKey, err = hex.Dec(p.Host); chk.E(err) {
  46  		err = errors.New("invalid public key")
  47  		return
  48  	}
  49  	query := p.Query()
  50  	var ok bool
  51  	var relay []string
  52  	if relay, ok = query["relay"]; !ok {
  53  		err = errors.New("missing relay parameter")
  54  		return
  55  	}
  56  	if len(relay) == 0 {
  57  		return nil, errors.New("no relays")
  58  	}
  59  	parts.relay = relay[0]
  60  	var secret string
  61  	if secret = query.Get("secret"); secret == "" {
  62  		err = errors.New("missing secret parameter")
  63  		return
  64  	}
  65  	var secretBytes []byte
  66  	if secretBytes, err = hex.Dec(secret); chk.E(err) {
  67  		err = errors.New("invalid secret")
  68  		return
  69  	}
  70  	var clientKey *p8k.Signer
  71  	if clientKey, err = p8k.New(); chk.E(err) {
  72  		return
  73  	}
  74  	if err = clientKey.InitSec(secretBytes); chk.E(err) {
  75  		return
  76  	}
  77  	parts.clientSecretKey = clientKey
  78  	if parts.conversationKey, err = encryption.GenerateConversationKey(
  79  		clientKey.Sec(),
  80  		parts.walletPublicKey,
  81  	); chk.E(err) {
  82  		return
  83  	}
  84  	return
  85  }
  86