139 lines
4.4 KiB
Go
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)
|
||
|
}
|