Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions ignite/pkg/cosmosclient/cosmosclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ type Gasometer interface {
CalculateGas(clientCtx gogogrpc.ClientConn, txf tx.Factory, msgs ...sdktypes.Msg) (*txtypes.SimulateResponse, uint64, error)
}

// Signer allows to mock the tx.Sign func.
type Signer interface {
Sign(txf tx.Factory, name string, txBuilder client.TxBuilder, overwriteSig bool) error
}

// Client is a client to access your chain by querying and broadcasting transactions.
type Client struct {
// RPC is Tendermint RPC.
Expand All @@ -87,6 +92,7 @@ type Client struct {
bankQueryClient banktypes.QueryClient
faucetClient FaucetClient
gasometer Gasometer
signer Signer

addressPrefix string

Expand Down Expand Up @@ -248,6 +254,14 @@ func WithGasometer(gasometer Gasometer) Option {
}
}

// WithSigner sets the signer.
// Already set by default.
func WithSigner(signer Signer) Option {
return func(c *Client) {
c.signer = signer
}
}

// New creates a new client with given options.
func New(ctx context.Context, options ...Option) (Client, error) {
c := Client{
Expand Down Expand Up @@ -322,6 +336,9 @@ func New(ctx context.Context, options ...Option) (Client, error) {
if c.gasometer == nil {
c.gasometer = gasometer{}
}
if c.signer == nil {
c.signer = signer{}
}
// set address prefix in SDK global config
c.SetConfigAddressPrefix()

Expand Down
167 changes: 68 additions & 99 deletions ignite/pkg/cosmosclient/cosmosclient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,25 @@ import (
"github.com/ignite/cli/ignite/pkg/cosmosfaucet"
)

const (
defaultFaucetDenom = "token"
defaultFaucetMinAmount = 100
)

//go:generate mockery --srcpkg github.com/tendermint/tendermint/rpc/client/ --name Client --structname RPCClient --filename rpclient.go --with-expecter
//go:generate mockery --srcpkg github.com/cosmos/cosmos-sdk/client --name AccountRetriever --filename account_retriever.go --with-expecter
//go:generate mockery --srcpkg github.com/cosmos/cosmos-sdk/x/bank/types --name QueryClient --structname BankQueryClient --filename bank_query_client.go --with-expecter
//go:generate mockery --srcpkg . --name FaucetClient --structname FaucetClient --filename faucet_client.go --with-expecter
//go:generate mockery --srcpkg . --name Gasometer --filename gasometer.go --with-expecter
//go:generate mockery --srcpkg . --name Signer --filename signer.go --with-expecter

type suite struct {
rpcClient *mocks.RPCClient
accountRetriever *mocks.AccountRetriever
bankQueryClient *mocks.BankQueryClient
gasometer *mocks.Gasometer
faucetClient *mocks.FaucetClient
signer *mocks.Signer
}

func newClient(t *testing.T, setup func(suite), opts ...cosmosclient.Option) cosmosclient.Client {
Expand All @@ -41,6 +48,7 @@ func newClient(t *testing.T, setup func(suite), opts ...cosmosclient.Option) cos
bankQueryClient: mocks.NewBankQueryClient(t),
gasometer: mocks.NewGasometer(t),
faucetClient: mocks.NewFaucetClient(t),
signer: mocks.NewSigner(t),
}
// Because rpcClient is passed as argument inside clientContext of mocked
// methods, we must EXPECT a call to String (because testify/mock is calling
Expand All @@ -61,6 +69,7 @@ func newClient(t *testing.T, setup func(suite), opts ...cosmosclient.Option) cos
cosmosclient.WithBankQueryClient(s.bankQueryClient),
cosmosclient.WithGasometer(s.gasometer),
cosmosclient.WithFaucetClient(s.faucetClient),
cosmosclient.WithSigner(s.signer),
}...)
c, err := cosmosclient.New(context.Background(), opts...)
require.NoError(t, err)
Expand Down Expand Up @@ -309,10 +318,6 @@ func TestClientStatus(t *testing.T) {
}

func TestClientCreateTx(t *testing.T) {
const (
defaultFaucetDenom = "token"
defaultFaucetMinAmount = 100
)
var (
accountName = "bob"
passphrase = "passphrase"
Expand Down Expand Up @@ -354,12 +359,7 @@ func TestClientCreateTx(t *testing.T) {
},
expectedJSONTx: `{"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"from","to_address":"to","amount":[{"denom":"token","amount":"1"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"300000","payer":"","granter":""},"tip":null},"signatures":[]}`,
setup: func(s suite) {
s.accountRetriever.EXPECT().
EnsureExists(mock.Anything, sdkaddress).
Return(nil)
s.accountRetriever.EXPECT().
GetAccountNumberSequence(mock.Anything, sdkaddress).
Return(1, 2, nil)
s.expectPrepareFactory(sdkaddress)
},
},
{
Expand All @@ -376,26 +376,9 @@ func TestClientCreateTx(t *testing.T) {
},
expectedJSONTx: `{"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"from","to_address":"to","amount":[{"denom":"token","amount":"1"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"300000","payer":"","granter":""},"tip":null},"signatures":[]}`,
setup: func(s suite) {
balance := sdktypes.NewCoin("token", sdktypes.NewIntFromUint64(defaultFaucetMinAmount))
s.bankQueryClient.EXPECT().Balance(
context.Background(),
&banktypes.QueryBalanceRequest{
Address: sdkaddress.String(),
Denom: defaultFaucetDenom,
},
).Return(
&banktypes.QueryBalanceResponse{
Balance: &balance,
},
nil,
)
s.expectMakeSureAccountHasToken(sdkaddress.String(), defaultFaucetMinAmount)

s.accountRetriever.EXPECT().
EnsureExists(mock.Anything, sdkaddress).
Return(nil)
s.accountRetriever.EXPECT().
GetAccountNumberSequence(mock.Anything, sdkaddress).
Return(1, 2, nil)
s.expectPrepareFactory(sdkaddress)
},
},
{
Expand All @@ -412,46 +395,8 @@ func TestClientCreateTx(t *testing.T) {
},
expectedJSONTx: `{"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"from","to_address":"to","amount":[{"denom":"token","amount":"1"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"300000","payer":"","granter":""},"tip":null},"signatures":[]}`,
setup: func(s suite) {
balance := sdktypes.NewCoin("token", sdktypes.NewIntFromUint64(defaultFaucetMinAmount-1))
s.bankQueryClient.EXPECT().Balance(
context.Background(),
&banktypes.QueryBalanceRequest{
Address: sdkaddress.String(),
Denom: defaultFaucetDenom,
},
).Return(
&banktypes.QueryBalanceResponse{
Balance: &balance,
},
nil,
).Once()

s.faucetClient.EXPECT().Transfer(context.Background(),
cosmosfaucet.TransferRequest{AccountAddress: sdkaddress.String()},
).Return(
cosmosfaucet.TransferResponse{}, nil,
)

newBalance := sdktypes.NewCoin("token", sdktypes.NewIntFromUint64(defaultFaucetMinAmount))
s.bankQueryClient.EXPECT().Balance(
mock.Anything,
&banktypes.QueryBalanceRequest{
Address: sdkaddress.String(),
Denom: defaultFaucetDenom,
},
).Return(
&banktypes.QueryBalanceResponse{
Balance: &newBalance,
},
nil,
).Once()

s.accountRetriever.EXPECT().
EnsureExists(mock.Anything, sdkaddress).
Return(nil)
s.accountRetriever.EXPECT().
GetAccountNumberSequence(mock.Anything, sdkaddress).
Return(1, 2, nil)
s.expectMakeSureAccountHasToken(sdkaddress.String(), defaultFaucetMinAmount-1)
s.expectPrepareFactory(sdkaddress)
},
},
{
Expand All @@ -468,12 +413,7 @@ func TestClientCreateTx(t *testing.T) {
},
expectedJSONTx: `{"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"from","to_address":"to","amount":[{"denom":"token","amount":"1"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[{"denom":"token","amount":"10"}],"gas_limit":"300000","payer":"","granter":""},"tip":null},"signatures":[]}`,
setup: func(s suite) {
s.accountRetriever.EXPECT().
EnsureExists(mock.Anything, sdkaddress).
Return(nil)
s.accountRetriever.EXPECT().
GetAccountNumberSequence(mock.Anything, sdkaddress).
Return(1, 2, nil)
s.expectPrepareFactory(sdkaddress)
},
},
{
Expand All @@ -491,12 +431,7 @@ func TestClientCreateTx(t *testing.T) {
},
expectedJSONTx: `{"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"from","to_address":"to","amount":[{"denom":"token","amount":"1"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[{"denom":"token","amount":"900000"}],"gas_limit":"300000","payer":"","granter":""},"tip":null},"signatures":[]}`,
setup: func(s suite) {
s.accountRetriever.EXPECT().
EnsureExists(mock.Anything, sdkaddress).
Return(nil)
s.accountRetriever.EXPECT().
GetAccountNumberSequence(mock.Anything, sdkaddress).
Return(1, 2, nil)
s.expectPrepareFactory(sdkaddress)
},
},
{
Expand All @@ -514,12 +449,7 @@ func TestClientCreateTx(t *testing.T) {
},
expectedError: "cannot provide both fees and gas prices",
setup: func(s suite) {
s.accountRetriever.EXPECT().
EnsureExists(mock.Anything, sdkaddress).
Return(nil)
s.accountRetriever.EXPECT().
GetAccountNumberSequence(mock.Anything, sdkaddress).
Return(1, 2, nil)
s.expectPrepareFactory(sdkaddress)
},
},
{
Expand All @@ -536,12 +466,7 @@ func TestClientCreateTx(t *testing.T) {
},
expectedJSONTx: `{"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"from","to_address":"to","amount":[{"denom":"token","amount":"1"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"20042","payer":"","granter":""},"tip":null},"signatures":[]}`,
setup: func(s suite) {
s.accountRetriever.EXPECT().
EnsureExists(mock.Anything, sdkaddress).
Return(nil)
s.accountRetriever.EXPECT().
GetAccountNumberSequence(mock.Anything, sdkaddress).
Return(1, 2, nil)
s.expectPrepareFactory(sdkaddress)
s.gasometer.EXPECT().
CalculateGas(mock.Anything, mock.Anything, mock.Anything).
Return(nil, 42, nil)
Expand All @@ -561,12 +486,7 @@ func TestClientCreateTx(t *testing.T) {
},
expectedJSONTx: `{"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"from","to_address":"to","amount":[{"denom":"token","amount":"1"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"20042","payer":"","granter":""},"tip":null},"signatures":[]}`,
setup: func(s suite) {
s.accountRetriever.EXPECT().
EnsureExists(mock.Anything, sdkaddress).
Return(nil)
s.accountRetriever.EXPECT().
GetAccountNumberSequence(mock.Anything, sdkaddress).
Return(1, 2, nil)
s.expectPrepareFactory(sdkaddress)
s.gasometer.EXPECT().
CalculateGas(mock.Anything, mock.Anything, mock.Anything).
Return(nil, 42, nil)
Expand Down Expand Up @@ -598,3 +518,52 @@ func TestClientCreateTx(t *testing.T) {
})
}
}

func (s suite) expectMakeSureAccountHasToken(address string, balance int64) {
currentBalance := sdktypes.NewInt64Coin(defaultFaucetDenom, balance)
s.bankQueryClient.EXPECT().Balance(
context.Background(),
&banktypes.QueryBalanceRequest{
Address: address,
Denom: defaultFaucetDenom,
},
).Return(
&banktypes.QueryBalanceResponse{
Balance: &currentBalance,
},
nil,
).Once()
if balance >= defaultFaucetMinAmount {
// balance is high enought, faucet won't be called
return
}

s.faucetClient.EXPECT().Transfer(context.Background(),
cosmosfaucet.TransferRequest{AccountAddress: address},
).Return(
cosmosfaucet.TransferResponse{}, nil,
)

newBalance := sdktypes.NewInt64Coin(defaultFaucetDenom, defaultFaucetMinAmount)
s.bankQueryClient.EXPECT().Balance(
mock.Anything,
&banktypes.QueryBalanceRequest{
Address: address,
Denom: defaultFaucetDenom,
},
).Return(
&banktypes.QueryBalanceResponse{
Balance: &newBalance,
},
nil,
).Once()
}

func (s suite) expectPrepareFactory(sdkaddress sdktypes.Address) {
s.accountRetriever.EXPECT().
EnsureExists(mock.Anything, sdkaddress).
Return(nil)
s.accountRetriever.EXPECT().
GetAccountNumberSequence(mock.Anything, sdkaddress).
Return(1, 2, nil)
}
2 changes: 1 addition & 1 deletion ignite/pkg/cosmosclient/gasometer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
gogogrpc "github.com/gogo/protobuf/grpc"
)

// Implements Gasometer
// gasometer implements the Gasometer interface
type gasometer struct{}

func (gasometer) CalculateGas(clientCtx gogogrpc.ClientConn, txf tx.Factory, msgs ...sdktypes.Msg) (*txtypes.SimulateResponse, uint64, error) {
Expand Down
Loading