laconicd-deprecated/x/wasm/ibctesting/wasm.go
2023-02-28 15:05:49 +05:30

139 lines
4.4 KiB
Go

package ibctesting
import (
"bytes"
"compress/gzip"
"encoding/json"
"fmt"
"os"
"strings"
ibctesting "github.com/cosmos/ibc-go/v4/testing"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/golang/protobuf/proto" //nolint
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/rand"
"github.com/cerc-io/laconicd/x/wasm/types"
)
var wasmIdent = []byte("\x00\x61\x73\x6D")
// SeedNewContractInstance stores some wasm code and instantiates a new contract on this chain.
// This method can be called to prepare the store with some valid CodeInfo and ContractInfo. The returned
// Address is the contract address for this instance. Test should make use of this data and/or use NewIBCContractMockWasmer
// for using a contract mock in Go.
func (chain *TestChain) SeedNewContractInstance() sdk.AccAddress {
pInstResp := chain.StoreCode(append(wasmIdent, rand.Bytes(10)...))
codeID := pInstResp.CodeID
anyAddressStr := chain.SenderAccount.GetAddress().String()
initMsg := []byte(fmt.Sprintf(`{"verifier": %q, "beneficiary": %q}`, anyAddressStr, anyAddressStr))
return chain.InstantiateContract(codeID, initMsg)
}
func (chain *TestChain) StoreCodeFile(filename string) types.MsgStoreCodeResponse {
wasmCode, err := os.ReadFile(filename)
require.NoError(chain.t, err)
if strings.HasSuffix(filename, "wasm") { // compress for gas limit
var buf bytes.Buffer
gz := gzip.NewWriter(&buf)
_, err := gz.Write(wasmCode)
require.NoError(chain.t, err)
err = gz.Close()
require.NoError(chain.t, err)
wasmCode = buf.Bytes()
}
return chain.StoreCode(wasmCode)
}
func (chain *TestChain) StoreCode(byteCode []byte) types.MsgStoreCodeResponse {
storeMsg := &types.MsgStoreCode{
Sender: chain.SenderAccount.GetAddress().String(),
WASMByteCode: byteCode,
}
r, err := chain.SendMsgs(storeMsg)
require.NoError(chain.t, err)
protoResult := chain.parseSDKResultData(r)
require.Len(chain.t, protoResult.Data, 1)
// unmarshal protobuf response from data
var pInstResp types.MsgStoreCodeResponse
require.NoError(chain.t, pInstResp.Unmarshal(protoResult.Data[0].Data))
require.NotEmpty(chain.t, pInstResp.CodeID)
require.NotEmpty(chain.t, pInstResp.Checksum)
return pInstResp
}
func (chain *TestChain) InstantiateContract(codeID uint64, initMsg []byte) sdk.AccAddress {
instantiateMsg := &types.MsgInstantiateContract{
Sender: chain.SenderAccount.GetAddress().String(),
Admin: chain.SenderAccount.GetAddress().String(),
CodeID: codeID,
Label: "ibc-test",
Msg: initMsg,
Funds: sdk.Coins{ibctesting.TestCoin},
}
r, err := chain.SendMsgs(instantiateMsg)
require.NoError(chain.t, err)
protoResult := chain.parseSDKResultData(r)
require.Len(chain.t, protoResult.Data, 1)
var pExecResp types.MsgInstantiateContractResponse
require.NoError(chain.t, pExecResp.Unmarshal(protoResult.Data[0].Data))
a, err := sdk.AccAddressFromBech32(pExecResp.Address)
require.NoError(chain.t, err)
return a
}
// SmartQuery This will serialize the query message and submit it to the contract.
// The response is parsed into the provided interface.
// Usage: SmartQuery(addr, QueryMsg{Foo: 1}, &response)
func (chain *TestChain) SmartQuery(contractAddr string, queryMsg interface{}, response interface{}) error {
msg, err := json.Marshal(queryMsg)
if err != nil {
return err
}
req := types.QuerySmartContractStateRequest{
Address: contractAddr,
QueryData: msg,
}
reqBin, err := proto.Marshal(&req)
if err != nil {
return err
}
// TODO: what is the query?
res := chain.App.Query(abci.RequestQuery{
Path: "/cosmwasm.wasm.v1.Query/SmartContractState",
Data: reqBin,
})
if res.Code != 0 {
return fmt.Errorf("query failed: (%d) %s", res.Code, res.Log)
}
// unpack protobuf
var resp types.QuerySmartContractStateResponse
err = proto.Unmarshal(res.Value, &resp)
if err != nil {
return err
}
// unpack json content
return json.Unmarshal(resp.Data, response)
}
func (chain *TestChain) parseSDKResultData(r *sdk.Result) sdk.TxMsgData {
var protoResult sdk.TxMsgData
require.NoError(chain.t, proto.Unmarshal(r.Data, &protoResult))
return protoResult
}
// ContractInfo is a helper function to returns the ContractInfo for the given contract address
func (chain *TestChain) ContractInfo(contractAddr sdk.AccAddress) *types.ContractInfo {
return chain.App.WasmKeeper.GetContractInfo(chain.GetContext(), contractAddr)
}