mirror of
https://github.com/muun/recovery.git
synced 2025-07-20 22:11:16 -04:00
322 lines
7.4 KiB
Go
Executable File
322 lines
7.4 KiB
Go
Executable File
package libwallet
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
const (
|
|
address = "2NDhvuRPCYXq4fB8SprminieZ2a1i3JFXyS"
|
|
amountURI = address + "?amount=1.2"
|
|
completeURI = amountURI + "&label=hola&message=mensaje%20con%20espacios"
|
|
uriWithSlashes = "bitcoin://" + amountURI
|
|
|
|
invalidAddress = "2NDhvuRPCYXq4fB8SprminieZ2a1i3JFXya"
|
|
randomText = "fooo"
|
|
|
|
bip70URL = "https://bitpay.com/i/KXCEAtJQssR9vG2BxdjFwx"
|
|
bip70NonRetroCompatAddress = bitcoinScheme + "?r=" + bip70URL
|
|
bip70RetroCompatAddress = bitcoinScheme + address + "?r=" + bip70URL
|
|
)
|
|
|
|
func TestGetPaymentURI(t *testing.T) {
|
|
|
|
const (
|
|
invoice = "lnbcrt1pwtpd4xpp55meuklpslk5jtxytyh7u2q490c2xhm68dm3a94486zntsg7ad4vsdqqcqzys763w70h39ze44ngzhdt2mag84wlkefqkphuy7ssg4la5gt9vcpmqts00fnapf8frs928mc5ujfutzyu8apkezhrfvydx82l40w0fckqqmerzjc"
|
|
invoiceHashHex = "a6f3cb7c30fda925988b25fdc502a57e146bef476ee3d2d6a7d0a6b823dd6d59"
|
|
invoiceDestinationHex = "028cfad4e092191a41f081bedfbe5a6e8f441603c78bf9001b8fb62ac0858f20edasd"
|
|
)
|
|
|
|
invoiceDestination, _ := hex.DecodeString(invoiceDestinationHex)
|
|
invoicePaymentHash := make([]byte, 32)
|
|
hex.Decode(invoicePaymentHash[:], []byte(invoiceHashHex))
|
|
|
|
type args struct {
|
|
address string
|
|
network Network
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want *MuunPaymentURI
|
|
wantErr bool
|
|
}{
|
|
|
|
{
|
|
name: "validAddress",
|
|
args: args{
|
|
address: address,
|
|
network: *Regtest(),
|
|
},
|
|
want: &MuunPaymentURI{
|
|
Address: address,
|
|
Uri: bitcoinScheme + address,
|
|
},
|
|
},
|
|
{
|
|
name: "amountValidAddress",
|
|
args: args{
|
|
address: amountURI,
|
|
network: *Regtest(),
|
|
},
|
|
want: &MuunPaymentURI{
|
|
Address: address,
|
|
Amount: "1.2",
|
|
Uri: bitcoinScheme + amountURI,
|
|
},
|
|
},
|
|
{
|
|
name: "completeValidAddress",
|
|
args: args{
|
|
address: completeURI,
|
|
network: *Regtest(),
|
|
},
|
|
want: &MuunPaymentURI{
|
|
Address: address,
|
|
Amount: "1.2",
|
|
Label: "hola",
|
|
Message: "mensaje con espacios",
|
|
Uri: bitcoinScheme + completeURI,
|
|
},
|
|
},
|
|
{
|
|
name: "invalidAddress",
|
|
args: args{
|
|
address: invalidAddress,
|
|
network: *Regtest(),
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "randomText",
|
|
args: args{
|
|
address: randomText,
|
|
network: *Regtest(),
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "BIP70NonRetroCompatAddress",
|
|
args: args{
|
|
address: bip70NonRetroCompatAddress,
|
|
network: *Regtest(),
|
|
},
|
|
want: &MuunPaymentURI{
|
|
Uri: bip70NonRetroCompatAddress,
|
|
Bip70Url: bip70URL,
|
|
},
|
|
},
|
|
{
|
|
name: "BIP70RetroCompatAddress",
|
|
args: args{
|
|
address: bip70RetroCompatAddress,
|
|
network: *Regtest(),
|
|
},
|
|
want: &MuunPaymentURI{
|
|
Address: address,
|
|
Uri: bip70RetroCompatAddress,
|
|
Bip70Url: bip70URL,
|
|
},
|
|
},
|
|
{
|
|
name: "URL like address",
|
|
args: args{
|
|
address: uriWithSlashes,
|
|
network: *Regtest(),
|
|
},
|
|
want: &MuunPaymentURI{
|
|
Address: address,
|
|
Uri: uriWithSlashes,
|
|
Amount: "1.2",
|
|
},
|
|
},
|
|
{
|
|
name: "bad url",
|
|
args: args{
|
|
address: ":foo#%--",
|
|
network: *Regtest(),
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "bad query",
|
|
args: args{
|
|
address: "bitcoin:123123?%&-=asd",
|
|
network: *Regtest(),
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "network mismatch",
|
|
args: args{
|
|
address: amountURI,
|
|
network: *Mainnet(),
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "BIP with lightning",
|
|
args: args{
|
|
address: "bitcoin:123123?lightning=" + invoice,
|
|
network: *network,
|
|
},
|
|
want: &MuunPaymentURI{Invoice: &Invoice{
|
|
RawInvoice: invoice,
|
|
FallbackAddress: nil,
|
|
Network: network,
|
|
MilliSat: "",
|
|
Destination: invoiceDestination,
|
|
PaymentHash: invoicePaymentHash,
|
|
Description: "",
|
|
}},
|
|
},
|
|
{
|
|
name: "ALL CAPS",
|
|
args: args{
|
|
address: "BITCOIN:BC1QSQP0D3TY8AAA8N9J8R0D2PF3G40VN4AS9TPWY3J9R3GK5K64VX6QWPAXH2",
|
|
network: *Mainnet(),
|
|
},
|
|
want: &MuunPaymentURI{
|
|
Address: strings.ToLower("BC1QSQP0D3TY8AAA8N9J8R0D2PF3G40VN4AS9TPWY3J9R3GK5K64VX6QWPAXH2"),
|
|
Uri: "BITCOIN:BC1QSQP0D3TY8AAA8N9J8R0D2PF3G40VN4AS9TPWY3J9R3GK5K64VX6QWPAXH2",
|
|
},
|
|
},
|
|
{
|
|
name: "MiXeD Case",
|
|
args: args{
|
|
address: "BiTcOiN:BC1QSQP0D3TY8AAA8N9J8R0D2PF3G40VN4AS9TPWY3J9R3GK5K64VX6QWPAXH2",
|
|
network: *Mainnet(),
|
|
},
|
|
want: &MuunPaymentURI{
|
|
Address: strings.ToLower("BC1QSQP0D3TY8AAA8N9J8R0D2PF3G40VN4AS9TPWY3J9R3GK5K64VX6QWPAXH2"),
|
|
Uri: "BiTcOiN:BC1QSQP0D3TY8AAA8N9J8R0D2PF3G40VN4AS9TPWY3J9R3GK5K64VX6QWPAXH2",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := GetPaymentURI(tt.args.address, &tt.args.network)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("GetPaymentURI() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if got != nil && got.Invoice != nil {
|
|
// expiry is relative to now, so ignore it
|
|
got.Invoice.Expiry = 0
|
|
}
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("GetPaymentURI() = %+v, want %+v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_normalizeAddress(t *testing.T) {
|
|
type args struct {
|
|
rawAddress string
|
|
targetScheme string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want string
|
|
}{
|
|
{
|
|
name: "normalAddress",
|
|
args: args{
|
|
rawAddress: address,
|
|
targetScheme: bitcoinScheme,
|
|
},
|
|
want: bitcoinScheme + address,
|
|
},
|
|
{
|
|
name: "bitcoinAddress",
|
|
args: args{
|
|
rawAddress: bitcoinScheme + address,
|
|
targetScheme: bitcoinScheme,
|
|
},
|
|
want: bitcoinScheme + address,
|
|
},
|
|
{
|
|
name: "muunAddress",
|
|
args: args{
|
|
rawAddress: muunScheme + address,
|
|
targetScheme: bitcoinScheme,
|
|
},
|
|
want: bitcoinScheme + address,
|
|
},
|
|
{
|
|
name: "muun to lightning",
|
|
args: args{
|
|
rawAddress: muunScheme + address,
|
|
targetScheme: lightningScheme,
|
|
},
|
|
want: lightningScheme + address,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got, _ := buildUriFromString(tt.args.rawAddress, tt.args.targetScheme); got != tt.want {
|
|
t.Errorf("buildUriFromString() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDoPaymentRequestCall(t *testing.T) {
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("/payment-request/", func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Header.Get("Accept") != "application/bitcoin-paymentrequest" {
|
|
t.Fatal("expected Accept header to be application/bitcoin-paymentrequest")
|
|
}
|
|
|
|
script, _ := hex.DecodeString("76a9146efcf883b4b6f9997be9a0600f6c095fe2bd2d9288ac")
|
|
|
|
serializedPaymentDetails, _ := proto.Marshal(&PaymentDetails{
|
|
Network: "test",
|
|
Outputs: []*Output{
|
|
{
|
|
Script: script,
|
|
Amount: 2500,
|
|
},
|
|
},
|
|
Time: 100000,
|
|
Expires: 102000,
|
|
Memo: "Hello World",
|
|
PaymentUrl: "http://localhost:8000/pay",
|
|
MerchantData: []byte(""),
|
|
})
|
|
payReq, _ := proto.Marshal(&PaymentRequest{SerializedPaymentDetails: serializedPaymentDetails})
|
|
|
|
w.Write(payReq)
|
|
})
|
|
server := httptest.NewServer(mux)
|
|
defer server.Close()
|
|
|
|
url := server.URL + "/payment-request/"
|
|
paymentURI, err := DoPaymentRequestCall(url, Testnet())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
expected := &MuunPaymentURI{
|
|
Address: "mqdofsXHpePPGBFXuwwypAqCcXi48Xhb2f",
|
|
Message: "Hello World",
|
|
Amount: "0.000025",
|
|
Bip70Url: url,
|
|
CreationTime: "100000",
|
|
ExpiresTime: "102000",
|
|
}
|
|
if !reflect.DeepEqual(paymentURI, expected) {
|
|
t.Fatalf("decoded URI struct does not match expected, %+v != %+v", paymentURI, expected)
|
|
}
|
|
}
|