Skip to content

Commit 5e0002a

Browse files
committed
add test for verify with fee, fix lint errors
1 parent 4975897 commit 5e0002a

File tree

3 files changed

+197
-1
lines changed

3 files changed

+197
-1
lines changed

spv/verify_test.go

+17
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"testing"
66

77
"github.com/bitcoin-sv/go-sdk/transaction"
8+
feemodel "github.com/bitcoin-sv/go-sdk/transaction/fee_model"
89
"github.com/stretchr/testify/require"
910
)
1011

@@ -29,3 +30,19 @@ func TestSPVVerifyScripts(t *testing.T) {
2930
require.NoError(t, err)
3031
require.True(t, verified)
3132
}
33+
34+
func TestSPVVerifyWithSufficientFee(t *testing.T) {
35+
// Create or load your transaction
36+
tx, err := transaction.NewTransactionFromBEEFHex(BRC62Hex)
37+
require.NoError(t, err)
38+
39+
// Create a fee model with a reasonable fee rate
40+
feeModel := &feemodel.SatoshisPerKilobyte{
41+
Satoshis: 10,
42+
}
43+
44+
// Call Verify with the fee model
45+
verified, err := Verify(tx, &GullibleHeadersClient{}, feeModel)
46+
require.NoError(t, err)
47+
require.True(t, verified)
48+
}

transaction/chaintracker/whatsonchain.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,22 @@ var (
3030
type WhatsOnChain struct {
3131
Network Network
3232
ApiKey string
33+
baseURL string
34+
client *http.Client
3335
}
3436

3537
func NewWhatsOnChain(network Network, apiKey string) *WhatsOnChain {
3638
return &WhatsOnChain{
3739
Network: network,
3840
ApiKey: apiKey,
41+
baseURL: fmt.Sprintf("https://api.whatsonchain.com/v1/bsv/%s", network),
42+
client: http.DefaultClient,
3943
}
4044
}
4145

4246
// Assuming BlockHeader is defined elsewhere
4347
func (w *WhatsOnChain) GetBlockHeader(height uint32) (header *BlockHeader, err error) {
44-
url := fmt.Sprintf("https://api.whatsonchain.com/v1/bsv/%s/block/%d/header", w.Network, height)
48+
url := fmt.Sprintf("%s/block/%d/header", w.baseURL, height)
4549
req, err := http.NewRequestWithContext(context.Background(), "GET", url, nil)
4650
if err != nil {
4751
return nil, err
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// whatsonchain_test.go
2+
3+
package chaintracker
4+
5+
import (
6+
"encoding/json"
7+
"net/http"
8+
"net/http/httptest"
9+
"testing"
10+
11+
"github.com/bitcoin-sv/go-sdk/chainhash"
12+
)
13+
14+
func TestWhatsOnChainGetBlockHeaderSuccess(t *testing.T) {
15+
// Mock BlockHeader data
16+
expectedHeader := &BlockHeader{
17+
Hash: &chainhash.Hash{},
18+
Height: 100,
19+
Version: 1,
20+
MerkleRoot: &chainhash.Hash{},
21+
Time: 1234567890,
22+
Nonce: 0,
23+
Bits: "1d00ffff",
24+
PrevHash: &chainhash.Hash{},
25+
}
26+
27+
// Create a test server
28+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
29+
// Check the request method and path
30+
if r.Method != http.MethodGet {
31+
t.Fatalf("expected GET method, got %s", r.Method)
32+
}
33+
expectedPath := "/block/100/header"
34+
if r.URL.Path != expectedPath {
35+
t.Fatalf("expected path %s, got %s", expectedPath, r.URL.Path)
36+
}
37+
// Set the Authorization header if needed
38+
if auth := r.Header.Get("Authorization"); auth != "testapikey" {
39+
t.Fatalf("expected Authorization header 'testapikey', got '%s'", auth)
40+
}
41+
// Write the mock response
42+
w.WriteHeader(http.StatusOK)
43+
json.NewEncoder(w).Encode(expectedHeader)
44+
}))
45+
defer ts.Close()
46+
47+
// Initialize WhatsOnChain with the test server URL and client
48+
woc := &WhatsOnChain{
49+
Network: "main",
50+
ApiKey: "testapikey",
51+
baseURL: ts.URL,
52+
client: ts.Client(),
53+
}
54+
55+
header, err := woc.GetBlockHeader(100)
56+
if err != nil {
57+
t.Fatalf("expected no error, got %v", err)
58+
return // Add this return statement
59+
}
60+
if header == nil {
61+
t.Fatalf("expected header, got nil")
62+
return // Add this return statement
63+
}
64+
if header.Height != expectedHeader.Height {
65+
t.Errorf("expected height %d, got %d", expectedHeader.Height, header.Height)
66+
}
67+
}
68+
69+
func TestWhatsOnChainGetBlockHeaderNotFound(t *testing.T) {
70+
// Create a test server that returns 404
71+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
72+
w.WriteHeader(http.StatusNotFound)
73+
}))
74+
defer ts.Close()
75+
76+
woc := &WhatsOnChain{
77+
Network: "main",
78+
ApiKey: "testapikey",
79+
baseURL: ts.URL,
80+
client: ts.Client(),
81+
}
82+
83+
header, err := woc.GetBlockHeader(100)
84+
if err != nil {
85+
t.Fatalf("expected no error, got %v", err)
86+
}
87+
if header != nil {
88+
t.Fatalf("expected nil header, got %v", header)
89+
}
90+
}
91+
92+
func TestWhatsOnChainGetBlockHeaderErrorResponse(t *testing.T) {
93+
// Create a test server that returns 500 Internal Server Error
94+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
95+
w.WriteHeader(http.StatusInternalServerError)
96+
w.Write([]byte("Internal Server Error"))
97+
}))
98+
defer ts.Close()
99+
100+
woc := &WhatsOnChain{
101+
Network: "main",
102+
ApiKey: "testapikey",
103+
baseURL: ts.URL,
104+
client: ts.Client(),
105+
}
106+
107+
header, err := woc.GetBlockHeader(100)
108+
if err == nil {
109+
t.Fatalf("expected error, got nil")
110+
}
111+
if header != nil {
112+
t.Fatalf("expected nil header, got %v", header)
113+
}
114+
}
115+
116+
func TestWhatsOnChainIsValidRootForHeightSuccess(t *testing.T) {
117+
// Mock BlockHeader data with a known MerkleRoot
118+
merkleRootHash := chainhash.HashH([]byte("test merkle root"))
119+
expectedHeader := &BlockHeader{
120+
MerkleRoot: &merkleRootHash,
121+
}
122+
123+
// Create a test server
124+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
125+
w.WriteHeader(http.StatusOK)
126+
json.NewEncoder(w).Encode(expectedHeader)
127+
}))
128+
defer ts.Close()
129+
130+
woc := &WhatsOnChain{
131+
Network: "main",
132+
ApiKey: "testapikey",
133+
baseURL: ts.URL,
134+
client: ts.Client(),
135+
}
136+
137+
isValid, err := woc.IsValidRootForHeight(&merkleRootHash, 100)
138+
if err != nil {
139+
t.Fatalf("expected no error, got %v", err)
140+
}
141+
if !isValid {
142+
t.Fatalf("expected isValid to be true, got false")
143+
}
144+
}
145+
146+
func TestWhatsOnChainIsValidRootForHeightInvalidRoot(t *testing.T) {
147+
// Mock BlockHeader data with a different MerkleRoot
148+
merkleRootHash := chainhash.HashH([]byte("test merkle root"))
149+
differentMerkleRootHash := chainhash.HashH([]byte("different merkle root"))
150+
expectedHeader := &BlockHeader{
151+
MerkleRoot: &merkleRootHash,
152+
}
153+
154+
// Create a test server
155+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
156+
w.WriteHeader(http.StatusOK)
157+
json.NewEncoder(w).Encode(expectedHeader)
158+
}))
159+
defer ts.Close()
160+
161+
woc := &WhatsOnChain{
162+
Network: "main",
163+
ApiKey: "testapikey",
164+
baseURL: ts.URL,
165+
client: ts.Client(),
166+
}
167+
168+
isValid, err := woc.IsValidRootForHeight(&differentMerkleRootHash, 100)
169+
if err != nil {
170+
t.Fatalf("expected no error, got %v", err)
171+
}
172+
if isValid {
173+
t.Fatalf("expected isValid to be false, got true")
174+
}
175+
}

0 commit comments

Comments
 (0)