Skip to content

Commit 5161f01

Browse files
authored
Merge pull request #142 from renproject/feat/cosmos-estimate-gas
Fix the gas price for cosmos compat chains
2 parents d475196 + 1ff8685 commit 5161f01

File tree

3 files changed

+73
-10
lines changed

3 files changed

+73
-10
lines changed

chain/cosmos/tx.go

+26-9
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,27 @@ const (
3030
DefaultChainID = pack.String("testnet")
3131
// DefaultSignMode used in signing the tx
3232
DefaultSignMode = 1
33+
// DefaultDecimalsDivisor is used when estimating gas prices for some Cosmos
34+
// chains, so that the result is an integer.
35+
// For example, the recommended Terra gas price is currently 0.01133 uluna.
36+
// To ensure we're only dealing with integers, the value can be represented
37+
// as 1133. When the transaction builder is calculating fees, it will divide
38+
// the total by the divisor (in this case 1e5), to calculate the actual
39+
// value.
40+
DefaultDecimalsDivisor = 1
3341
)
3442

3543
// TxBuilderOptions only contains necessary options to build tx from tx builder
3644
type TxBuilderOptions struct {
37-
ChainID pack.String
45+
ChainID pack.String
46+
DecimalsDivisor pack.U256
3847
}
3948

4049
// DefaultTxBuilderOptions returns TxBuilderOptions with the default settings.
4150
func DefaultTxBuilderOptions() TxBuilderOptions {
4251
return TxBuilderOptions{
43-
ChainID: DefaultChainID,
52+
ChainID: DefaultChainID,
53+
DecimalsDivisor: pack.NewU256FromU64(DefaultDecimalsDivisor),
4454
}
4555
}
4656

@@ -50,20 +60,27 @@ func (opts TxBuilderOptions) WithChainID(chainID pack.String) TxBuilderOptions {
5060
return opts
5161
}
5262

63+
func (opts TxBuilderOptions) WithDecimalsDivisor(decimalDivisor pack.U256) TxBuilderOptions {
64+
opts.DecimalsDivisor = decimalDivisor
65+
return opts
66+
}
67+
5368
type txBuilder struct {
54-
client *Client
55-
chainID pack.String
56-
signMode int32
69+
client *Client
70+
chainID pack.String
71+
signMode int32
72+
decimalsDivisor pack.U256
5773
}
5874

5975
// NewTxBuilder returns an implementation of the transaction builder interface
6076
// from the Cosmos Compat API, and exposes the functionality to build simple
6177
// Cosmos based transactions.
6278
func NewTxBuilder(options TxBuilderOptions, client *Client) account.TxBuilder {
6379
return txBuilder{
64-
signMode: DefaultSignMode,
65-
client: client,
66-
chainID: options.ChainID,
80+
signMode: DefaultSignMode,
81+
client: client,
82+
chainID: options.ChainID,
83+
decimalsDivisor: options.DecimalsDivisor,
6784
}
6885
}
6986

@@ -107,7 +124,7 @@ func (builder txBuilder) BuildTx(ctx context.Context, fromPubKey *id.PubKey, to
107124

108125
fees := Coins{Coin{
109126
Denom: builder.client.opts.CoinDenom,
110-
Amount: pack.NewU64(gasPrice.Mul(gasLimit).Int().Uint64()),
127+
Amount: pack.NewU64(gasPrice.Mul(gasLimit).Div(builder.decimalsDivisor).Int().Uint64()),
111128
}}
112129

113130
accountNumber, err := builder.client.AccountNumber(ctx, from)

chain/ethereum/gas.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ var (
2929
)
3030

3131
type feeHistoryResult struct {
32-
Reward [][]string `json:"reward"`
32+
Reward [][]string `json:"reward"`
3333
}
3434

3535
// GasOptions allow a user to configure the parameters used while heuristically recommending

chain/terra/terra.go

+46
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
package terra
22

33
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"net/http"
8+
"strconv"
9+
410
"github.com/cosmos/cosmos-sdk/types"
511
"github.com/renproject/multichain/api/account"
612
"github.com/renproject/multichain/chain/cosmos"
13+
"github.com/renproject/pack"
714
"github.com/terra-money/core/app"
815
)
916

17+
const DefaultTerraDecimalsDivisor = 1e5
18+
1019
type (
1120
// Client re-exports cosmos.Client
1221
Client = cosmos.Client
@@ -54,3 +63,40 @@ func NewClient(opts ClientOptions) *Client {
5463
func NewTxBuilder(opts TxBuilderOptions, client *Client) account.TxBuilder {
5564
return cosmos.NewTxBuilder(opts, client)
5665
}
66+
67+
type GasEstimator struct {
68+
url string
69+
decimals int
70+
fallbackGas pack.U256
71+
}
72+
73+
func NewHttpGasEstimator(url string, decimals int, fallbackGas pack.U256) GasEstimator {
74+
return GasEstimator{
75+
url: url,
76+
decimals: decimals,
77+
fallbackGas: fallbackGas,
78+
}
79+
}
80+
81+
func (gasEstimator GasEstimator) EstimateGas(ctx context.Context) (pack.U256, pack.U256, error) {
82+
response, err := http.Get(gasEstimator.url)
83+
if err != nil {
84+
return gasEstimator.fallbackGas, gasEstimator.fallbackGas, err
85+
}
86+
defer response.Body.Close()
87+
88+
var results map[string]string
89+
if err := json.NewDecoder(response.Body).Decode(&results); err != nil {
90+
return gasEstimator.fallbackGas, gasEstimator.fallbackGas, err
91+
}
92+
gasPriceStr, ok := results["uluna"]
93+
if !ok {
94+
return gasEstimator.fallbackGas, gasEstimator.fallbackGas, fmt.Errorf("no uluna in response")
95+
}
96+
gasPriceFloat, err := strconv.ParseFloat(gasPriceStr, 64)
97+
if err != nil {
98+
return gasEstimator.fallbackGas, gasEstimator.fallbackGas, fmt.Errorf("invalid gas price, %v", err)
99+
}
100+
gasPrice := uint64(gasPriceFloat * float64(gasEstimator.decimals))
101+
return pack.NewU256FromUint64(gasPrice), pack.NewU256FromUint64(gasPrice), nil
102+
}

0 commit comments

Comments
 (0)