mukan-ignite/ignite/pkg/cosmosclient/txservice.go
Mukan Erkin Törük 26b204bd04
Some checks are pending
Docs Deploy / build_and_deploy (push) Waiting to run
Generate Docs / cli (push) Waiting to run
Generate Config Doc / cli (push) Waiting to run
Go formatting / go-formatting (push) Waiting to run
Check links / markdown-link-check (push) Waiting to run
Integration / pre-test (push) Waiting to run
Integration / test on (push) Blocked by required conditions
Integration / status (push) Blocked by required conditions
Lint / Lint Go code (push) Waiting to run
Test / test (ubuntu-latest) (push) Waiting to run
feat: fork Ignite CLI v29 as Mukan Ignite — remove cosmos-sdk restrictions
2026-05-11 03:31:37 +03:00

142 lines
4.2 KiB
Go

package cosmosclient
import (
"context"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx"
sdktypes "github.com/cosmos/cosmos-sdk/types"
"github.com/ignite/cli/v29/ignite/pkg/errors"
)
// BroadcastOption configures broadcast behavior.
type BroadcastOption func(*broadcastConfig)
// broadcastConfig holds configuration for broadcast operations.
type broadcastConfig struct {
sequence uint64
unordered bool
}
// WithSequence overrides the account sequence for the transaction.
func WithSequence(sequence uint64) BroadcastOption {
return func(cfg *broadcastConfig) {
cfg.sequence = sequence
}
}
// WithUnordered sets the unordered flag for the transaction.
// NOTE: This is only supported for Cosmos SDK versions >= v0.53.
func WithUnordered(unordered bool) BroadcastOption {
return func(cfg *broadcastConfig) {
cfg.unordered = unordered
}
}
type TxService struct {
client Client
clientContext client.Context
txBuilder client.TxBuilder
txFactory tx.Factory
}
// Gas is gas decided to use for this tx.
// either calculated or configured by the caller.
func (s TxService) Gas() uint64 {
return s.txBuilder.GetTx().GetGas()
}
// broadcast signs and broadcasts the transaction returning the initial broadcast response.
func (s TxService) broadcast(ctx context.Context, opts ...BroadcastOption) (*sdktypes.TxResponse, error) {
defer s.client.lockBech32Prefix()()
// validate msgs.
for _, msg := range s.txBuilder.GetTx().GetMsgs() {
msg, ok := msg.(sdktypes.HasValidateBasic)
if !ok {
continue
}
if err := msg.ValidateBasic(); err != nil {
return nil, errors.WithStack(err)
}
}
// Apply broadcast options
cfg := &broadcastConfig{}
for _, opt := range opts {
opt(cfg)
}
// Override sequence if specified
if cfg.sequence != 0 {
s.txFactory = s.txFactory.WithSequence(cfg.sequence)
}
s.txFactory = s.txFactory.WithUnordered(cfg.unordered)
accountName := s.clientContext.FromName
if err := s.client.signer.Sign(ctx, s.txFactory, accountName, s.txBuilder, true); err != nil {
return nil, errors.WithStack(err)
}
txBytes, err := s.clientContext.TxConfig.TxEncoder()(s.txBuilder.GetTx())
if err != nil {
return nil, errors.WithStack(err)
}
resp, err := s.clientContext.BroadcastTx(txBytes)
if err := handleBroadcastResult(resp, err); err != nil {
return nil, err
}
return resp, nil
}
// Broadcast signs and broadcasts this tx.
// If faucet is enabled and if the "from" account doesn't have enough funds, is
// it automatically filled with the default amount, and the tx is broadcasted
// again. Note that this may still end with the same error if the amount is
// greater than the amount dumped by the faucet.
func (s TxService) Broadcast(ctx context.Context, opts ...BroadcastOption) (Response, error) {
resp, err := s.broadcast(ctx, opts...)
if err != nil {
return Response{}, err
}
res, err := s.client.WaitForTx(ctx, resp.TxHash)
if err != nil {
return Response{}, err
}
// NOTE(tb) second and third parameters are omitted:
// - second parameter represents the tx and should be of type sdktypes.Any,
// but it is very ugly to decode, not sure if it's worth it (see sdk code
// x/auth/query.go method makeTxResult)
// - third parameter represents the timestamp of the tx, which must be
// fetched from the block itself. So it requires another API call to
// fetch the block from res.Height, not sure if it's worth it too.
resp = sdktypes.NewResponseResultTx(res, nil, "")
return Response{
Codec: s.clientContext.Codec,
TxResponse: resp,
}, handleBroadcastResult(resp, err)
}
// BroadcastAsync signs and broadcasts this tx.
// It is similar to Broadcast but it does not wait for the transaction to be included in a block.
func (s TxService) BroadcastAsync(ctx context.Context, opts ...BroadcastOption) (Response, error) {
resp, err := s.broadcast(ctx, opts...)
if err != nil {
return Response{}, err
}
return Response{
Codec: s.clientContext.Codec,
TxResponse: resp,
}, handleBroadcastResult(resp, err)
}
// EncodeJSON encodes the transaction as a json string.
func (s TxService) EncodeJSON() ([]byte, error) {
return s.client.context.TxConfig.TxJSONEncoder()(s.txBuilder.GetTx())
}