diff --git a/manager/eris-mint/eris-mint.go b/manager/eris-mint/eris-mint.go
index d15f75cdd766bfc1fb000de6b1f8e246b84922e3..809540879b1d262b843adadcd544dff5126e609e 100644
--- a/manager/eris-mint/eris-mint.go
+++ b/manager/eris-mint/eris-mint.go
@@ -159,7 +159,7 @@ func (app *ErisMint) CheckTx(txBytes []byte) (res tmsp.Result) {
 		return tmsp.NewError(tmsp.CodeType_EncodingError, fmt.Sprintf("Encoding error: %v", err))
 	}
 
-	// TODO: make errors tmsp aware
+	// TODO: map ExecTx errors to sensible TMSP error codes
 	err = sm.ExecTx(app.checkCache, *tx, false, nil)
 	if err != nil {
 		return tmsp.NewError(tmsp.CodeType_InternalError, fmt.Sprintf("Internal error: %v", err))
@@ -185,14 +185,11 @@ func (app *ErisMint) Commit() (res tmsp.Result) {
 	// sync the AppendTx cache
 	app.cache.Sync()
 
-	// if there were any txs in the block,
-	// reset the check cache to the new height
-	if app.nTxs > 0 {
-		log.WithFields(log.Fields{
-			"txs": app.nTxs,
-		}).Info("Reset checkCache")
-		app.checkCache = sm.NewBlockCache(app.state)
-	}
+	// Refresh the checkCache with the latest commited state
+	log.WithFields(log.Fields{
+		"txs": app.nTxs,
+	}).Info("Reset checkCache")
+	app.checkCache = sm.NewBlockCache(app.state)
 	app.nTxs = 0
 
 	// save state to disk
diff --git a/manager/eris-mint/pipe.go b/manager/eris-mint/pipe.go
index 00d955de8a48779f5a584b0acbfab78254344c3a..1c01c75bb11172575c438e946d500c013f93d50f 100644
--- a/manager/eris-mint/pipe.go
+++ b/manager/eris-mint/pipe.go
@@ -547,12 +547,12 @@ func (pipe *erisMintPipe) BroadcastTxSync(tx txs.Tx) (*rpc_tm_types.ResultBroadc
 func (pipe *erisMintPipe) BlockchainInfo(minHeight, maxHeight,
 	maxBlockLookback int) (*rpc_tm_types.ResultBlockchainInfo, error) {
 
-	blockStore := pipe.blockchain.blockStore
+	height := pipe.consensusEngine.Height()
 
 	if maxHeight < 1 {
-		maxHeight = blockStore.Height()
+		maxHeight = height
 	} else {
-		maxHeight = imath.MinInt(blockStore.Height(), maxHeight)
+		maxHeight = imath.MinInt(height, maxHeight)
 	}
 	if minHeight < 1 {
 		minHeight = imath.MaxInt(1, maxHeight-maxBlockLookback)
@@ -560,9 +560,9 @@ func (pipe *erisMintPipe) BlockchainInfo(minHeight, maxHeight,
 
 	blockMetas := []*tm_types.BlockMeta{}
 	for height := maxHeight; height >= minHeight; height-- {
-		blockMeta := blockStore.LoadBlockMeta(height)
+		blockMeta := pipe.consensusEngine.LoadBlockMeta(height)
 		blockMetas = append(blockMetas, blockMeta)
 	}
 
-	return &rpc_tm_types.ResultBlockchainInfo{blockStore.Height(), blockMetas}, nil
+	return &rpc_tm_types.ResultBlockchainInfo{height, blockMetas}, nil
 }
diff --git a/manager/eris-mint/state/execution.go b/manager/eris-mint/state/execution.go
index 34d8afd049e7ae8b3d0879aca10f445965807d52..ceefbbd8368a2491e1a743f87b823fd40558935e 100644
--- a/manager/eris-mint/state/execution.go
+++ b/manager/eris-mint/state/execution.go
@@ -571,6 +571,7 @@ func ExecTx(blockCache *BlockCache, tx txs.Tx, runCall bool, evc events.Fireable
 
 		if entry != nil {
 			var expired bool
+
 			// if the entry already exists, and hasn't expired, we must be owner
 			if entry.Expires > lastBlockHeight {
 				// ensure we are owner
diff --git a/rpc/tendermint/client/client.go b/rpc/tendermint/client/client.go
index a696389c7c348b122cabd919924f79d386d3dec6..9750b373c8f8978e38af9a6770f54b3c3fdfc7af 100644
--- a/rpc/tendermint/client/client.go
+++ b/rpc/tendermint/client/client.go
@@ -1,6 +1,9 @@
 package client
 
 import (
+	"errors"
+	"fmt"
+
 	acm "github.com/eris-ltd/eris-db/account"
 	core_types "github.com/eris-ltd/eris-db/core/types"
 	rpc_types "github.com/eris-ltd/eris-db/rpc/tendermint/core/types"
@@ -10,14 +13,7 @@ import (
 )
 
 func Status(client rpcclient.Client) (*rpc_types.ResultStatus, error) {
-	var res rpc_types.ErisDBResult //ResultStatus)
-	var err error
-	switch cli := client.(type) {
-	case *rpcclient.ClientJSONRPC:
-		_, err = cli.Call("status", []interface{}{}, &res)
-	case *rpcclient.ClientURI:
-		_, err = cli.Call("status", map[string]interface{}{}, &res)
-	}
+	res, err := performCall(client, "status")
 	if err != nil {
 		return nil, err
 	}
@@ -25,30 +21,16 @@ func Status(client rpcclient.Client) (*rpc_types.ResultStatus, error) {
 }
 
 func GenPrivAccount(client rpcclient.Client) (*acm.PrivAccount, error) {
-	var res rpc_types.ErisDBResult
-	var err error
-	switch cli := client.(type) {
-	case *rpcclient.ClientJSONRPC:
-		_, err = cli.Call("unsafe/gen_priv_account", []interface{}{}, &res)
-	case *rpcclient.ClientURI:
-		_, err = cli.Call("unsafe/gen_priv_account", map[string]interface{}{}, &res)
-	}
+	res, err := performCall(client, "unsafe/gen_priv_account")
 	if err != nil {
 		return nil, err
 	}
 	return res.(*rpc_types.ResultGenPrivAccount).PrivAccount, nil
 }
 
-func GetAccount(client rpcclient.Client, addr []byte) (*acm.Account, error) {
-	var res rpc_types.ErisDBResult
-	var err error
-	switch cli := client.(type) {
-	case *rpcclient.ClientJSONRPC:
-		_, err = cli.Call("get_account", []interface{}{addr}, &res)
-	case *rpcclient.ClientURI:
-		_, err = cli.Call("get_account", map[string]interface{}{"address": addr},
-			&res)
-	}
+func GetAccount(client rpcclient.Client, address []byte) (*acm.Account, error) {
+	res, err := performCall(client, "get_account",
+		"address", address)
 	if err != nil {
 		return nil, err
 	}
@@ -56,21 +38,10 @@ func GetAccount(client rpcclient.Client, addr []byte) (*acm.Account, error) {
 }
 
 func SignTx(client rpcclient.Client, tx txs.Tx,
-	privAccs []*acm.PrivAccount) (txs.Tx, error) {
-	wrapTx := struct {
-		txs.Tx `json:"unwrap"`
-	}{tx}
-	var res rpc_types.ErisDBResult
-	var err error
-	switch cli := client.(type) {
-	case *rpcclient.ClientJSONRPC:
-		_, err = cli.Call("unsafe/sign_tx", []interface{}{wrapTx, privAccs}, &res)
-	case *rpcclient.ClientURI:
-		_, err = cli.Call("unsafe/sign_tx", map[string]interface{}{
-			"tx":           wrapTx,
-			"privAccounts": privAccs,
-		}, &res)
-	}
+	privAccounts []*acm.PrivAccount) (txs.Tx, error) {
+	res, err := performCall(client, "unsafe/sign_tx",
+		"tx", wrappedTx{tx},
+		"privAccounts", privAccounts)
 	if err != nil {
 		return nil, err
 	}
@@ -79,18 +50,8 @@ func SignTx(client rpcclient.Client, tx txs.Tx,
 
 func BroadcastTx(client rpcclient.Client,
 	tx txs.Tx) (txs.Receipt, error) {
-	wrapTx := struct {
-		txs.Tx `json:"unwrap"`
-	}{tx}
-	var res rpc_types.ErisDBResult
-	var err error
-	switch cli := client.(type) {
-	case *rpcclient.ClientJSONRPC:
-		_, err = cli.Call("broadcast_tx", []interface{}{wrapTx}, &res)
-	case *rpcclient.ClientURI:
-		_, err = cli.Call("broadcast_tx", map[string]interface{}{"tx": wrapTx},
-			&res)
-	}
+	res, err := performCall(client, "broadcast_tx",
+		"tx", wrappedTx{tx})
 	if err != nil {
 		return txs.Receipt{}, err
 	}
@@ -102,55 +63,31 @@ func BroadcastTx(client rpcclient.Client,
 }
 
 func DumpStorage(client rpcclient.Client,
-	addr []byte) (*rpc_types.ResultDumpStorage, error) {
-	var res rpc_types.ErisDBResult
-	var err error
-	switch cli := client.(type) {
-	case *rpcclient.ClientJSONRPC:
-		_, err = cli.Call("dump_storage", []interface{}{addr}, &res)
-	case *rpcclient.ClientURI:
-		_, err = cli.Call("dump_storage", map[string]interface{}{"address": addr},
-			&res)
-	}
+	address []byte) (*rpc_types.ResultDumpStorage, error) {
+	res, err := performCall(client, "dump_storage",
+		"address", address)
 	if err != nil {
 		return nil, err
 	}
 	return res.(*rpc_types.ResultDumpStorage), err
 }
 
-func GetStorage(client rpcclient.Client, addr, key []byte) ([]byte, error) {
-	var res rpc_types.ErisDBResult
-	var err error
-	switch cli := client.(type) {
-	case *rpcclient.ClientJSONRPC:
-		_, err = cli.Call("get_storage", []interface{}{addr, key}, &res)
-	case *rpcclient.ClientURI:
-		_, err = cli.Call("get_storage", map[string]interface{}{
-			"address": addr,
-			"key":     key,
-		}, &res)
-	}
+func GetStorage(client rpcclient.Client, address, key []byte) ([]byte, error) {
+	res, err := performCall(client, "get_storage",
+		"address", address,
+		"key", key)
 	if err != nil {
 		return nil, err
 	}
 	return res.(*rpc_types.ResultGetStorage).Value, nil
 }
 
-func CallCode(client rpcclient.Client,
-	fromAddress, code, data []byte) (*rpc_types.ResultCall, error) {
-	var res rpc_types.ErisDBResult
-	var err error
-	switch cli := client.(type) {
-	case *rpcclient.ClientJSONRPC:
-		_, err = cli.Call("call_code", []interface{}{fromAddress, code, data}, &res)
-	case *rpcclient.ClientURI:
-		_, err = cli.Call("call_code", map[string]interface{}{
-			"fromAddress": fromAddress,
-			"code":        code,
-			"data":        data,
-		}, &res)
-
-	}
+func CallCode(client rpcclient.Client, fromAddress, code,
+	data []byte) (*rpc_types.ResultCall, error) {
+	res, err := performCall(client, "call_code",
+		"fromAddress", fromAddress,
+		"code", code,
+		"data", data)
 	if err != nil {
 		return nil, err
 	}
@@ -159,19 +96,10 @@ func CallCode(client rpcclient.Client,
 
 func Call(client rpcclient.Client, fromAddress, toAddress,
 	data []byte) (*rpc_types.ResultCall, error) {
-	var res rpc_types.ErisDBResult
-	var err error
-	switch cli := client.(type) {
-	case *rpcclient.ClientJSONRPC:
-		_, err = cli.Call("call", []interface{}{fromAddress, toAddress, data}, &res)
-	case *rpcclient.ClientURI:
-		_, err = cli.Call("call", map[string]interface{}{
-			"fromAddress": fromAddress,
-			"toAddress":   toAddress,
-			"data":        data,
-		}, &res)
-
-	}
+	res, err := performCall(client, "call",
+		"fromAddress", fromAddress,
+		"toAddress", toAddress,
+		"data", data)
 	if err != nil {
 		return nil, err
 	}
@@ -179,16 +107,62 @@ func Call(client rpcclient.Client, fromAddress, toAddress,
 }
 
 func GetName(client rpcclient.Client, name string) (*core_types.NameRegEntry, error) {
-	var res rpc_types.ErisDBResult
-	var err error
-	switch cli := client.(type) {
-	case *rpcclient.ClientJSONRPC:
-		_, err = cli.Call("get_name", []interface{}{name}, &res)
-	case *rpcclient.ClientURI:
-		_, err = cli.Call("get_name", map[string]interface{}{"name": name}, &res)
-	}
+	res, err := performCall(client, "get_name",
+		"name", name)
 	if err != nil {
 		return nil, err
 	}
 	return res.(*rpc_types.ResultGetName).Entry, nil
 }
+
+func BlockchainInfo(client rpcclient.Client, minHeight,
+	maxHeight int) (*rpc_types.ResultBlockchainInfo, error) {
+	res, err := performCall(client, "blockchain",
+		"minHeight", minHeight,
+		"maxHeight", maxHeight)
+	if err != nil {
+		return nil, err
+	}
+	return res.(*rpc_types.ResultBlockchainInfo), err
+}
+
+func performCall(client rpcclient.Client, method string,
+	paramKeyVals ...interface{}) (res rpc_types.ErisDBResult, err error) {
+	paramsMap, paramsSlice, err := mapAndValues(paramKeyVals...)
+	if err != nil {
+		return
+	}
+	switch cli := client.(type) {
+	case *rpcclient.ClientJSONRPC:
+		_, err = cli.Call(method, paramsSlice, &res)
+	case *rpcclient.ClientURI:
+		_, err = cli.Call(method, paramsMap, &res)
+	}
+	return
+
+}
+func mapAndValues(orderedKeyVals ...interface{}) (map[string]interface{},
+	[]interface{}, error) {
+	if len(orderedKeyVals)%2 != 0 {
+		return nil, nil, fmt.Errorf("mapAndValues requires a even length list of"+
+			" keys and values but got: %v (length %v)",
+			orderedKeyVals, len(orderedKeyVals))
+	}
+	paramsMap := make(map[string]interface{})
+	paramsSlice := make([]interface{}, len(orderedKeyVals)/2)
+	for i := 0; i < len(orderedKeyVals); i += 2 {
+		key, ok := orderedKeyVals[i].(string)
+		if !ok {
+			return nil, nil, errors.New("mapAndValues requires every even element" +
+				" of orderedKeyVals to be a string key")
+		}
+		val := orderedKeyVals[i+1]
+		paramsMap[key] = val
+		paramsSlice = append(paramsSlice, val)
+	}
+	return paramsMap, paramsSlice, nil
+}
+
+type wrappedTx struct {
+	txs.Tx `json:"unwrap"`
+}
diff --git a/rpc/tendermint/test/client_ws_test.go b/rpc/tendermint/test/client_ws_test.go
index 69153da425e711d7ef9ab9ab67b1af01b9db777c..2f55ebf9ccb803378d319b2b268816c71df26c8a 100644
--- a/rpc/tendermint/test/client_ws_test.go
+++ b/rpc/tendermint/test/client_ws_test.go
@@ -5,6 +5,7 @@ import (
 	"testing"
 
 	"github.com/eris-ltd/eris-db/txs"
+	"github.com/stretchr/testify/assert"
 	_ "github.com/tendermint/tendermint/config/tendermint_test"
 )
 
@@ -28,10 +29,10 @@ func TestWSNewBlock(t *testing.T) {
 		unsubscribe(t, wsc, eid)
 		wsc.Stop()
 	}()
-	waitForEvent(t, wsc, eid, true, func() {},
-		func(eid string, eventData txs.EventData) error {
+	waitForEvent(t, wsc, eid, func() {},
+		func(eid string, eventData txs.EventData) (bool, error) {
 			fmt.Println("Check: ", eventData.(txs.EventDataNewBlock).Block)
-			return nil
+			return true, nil
 		})
 }
 
@@ -50,8 +51,8 @@ func TestWSBlockchainGrowth(t *testing.T) {
 	// listen for NewBlock, ensure height increases by 1
 	var initBlockN int
 	for i := 0; i < 2; i++ {
-		waitForEvent(t, wsc, eid, true, func() {},
-			func(eid string, eventData txs.EventData) error {
+		waitForEvent(t, wsc, eid, func() {},
+			func(eid string, eventData txs.EventData) (bool, error) {
 				eventDataNewBlock, ok := eventData.(txs.EventDataNewBlock)
 				if !ok {
 					t.Fatalf("Was expecting EventDataNewBlock but got %v", eventData)
@@ -61,11 +62,12 @@ func TestWSBlockchainGrowth(t *testing.T) {
 					initBlockN = block.Height
 				} else {
 					if block.Header.Height != initBlockN+i {
-						return fmt.Errorf("Expected block %d, got block %d", i, block.Header.Height)
+						return true, fmt.Errorf("Expected block %d, got block %d", i,
+							block.Header.Height)
 					}
 				}
 
-				return nil
+				return true, nil
 			})
 	}
 }
@@ -85,11 +87,13 @@ func TestWSSend(t *testing.T) {
 		unsubscribe(t, wsc, eidOutput)
 		wsc.Stop()
 	}()
-	waitForEvent(t, wsc, eidInput, true, func() {
+	waitForEvent(t, wsc, eidInput, func() {
 		tx := makeDefaultSendTxSigned(t, wsTyp, toAddr, amt)
 		broadcastTx(t, wsTyp, tx)
 	}, unmarshalValidateSend(amt, toAddr))
-	waitForEvent(t, wsc, eidOutput, true, func() {}, unmarshalValidateSend(amt, toAddr))
+
+	waitForEvent(t, wsc, eidOutput, func() {},
+		unmarshalValidateSend(amt, toAddr))
 }
 
 // ensure events are only fired once for a given transaction
@@ -107,17 +111,20 @@ func TestWSDoubleFire(t *testing.T) {
 	amt := int64(100)
 	toAddr := user[1].Address
 	// broadcast the transaction, wait to hear about it
-	waitForEvent(t, wsc, eid, true, func() {
+	waitForEvent(t, wsc, eid, func() {
 		tx := makeDefaultSendTxSigned(t, wsTyp, toAddr, amt)
 		broadcastTx(t, wsTyp, tx)
-	}, func(eid string, b txs.EventData) error {
-		return nil
+	}, func(eid string, b txs.EventData) (bool, error) {
+		return true, nil
 	})
 	// but make sure we don't hear about it twice
-	waitForEvent(t, wsc, eid, false, func() {
-	}, func(eid string, b txs.EventData) error {
-		return nil
-	})
+	err := waitForEvent(t, wsc, eid,
+		func() {},
+		func(eid string, b txs.EventData) (bool, error) {
+			return false, nil
+		})
+	assert.True(t, err.Timeout(), "We should have timed out waiting for second"+
+		" %v event", eid)
 }
 
 // create a contract, wait for the event, and send it a msg, validate the return
@@ -136,7 +143,7 @@ func TestWSCallWait(t *testing.T) {
 	code, returnCode, returnVal := simpleContract()
 	var contractAddr []byte
 	// wait for the contract to be created
-	waitForEvent(t, wsc, eid1, true, func() {
+	waitForEvent(t, wsc, eid1, func() {
 		tx := makeDefaultCallTx(t, wsTyp, nil, code, amt, gasLim, fee)
 		receipt := broadcastTx(t, wsTyp, tx)
 		contractAddr = receipt.ContractAddr
@@ -151,7 +158,7 @@ func TestWSCallWait(t *testing.T) {
 	}()
 	// get the return value from a call
 	data := []byte{0x1}
-	waitForEvent(t, wsc, eid2, true, func() {
+	waitForEvent(t, wsc, eid2, func() {
 		tx := makeDefaultCallTx(t, wsTyp, contractAddr, data, amt, gasLim, fee)
 		receipt := broadcastTx(t, wsTyp, tx)
 		contractAddr = receipt.ContractAddr
@@ -182,7 +189,7 @@ func TestWSCallNoWait(t *testing.T) {
 	}()
 	// get the return value from a call
 	data := []byte{0x1}
-	waitForEvent(t, wsc, eid, true, func() {
+	waitForEvent(t, wsc, eid, func() {
 		tx := makeDefaultCallTx(t, wsTyp, contractAddr, data, amt, gasLim, fee)
 		broadcastTx(t, wsTyp, tx)
 	}, unmarshalValidateTx(amt, returnVal))
@@ -219,12 +226,12 @@ func TestWSCallCall(t *testing.T) {
 	// call contract2, which should call contract1, and wait for ev1
 
 	// let the contract get created first
-	waitForEvent(t, wsc, eid1, true, func() {
-	}, func(eid string, b txs.EventData) error {
-		return nil
+	waitForEvent(t, wsc, eid1, func() {
+	}, func(eid string, b txs.EventData) (bool, error) {
+		return true, nil
 	})
 	// call it
-	waitForEvent(t, wsc, eid1, true, func() {
+	waitForEvent(t, wsc, eid1, func() {
 		tx := makeDefaultCallTx(t, wsTyp, contractAddr2, nil, amt, gasLim, fee)
 		broadcastTx(t, wsTyp, tx)
 		*txid = txs.TxHash(chainID, tx)
diff --git a/rpc/tendermint/test/tests.go b/rpc/tendermint/test/tests.go
index 832534e9b0ec12f97f26470fa85f7900fadf5f78..f1eac5cba98557aeca1ad8964952e95089c48c83 100644
--- a/rpc/tendermint/test/tests.go
+++ b/rpc/tendermint/test/tests.go
@@ -8,14 +8,11 @@ import (
 	edbcli "github.com/eris-ltd/eris-db/rpc/tendermint/client"
 	"github.com/eris-ltd/eris-db/txs"
 
+	"github.com/stretchr/testify/assert"
 	tm_common "github.com/tendermint/go-common"
 	"golang.org/x/crypto/ripemd160"
 )
 
-func doNothing(eventId string, eventData txs.EventData) error {
-	return nil
-}
-
 func testStatus(t *testing.T, typ string) {
 	client := clients[typ]
 	resp, err := edbcli.Status(client)
@@ -105,7 +102,7 @@ func testGetStorage(t *testing.T, typ string) {
 	}
 
 	// allow it to get mined
-	waitForEvent(t, wsc, eid, true, func() {}, doNothing)
+	waitForEvent(t, wsc, eid, func() {}, doNothing)
 	mempoolCount = 0
 
 	v := getStorage(t, typ, contractAddr, []byte{0x1})
@@ -165,7 +162,7 @@ func testCall(t *testing.T, typ string) {
 	}
 
 	// allow it to get mined
-	waitForEvent(t, wsc, eid, true, func() {}, doNothing)
+	waitForEvent(t, wsc, eid, func() {}, doNothing)
 	mempoolCount = 0
 
 	// run a call through the contract
@@ -175,7 +172,6 @@ func testCall(t *testing.T, typ string) {
 }
 
 func testNameReg(t *testing.T, typ string) {
-	client := clients[typ]
 	wsc := newWSClient(t)
 
 	txs.MinNameRegistrationPeriod = 1
@@ -183,86 +179,79 @@ func testNameReg(t *testing.T, typ string) {
 	// register a new name, check if its there
 	// since entries ought to be unique and these run against different clients, we append the typ
 	name := "ye_old_domain_name_" + typ
-	data := "if not now, when"
+	const data = "if not now, when"
 	fee := int64(1000)
 	numDesiredBlocks := int64(2)
 	amt := fee + numDesiredBlocks*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*txs.NameBaseCost(name, data)
 
-	eid := txs.EventStringNameReg(name)
-	subscribe(t, wsc, eid)
-
 	tx := makeDefaultNameTx(t, typ, name, data, amt, fee)
-	broadcastTx(t, typ, tx)
 	// verify the name by both using the event and by checking get_name
-	waitForEvent(t, wsc, eid, true, func() {}, func(eid string, b txs.EventData) error {	// TODO: unmarshal thtxs.EventData		_ = b // TODO
-		tx, err := unmarshalResponseNameReg([]byte{})
-		if err != nil {
-			return err
-		}
-		if tx.Name != name {
-			t.Fatal(fmt.Sprintf("Err on received event tx.Name: Got %s, expected %s", tx.Name, name))
-		}
-		if tx.Data != data {
-			t.Fatal(fmt.Sprintf("Err on received event tx.Data: Got %s, expected %s", tx.Data, data))
-		}
-		return nil
-	})
+	subscribeAndWaitForNext(t, wsc, txs.EventStringNameReg(name),
+		func() {
+			broadcastTxAndWaitForBlock(t, typ, wsc, tx)
+		},
+		func(eid string, eventData txs.EventData) (bool, error) {
+			eventDataTx := asEventDataTx(t, eventData)
+			tx, ok := eventDataTx.Tx.(*txs.NameTx)
+			if !ok {
+				t.Fatalf("Could not convert %v to *NameTx", eventDataTx)
+			}
+			assert.Equal(t, name, tx.Name)
+			assert.Equal(t, data, tx.Data)
+			return true, nil
+		})
 	mempoolCount = 0
-	entry := getNameRegEntry(t, typ, name)
-	if entry.Data != data {
-		t.Fatal(fmt.Sprintf("Err on entry.Data: Got %s, expected %s", entry.Data, data))
-	}
-	if bytes.Compare(entry.Owner, user[0].Address) != 0 {
-		t.Fatal(fmt.Sprintf("Err on entry.Owner: Got %s, expected %s", entry.Owner, user[0].Address))
-	}
-
-	unsubscribe(t, wsc, eid)
 
-	// for the rest we just use new block event
-	// since we already tested the namereg event
-	eid = txs.EventStringNewBlock()
-	subscribe(t, wsc, eid)
-	defer func() {
-		unsubscribe(t, wsc, eid)
-		wsc.Stop()
-	}()
+	entry := getNameRegEntry(t, typ, name)
+	assert.Equal(t, data, entry.Data)
+	assert.Equal(t, user[0].Address, entry.Owner)
 
 	// update the data as the owner, make sure still there
-	numDesiredBlocks = int64(2)
-	data = "these are amongst the things I wish to bestow upon the youth of generations come: a safe supply of honey, and a better money. For what else shall they need"
-	amt = fee + numDesiredBlocks*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*txs.NameBaseCost(name, data)
-	tx = makeDefaultNameTx(t, typ, name, data, amt, fee)
-	broadcastTx(t, typ, tx)
-	// commit block
-	waitForEvent(t, wsc, eid, true, func() {}, doNothing)
+	numDesiredBlocks = int64(4)
+	const updatedData = "these are amongst the things I wish to bestow upon the youth of generations come: a safe supply of honey, and a better money. For what else shall they need"
+	amt = fee + numDesiredBlocks*txs.NameByteCostMultiplier*txs.NameBlockCostMultiplier*txs.NameBaseCost(name, updatedData)
+	tx = makeDefaultNameTx(t, typ, name, updatedData, amt, fee)
+	broadcastTxAndWaitForBlock(t, typ, wsc, tx)
 	mempoolCount = 0
 	entry = getNameRegEntry(t, typ, name)
-	if entry.Data != data {
-		t.Fatal(fmt.Sprintf("Err on entry.Data: Got %s, expected %s", entry.Data, data))
-	}
+
+	assert.Equal(t, updatedData, entry.Data)
 
 	// try to update as non owner, should fail
-	nonce := getNonce(t, typ, user[1].Address)
-	data2 := "this is not my beautiful house"
-	tx = txs.NewNameTxWithNonce(user[1].PubKey, name, data2, amt, fee, nonce+1)
+	//waitBlocks(t, wsc, 4)
+	tx = txs.NewNameTxWithNonce(user[1].PubKey, name, "never mind", amt, fee,
+		getNonce(t, typ, user[1].Address)+1)
 	tx.Sign(chainID, user[1])
-	_, err := edbcli.BroadcastTx(client, tx)
-	if err == nil {
-		t.Fatal("Expected error on NameTx")
-	}
 
-	// commit block
-	waitForEvent(t, wsc, eid, true, func() {}, doNothing)
+	_, err := broadcastTxAndWaitForBlock(t, typ, wsc, tx)
 
-	// now the entry should be expired, so we can update as non owner
-	_, err = edbcli.BroadcastTx(client, tx)
-	waitForEvent(t, wsc, eid, true, func() {}, doNothing)
+	assert.Error(t, err, "Expected error when updating someone else's unexpired"+
+		" name registry entry")
+	//now the entry should be expired, so we can update as non owner
+	const data2 = "this is not my beautiful house"
+	tx = txs.NewNameTxWithNonce(user[1].PubKey, name, data2, amt, fee,
+		getNonce(t, typ, user[1].Address)+1)
+	tx.Sign(chainID, user[1])
+	_, err = broadcastTxAndWaitForBlock(t, typ, wsc, tx)
+	assert.NoError(t, err, "Should be able to update a previously expired name"+
+		" registry entry as a different address")
 	mempoolCount = 0
 	entry = getNameRegEntry(t, typ, name)
-	if entry.Data != data2 {
-		t.Fatal(fmt.Sprintf("Error on entry.Data: Got %s, expected %s", entry.Data, data2))
-	}
-	if bytes.Compare(entry.Owner, user[1].Address) != 0 {
-		t.Fatal(fmt.Sprintf("Err on entry.Owner: Got %s, expected %s", entry.Owner, user[1].Address))
+	assert.Equal(t, data2, entry.Data)
+	assert.Equal(t, user[1].Address, entry.Owner)
+}
+
+// ------ Test Utils -------
+
+func asEventDataTx(t *testing.T, eventData txs.EventData) txs.EventDataTx {
+	eventDataTx, ok := eventData.(txs.EventDataTx)
+	if !ok {
+		t.Fatalf("Expected eventData to be EventDataTx was %v", eventData)
 	}
+	return eventDataTx
+}
+
+func doNothing(eventId string, eventData txs.EventData) (bool, error) {
+	// And ask waitForEvent to stop waiting
+	return true, nil
 }
diff --git a/rpc/tendermint/test/ws_helpers.go b/rpc/tendermint/test/ws_helpers.go
index 76c624109634c60669930b0d450829131e5bbfff..bd694259e390b1e011284176ec21a9a8594330a6 100644
--- a/rpc/tendermint/test/ws_helpers.go
+++ b/rpc/tendermint/test/ws_helpers.go
@@ -10,7 +10,9 @@ import (
 	ctypes "github.com/eris-ltd/eris-db/rpc/tendermint/core/types"
 	"github.com/eris-ltd/eris-db/txs"
 	"github.com/tendermint/tendermint/types"
+	tm_types "github.com/tendermint/tendermint/types"
 
+	edbcli "github.com/eris-ltd/eris-db/rpc/tendermint/client"
 	"github.com/tendermint/go-events"
 	client "github.com/tendermint/go-rpc/client"
 	rpctypes "github.com/tendermint/go-rpc/types"
@@ -47,14 +49,77 @@ func unsubscribe(t *testing.T, wsc *client.WSClient, eventid string) {
 	}
 }
 
-// wait for an event; do things that might trigger events, and check them when they are received
-// the check function takes an event id and the byte slice read off the ws
+// broadcast transaction and wait for new block
+func broadcastTxAndWaitForBlock(t *testing.T, typ string, wsc *client.WSClient,
+	tx txs.Tx) (txs.Receipt, error) {
+	var rec txs.Receipt
+	var err error
+	initialHeight := -1
+	runThenWaitForBlock(t, wsc,
+		func(block *tm_types.Block) bool {
+			if initialHeight < 0 {
+				initialHeight = block.Height
+				return false
+			} else {
+				return block.Height > initialHeight
+			}
+		},
+		func() {
+			rec, err = edbcli.BroadcastTx(clients[typ], tx)
+			mempoolCount += 1
+		})
+	return rec, err
+}
+
+func waitNBlocks(t *testing.T, wsc *client.WSClient, n int) {
+	i := 0
+	runThenWaitForBlock(t, wsc,
+		func(block *tm_types.Block) bool {
+			i++
+			return i <= n
+		},
+		func() {})
+}
+
+func runThenWaitForBlock(t *testing.T, wsc *client.WSClient,
+	blockPredicate func(*tm_types.Block) bool, runner func()) {
+	subscribeAndWaitForNext(t, wsc, txs.EventStringNewBlock(),
+		runner,
+		func(event string, eventData txs.EventData) (bool, error) {
+			return blockPredicate(eventData.(txs.EventDataNewBlock).Block), nil
+		})
+}
+
+func subscribeAndWaitForNext(t *testing.T, wsc *client.WSClient, event string,
+	runner func(),
+	eventDataChecker func(string, txs.EventData) (bool, error)) {
+	subscribe(t, wsc, event)
+	waitForEvent(t,
+		wsc,
+		event,
+		runner,
+		eventDataChecker)
+	unsubscribe(t, wsc, event)
+}
+
+// waitForEvent executes runner that is expected to trigger events. It then
+// waits for any events on the supplies WSClient and checks the eventData with
+// the eventDataChecker which is a function that is passed the event name
+// and the EventData and returns the pair of stopWaiting, err. Where if
+// stopWaiting is true waitForEvent will return or if stopWaiting is false
+// waitForEvent will keep listening for new events. If an error is returned
+// waitForEvent will fail the test.
 func waitForEvent(t *testing.T, wsc *client.WSClient, eventid string,
-	dieOnTimeout bool, f func(), check func(string, txs.EventData) error) {
-	// go routine to wait for webscoket msg
+	runner func(),
+	eventDataChecker func(string, txs.EventData) (bool, error)) waitForEventError {
+
+	// go routine to wait for websocket msg
 	goodCh := make(chan txs.EventData)
 	errCh := make(chan error)
 
+	// do stuff (transactions)
+	runner()
+
 	// Read message
 	go func() {
 		var err error
@@ -82,37 +147,40 @@ func waitForEvent(t *testing.T, wsc *client.WSClient, eventid string,
 		}
 	}()
 
-	// do stuff (transactions)
-	f()
-
 	// wait for an event or timeout
 	timeout := time.NewTimer(timeoutSeconds * time.Second)
-	select {
-	case <-timeout.C:
-		if dieOnTimeout {
-			wsc.Stop()
-			t.Fatalf("%s event was not received in time", eventid)
-		}
-		// else that's great, we didn't hear the event
-		// and we shouldn't have
-	case eventData := <-goodCh:
-		if dieOnTimeout {
-			// message was received and expected
+	for {
+		select {
+		case <-timeout.C:
+			return waitForEventError{timeout: true}
+		case eventData := <-goodCh:
 			// run the check
-			if err := check(eventid, eventData); err != nil {
+			stopWaiting, err := eventDataChecker(eventid, eventData)
+			if err != nil {
 				t.Fatal(err) // Show the stack trace.
 			}
-		} else {
-			wsc.Stop()
-			t.Fatalf("%s event was not expected", eventid)
+			if stopWaiting {
+				return waitForEventError{}
+			}
+		case err := <-errCh:
+			t.Fatal(err)
 		}
-	case err := <-errCh:
-		t.Fatal(err)
-		panic(err) // Show the stack trace.
-
 	}
 }
 
+type waitForEventError struct {
+	error
+	timeout bool
+}
+
+func (err waitForEventError) Timeout() bool {
+	return err.timeout
+}
+
+func acceptFirstBlock(_ *tm_types.Block) bool {
+	return true
+}
+
 //--------------------------------------------------------------------------------
 
 func unmarshalResponseNewBlock(b []byte) (*types.Block, error) {
@@ -148,68 +216,71 @@ func unmarshalResponseNameReg(b []byte) (*txs.NameTx, error) {
 	return tx, nil
 }
 
-func unmarshalValidateSend(amt int64, toAddr []byte) func(string, txs.EventData) error {
-	return func(eid string, eventData txs.EventData) error {
+func unmarshalValidateSend(amt int64,
+	toAddr []byte) func(string, txs.EventData) (bool, error) {
+	return func(eid string, eventData txs.EventData) (bool, error) {
 		var data = eventData.(txs.EventDataTx)
 		if data.Exception != "" {
-			return fmt.Errorf(data.Exception)
+			return true, fmt.Errorf(data.Exception)
 		}
 		tx := data.Tx.(*txs.SendTx)
 		if !bytes.Equal(tx.Inputs[0].Address, user[0].Address) {
-			return fmt.Errorf("Senders do not match up! Got %x, expected %x", tx.Inputs[0].Address, user[0].Address)
+			return true, fmt.Errorf("Senders do not match up! Got %x, expected %x", tx.Inputs[0].Address, user[0].Address)
 		}
 		if tx.Inputs[0].Amount != amt {
-			return fmt.Errorf("Amt does not match up! Got %d, expected %d", tx.Inputs[0].Amount, amt)
+			return true, fmt.Errorf("Amt does not match up! Got %d, expected %d", tx.Inputs[0].Amount, amt)
 		}
 		if !bytes.Equal(tx.Outputs[0].Address, toAddr) {
-			return fmt.Errorf("Receivers do not match up! Got %x, expected %x", tx.Outputs[0].Address, user[0].Address)
+			return true, fmt.Errorf("Receivers do not match up! Got %x, expected %x", tx.Outputs[0].Address, user[0].Address)
 		}
-		return nil
+		return true, nil
 	}
 }
 
-func unmarshalValidateTx(amt int64, returnCode []byte) func(string, txs.EventData) error {
-	return func(eid string, eventData txs.EventData) error {
+func unmarshalValidateTx(amt int64,
+	returnCode []byte) func(string, txs.EventData) (bool, error) {
+	return func(eid string, eventData txs.EventData) (bool, error) {
 		var data = eventData.(txs.EventDataTx)
 		if data.Exception != "" {
-			return fmt.Errorf(data.Exception)
+			return true, fmt.Errorf(data.Exception)
 		}
 		tx := data.Tx.(*txs.CallTx)
 		if !bytes.Equal(tx.Input.Address, user[0].Address) {
-			return fmt.Errorf("Senders do not match up! Got %x, expected %x",
+			return true, fmt.Errorf("Senders do not match up! Got %x, expected %x",
 				tx.Input.Address, user[0].Address)
 		}
 		if tx.Input.Amount != amt {
-			return fmt.Errorf("Amt does not match up! Got %d, expected %d",
+			return true, fmt.Errorf("Amt does not match up! Got %d, expected %d",
 				tx.Input.Amount, amt)
 		}
 		ret := data.Return
 		if !bytes.Equal(ret, returnCode) {
-			return fmt.Errorf("Tx did not return correctly. Got %x, expected %x", ret, returnCode)
+			return true, fmt.Errorf("Tx did not return correctly. Got %x, expected %x", ret, returnCode)
 		}
-		return nil
+		return true, nil
 	}
 }
 
-func unmarshalValidateCall(origin, returnCode []byte, txid *[]byte) func(string, txs.EventData) error {
-	return func(eid string, eventData txs.EventData) error {
+func unmarshalValidateCall(origin,
+	returnCode []byte, txid *[]byte) func(string, txs.EventData) (bool, error) {
+	return func(eid string, eventData txs.EventData) (bool, error) {
 		var data = eventData.(txs.EventDataCall)
 		if data.Exception != "" {
-			return fmt.Errorf(data.Exception)
+			return true, fmt.Errorf(data.Exception)
 		}
 		if !bytes.Equal(data.Origin, origin) {
-			return fmt.Errorf("Origin does not match up! Got %x, expected %x",
+			return true, fmt.Errorf("Origin does not match up! Got %x, expected %x",
 				data.Origin, origin)
 		}
 		ret := data.Return
 		if !bytes.Equal(ret, returnCode) {
-			return fmt.Errorf("Call did not return correctly. Got %x, expected %x", ret, returnCode)
+			return true, fmt.Errorf("Call did not return correctly. Got %x, expected %x", ret, returnCode)
 		}
 		if !bytes.Equal(data.TxID, *txid) {
-			return fmt.Errorf("TxIDs do not match up! Got %x, expected %x",
+			return true, fmt.Errorf("TxIDs do not match up! Got %x, expected %x",
 				data.TxID, *txid)
 		}
-		return nil
+		return true, nil
 	}
 }