Skip to content

Commit

Permalink
feat(cosmosclient): add tx options (incl memo setting) (backport #4276)…
Browse files Browse the repository at this point in the history
… (#4279)

* feat(cosmosclient): add tx options (incl memo setting) (#4276)

(cherry picked from commit 6bcbe4e)

* Update changelog.md

Co-authored-by: Danilo Pantani <danpantani@gmail.com>

* Update changelog.md

---------

Co-authored-by: Julien Robert <julien@rbrt.fr>
Co-authored-by: Danilo Pantani <danpantani@gmail.com>
  • Loading branch information
3 people authored Jul 29, 2024
1 parent 04dbd45 commit f7f0c84
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 24 deletions.
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

## [`v28.5.1`](https://github.com/ignite/cli/releases/tag/v28.5.1)

### Features

- [#4276](https://github.com/ignite/cli/pull/4276) Add `cosmosclient.CreateTxWithOptions` method to facilite more custom tx creation

### Changes

- [#4262](https://github.com/ignite/cli/pull/4262) Bring back relayer command
Expand Down
70 changes: 47 additions & 23 deletions ignite/pkg/cosmosclient/cosmosclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ type Client struct {
}

// Option configures your client.
// Option, are global to the client and affect all transactions.
// If you want to override a global option on a transaction, use the TxOptions struct.
type Option func(*Client)

// WithHome sets the data dir of your chain. This option is used to access your chain's
Expand Down Expand Up @@ -175,12 +177,14 @@ func WithNodeAddress(addr string) Option {
}
}

// WithAddressPrefix sets the address prefix on the client.
func WithAddressPrefix(prefix string) Option {
return func(c *Client) {
c.addressPrefix = prefix
}
}

// WithUseFaucet sets the faucet address on the client.
func WithUseFaucet(faucetAddress, denom string, minAmount uint64) Option {
return func(c *Client) {
c.useFaucet = true
Expand Down Expand Up @@ -216,7 +220,8 @@ func WithGasAdjustment(gasAdjustment float64) Option {
}
}

// WithFees sets the fees (e.g. 10uatom).
// WithFees sets the fees (e.g. 10uatom) on the client.
// It will be used for all transactions if not overridden on the transaction options.
func WithFees(fees string) Option {
return func(c *Client) {
c.fees = fees
Expand Down Expand Up @@ -544,15 +549,17 @@ func (c Client) BroadcastTx(ctx context.Context, account cosmosaccount.Account,
return txService.Broadcast(ctx)
}

func (c Client) CreateTx(goCtx context.Context, account cosmosaccount.Account, msgs ...sdktypes.Msg) (TxService, error) {
// CreateTxWithOptions creates a transaction with the given options.
// Options override global client options.
func (c Client) CreateTxWithOptions(ctx context.Context, account cosmosaccount.Account, options TxOptions, msgs ...sdktypes.Msg) (TxService, error) {
defer c.lockBech32Prefix()()

if c.useFaucet && !c.generateOnly {
addr, err := account.Address(c.addressPrefix)
if err != nil {
return TxService{}, errors.WithStack(err)
}
if err := c.makeSureAccountHasTokens(goCtx, addr); err != nil {
if err := c.makeSureAccountHasTokens(ctx, addr); err != nil {
return TxService{}, err
}
}
Expand All @@ -562,36 +569,49 @@ func (c Client) CreateTx(goCtx context.Context, account cosmosaccount.Account, m
return TxService{}, errors.WithStack(err)
}

ctx := c.context.
clientCtx := c.context.
WithFromName(account.Name).
WithFromAddress(sdkaddr)

txf, err := c.prepareFactory(ctx)
txf, err := c.prepareFactory(clientCtx)
if err != nil {
return TxService{}, err
}

if c.gasAdjustment != 0 && c.gasAdjustment != defaultGasAdjustment {
txf = txf.WithGasAdjustment(c.gasAdjustment)
if options.Memo != "" {
txf = txf.WithMemo(options.Memo)
}

var gas uint64
if c.gas != "" && c.gas != GasAuto {
gas, err = strconv.ParseUint(c.gas, 10, 64)
if err != nil {
return TxService{}, errors.WithStack(err)
}
txf = txf.WithFees(c.fees)
if options.Fees != "" {
txf = txf.WithFees(options.Fees)
}

if options.GasLimit != 0 {
txf = txf.WithGas(options.GasLimit)
} else {
_, gas, err = c.gasometer.CalculateGas(ctx, txf, msgs...)
if err != nil {
return TxService{}, errors.WithStack(err)
if c.gasAdjustment != 0 && c.gasAdjustment != defaultGasAdjustment {
txf = txf.WithGasAdjustment(c.gasAdjustment)
}
// the simulated gas can vary from the actual gas needed for a real transaction
// we add an amount to ensure sufficient gas is provided
gas += 20000

var gas uint64
if c.gas != "" && c.gas != GasAuto {
gas, err = strconv.ParseUint(c.gas, 10, 64)
if err != nil {
return TxService{}, errors.WithStack(err)
}
} else {
_, gas, err = c.gasometer.CalculateGas(clientCtx, txf, msgs...)
if err != nil {
return TxService{}, errors.WithStack(err)
}
// the simulated gas can vary from the actual gas needed for a real transaction
// we add an amount to ensure sufficient gas is provided
gas += 20000
}

txf = txf.WithGas(gas)
}
txf = txf.WithGas(gas)
txf = txf.WithFees(c.fees)

if c.gasPrices != "" {
txf = txf.WithGasPrices(c.gasPrices)
Expand All @@ -602,16 +622,20 @@ func (c Client) CreateTx(goCtx context.Context, account cosmosaccount.Account, m
return TxService{}, errors.WithStack(err)
}

txUnsigned.SetFeeGranter(ctx.GetFeeGranterAddress())
txUnsigned.SetFeeGranter(clientCtx.GetFeeGranterAddress())

return TxService{
client: c,
clientContext: ctx,
clientContext: clientCtx,
txBuilder: txUnsigned,
txFactory: txf,
}, nil
}

func (c Client) CreateTx(ctx context.Context, account cosmosaccount.Account, msgs ...sdktypes.Msg) (TxService, error) {
return c.CreateTxWithOptions(ctx, account, TxOptions{}, msgs...)
}

// GetBlockTXs returns the transactions in a block.
// The list of transactions can be empty if there are no transactions in the block
// at the moment this method is called.
Expand Down
1 change: 0 additions & 1 deletion ignite/pkg/cosmosclient/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
// Useful because the original implementation may return JSON errors when the
// requested node is busy, which is confusing for the user. With rpcWrapper,
// the error is prefixed with 'error while requesting node xxx: JSON error'.
// TODO(tb): we may remove this wrapper once https://github.com/tendermint/tendermint/issues/9312 is fixed.
type rpcWrapper struct {
rpcclient.Client
nodeAddress string
Expand Down
2 changes: 2 additions & 0 deletions ignite/pkg/cosmosclient/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"github.com/cosmos/cosmos-sdk/client/tx"
)

var _ Signer = signer{}

// signer implements the Signer interface.
type signer struct{}

Expand Down
15 changes: 15 additions & 0 deletions ignite/pkg/cosmosclient/tx_options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package cosmosclient

// TxOptions contains options for creating a transaction.
// It is used by the CreateTxWithOptions method.
type TxOptions struct {
// Memo is the memo to be used for the transaction.
Memo string

// GasLimit is the gas limit to be used for the transaction.
// If GasLimit is set to 0, the gas limit will be automatically calculated.
GasLimit uint64

// Fees is the fees to be used for the transaction.
Fees string
}

0 comments on commit f7f0c84

Please sign in to comment.