Skip to content

Commit

Permalink
Merge branch 'main' into feat/spv-1085-merkle-roots-verifier
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-4chain authored Oct 11, 2024
2 parents 36b9254 + 1de1edc commit 4a1ca37
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 64 deletions.
32 changes: 26 additions & 6 deletions actions/testabilities/fixture_spvwallet_application.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import (
"github.com/bitcoin-sv/spv-wallet/engine/datastore"
"github.com/bitcoin-sv/spv-wallet/engine/tester"
"github.com/bitcoin-sv/spv-wallet/engine/tester/fixtures"
"github.com/bitcoin-sv/spv-wallet/engine/tester/paymailmock"
"github.com/bitcoin-sv/spv-wallet/server"
"github.com/go-resty/resty/v2"
"github.com/jarcoal/httpmock"
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -46,16 +48,21 @@ type appFixture struct {
engine engine.ClientInterface
t testing.TB
logger zerolog.Logger
transport testServer
server testServer
dbConnectionString string
dbConnection *sql.DB
externalTransport *httpmock.MockTransport
paymailClient *paymailmock.PaymailClientMock
}

func Given(t testing.TB) SPVWalletApplicationFixture {
f := &appFixture{
t: t,
logger: tester.Logger(t),
config: getConfigForTests(),
t: t,
logger: tester.Logger(t),
config: getConfigForTests(),
externalTransport: httpmock.NewMockTransport(),
// TODO reuse externalTransport in paymailmock
paymailClient: paymailmock.MockClient(fixtures.PaymailDomainExternal),
}

f.initDbConnection()
Expand All @@ -81,14 +88,15 @@ func (f *appFixture) StartedSPVWalletWithConfiguration(opts ...ConfigOpts) (clea

options, err := f.config.ToEngineOptions(f.logger)
require.NoError(f.t, err)
options = f.addMockedExternalDependenciesOptions(options)

f.engine, err = engine.NewClient(context.Background(), options...)
require.NoError(f.t, err)

f.registerUsersFromFixture()

s := server.NewServer(f.config, f.engine, f.logger)
f.transport.handlers = s.Handlers()
f.server.handlers = s.Handlers()

return func() {
err := f.engine.Close(context.Background())
Expand All @@ -105,7 +113,7 @@ func (f *appFixture) ForAnonymous() *resty.Client {
c.OnError(func(_ *resty.Request, err error) {
f.t.Fatalf("HTTP request end up with unexpected error: %v", err)
})
c.GetClient().Transport = f.transport
c.GetClient().Transport = f.server
return c
}

Expand Down Expand Up @@ -152,6 +160,18 @@ func (f *appFixture) initDbConnection() {
f.config.Db.SQLite.ExistingConnection = f.dbConnection
}

func (f *appFixture) addMockedExternalDependenciesOptions(options []engine.ClientOps) []engine.ClientOps {
options = append(options, engine.WithHTTPClient(f.httpClientWithMockedTransport()))
options = append(options, engine.WithPaymailClient(f.paymailClient))
return options
}

func (f *appFixture) httpClientWithMockedTransport() *resty.Client {
client := resty.New()
client.SetTransport(f.externalTransport)
return client
}

func getConfigForTests() *config.AppConfig {
cfg := config.GetDefaultAppConfig()
cfg.Authentication.RequireSigning = false
Expand Down
14 changes: 13 additions & 1 deletion config/config_to_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"crypto/tls"
"fmt"
"net/url"
"time"

broadcastclient "github.com/bitcoin-sv/go-broadcast-client/broadcast/broadcast-client"
"github.com/bitcoin-sv/spv-wallet/engine"
Expand All @@ -14,6 +15,7 @@ import (
"github.com/bitcoin-sv/spv-wallet/engine/utils"
"github.com/bitcoin-sv/spv-wallet/metrics"
"github.com/go-redis/redis/v8"
"github.com/go-resty/resty/v2"
"github.com/mrz1836/go-cachestore"
"github.com/rs/zerolog"
)
Expand All @@ -22,6 +24,8 @@ import (
func (c *AppConfig) ToEngineOptions(logger zerolog.Logger) (options []engine.ClientOps, err error) {
options = c.addUserAgentOpts(options)

options = c.addHttpClientOpts(options)

options = c.addMetricsOpts(options)

options = c.addLoggerOpts(logger, options)
Expand Down Expand Up @@ -59,6 +63,14 @@ func (c *AppConfig) ToEngineOptions(logger zerolog.Logger) (options []engine.Cli
return options, nil
}

func (c *AppConfig) addHttpClientOpts(options []engine.ClientOps) []engine.ClientOps {
client := resty.New()
client.SetTimeout(20 * time.Second)
client.SetDebug(c.Logging.Level == zerolog.LevelTraceValue)
client.SetHeader("User-Agent", c.GetUserAgent())
return append(options, engine.WithHTTPClient(client))
}

func (c *AppConfig) addFeeQuotes(options []engine.ClientOps) []engine.ClientOps {
options = append(options, engine.WithFeeQuotes(c.ARC.UseFeeQuotes))

Expand Down Expand Up @@ -90,7 +102,7 @@ func (c *AppConfig) addMetricsOpts(options []engine.ClientOps) []engine.ClientOp
}

func (c *AppConfig) addDebugOpts(options []engine.ClientOps) []engine.ClientOps {
if c.Logging.Level == "debug" || c.Logging.Level == "trace" {
if c.Logging.Level == zerolog.LevelDebugValue || c.Logging.Level == zerolog.LevelTraceValue {
options = append(options, engine.WithDebugging())
}
return options
Expand Down
4 changes: 4 additions & 0 deletions engine/chain/chain_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ type chainService struct {

// NewChainService creates a new chain service.
func NewChainService(logger zerolog.Logger, httpClient *resty.Client, arcCfg chainmodels.ARCConfig, bhsConf chainmodels.BHSConfig) Service {
if httpClient == nil {
panic("httpClient is required")
}

return &chainService{
arc.NewARCService(logger.With().Str("chain", "arc").Logger(), httpClient, arcCfg),
bhs.NewBHSService(logger.With().Str("chain", "bhs").Logger(), httpClient, bhsConf),
Expand Down
8 changes: 2 additions & 6 deletions engine/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/bitcoin-sv/spv-wallet/engine/spverrors"
"github.com/bitcoin-sv/spv-wallet/engine/taskmanager"
"github.com/bitcoin-sv/spv-wallet/engine/transaction/draft"
"github.com/go-resty/resty/v2"
"github.com/mrz1836/go-cachestore"
"github.com/rs/zerolog"
)
Expand All @@ -38,7 +39,7 @@ type (
dataStore *dataStoreOptions // Configuration options for the DataStore (PostgreSQL, etc.)
debug bool // If the client is in debug mode
encryptionKey string // Encryption key for encrypting sensitive information (IE: paymail xPub) (hex encoded key)
httpClient HTTPInterface // HTTP interface to use
httpClient *resty.Client // HTTP client to use for http calls
iuc bool // (Input UTXO Check) True will check input utxos when saving transactions
logger *zerolog.Logger // Internal logging
metrics *metrics.Metrics // Metrics with a collector interface
Expand Down Expand Up @@ -339,11 +340,6 @@ func (c *Client) GetModelNames() []string {
return c.options.models.modelNames
}

// HTTPClient will return the http interface to use in the client
func (c *Client) HTTPClient() HTTPInterface {
return c.options.httpClient
}

// IsDebug will return the debug flag (bool)
func (c *Client) IsDebug() bool {
return c.options.debug
Expand Down
7 changes: 4 additions & 3 deletions engine/client_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"github.com/bitcoin-sv/spv-wallet/engine/spverrors"
"github.com/bitcoin-sv/spv-wallet/engine/taskmanager"
"github.com/bitcoin-sv/spv-wallet/engine/transaction/draft"
"github.com/go-resty/resty/v2"
"github.com/mrz1836/go-cachestore"
)

Expand Down Expand Up @@ -43,7 +42,7 @@ func (c *Client) loadChainstate(ctx context.Context) (err error) {
// Load chainstate if a custom interface was NOT provided
if c.options.chainstate.ClientInterface == nil {
c.options.chainstate.options = append(c.options.chainstate.options, chainstate.WithUserAgent(c.UserAgent()))
c.options.chainstate.options = append(c.options.chainstate.options, chainstate.WithHTTPClient(c.HTTPClient()))
c.options.chainstate.options = append(c.options.chainstate.options, chainstate.WithHTTPClient(c.options.httpClient.GetClient()))
c.options.chainstate.options = append(c.options.chainstate.options, chainstate.WithMetrics(c.options.metrics))
c.options.chainstate.ClientInterface, err = chainstate.NewClient(ctx, c.options.chainstate.options...)
}
Expand Down Expand Up @@ -150,7 +149,9 @@ func (c *Client) loadPaymailComponents() (err error) {
if err != nil {
return
}
c.options.paymail.client.WithCustomHTTPClient(c.options.httpClient)
}

if c.options.paymail.service == nil {
logger := c.Logger().With().Str("subservice", "paymail").Logger()
c.options.paymail.service = paymailclient.NewServiceClient(c.Cachestore(), c.options.paymail.client, logger)
Expand Down Expand Up @@ -206,7 +207,7 @@ func (c *Client) loadTransactionDraftService() error {
func (c *Client) loadChainService() {
if c.options.chainService == nil {
logger := c.Logger().With().Str("subservice", "chain").Logger()
c.options.chainService = chain.NewChainService(logger, resty.New(), c.options.arcConfig, c.options.bhsConfig)
c.options.chainService = chain.NewChainService(logger, c.options.httpClient, c.options.arcConfig, c.options.bhsConfig)
}
}

Expand Down
9 changes: 3 additions & 6 deletions engine/client_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package engine

import (
"database/sql"
"net/http"
"net/url"
"strings"
"time"
Expand All @@ -16,11 +15,11 @@ import (
"github.com/bitcoin-sv/spv-wallet/engine/datastore"
"github.com/bitcoin-sv/spv-wallet/engine/logging"
"github.com/bitcoin-sv/spv-wallet/engine/metrics"
// "github.com/bitcoin-sv/spv-wallet/engine/notifications"
"github.com/bitcoin-sv/spv-wallet/engine/taskmanager"
"github.com/bitcoin-sv/spv-wallet/engine/utils"
"github.com/coocood/freecache"
"github.com/go-redis/redis/v8"
"github.com/go-resty/resty/v2"
"github.com/mrz1836/go-cache"
"github.com/mrz1836/go-cachestore"
"github.com/rs/zerolog"
Expand Down Expand Up @@ -70,9 +69,7 @@ func defaultClientOptions() *clientOptions {
},

// Default http client
httpClient: &http.Client{
Timeout: defaultHTTPTimeout,
},
httpClient: resty.New(),

// Blank model options (use the Base models)
models: &modelOptions{
Expand Down Expand Up @@ -213,7 +210,7 @@ func WithIUCDisabled() ClientOps {
}

// WithHTTPClient will set the custom http interface
func WithHTTPClient(httpClient HTTPInterface) ClientOps {
func WithHTTPClient(httpClient *resty.Client) ClientOps {
return func(c *clientOptions) {
if httpClient != nil {
c.httpClient = httpClient
Expand Down
39 changes: 0 additions & 39 deletions engine/client_options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package engine

import (
"context"
"net/http"
"os"
"testing"
"time"
Expand Down Expand Up @@ -558,44 +557,6 @@ func TestWithIUCDisabled(t *testing.T) {
})
}

// TestWithHTTPClient will test the method WithHTTPClient()
func TestWithHTTPClient(t *testing.T) {
t.Parallel()
testLogger := zerolog.Nop()

t.Run("check type", func(t *testing.T) {
opt := WithHTTPClient(nil)
assert.IsType(t, *new(ClientOps), opt)
})

t.Run("test applying nil", func(t *testing.T) {
opts := DefaultClientOpts(false, true)
opts = append(opts, WithHTTPClient(nil))
opts = append(opts, WithLogger(&testLogger))

tc, err := NewClient(context.Background(), opts...)
require.NoError(t, err)
require.NotNil(t, tc)
defer CloseClient(context.Background(), t, tc)

assert.NotNil(t, tc.HTTPClient())
})

t.Run("test applying option", func(t *testing.T) {
customClient := &http.Client{}
opts := DefaultClientOpts(false, true)
opts = append(opts, WithHTTPClient(customClient))
opts = append(opts, WithLogger(&testLogger))

tc, err := NewClient(context.Background(), opts...)
require.NoError(t, err)
require.NotNil(t, tc)
defer CloseClient(context.Background(), t, tc)

assert.Equal(t, customClient, tc.HTTPClient())
})
}

// TestWithCustomCachestore will test the method WithCustomCachestore()
func TestWithCustomCachestore(t *testing.T) {
t.Parallel()
Expand Down
2 changes: 0 additions & 2 deletions engine/definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ const (
defaultCacheLockTTW = 10 // in Seconds
defaultDatabaseReadTimeout = 20 * time.Second // For all "GET" or "SELECT" methods
defaultDraftTxExpiresIn = 20 * time.Second // Default TTL for draft transactions
defaultHTTPTimeout = 20 * time.Second // Default timeout for HTTP requests
defaultOverheadSize = uint64(8) // 8 bytes is the default overhead in a transaction = 4 bytes version + 4 bytes nLockTime
defaultQueryTxTimeout = 10 * time.Second // Default timeout for syncing on-chain information
defaultUserAgent = "spv-wallet: " + version // Default user agent
dustLimit = uint64(1) // Dust limit
sqliteTestVersion = "3.37.0" // SQLite Testing Version (dummy version for now)
Expand Down
1 change: 0 additions & 1 deletion engine/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ type ClientService interface {
Cluster() cluster.ClientInterface
Chainstate() chainstate.ClientInterface
Datastore() datastore.ClientInterface
HTTPClient() HTTPInterface
Logger() *zerolog.Logger
Notifications() *notifications.Notifications
PaymailClient() paymail.ClientInterface
Expand Down

0 comments on commit 4a1ca37

Please sign in to comment.