diff --git a/pkg/service/cost.go b/pkg/service/cost.go index 46ac70ad..f6a10e69 100644 --- a/pkg/service/cost.go +++ b/pkg/service/cost.go @@ -195,10 +195,22 @@ func (c cost) EstimateTransaction(p EstimationParams, chain Chain) (estimate mod // transactionCost is for native token transaction cost (tx_value) transactionCost := costEth * nativeCost - // Query owlracle for gas - ethGasFee, err := c.lookupGas(chain.OwlracleName) - if err != nil { - return estimate, libcommon.StringError(err) + ethGasFee := 0.0 + if chain.OwlracleName == "internal" { + // Use the internal gas rate calculator + // Recommended gas rate with 10% boost and 10% tip respectively + gas, tip, err := GetGasRate(chain, 10, 10) + if err != nil { + return estimate, libcommon.StringError(err) + } + gasWithTip := big.NewInt(0).Add(gas, tip) + ethGasFee = float64(gasWithTip.Int64()) / 1e9 + } else { + // Query owlracle for gas + ethGasFee, err = c.lookupGas(chain.OwlracleName) + if err != nil { + return estimate, libcommon.StringError(err) + } } // Convert it from gwei to eth to USD and apply buffer diff --git a/pkg/service/executor.go b/pkg/service/executor.go index 10690cf5..1b01212a 100644 --- a/pkg/service/executor.go +++ b/pkg/service/executor.go @@ -48,6 +48,7 @@ type Executor interface { GetEventData(txIds []string, eventSignature string) ([]types.Log, error) ForwardNonFungibleTokens(txIds []string, recipient string) ([]string, []string, error) ForwardTokens(txIds []string, recipient string) ([]string, []string, []string, error) + GetGasRate(boostPercent int64, tipPercent int64) (*big.Int, *big.Int, error) } type executor struct { @@ -257,9 +258,11 @@ func (e executor) generateTransactionMessage(call ContractCall, incrementNonce u return w3types.Message{}, libcommon.StringError(err) } - // Get dynamic fee tx gas params - tipCap, _ := e.geth.SuggestGasTipCap(context.Background()) - feeCap, _ := e.geth.SuggestGasPrice(context.Background()) + // TODO: get boost factors from gas analysis engine + gas, tip, err := e.GetGasRate(10, 10) + if err != nil { + return w3types.Message{}, libcommon.StringError(err) + } // Get handle to function we wish to call funcEVM, err := w3.NewFunc(call.CxFunc, call.CxReturn) @@ -277,8 +280,8 @@ func (e executor) generateTransactionMessage(call ContractCall, incrementNonce u return w3types.Message{ From: sender, To: &to, - GasFeeCap: feeCap, - GasTipCap: tipCap, + GasFeeCap: gas, + GasTipCap: tip, Value: value, Input: data, Nonce: nonce + incrementNonce, @@ -300,9 +303,11 @@ func (e executor) generateTransactionRequest(call ContractCall, incrementNonce u return tx, libcommon.StringError(err) } - // Get dynamic fee tx gas params - tipCap, _ := e.geth.SuggestGasTipCap(context.Background()) - feeCap, _ := e.geth.SuggestGasPrice(context.Background()) + // TODO: get boost factors from gas analysis engine + gas, tip, err := e.GetGasRate(10, 10) + if err != nil { + return tx, libcommon.StringError(err) + } // Type conversion for chainId chainIdBig := new(big.Int).SetUint64(chainId64) @@ -314,8 +319,8 @@ func (e executor) generateTransactionRequest(call ContractCall, incrementNonce u dynamicFeeTx := types.DynamicFeeTx{ ChainID: chainIdBig, Nonce: msg.Nonce + incrementNonce, - GasTipCap: tipCap, - GasFeeCap: feeCap, + GasTipCap: tip, + GasFeeCap: gas, Gas: w3.I(call.TxGasLimit).Uint64(), To: msg.To, Value: msg.Value, @@ -486,3 +491,41 @@ func (e executor) ForwardTokens(txIds []string, recipient string) ([]string, []s return forwardTxIds, tokens, quantities, nil } + +func (e executor) GetGasRate(boostPercent int64, tipPercent int64) (*big.Int, *big.Int, error) { + gasPrice, err := e.geth.SuggestGasPrice(context.Background()) + if err != nil { + return nil, nil, libcommon.StringError(err) + } + + gasBoost := big.NewInt(gasPrice.Int64()) + gasBoost.Mul(gasBoost, big.NewInt(boostPercent)) + gasBoost.Div(gasBoost, big.NewInt(100)) + gasPrice.Add(gasBoost, gasPrice) + tip := big.NewInt(gasPrice.Int64()) + tip.Mul(tip, big.NewInt(tipPercent)) + tip.Div(tip, big.NewInt(100)) + + return gasPrice, tip, nil +} + +func GetGasRate(chain Chain, boostPercent int64, tipPercent int64) (*big.Int, *big.Int, error) { + geth, err := ethclient.Dial(chain.RPC) + if err != nil { + return nil, nil, libcommon.StringError(err) + } + gasPrice, err := geth.SuggestGasPrice(context.Background()) + if err != nil { + return nil, nil, libcommon.StringError(err) + } + + gasBoost := big.NewInt(gasPrice.Int64()) + gasBoost.Mul(gasBoost, big.NewInt(boostPercent)) + gasBoost.Div(gasBoost, big.NewInt(100)) + gasPrice.Add(gasBoost, gasPrice) + tip := big.NewInt(gasPrice.Int64()) + tip.Mul(tip, big.NewInt(tipPercent)) + tip.Div(tip, big.NewInt(100)) + + return gasPrice, tip, nil +} diff --git a/pkg/service/gas_test.go b/pkg/service/gas_test.go new file mode 100644 index 00000000..f4ae7305 --- /dev/null +++ b/pkg/service/gas_test.go @@ -0,0 +1,17 @@ +package service + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetGasPrices(t *testing.T) { + gas, tip, err := GetGasRate(Chain{RPC: "https://api.avax.network/ext/bc/C/rpc"}, 10, 10) + assert.NoError(t, err) + assert.Greater(t, gas.Int64(), int64(0)) + assert.Greater(t, tip.Int64(), int64(0)) + fmt.Printf("gas: %d, tip: %d", gas.Int64(), tip.Int64()) + +}