package faucet_test
import (
"context"
"fmt"
"net/http"
"strings"
"testing"
"time"
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/stretchr/testify/require"
"golang.org/x/sync/errgroup"
"github.com/ignite/cli/v29/ignite/pkg/cosmosclient"
"github.com/ignite/cli/v29/ignite/pkg/cosmosfaucet"
"github.com/ignite/cli/v29/ignite/pkg/xurl"
envtest "github.com/ignite/cli/v29/integration"
)
const (
addr = "cosmos1zqr2gd7hwkyw55knad0l6ml6ngutd70878evqj"
)
var (
defaultCoins = []string{"10token", "1stake"}
maxCoins = []string{"102token", "100000000stake"}
)
func TestRequestCoinsFromFaucet(t *testing.T) {
var (
env = envtest.New(t)
app = env.ScaffoldApp("github.com/test/faucetapp")
servers = app.RandomizeServerPorts()
faucetURL = app.EnableFaucet(defaultCoins, maxCoins)
ctx, cancel = context.WithTimeout(env.Ctx(), envtest.ServeTimeout)
faucetClient = cosmosfaucet.NewClient(faucetURL)
)
isErrTransferRequest := func(err error, expectedCode int) {
var errTransfer cosmosfaucet.ErrTransferRequest
require.ErrorAs(t, err, &errTransfer)
require.EqualValues(t, expectedCode, errTransfer.StatusCode)
}
go func() {
app.Serve("should serve app", envtest.ExecCtx(ctx))
}()
defer cancel()
app.WaitChainUp(ctx, servers.API)
err := env.IsFaucetServed(ctx, faucetClient)
require.NoError(t, err)
time.Sleep(time.Second * 1)
nodeAddr, err := xurl.HTTP(servers.RPC)
require.NoError(t, err)
cosmosClient, err := cosmosclient.New(ctx, cosmosclient.WithNodeAddress(nodeAddr))
require.NoError(t, err)
_, err = faucetClient.Transfer(ctx, cosmosfaucet.NewTransferRequest(addr, nil))
require.NoError(t, err)
checkAccountBalance(ctx, t, cosmosClient, addr, defaultCoins)
_, err = faucetClient.Transfer(ctx, cosmosfaucet.NewTransferRequest(addr, []string{"20token", "2stake"}))
require.NoError(t, err)
checkAccountBalance(ctx, t, cosmosClient, addr, []string{"30token", "3stake"})
_, err = faucetClient.Transfer(ctx, cosmosfaucet.NewTransferRequest(addr, []string{"no-token"}))
isErrTransferRequest(err, http.StatusBadRequest)
_, err = faucetClient.Transfer(ctx, cosmosfaucet.NewTransferRequest(addr, []string{"500token"}))
isErrTransferRequest(err, http.StatusInternalServerError)
_, err = faucetClient.Transfer(ctx, cosmosfaucet.NewTransferRequest(addr, []string{"500nonexistent"}))
isErrTransferRequest(err, http.StatusInternalServerError)
g, ctx := errgroup.WithContext(ctx)
for i := 0; i < 10; i++ {
g.Go(func() error {
c := faucetClient
index := i + 1
coins := []string{
sdk.NewCoin("token", math.NewInt(int64(index*2))).String(),
sdk.NewCoin("stake", math.NewInt(int64(index*3))).String(),
}
_, err := c.Transfer(ctx, cosmosfaucet.NewTransferRequest(addr, coins))
return err
})
}
require.NoError(t, g.Wait())
checkAccountBalance(ctx, t, cosmosClient, addr, []string{"168stake", "140token"})
}
func checkAccountBalance(ctx context.Context, t *testing.T, c cosmosclient.Client, accAddr string, coins []string) {
t.Helper()
resp, err := banktypes.NewQueryClient(c.Context()).AllBalances(ctx, &banktypes.QueryAllBalancesRequest{
Address: accAddr,
})
require.NoError(t, err)
require.Len(t, resp.Balances, len(coins))
expectedCoins, err := sdk.ParseCoinsNormalized(strings.Join(coins, ","))
require.NoError(t, err)
expectedCoins = expectedCoins.Sort()
gotCoins := resp.Balances.Sort()
require.True(t, gotCoins.Equal(expectedCoins),
fmt.Sprintf("%s should be equals to %s", gotCoins.String(), expectedCoins.String()),
)
}