Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(SPV-912): handle invalid configuration #270

Merged
merged 1 commit into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion access_keys_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ func TestAccessKeys(t *testing.T) {
}))
defer server.Close()

client := NewWithAccessKey(server.URL, fixtures.AccessKeyString)
client, err := NewWithAccessKey(server.URL, fixtures.AccessKeyString)
require.NoError(t, err)
require.NotNil(t, client.accessKey)

t.Run("GetAccessKey", func(t *testing.T) {
Expand Down
3 changes: 2 additions & 1 deletion admin_contacts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ func TestAdminContactActions(t *testing.T) {
}))
defer server.Close()

client := NewWithAdminKey(server.URL, fixtures.XPrivString)
client, err := NewWithAdminKey(server.URL, fixtures.XPrivString)
require.NoError(t, err)
require.NotNil(t, client.adminXPriv)

t.Run("AdminGetContacts", func(t *testing.T) {
Expand Down
56 changes: 31 additions & 25 deletions client_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,63 +7,81 @@ import (

bip32 "github.com/bitcoin-sv/go-sdk/compat/bip32"
ec "github.com/bitcoin-sv/go-sdk/primitives/ec"

"github.com/pkg/errors"
)

// configurator is the interface for configuring WalletClient
type configurator interface {
Configure(c *WalletClient)
Configure(c *WalletClient) error
}

// xPrivConf sets the xPrivString field of a WalletClient
type xPrivConf struct {
XPrivString string
}

func (w *xPrivConf) Configure(c *WalletClient) {
func (w *xPrivConf) Configure(c *WalletClient) error {
var err error
if c.xPriv, err = bip32.GenerateHDKeyFromString(w.XPrivString); err != nil {
c.xPriv = nil
return ErrInvalidXpriv.Wrap(err)
}
return nil
}

// xPubConf sets the xPubString on the client
type xPubConf struct {
XPubString string
}

func (w *xPubConf) Configure(c *WalletClient) {
func (w *xPubConf) Configure(c *WalletClient) error {
var err error
if c.xPub, err = bip32.GetHDKeyFromExtendedPublicKey(w.XPubString); err != nil {
c.xPub = nil
return ErrInvalidXpub.Wrap(err)
}

return nil
}

// accessKeyConf sets the accessKeyString on the client
type accessKeyConf struct {
AccessKeyString string
}

func (w *accessKeyConf) Configure(c *WalletClient) {
func (w *accessKeyConf) Configure(c *WalletClient) error {
var err error
if c.accessKey, err = w.initializeAccessKey(); err != nil {
c.accessKey = nil
return err
}
return nil
}

func (w *accessKeyConf) initializeAccessKey() (*ec.PrivateKey, error) {
var errPriv, errPub error
privateKey, errPriv := ec.PrivateKeyFromWif(w.AccessKeyString)
if errPriv != nil {
privateKey, errPub = ec.PrivateKeyFromHex(w.AccessKeyString)
if privateKey == nil {
return nil, ErrInvalidAccessKey.Wrap(errPriv).Wrap(errPub)
}
}

return privateKey, nil
}

// adminKeyConf sets the admin key for creating new xpubs
type adminKeyConf struct {
AdminKeyString string
}

func (w *adminKeyConf) Configure(c *WalletClient) {
func (w *adminKeyConf) Configure(c *WalletClient) error {
var err error
c.adminXPriv, err = bip32.GenerateHDKeyFromString(w.AdminKeyString)
if err != nil {
c.adminXPriv = nil
return ErrInvalidAdminKey.Wrap(err)
}
return nil
}

// httpConf sets the URL and httpConf client of a WalletClient
Expand All @@ -72,13 +90,11 @@ type httpConf struct {
HTTPClient *http.Client
}

func (w *httpConf) Configure(c *WalletClient) {
func (w *httpConf) Configure(c *WalletClient) error {
// Ensure the ServerURL ends with a clean base URL
baseURL, err := validateAndCleanURL(w.ServerURL)
if err != nil {
// Handle the error appropriately
fmt.Println("Invalid URL provided:", err)
return
return ErrInvalidServerURL.Wrap(err)
}

const basePath = "/v1"
Expand All @@ -90,27 +106,17 @@ func (w *httpConf) Configure(c *WalletClient) {
} else {
c.httpClient = http.DefaultClient
}
return nil
}

// signRequest configures whether to sign HTTP requests
type signRequest struct {
Sign bool
}

func (w *signRequest) Configure(c *WalletClient) {
func (w *signRequest) Configure(c *WalletClient) error {
c.signRequest = w.Sign
}

func (w *accessKeyConf) initializeAccessKey() (*ec.PrivateKey, error) {
privateKey, err := ec.PrivateKeyFromWif(w.AccessKeyString)
if err != nil {
privateKey, _ = ec.PrivateKeyFromHex(w.AccessKeyString)
if privateKey == nil {
return nil, errors.New("failed to decode access key")
}
}

return privateKey, nil
return nil
}

// validateAndCleanURL ensures that the provided URL is valid, and strips it down to just the base URL.
Expand Down
3 changes: 2 additions & 1 deletion contacts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ func TestContactActionsRouting(t *testing.T) {
}))
defer server.Close()

client := NewWithAccessKey(server.URL, fixtures.AccessKeyString)
client, err := NewWithAccessKey(server.URL, fixtures.AccessKeyString)
require.NoError(t, err)
require.NotNil(t, client.accessKey)

t.Run("RejectContact", func(t *testing.T) {
Expand Down
3 changes: 2 additions & 1 deletion destinations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ func TestDestinations(t *testing.T) {
}
}))
defer server.Close()
client := NewWithAccessKey(server.URL, fixtures.AccessKeyString)
client, err := NewWithAccessKey(server.URL, fixtures.AccessKeyString)
require.NoError(t, err)
require.NotNil(t, client.accessKey)

t.Run("GetDestinationByID", func(t *testing.T) {
Expand Down
18 changes: 18 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,24 @@ var ErrAdminKey = models.SPVError{Message: "an admin key must be set to be able
// ErrMissingXpriv is when xpriv is missing
var ErrMissingXpriv = models.SPVError{Message: "xpriv is missing", StatusCode: 401, Code: "error-unauthorized-xpriv-missing"}

// ErrInvalidXpriv is when xpriv is invalid
var ErrInvalidXpriv = models.SPVError{Message: "xpriv is invalid", StatusCode: 401, Code: "error-unauthorized-xpriv-invalid"}

// ErrInvalidXpub is when xpub is invalid
var ErrInvalidXpub = models.SPVError{Message: "xpub is invalid", StatusCode: 401, Code: "error-unauthorized-xpub-invalid"}

// ErrInvalidAccessKey is when access key is invalid
var ErrInvalidAccessKey = models.SPVError{Message: "access key is invalid", StatusCode: 401, Code: "error-unauthorized-access-key-invalid"}

// ErrInvalidAdminKey is when admin key is invalid
var ErrInvalidAdminKey = models.SPVError{Message: "admin key is invalid", StatusCode: 401, Code: "error-unauthorized-admin-key-invalid"}

// ErrInvalidServerURL is when server url is invalid
var ErrInvalidServerURL = models.SPVError{Message: "server url is invalid", StatusCode: 401, Code: "error-unauthorized-server-url-invalid"}

// ErrCreateClient is when client creation fails
var ErrCreateClient = models.SPVError{Message: "failed to create client", StatusCode: 500, Code: "error-create-client-failed"}

// ErrMissingKey is when neither xPriv nor adminXPriv is provided
var ErrMissingKey = models.SPVError{Message: "neither xPriv nor adminXPriv is provided", StatusCode: 404, Code: "error-shared-config-key-missing"}

Expand Down
8 changes: 6 additions & 2 deletions examples/admin_add_user/admin_add_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ func main() {

server := "http://localhost:3003/v1"

adminClient := walletclient.NewWithAdminKey(server, examples.ExampleAdminKey)
adminClient, err := walletclient.NewWithAdminKey(server, examples.ExampleAdminKey)
if err != nil {
examples.GetFullErrorMessage(err)
os.Exit(1)
}
ctx := context.Background()

metadata := map[string]any{"some_metadata": "example"}

err := adminClient.AdminNewXpub(ctx, examples.ExampleXPub, metadata)
err = adminClient.AdminNewXpub(ctx, examples.ExampleXPub, metadata)
if err != nil {
examples.GetFullErrorMessage(err)
os.Exit(1)
Expand Down
8 changes: 6 additions & 2 deletions examples/admin_remove_user/admin_remove_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ func main() {

const server = "http://localhost:3003/v1"

adminClient := walletclient.NewWithAdminKey(server, examples.ExampleAdminKey)
adminClient, err := walletclient.NewWithAdminKey(server, examples.ExampleAdminKey)
if err != nil {
examples.GetFullErrorMessage(err)
os.Exit(1)
}
ctx := context.Background()

err := adminClient.AdminDeletePaymail(ctx, examples.ExamplePaymail)
err = adminClient.AdminDeletePaymail(ctx, examples.ExamplePaymail)
if err != nil {
examples.GetFullErrorMessage(err)
os.Exit(1)
Expand Down
6 changes: 5 additions & 1 deletion examples/create_transaction/create_transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ func main() {

const server = "http://localhost:3003/v1"

client := walletclient.NewWithXPriv(server, examples.ExampleXPriv)
client, err := walletclient.NewWithXPriv(server, examples.ExampleXPriv)
if err != nil {
examples.GetFullErrorMessage(err)
os.Exit(1)
}
ctx := context.Background()

recipient := walletclient.Recipients{To: "[email protected]", Satoshis: 1}
Expand Down
10 changes: 7 additions & 3 deletions examples/generate_totp/generate_totp.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ func main() {
const digits = 4
const period = 1200 // 20 minutes

client := walletclient.NewWithXPriv(server, aliceXPriv)
client, err := walletclient.NewWithXPriv(server, aliceXPriv)
if err != nil {
examples.GetFullErrorMessage(err)
os.Exit(1)
}

mockContact := &models.Contact{
PubKey: bobPKI,
Expand All @@ -30,14 +34,14 @@ func main() {

totpCode, err := client.GenerateTotpForContact(mockContact, period, digits)
if err != nil {
fmt.Println(err)
examples.GetFullErrorMessage(err)
os.Exit(1)
}
fmt.Println("TOTP code from Alice to Bob: ", totpCode)

valid, err := client.ValidateTotpForContact(mockContact, totpCode, mockContact.Paymail, period, digits)
if err != nil {
fmt.Println(err)
examples.GetFullErrorMessage(err)
os.Exit(1)
}
fmt.Println("Is TOTP code valid: ", valid)
Expand Down
6 changes: 5 additions & 1 deletion examples/get_balance/get_balance.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ func main() {

const server = "http://localhost:3003/v1"

client := walletclient.NewWithXPriv(server, examples.ExampleXPriv)
client, err := walletclient.NewWithXPriv(server, examples.ExampleXPriv)
if err != nil {
examples.GetFullErrorMessage(err)
os.Exit(1)
}
ctx := context.Background()

xpubInfo, err := client.GetXPub(ctx)
Expand Down
2 changes: 1 addition & 1 deletion examples/go.mod

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions examples/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions examples/handle_exceptions/handle_exceptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,17 @@ func main() {

const server = "http://localhost:3003/v1"

client := walletclient.NewWithXPub(server, examples.ExampleAdminKey)
client, err := walletclient.NewWithXPub(server, examples.ExampleAdminKey)
if err != nil {
examples.GetFullErrorMessage(err)
os.Exit(1)
}
ctx := context.Background()

fmt.Println("Client created")

status, err := client.AdminGetStatus(ctx)
if err != nil {
fmt.Println("Error: ", err)
examples.GetFullErrorMessage(err)
os.Exit(1)
}
Expand Down
6 changes: 5 additions & 1 deletion examples/list_transactions/list_transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ func main() {

const server = "http://localhost:3003/v1"

client := walletclient.NewWithXPriv(server, examples.ExampleXPriv)
client, err := walletclient.NewWithXPriv(server, examples.ExampleXPriv)
if err != nil {
examples.GetFullErrorMessage(err)
os.Exit(1)
}
ctx := context.Background()

metadata := map[string]any{}
Expand Down
6 changes: 5 additions & 1 deletion examples/send_op_return/send_op_return.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ func main() {

const server = "http://localhost:3003/v1"
chris-4chain marked this conversation as resolved.
Show resolved Hide resolved

client := walletclient.NewWithXPriv(server, examples.ExampleXPriv)
client, err := walletclient.NewWithXPriv(server, examples.ExampleXPriv)
if err != nil {
examples.GetFullErrorMessage(err)
os.Exit(1)
}
ctx := context.Background()

metadata := map[string]any{}
Expand Down
Loading
Loading