Skip to content

Commit

Permalink
Merge pull request #403 from BuxOrg/fix-461-arc-fee-quotes
Browse files Browse the repository at this point in the history
fix(BUX-461) fee quotes for both arc and mAPI with user defined fee quote
  • Loading branch information
chris-4chain authored Jan 12, 2024
2 parents 85cbe7a + b5f0a56 commit eda28a6
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 25 deletions.
4 changes: 4 additions & 0 deletions config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 10 additions & 8 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down
4 changes: 1 addition & 3 deletions config/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,7 @@ func getNodesDefaults() *NodesConfig {
MinerID: "03ad780153c47df915b3d2e23af727c68facaca4facd5f155bf5018b979b9aeb83",
},
},
Mapi: &MapiConfig{
UseFeeQuotes: true,
},
UseFeeQuotes: true,
}
}

Expand Down
12 changes: 9 additions & 3 deletions config/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -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...)

Expand Down Expand Up @@ -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
}
4 changes: 4 additions & 0 deletions config/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,9 @@ func (a *AppConfig) Validate() error {
return err
}

if err = a.Nodes.Validate(); err != nil {
return err
}

return nil
}
40 changes: 35 additions & 5 deletions config/validate_nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 != ""
}
23 changes: 23 additions & 0 deletions config/validate_nodes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
})
}
4 changes: 2 additions & 2 deletions go.mod

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

8 changes: 4 additions & 4 deletions go.sum

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

0 comments on commit eda28a6

Please sign in to comment.