diff --git a/pkg/user/signer.go b/pkg/user/signer.go index 0340e3ad57..224f203978 100644 --- a/pkg/user/signer.go +++ b/pkg/user/signer.go @@ -1,15 +1,18 @@ package user import ( + "context" "errors" "fmt" + "github.com/celestiaorg/celestia-app/v3/app/grpc/gasestimation" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/crypto/keyring" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdktypes "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/tx/signing" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" + "google.golang.org/grpc" blobtypes "github.com/celestiaorg/celestia-app/v3/x/blob/types" "github.com/celestiaorg/go-square/v2/share" @@ -298,3 +301,46 @@ func (s *Signer) getSignatureV2(sequence uint64, pubKey cryptotypes.PubKey, sign } return sigV2 } + +// QueryGasPrice takes a priority and an app gRPC client. +// Returns the current network gas price corresponding to the provided priority. +// More on the gas price estimation can be found in docs/architecture/adr-023-gas-used-and-gas-price-estimation.md +func (s *Signer) QueryGasPrice( + ctx context.Context, + grpcClient *grpc.ClientConn, + priority gasestimation.TxPriority, +) (float64, error) { + estimator := gasestimation.NewGasEstimatorClient(grpcClient) + gasPrice, err := estimator.EstimateGasPrice( + ctx, + &gasestimation.EstimateGasPriceRequest{TxPriority: priority}, + ) + if err != nil { + return 0, err + } + return gasPrice.EstimatedGasPrice, nil +} + +// QueryGasUsedAndPrice takes a priority, an app gRPC client, and a transaction bytes. +// Returns the current network gas price corresponding to the provided priority, +// and the gas used estimation for the provided transaction bytes. +// More on the gas estimation can be found in docs/architecture/adr-023-gas-used-and-gas-price-estimation.md +func (s *Signer) QueryGasUsedAndPrice( + ctx context.Context, + grpcClient *grpc.ClientConn, + priority gasestimation.TxPriority, + txBytes []byte, +) (float64, uint64, error) { + estimator := gasestimation.NewGasEstimatorClient(grpcClient) + gasEstimation, err := estimator.EstimateGasPriceAndUsage( + ctx, + &gasestimation.EstimateGasPriceAndUsageRequest{ + TxPriority: priority, + TxBytes: txBytes, + }, + ) + if err != nil { + return 0, 0, err + } + return gasEstimation.EstimatedGasPrice, gasEstimation.EstimatedGasUsed, nil +} diff --git a/pkg/user/tx_client_test.go b/pkg/user/tx_client_test.go index 6ae0c2efa2..55d870b913 100644 --- a/pkg/user/tx_client_test.go +++ b/pkg/user/tx_client_test.go @@ -5,6 +5,9 @@ import ( "testing" "time" + "github.com/celestiaorg/celestia-app/v3/app/grpc/gasestimation" + "github.com/stretchr/testify/assert" + "github.com/celestiaorg/celestia-app/v3/app" "github.com/celestiaorg/celestia-app/v3/app/encoding" "github.com/celestiaorg/celestia-app/v3/pkg/appconsts" @@ -350,3 +353,29 @@ func setupTxClient(t *testing.T, ttlDuration time.Duration) (encoding.Config, *u require.NoError(t, err) return encCfg, txClient, ctx } + +func (suite *TxClientTestSuite) TestGasPriceAndUsedEstimate() { + t := suite.T() + ctx := context.Background() + signer := suite.txClient.Signer() + + t.Run("query the gas price from the app gRPC", func(t *testing.T) { + gasPrice, err := signer.QueryGasPrice(ctx, suite.ctx.GRPCClient, gasestimation.TxPriority_TX_PRIORITY_HIGH) + assert.NoError(t, err) + assert.Greater(t, gasPrice, float64(0)) + }) + + t.Run("query the gas price and gas used from the app gRPC", func(t *testing.T) { + msg := bank.NewMsgSend( + suite.txClient.DefaultAddress(), + testnode.RandomAddress().(sdk.AccAddress), + sdk.NewCoins(sdk.NewInt64Coin(appconsts.BondDenom, 10)), + ) + rawTx, err := signer.CreateTx([]sdk.Msg{msg}) + require.NoError(t, err) + gasPrice, gasUsed, err := signer.QueryGasUsedAndPrice(ctx, suite.ctx.GRPCClient, gasestimation.TxPriority_TX_PRIORITY_HIGH, rawTx) + assert.NoError(t, err) + assert.Greater(t, gasPrice, float64(0)) + assert.Greater(t, gasUsed, uint64(0)) + }) +}