Skip to content

Commit

Permalink
feat(BUX-641): featch SharedConfig & expose PublicConfig
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-4chain committed Mar 7, 2024
1 parent 8375025 commit 0ca2580
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 0 deletions.
75 changes: 75 additions & 0 deletions domain/config/config_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package config

import (
"slices"
"sync"

backendconfig "github.com/bitcoin-sv/spv-wallet-web-backend/config"
"github.com/bitcoin-sv/spv-wallet-web-backend/domain/users"
"github.com/bitcoin-sv/spv-wallet/models"
"github.com/rs/zerolog"
"github.com/spf13/viper"
)

type ConfigService struct {
adminWalletClient users.AdminWalletClient
log *zerolog.Logger

sharedConfig *models.SharedConfig
publicConfig *PublicConfig
mutex sync.Mutex
}

func NewConfigService(adminWalletClient users.AdminWalletClient, log *zerolog.Logger) *ConfigService {
return &ConfigService{
adminWalletClient: adminWalletClient,
log: log,
sharedConfig: nil,
publicConfig: nil,
}
}

// GetSharedConfig returns shared config.
// If shared config is not cached, it will be fetched from the spv-wallet.
// SharedConfig should not be exposed to the public - use PublicConfig instead.
func (s *ConfigService) GetSharedConfig() *models.SharedConfig {
if s.sharedConfig != nil {
return s.sharedConfig
}

s.mutex.Lock()
defer s.mutex.Unlock()
model, err := s.adminWalletClient.GetSharedConfig()
if err != nil {
s.log.Error().Err(err).Msg("Failed to get shared config")
return nil
}
s.sharedConfig = model
return s.sharedConfig
}

// GetPublicConfig returns public config.
func (s *ConfigService) GetPublicConfig() *PublicConfig {
if s.publicConfig != nil {
return s.publicConfig
}
shared := s.GetSharedConfig()
if shared == nil {
return nil
}

s.publicConfig = s.makePublicConfig(shared)
return s.publicConfig
}

func (s *ConfigService) makePublicConfig(shared *models.SharedConfig) *PublicConfig {
configuredPaymailDomain := viper.GetString(backendconfig.EnvPaymailDomain)
if !slices.Contains(shared.PaymilDomains, configuredPaymailDomain) {
s.log.Warn().Str("configuredPaymailDomain", configuredPaymailDomain).Msg("Configured paymail domain is not in the list of paymail domains from SPV Wallet")
}

return &PublicConfig{
PaymilDomain: configuredPaymailDomain,
ExperimentalFeatures: shared.ExperimentalFeatures,
}
}
8 changes: 8 additions & 0 deletions domain/config/public_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package config

import "github.com/bitcoin-sv/spv-wallet/models"

type PublicConfig struct {
PaymilDomain string `json:"paymail_domain"`
ExperimentalFeatures models.ExperimentalConfig `json:"experimental_features"`
}
3 changes: 3 additions & 0 deletions domain/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package domain

import (
db_users "github.com/bitcoin-sv/spv-wallet-web-backend/data/users"
"github.com/bitcoin-sv/spv-wallet-web-backend/domain/config"
"github.com/bitcoin-sv/spv-wallet-web-backend/domain/transactions"
"github.com/bitcoin-sv/spv-wallet-web-backend/domain/users"
"github.com/bitcoin-sv/spv-wallet-web-backend/transports/spvwallet"
Expand All @@ -14,6 +15,7 @@ type Services struct {
UsersService *users.UserService
TransactionsService *transactions.TransactionService
WalletClientFactory users.WalletClientFactory
ConfigService *config.ConfigService
}

// NewServices creates services instance.
Expand All @@ -31,5 +33,6 @@ func NewServices(usersRepo *db_users.UsersRepository, log *zerolog.Logger) (*Ser
UsersService: uService,
TransactionsService: transactions.NewTransactionService(adminWalletClient, walletClientFactory, log),
WalletClientFactory: walletClientFactory,
ConfigService: config.NewConfigService(adminWalletClient, log),
}, nil
}
1 change: 1 addition & 0 deletions domain/users/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ type (
AdminWalletClient interface {
RegisterXpub(xpriv *bip32.ExtendedKey) (string, error)
RegisterPaymail(alias, xpub string) (string, error)
GetSharedConfig() (*models.SharedConfig, error)
}

// WalletClientFactory defines methods to create user and admin clients.
Expand Down
40 changes: 40 additions & 0 deletions transports/http/endpoints/api/config/endpoints.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package config

import (
"github.com/bitcoin-sv/spv-wallet-web-backend/domain"
router "github.com/bitcoin-sv/spv-wallet-web-backend/transports/http/endpoints/routes"
"github.com/gin-gonic/gin"
)

type handler struct {
services *domain.Services
}

func NewHandler(s *domain.Services) router.RootEndpoints {
handler := &handler{
services: s,
}
prefix := "/api/v1"

rootEndpoints := router.RootEndpointsFunc(func(router *gin.RouterGroup) {
router.GET(prefix+"/config", handler.getPublicConfig)
})

return rootEndpoints
}

// getConfig returns config fields exposed to clients.
//
// @Summary Get config returns config fields exposed to clients
// @Tags sharedconfig
// @Produce json
// @Success 200 {object} PublicConfig
// @Router /api/v1/config [get]
func (h *handler) getPublicConfig(c *gin.Context) {
pubConf := h.services.ConfigService.GetPublicConfig()
if pubConf == nil {
c.JSON(500, "Failed to get public config")
return
}
c.JSON(200, pubConf)
}
2 changes: 2 additions & 0 deletions transports/http/endpoints/wallet_endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/bitcoin-sv/spv-wallet-web-backend/transports/http/auth"
"github.com/bitcoin-sv/spv-wallet-web-backend/transports/http/endpoints/api/access"
"github.com/bitcoin-sv/spv-wallet-web-backend/transports/http/endpoints/api/config"
"github.com/bitcoin-sv/spv-wallet-web-backend/transports/http/endpoints/api/transactions"
"github.com/bitcoin-sv/spv-wallet-web-backend/transports/http/endpoints/api/users"
router "github.com/bitcoin-sv/spv-wallet-web-backend/transports/http/endpoints/routes"
Expand All @@ -31,6 +32,7 @@ func SetupWalletRoutes(s *domain.Services, db *sql.DB, log *zerolog.Logger, ws w
routes := []interface{}{
swagger.NewHandler(),
status.NewHandler(),
config.NewHandler(s),
usersRootEndpoints,
usersApiEndpoints,
accessRootEndpoints,
Expand Down
9 changes: 9 additions & 0 deletions transports/spvwallet/admin_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,12 @@ func (c *AdminWalletClient) RegisterPaymail(alias, xpub string) (string, error)
}
return address, nil
}

func (c *AdminWalletClient) GetSharedConfig() (*models.SharedConfig, error) {
sharedConfig, err := c.client.AdminGetSharedConfig(context.Background())
if err != nil {
c.log.Error().Msgf("Error while getting shared config: %v", err.Error())
return nil, err
}
return sharedConfig, nil
}

0 comments on commit 0ca2580

Please sign in to comment.