diff --git a/api/api_test.go b/api/api_test.go index a6ff1a9..25046fc 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -522,11 +522,16 @@ func TestMain(m *testing.M) { WithdrawalDelay: uint64(3000), } - stateAPIUpdater = stateapiupdater.NewUpdater(hdb, nodeConfig, &common.SCVariables{ + stateAPIUpdater, err = stateapiupdater.NewUpdater(hdb, nodeConfig, &common.SCVariables{ Rollup: rollupVars, Auction: auctionVars, WDelayer: wdelayerVars, - }, constants) + }, constants, &stateapiupdater.RecommendedFeePolicy{ + PolicyType: stateapiupdater.RecommendedFeePolicyTypeAvgLastHour, + }) + if err != nil { + panic(err) + } // Generate test data, as expected to be received/sended from/to the API testCoords := genTestCoordinators(commonCoords) diff --git a/api/stateapiupdater/stateapiupdater.go b/api/stateapiupdater/stateapiupdater.go index d8cc325..e539da6 100644 --- a/api/stateapiupdater/stateapiupdater.go +++ b/api/stateapiupdater/stateapiupdater.go @@ -6,6 +6,7 @@ import ( "github.com/hermeznetwork/hermez-node/common" "github.com/hermeznetwork/hermez-node/db/historydb" + "github.com/hermeznetwork/hermez-node/log" "github.com/hermeznetwork/tracerr" ) @@ -17,11 +18,45 @@ type Updater struct { vars common.SCVariablesPtr consts historydb.Constants rw sync.RWMutex + rfp *RecommendedFeePolicy +} + +// RecommendedFeePolicy describes how the recommended fee is calculated +type RecommendedFeePolicy struct { + PolicyType RecommendedFeePolicyType + StaticValue float64 +} + +// RecommendedFeePolicyType describes the different available recommended fee strategies +type RecommendedFeePolicyType string + +const ( + // Always give the same StaticValue as recommended fee + RecommendedFeePolicyTypeStatic RecommendedFeePolicyType = "Static" + // Set the recommended fee using the average fee of the last hour + RecommendedFeePolicyTypeAvgLastHour RecommendedFeePolicyType = "AvgLastHour" +) + +func (rfp *RecommendedFeePolicy) valid() bool { + switch rfp.PolicyType { + case RecommendedFeePolicyTypeStatic: + if rfp.StaticValue == 0 { + log.Warn("RcommendedFee is set to 0 USD, and the policy is static") + } + return true + case RecommendedFeePolicyTypeAvgLastHour: + return true + default: + return false + } } // NewUpdater creates a new Updater func NewUpdater(hdb *historydb.HistoryDB, config *historydb.NodeConfig, vars *common.SCVariables, - consts *historydb.Constants) *Updater { + consts *historydb.Constants, rfp *RecommendedFeePolicy) (*Updater, error) { + if ok := rfp.valid(); !ok { + return nil, tracerr.New("Invalid recommende fee policy") + } u := Updater{ hdb: hdb, config: *config, @@ -31,9 +66,10 @@ func NewUpdater(hdb *historydb.HistoryDB, config *historydb.NodeConfig, vars *co ForgeDelay: config.ForgeDelay, }, }, + rfp: rfp, } u.SetSCVars(vars.AsPtr()) - return &u + return &u, nil } // Store the State in the HistoryDB @@ -65,13 +101,27 @@ func (u *Updater) SetSCVars(vars *common.SCVariablesPtr) { // UpdateRecommendedFee update Status.RecommendedFee information func (u *Updater) UpdateRecommendedFee() error { - recommendedFee, err := u.hdb.GetRecommendedFee(u.config.MinFeeUSD, u.config.MaxFeeUSD) - if err != nil { - return tracerr.Wrap(err) + switch u.rfp.PolicyType { + case RecommendedFeePolicyTypeStatic: + u.rw.Lock() + u.state.RecommendedFee = common.RecommendedFee{ + ExistingAccount: u.rfp.StaticValue, + CreatesAccount: u.rfp.StaticValue, + CreatesAccountInternal: u.rfp.StaticValue, + } + u.rw.Unlock() + case RecommendedFeePolicyTypeAvgLastHour: + recommendedFee, err := u.hdb.GetRecommendedFee(u.config.MinFeeUSD, u.config.MaxFeeUSD) + if err != nil { + return tracerr.Wrap(err) + } + u.rw.Lock() + u.state.RecommendedFee = *recommendedFee + u.rw.Unlock() + default: + return tracerr.New("Invalid recommende fee policy") } - u.rw.Lock() - u.state.RecommendedFee = *recommendedFee - u.rw.Unlock() + return nil } diff --git a/api/swagger.yml b/api/swagger.yml index 2fbf6c8..6bea4d0 100644 --- a/api/swagger.yml +++ b/api/swagger.yml @@ -59,9 +59,9 @@ externalDocs: description: Find out more about Hermez network. url: 'https://hermez.io' servers: - - description: Hosted mock up, returns fake data usefull for development + - description: Hosted mock up, returns fake data useful for development url: https://apimock.hermez.network - - description: Localhost mock up, returns fake data usefull for development + - description: Localhost mock up, returns fake data useful for development url: http://localhost:4010 - description: Testnet (Rinkeby) server url: https://api.testnet.hermez.io diff --git a/cli/node/cfg.buidler.toml b/cli/node/cfg.buidler.toml index f2d561e..e9f0467 100644 --- a/cli/node/cfg.buidler.toml +++ b/cli/node/cfg.buidler.toml @@ -145,3 +145,11 @@ Coordinator = true BatchPath = "/tmp/iden3-test/hermez/batchesdebug" LightScrypt = true # RollupVerifierIndex = 0 + +[RecommendedFeePolicy] +# Strategy used to calculate the recommended fee that the API will expose. +# Available options: +# - Static: always return the same value (StaticValue) in USD +# - AvgLastHour: calculate using the average fee of the forged transactions during the last hour +PolicyType = "Static" +StaticValue = 0.99 \ No newline at end of file diff --git a/cli/node/main.go b/cli/node/main.go index 619dbab..a6f964a 100644 --- a/cli/node/main.go +++ b/cli/node/main.go @@ -365,6 +365,7 @@ func getConfig(c *cli.Context) (*Config, error) { } case modeCoord: cfg.mode = node.ModeCoordinator + fmt.Println("LOADING CFG") cfg.node, err = config.LoadNode(nodeCfgPath, true) if err != nil { return nil, tracerr.Wrap(err) diff --git a/config/config.go b/config/config.go index 419617f..0fb0e13 100644 --- a/config/config.go +++ b/config/config.go @@ -8,6 +8,7 @@ import ( "github.com/BurntSushi/toml" ethCommon "github.com/ethereum/go-ethereum/common" + "github.com/hermeznetwork/hermez-node/api/stateapiupdater" "github.com/hermeznetwork/hermez-node/common" "github.com/hermeznetwork/hermez-node/priceupdater" "github.com/hermeznetwork/tracerr" @@ -347,8 +348,9 @@ type Node struct { // can wait to stablish a SQL connection SQLConnectionTimeout Duration } `validate:"required"` - Debug NodeDebug `validate:"required"` - Coordinator Coordinator `validate:"-"` + RecommendedFeePolicy stateapiupdater.RecommendedFeePolicy `validate:"required"` + Debug NodeDebug `validate:"required"` + Coordinator Coordinator `validate:"-"` } // APIServer is the api server configuration parameters diff --git a/node/node.go b/node/node.go index 3445933..900ab1c 100644 --- a/node/node.go +++ b/node/node.go @@ -288,7 +288,16 @@ func NewNode(mode Mode, cfg *config.Node) (*Node, error) { return nil, tracerr.Wrap(err) } - stateAPIUpdater := stateapiupdater.NewUpdater(historyDB, &hdbNodeCfg, initSCVars, &hdbConsts) + stateAPIUpdater, err := stateapiupdater.NewUpdater( + historyDB, + &hdbNodeCfg, + initSCVars, + &hdbConsts, + &cfg.RecommendedFeePolicy, + ) + if err != nil { + return nil, tracerr.Wrap(err) + } var coord *coordinator.Coordinator if mode == ModeCoordinator {