package envtest import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "net/url" "strings" "time" "github.com/stretchr/testify/require" "github.com/ignite/cli/v29/ignite/pkg/cmdrunner/step" "github.com/ignite/cli/v29/ignite/pkg/errors" "github.com/ignite/cli/v29/ignite/pkg/gomodulepath" "github.com/ignite/cli/v29/ignite/pkg/xurl" ) const defaultRequestTimeout = 90 * time.Second type TxResponse struct { Code int `json:"code"` Codespace string `json:"codespace"` RawLog string `json:"raw_log"` TxHash string `json:"txhash"` Height string `json:"height"` Data string `json:"data"` Info string `json:"info"` GasWanted string `json:"gas_wanted"` GasUsed string `json:"gas_used"` Timestamp string `json:"timestamp"` } func (a App) CLITx(chainRPC, module, method string, args ...string) TxResponse { nodeAddr, err := xurl.TCP(chainRPC) require.NoErrorf(a.env.T(), err, "cant read nodeAddr from host.RPC %v", chainRPC) args = append(args, "--node", nodeAddr, "--home", a.homePath, "--from", "alice", "--output", "json", "--log_format", "json", "--keyring-backend", "test", "--yes", ) var ( output = &bytes.Buffer{} outErr = &bytes.Buffer{} txResponse = TxResponse{} ) stepsTx := step.NewSteps( step.New( step.Stdout(output), step.Stderr(outErr), step.PreExec(func() error { output.Reset() outErr.Reset() return nil }), step.Exec( a.Binary(), append([]string{"tx", module, method}, args...)..., ), step.PostExec(func(execErr error) error { if execErr != nil { return execErr } if outErr.Len() > 0 { return errors.Errorf("error executing request: %s", outErr.String()) } output := output.Bytes() if err := json.Unmarshal(output, &txResponse); err != nil { return errors.Errorf("unmarshalling tx response error: %w, response: %s", err, string(output)) } return nil }), )) ctx, cancel := context.WithTimeout(a.env.Ctx(), defaultRequestTimeout) defer cancel() if !a.env.Exec("sending chain request "+args[0], stepsTx, ExecRetry(), ExecCtx(ctx)) { cancel() a.env.t.FailNow() } return txResponse } func (a App) CLIQueryTx(chainRPC, txHash string) (txResponse TxResponse) { output := a.query(chainRPC, "tx", txHash) err := json.Unmarshal(output, &txResponse) require.NoError(a.env.T(), err, "unmarshalling tx response: %s", string(output)) return txResponse } func (a App) CLIQuery(chainRPC, module, method string, args ...string) []byte { return a.query(chainRPC, module, method, args...) } func (a App) query(chainRPC, module, method string, args ...string) []byte { nodeAddr, err := xurl.TCP(chainRPC) require.NoErrorf(a.env.T(), err, "cant read nodeAddr from host.RPC %v", chainRPC) var ( output = &bytes.Buffer{} outErr = &bytes.Buffer{} ) cmd := append([]string{"query", module, method}, args...) cmd = append(cmd, "--node", nodeAddr, "--home", a.homePath, "--output", "json", "--log_format", "json", ) steps := step.NewSteps( step.New( step.Stdout(output), step.Stderr(outErr), step.PreExec(func() error { output.Reset() outErr.Reset() return nil }), step.Exec(a.Binary(), cmd...), step.PostExec(func(execErr error) error { if execErr != nil { return execErr } if outErr.Len() > 0 { return errors.Errorf("error executing request: %s", outErr.String()) } return nil }), )) if !a.env.Exec(fmt.Sprintf("fetching query data %s => %s", module, method), steps, ExecRetry()) { a.env.t.FailNow() } return output.Bytes() } func (a App) APIQuery(ctx context.Context, chainAPI, namespace, module, method string, args ...string) []byte { ctx, cancel := context.WithTimeout(ctx, defaultRequestTimeout) defer cancel() chainAPI, err := xurl.HTTP(chainAPI) require.NoErrorf(a.env.T(), err, "failed to convert chain API %s to HTTP", chainAPI) modulePath := gomodulepath.ExtractAppPath(namespace) apiURL, err := url.JoinPath(chainAPI, modulePath, module, "v1", method, strings.Join(args, "/")) require.NoErrorf(a.env.T(), err, "failed to create API URL") req, err := http.NewRequestWithContext(ctx, "GET", apiURL, nil) require.NoErrorf(a.env.T(), err, "failed to create HTTP request") req.Header.Set("Accept", "application/json") resp, err := http.DefaultClient.Do(req) require.NoErrorf(a.env.T(), err, "failed to execute HTTP request") defer resp.Body.Close() if resp.StatusCode != http.StatusOK { require.Failf(a.env.T(), "unexpected status code", "expected 200 OK, got %d", resp.StatusCode) } body, err := io.ReadAll(resp.Body) require.NoErrorf(a.env.T(), err, "failed to read response body") return body }