Skip to content

Commit

Permalink
add unit tests for feemarket gas prices query
Browse files Browse the repository at this point in the history
  • Loading branch information
quasisamurai committed Jun 18, 2024
1 parent 76b2d18 commit 27bd820
Show file tree
Hide file tree
Showing 6 changed files with 2,165 additions and 30 deletions.
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ toolchain go1.22.4

require (
cosmossdk.io/api v0.7.5
cosmossdk.io/math v1.3.0
github.com/avast/retry-go/v4 v4.5.1
github.com/cometbft/cometbft v0.38.7
github.com/cosmos/cosmos-sdk v0.50.7
Expand All @@ -16,6 +17,7 @@ require (
github.com/go-openapi/strfmt v0.21.3
github.com/go-openapi/swag v0.22.3
github.com/go-openapi/validate v0.21.0
github.com/golang/mock v1.6.0
github.com/gorilla/mux v1.8.1
github.com/kelseyhightower/envconfig v1.4.0
github.com/neutron-org/neutron-logger v0.0.0-20221027125151-535167f2dd73
Expand All @@ -42,7 +44,6 @@ require (
cosmossdk.io/depinject v1.0.0-alpha.4 // indirect
cosmossdk.io/errors v1.0.1 // indirect
cosmossdk.io/log v1.3.1 // indirect
cosmossdk.io/math v1.3.0 // indirect
cosmossdk.io/store v1.1.0 // indirect
cosmossdk.io/x/feegrant v0.1.1 // indirect
cosmossdk.io/x/tx v0.13.3 // indirect
Expand Down Expand Up @@ -125,7 +126,6 @@ require (
github.com/gogo/protobuf v1.3.3 // indirect
github.com/golang/glog v1.2.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/google/btree v1.1.2 // indirect
Expand Down Expand Up @@ -256,7 +256,7 @@ replace (
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
github.com/ChainSafe/go-schnorrkel => github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d
github.com/CosmWasm/wasmd => github.com/neutron-org/wasmd v0.45.1-0.20240501180153-d9bebe629e05
github.com/cosmos/admin-module => github.com/neutron-org/admin-module v1.0.2-0.20240402143659-7dcb4a8c2056
github.com/cosmos/admin-module/v2 => github.com/neutron-org/admin-module/v2 v2.0.0
github.com/cosmos/cosmos-sdk => github.com/neutron-org/cosmos-sdk v0.50.7-neutron
github.com/cosmos/gaia/v11 => github.com/cosmos/gaia/v11 v11.0.0-20230724152830-861ba391c3b4
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
Expand Down
153 changes: 153 additions & 0 deletions internal/submit/submit_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package submit

import (
"context"
"testing"

cosmossdk_io_math "cosmossdk.io/math"
abci "github.com/cometbft/cometbft/abci/types"
coretypes "github.com/cometbft/cometbft/rpc/core/types"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/types"
authtxtypes "github.com/cosmos/cosmos-sdk/x/auth/tx"
"github.com/golang/mock/gomock"
submit_mock "github.com/neutron-org/neutron-query-relayer/testutil/mocks/submit"
feemarkettypes "github.com/skip-mev/feemarket/x/feemarket/types"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
)

func setupTest(t *testing.T, gasMultiplier float64, maxGas float64, gasPrices string, mockClient *submit_mock.MockClient) *TxSender {
logger, _ := zap.NewDevelopment()
txConfig := authtxtypes.NewTxConfig(codec.NewProtoCodec(nil), authtxtypes.DefaultSignModes)
return &TxSender{
rpcClient: mockClient,
txConfig: txConfig,
logger: logger,
denom: "testdenom",
gasMultiplier: gasMultiplier,
maxGas: maxGas,
gasPrices: gasPrices,
}
}

func TestQueryDynamicPrice(t *testing.T) {
tests := []struct {
name string
gasMultiplier float64
maxGas float64
gasPrices string
mockResponse *coretypes.ResultABCIQuery
expectedPrice string
expectError bool
}{
{
name: "Basic",
gasMultiplier: 1.0,
maxGas: 100000000,
mockResponse: &coretypes.ResultABCIQuery{
Response: abci.ResponseQuery{
Code: 0,
Value: func() []byte {
gasPrice := feemarkettypes.GasPriceResponse{
Price: types.DecCoin{
Denom: "testdenom",
Amount: cosmossdk_io_math.LegacyNewDec(123),
},
}
rawGasPrice, _ := gasPrice.Marshal()
return rawGasPrice
}(),
},
},
expectedPrice: "123testdenom",
expectError: false,
},
{
name: "Multiply",
gasMultiplier: 1.1,
maxGas: 100000000,
mockResponse: &coretypes.ResultABCIQuery{
Response: abci.ResponseQuery{
Code: 0,
Value: func() []byte {
gasPrice := feemarkettypes.GasPriceResponse{
Price: types.DecCoin{
Denom: "testdenom",
Amount: cosmossdk_io_math.LegacyNewDec(123),
},
}
rawGasPrice, _ := gasPrice.Marshal()
return rawGasPrice
}(),
},
},
expectedPrice: "135.3testdenom",
expectError: false,
},
{
name: "DefaultGasPrice",
gasMultiplier: 1.0,
maxGas: 100.0,
gasPrices: "99.0testdenom",
mockResponse: &coretypes.ResultABCIQuery{
Response: abci.ResponseQuery{
Code: 1,
},
},
expectedPrice: "99.0testdenom",
expectError: false,
},
{
name: "MaxGas",
gasMultiplier: 1.5,
maxGas: 111.1,
gasPrices: "99.0testdenom",
mockResponse: &coretypes.ResultABCIQuery{
Response: abci.ResponseQuery{
Code: 0,
Value: func() []byte {
gasPrice := feemarkettypes.GasPriceResponse{
Price: types.DecCoin{
Denom: "testdenom",
Amount: cosmossdk_io_math.LegacyNewDec(123),
},
}
rawGasPrice, _ := gasPrice.Marshal()
return rawGasPrice
}(),
},
},
expectedPrice: "111.1testdenom",
expectError: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockClient := submit_mock.NewMockClient(ctrl)
txs := setupTest(t, tt.gasMultiplier, tt.maxGas, tt.gasPrices, mockClient)

if tt.mockResponse != nil {
mockClient.EXPECT().
ABCIQueryWithOptions(gomock.Any(), getPricesQueryPath, gomock.Any(), gomock.Any()).
Return(tt.mockResponse, nil)
} else {
mockClient.EXPECT().
ABCIQueryWithOptions(gomock.Any(), getPricesQueryPath, gomock.Any(), gomock.Any()).
Return(nil, nil)
}

price, err := txs.getGasPrice(context.Background())
if tt.expectError {
require.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, tt.expectedPrice, price)
}
})
}
}
24 changes: 14 additions & 10 deletions internal/submit/tx_sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"
"sync"

cosmossdk_io_math "cosmossdk.io/math"
tmtypes "github.com/cometbft/cometbft/types"
"go.uber.org/zap"

Expand Down Expand Up @@ -228,42 +229,45 @@ func (txs *TxSender) queryAccount(ctx context.Context, address string) (*authtyp
return &account, nil
}

func (txs *TxSender) queryDynamicPrice(ctx context.Context) (string, error) {
func (txs *TxSender) queryDynamicPrice(ctx context.Context) (cosmossdk_io_math.LegacyDec, error) {
request := feemarkettypes.GasPriceRequest{Denom: txs.denom}
req, err := request.Marshal()
if err != nil {
return "", fmt.Errorf("error marshalling query gas prices request for denom=%s: %w", txs.denom, err)
return cosmossdk_io_math.LegacyZeroDec(), fmt.Errorf("error marshalling query gas prices request for denom=%s: %w", txs.denom, err)
}
simQuery := abci.RequestQuery{
Path: getPricesQueryPath,
Data: req,
}
res, err := txs.rpcClient.ABCIQueryWithOptions(ctx, simQuery.Path, simQuery.Data, rpcclient.DefaultABCIQueryOptions)
if err != nil {
return "", fmt.Errorf("error making abci query: %w", err)
return cosmossdk_io_math.LegacyZeroDec(), fmt.Errorf("error making abci query: %w", err)
}

if res.Response.Code != 0 {
return "", fmt.Errorf("error fetching feemarket gas price for denom=%s log=%s", txs.denom, res.Response.Log)
return cosmossdk_io_math.LegacyZeroDec(), fmt.Errorf("error fetching feemarket gas price for denom=%s", txs.denom)
}

var response feemarkettypes.GasPriceResponse
if err := response.Unmarshal(res.Response.Value); err != nil {
return "", fmt.Errorf("error unmarshalling GasPriceResponse for denom=%s: %w", txs.denom, err)
return cosmossdk_io_math.LegacyZeroDec(), fmt.Errorf("error unmarshalling GasPriceResponse for denom=%s: %w", txs.denom, err)
}

gasPrice := response.Price.Amount.String() + txs.denom
gasPrice := response.Price.Amount

return gasPrice, nil
}

func (txs *TxSender) multiplyGas(gas string) (string, error) {
floatGas, err := strconv.ParseFloat(gas, 64)
func (txs *TxSender) multiplyGas(gas cosmossdk_io_math.LegacyDec) (string, error) {
floatGas, err := gas.Float64()
if err != nil {
return "", err
}

multipliedGas := txs.gasMultiplier * floatGas
if err != nil {
return "", err
}
if multipliedGas > txs.maxGas {
multipliedGas = txs.maxGas
}
Expand All @@ -280,15 +284,15 @@ func (txs *TxSender) multiplyGas(gas string) (string, error) {
func (txs *TxSender) getGasPrice(ctx context.Context) (string, error) {
gasPrice, err := txs.queryDynamicPrice(ctx)
if err != nil {
return txs.gasPrices, err
return txs.gasPrices, nil
}

multipliedGas, err := txs.multiplyGas(gasPrice)
if err != nil {
return "", err
}

return multipliedGas, nil
return multipliedGas + txs.denom, nil
}

func (txs *TxSender) signAndBuildTxBz(ctx context.Context, txf tx.Factory, msgs []sdk.Msg) ([]byte, error) {
Expand Down
1 change: 1 addition & 0 deletions testutil/mocks/gomock.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
package mocks

//go:generate mockgen -source=./../../internal/subscriber/clients.go -destination ./subscriber/expected_clients.go
//go:generate mockgen -source=$GOPATH/pkg/mod/github.com/cometbft/cometbft@v0.38.7/rpc/client/interface.go -destination ./submit/mock_client.go
Loading

0 comments on commit 27bd820

Please sign in to comment.