mukan-ignite/ignite/pkg/cosmosclient/txservice_test.go
Mukan Erkin Törük c32551b6f7
Some checks failed
Docs Deploy / build_and_deploy (push) Has been cancelled
Generate Docs / cli (push) Has been cancelled
Generate Config Doc / cli (push) Has been cancelled
Go formatting / go-formatting (push) Has been cancelled
Check links / markdown-link-check (push) Has been cancelled
Integration / pre-test (push) Has been cancelled
Integration / test on (push) Has been cancelled
Integration / status (push) Has been cancelled
Lint / Lint Go code (push) Has been cancelled
Test / test (ubuntu-latest) (push) Has been cancelled
refactor: replace all github.com upstream refs with git.cw.tr/mukan-network
2026-05-11 03:36:24 +03:00

309 lines
8.6 KiB
Go

package cosmosclient_test
import (
"encoding/hex"
"testing"
"cosmossdk.io/math"
abci "github.com/cometbft/cometbft/abci/types"
ctypes "github.com/cometbft/cometbft/rpc/core/types"
sdktypes "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/cosmosaccount"
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/cosmosclient"
"git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/errors"
)
func TestTxServiceBroadcast(t *testing.T) {
var (
accountName = "bob"
passphrase = "passphrase"
txHash = []byte{1, 2, 3}
txHashStr = hex.EncodeToString(txHash)
)
r, err := cosmosaccount.NewInMemory()
require.NoError(t, err)
a, _, err := r.Create(accountName)
require.NoError(t, err)
// Export created account to we can import it in the Client below.
key, err := r.Export(accountName, passphrase)
require.NoError(t, err)
sdkaddr, err := a.Record.GetAddress()
require.NoError(t, err)
msg := &banktypes.MsgSend{
FromAddress: sdkaddr.String(),
ToAddress: "cosmos1k8e50d2d8xkdfw9c4et3m45llh69e7xzw6uzga",
Amount: sdktypes.NewCoins(
sdktypes.NewCoin("token", math.NewIntFromUint64(1)),
),
}
tests := []struct {
name string
msg sdktypes.Msg
opts []cosmosclient.Option
expectedResponse *sdktypes.TxResponse
expectedError string
setup func(suite)
}{
{
name: "fail: error not found",
msg: msg,
expectedError: "make sure that your account has enough balance",
setup: func(s suite) {
s.expectPrepareFactory(sdkaddr)
s.signer.EXPECT().
Sign(mock.Anything, mock.Anything, "bob", mock.Anything, true).
Return(nil)
s.rpcClient.EXPECT().
BroadcastTxSync(mock.Anything, mock.Anything).
Return(nil, sdkerrors.ErrNotFound)
},
},
{
name: "fail: response code > 0",
msg: msg,
expectedError: "error code: '42' msg: 'oups'",
setup: func(s suite) {
s.expectPrepareFactory(sdkaddr)
s.signer.EXPECT().
Sign(mock.Anything, mock.Anything, "bob", mock.Anything, true).
Return(nil)
s.rpcClient.EXPECT().
BroadcastTxSync(mock.Anything, mock.Anything).
Return(&ctypes.ResultBroadcastTx{
Code: 42,
Log: "oups",
}, nil)
},
},
{
name: "ok: tx confirmed immediately",
msg: msg,
expectedResponse: &sdktypes.TxResponse{
TxHash: txHashStr,
RawLog: "log",
},
setup: func(s suite) {
s.expectPrepareFactory(sdkaddr)
s.signer.EXPECT().
Sign(mock.Anything, mock.Anything, "bob", mock.Anything, true).
Return(nil)
s.rpcClient.EXPECT().
BroadcastTxSync(mock.Anything, mock.Anything).
Return(&ctypes.ResultBroadcastTx{
Hash: txHash,
}, nil)
// Tx is broadcasted, now check for confirmation
s.rpcClient.EXPECT().Tx(mock.Anything, txHash, false).
Return(&ctypes.ResultTx{
Hash: txHash,
TxResult: abci.ExecTxResult{
Log: "log",
},
}, nil)
},
},
{
name: "fail: tx confirmed with error code",
msg: msg,
expectedError: "error code: '42' msg: 'oups'",
setup: func(s suite) {
s.expectPrepareFactory(sdkaddr)
s.signer.EXPECT().
Sign(mock.Anything, mock.Anything, "bob", mock.Anything, true).
Return(nil)
s.rpcClient.EXPECT().
BroadcastTxSync(mock.Anything, mock.Anything).
Return(&ctypes.ResultBroadcastTx{
Hash: txHash,
}, nil)
// Tx is broadcasted, now check for confirmation
s.rpcClient.EXPECT().Tx(mock.Anything, txHash, false).
Return(&ctypes.ResultTx{
Hash: txHash,
TxResult: abci.ExecTxResult{
Code: 42,
Log: "oups",
},
}, nil)
},
},
{
name: "ok: tx confirmed after a while",
msg: msg,
expectedResponse: &sdktypes.TxResponse{
TxHash: txHashStr,
},
setup: func(s suite) {
s.expectPrepareFactory(sdkaddr)
s.signer.EXPECT().
Sign(mock.Anything, mock.Anything, "bob", mock.Anything, true).
Return(nil)
s.rpcClient.EXPECT().
BroadcastTxSync(mock.Anything, mock.Anything).
Return(&ctypes.ResultBroadcastTx{
Hash: txHash,
}, nil)
// Tx is broadcasted, now check for confirmation
// First time the tx is not found (not confirmed yet)
s.rpcClient.EXPECT().Tx(mock.Anything, txHash, false).
Return(nil, errors.New("not found")).Once()
// Wait for 1 block
s.rpcClient.EXPECT().Status(mock.Anything).
Return(&ctypes.ResultStatus{
SyncInfo: ctypes.SyncInfo{LatestBlockHeight: 1},
}, nil).Once()
s.rpcClient.EXPECT().Status(mock.Anything).
Return(&ctypes.ResultStatus{
SyncInfo: ctypes.SyncInfo{LatestBlockHeight: 2},
}, nil).Once()
// Then try gain to fetch the tx, this time it is confirmed
s.rpcClient.EXPECT().Tx(mock.Anything, txHash, false).
Return(&ctypes.ResultTx{
Hash: txHash,
}, nil)
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := newClient(t, tt.setup, tt.opts...)
account, err := c.AccountRegistry.Import(accountName, key, passphrase)
require.NoError(t, err)
ctx := c.Context().
WithFromName(accountName).
WithFromAddress(sdkaddr)
txService, err := c.CreateTx(ctx.CmdContext, account, tt.msg)
require.NoError(t, err)
res, err := txService.Broadcast(ctx.CmdContext)
if tt.expectedError != "" {
require.EqualError(t, err, tt.expectedError)
return
}
require.NoError(t, err)
require.Equal(t, ctx.Codec, res.Codec)
require.Equal(t, tt.expectedResponse, res.TxResponse)
})
}
}
func TestTxServiceBroadcastAsync(t *testing.T) {
var (
accountName = "bob"
passphrase = "passphrase"
txHash = []byte{1, 2, 3}
txHashStr = hex.EncodeToString(txHash)
)
r, err := cosmosaccount.NewInMemory()
require.NoError(t, err)
a, _, err := r.Create(accountName)
require.NoError(t, err)
// Export created account to we can import it in the Client below.
key, err := r.Export(accountName, passphrase)
require.NoError(t, err)
sdkaddr, err := a.Record.GetAddress()
require.NoError(t, err)
msg := &banktypes.MsgSend{
FromAddress: sdkaddr.String(),
ToAddress: "cosmos1k8e50d2d8xkdfw9c4et3m45llh69e7xzw6uzga",
Amount: sdktypes.NewCoins(
sdktypes.NewCoin("token", math.NewIntFromUint64(1)),
),
}
tests := []struct {
name string
msg sdktypes.Msg
opts []cosmosclient.Option
expectedResponse *sdktypes.TxResponse
expectedError string
setup func(suite)
}{
{
name: "fail: error not found",
msg: msg,
expectedError: "make sure that your account has enough balance",
setup: func(s suite) {
s.expectPrepareFactory(sdkaddr)
s.signer.EXPECT().
Sign(mock.Anything, mock.Anything, "bob", mock.Anything, true).
Return(nil)
s.rpcClient.EXPECT().
BroadcastTxSync(mock.Anything, mock.Anything).
Return(nil, sdkerrors.ErrNotFound)
},
},
{
name: "fail: response code > 0",
msg: msg,
expectedError: "error code: '42' msg: 'oups'",
setup: func(s suite) {
s.expectPrepareFactory(sdkaddr)
s.signer.EXPECT().
Sign(mock.Anything, mock.Anything, "bob", mock.Anything, true).
Return(nil)
s.rpcClient.EXPECT().
BroadcastTxSync(mock.Anything, mock.Anything).
Return(&ctypes.ResultBroadcastTx{
Code: 42,
Log: "oups",
}, nil)
},
},
{
name: "ok: tx broadcasted successfully",
msg: msg,
expectedResponse: &sdktypes.TxResponse{
TxHash: txHashStr,
RawLog: "",
},
setup: func(s suite) {
s.expectPrepareFactory(sdkaddr)
s.signer.EXPECT().
Sign(mock.Anything, mock.Anything, "bob", mock.Anything, true).
Return(nil)
s.rpcClient.EXPECT().
BroadcastTxSync(mock.Anything, mock.Anything).
Return(&ctypes.ResultBroadcastTx{
Hash: txHash,
}, nil)
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := newClient(t, tt.setup, tt.opts...)
account, err := c.AccountRegistry.Import(accountName, key, passphrase)
require.NoError(t, err)
ctx := c.Context().
WithFromName(accountName).
WithFromAddress(sdkaddr)
txService, err := c.CreateTx(ctx.CmdContext, account, tt.msg)
require.NoError(t, err)
res, err := txService.BroadcastAsync(ctx.CmdContext)
if tt.expectedError != "" {
require.EqualError(t, err, tt.expectedError)
return
}
require.NoError(t, err)
require.Equal(t, ctx.Codec, res.Codec)
require.Equal(t, tt.expectedResponse, res.TxResponse)
})
}
}