diff --git a/http.go b/http.go index a9fd69f..0569d94 100644 --- a/http.go +++ b/http.go @@ -38,7 +38,7 @@ func (wc *WalletClient) SetAdminKey(adminKey *bip32.ExtendedKey) { func (wc *WalletClient) GetXPub(ctx context.Context) (*models.Xpub, ResponseError) { var xPub models.Xpub if err := wc.doHTTPRequest( - ctx, http.MethodGet, "/xpub", nil, wc.xPriv, true, &xPub, + ctx, http.MethodGet, "/xpub", nil, wc.getPrivKey(), true, &xPub, ); err != nil { return nil, err } @@ -57,7 +57,7 @@ func (wc *WalletClient) UpdateXPubMetadata(ctx context.Context, metadata *models var xPub models.Xpub if err := wc.doHTTPRequest( - ctx, http.MethodPatch, "/xpub", jsonStr, wc.xPriv, true, &xPub, + ctx, http.MethodPatch, "/xpub", jsonStr, wc.getPrivKey(), true, &xPub, ); err != nil { return nil, err } @@ -69,7 +69,7 @@ func (wc *WalletClient) UpdateXPubMetadata(ctx context.Context, metadata *models func (wc *WalletClient) GetAccessKey(ctx context.Context, id string) (*models.AccessKey, ResponseError) { var accessKey models.AccessKey if err := wc.doHTTPRequest( - ctx, http.MethodGet, "/access-key?"+FieldID+"="+id, nil, wc.xPriv, true, &accessKey, + ctx, http.MethodGet, "/access-key?"+FieldID+"="+id, nil, wc.getPrivKey(), true, &accessKey, ); err != nil { return nil, err } @@ -87,7 +87,7 @@ func (wc *WalletClient) GetAccessKeys(ctx context.Context, metadataConditions *m } var accessKey []*models.AccessKey if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/access-key/search", jsonStr, wc.xPriv, true, &accessKey, + ctx, http.MethodPost, "/access-key/search", jsonStr, wc.getPrivKey(), true, &accessKey, ); err != nil { return nil, err } @@ -107,7 +107,7 @@ func (wc *WalletClient) GetAccessKeysCount(ctx context.Context, conditions map[s var count int64 if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/access-key/count", jsonStr, wc.xPriv, true, &count, + ctx, http.MethodPost, "/access-key/count", jsonStr, wc.getPrivKey(), true, &count, ); err != nil { return 0, err } @@ -119,7 +119,7 @@ func (wc *WalletClient) GetAccessKeysCount(ctx context.Context, conditions map[s func (wc *WalletClient) RevokeAccessKey(ctx context.Context, id string) (*models.AccessKey, ResponseError) { var accessKey models.AccessKey if err := wc.doHTTPRequest( - ctx, http.MethodDelete, "/access-key?"+FieldID+"="+id, nil, wc.xPriv, true, &accessKey, + ctx, http.MethodDelete, "/access-key?"+FieldID+"="+id, nil, wc.getPrivKey(), true, &accessKey, ); err != nil { return nil, err } @@ -137,7 +137,7 @@ func (wc *WalletClient) CreateAccessKey(ctx context.Context, metadata *models.Me } var accessKey models.AccessKey if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/access-key", jsonStr, wc.xPriv, true, &accessKey, + ctx, http.MethodPost, "/access-key", jsonStr, wc.getPrivKey(), true, &accessKey, ); err != nil { return nil, err } @@ -149,7 +149,7 @@ func (wc *WalletClient) CreateAccessKey(ctx context.Context, metadata *models.Me func (wc *WalletClient) GetDestinationByID(ctx context.Context, id string) (*models.Destination, ResponseError) { var destination models.Destination if err := wc.doHTTPRequest( - ctx, http.MethodGet, "/destination?"+FieldID+"="+id, nil, wc.xPriv, true, &destination, + ctx, http.MethodGet, "/destination?"+FieldID+"="+id, nil, wc.getPrivKey(), true, &destination, ); err != nil { return nil, err } @@ -161,7 +161,7 @@ func (wc *WalletClient) GetDestinationByID(ctx context.Context, id string) (*mod func (wc *WalletClient) GetDestinationByAddress(ctx context.Context, address string) (*models.Destination, ResponseError) { var destination models.Destination if err := wc.doHTTPRequest( - ctx, http.MethodGet, "/destination?"+FieldAddress+"="+address, nil, wc.xPriv, true, &destination, + ctx, http.MethodGet, "/destination?"+FieldAddress+"="+address, nil, wc.getPrivKey(), true, &destination, ); err != nil { return nil, err } @@ -173,7 +173,7 @@ func (wc *WalletClient) GetDestinationByAddress(ctx context.Context, address str func (wc *WalletClient) GetDestinationByLockingScript(ctx context.Context, lockingScript string) (*models.Destination, ResponseError) { var destination models.Destination if err := wc.doHTTPRequest( - ctx, http.MethodGet, "/destination?"+FieldLockingScript+"="+lockingScript, nil, wc.xPriv, true, &destination, + ctx, http.MethodGet, "/destination?"+FieldLockingScript+"="+lockingScript, nil, wc.getPrivKey(), true, &destination, ); err != nil { return nil, err } @@ -191,7 +191,7 @@ func (wc *WalletClient) GetDestinations(ctx context.Context, metadataConditions } var destinations []*models.Destination if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/destination/search", jsonStr, wc.xPriv, true, &destinations, + ctx, http.MethodPost, "/destination/search", jsonStr, wc.getPrivKey(), true, &destinations, ); err != nil { return nil, err } @@ -211,7 +211,7 @@ func (wc *WalletClient) GetDestinationsCount(ctx context.Context, conditions map var count int64 if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/destination/count", jsonStr, wc.xPriv, true, &count, + ctx, http.MethodPost, "/destination/count", jsonStr, wc.getPrivKey(), true, &count, ); err != nil { return 0, err } @@ -229,7 +229,7 @@ func (wc *WalletClient) NewDestination(ctx context.Context, metadata *models.Met } var destination models.Destination if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/destination", jsonStr, wc.xPriv, true, &destination, + ctx, http.MethodPost, "/destination", jsonStr, wc.getPrivKey(), true, &destination, ); err != nil { return nil, err } @@ -251,7 +251,7 @@ func (wc *WalletClient) UpdateDestinationMetadataByID(ctx context.Context, id st var destination models.Destination if err := wc.doHTTPRequest( - ctx, http.MethodPatch, "/destination", jsonStr, wc.xPriv, true, &destination, + ctx, http.MethodPatch, "/destination", jsonStr, wc.getPrivKey(), true, &destination, ); err != nil { return nil, err } @@ -273,7 +273,7 @@ func (wc *WalletClient) UpdateDestinationMetadataByAddress(ctx context.Context, var destination models.Destination if err := wc.doHTTPRequest( - ctx, http.MethodPatch, "/destination", jsonStr, wc.xPriv, true, &destination, + ctx, http.MethodPatch, "/destination", jsonStr, wc.getPrivKey(), true, &destination, ); err != nil { return nil, err } @@ -295,7 +295,7 @@ func (wc *WalletClient) UpdateDestinationMetadataByLockingScript(ctx context.Con var destination models.Destination if err := wc.doHTTPRequest( - ctx, http.MethodPatch, "/destination", jsonStr, wc.xPriv, true, &destination, + ctx, http.MethodPatch, "/destination", jsonStr, wc.getPrivKey(), true, &destination, ); err != nil { return nil, err } @@ -306,7 +306,7 @@ func (wc *WalletClient) UpdateDestinationMetadataByLockingScript(ctx context.Con // GetTransaction will get a transaction by ID func (wc *WalletClient) GetTransaction(ctx context.Context, txID string) (*models.Transaction, ResponseError) { var transaction models.Transaction - if err := wc.doHTTPRequest(ctx, http.MethodGet, "/transaction?"+FieldID+"="+txID, nil, wc.xPriv, *wc.signRequest, &transaction); err != nil { + if err := wc.doHTTPRequest(ctx, http.MethodGet, "/transaction?"+FieldID+"="+txID, nil, wc.getPrivKey(), *wc.signRequest, &transaction); err != nil { return nil, err } @@ -326,7 +326,7 @@ func (wc *WalletClient) GetTransactions(ctx context.Context, conditions map[stri var transactions []*models.Transaction if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/transaction/search", jsonStr, wc.xPriv, *wc.signRequest, &transactions, + ctx, http.MethodPost, "/transaction/search", jsonStr, wc.getPrivKey(), *wc.signRequest, &transactions, ); err != nil { return nil, err } @@ -348,7 +348,7 @@ func (wc *WalletClient) GetTransactionsCount(ctx context.Context, conditions map var count int64 if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/transaction/count", jsonStr, wc.xPriv, *wc.signRequest, &count, + ctx, http.MethodPost, "/transaction/count", jsonStr, wc.getPrivKey(), *wc.signRequest, &count, ); err != nil { return 0, err } @@ -398,7 +398,7 @@ func (wc *WalletClient) createDraftTransaction(ctx context.Context, var draftTransaction *models.DraftTransaction if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/transaction", jsonStr, wc.xPriv, true, &draftTransaction, + ctx, http.MethodPost, "/transaction", jsonStr, wc.getPrivKey(), true, &draftTransaction, ); err != nil { return nil, err } @@ -424,7 +424,7 @@ func (wc *WalletClient) RecordTransaction(ctx context.Context, hex, referenceID var transaction models.Transaction if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/transaction/record", jsonStr, wc.xPriv, *wc.signRequest, &transaction, + ctx, http.MethodPost, "/transaction/record", jsonStr, wc.getPrivKey(), *wc.signRequest, &transaction, ); err != nil { return nil, err } @@ -446,7 +446,7 @@ func (wc *WalletClient) UpdateTransactionMetadata(ctx context.Context, txID stri var transaction models.Transaction if err := wc.doHTTPRequest( - ctx, http.MethodPatch, "/transaction", jsonStr, wc.xPriv, *wc.signRequest, &transaction, + ctx, http.MethodPatch, "/transaction", jsonStr, wc.getPrivKey(), *wc.signRequest, &transaction, ); err != nil { return nil, err } @@ -476,7 +476,7 @@ func (wc *WalletClient) GetUtxo(ctx context.Context, txID string, outputIndex ui var utxo models.Utxo if err := wc.doHTTPRequest( - ctx, http.MethodGet, url, nil, wc.xPriv, true, &utxo, + ctx, http.MethodGet, url, nil, wc.getPrivKey(), true, &utxo, ); err != nil { return nil, err } @@ -497,7 +497,7 @@ func (wc *WalletClient) GetUtxos(ctx context.Context, conditions map[string]inte var utxos []*models.Utxo if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/utxo/search", jsonStr, wc.xPriv, *wc.signRequest, &utxos, + ctx, http.MethodPost, "/utxo/search", jsonStr, wc.getPrivKey(), *wc.signRequest, &utxos, ); err != nil { return nil, err } @@ -517,7 +517,7 @@ func (wc *WalletClient) GetUtxosCount(ctx context.Context, conditions map[string var count int64 if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/utxo/count", jsonStr, wc.xPriv, *wc.signRequest, &count, + ctx, http.MethodPost, "/utxo/count", jsonStr, wc.getPrivKey(), *wc.signRequest, &count, ); err != nil { return 0, err } @@ -625,7 +625,7 @@ func (wc *WalletClient) authenticateWithAccessKey(req *http.Request, rawJSON []b // AcceptContact will accept the contact associated with the paymail func (wc *WalletClient) AcceptContact(ctx context.Context, paymail string) ResponseError { if err := wc.doHTTPRequest( - ctx, http.MethodPatch, "/contact/accepted/"+paymail, nil, wc.xPriv, *wc.signRequest, nil, + ctx, http.MethodPatch, "/contact/accepted/"+paymail, nil, wc.getPrivKey(), *wc.signRequest, nil, ); err != nil { return err } @@ -636,7 +636,7 @@ func (wc *WalletClient) AcceptContact(ctx context.Context, paymail string) Respo // RejectContact will reject the contact associated with the paymail func (wc *WalletClient) RejectContact(ctx context.Context, paymail string) ResponseError { if err := wc.doHTTPRequest( - ctx, http.MethodPatch, "/contact/rejected/"+paymail, nil, wc.xPriv, *wc.signRequest, nil, + ctx, http.MethodPatch, "/contact/rejected/"+paymail, nil, wc.getPrivKey(), *wc.signRequest, nil, ); err != nil { return err } @@ -656,7 +656,7 @@ func (wc *WalletClient) ConfirmContact(ctx context.Context, contact *models.Cont } if err := wc.doHTTPRequest( - ctx, http.MethodPatch, "/contact/confirmed/"+contact.Paymail, nil, wc.xPriv, *wc.signRequest, nil, + ctx, http.MethodPatch, "/contact/confirmed/"+contact.Paymail, nil, wc.getPrivKey(), *wc.signRequest, nil, ); err != nil { return err } @@ -677,7 +677,7 @@ func (wc *WalletClient) GetContacts(ctx context.Context, conditions map[string]i var result []*models.Contact if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/contact/search", jsonStr, wc.xPriv, *wc.signRequest, &result, + ctx, http.MethodPost, "/contact/search", jsonStr, wc.getPrivKey(), *wc.signRequest, &result, ); err != nil { return nil, err } @@ -707,7 +707,7 @@ func (wc *WalletClient) UpsertContactForPaymail(ctx context.Context, paymail, fu var result models.Contact if err := wc.doHTTPRequest( - ctx, http.MethodPut, "/contact/"+paymail, jsonStr, wc.xPriv, *wc.signRequest, &result, + ctx, http.MethodPut, "/contact/"+paymail, jsonStr, wc.getPrivKey(), *wc.signRequest, &result, ); err != nil { return nil, err } @@ -741,7 +741,7 @@ func (wc *WalletClient) AdminNewXpub(ctx context.Context, rawXPub string, metada func (wc *WalletClient) AdminGetStatus(ctx context.Context) (bool, ResponseError) { var status bool if err := wc.doHTTPRequest( - ctx, http.MethodGet, "/admin/status", nil, wc.xPriv, true, &status, + ctx, http.MethodGet, "/admin/status", nil, wc.getPrivKey(), true, &status, ); err != nil { return false, err } @@ -753,7 +753,7 @@ func (wc *WalletClient) AdminGetStatus(ctx context.Context) (bool, ResponseError func (wc *WalletClient) AdminGetStats(ctx context.Context) (*models.AdminStats, ResponseError) { var stats *models.AdminStats if err := wc.doHTTPRequest( - ctx, http.MethodGet, "/admin/stats", nil, wc.xPriv, true, &stats, + ctx, http.MethodGet, "/admin/stats", nil, wc.getPrivKey(), true, &stats, ); err != nil { return nil, err } @@ -829,7 +829,7 @@ func (wc *WalletClient) AdminGetPaymail(ctx context.Context, address string) (*m var model *models.PaymailAddress if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/admin/paymail/get", jsonStr, wc.xPriv, true, &model, + ctx, http.MethodPost, "/admin/paymail/get", jsonStr, wc.getPrivKey(), true, &model, ); err != nil { return nil, err } @@ -870,7 +870,7 @@ func (wc *WalletClient) AdminCreatePaymail(ctx context.Context, rawXPub string, var model *models.PaymailAddress if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/admin/paymail/create", jsonStr, wc.xPriv, true, &model, + ctx, http.MethodPost, "/admin/paymail/create", jsonStr, wc.getPrivKey(), true, &model, ); err != nil { return nil, err } @@ -888,7 +888,7 @@ func (wc *WalletClient) AdminDeletePaymail(ctx context.Context, address string) } if err := wc.doHTTPRequest( - ctx, http.MethodDelete, "/admin/paymail/delete", jsonStr, wc.xPriv, true, nil, + ctx, http.MethodDelete, "/admin/paymail/delete", jsonStr, wc.getPrivKey(), true, nil, ); err != nil { return err } @@ -966,7 +966,7 @@ func (wc *WalletClient) adminGetModels(ctx context.Context, conditions map[strin } if err := wc.doHTTPRequest( - ctx, http.MethodPost, path, jsonStr, wc.xPriv, true, &models, + ctx, http.MethodPost, path, jsonStr, wc.getPrivKey(), true, &models, ); err != nil { return err } @@ -985,7 +985,7 @@ func (wc *WalletClient) adminCount(ctx context.Context, conditions map[string]in var count int64 if err := wc.doHTTPRequest( - ctx, http.MethodPost, path, jsonStr, wc.xPriv, true, &count, + ctx, http.MethodPost, path, jsonStr, wc.getPrivKey(), true, &count, ); err != nil { return 0, err } @@ -1004,7 +1004,7 @@ func (wc *WalletClient) AdminRecordTransaction(ctx context.Context, hex string) var transaction models.Transaction if err := wc.doHTTPRequest( - ctx, http.MethodPost, "/admin/transactions/record", jsonStr, wc.xPriv, *wc.signRequest, &transaction, + ctx, http.MethodPost, "/admin/transactions/record", jsonStr, wc.getPrivKey(), *wc.signRequest, &transaction, ); err != nil { return nil, err } @@ -1016,7 +1016,7 @@ func (wc *WalletClient) AdminRecordTransaction(ctx context.Context, hex string) func (wc *WalletClient) AdminGetSharedConfig(ctx context.Context) (*models.SharedConfig, ResponseError) { var model *models.SharedConfig if err := wc.doHTTPRequest( - ctx, http.MethodGet, "/admin/shared-config", nil, wc.xPriv, true, &model, + ctx, http.MethodGet, "/admin/shared-config", nil, wc.getPrivKey(), true, &model, ); err != nil { return nil, err } @@ -1076,7 +1076,7 @@ func (wc *WalletClient) AdminRejectContact(ctx context.Context, id string) (*mod // FinalizeTransaction will finalize the transaction func (wc *WalletClient) FinalizeTransaction(draft *models.DraftTransaction) (string, ResponseError) { - res, err := GetSignedHex(draft, wc.xPriv) + res, err := GetSignedHex(draft, wc.getPrivKey()) if err != nil { return "", WrapError(err) } diff --git a/walletclient.go b/walletclient.go index f350025..bf5e643 100644 --- a/walletclient.go +++ b/walletclient.go @@ -1,6 +1,7 @@ package walletclient import ( + "fmt" "net/http" "github.com/bitcoin-sv/spv-wallet/models" @@ -29,7 +30,6 @@ type WalletClient struct { // It configures the client with a specific server URL and a flag indicating whether requests should be signed. // - `xPriv`: The extended private key used for cryptographic operations. // - `serverURL`: The URL of the server the client will interact with. -// - `sign`: A boolean flag to determine if the outgoing requests should be signed. func NewWithXPriv(xPriv, serverURL string) (*WalletClient, error) { return newWalletClient( &WithXPriv{XPrivString: &xPriv}, @@ -42,7 +42,6 @@ func NewWithXPriv(xPriv, serverURL string) (*WalletClient, error) { // This client is configured for operations that require a public key, such as verifying signatures or receiving transactions. // - `xPub`: The extended public key used for cryptographic verification and other public operations. // - `serverURL`: The URL of the server the client will interact with. -// - `sign`: A boolean flag to determine if the outgoing requests should be signed. func NewWithXPub(xPub, serverURL string) (*WalletClient, error) { return newWalletClient( &WithXPub{XPubString: &xPub}, @@ -55,10 +54,8 @@ func NewWithXPub(xPub, serverURL string) (*WalletClient, error) { // This configuration is typically used for administrative tasks such as managing sub-wallets or configuring system-wide settings. // - `adminKey`: The extended private key used for administrative operations. // - `serverURL`: The URL of the server the client will interact with. -// - `sign`: A boolean flag to determine if the outgoing requests should be signed. func NewWithAdminKey(adminKey, serverURL string) (*WalletClient, error) { return newWalletClient( - &WithXPriv{XPrivString: &adminKey}, // this need to be removed .. pls ignore for now &WithAdminKey{AdminKeyString: &adminKey}, &WithHTTP{ServerURL: &serverURL}, &WithSignRequest{Sign: Ptr(true)}, @@ -69,7 +66,6 @@ func NewWithAdminKey(adminKey, serverURL string) (*WalletClient, error) { // This method is useful for scenarios where the client needs to authenticate using a less sensitive key than an xPriv. // - `accessKey`: The access key used for API authentication. // - `serverURL`: The URL of the server the client will interact with. -// - `sign`: A boolean flag to determine if the outgoing requests should be signed. func NewWithAccessKey(accessKey, serverURL string) (*WalletClient, error) { return newWalletClient( &WithAccessKey{AccessKeyString: &accessKey}, @@ -97,6 +93,7 @@ func newWalletClient(configurators ...WalletClientConfigurator) (*WalletClient, // initializeKeys handles the initialization of keys based on the existing fields. func (c *WalletClient) initializeKeys() error { var err error + fmt.Printf("===== %+v\n", c) switch { case c.xPrivString != nil: if c.xPriv, err = bitcoin.GenerateHDKeyFromString(*c.xPrivString); err != nil { @@ -111,6 +108,8 @@ func (c *WalletClient) initializeKeys() error { } case c.accessKeyString != nil: return c.initializeAccessKey() + case c.adminXPriv != nil: + return nil default: return errors.New("no keys provided for initialization") } @@ -153,3 +152,11 @@ func addSignature(header *http.Header, xPriv *bip32.ExtendedKey, bodyString stri func Ptr[T any](obj T) *T { return &obj } + +// getPrivKey retrieves the client's private key. If the primary key is not set, +func (wc *WalletClient) getPrivKey() *bip32.ExtendedKey { + if wc.adminXPriv != nil { + return wc.adminXPriv + } + return wc.xPriv +} diff --git a/walletclient_test.go b/walletclient_test.go index 6f1313f..b03bca4 100644 --- a/walletclient_test.go +++ b/walletclient_test.go @@ -70,7 +70,7 @@ func TestNewWalletClient(t *testing.T) { client, err := NewWithAdminKey(fixtures.XPrivString, server.URL) require.NoError(t, err) require.NotNil(t, client) - require.Equal(t, fixtures.XPrivString, *client.xPrivString) + require.Nil(t, client.xPrivString) require.Equal(t, fixtures.XPrivString, client.adminXPriv.String()) require.Equal(t, server.URL, *client.server) require.NotNil(t, client.httpClient)