diff --git a/config.example.yaml b/config.example.yaml index 9b5b5a6b3..373296861 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -79,6 +79,10 @@ _nodes: apis: - arc_url: https://arc.gorillapool.io token: + use_fee_quotes: true + fee_unit: + satoshis: 1 + bytes: 1000 # Prefixed with "_", because it's unused by default _notifications: enabled: false diff --git a/config/config.go b/config/config.go index c14d7ba92..a2d9aea45 100644 --- a/config/config.go +++ b/config/config.go @@ -148,9 +148,16 @@ type NewRelicConfig struct { // NodesConfig consists of blockchain nodes (such as Minercraft and Arc) configuration type NodesConfig struct { - Protocol NodesProtocol `json:"protocol" mapstructure:"protocol"` - Apis []*MinerAPI `json:"apis" mapstructure:"apis"` - Mapi *MapiConfig `json:"mapi" mapstructure:"mapi"` + Protocol NodesProtocol `json:"protocol" mapstructure:"protocol"` + Apis []*MinerAPI `json:"apis" mapstructure:"apis"` + UseFeeQuotes bool `json:"use_fee_quotes" mapstructure:"use_fee_quotes"` + FeeUnit *FeeUnitConfig `json:"fee_unit" mapstructure:"fee_unit"` +} + +// FeeUnitConfig reflects the utils.FeeUnit struct with proper annotations for json and mapstructure +type FeeUnitConfig struct { + Satoshis int `json:"satoshis" mapstructure:"satoshis"` + Bytes int `json:"bytes" mapstructure:"bytes"` } // MinerAPI holds connection info for a single miner endpoint @@ -163,11 +170,6 @@ type MinerAPI struct { MinerID string `json:"minerid" mapstructure:"minerid"` } -// MapiConfig holds mApi-specific configuration -type MapiConfig struct { - UseFeeQuotes bool `json:"use_fee_quotes" mapstructure:"use_fee_quotes"` -} - // NotificationsConfig is the configuration for notifications type NotificationsConfig struct { // Enabled is the flag that enables notifications service. diff --git a/config/defaults.go b/config/defaults.go index d4a99d123..2f97cb927 100644 --- a/config/defaults.go +++ b/config/defaults.go @@ -124,9 +124,7 @@ func getNodesDefaults() *NodesConfig { MinerID: "03ad780153c47df915b3d2e23af727c68facaca4facd5f155bf5018b979b9aeb83", }, }, - Mapi: &MapiConfig{ - UseFeeQuotes: true, - }, + UseFeeQuotes: true, } } diff --git a/config/services.go b/config/services.go index 860c8c2a2..bacc8260b 100644 --- a/config/services.go +++ b/config/services.go @@ -191,6 +191,15 @@ func (s *AppServices) loadBux(ctx context.Context, appConfig *AppConfig, testMod options = loadBroadcastClientArc(appConfig, options, logger) } + options = append(options, bux.WithFeeQuotes(appConfig.Nodes.UseFeeQuotes)) + + if appConfig.Nodes.FeeUnit != nil { + options = append(options, bux.WithFeeUnit(&utils.FeeUnit{ + Satoshis: appConfig.Nodes.FeeUnit.Satoshis, + Bytes: appConfig.Nodes.FeeUnit.Bytes, + })) + } + // Create the new client s.Bux, err = bux.NewClient(ctx, options...) @@ -388,8 +397,5 @@ func loadMinercraftMapi(appConfig *AppConfig, options []bux.ClientOps) []bux.Cli bux.WithMAPI(), bux.WithMinercraftAPIs(appConfig.Nodes.toMinercraftMapi()), ) - if appConfig.Nodes.Mapi != nil && appConfig.Nodes.Mapi.UseFeeQuotes { - options = append(options, bux.WithMinercraftFeeQuotes()) - } return options } diff --git a/config/validate.go b/config/validate.go index 3a91deb1b..cb4af6231 100644 --- a/config/validate.go +++ b/config/validate.go @@ -28,5 +28,9 @@ func (a *AppConfig) Validate() error { return err } + if err = a.Nodes.Validate(); err != nil { + return err + } + return nil } diff --git a/config/validate_nodes.go b/config/validate_nodes.go index 3884f9ad3..1182c1078 100644 --- a/config/validate_nodes.go +++ b/config/validate_nodes.go @@ -20,25 +20,55 @@ func (n *NodesConfig) Validate() error { return errors.New("no miner apis configured") } - // check if at least one mapi url is configured if n.Protocol == NodesProtocolMapi { - found := slices.IndexFunc(n.Apis, func(el *MinerAPI) bool { - return el.MapiURL != "" + // check if at least one mapi url is configured + anyMapiNode := slices.IndexFunc(n.Apis, func(el *MinerAPI) bool { + return isMapiNode(el) }) - if found == -1 { + if anyMapiNode == -1 { return errors.New("no mapi urls configured") } + + wrongMapiNode := slices.IndexFunc(n.Apis, func(el *MinerAPI) bool { + return isMapiNode(el) && el.MinerID == "" + }) + if wrongMapiNode != -1 { + return errors.New("mapi url configured without miner id") + } + + // check if MinerIDs for mAPI nodes are unique + ids := make(map[string]bool) + for _, el := range n.Apis { + if isMapiNode(el) { + if _, ok := ids[el.MinerID]; ok { + return errors.New("miner ids are not unique") + } + ids[el.MinerID] = true + } + } } // check if at least one arc url is configured if n.Protocol == NodesProtocolArc { found := slices.IndexFunc(n.Apis, func(el *MinerAPI) bool { - return el.ArcURL != "" + return isArcNode(el) }) if found == -1 { return errors.New("no arc urls configured") } } + if !n.UseFeeQuotes && n.FeeUnit == nil { + return errors.New("fee unit is not configured, define nodes.fee_unit or set nodes.use_fee_quotes") + } + return nil } + +func isMapiNode(node *MinerAPI) bool { + return node.MapiURL != "" +} + +func isArcNode(node *MinerAPI) bool { + return node.ArcURL != "" +} diff --git a/config/validate_nodes_test.go b/config/validate_nodes_test.go index 151777e98..ae2e37066 100644 --- a/config/validate_nodes_test.go +++ b/config/validate_nodes_test.go @@ -57,4 +57,27 @@ func TestNodesConfig_Validate(t *testing.T) { n.Apis[0].ArcURL = "" assert.Error(t, n.Validate()) }) + + t.Run("mapi url without miner id", func(t *testing.T) { + n := getNodesDefaults() + + n.Protocol = NodesProtocolMapi + n.Apis[0].MapiURL = "http://localhost" + n.Apis[0].MinerID = "" + assert.Error(t, n.Validate()) + }) + + t.Run("mapi url with the same miner id", func(t *testing.T) { + n := getNodesDefaults() + + n.Protocol = NodesProtocolMapi + n.Apis[0].MapiURL = "http://localhost" + n.Apis[0].MinerID = "miner1" + n.Apis = append(n.Apis, &MinerAPI{ + MapiURL: "http://localhost", + MinerID: "miner1", + }) + + assert.Error(t, n.Validate()) + }) } diff --git a/go.mod b/go.mod index 1e09ab05e..37cdf03fe 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,9 @@ go 1.21.5 require ( github.com/99designs/gqlgen v0.17.42 - github.com/BuxOrg/bux v0.12.0 + github.com/BuxOrg/bux v0.13.0 github.com/BuxOrg/bux-models v0.3.0 - github.com/bitcoin-sv/go-broadcast-client v0.15.0 + github.com/bitcoin-sv/go-broadcast-client v0.16.0 github.com/go-ozzo/ozzo-validation v3.6.0+incompatible github.com/go-redis/redis/v8 v8.11.5 github.com/gofrs/uuid v4.4.0+incompatible diff --git a/go.sum b/go.sum index c89750fdb..7d89cb6b8 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/99designs/gqlgen v0.17.42 h1:BVWDOb2VVHQC5k3m6oa0XhDnxltLLrU4so7x/u39Zu4= github.com/99designs/gqlgen v0.17.42/go.mod h1:GQ6SyMhwFbgHR0a8r2Wn8fYgEwPxxmndLFPhU63+cJE= -github.com/BuxOrg/bux v0.12.0 h1:4gzQXTJn2GL141AWDrfTB7KLbK5IiXCsLQBNpQgh9K4= -github.com/BuxOrg/bux v0.12.0/go.mod h1:qqsUfSVqp3IJv5NajpoMcHiAouw+40IX7sBBCclhJvo= +github.com/BuxOrg/bux v0.13.0 h1:ph5JqTJjztOFbC4JPNAW+4KN8w+PXekzK+8ij/2yXEo= +github.com/BuxOrg/bux v0.13.0/go.mod h1:qqsUfSVqp3IJv5NajpoMcHiAouw+40IX7sBBCclhJvo= github.com/BuxOrg/bux-models v0.3.0 h1:+pvpDdYaiIgeOhAO847RK07Vzc+vuUvy2ok/xJevQyg= github.com/BuxOrg/bux-models v0.3.0/go.mod h1:JCpoXxVnKZmCy3rg6nOtLQL5AXh6iEo2tBvcD/qAxEY= github.com/DATA-DOG/go-sqlmock v1.5.1 h1:FK6RCIUSfmbnI/imIICmboyQBkOckutaa6R5YYlLZyo= @@ -30,8 +30,8 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.43.45 h1:2708Bj4uV+ym62MOtBnErm/CDX61C4mFe9V2gXy1caE= github.com/aws/aws-sdk-go v1.43.45/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/bitcoin-sv/go-broadcast-client v0.15.0 h1:e6L/fMFf1zLy06gjtOJMA79ao1L8sMmVYnSwgvNs37U= -github.com/bitcoin-sv/go-broadcast-client v0.15.0/go.mod h1:Hk17oGEO1ocw9Glp7/OooqjKbHF2FdfbkuTUBzOjjBI= +github.com/bitcoin-sv/go-broadcast-client v0.16.0 h1:KadOLv+i9Y6xAOkHsSl2PIECQ59SpUyYurY6Ysvpz5A= +github.com/bitcoin-sv/go-broadcast-client v0.16.0/go.mod h1:GRAliwumNBjEbLRIEkXqIKJpsgmMfjvlIDqgyw/NoJE= github.com/bitcoin-sv/go-paymail v0.11.0 h1:jEfBLLaUUIxN3WnkU9d6Wj9IUen1Xx09dWUHlz3gTnQ= github.com/bitcoin-sv/go-paymail v0.11.0/go.mod h1:wH4jOVM24y7+OS2rLeJpwzJ73abM2rq/aeKZom0lHSk= github.com/bitcoinschema/go-bitcoin/v2 v2.0.5 h1:Sgh5Eb746Zck/46rFDrZZEXZWyO53fMuWYhNoZa1tck=