diff --git a/indexedDb/implementation.go b/indexedDb/channels/implementation.go
similarity index 71%
rename from indexedDb/implementation.go
rename to indexedDb/channels/implementation.go
index 1b9daca0c5ef11d754eeb8b170278d00fdbbae3a..07718dbe825a7023bc266f5d572e8b34f4e75311 100644
--- a/indexedDb/implementation.go
+++ b/indexedDb/channels/implementation.go
@@ -7,13 +7,13 @@
 
 //go:build js && wasm
 
-package indexedDb
+package channels
 
 import (
-	"context"
 	"crypto/ed25519"
 	"encoding/base64"
 	"encoding/json"
+	"gitlab.com/elixxir/xxdk-wasm/indexedDb"
 	"sync"
 	"syscall/js"
 	"time"
@@ -30,10 +30,6 @@ import (
 	"gitlab.com/xx_network/primitives/id"
 )
 
-// dbTimeout is the global timeout for operations with the storage
-// [context.Context].
-const dbTimeout = time.Second
-
 // wasmModel implements [channels.EventModel] interface, which uses the channels
 // system passed an object that adheres to in order to get events on the
 // channel.
@@ -44,11 +40,6 @@ type wasmModel struct {
 	updateMux         sync.Mutex
 }
 
-// newContext builds a context for database operations.
-func newContext() (context.Context, context.CancelFunc) {
-	return context.WithTimeout(context.Background(), dbTimeout)
-}
-
 // JoinChannel is called whenever a channel is joined locally.
 func (w *wasmModel) JoinChannel(channel *cryptoBroadcast.Channel) {
 	parentErr := errors.New("failed to JoinChannel")
@@ -74,38 +65,11 @@ func (w *wasmModel) JoinChannel(channel *cryptoBroadcast.Channel) {
 		return
 	}
 
-	// Prepare the Transaction
-	txn, err := w.db.Transaction(idb.TransactionReadWrite, channelsStoreName)
-	if err != nil {
-		jww.ERROR.Printf("%+v", errors.WithMessagef(parentErr,
-			"Unable to create Transaction: %+v", err))
-		return
-	}
-	store, err := txn.ObjectStore(channelsStoreName)
+	_, err = indexedDb.Put(w.db, channelsStoreName, channelObj)
 	if err != nil {
 		jww.ERROR.Printf("%+v", errors.WithMessagef(parentErr,
-			"Unable to get ObjectStore: %+v", err))
-		return
-	}
-
-	// Perform the operation
-	_, err = store.Put(channelObj)
-	if err != nil {
-		jww.ERROR.Printf("%+v", errors.WithMessagef(parentErr,
-			"Unable to Add Channel: %+v", err))
-		return
-	}
-
-	// Wait for the operation to return
-	ctx, cancel := newContext()
-	err = txn.Await(ctx)
-	cancel()
-	if err != nil {
-		jww.ERROR.Printf("%+v", errors.WithMessagef(parentErr,
-			"Adding Channel failed: %+v", err))
-		return
+			"Unable to put Channel: %+v", err))
 	}
-	jww.DEBUG.Printf("Successfully added channel: %s", channel.ReceptionID)
 }
 
 // LeaveChannel is called whenever a channel is left locally.
@@ -135,7 +99,7 @@ func (w *wasmModel) LeaveChannel(channelID *id.ID) {
 	}
 
 	// Wait for the operation to return
-	ctx, cancel := newContext()
+	ctx, cancel := indexedDb.NewContext()
 	err = txn.Await(ctx)
 	cancel()
 	if err != nil {
@@ -183,7 +147,7 @@ func (w *wasmModel) deleteMsgByChannel(channelID *id.ID) error {
 	if err != nil {
 		return errors.WithMessagef(parentErr, "Unable to open Cursor: %+v", err)
 	}
-	ctx, cancel := newContext()
+	ctx, cancel := indexedDb.NewContext()
 	err = cursorRequest.Iter(ctx,
 		func(cursor *idb.CursorWithValue) error {
 			_, err := cursor.Delete()
@@ -363,7 +327,7 @@ func (w *wasmModel) UpdateFromUUID(uuid uint64,
 	key := js.ValueOf(uuid)
 
 	// Use the key to get the existing Message
-	currentMsg, err := w.get(messageStoreName, key)
+	currentMsg, err := indexedDb.Get(w.db, messageStoreName, key)
 	if err != nil {
 		jww.ERROR.Printf("%+v", errors.WithMessagef(parentErr,
 			"Failed to get message: %+v", err))
@@ -473,33 +437,14 @@ func (w *wasmModel) receiveHelper(newMessage *Message, isUpdate bool) (uint64,
 		messageObj.Delete("id")
 	}
 
-	// Prepare the Transaction
-	txn, err := w.db.Transaction(idb.TransactionReadWrite, messageStoreName)
-	if err != nil {
-		return 0, errors.Errorf("Unable to create Transaction: %+v",
-			err)
-	}
-	store, err := txn.ObjectStore(messageStoreName)
-	if err != nil {
-		return 0, errors.Errorf("Unable to get ObjectStore: %+v", err)
-	}
-
-	// Perform the upsert (put) operation
-	addReq, err := store.Put(messageObj)
-	if err != nil {
-		return 0, errors.Errorf("Unable to upsert Message: %+v", err)
-	}
-
-	// Wait for the operation to return
-	ctx, cancel := newContext()
-	err = txn.Await(ctx)
-	cancel()
+	// Store message to database
+	addReq, err := indexedDb.Put(w.db, messageStoreName, messageObj)
 	if err != nil {
-		return 0, errors.Errorf("Upserting Message failed: %+v", err)
+		return 0, errors.Errorf("Unable to put Message: %+v", err)
 	}
 	res, err := addReq.Result()
 	if err != nil {
-		return 0, errors.Errorf("Getting result from request failed: %+v", err)
+		return 0, errors.Errorf("Unable to get Message result: %+v", err)
 	}
 
 	// NOTE: Sometimes the insert fails to return an error but hits a duplicate
@@ -561,151 +506,20 @@ func (w *wasmModel) GetMessage(messageID cryptoChannel.MessageID) (channels.Mode
 	}, nil
 }
 
-// get is a generic private helper for getting values from the given
-// [idb.ObjectStore].
-func (w *wasmModel) get(objectStoreName string, key js.Value) (string, error) {
-	parentErr := errors.Errorf("failed to get %s/%s", objectStoreName, key)
-
-	// Prepare the Transaction
-	txn, err := w.db.Transaction(idb.TransactionReadOnly, objectStoreName)
-	if err != nil {
-		return "", errors.WithMessagef(parentErr,
-			"Unable to create Transaction: %+v", err)
-	}
-	store, err := txn.ObjectStore(objectStoreName)
-	if err != nil {
-		return "", errors.WithMessagef(parentErr,
-			"Unable to get ObjectStore: %+v", err)
-	}
-
-	// Perform the operation
-	getRequest, err := store.Get(key)
-	if err != nil {
-		return "", errors.WithMessagef(parentErr,
-			"Unable to Get from ObjectStore: %+v", err)
-	}
 
-	// Wait for the operation to return
-	ctx, cancel := newContext()
-	resultObj, err := getRequest.Await(ctx)
-	cancel()
-	if err != nil {
-		return "", errors.WithMessagef(parentErr,
-			"Unable to get from ObjectStore: %+v", err)
-	}
-
-	// Process result into string
-	resultStr := utils.JsToJson(resultObj)
-	jww.DEBUG.Printf("Got from %s/%s: %s", objectStoreName, key, resultStr)
-	return resultStr, nil
-}
-
-// getIndex is a generic private helper for getting values from the given
-// [idb.ObjectStore] using a [idb.Index].
-func (w *wasmModel) getIndex(objectStoreName string,
-	indexName string, key js.Value) (js.Value, error) {
-
-	parentErr := errors.Errorf("failed to getIndex %s/%s/%s",
-		objectStoreName, indexName, key)
-
-	// Prepare the Transaction
-	txn, err := w.db.Transaction(idb.TransactionReadOnly, objectStoreName)
-	if err != nil {
-		return js.Null(), errors.WithMessagef(parentErr,
-			"Unable to create Transaction: %+v", err)
-	}
-	store, err := txn.ObjectStore(objectStoreName)
-	if err != nil {
-		return js.Null(), errors.WithMessagef(parentErr,
-			"Unable to get ObjectStore: %+v", err)
-	}
-	idx, err := store.Index(indexName)
-	if err != nil {
-		return js.Null(), errors.WithMessagef(parentErr,
-			"Unable to get index: %+v", err)
-	}
-
-	// Perform the operation
-	getRequest, err := idx.Get(key)
-	if err != nil {
-		return js.Null(), errors.WithMessagef(parentErr,
-			"Unable to Get from ObjectStore: %+v", err)
-	}
-
-	// Wait for the operation to return
-	ctx, cancel := newContext()
-	resultObj, err := getRequest.Await(ctx)
-	cancel()
-	if err != nil {
-		return js.Null(), errors.WithMessagef(parentErr,
-			"Unable to get from ObjectStore: %+v", err)
-	}
-
-	jww.DEBUG.Printf("Got via index from %s/%s/%s: %s",
-		objectStoreName, indexName, key, resultObj.String())
-	return resultObj, nil
-}
-
-func (w *wasmModel) msgIDLookup(messageID cryptoChannel.MessageID) (*Message,
+// msgIDLookup gets the UUID of the Message with the given messageID.
+func (w *wasmModel) msgIDLookup(messageID cryptoChannel.MessageID) (uint64,
 	error) {
-	msgIDStr := base64.StdEncoding.EncodeToString(messageID.Marshal())
-	keyObj, err := w.getIndex(messageStoreName,
-		messageStoreMessageIndex, js.ValueOf(msgIDStr))
+	msgIDStr := js.ValueOf(base64.StdEncoding.EncodeToString(messageID.Bytes()))
+	resultObj, err := indexedDb.GetIndex(w.db, messageStoreName,
+		messageStoreMessageIndex, msgIDStr)
 	if err != nil {
-		return nil, err
-	} else if keyObj.IsUndefined() {
-		return nil, errors.Errorf("no message for %s found", msgIDStr)
+		return 0, err
 	}
 
-	// Process result into string
-	resultMsg := &Message{}
-	err = json.Unmarshal([]byte(utils.JsToJson(keyObj)), resultMsg)
-	if err != nil {
-		return nil, err
+	uuid := uint64(0)
+	if !resultObj.IsUndefined() {
+		uuid = uint64(resultObj.Get("id").Int())
 	}
 	return resultMsg, nil
 }
-
-// dump returns the given [idb.ObjectStore] contents to string slice for
-// debugging purposes.
-func (w *wasmModel) dump(objectStoreName string) ([]string, error) {
-	parentErr := errors.Errorf("failed to dump %s", objectStoreName)
-
-	txn, err := w.db.Transaction(idb.TransactionReadOnly, objectStoreName)
-	if err != nil {
-		return nil, errors.WithMessagef(parentErr,
-			"Unable to create Transaction: %+v", err)
-	}
-	store, err := txn.ObjectStore(objectStoreName)
-	if err != nil {
-		return nil, errors.WithMessagef(parentErr,
-			"Unable to get ObjectStore: %+v", err)
-	}
-	cursorRequest, err := store.OpenCursor(idb.CursorNext)
-	if err != nil {
-		return nil, errors.WithMessagef(parentErr,
-			"Unable to open Cursor: %+v", err)
-	}
-
-	// Run the query
-	jww.DEBUG.Printf("%s values:", objectStoreName)
-	results := make([]string, 0)
-	ctx, cancel := newContext()
-	err = cursorRequest.Iter(ctx,
-		func(cursor *idb.CursorWithValue) error {
-			value, err := cursor.Value()
-			if err != nil {
-				return err
-			}
-			valueStr := utils.JsToJson(value)
-			results = append(results, valueStr)
-			jww.DEBUG.Printf("- %v", valueStr)
-			return nil
-		})
-	cancel()
-	if err != nil {
-		return nil, errors.WithMessagef(parentErr,
-			"Unable to dump ObjectStore: %+v", err)
-	}
-	return results, nil
-}
diff --git a/indexedDb/implementation_test.go b/indexedDb/channels/implementation_test.go
similarity index 94%
rename from indexedDb/implementation_test.go
rename to indexedDb/channels/implementation_test.go
index 3223a5cf8a92a2059a8dc837b4bdb51c242bd9e0..1760cf31c4733013d385e388e1a99864dfdd9840 100644
--- a/indexedDb/implementation_test.go
+++ b/indexedDb/channels/implementation_test.go
@@ -7,12 +7,13 @@
 
 //go:build js && wasm
 
-package indexedDb
+package channels
 
 import (
 	"encoding/json"
 	"fmt"
 	"github.com/hack-pad/go-indexeddb/idb"
+	"gitlab.com/elixxir/xxdk-wasm/indexedDb"
 	"gitlab.com/elixxir/xxdk-wasm/storage"
 	"gitlab.com/xx_network/primitives/netTime"
 	"os"
@@ -54,7 +55,7 @@ func Test_wasmModel_UpdateSentStatus(t *testing.T) {
 	}
 
 	// Ensure one message is stored
-	results, err := eventModel.dump(messageStoreName)
+	results, err := indexedDb.Dump(eventModel.db, messageStoreName)
 	if err != nil {
 		t.Fatalf("%+v", err)
 	}
@@ -68,7 +69,7 @@ func Test_wasmModel_UpdateSentStatus(t *testing.T) {
 		nil, nil, nil, &expectedStatus)
 
 	// Check the resulting status
-	results, err = eventModel.dump(messageStoreName)
+	results, err = indexedDb.Dump(eventModel.db, messageStoreName)
 	if err != nil {
 		t.Fatalf("%+v", err)
 	}
@@ -112,7 +113,7 @@ func Test_wasmModel_JoinChannel_LeaveChannel(t *testing.T) {
 	}
 	eventModel.JoinChannel(testChannel)
 	eventModel.JoinChannel(testChannel2)
-	results, err := eventModel.dump(channelsStoreName)
+	results, err := indexedDb.Dump(eventModel.db, channelsStoreName)
 	if err != nil {
 		t.Fatalf("%+v", err)
 	}
@@ -120,7 +121,7 @@ func Test_wasmModel_JoinChannel_LeaveChannel(t *testing.T) {
 		t.Fatalf("Expected 2 channels to exist")
 	}
 	eventModel.LeaveChannel(testChannel.ReceptionID)
-	results, err = eventModel.dump(channelsStoreName)
+	results, err = indexedDb.Dump(eventModel.db, channelsStoreName)
 	if err != nil {
 		t.Fatalf("%+v", err)
 	}
@@ -151,8 +152,6 @@ func Test_wasmModel_UUIDTest(t *testing.T) {
 		uuids[i] = uuid
 	}
 
-	_, _ = eventModel.dump(messageStoreName)
-
 	for i := 0; i < 10; i++ {
 		for j := i + 1; j < 10; j++ {
 			if uuids[i] == uuids[j] {
@@ -186,8 +185,6 @@ func Test_wasmModel_DuplicateReceives(t *testing.T) {
 		uuids[i] = uuid
 	}
 
-	_, _ = eventModel.dump(messageStoreName)
-
 	for i := 0; i < 10; i++ {
 		for j := i + 1; j < 10; j++ {
 			if uuids[i] != uuids[j] {
@@ -230,7 +227,7 @@ func Test_wasmModel_deleteMsgByChannel(t *testing.T) {
 	}
 
 	// Check pre-results
-	result, err := eventModel.dump(messageStoreName)
+	result, err := indexedDb.Dump(eventModel.db, messageStoreName)
 	if err != nil {
 		t.Fatalf("%+v", err)
 	}
@@ -245,7 +242,7 @@ func Test_wasmModel_deleteMsgByChannel(t *testing.T) {
 	}
 
 	// Check final results
-	result, err = eventModel.dump(messageStoreName)
+	result, err = indexedDb.Dump(eventModel.db, messageStoreName)
 	if err != nil {
 		t.Fatalf("%+v", err)
 	}
@@ -298,7 +295,7 @@ func TestWasmModel_receiveHelper_UniqueIndex(t *testing.T) {
 	if err != nil {
 		t.Fatalf("%+v", err)
 	}
-	results, err := eventModel.dump(messageStoreName)
+	results, err := indexedDb.Dump(eventModel.db, messageStoreName)
 	if err != nil {
 		t.Fatalf("%+v", err)
 	}
@@ -327,7 +324,7 @@ func TestWasmModel_receiveHelper_UniqueIndex(t *testing.T) {
 
 	// The update to duplicate message ID won't fail,
 	// but it just silently shouldn't happen
-	results, err = eventModel.dump(messageStoreName)
+	results, err = indexedDb.Dump(eventModel.db, messageStoreName)
 	if err != nil {
 		t.Fatalf("%+v", err)
 	}
diff --git a/indexedDb/init.go b/indexedDb/channels/init.go
similarity index 97%
rename from indexedDb/init.go
rename to indexedDb/channels/init.go
index 543ae0aee22c79755143fdbc23f03b433ffca324..0b52434ff260ee3df42c8b0f201527f08377205b 100644
--- a/indexedDb/init.go
+++ b/indexedDb/channels/init.go
@@ -7,7 +7,7 @@
 
 //go:build js && wasm
 
-package indexedDb
+package channels
 
 import (
 	"github.com/hack-pad/go-indexeddb/idb"
@@ -15,6 +15,7 @@ import (
 	jww "github.com/spf13/jwalterweatherman"
 	"gitlab.com/elixxir/client/v4/channels"
 	cryptoChannel "gitlab.com/elixxir/crypto/channel"
+	"gitlab.com/elixxir/xxdk-wasm/indexedDb"
 	"gitlab.com/elixxir/xxdk-wasm/storage"
 	"gitlab.com/xx_network/primitives/id"
 	"syscall/js"
@@ -58,7 +59,7 @@ func NewWASMEventModel(path string, encryption cryptoChannel.Cipher,
 func newWASMModel(databaseName string, encryption cryptoChannel.Cipher,
 	cb MessageReceivedCallback) (*wasmModel, error) {
 	// Attempt to open database object
-	ctx, cancel := newContext()
+	ctx, cancel := indexedDb.NewContext()
 	defer cancel()
 	openRequest, err := idb.Global().Open(ctx, databaseName, currentVersion,
 		func(db *idb.Database, oldVersion, newVersion uint) error {
@@ -206,7 +207,7 @@ func (w *wasmModel) hackTestDb() error {
 	if helper != nil {
 		return helper
 	}
-	result, err := w.get(messageStoreName, js.ValueOf(msgId))
+	result, err := indexedDb.Get(w.db, messageStoreName, js.ValueOf(msgId))
 	if err != nil {
 		return err
 	}
diff --git a/indexedDb/model.go b/indexedDb/channels/model.go
similarity index 97%
rename from indexedDb/model.go
rename to indexedDb/channels/model.go
index c6e29184705b83cc4992b4801fce78b7a12fc4e4..02a3ebd42479a26cffa7e758c8d317a21a906099 100644
--- a/indexedDb/model.go
+++ b/indexedDb/channels/model.go
@@ -7,7 +7,7 @@
 
 //go:build js && wasm
 
-package indexedDb
+package channels
 
 import (
 	"time"
@@ -60,7 +60,7 @@ type Message struct {
 	Round           uint64        `json:"round"`
 
 	// User cryptographic Identity struct -- could be pulled out
-	Pubkey         []byte `json:"pubkey"` // Index
+	Pubkey         []byte `json:"pubkey"`
 	CodesetVersion uint8  `json:"codeset_version"`
 }
 
diff --git a/indexedDb/utils.go b/indexedDb/utils.go
new file mode 100644
index 0000000000000000000000000000000000000000..7d7e7e6b394eb492ea09519f5939f4fd5c79ca59
--- /dev/null
+++ b/indexedDb/utils.go
@@ -0,0 +1,226 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright © 2022 xx foundation                                             //
+//                                                                            //
+// Use of this source code is governed by a license that can be found in the  //
+// LICENSE file.                                                              //
+////////////////////////////////////////////////////////////////////////////////
+
+//go:build js && wasm
+
+// This file contains several generic IndexedDB helper functions that
+// may be useful for any IndexedDB implementations.
+
+package indexedDb
+
+import (
+	"context"
+	"github.com/hack-pad/go-indexeddb/idb"
+	"github.com/pkg/errors"
+	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/xxdk-wasm/utils"
+	"syscall/js"
+	"time"
+)
+
+// dbTimeout is the global timeout for operations with the storage
+// [context.Context].
+const dbTimeout = time.Second
+
+// NewContext builds a context for indexedDb operations.
+func NewContext() (context.Context, context.CancelFunc) {
+	return context.WithTimeout(context.Background(), dbTimeout)
+}
+
+// Get is a generic helper for getting values from the given [idb.ObjectStore].
+func Get(db *idb.Database, objectStoreName string, key js.Value) (string, error) {
+	parentErr := errors.Errorf("failed to Get %s/%s", objectStoreName, key)
+
+	// Prepare the Transaction
+	txn, err := db.Transaction(idb.TransactionReadOnly, objectStoreName)
+	if err != nil {
+		return "", errors.WithMessagef(parentErr,
+			"Unable to create Transaction: %+v", err)
+	}
+	store, err := txn.ObjectStore(objectStoreName)
+	if err != nil {
+		return "", errors.WithMessagef(parentErr,
+			"Unable to get ObjectStore: %+v", err)
+	}
+
+	// Perform the operation
+	getRequest, err := store.Get(key)
+	if err != nil {
+		return "", errors.WithMessagef(parentErr,
+			"Unable to Get from ObjectStore: %+v", err)
+	}
+
+	// Wait for the operation to return
+	ctx, cancel := NewContext()
+	resultObj, err := getRequest.Await(ctx)
+	cancel()
+	if err != nil {
+		return "", errors.WithMessagef(parentErr,
+			"Unable to get from ObjectStore: %+v", err)
+	}
+
+	// Process result into string
+	resultStr := utils.JsToJson(resultObj)
+	jww.DEBUG.Printf("Got from %s/%s: %s", objectStoreName, key, resultStr)
+	return resultStr, nil
+}
+
+// GetIndex is a generic helper for getting values from the given
+// [idb.ObjectStore] using the given [idb.Index].
+func GetIndex(db *idb.Database, objectStoreName string,
+	indexName string, key js.Value) (js.Value, error) {
+	parentErr := errors.Errorf("failed to GetIndex %s/%s/%s",
+		objectStoreName, indexName, key)
+
+	// Prepare the Transaction
+	txn, err := db.Transaction(idb.TransactionReadOnly, objectStoreName)
+	if err != nil {
+		return js.Value{}, errors.WithMessagef(parentErr,
+			"Unable to create Transaction: %+v", err)
+	}
+	store, err := txn.ObjectStore(objectStoreName)
+	if err != nil {
+		return js.Value{}, errors.WithMessagef(parentErr,
+			"Unable to get ObjectStore: %+v", err)
+	}
+	idx, err := store.Index(indexName)
+	if err != nil {
+		return js.Value{}, errors.WithMessagef(parentErr,
+			"Unable to get Index: %+v", err)
+	}
+
+	// Perform the operation
+	getRequest, err := idx.Get(key)
+	if err != nil {
+		return js.Value{}, errors.WithMessagef(parentErr,
+			"Unable to Get from ObjectStore: %+v", err)
+	}
+
+	// Wait for the operation to return
+	ctx, cancel := NewContext()
+	resultObj, err := getRequest.Await(ctx)
+	cancel()
+	if err != nil {
+		return js.Value{}, errors.WithMessagef(parentErr,
+			"Unable to get from ObjectStore: %+v", err)
+	}
+
+	// Process result into string
+	resultStr := utils.JsToJson(resultObj)
+	jww.DEBUG.Printf("Got from %s/%s/%s: %s",
+		objectStoreName, indexName, key, resultStr)
+	return resultObj, nil
+}
+
+// Put is a generic helper for putting values into the given [idb.ObjectStore].
+// Equivalent to insert if not exists else update.
+func Put(db *idb.Database, objectStoreName string, value js.Value) (*idb.Request, error) {
+	// Prepare the Transaction
+	txn, err := db.Transaction(idb.TransactionReadWrite, objectStoreName)
+	if err != nil {
+		return nil, errors.Errorf("Unable to create Transaction: %+v", err)
+	}
+	store, err := txn.ObjectStore(objectStoreName)
+	if err != nil {
+		return nil, errors.Errorf("Unable to get ObjectStore: %+v", err)
+	}
+
+	// Perform the operation
+	request, err := store.Put(value)
+	if err != nil {
+		return nil, errors.Errorf("Unable to Put: %+v", err)
+	}
+
+	// Wait for the operation to return
+	ctx, cancel := NewContext()
+	err = txn.Await(ctx)
+	cancel()
+	if err != nil {
+		return nil, errors.Errorf("Putting value failed: %+v", err)
+	}
+	jww.DEBUG.Printf("Successfully put value in %s: %v",
+		objectStoreName, value.String())
+	return request, nil
+}
+
+// Delete is a generic helper for removing values from the given [idb.ObjectStore].
+func Delete(db *idb.Database, objectStoreName string, key js.Value) error {
+	parentErr := errors.Errorf("failed to Delete %s/%s", objectStoreName, key)
+
+	// Prepare the Transaction
+	txn, err := db.Transaction(idb.TransactionReadOnly, objectStoreName)
+	if err != nil {
+		return errors.WithMessagef(parentErr,
+			"Unable to create Transaction: %+v", err)
+	}
+	store, err := txn.ObjectStore(objectStoreName)
+	if err != nil {
+		return errors.WithMessagef(parentErr,
+			"Unable to get ObjectStore: %+v", err)
+	}
+
+	// Perform the operation
+	deleteRequest, err := store.Delete(key)
+	if err != nil {
+		return errors.WithMessagef(parentErr,
+			"Unable to Get from ObjectStore: %+v", err)
+	}
+
+	// Wait for the operation to return
+	ctx, cancel := NewContext()
+	err = deleteRequest.Await(ctx)
+	cancel()
+	if err != nil {
+		return errors.WithMessagef(parentErr,
+			"Unable to delete from ObjectStore: %+v", err)
+	}
+	return nil
+}
+
+// Dump returns the given [idb.ObjectStore] contents to string slice for
+// testing and debugging purposes.
+func Dump(db *idb.Database, objectStoreName string) ([]string, error) {
+	parentErr := errors.Errorf("failed to Dump %s", objectStoreName)
+
+	txn, err := db.Transaction(idb.TransactionReadOnly, objectStoreName)
+	if err != nil {
+		return nil, errors.WithMessagef(parentErr,
+			"Unable to create Transaction: %+v", err)
+	}
+	store, err := txn.ObjectStore(objectStoreName)
+	if err != nil {
+		return nil, errors.WithMessagef(parentErr,
+			"Unable to get ObjectStore: %+v", err)
+	}
+	cursorRequest, err := store.OpenCursor(idb.CursorNext)
+	if err != nil {
+		return nil, errors.WithMessagef(parentErr,
+			"Unable to open Cursor: %+v", err)
+	}
+
+	// Run the query
+	jww.DEBUG.Printf("%s values:", objectStoreName)
+	results := make([]string, 0)
+	ctx, cancel := NewContext()
+	err = cursorRequest.Iter(ctx,
+		func(cursor *idb.CursorWithValue) error {
+			value, err := cursor.Value()
+			if err != nil {
+				return err
+			}
+			valueStr := utils.JsToJson(value)
+			results = append(results, valueStr)
+			jww.DEBUG.Printf("- %v", valueStr)
+			return nil
+		})
+	cancel()
+	if err != nil {
+		return nil, errors.WithMessagef(parentErr,
+			"Unable to dump ObjectStore: %+v", err)
+	}
+	return results, nil
+}
diff --git a/wasm/channels.go b/wasm/channels.go
index c8434b7b77e18d61fdcf845fd3ce9ead238acac3..bffaa262973038eae6f72f53284fc095189555f2 100644
--- a/wasm/channels.go
+++ b/wasm/channels.go
@@ -13,12 +13,12 @@ import (
 	"encoding/base64"
 	"encoding/json"
 	"gitlab.com/elixxir/client/v4/channels"
+	"gitlab.com/elixxir/xxdk-wasm/indexedDb/channels"
 	"gitlab.com/xx_network/primitives/id"
 	"sync"
 	"syscall/js"
 
 	"gitlab.com/elixxir/client/v4/bindings"
-	"gitlab.com/elixxir/xxdk-wasm/indexedDb"
 	"gitlab.com/elixxir/xxdk-wasm/utils"
 )
 
@@ -387,7 +387,7 @@ func newChannelsManagerWithIndexedDb(cmixID int, privateIdentity []byte,
 		cb.Invoke(uuid, utils.CopyBytesToJS(channelID.Marshal()), update)
 	}
 
-	model := indexedDb.NewWASMEventModelBuilder(cipher, messageReceivedCB)
+	model := channels.NewWASMEventModelBuilder(cipher, messageReceivedCB)
 
 	promiseFn := func(resolve, reject func(args ...any) js.Value) {
 		cm, err := bindings.NewChannelsManagerGoEventModel(
@@ -486,7 +486,7 @@ func loadChannelsManagerWithIndexedDb(cmixID int, storageTag string,
 		cb.Invoke(uuid, utils.CopyBytesToJS(channelID.Marshal()), updated)
 	}
 
-	model := indexedDb.NewWASMEventModelBuilder(cipher, messageReceivedCB)
+	model := channels.NewWASMEventModelBuilder(cipher, messageReceivedCB)
 
 	promiseFn := func(resolve, reject func(args ...any) js.Value) {
 		cm, err := bindings.LoadChannelsManagerGoEventModel(