package interchaintest import ( "context" "fmt" "strings" "testing" "github.com/persistenceOne/persistenceCore/v9/interchaintest/helpers" "github.com/strangelove-ventures/interchaintest/v7" "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" "github.com/strangelove-ventures/interchaintest/v7/ibc" interchaintestrelayer "github.com/strangelove-ventures/interchaintest/v7/relayer" "github.com/strangelove-ventures/interchaintest/v7/testreporter" "github.com/strangelove-ventures/interchaintest/v7/testutil" "github.com/stretchr/testify/require" "go.uber.org/zap/zaptest" ) // TestPersistenceIBCHooks ensures the ibc-hooks middleware from osmosis works. func TestPersistenceIBCHooks(t *testing.T) { if testing.Short() { t.Skip() } t.Parallel() // Create chain factory with Persistence and Persistence2 numVals := 1 numFullNodes := 0 cfg2 := persistenceChainConfig().Clone() cfg2.Name = "persistence-counterparty" cfg2.ChainID = "ictest-core-2" cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{ { Name: "persistence", ChainConfig: persistenceChainConfig(), NumValidators: &numVals, NumFullNodes: &numFullNodes, }, { Name: "persistence", ChainConfig: cfg2, NumValidators: &numVals, NumFullNodes: &numFullNodes, }, }) const ( path = "ibc-path" ) // Get chains from the chain factory chains, err := cf.Chains(t.Name()) require.NoError(t, err) client, network := interchaintest.DockerSetup(t) p1Chain, p2Chain := chains[0].(*cosmos.CosmosChain), chains[1].(*cosmos.CosmosChain) relayerType, relayerName := ibc.CosmosRly, "relay" // Get a relayer instance rf := interchaintest.NewBuiltinRelayerFactory( relayerType, zaptest.NewLogger(t), interchaintestrelayer.CustomDockerImage(IBCRelayerImage, IBCRelayerVersion, "100:1000"), interchaintestrelayer.StartupFlags("--processor", "events", "--block-history", "100"), ) r := rf.Build(t, client, network) ic := interchaintest.NewInterchain(). AddChain(p1Chain). AddChain(p2Chain). AddRelayer(r, relayerName). AddLink(interchaintest.InterchainLink{ Chain1: p1Chain, Chain2: p2Chain, Relayer: r, Path: path, }) ctx := context.Background() rep := testreporter.NewNopReporter() eRep := rep.RelayerExecReporter(t) require.NoError(t, ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{ TestName: t.Name(), Client: client, NetworkID: network, BlockDatabaseFile: interchaintest.DefaultBlockDatabaseFilepath(), SkipPathCreation: false, })) t.Cleanup(func() { _ = ic.Close() }) // Create some user accounts on both chains users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), genesisWalletAmount, p1Chain, p2Chain) // Wait a few blocks for relayer to start and for user accounts to be created err = testutil.WaitForBlocks(ctx, 5, p1Chain, p2Chain) require.NoError(t, err) // Get our Bech32 encoded user addresses persistenceUser, persistence2User := users[0], users[1] persistenceUserAddr := persistenceUser.FormattedAddress() channel, err := ibc.GetTransferChannel(ctx, r, eRep, p1Chain.Config().ChainID, p2Chain.Config().ChainID) require.NoError(t, err) err = r.StartRelayer(ctx, eRep, path) require.NoError(t, err) t.Cleanup( func() { err := r.StopRelayer(ctx, eRep) if err != nil { t.Logf("an error occured while stopping the relayer: %s", err) } }, ) _, contractAddr := helpers.SetupContract(t, ctx, p2Chain, persistence2User.KeyName(), "contracts/ibchooks_counter.wasm", `{"count":0}`) // do an ibc transfer through the memo to the other chain. transfer := ibc.WalletAmount{ Address: contractAddr, Denom: p1Chain.Config().Denom, Amount: int64(1), } memo := ibc.TransferOptions{ Memo: fmt.Sprintf(`{"wasm":{"contract":"%s","msg":%s}}`, contractAddr, `{"increment":{}}`), } // Initial transfer. Account is created by the wasm execute is not so we must do this twice to properly set up transferTx, err := p1Chain.SendIBCTransfer(ctx, channel.ChannelID, persistenceUser.KeyName(), transfer, memo) require.NoError(t, err) p1Height, err := p1Chain.Height(ctx) require.NoError(t, err) _, err = testutil.PollForAck(ctx, p1Chain, p1Height-5, p1Height+25, transferTx.Packet) require.NoError(t, err) // Second time, this will make the counter == 1 since the account is now created. transferTx, err = p1Chain.SendIBCTransfer(ctx, channel.ChannelID, persistenceUser.KeyName(), transfer, memo) require.NoError(t, err) p1Height, err = p1Chain.Height(ctx) require.NoError(t, err) _, err = testutil.PollForAck(ctx, p1Chain, p1Height-5, p1Height+25, transferTx.Packet) require.NoError(t, err) // Get the address on the other chain's side addr := helpers.GetIBCHooksUserAddress(t, ctx, p1Chain, channel.ChannelID, persistenceUserAddr) require.NotEmpty(t, addr) // Get funds on the receiving chain funds := helpers.GetIBCHookTotalFunds(t, ctx, p2Chain, contractAddr, addr) require.Equal(t, int(1), len(funds.Data.TotalFunds)) var ibcDenom string for _, coin := range funds.Data.TotalFunds { if strings.HasPrefix(coin.Denom, "ibc/") { ibcDenom = coin.Denom break } } require.NotEmpty(t, ibcDenom) // ensure the count also increased to 1 as expected. count := helpers.GetIBCHookCount(t, ctx, p2Chain, contractAddr, addr) require.Equal(t, int64(1), count.Data.Count) }