mirror of
https://github.com/nbd-wtf/go-nostr.git
synced 2025-03-17 13:22:56 +01:00
Merge 1c9e97d2101b29d30d12c8d35bf568b56ceee5dc into 7c9c5d7cd9e1b946a25b57726d816abb79873bb9
This commit is contained in:
commit
19c09f45d6
43
nip47/nip47.go
Normal file
43
nip47/nip47.go
Normal file
@ -0,0 +1,43 @@
|
||||
package nip47
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
)
|
||||
|
||||
type NWCURIParts struct {
|
||||
clientSecretKey string
|
||||
walletPublicKey string
|
||||
relays []string
|
||||
}
|
||||
|
||||
// extracts the NWC URI parts from a connection URI
|
||||
func ParseNWCURI(nwcUri string) (*NWCURIParts, error) {
|
||||
p, err := url.Parse(nwcUri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if p.Scheme != "nostr+walletconnect" {
|
||||
return nil, errors.New("incorrect scheme")
|
||||
}
|
||||
if !nostr.IsValid32ByteHex(p.Host) {
|
||||
return nil, errors.New("invalid wallet public key")
|
||||
}
|
||||
query := p.Query()
|
||||
relays := query["relay"]
|
||||
secret := query.Get("secret")
|
||||
if !nostr.IsValid32ByteHex(secret) {
|
||||
return nil, errors.New("invalid secret")
|
||||
}
|
||||
if len(relays) == 0 {
|
||||
return nil, errors.New("no relays")
|
||||
}
|
||||
|
||||
return &NWCURIParts{
|
||||
walletPublicKey: p.Host,
|
||||
clientSecretKey: secret,
|
||||
relays: relays,
|
||||
}, nil
|
||||
}
|
23
nip47/nip47_test.go
Normal file
23
nip47/nip47_test.go
Normal file
@ -0,0 +1,23 @@
|
||||
package nip47
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParseNWCURI(t *testing.T) {
|
||||
uriParts, err := ParseNWCURI("nostr+walletconnect://739b65aa39cd4318708b5ae5ea85d52b758aa1f5502d32cb033eff9115f95f8d?relay=wss://relay.getalby.com/v1&secret=a5aa9fc79d90271f217c599191ce8479a0404d0c2417f85bc5bee18a89c0cb47")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "739b65aa39cd4318708b5ae5ea85d52b758aa1f5502d32cb033eff9115f95f8d", uriParts.walletPublicKey)
|
||||
assert.Equal(t, "a5aa9fc79d90271f217c599191ce8479a0404d0c2417f85bc5bee18a89c0cb47", uriParts.clientSecretKey)
|
||||
assert.Equal(t, []string{"wss://relay.getalby.com/v1"}, uriParts.relays)
|
||||
|
||||
_, err = ParseNWCURI("nostr+walletconnect://739b65aa39cd4318708b5ae5ea85d52b758aa1f5502d32cb033eff9115f95f8d?relay=wss://relay.getalby.com/v1")
|
||||
assert.Equal(t, "invalid secret", err.Error())
|
||||
_, err = ParseNWCURI("nostr+walletconnect://739b65aa39cd4318708b5ae5ea85d52b758aa1f5502d32cb033eff9115f95f8d?secret=a5aa9fc79d90271f217c599191ce8479a0404d0c2417f85bc5bee18a89c0cb47")
|
||||
assert.Equal(t, "no relays", err.Error())
|
||||
_, err = ParseNWCURI("nostrwalletconnect://739b65aa39cd4318708b5ae5ea85d52b758aa1f5502d32cb033eff9115f95f8d?relay=wss://relay.getalby.com/v1&secret=a5aa9fc79d90271f217c599191ce8479a0404d0c2417f85bc5bee18a89c0cb47")
|
||||
assert.Equal(t, "incorrect scheme", err.Error())
|
||||
}
|
341
nip47/nwc_client.go
Normal file
341
nip47/nwc_client.go
Normal file
@ -0,0 +1,341 @@
|
||||
package nip47
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/nbd-wtf/go-nostr"
|
||||
"github.com/nbd-wtf/go-nostr/nip44"
|
||||
)
|
||||
|
||||
type WalletServiceInfo struct {
|
||||
EncryptionTypes []string
|
||||
Capabilities []string
|
||||
NotificationTypes []string
|
||||
}
|
||||
|
||||
type GetInfoResult struct {
|
||||
Alias string `json:"alias"`
|
||||
Color string `json:"color"`
|
||||
Pubkey string `json:"pubkey"`
|
||||
Network string `json:"network"`
|
||||
BlockHeight uint `json:"block_height"`
|
||||
BlockHash string `json:"block_hash"`
|
||||
Methods []string `json:"methods"`
|
||||
Notifications []string `json:"notifications"`
|
||||
}
|
||||
|
||||
type MakeInvoiceParams struct {
|
||||
Amount uint64 `json:"amount"`
|
||||
Expiry *uint32 `json:"expiry"`
|
||||
Description string `json:"description"`
|
||||
DescriptionHash string `json:"description_hash"`
|
||||
Metadata interface{} `json:"metadata"`
|
||||
}
|
||||
|
||||
type PayInvoiceParams struct {
|
||||
Invoice string `json:"invoice"`
|
||||
Amount *uint64 `json:"amount"`
|
||||
Metadata interface{} `json:"metadata"`
|
||||
}
|
||||
|
||||
type LookupInvoiceParams struct {
|
||||
PaymentHash string `json:"payment_hash"`
|
||||
Invoice string `json:"invoice"`
|
||||
}
|
||||
|
||||
type ListTransactionsParams struct {
|
||||
From uint64 `json:"from"`
|
||||
To uint64 `json:"to"`
|
||||
Limit uint16 `json:"limit"`
|
||||
Offset uint32 `json:"offset"`
|
||||
Unpaid bool `json:"unpaid"`
|
||||
UnpaidOutgoing bool `json:"unpaid_outgoing"`
|
||||
UnpaidIncoming bool `json:"unpaid_incoming"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type GetBalanceResult struct {
|
||||
Balance uint64 `json:"balance"`
|
||||
}
|
||||
|
||||
type PayInvoiceResult struct {
|
||||
Preimage string `json:"preimage"`
|
||||
FeesPaid uint64 `json:"fees_paid"`
|
||||
}
|
||||
|
||||
type MakeInvoiceResult = Transaction
|
||||
type LookupInvoiceResult = Transaction
|
||||
type ListTransactionsResult struct {
|
||||
Transactions []Transaction `json:"transactions"`
|
||||
TotalCount uint32 `json:"total_count"`
|
||||
}
|
||||
|
||||
type Transaction struct {
|
||||
Type string `json:"type"`
|
||||
State string `json:"state"`
|
||||
Invoice string `json:"invoice"`
|
||||
Description string `json:"description"`
|
||||
DescriptionHash string `json:"description_hash"`
|
||||
Preimage string `json:"preimage"`
|
||||
PaymentHash string `json:"payment_hash"`
|
||||
Amount uint64 `json:"amount"`
|
||||
FeesPaid uint64 `json:"fees_paid"`
|
||||
CreatedAt uint64 `json:"created_at"`
|
||||
ExpiresAt uint64 `json:"expires_at"`
|
||||
SettledAt *uint64 `json:"settled_at"`
|
||||
Metadata interface{} `json:"metadata"`
|
||||
}
|
||||
|
||||
type NWCClient struct {
|
||||
pool *nostr.SimplePool
|
||||
relays []string
|
||||
conversationKey [32]byte // nip44
|
||||
clientSecretKey string
|
||||
walletPublicKey string
|
||||
}
|
||||
|
||||
var json = jsoniter.ConfigFastest
|
||||
|
||||
type Request struct {
|
||||
Method string `json:"method"`
|
||||
Params interface{} `json:"params"`
|
||||
}
|
||||
|
||||
type ResponseError struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
func (err *ResponseError) Error() string {
|
||||
return fmt.Sprintf("%s %s", err.Code, err.Message)
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
ResultType string `json:"result_type"`
|
||||
Error *ResponseError `json:"error"`
|
||||
Result interface{} `json:"result"`
|
||||
}
|
||||
|
||||
// creates a new NWC client from a NWC URI
|
||||
func NewNWCClientFromURI(ctx context.Context, nwcUri string, pool *nostr.SimplePool) (client *NWCClient, err error) {
|
||||
nwcUriParts, err := ParseNWCURI(nwcUri)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewNWCClient(ctx, nwcUriParts.clientSecretKey, nwcUriParts.walletPublicKey, nwcUriParts.relays, pool)
|
||||
}
|
||||
|
||||
// creates a new NWC client from NWC URI parts
|
||||
func NewNWCClient(ctx context.Context, clientSecretKey string, walletPublicKey string, relays []string, pool *nostr.SimplePool) (client *NWCClient, err error) {
|
||||
|
||||
if pool == nil {
|
||||
pool = nostr.NewSimplePool(ctx)
|
||||
}
|
||||
|
||||
conversationKey, err := nip44.GenerateConversationKey(walletPublicKey, clientSecretKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &NWCClient{
|
||||
pool: pool,
|
||||
relays: relays,
|
||||
clientSecretKey: clientSecretKey,
|
||||
conversationKey: conversationKey,
|
||||
walletPublicKey: walletPublicKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// fetches the NIP-47 info event (kind 13194)
|
||||
func (client NWCClient) GetWalletServiceInfo(ctx context.Context) (*WalletServiceInfo, error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
events := client.pool.SubscribeMany(ctx, client.relays, nostr.Filter{
|
||||
Limit: 1,
|
||||
Kinds: []int{13194},
|
||||
Authors: []string{client.walletPublicKey}})
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, fmt.Errorf("context canceled")
|
||||
case event := <-events:
|
||||
encryptionTypes := []string{}
|
||||
notificationTypes := []string{}
|
||||
encryptionTag := event.Tags.GetFirst([]string{"encryption"})
|
||||
notificationsTag := event.Tags.GetFirst([]string{"notifications"})
|
||||
if encryptionTag != nil {
|
||||
encryptionTypes = strings.Split((*encryptionTag).Value(), " ")
|
||||
}
|
||||
if notificationsTag != nil {
|
||||
notificationTypes = strings.Split((*notificationsTag).Value(), " ")
|
||||
}
|
||||
info := &WalletServiceInfo{
|
||||
EncryptionTypes: encryptionTypes,
|
||||
NotificationTypes: notificationTypes,
|
||||
Capabilities: strings.Split(event.Content, " "),
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
}
|
||||
|
||||
// executes the NIP-47 get_info request method
|
||||
func (client NWCClient) GetInfo(ctx context.Context) (*GetInfoResult, error) {
|
||||
getInfoResult := GetInfoResult{}
|
||||
err := client.RPC(ctx, "get_info", nil, &getInfoResult, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &getInfoResult, nil
|
||||
}
|
||||
|
||||
// executes the NIP-47 make_invoice request method
|
||||
func (client NWCClient) MakeInvoice(ctx context.Context, params *MakeInvoiceParams) (*MakeInvoiceResult, error) {
|
||||
makeInvoiceResult := MakeInvoiceResult{}
|
||||
err := client.RPC(ctx, "make_invoice", params, &makeInvoiceResult, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &makeInvoiceResult, nil
|
||||
}
|
||||
|
||||
// executes the NIP-47 pay_invoice request method
|
||||
func (client NWCClient) PayInvoice(ctx context.Context, params *PayInvoiceParams) (*PayInvoiceResult, error) {
|
||||
payInvoiceResult := PayInvoiceResult{}
|
||||
err := client.RPC(ctx, "pay_invoice", params, &payInvoiceResult, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &payInvoiceResult, nil
|
||||
}
|
||||
|
||||
// executes the NIP-47 lookup_invoice request method
|
||||
func (client NWCClient) LookupInvoice(ctx context.Context, params *LookupInvoiceParams) (*LookupInvoiceResult, error) {
|
||||
lookupInvoiceResult := LookupInvoiceResult{}
|
||||
err := client.RPC(ctx, "lookup_invoice", params, &lookupInvoiceResult, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &lookupInvoiceResult, nil
|
||||
}
|
||||
|
||||
// executes the NIP-47 list_transactions request method
|
||||
func (client NWCClient) ListTransactions(ctx context.Context, params *ListTransactionsParams) (*ListTransactionsResult, error) {
|
||||
listTransactionsResult := ListTransactionsResult{}
|
||||
err := client.RPC(ctx, "list_transactions", params, &listTransactionsResult, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &listTransactionsResult, nil
|
||||
}
|
||||
|
||||
// executes the NIP-47 get_balance request method
|
||||
func (client NWCClient) GetBalance(ctx context.Context) (*GetBalanceResult, error) {
|
||||
getBalanceResult := GetBalanceResult{}
|
||||
err := client.RPC(ctx, "get_balance", nil, &getBalanceResult, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &getBalanceResult, nil
|
||||
}
|
||||
|
||||
type rpcOptions struct {
|
||||
timeoutSeconds *uint64
|
||||
}
|
||||
|
||||
// executes a custom NIP-47 request method and waits for the response
|
||||
func (client NWCClient) RPC(ctx context.Context, method string, params interface{}, result interface{}, opts *rpcOptions) error {
|
||||
timeoutSeconds := uint64(10)
|
||||
if opts != nil && opts.timeoutSeconds != nil {
|
||||
timeoutSeconds = *opts.timeoutSeconds
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Duration(timeoutSeconds)*time.Second)
|
||||
defer cancel()
|
||||
|
||||
req, err := json.Marshal(Request{
|
||||
Method: method,
|
||||
Params: params,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
content, err := nip44.Encrypt(string(req), client.conversationKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error encrypting request: %w", err)
|
||||
}
|
||||
|
||||
evt := nostr.Event{
|
||||
Content: content,
|
||||
CreatedAt: nostr.Now(),
|
||||
Kind: 23194,
|
||||
Tags: nostr.Tags{{"p", client.walletPublicKey}, {"encryption", "nip44_v2"}},
|
||||
}
|
||||
if err := evt.Sign(client.clientSecretKey); err != nil {
|
||||
return fmt.Errorf("failed to sign request event: %w", err)
|
||||
}
|
||||
|
||||
hasWorked := make(chan struct{})
|
||||
|
||||
events := client.pool.SubscribeMany(ctx, client.relays, nostr.Filter{
|
||||
Limit: 1,
|
||||
Kinds: []int{23195},
|
||||
Authors: []string{client.walletPublicKey},
|
||||
Tags: nostr.TagMap{"e": []string{evt.ID}}})
|
||||
|
||||
for _, url := range client.relays {
|
||||
go func(url string) {
|
||||
relay, err := client.pool.EnsureRelay(url)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = relay.Publish(ctx, evt)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case hasWorked <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}(url)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-hasWorked:
|
||||
// continue
|
||||
case <-ctx.Done():
|
||||
return fmt.Errorf("couldn't connect to any relay")
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return fmt.Errorf("context canceled")
|
||||
case event := <-events:
|
||||
plain, err := nip44.Decrypt(event.Content, client.conversationKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp := Response{
|
||||
Result: &result,
|
||||
}
|
||||
err = json.Unmarshal([]byte(plain), &resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
172
nip47/nwc_client_test.go
Normal file
172
nip47/nwc_client_test.go
Normal file
@ -0,0 +1,172 @@
|
||||
package nip47
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetWalletServiceInfo(t *testing.T) {
|
||||
client := createTestClient(t)
|
||||
|
||||
walletServiceInfo, err := client.GetWalletServiceInfo(context.TODO())
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, walletServiceInfo)
|
||||
assert.Contains(t, walletServiceInfo.Capabilities, "get_info")
|
||||
assert.Contains(t, walletServiceInfo.NotificationTypes, "payment_received")
|
||||
assert.Contains(t, walletServiceInfo.EncryptionTypes, "nip44_v2")
|
||||
}
|
||||
|
||||
func TestGetInfo(t *testing.T) {
|
||||
client := createTestClient(t)
|
||||
|
||||
getInfoResult, err := client.GetInfo(context.TODO())
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, getInfoResult)
|
||||
assert.Contains(t, getInfoResult.Methods, "get_info")
|
||||
assert.Contains(t, getInfoResult.Notifications, "payment_received")
|
||||
assert.Greater(t, getInfoResult.BlockHeight, uint(840_000))
|
||||
assert.Equal(t, 64, len(getInfoResult.BlockHash))
|
||||
assert.Equal(t, "mainnet", getInfoResult.Network)
|
||||
}
|
||||
|
||||
func TestMakeInvoice(t *testing.T) {
|
||||
client := createTestClient(t)
|
||||
|
||||
makeInvoiceResult, err := client.MakeInvoice(context.TODO(), &MakeInvoiceParams{
|
||||
Amount: uint64(1000),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, makeInvoiceResult)
|
||||
assert.Equal(t, makeInvoiceResult.Amount, uint64(1000))
|
||||
assert.True(t, strings.HasPrefix(makeInvoiceResult.Invoice, "lnbc"))
|
||||
assert.Equal(t, "pending", makeInvoiceResult.State)
|
||||
assert.Nil(t, makeInvoiceResult.SettledAt)
|
||||
assert.Greater(t, makeInvoiceResult.ExpiresAt, uint64(time.Now().Unix()))
|
||||
assert.Empty(t, makeInvoiceResult.Preimage)
|
||||
}
|
||||
|
||||
func TestLookupInvoice(t *testing.T) {
|
||||
client := createTestClient(t)
|
||||
|
||||
makeInvoiceResult, err := client.MakeInvoice(context.TODO(), &MakeInvoiceParams{
|
||||
Amount: uint64(1000),
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, makeInvoiceResult)
|
||||
|
||||
lookupInvoiceResult, err := client.LookupInvoice(context.TODO(), &LookupInvoiceParams{
|
||||
PaymentHash: makeInvoiceResult.PaymentHash,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, lookupInvoiceResult)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, lookupInvoiceResult)
|
||||
assert.Equal(t, lookupInvoiceResult.Amount, uint64(1000))
|
||||
assert.True(t, strings.HasPrefix(lookupInvoiceResult.Invoice, "lnbc"))
|
||||
assert.Equal(t, "pending", lookupInvoiceResult.State)
|
||||
assert.Nil(t, lookupInvoiceResult.SettledAt)
|
||||
assert.Greater(t, lookupInvoiceResult.ExpiresAt, uint64(time.Now().Unix()))
|
||||
assert.Empty(t, lookupInvoiceResult.Preimage)
|
||||
}
|
||||
|
||||
func TestListTransactions(t *testing.T) {
|
||||
client := createTestClient(t)
|
||||
|
||||
makeInvoiceResult, err := client.MakeInvoice(context.TODO(), &MakeInvoiceParams{
|
||||
Amount: uint64(1000),
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, makeInvoiceResult)
|
||||
|
||||
listTransactionsResult, err := client.ListTransactions(context.TODO(), &ListTransactionsParams{
|
||||
Unpaid: true,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, listTransactionsResult)
|
||||
require.NotZero(t, len(listTransactionsResult.Transactions))
|
||||
require.NotZero(t, listTransactionsResult.TotalCount)
|
||||
|
||||
transaction := listTransactionsResult.Transactions[0]
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, transaction)
|
||||
assert.Equal(t, transaction.Amount, uint64(1000))
|
||||
assert.True(t, strings.HasPrefix(transaction.Invoice, "lnbc"))
|
||||
assert.Equal(t, "pending", transaction.State)
|
||||
assert.Nil(t, transaction.SettledAt)
|
||||
assert.Greater(t, transaction.ExpiresAt, uint64(time.Now().Unix()))
|
||||
assert.Empty(t, transaction.Preimage)
|
||||
}
|
||||
func TestGetBalance(t *testing.T) {
|
||||
client := createTestClient(t)
|
||||
|
||||
getBalanceResult, err := client.GetBalance(context.TODO())
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, getBalanceResult)
|
||||
|
||||
assert.Equal(t, uint64(100_000), getBalanceResult.Balance)
|
||||
}
|
||||
|
||||
func TestPayInvoice(t *testing.T) {
|
||||
client := createTestClient(t)
|
||||
|
||||
makeInvoiceResult, err := client.MakeInvoice(context.TODO(), &MakeInvoiceParams{
|
||||
Amount: uint64(1000),
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, makeInvoiceResult)
|
||||
|
||||
payInvoiceResult, err := client.PayInvoice(context.TODO(), &PayInvoiceParams{
|
||||
Invoice: makeInvoiceResult.Invoice,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, payInvoiceResult)
|
||||
assert.Equal(t, 64, len(payInvoiceResult.Preimage))
|
||||
assert.Equal(t, uint64(0), payInvoiceResult.FeesPaid)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, makeInvoiceResult)
|
||||
|
||||
lookupInvoiceResult, err := client.LookupInvoice(context.TODO(), &LookupInvoiceParams{
|
||||
PaymentHash: makeInvoiceResult.PaymentHash,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, lookupInvoiceResult)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, lookupInvoiceResult)
|
||||
assert.Equal(t, lookupInvoiceResult.Amount, uint64(1000))
|
||||
assert.True(t, strings.HasPrefix(lookupInvoiceResult.Invoice, "lnbc"))
|
||||
assert.Equal(t, "settled", lookupInvoiceResult.State)
|
||||
require.NotNil(t, lookupInvoiceResult.SettledAt)
|
||||
assert.LessOrEqual(t, *lookupInvoiceResult.SettledAt, uint64(time.Now().Unix()))
|
||||
assert.Greater(t, lookupInvoiceResult.ExpiresAt, uint64(time.Now().Unix()))
|
||||
assert.Equal(t, 64, len(lookupInvoiceResult.Preimage))
|
||||
}
|
||||
|
||||
func createTestClient(t *testing.T) *NWCClient {
|
||||
nwcUri := os.Getenv("NWC_URI")
|
||||
if nwcUri == "" {
|
||||
t.Skip()
|
||||
return nil
|
||||
}
|
||||
client, err := NewNWCClientFromURI(context.TODO(), nwcUri, nil)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, client)
|
||||
return client
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user