diff --git a/go.mod b/go.mod
index 714cc010e7b4b04dd4e674d0bd3290506f7dfdab..8c3011f6a1fee6109fe81eb8e968b0bb548b80b7 100644
--- a/go.mod
+++ b/go.mod
@@ -8,8 +8,8 @@ require (
 	github.com/pkg/errors v0.9.1
 	github.com/spf13/cobra v1.7.0
 	github.com/spf13/jwalterweatherman v1.1.0
-	gitlab.com/elixxir/client/v4 v4.6.4-0.20230523215224-750d3d1707fd
-	gitlab.com/elixxir/crypto v0.0.7-0.20230522162218-45433d877235
+	gitlab.com/elixxir/client/v4 v4.6.4-0.20230523181720-70dea644d559
+	gitlab.com/elixxir/crypto v0.0.7-0.20230522190154-5cbcf67f4b39
 	gitlab.com/elixxir/primitives v0.0.3-0.20230214180039-9a25e2d3969c
 	gitlab.com/elixxir/wasm-utils v0.0.0-20230522231408-a43b2c1481b2
 	gitlab.com/xx_network/crypto v0.0.5-0.20230214003943-8a09396e95dd
@@ -59,6 +59,7 @@ require (
 	gitlab.com/elixxir/bloomfilter v0.0.0-20230322223210-fa84f6842de8 // indirect
 	gitlab.com/elixxir/comms v0.0.4-0.20230519211512-4a998f4b0938 // indirect
 	gitlab.com/elixxir/ekv v0.3.1-0.20230504190918-f5e96603c2e0 // indirect
+	gitlab.com/elixxir/wasm-utils v0.0.0-20230522231408-a43b2c1481b2 // indirect
 	gitlab.com/xx_network/comms v0.0.4-0.20230214180029-5387fb85736d // indirect
 	gitlab.com/xx_network/ring v0.0.3-0.20220902183151-a7d3b15bc981 // indirect
 	gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect
diff --git a/go.sum b/go.sum
index 3d373783de8a69f614d0a278747f6839aac5bea7..e596cd0c8a1470a0cd2488f065f69f95ff262519 100644
--- a/go.sum
+++ b/go.sum
@@ -405,16 +405,50 @@ github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
 github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
 gitlab.com/elixxir/bloomfilter v0.0.0-20230322223210-fa84f6842de8 h1:uAFCyBkXprQoPkcDDfxXtaMyL5x+xSGrAWzR907xROQ=
 gitlab.com/elixxir/bloomfilter v0.0.0-20230322223210-fa84f6842de8/go.mod h1:1X8gRIAPDisS3W6Vtr/ymiUmZMJUIwDV1o5DEOo/pzw=
-gitlab.com/elixxir/client/v4 v4.6.4-0.20230523215224-750d3d1707fd h1:ZF/3GcYFMe0KJt8zF1IhCK9YCgBpn3f+cTLqJKWFh+M=
-gitlab.com/elixxir/client/v4 v4.6.4-0.20230523215224-750d3d1707fd/go.mod h1:HgAbm91+FJ5NZ+tO9J1YoAcOOeH3n6ctu0AARQPHr5I=
+gitlab.com/elixxir/client/v4 v4.6.2-0.20230413171204-002612660098 h1:bdwXgEa0i9KpLiKQdhv6MEWAYLt3MsbNuIzFanVpWLY=
+gitlab.com/elixxir/client/v4 v4.6.2-0.20230413171204-002612660098/go.mod h1:G+lN+LvQPGcm5BQnrhnqT1xiRIAzH3OffAM+5oI9SUg=
+gitlab.com/elixxir/client/v4 v4.6.2-0.20230425190953-cd51598e9245 h1:pBwoSYD+BFIr5Wyc+PQhqm+fZGsRSNXCpF0z1cQQzK8=
+gitlab.com/elixxir/client/v4 v4.6.2-0.20230425190953-cd51598e9245/go.mod h1:G+lN+LvQPGcm5BQnrhnqT1xiRIAzH3OffAM+5oI9SUg=
+gitlab.com/elixxir/client/v4 v4.6.2-0.20230511215110-b43e18a47875 h1:u9DlU8xAk0rTvguhWK+6D/MfLHdR+jlDTfGJjiszJDE=
+gitlab.com/elixxir/client/v4 v4.6.2-0.20230511215110-b43e18a47875/go.mod h1:dLKU2zSWrZLk/fomAtt1DFGgpTHQAfPdxdXNp3EtRZU=
+gitlab.com/elixxir/client/v4 v4.6.2-0.20230512234533-17b97e5a36cc h1:f5lwmwejXTerTUjro9d5Ws1mKGD6ChXHMaBMhB3OhgA=
+gitlab.com/elixxir/client/v4 v4.6.2-0.20230512234533-17b97e5a36cc/go.mod h1:dLKU2zSWrZLk/fomAtt1DFGgpTHQAfPdxdXNp3EtRZU=
+gitlab.com/elixxir/client/v4 v4.6.2-0.20230515171506-7294c8dd22fa h1:HCt2CMRWlT19OYQkC2xcU2+Saa1ZcH2y4IQeqg3NcX0=
+gitlab.com/elixxir/client/v4 v4.6.2-0.20230515171506-7294c8dd22fa/go.mod h1:dLKU2zSWrZLk/fomAtt1DFGgpTHQAfPdxdXNp3EtRZU=
+gitlab.com/elixxir/client/v4 v4.6.2-0.20230516202225-832a99a19553 h1:jdEpGIKNmFHMVmqIOnXFUeWObmReM0IOMov4eqD8OY8=
+gitlab.com/elixxir/client/v4 v4.6.2-0.20230516202225-832a99a19553/go.mod h1:dLKU2zSWrZLk/fomAtt1DFGgpTHQAfPdxdXNp3EtRZU=
+gitlab.com/elixxir/client/v4 v4.6.2-0.20230519185423-524554d6cfd1 h1:Uksd5R1Hk3j7RJqWDyanmD8fOQTL2bBfH0/F8vC6ysI=
+gitlab.com/elixxir/client/v4 v4.6.2-0.20230519185423-524554d6cfd1/go.mod h1:dLKU2zSWrZLk/fomAtt1DFGgpTHQAfPdxdXNp3EtRZU=
+gitlab.com/elixxir/client/v4 v4.6.3 h1:oUsm5cn2Vnfqz+xwGYKrqFkPNN3sDAyp00EPGhUIA5E=
+gitlab.com/elixxir/client/v4 v4.6.3/go.mod h1:G+lN+LvQPGcm5BQnrhnqT1xiRIAzH3OffAM+5oI9SUg=
+gitlab.com/elixxir/client/v4 v4.6.4-0.20230519223444-1d981a1d95aa h1:PJylTJ4ol3p3Si9cipFmhhWo0YD4VXMrbHQODJ9ACKE=
+gitlab.com/elixxir/client/v4 v4.6.4-0.20230519223444-1d981a1d95aa/go.mod h1:rDC4sLKgj5kuuiJRp8bD1M7r0mlb0ib7q8q1Euct9/k=
+gitlab.com/elixxir/client/v4 v4.6.4-0.20230522204511-a198ba2e5749 h1:mFhb9/TDAtmvuDtBL70vvQCwg7OGSWcCLxXcqcfG3rQ=
+gitlab.com/elixxir/client/v4 v4.6.4-0.20230522204511-a198ba2e5749/go.mod h1:rDC4sLKgj5kuuiJRp8bD1M7r0mlb0ib7q8q1Euct9/k=
+gitlab.com/elixxir/client/v4 v4.6.4-0.20230522213235-dc7d3feb05b9 h1:/g+OA8nsI0LwY1NgR7WPOAztengA2UqrY7xXZarmwgk=
+gitlab.com/elixxir/client/v4 v4.6.4-0.20230522213235-dc7d3feb05b9/go.mod h1:trGefpFqH2+kx4/uEV+yyiEWpGq3AhRMnuBQDhDQKMM=
+gitlab.com/elixxir/client/v4 v4.6.4-0.20230523165030-737b5db25f0d h1:amrJ1WHTJd9+EArwgoq4XUwHu09hFwxYNtTc3S7W7ew=
+gitlab.com/elixxir/client/v4 v4.6.4-0.20230523165030-737b5db25f0d/go.mod h1:trGefpFqH2+kx4/uEV+yyiEWpGq3AhRMnuBQDhDQKMM=
+gitlab.com/elixxir/client/v4 v4.6.4-0.20230523181720-70dea644d559 h1:F1/+kAVnCqsxHeAiX7S0wYDGF0VhfNMEGoZZayyvt2w=
+gitlab.com/elixxir/client/v4 v4.6.4-0.20230523181720-70dea644d559/go.mod h1:trGefpFqH2+kx4/uEV+yyiEWpGq3AhRMnuBQDhDQKMM=
+gitlab.com/elixxir/comms v0.0.4-0.20230310205528-f06faa0d2f0b h1:8AVK93UEs/aufoqtFgyMVt9gf0oJ8F4pA60ZvEVvG+s=
+gitlab.com/elixxir/comms v0.0.4-0.20230310205528-f06faa0d2f0b/go.mod h1:z+qW0D9VpY5QKTd7wRlb5SK4kBNqLYsa4DXBcUXue9Q=
 gitlab.com/elixxir/comms v0.0.4-0.20230519211512-4a998f4b0938 h1:f27+QUFiGWrprKm+fstOg3ABkYLpWcZi3+8Lf5eDnqY=
 gitlab.com/elixxir/comms v0.0.4-0.20230519211512-4a998f4b0938/go.mod h1:z+qW0D9VpY5QKTd7wRlb5SK4kBNqLYsa4DXBcUXue9Q=
-gitlab.com/elixxir/crypto v0.0.7-0.20230522162218-45433d877235 h1:0BySdXTzRWxzH8k5RiNNMmmn2lpuQWLVcDDA/7ehyqc=
-gitlab.com/elixxir/crypto v0.0.7-0.20230522162218-45433d877235/go.mod h1:IYInxKr5Q7EH3oNhg1QX1/sTTRNi7L0JkcyfdRegoio=
+gitlab.com/elixxir/crypto v0.0.7-0.20230413162806-a99ec4bfea32 h1:Had0F7rMPgJJ2BUZoFNgeJq33md9RpV15nvd08Uxdzc=
+gitlab.com/elixxir/crypto v0.0.7-0.20230413162806-a99ec4bfea32/go.mod h1:/SLOlvkYVVJf6IU+vEjMLnS7cjjcoTlPV45g6tv6INc=
+gitlab.com/elixxir/crypto v0.0.7-0.20230519214355-b10a9f95d395 h1:aOoL0oyocmLUbCBXgF52QhtBXvAi+eXM1d0DrDsFkIg=
+gitlab.com/elixxir/crypto v0.0.7-0.20230519214355-b10a9f95d395/go.mod h1:IYInxKr5Q7EH3oNhg1QX1/sTTRNi7L0JkcyfdRegoio=
+gitlab.com/elixxir/crypto v0.0.7-0.20230522190154-5cbcf67f4b39 h1:cU8066kdJRH88GUetdoYfT4ATg+uzSyquhHbVcbxw7Q=
+gitlab.com/elixxir/crypto v0.0.7-0.20230522190154-5cbcf67f4b39/go.mod h1:IYInxKr5Q7EH3oNhg1QX1/sTTRNi7L0JkcyfdRegoio=
+gitlab.com/elixxir/ekv v0.2.1 h1:dtwbt6KmAXG2Tik5d60iDz2fLhoFBgWwST03p7T+9Is=
+gitlab.com/elixxir/ekv v0.2.1/go.mod h1:USLD7xeDnuZEavygdrgzNEwZXeLQJK/w1a+htpN+JEU=
 gitlab.com/elixxir/ekv v0.3.1-0.20230504190918-f5e96603c2e0 h1:4d2vg4Sh3N5mR1ta152cg6ybPWHYqsPtkEyJKaDYGnw=
 gitlab.com/elixxir/ekv v0.3.1-0.20230504190918-f5e96603c2e0/go.mod h1:EMaUQrsOxvEPQ0/8V/PSkGqFmEC2axBG/uqY0oW2uJM=
 gitlab.com/elixxir/primitives v0.0.3-0.20230214180039-9a25e2d3969c h1:muG8ff95woeVVwQoJHCEclxBFB22lc7EixPylEkYDRU=
 gitlab.com/elixxir/primitives v0.0.3-0.20230214180039-9a25e2d3969c/go.mod h1:phun4PLkHJA6wcL4JIhhxZztrmCyJHWPNppBP3DUD2Y=
+gitlab.com/elixxir/wasm-utils v0.0.0-20230519212008-29635852d8c7 h1:3pimSfFr0uy3OhOMM9IHXZBeG2xJX0nor2yph9xx3oM=
+gitlab.com/elixxir/wasm-utils v0.0.0-20230519212008-29635852d8c7/go.mod h1:wB7Vh/7LWUm8wYRBSd+6lxfpk4CnDaHTkLCIVKfL2TA=
 gitlab.com/elixxir/wasm-utils v0.0.0-20230522231408-a43b2c1481b2 h1:GQb350yPBkWRkPRgNSVFF0ZZDOAlXWIKQBI/1Ff6biU=
 gitlab.com/elixxir/wasm-utils v0.0.0-20230522231408-a43b2c1481b2/go.mod h1:wB7Vh/7LWUm8wYRBSd+6lxfpk4CnDaHTkLCIVKfL2TA=
 gitlab.com/xx_network/comms v0.0.4-0.20230214180029-5387fb85736d h1:AZf2h0fxyO1KxhZPP9//jG3Swb2BcuKbxtNXJgooLss=
diff --git a/indexedDb/impl/channels/callbacks.go b/indexedDb/impl/channels/callbacks.go
index e41bf1dd0f95fc7b7073e7b79b129f6c74b348ad..1d541bf5f23280bfc41d45d6b64f05e2ff4c6684 100644
--- a/indexedDb/impl/channels/callbacks.go
+++ b/indexedDb/impl/channels/callbacks.go
@@ -15,6 +15,7 @@ import (
 
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/v4/bindings"
 	"gitlab.com/elixxir/client/v4/channels"
 	"gitlab.com/elixxir/client/v4/cmix/rounds"
 	cryptoBroadcast "gitlab.com/elixxir/crypto/broadcast"
@@ -81,25 +82,25 @@ func (m *manager) newWASMEventModelCB(data []byte) ([]byte, error) {
 
 // EventUpdate implements [bindings.ChannelUICallbacks.EventUpdate].
 func (m *manager) EventUpdate(eventType int64, jsonData []byte) {
-	// Package parameters for sending
-	msg := &wChannels.EventUpdateCallbackMessage{
-		EventType: eventType,
-		JsonData:  jsonData,
+	var callbackTag worker.Tag
+	isValid := false
+	switch eventType {
+	case bindings.MessageReceived:
+		callbackTag = wChannels.MessageReceivedCallbackTag
+		isValid = true
+	case bindings.MessageDeleted:
+		callbackTag = wChannels.DeletedMessageCallbackTag
+		isValid = true
+	case bindings.UserMuted:
+		callbackTag = wChannels.MutedUserCallbackTag
+		isValid = true
+	default:
+		jww.ERROR.Printf("invalid indexedDB EventUpdate type %d: %+v)",
+			eventType, jsonData)
+	}
+	if isValid {
+		m.wtm.SendMessage(callbackTag, jsonData)
 	}
-	data, err := json.Marshal(msg)
-	if err != nil {
-		jww.ERROR.Printf("Could not JSON marshal %T: %+v", msg, err)
-		return
-	}
-
-	// Send it to the main thread
-	m.wtm.SendMessage(wChannels.EventUpdateCallbackTag, data)
-}
-
-// NicknameUpdate implements [bindings.ChannelUICallbacks.NicknameUpdate]
-func (m *manager) NicknameUpdate(channelIdBytes []byte, nickname string,
-	exists bool) {
-	jww.FATAL.Panicf("unimplemented")
 }
 
 // joinChannelCB is the callback for wasmModel.JoinChannel. Always returns nil;
diff --git a/indexedDb/impl/channels/implementation.go b/indexedDb/impl/channels/implementation.go
index f043c60be8b1c2b91931a466c1153ee2680ce07c..013d4e9a720f02b14b4efa1bfe3e159f0b277c26 100644
--- a/indexedDb/impl/channels/implementation.go
+++ b/indexedDb/impl/channels/implementation.go
@@ -172,11 +172,7 @@ func (w *wasmModel) ReceiveMessage(channelID *id.ID, messageID message.ID,
 		return 0
 	}
 
-	go w.eventUpdate(bindings.MessageReceived, bindings.MessageReceivedJson{
-		Uuid:      int64(uuid),
-		ChannelID: channelID,
-		Update:    false,
-	})
+	w.sendReceiveMessageUpdate(uuid, channelID, false)
 	return uuid
 }
 
@@ -215,11 +211,7 @@ func (w *wasmModel) ReceiveReply(channelID *id.ID, messageID,
 		return 0
 	}
 
-	go w.eventUpdate(bindings.MessageReceived, bindings.MessageReceivedJson{
-		Uuid:      int64(uuid),
-		ChannelID: channelID,
-		Update:    false,
-	})
+	w.sendReceiveMessageUpdate(uuid, channelID, false)
 	return uuid
 }
 
@@ -257,12 +249,7 @@ func (w *wasmModel) ReceiveReaction(channelID *id.ID, messageID,
 		jww.ERROR.Printf("Failed to receive reaction: %+v", err)
 		return 0
 	}
-
-	go w.eventUpdate(bindings.MessageReceived, bindings.MessageReceivedJson{
-		Uuid:      int64(uuid),
-		ChannelID: channelID,
-		Update:    false,
-	})
+	w.sendReceiveMessageUpdate(uuid, channelID, false)
 	return uuid
 }
 
@@ -409,18 +396,7 @@ func (w *wasmModel) updateMessage(currentMsg *Message, messageID *message.ID,
 	if err != nil {
 		return 0, err
 	}
-
-	channelID, err := id.Unmarshal(currentMsg.ChannelID)
-	if err != nil {
-		return 0, err
-	}
-
-	go w.eventUpdate(bindings.MessageReceived, bindings.MessageReceivedJson{
-		Uuid:      int64(uuid),
-		ChannelID: channelID,
-		Update:    true,
-	})
-
+	w.sendReceiveMessageUpdate(uuid, (*id.ID)(currentMsg.ChannelID), true)
 	return uuid, nil
 }
 
@@ -517,21 +493,48 @@ func (w *wasmModel) DeleteMessage(messageID message.ID) error {
 		return err
 	}
 
-	go w.eventUpdate(bindings.MessageDeleted,
-		bindings.MessageDeletedJson{MessageID: messageID})
-
+	eventData, err := json.Marshal(bindings.MessageDeletedJson{
+		MessageID: messageID,
+	})
+	if err != nil {
+		jww.WARN.Printf("couldn't marshal MessageDeleted: %s, %+v",
+			messageID, err)
+	} else {
+		go w.cbs.EventUpdate(bindings.MessageDeleted, eventData)
+	}
 	return nil
 }
 
 // MuteUser is called whenever a user is muted or unmuted.
 func (w *wasmModel) MuteUser(
 	channelID *id.ID, pubKey ed25519.PublicKey, unmute bool) {
-
-	go w.eventUpdate(bindings.UserMuted, bindings.UserMutedJson{
+	eventData, err := json.Marshal(bindings.UserMutedJson{
 		ChannelID: channelID,
 		PubKey:    pubKey,
 		Unmute:    unmute,
 	})
+	if err != nil {
+		jww.WARN.Printf("couldn't marshal UserMuted: %s, %+v",
+			pubKey, err)
+	} else {
+		go w.cbs.EventUpdate(bindings.UserMuted, eventData)
+	}
+}
+
+func (w *wasmModel) sendReceiveMessageUpdate(uuid uint64, channelID *id.ID,
+	update bool) {
+	eventMsg := bindings.MessageReceivedJson{
+		Uuid:      int64(uuid),
+		ChannelID: channelID,
+		Update:    update,
+	}
+	eventData, err := json.Marshal(eventMsg)
+	if err != nil {
+		jww.WARN.Printf("couldn't marshal MessageReceive: %v, %+v",
+			eventMsg, err)
+	} else {
+		go w.cbs.EventUpdate(bindings.MessageReceived, eventData)
+	}
 }
 
 // valueToMessage is a helper for converting js.Value to Message.
diff --git a/indexedDb/impl/channels/implementation_test.go b/indexedDb/impl/channels/implementation_test.go
index cdf17e6f2e63e9990af5acc02f6852ee0459528f..1a8c87f0792a71ab6274e4e82f7ef075bd17e5f7 100644
--- a/indexedDb/impl/channels/implementation_test.go
+++ b/indexedDb/impl/channels/implementation_test.go
@@ -43,7 +43,8 @@ func TestMain(m *testing.M) {
 }
 
 type dummyCbs struct{}
-func (c *dummyCbs) EventUpdate(int64, []byte) {}
+
+func (c *dummyCbs) EventUpdate(eventType int64, dataJson []byte) {}
 
 // Happy path test for receiving, updating, getting, and deleting a File.
 func TestWasmModel_ReceiveFile(t *testing.T) {
diff --git a/indexedDb/worker/channels/init.go b/indexedDb/worker/channels/init.go
index e8a8f9419ff25da299bcb3f868b01ab4b1e048d5..dd0dd99d474299327a12aff8712ced83f9ba46e5 100644
--- a/indexedDb/worker/channels/init.go
+++ b/indexedDb/worker/channels/init.go
@@ -27,8 +27,10 @@ import (
 // databaseSuffix is the suffix to be appended to the name of the database.
 const databaseSuffix = "_speakeasy"
 
-// EventUpdate is called any time an event occurs.
-type EventUpdate func(eventType int64, jsonData []byte)
+// eventUpdateCallback is the [bindings.ChannelUICallback] callback function
+// it has a type ([bindings.NickNameUpdate] to [bindings.MessageDeleted]
+// and json data that is the callback information.
+type eventUpdateCallback func(eventType int64, jsonData []byte)
 
 // NewWASMEventModelBuilder returns an EventModelBuilder which allows
 // the channel manager to define the path but the callback is the same
@@ -62,10 +64,18 @@ func NewWASMEventModel(path, wasmJsPath string, encryption cryptoChannel.Cipher,
 		return nil, err
 	}
 
-	// Register handler to manage messages for the EventUpdate
-	wm.RegisterCallback(EventUpdateCallbackTag,
+	// Register handler to manage messages for the MessageReceivedCallback
+	wm.RegisterCallback(MessageReceivedCallbackTag,
 		messageReceivedCallbackHandler(channelCbs.EventUpdate))
 
+	// Register handler to manage messages for the DeletedMessageCallback
+	wm.RegisterCallback(DeletedMessageCallbackTag,
+		deletedMessageCallbackHandler(channelCbs.EventUpdate))
+
+	// Register handler to manage messages for the MutedUserCallback
+	wm.RegisterCallback(MutedUserCallbackTag,
+		mutedUserCallbackHandler(channelCbs.EventUpdate))
+
 	// Store the database name
 	err = storage.StoreIndexedDb(databaseName)
 	if err != nil {
@@ -120,17 +130,25 @@ type EventUpdateCallbackMessage struct {
 
 // messageReceivedCallbackHandler returns a handler to manage messages for the
 // MessageReceivedCallback.
-func messageReceivedCallbackHandler(cb EventUpdate) func(data []byte) {
+func messageReceivedCallbackHandler(cb eventUpdateCallback) func(data []byte) {
 	return func(data []byte) {
-		var msg EventUpdateCallbackMessage
-		err := json.Unmarshal(data, &msg)
-		if err != nil {
-			jww.ERROR.Printf(
-				"Failed to JSON unmarshal %T from worker: %+v", msg, err)
-			return
-		}
+		cb(bindings.MessageReceived, data)
+	}
+}
 
-		cb(msg.EventType, msg.JsonData)
+// deletedMessageCallbackHandler returns a handler to manage messages for the
+// DeletedMessageCallback.
+func deletedMessageCallbackHandler(cb eventUpdateCallback) func(data []byte) {
+	return func(data []byte) {
+		cb(bindings.MessageDeleted, data)
+	}
+}
+
+// mutedUserCallbackHandler returns a handler to manage messages for the
+// MutedUserCallback.
+func mutedUserCallbackHandler(cb eventUpdateCallback) func(data []byte) {
+	return func(data []byte) {
+		cb(bindings.UserMuted, data)
 	}
 }
 
diff --git a/indexedDb/worker/channels/tags.go b/indexedDb/worker/channels/tags.go
index f21c91653547cfe37158d514ef482c468084d800..019911288e4cdc2c78ad352d7813094e31aeee99 100644
--- a/indexedDb/worker/channels/tags.go
+++ b/indexedDb/worker/channels/tags.go
@@ -14,8 +14,11 @@ import "gitlab.com/elixxir/xxdk-wasm/worker"
 // List of tags that can be used when sending a message or registering a handler
 // to receive a message.
 const (
-	NewWASMEventModelTag   worker.Tag = "NewWASMEventModel"
-	EventUpdateCallbackTag worker.Tag = "EventUpdateCallback"
+	NewWASMEventModelTag          worker.Tag = "NewWASMEventModel"
+	NotificationUpdateCallbackTag worker.Tag = "NotificationUpdateCallback"
+	MessageReceivedCallbackTag    worker.Tag = "MessageReceivedCallback"
+	DeletedMessageCallbackTag     worker.Tag = "DeletedMessageCallback"
+	MutedUserCallbackTag          worker.Tag = "MutedUserCallback"
 
 	JoinChannelTag         worker.Tag = "JoinChannel"
 	LeaveChannelTag        worker.Tag = "LeaveChannel"
diff --git a/main.go b/main.go
index bf8ab4ae1251c5ccf8413efdbc1daf94bb014b7b..267bb55bb812d1950c412a51337464cd35f39b36 100644
--- a/main.go
+++ b/main.go
@@ -100,6 +100,11 @@ func setGlobals() {
 	js.Global().Set("InitializeBackup", js.FuncOf(wasm.InitializeBackup))
 	js.Global().Set("ResumeBackup", js.FuncOf(wasm.ResumeBackup))
 
+	// wasm/notifications.go
+	js.Global().Set("LoadNotifications", js.FuncOf(wasm.LoadNotifications))
+	js.Global().Set("LoadNotificationsDummy",
+		js.FuncOf(wasm.LoadNotificationsDummy))
+
 	// wasm/channels.go
 	js.Global().Set("GenerateChannelIdentity",
 		js.FuncOf(wasm.GenerateChannelIdentity))
@@ -133,6 +138,8 @@ func setGlobals() {
 	js.Global().Set("CheckNoMessageErr", js.FuncOf(wasm.CheckNoMessageErr))
 	js.Global().Set("NewChannelsDatabaseCipher",
 		js.FuncOf(wasm.NewChannelsDatabaseCipher))
+	js.Global().Set("GetNotificationReportsForMe",
+		js.FuncOf(wasm.GetNotificationReportsForMe))
 
 	// wasm/dm.go
 	js.Global().Set("InitChannelsFileTransfer",
diff --git a/wasm/channels.go b/wasm/channels.go
index a21c9a42a1486ab84937c525028daa8c3d291817..f7aa105d2b27763cdef1f69126812be92594f67b 100644
--- a/wasm/channels.go
+++ b/wasm/channels.go
@@ -17,10 +17,8 @@ import (
 	"syscall/js"
 
 	"gitlab.com/elixxir/client/v4/bindings"
-	"gitlab.com/elixxir/client/v4/channels"
 	"gitlab.com/elixxir/wasm-utils/exception"
 	"gitlab.com/elixxir/wasm-utils/utils"
-	channelsDb "gitlab.com/elixxir/xxdk-wasm/indexedDb/worker/channels"
 )
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -80,6 +78,11 @@ func newChannelsManagerJS(api *bindings.ChannelsManager) map[string]any {
 
 		// Channel Receiving Logic and Callback Registration
 		"RegisterReceiveHandler": js.FuncOf(cm.RegisterReceiveHandler),
+
+		// Notifications
+		"SetMobileNotificationsLevel": js.FuncOf(
+			cm.SetMobileNotificationsLevel),
+		"GetNotificationLevel": js.FuncOf(cm.GetNotificationLevel),
 	}
 
 	return channelsManagerMap
@@ -255,35 +258,34 @@ func GetPublicChannelIdentityFromPrivate(_ js.Value, args []js.Value) any {
 // Parameters:
 //   - args[0] - ID of [Cmix] object in tracker (int). This can be retrieved
 //     using [Cmix.GetID].
-//   - args[1] - Bytes of a private identity ([channel.PrivateIdentity]) that is
+//   - args[1] - ID of [bindings.Notifications] object in tracker (int). Can be
+//     retrieved using [Notifications.GetID].
+//   - args[2] - Bytes of a private identity ([channel.PrivateIdentity]) that is
 //     generated by [GenerateChannelIdentity] (Uint8Array).
-//   - args[2] - A function that initialises and returns a Javascript object
-//     that matches the [bindings.EventModel] interface. The function must match
-//     the Build function in [bindings.EventModelBuilder].
 //   - args[3] - JSON of an array of integers of [channels.ExtensionBuilder]
 //     IDs. The ID can be retrieved from an object with an extension builder
 //     (e.g., [ChannelsFileTransfer.GetExtensionBuilderID]). Leave empty if not
 //     using extension builders. Example: `[2,11,5]` (Uint8Array).
-//   - args[4] - ID of [Notifications] object in tracker. This can be retrieved
-//     using [Notifications.GetID] (int).
-//   - args[5] - A Javascript object that implements the function on
-//     [bindings.ChannelUICallbacks]. It is a callback that informs the UI about
-//     various events. The entire interface can be nil, but if defined, each
-//     method must be implemented.
+//   - args[4] - A function that initialises and returns a Javascript object
+//     that matches the [bindings.EventModel] interface. The function must match
+//     the Build function in [bindings.EventModelBuilder].
+//   - args[4] - A callback object which implements the
+//     [bindings.ChannelUICallbacks] javascript functions.
 //
 // Returns:
 //   - Javascript representation of the [ChannelsManager] object.
 //   - Throws an error if creating the manager fails.
 func NewChannelsManager(_ js.Value, args []js.Value) any {
 	cmixId := args[0].Int()
-	privateIdentity := utils.CopyBytesToGo(args[1])
-	em := newEventModelBuilder(args[2])
+	notificationsId := args[1].Int()
+	privateIdentity := utils.CopyBytesToGo(args[2])
 	extensionBuilderIDsJSON := utils.CopyBytesToGo(args[3])
-	notificationsID := args[4].Int()
-	cUI := newChannelUI(args[5])
+	em := newEventModelBuilder(args[4])
+	channelCbs := newChannelUI(args[5])
 
 	cm, err := bindings.NewChannelsManager(
-		cmixId, privateIdentity, em, extensionBuilderIDsJSON, notificationsID, cUI)
+		cmixId, privateIdentity, extensionBuilderIDsJSON, em,
+		notificationsId, channelCbs)
 	if err != nil {
 		exception.ThrowTrace(err)
 		return nil
@@ -303,34 +305,27 @@ func NewChannelsManager(_ js.Value, args []js.Value) any {
 // Parameters:
 //   - args[0] - ID of [Cmix] object in tracker (int). This can be retrieved
 //     using [Cmix.GetID].
-//   - args[1] - The storage tag associated with the previously created channel
+//   - args[1] - ID of [bindings.Notifications] object in tracker (int). Can be
+//     retrieved using [Notifications.GetID].
+//   - args[2] - The storage tag associated with the previously created channel
 //     manager and retrieved with [ChannelsManager.GetStorageTag] (string).
-//   - args[2] - A function that initializes and returns a Javascript object
+//   - args[3] - A function that initialises and returns a Javascript object
 //     that matches the [bindings.EventModel] interface. The function must match
 //     the Build function in [bindings.EventModelBuilder].
-//   - args[3] - JSON of an array of integers of [channels.ExtensionBuilder]
-//     IDs. The ID can be retrieved from an object with an extension builder
-//     (e.g., [ChannelsFileTransfer.GetExtensionBuilderID]). Leave empty if not
-//     using extension builders. Example: `[2,11,5]`.
-//   - args[4] - ID of [Notifications] object in tracker. This can be retrieved
-//     using [Notifications.GetID] (int).
-//   - args[5] - A Javascript object that implements the function on
-//     [bindings.ChannelUICallbacks]. It is a callback that informs the UI about
-//     various events. The entire interface can be nil, but if defined, each
-//     method must be implemented.
+//   - args[4] - A callback object which implements the
+//     [bindings.ChannelUICallbacks] javascript functions.
 //
 // Returns:
 //   - Javascript representation of the [ChannelsManager] object.
 //   - Throws an error if loading the manager fails.
 func LoadChannelsManager(_ js.Value, args []js.Value) any {
-	cmixID := args[0].Int()
-	storageTag := args[1].String()
-	em := newEventModelBuilder(args[2])
-	extensionBuilderIDsJSON := utils.CopyBytesToGo(args[3])
-	notificationsID := args[4].Int()
-	cUI := newChannelUI(args[5])
-	cm, err := bindings.LoadChannelsManager(
-		cmixID, storageTag, em, extensionBuilderIDsJSON, notificationsID, cUI)
+	cMixID := args[0].Int()
+	notificationsID := args[1].Int()
+	storageTag := args[2].String()
+	em := newEventModelBuilder(args[3])
+	cUI := newChannelUI(args[4])
+	cm, err := bindings.LoadChannelsManager(cMixID, storageTag, em,
+		notificationsID, cUI)
 	if err != nil {
 		exception.ThrowTrace(err)
 		return nil
@@ -353,19 +348,17 @@ func LoadChannelsManager(_ js.Value, args []js.Value) any {
 // Parameters:
 //   - args[0] - ID of [Cmix] object in tracker (int). This can be retrieved
 //     using [Cmix.GetID].
-//   - args[1] - Path to Javascript file that starts the worker (string).
-//   - args[2] - Bytes of a private identity ([channel.PrivateIdentity]) that is
+//   - args[1] - ID of [bindings.Notifications] object in tracker (int). Can be
+//     retrieved using [Notifications.GetID].
+//   - args[2] - Path to Javascript file that starts the worker (string).
+//   - args[3] - Bytes of a private identity ([channel.PrivateIdentity]) that is
 //     generated by [GenerateChannelIdentity] (Uint8Array).
-//   - args[3] - JSON of an array of integers of [channels.ExtensionBuilder]
+//   - args[4] - JSON of an array of integers of [channels.ExtensionBuilder]
 //     IDs. The ID can be retrieved from an object with an extension builder
 //     (e.g., [ChannelsFileTransfer.GetExtensionBuilderID]). Leave empty if not
 //     using extension builders. Example: `[2,11,5]` (Uint8Array).
-//   - args[4] - ID of [Notifications] object in tracker. This can be retrieved
-//     using [Notifications.GetID] (int).
-//   - args[5] - A Javascript object that implements the function on
-//     [bindings.ChannelUICallbacks]. It is a callback that informs the UI about
-//     various events. The entire interface can be nil, but if defined, each
-//     method must be implemented.
+//   - args[5] - A callback object which implements the
+//     [bindings.ChannelUICallbacks] javascript functions.
 //   - args[6] - ID of [ChannelDbCipher] object in tracker (int). Create this
 //     object with [NewChannelsDatabaseCipher] and get its id with
 //     [ChannelDbCipher.GetID].
@@ -376,11 +369,11 @@ func LoadChannelsManager(_ js.Value, args []js.Value) any {
 //   - Throws an error if the cipher ID does not correspond to a cipher.
 func NewChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) any {
 	cmixID := args[0].Int()
-	wasmJsPath := args[1].String()
-	privateIdentity := utils.CopyBytesToGo(args[2])
-	extensionBuilderIDsJSON := utils.CopyBytesToGo(args[3])
-	notificationsID := args[4].Int()
-	cUI := newChannelUI(args[5])
+	notificationsID := args[1].Int()
+	wasmJsPath := args[2].String()
+	privateIdentity := utils.CopyBytesToGo(args[3])
+	extensionBuilderIDsJSON := utils.CopyBytesToGo(args[4])
+	channelCbs := newChannelUI(args[5])
 	cipherID := args[6].Int()
 
 	cipher, err := bindings.GetChannelDbCipherTrackerFromID(cipherID)
@@ -388,8 +381,9 @@ func NewChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) any {
 		exception.ThrowTrace(err)
 	}
 
-	return newChannelsManagerWithIndexedDb(cmixID, wasmJsPath, privateIdentity,
-		extensionBuilderIDsJSON, notificationsID, cUI, cipher)
+	return newChannelsManagerWithIndexedDb(cmixID, notificationsID,
+		wasmJsPath, privateIdentity,
+		extensionBuilderIDsJSON, channelCbs, cipher)
 }
 
 // NewChannelsManagerWithIndexedDbUnsafe creates a new [ChannelsManager] from a
@@ -407,19 +401,17 @@ func NewChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) any {
 // Parameters:
 //   - args[0] - ID of [Cmix] object in tracker (int). This can be retrieved
 //     using [Cmix.GetID].
-//   - args[1] - Path to Javascript file that starts the worker (string).
-//   - args[2] - Bytes of a private identity ([channel.PrivateIdentity]) that is
+//   - args[1] - ID of [bindings.Notifications] object in tracker (int). Can be
+//     retrieved using [Notifications.GetID].
+//   - args[2] - Path to Javascript file that starts the worker (string).
+//   - args[3] - Bytes of a private identity ([channel.PrivateIdentity]) that is
 //     generated by [GenerateChannelIdentity] (Uint8Array).
-//   - args[3] - JSON of an array of integers of [channels.ExtensionBuilder]
+//   - args[4] - JSON of an array of integers of [channels.ExtensionBuilder]
 //     IDs. The ID can be retrieved from an object with an extension builder
 //     (e.g., [ChannelsFileTransfer.GetExtensionBuilderID]). Leave empty if not
 //     using extension builders. Example: `[2,11,5]` (Uint8Array).
-//   - args[4] - ID of [Notifications] object in tracker. This can be retrieved
-//     using [Notifications.GetID] (int).
-//   - args[5] - A Javascript object that implements the function on
-//     [bindings.ChannelUICallbacks]. It is a callback that informs the UI about
-//     various events. The entire interface can be nil, but if defined, each
-//     method must be implemented.
+//   - args[5] - A callback object which implements the
+//     [bindings.ChannelUICallbacks] javascript functions.
 //
 // Returns a promise:
 //   - Resolves to a Javascript representation of the [ChannelsManager] object.
@@ -428,18 +420,19 @@ func NewChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) any {
 // FIXME: package names in comments for indexedDb
 func NewChannelsManagerWithIndexedDbUnsafe(_ js.Value, args []js.Value) any {
 	cmixID := args[0].Int()
-	wasmJsPath := args[1].String()
-	privateIdentity := utils.CopyBytesToGo(args[2])
-	extensionBuilderIDsJSON := utils.CopyBytesToGo(args[3])
-	notificationsID := args[4].Int()
-	cUI := newChannelUI(args[5])
+	notificationsID := args[1].Int()
+	wasmJsPath := args[2].String()
+	privateIdentity := utils.CopyBytesToGo(args[3])
+	extensionBuilderIDsJSON := utils.CopyBytesToGo(args[4])
+	channelsCbs := newChannelUI(args[5])
 
-	return newChannelsManagerWithIndexedDb(cmixID, wasmJsPath, privateIdentity,
-		extensionBuilderIDsJSON, notificationsID, cUI, nil)
+	return newChannelsManagerWithIndexedDb(cmixID, notificationsID,
+		wasmJsPath, privateIdentity,
+		extensionBuilderIDsJSON, channelsCbs, nil)
 }
 
-func newChannelsManagerWithIndexedDb(cmixID int, wasmJsPath string,
-	privateIdentity, extensionBuilderIDsJSON []byte, notificationsID int,
+func newChannelsManagerWithIndexedDb(cmixID, notificationsID int,
+	wasmJsPath string, privateIdentity, extensionBuilderIDsJSON []byte,
 	channelsCbs bindings.ChannelUICallbacks,
 	cipher *bindings.ChannelDbCipher) any {
 
@@ -447,9 +440,9 @@ func newChannelsManagerWithIndexedDb(cmixID int, wasmJsPath string,
 		wasmJsPath, cipher, channelsCbs)
 
 	promiseFn := func(resolve, reject func(args ...any) js.Value) {
-		cm, err := bindings.NewChannelsManagerGoEventModel(cmixID,
-			privateIdentity, extensionBuilderIDsJSON, model, notificationsID,
-			channelsCbs)
+		cm, err := bindings.NewChannelsManagerGoEventModel(
+			cmixID, privateIdentity, extensionBuilderIDsJSON, model,
+			notificationsID, channelsCbs)
 		if err != nil {
 			reject(exception.NewTrace(err))
 		} else {
@@ -471,20 +464,14 @@ func newChannelsManagerWithIndexedDb(cmixID int, wasmJsPath string,
 // Parameters:
 //   - args[0] - ID of [Cmix] object in tracker (int). This can be retrieved
 //     using [Cmix.GetID].
-//   - args[1] - Path to Javascript file that starts the worker (string).
-//   - args[2] - The storage tag associated with the previously created channel
+//   - args[1] - ID of [bindings.Notifications] object in tracker (int). Can be
+//     retrieved using [Notifications.GetID].
+//   - args[2] - Path to Javascript file that starts the worker (string).
+//   - args[3] - The storage tag associated with the previously created channel
 //     manager and retrieved with [ChannelsManager.GetStorageTag] (string).
-//   - args[3] - JSON of an array of integers of [channels.ExtensionBuilder]
-//     IDs. The ID can be retrieved from an object with an extension builder
-//     (e.g., [ChannelsFileTransfer.GetExtensionBuilderID]). Leave empty if not
-//     using extension builders. Example: `[2,11,5]` (Uint8Array).
-//   - args[4] - ID of [Notifications] object in tracker. This can be retrieved
-//     using [Notifications.GetID] (int).
-//   - args[5] - A Javascript object that implements the function on
-//     [bindings.ChannelUICallbacks]. It is a callback that informs the UI about
-//     various events. The entire interface can be nil, but if defined, each
-//     method must be implemented.
-//   - args[6] - ID of [ChannelDbCipher] object in tracker (int). Create this
+//   - args[4] - A callback object which implements the
+//     [bindings.ChannelUICallbacks] javascript functions.
+//   - args[5] - ID of [ChannelDbCipher] object in tracker (int). Create this
 //     object with [NewChannelsDatabaseCipher] and get its id with
 //     [ChannelDbCipher.GetID].
 //
@@ -494,20 +481,20 @@ func newChannelsManagerWithIndexedDb(cmixID int, wasmJsPath string,
 //   - Throws an error if the cipher ID does not correspond to a cipher.
 func LoadChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) any {
 	cmixID := args[0].Int()
-	wasmJsPath := args[1].String()
-	storageTag := args[2].String()
-	extensionBuilderIDsJSON := utils.CopyBytesToGo(args[3])
-	notificationsID := args[4].Int()
-	channelsCbs := newChannelUI(args[5])
-	cipherID := args[6].Int()
+	notificationsID := args[1].Int()
+	wasmJsPath := args[2].String()
+	storageTag := args[3].String()
+	channelsCbs := newChannelUI(args[4])
+	cipherID := args[5].Int()
 
 	cipher, err := bindings.GetChannelDbCipherTrackerFromID(cipherID)
 	if err != nil {
 		exception.ThrowTrace(err)
 	}
 
-	return loadChannelsManagerWithIndexedDb(cmixID, wasmJsPath, storageTag,
-		extensionBuilderIDsJSON, notificationsID, channelsCbs, cipher)
+	return loadChannelsManagerWithIndexedDb(cmixID, notificationsID,
+		wasmJsPath, storageTag,
+		channelsCbs, cipher)
 }
 
 // LoadChannelsManagerWithIndexedDbUnsafe loads an existing [ChannelsManager]
@@ -523,37 +510,32 @@ func LoadChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) any {
 // Parameters:
 //   - args[0] - ID of [Cmix] object in tracker (int). This can be retrieved
 //     using [Cmix.GetID].
-//   - args[1] - Path to Javascript file that starts the worker (string).
-//   - args[2] - The storage tag associated with the previously created channel
+//   - args[1] - ID of [bindings.Notifications] object in tracker (int). Can be
+//     retrieved using [Notifications.GetID].
+//   - args[2] - Path to Javascript file that starts the worker (string).
+//   - args[3] - The storage tag associated with the previously created channel
 //     manager and retrieved with [ChannelsManager.GetStorageTag] (string).
-//   - args[3] - JSON of an array of integers of [channels.ExtensionBuilder]
-//     IDs. The ID can be retrieved from an object with an extension builder
-//     (e.g., [ChannelsFileTransfer.GetExtensionBuilderID]). Leave empty if not
-//     using extension builders. Example: `[2,11,5]` (Uint8Array).
-//   - args[4] - ID of [Notifications] object in tracker. This can be retrieved
-//     using [Notifications.GetID] (int).
-//   - args[5] - A Javascript object that implements the function on
-//     [bindings.ChannelUICallbacks]. It is a callback that informs the UI about
-//     various events. The entire interface can be nil, but if defined, each
-//     method must be implemented.
+//   - args[4] - A callback object which implements the
+//     [bindings.ChannelUICallbacks] javascript functions.
 //
 // Returns a promise:
 //   - Resolves to a Javascript representation of the [ChannelsManager] object.
 //   - Rejected with an error if loading indexedDb or the manager fails.
 func LoadChannelsManagerWithIndexedDbUnsafe(_ js.Value, args []js.Value) any {
 	cmixID := args[0].Int()
-	wasmJsPath := args[1].String()
-	storageTag := args[2].String()
-	extensionBuilderIDsJSON := utils.CopyBytesToGo(args[3])
-	notificationsID := args[4].Int()
-	cUI := newChannelUI(args[5])
+	notificationsID := args[1].Int()
+	wasmJsPath := args[2].String()
+	storageTag := args[3].String()
+	cUI := newChannelUI(args[4])
 
-	return loadChannelsManagerWithIndexedDb(cmixID, wasmJsPath, storageTag,
-		extensionBuilderIDsJSON, notificationsID, cUI, nil)
+	return loadChannelsManagerWithIndexedDb(cmixID, notificationsID,
+		wasmJsPath, storageTag,
+		cUI, nil)
 }
 
-func loadChannelsManagerWithIndexedDb(cmixID int, wasmJsPath, storageTag string,
-	extensionBuilderIDsJSON []byte, notificationsID int, channelsCbs bindings.ChannelUICallbacks,
+func loadChannelsManagerWithIndexedDb(cmixID, notificationsID int,
+	wasmJsPath, storageTag string,
+	channelsCbs bindings.ChannelUICallbacks,
 	cipher *bindings.ChannelDbCipher) any {
 
 	model := channelsDb.NewWASMEventModelBuilder(
@@ -561,7 +543,7 @@ func loadChannelsManagerWithIndexedDb(cmixID int, wasmJsPath, storageTag string,
 
 	promiseFn := func(resolve, reject func(args ...any) js.Value) {
 		cm, err := bindings.LoadChannelsManagerGoEventModel(
-			cmixID, storageTag, model, extensionBuilderIDsJSON, notificationsID,
+			cmixID, storageTag, model, nil, notificationsID,
 			channelsCbs)
 		if err != nil {
 			reject(exception.NewTrace(err))
@@ -992,16 +974,9 @@ func ValidForever(js.Value, []js.Value) any {
 //     to the user should be tracked while all actions should not be (boolean).
 //   - args[5] - JSON of [xxdk.CMIXParams]. If left empty
 //     [bindings.GetDefaultCMixParams] will be used internally (Uint8Array).
-//   - args[6] - JSON of a slice of public keys of users that should receive
-//     mobile notifications for the message.
-//
-// Example slice of public keys:
-//
-//	[
-//	  "FgJMvgSsY4rrKkS/jSe+vFOJOs5qSSyOUSW7UtF9/KU=",
-//	  "fPqcHtrJ398PAC35QyWXEU9PHzz8Z4BKQTCxSvpSygw=",
-//	  "JnjCgh7g/+hNiI9VPKW01aRSxGOFmNulNCymy3ImXAo="
-//	]
+//   - args[6] - pingBytes - An array of public keys of users that
+//     should receive mobile notifications for the message (JSON of
+//     []Uint8Array list).
 //
 // Returns a promise:
 //   - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array).
@@ -1013,11 +988,16 @@ func (cm *ChannelsManager) SendGeneric(_ js.Value, args []js.Value) any {
 	leaseTimeMS := int64(args[3].Int())
 	tracked := args[4].Bool()
 	cmixParamsJSON := utils.CopyBytesToGo(args[5])
-	pingsJSON := utils.CopyBytesToGo(args[6])
+	var pingBytes [][]byte
 
 	promiseFn := func(resolve, reject func(args ...any) js.Value) {
-		sendReport, err := cm.api.SendGeneric(marshalledChanId, messageType,
-			msg, leaseTimeMS, tracked, cmixParamsJSON, pingsJSON)
+		err := json.Unmarshal(utils.CopyBytesToGo(args[6]), pingBytes)
+		if err != nil {
+			reject(exception.NewTrace(err))
+		}
+		sendReport, err := cm.api.SendGeneric(marshalledChanId,
+			messageType, msg, leaseTimeMS, tracked,
+			cmixParamsJSON, pingBytes)
 		if err != nil {
 			reject(exception.NewTrace(err))
 		} else {
@@ -1047,16 +1027,9 @@ func (cm *ChannelsManager) SendGeneric(_ js.Value, args []js.Value) any {
 //     be enumerated here. Use [ValidForever] to last the max message life.
 //   - args[3] - JSON of [xxdk.CMIXParams]. If left empty
 //     [bindings.GetDefaultCMixParams] will be used internally (Uint8Array).
-//   - args[4] - JSON of a slice of public keys of users that should receive
-//     mobile notifications for the message.
-//
-// Example slice of public keys:
-//
-//	[
-//	  "FgJMvgSsY4rrKkS/jSe+vFOJOs5qSSyOUSW7UtF9/KU=",
-//	  "fPqcHtrJ398PAC35QyWXEU9PHzz8Z4BKQTCxSvpSygw=",
-//	  "JnjCgh7g/+hNiI9VPKW01aRSxGOFmNulNCymy3ImXAo="
-//	]
+//   - args[4] - pingBytes - An array of public keys of users that
+//     should receive mobile notifications for the message (JSON of
+//     []Uint8Array list).
 //
 // Returns a promise:
 //   - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array).
@@ -1066,11 +1039,16 @@ func (cm *ChannelsManager) SendMessage(_ js.Value, args []js.Value) any {
 	msg := args[1].String()
 	leaseTimeMS := int64(args[2].Int())
 	cmixParamsJSON := utils.CopyBytesToGo(args[3])
-	pingsJSON := utils.CopyBytesToGo(args[4])
+	var pingBytes [][]byte
 
 	promiseFn := func(resolve, reject func(args ...any) js.Value) {
+		err := json.Unmarshal(utils.CopyBytesToGo(args[6]), pingBytes)
+		if err != nil {
+			reject(exception.NewTrace(err))
+		}
 		sendReport, err := cm.api.SendMessage(
-			marshalledChanId, msg, leaseTimeMS, cmixParamsJSON, pingsJSON)
+			marshalledChanId, msg, leaseTimeMS, cmixParamsJSON,
+			pingBytes)
 		if err != nil {
 			reject(exception.NewTrace(err))
 		} else {
@@ -1107,16 +1085,9 @@ func (cm *ChannelsManager) SendMessage(_ js.Value, args []js.Value) any {
 //     be enumerated here. Use [ValidForever] to last the max message life.
 //   - args[4] - JSON of [xxdk.CMIXParams]. If left empty
 //     [bindings.GetDefaultCMixParams] will be used internally (Uint8Array).
-//   - args[5] - JSON of a slice of public keys of users that should receive
-//     mobile notifications for the message.
-//
-// Example slice of public keys:
-//
-//	[
-//	  "FgJMvgSsY4rrKkS/jSe+vFOJOs5qSSyOUSW7UtF9/KU=",
-//	  "fPqcHtrJ398PAC35QyWXEU9PHzz8Z4BKQTCxSvpSygw=",
-//	  "JnjCgh7g/+hNiI9VPKW01aRSxGOFmNulNCymy3ImXAo="
-//	]
+//   - args[6] - pingBytes - An array of public keys of users that
+//     should receive mobile notifications for the message (JSON of
+//     []Uint8Array list).
 //
 // Returns a promise:
 //   - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array).
@@ -1127,11 +1098,16 @@ func (cm *ChannelsManager) SendReply(_ js.Value, args []js.Value) any {
 	messageToReactTo := utils.CopyBytesToGo(args[2])
 	leaseTimeMS := int64(args[3].Int())
 	cmixParamsJSON := utils.CopyBytesToGo(args[4])
-	pingsJSON := utils.CopyBytesToGo(args[5])
+	var pingBytes [][]byte
 
 	promiseFn := func(resolve, reject func(args ...any) js.Value) {
+		err := json.Unmarshal(utils.CopyBytesToGo(args[6]), pingBytes)
+		if err != nil {
+			reject(exception.NewTrace(err))
+		}
 		sendReport, err := cm.api.SendReply(marshalledChanId, msg,
-			messageToReactTo, leaseTimeMS, cmixParamsJSON, pingsJSON)
+			messageToReactTo, leaseTimeMS, cmixParamsJSON,
+			pingBytes)
 		if err != nil {
 			reject(exception.NewTrace(err))
 		} else {
@@ -1164,20 +1140,26 @@ func (cm *ChannelsManager) SendReply(_ js.Value, args []js.Value) any {
 //     be enumerated here. Use [ValidForever] to last the max message life.
 //   - args[4] - JSON of [xxdk.CMIXParams]. If left empty
 //     [bindings.GetDefaultCMixParams] will be used internally (Uint8Array).
+//   - args[5] - pingBytes - An array of public keys of users that
+//     should receive mobile notifications for the message (JSON of
+//     []Uint8Array list).
 //
 // Returns a promise:
 //   - Resolves to the JSON of [bindings.ChannelSendReport] (Uint8Array).
 //   - Rejected with an error if sending fails.
 func (cm *ChannelsManager) SendReaction(_ js.Value, args []js.Value) any {
-	var (
-		marshalledChanId = utils.CopyBytesToGo(args[0])
-		reaction         = args[1].String()
-		messageToReactTo = utils.CopyBytesToGo(args[2])
-		leaseTimeMS      = int64(args[3].Int())
-		cmixParamsJSON   = utils.CopyBytesToGo(args[4])
-	)
+	marshalledChanId := utils.CopyBytesToGo(args[0])
+	reaction := args[1].String()
+	messageToReactTo := utils.CopyBytesToGo(args[2])
+	leaseTimeMS := int64(args[3].Int())
+	cmixParamsJSON := utils.CopyBytesToGo(args[4])
+	var pingBytes [][]byte
 
 	promiseFn := func(resolve, reject func(args ...any) js.Value) {
+		err := json.Unmarshal(utils.CopyBytesToGo(args[6]), pingBytes)
+		if err != nil {
+			reject(exception.NewTrace(err))
+		}
 		sendReport, err := cm.api.SendReaction(marshalledChanId, reaction,
 			messageToReactTo, leaseTimeMS, cmixParamsJSON)
 		if err != nil {
@@ -1585,17 +1567,18 @@ func (cm *ChannelsManager) GetMutedUsers(_ js.Value, args []js.Value) any {
 // Notifications                                                              //
 ////////////////////////////////////////////////////////////////////////////////
 
-// GetNotificationLevel returns the [channels.NotificationLevel] for the given
-// channel.
+// GetNotificationLevel implements
+// [bindings.ChannelsManager.GetNotificationLevel]
 //
 // Parameters:
-//   - args[0] - The marshalled bytes of the channel's [id.ID] (Uint8Array).
+//   - args[0] - channelIDBytes - The marshalled bytes of the
+//     channel's [id.ID] (Uint8Array)
 //
 // Returns:
-//   - The [channels.NotificationLevel] for the channel (int).
-//   - Throws an error if the channel ID cannot be unmarshalled or the channel
-//     cannot be found.
-func (cm *ChannelsManager) GetNotificationLevel(_ js.Value, args []js.Value) any {
+//   - int - The [channels.NotificationLevel] for the channel.
+//     throws an error if there is an issue
+func (cm *ChannelsManager) GetNotificationLevel(_ js.Value,
+	args []js.Value) any {
 	channelIDBytes := utils.CopyBytesToGo(args[0])
 
 	level, err := cm.api.GetNotificationLevel(channelIDBytes)
@@ -1607,116 +1590,59 @@ func (cm *ChannelsManager) GetNotificationLevel(_ js.Value, args []js.Value) any
 	return level
 }
 
-// SetMobileNotificationsLevel sets the notification level for the given
-// channel. The [channels.NotificationLevel] dictates the type of notifications
-// received and the status controls weather the notification is push or in-app.
-// If muted, both the level and status must be set to mute.
-//
-// To use push notifications, a token must be registered with the notification
-// manager. Note, when enabling push notifications, information may be shared
-// with third parties (i.e., Firebase and Google's Palantir) and may represent a
-// security risk to the user.
+// SetMobileNotificationsLevel implements
+// [bindings.ChannelsManager.SetMobileNotificationsLevel]
 //
 // Parameters:
-//   - args[0] - The marshalled bytes of the channel's [id.ID] (Uint8Array).
-//   - args[1] - The [channels.NotificationLevel] to set for the channel (int).
-//   - args[2] - The [notifications.NotificationState] to set for the channel
-//     (int).
-//
-// Returns:
-//   - Throws an error if setting the notification level fails.
-func (cm *ChannelsManager) SetMobileNotificationsLevel(_ js.Value, args []js.Value) any {
+//   - args[0] - channelIDBytes - The marshaled bytes of the channel's [id.ID]
+//     (Uint8Array).
+//   - args[1] - level - The [channels.NotificationLevel] to set for
+//     the channel.
+//   - args[2] - status - The [notifications.NotificationState] to set
+//     for the channel.
+//   - args[3] - push - True to enable push notifications and false to
+//     only have in-app notifications.
+//
+// Returns nothing or throws an error
+func (cm *ChannelsManager) SetMobileNotificationsLevel(_ js.Value,
+	args []js.Value) any {
 	channelIDBytes := utils.CopyBytesToGo(args[0])
 	level := args[1].Int()
 	status := args[2].Int()
+	push := args[3].Bool()
 
-	err := cm.api.SetMobileNotificationsLevel(channelIDBytes, level, status)
+	err := cm.api.SetMobileNotificationsLevel(channelIDBytes, level,
+		status, push)
 	if err != nil {
 		exception.ThrowTrace(err)
-		return nil
 	}
-
 	return nil
 }
 
-// GetNotificationReportsForMe checks the notification data against the filter
-// list to determine which notifications belong to the user. A list of
-// notification reports is returned detailing all notifications for the user.
+// GetNotificationReportsForMe implements
+// [bindings.GetNotificationsReportsForMe]
 //
 // Parameters:
-//   - notificationFilterJSON - JSON of a slice of [channels.NotificationFilter].
-//   - notificationDataJSON - JSON of a slice of [notifications.Data].
-//
-// Example JSON of a slice of [channels.NotificationFilter]:
-// [
-//
-//	  {
-//	    "identifier": "O8NUg0KaDo18ybTKajXM/sgqEYS37+lewPhGV/2sMAUDYXN5bUlkZW50aWZpZXI=",
-//	    "channelID": "O8NUg0KaDo18ybTKajXM/sgqEYS37+lewPhGV/2sMAUD",
-//	    "tags": ["6de69009a93d53793ee344e8fb48fae194eaf51861d3cc51c7348c337d13aedf-usrping"],
-//	    "allowLists": {
-//	      "allowWithTags": {},
-//	      "allowWithoutTags": {"102":{}, "2":{}}
-//	    }
-//	  },
-//	  {
-//	    "identifier": "O8NUg0KaDo18ybTKajXM/sgqEYS37+lewPhGV/2sMAUDc3ltSWRlbnRpZmllcg==",
-//	    "channelID": "O8NUg0KaDo18ybTKajXM/sgqEYS37+lewPhGV/2sMAUD",
-//	    "tags": ["6de69009a93d53793ee344e8fb48fae194eaf51861d3cc51c7348c337d13aedf-usrping"],
-//	    "allowLists": {
-//	      "allowWithTags": {},
-//	      "allowWithoutTags": {"1":{}, "40000":{}}
-//	    }
-//	  },
-//	  {
-//	    "identifier": "jCRgFRQvzzKOb8DJ0fqCRLgr9kiHN9LpqHXVhyHhhlQDYXN5bUlkZW50aWZpZXI=",
-//	    "channelID": "jCRgFRQvzzKOb8DJ0fqCRLgr9kiHN9LpqHXVhyHhhlQD",
-//	    "tags": ["6de69009a93d53793ee344e8fb48fae194eaf51861d3cc51c7348c337d13aedf-usrping"],
-//	    "allowLists": {
-//	      "allowWithTags": {},
-//	      "allowWithoutTags": {"102":{}, "2":{}}
-//	    }
-//	  }
-//	]
-//
-// Example JSON of a slice of [notifications.Data]:
-//
-//	[
-//	  {
-//	    "EphemeralID": -6475,
-//	    "RoundID": 875,
-//	    "IdentityFP": "jWG/UuxRjD80HEo0WX3KYIag5LCfgaWKAg==",
-//	    "MessageHash": "hDGE46QWa3d70y5nJTLbEaVmrFJHOyp2"
-//	  },
-//	  {
-//	    "EphemeralID": -2563,
-//	    "RoundID": 875,
-//	    "IdentityFP": "gL4nhCGKPNBm6YZ7KC0v4JThw65N9bRLTQ==",
-//	    "MessageHash": "WcS4vGrSWDK8Kj7JYOkMo8kSh1Xti94V"
-//	  },
-//	  {
-//	    "EphemeralID": -13247,
-//	    "RoundID": 875,
-//	    "IdentityFP": "qV3uD++VWPhD2rRMmvrP9j8hp+jpFSsUHg==",
-//	    "MessageHash": "VX6Tw7N48j7U2rRXYle20mFZi0If4CB1"
-//	  }
-//	]
+//   - args[0] - notificationFilterJSON - JSON of a slice of
+//     [channels.NotificationFilter] (Uint8Array).
+//   - args[1] - notificationDataJSON - JSON of a slice of
+//     [notifications.Data] (Uint8Array).
 //
 // Returns:
-//   - The JSON of a slice of [channels.NotificationReport] (Uint8Array).
-//   - Throws an error if getting the report fails.
+//   - []byte - JSON of a slice of [channels.NotificationReport].
+//     Throws an error if one occurs
 func GetNotificationReportsForMe(_ js.Value, args []js.Value) any {
 	notificationFilterJSON := utils.CopyBytesToGo(args[0])
 	notificationDataJSON := utils.CopyBytesToGo(args[1])
 
-	report, err := bindings.GetNotificationReportsForMe(
-		notificationFilterJSON, notificationDataJSON)
+	nrs, err := bindings.GetNotificationReportsForMe(notificationFilterJSON,
+		notificationDataJSON)
 	if err != nil {
 		exception.ThrowTrace(err)
 		return nil
 	}
 
-	return utils.CopyBytesToJS(report)
+	return utils.CopyBytesToJS(nrs)
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -2465,6 +2391,8 @@ type channelUI struct {
 	eventUpdate func(args ...any) js.Value
 }
 
-func (c *channelUI) EventUpdate(eventType int64, jsonData []byte) {
-	c.eventUpdate(int(eventType), utils.CopyBytesToJS(jsonData))
+// EventUpdate implements
+// [bindings.ChannelUICallbacks.EventUpdate].
+func (c *channelUI) EventUpdate(eventType int64, dataJson []byte) {
+	c.eventUpdate(eventType, utils.CopyBytesToJS(dataJson))
 }
diff --git a/wasm/collective.go b/wasm/collective.go
index 932926d34d878bb042628125d271f9ce5b2a8dee..294fda36577133ee6da47e0615583770640b7410 100644
--- a/wasm/collective.go
+++ b/wasm/collective.go
@@ -14,6 +14,7 @@ import (
 	"syscall/js"
 
 	"gitlab.com/elixxir/client/v4/bindings"
+	"gitlab.com/elixxir/wasm-utils/exception"
 	"gitlab.com/elixxir/wasm-utils/utils"
 )
 
diff --git a/wasm/e2eHandler.go b/wasm/e2eHandler.go
index ae3eb14c01991606c764022b9983c788bf36b81f..fd107b0b1390a9ec759e0cdfaf0a6544ee97d3e6 100644
--- a/wasm/e2eHandler.go
+++ b/wasm/e2eHandler.go
@@ -10,9 +10,10 @@
 package wasm
 
 import (
+	"syscall/js"
+
 	"gitlab.com/elixxir/wasm-utils/exception"
 	"gitlab.com/elixxir/wasm-utils/utils"
-	"syscall/js"
 )
 
 // GetReceptionID returns the marshalled default IDs.
@@ -200,16 +201,19 @@ type processor struct {
 //
 // Parameters:
 //   - message - Returns the message contents (Uint8Array).
-//   - tags - (Uint8Array).
-//   - metadata - (Uint8Array).
+//   - tags - a byte array representing the tags on the message (Uint8Array)
+//   - metadata - other arbitrary metadata (Uint8Array)
 //   - receptionId - Returns the marshalled bytes of the sender's [id.ID]
 //     (Uint8Array).
 //   - ephemeralId - Returns the ephemeral ID of the sender (int).
 //   - roundId - Returns the ID of the round sent on (int).
 func (p *processor) Process(message, tags, metadata, receptionId []byte,
-	ephemeralId, roundId int64) {
-	p.process(utils.CopyBytesToJS(message), utils.CopyBytesToJS(tags),
-		utils.CopyBytesToJS(metadata), utils.CopyBytesToJS(receptionId),
+	ephemeralId int64, roundId int64) {
+
+	p.process(utils.CopyBytesToJS(message),
+		utils.CopyBytesToJS(tags),
+		utils.CopyBytesToJS(metadata),
+		utils.CopyBytesToJS(receptionId),
 		ephemeralId, roundId)
 }
 
@@ -236,7 +240,9 @@ func (p *processor) String() string {
 //   - Throws TypeError if registering the service fails.
 func (e *E2e) AddService(_ js.Value, args []js.Value) any {
 	p := &processor{
-		utils.WrapCB(args[1], "Process"), utils.WrapCB(args[1], "String")}
+		utils.WrapCB(args[1], "Process"),
+		utils.WrapCB(args[1], "String"),
+	}
 
 	err := e.api.AddService(args[0].String(), p)
 	if err != nil {
diff --git a/wasm/follow.go b/wasm/follow.go
index 992596fc2cf80d543febdcd6facec9b658479f11..cfc49d4241bb0b87eb184685b4f521daa7105f03 100644
--- a/wasm/follow.go
+++ b/wasm/follow.go
@@ -10,10 +10,11 @@
 package wasm
 
 import (
+	"syscall/js"
+
 	"gitlab.com/elixxir/wasm-utils/exception"
 	"gitlab.com/elixxir/wasm-utils/utils"
 	"gitlab.com/elixxir/xxdk-wasm/storage"
-	"syscall/js"
 )
 
 // StartNetworkFollower kicks off the tracking of the network. It starts long-
@@ -381,21 +382,22 @@ func (tsc *trackServicesCallback) Callback(marshalData []byte, err error) {
 	tsc.callback(utils.CopyBytesToJS(marshalData), exception.NewTrace(err))
 }
 
-// trackCompressedServicesCallback adheres to the
-// [bindings.TrackCompressedServicesCallback] interface.
+// trackServicesCallback adheres to the [bindings.TrackServicesCallback]
+// interface.
 type trackCompressedServicesCallback struct {
 	callback func(args ...any) js.Value
 }
 
-// Callback is the callback for [Cmix.TrackServices] that passes a
-// JSON-marshalled list of compressed backend services. If an error occurs while
-// retrieving or marshalling the service list, then err will be non-null.
+// Callback is the callback for [Cmix.TrackCompressedServices]. This
+// will pass to the user a JSON-marshalled list of backend
+// services. If there was an error retrieving or marshalling the
+// service list, there is an error for the second parameter, which
+// will be non-null.
 //
 // Parameters:
-//   - marshalData - JSON of [message.CompressedServiceList] (Uint8Array),
-//     which is a map of [id.ID] to an array of [message.CompressedService].
-//   - err - Error that occurs during retrieval or marshalling. Null otherwise
-//     (Error).
+//   - marshalData - Returns the JSON of
+//     [message.CompressedServiceList] (Uint8Array).
+//   - err - Returns an error on failure (Error).
 //
 // Example JSON:
 //
@@ -422,8 +424,9 @@ type trackCompressedServicesCallback struct {
 //	     }
 //	   ]
 //	 }
-func (tsc *trackCompressedServicesCallback) Callback(marshalData []byte, err error) {
-	tsc.callback(utils.CopyBytesToJS(marshalData), exception.NewTrace(err))
+func (tcsc *trackCompressedServicesCallback) Callback(marshalData []byte,
+	err error) {
+	tcsc.callback(utils.CopyBytesToJS(marshalData), exception.NewTrace(err))
 }
 
 // TrackServicesWithIdentity will return via a callback the list of services the
@@ -434,17 +437,20 @@ func (tsc *trackCompressedServicesCallback) Callback(marshalData []byte, err err
 // Parameters:
 //   - args[0] - ID of [E2e] object in tracker (int).
 //   - args[1] - Javascript object that has functions that implement the
-//     [bindings.ClientError] interface.
-//   - args[2] - Javascript object that has functions that implement the
-//     [bindings.TrackCompressedServicesCallback], which will be passed the JSON
-//     of [message.CompressedServiceList].
+//     [bindings.TrackServicesCallback] interface.
+//   - args[1] - Javascript object that has functions that implement the
+//     [bindings.TrackCompressedServicesCallback] interface.
 //
 // Returns:
 //   - Throws TypeError if the [E2e] ID is invalid.
 func (c *Cmix) TrackServicesWithIdentity(_ js.Value, args []js.Value) any {
 	err := c.api.TrackServicesWithIdentity(args[0].Int(),
-		&trackServicesCallback{utils.WrapCB(args[0], "Callback")},
-		&trackCompressedServicesCallback{utils.WrapCB(args[0], "Callback")})
+		&trackServicesCallback{
+			utils.WrapCB(args[0], "Callback"),
+		},
+		&trackCompressedServicesCallback{
+			utils.WrapCB(args[0], "Callback"),
+		})
 	if err != nil {
 		exception.ThrowTrace(err)
 		return nil
diff --git a/wasm/notifications.go b/wasm/notifications.go
new file mode 100644
index 0000000000000000000000000000000000000000..2a4887292d140e22bbb8b14ee8d87ce1a72fbdff
--- /dev/null
+++ b/wasm/notifications.go
@@ -0,0 +1,131 @@
+////////////////////////////////////////////////////////////////////////////////
+// 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
+
+package wasm
+
+import (
+	"syscall/js"
+
+	"gitlab.com/elixxir/client/v4/bindings"
+	"gitlab.com/elixxir/client/v4/notifications"
+	"gitlab.com/elixxir/wasm-utils/exception"
+)
+
+type Notifications struct {
+	api bindings.Notifications
+}
+
+// newNotificationsJS wrapts the bindings Noticiation object and implements
+// wrappers in JS for all it's functionality.
+func newNotificationsJS(api bindings.Notifications) map[string]any {
+	n := Notifications{api}
+	notificationsImplJS := map[string]any{
+		"AddToken":    js.FuncOf(n.AddToken),
+		"RemoveToken": js.FuncOf(n.RemoveToken),
+		"SetMaxState": js.FuncOf(n.SetMaxState),
+		"GetMaxState": js.FuncOf(n.GetMaxState),
+		"GetID":       js.FuncOf(n.GetID),
+	}
+	return notificationsImplJS
+}
+
+// LoadNotifications returns a JS wrapped implementation of
+// [bindings.Notifications].
+//
+// Parameters:
+//   - args[0] - the cMixID integer
+//
+// Returns a notifications object or throws an error
+func LoadNotifications(_ js.Value, args []js.Value) any {
+	cMixID := args[0].Int()
+	api, err := bindings.LoadNotifications(cMixID)
+	if err != nil {
+		exception.ThrowTrace(err)
+		return nil
+	}
+
+	return newNotificationsJS(api)
+}
+
+// LoadNotificationsDummy returns a JS wrapped implementation of
+// [bindings.Notifications] with a dummy notifications implementation.
+//
+// Parameters:
+//   - args[0] - the cMixID integer
+//
+// Returns a notifications object or throws an error
+func LoadNotificationsDummy(_ js.Value, args []js.Value) any {
+	cMixID := args[0].Int()
+	api, err := bindings.LoadNotificationsDummy(cMixID)
+	if err != nil {
+		exception.ThrowTrace(err)
+		return nil
+	}
+
+	return newNotificationsJS(api)
+}
+
+// GetID returns the bindings ID for the [bindings.Notifications] object
+func (n *Notifications) GetID(js.Value, []js.Value) any {
+	return n.api.GetID()
+}
+
+// AddToken implements [bindings.Notifications.AddToken].
+//
+// Parameters:
+//   - args[0] - newToken string
+//   - args[1] - app string
+//
+// Returns nothing or an error (throwable)
+func (n *Notifications) AddToken(_ js.Value, args []js.Value) any {
+	newToken := args[0].String()
+	app := args[1].String()
+
+	err := n.api.AddToken(newToken, app)
+	if err != nil {
+		exception.ThrowTrace(err)
+	}
+
+	return nil
+}
+
+// RemoveToken implements [bindings.Notifications.RemoveToken].
+//
+// Returns nothing or throws an error.
+func (n *Notifications) RemoveToken(_ js.Value, args []js.Value) any {
+	err := n.api.RemoveToken()
+	if err != nil {
+		exception.ThrowTrace(err)
+	}
+	return nil
+}
+
+// SetMaxState implements [bindings.Notifications.SetMaxState]
+//
+// Parameters:
+//   - args[0] - maxState integer
+//
+// Returns nothing or throws an error
+func (n *Notifications) SetMaxState(_ js.Value, args []js.Value) any {
+	maxState := int64(args[0].Int())
+
+	err := n.api.SetMaxState(notifications.NotificationState(maxState))
+	if err != nil {
+		exception.ThrowTrace(err)
+	}
+
+	return nil
+}
+
+// GetMaxState implements [bindings.Notifications.GetMaxState]
+//
+// Returns the current maxState integer
+func (n *Notifications) GetMaxState(_ js.Value, args []js.Value) any {
+	return int64(n.api.GetMaxState())
+}