diff --git a/bindings/channels.go b/bindings/channels.go
index cf179b34a951e332e4042bad3ddc6bc196db18c4..1144e3f1a797ca99dba88511e6aab9efa1127ce9 100644
--- a/bindings/channels.go
+++ b/bindings/channels.go
@@ -739,3 +739,179 @@ func (cm *ChannelsManager) RegisterReceiveHandler(messageType int,
 	// Register handler
 	return cm.api.RegisterReceiveHandler(channels.MessageType(messageType), cb)
 }
+
+// EventModel is an interface which an external party which uses the channels
+// system passed an object which adheres to in order to get events on the channel.
+type EventModel interface {
+	// JoinChannel is called whenever a channel is joined locally.
+	//
+	// Parameters:
+	//  - channel is the pretty print representation of a channel.
+	JoinChannel(channel string)
+
+	// LeaveChannel is called whenever a channel is left locally.
+	//
+	// Parameters:
+	//  - ChannelId is the marshalled chenn
+	// This will receive a marshalled channel ID.
+	LeaveChannel(channelID []byte)
+
+	// ReceiveMessage is called whenever a message is received on a given channel
+	// It may be called multiple times on the same message, it is incumbent on
+	// the user of the API to filter such called by message ID.
+	//
+	// Parameters:
+	//  - ChannelID is the marshalled channel ID.
+	//  - MessageID is the marshalled message ID of the received message.
+	//  - senderUsername is the username of the sender of the message.
+	//  - text is the content of the message.
+	//  - Timestamp is time the message was received, represented as
+	//    nanoseconds since unix epoch.
+	//  - Lease is a number of nanoseconds that the message is valid for.
+	//  - Status is the status of the message.
+	//    Statuses will be enumerated as such:
+	//     Sent 		- 0
+	//     Delivered 	- 1
+	//     Failed 		- 2
+	ReceiveMessage(channelID []byte, messageID []byte,
+		senderUsername string, text string, timestamp int64,
+		lease int64, roundId int64, status int64)
+
+	// ReceiveReply is called whenever a message is received which is a reply
+	// on a given channel. It may be called multiple times on the same message,
+	// it is incumbent on the user of the API to filter such called by message ID
+	// Messages may arrive out of order, so a reply in theory can arrive before
+	// the initial message, as a result it may be important to buffer replies.
+	//
+	// Parameters:
+	//  - ChannelID is the marshalled channel ID.
+	//  - MessageID is the marshalled message ID of the received message.
+	//  - reactionTo is the message ID for the message that received a reply.
+	//  - senderUsername is the username of the sender of the message.
+	//  - text is the content of the message, in this case a reply.
+	//  - Timestamp is time the message was received, represented as
+	//    nanoseconds since unix epoch.
+	//  - Lease is a number of nanoseconds that the message is valid for.
+	//  - Status is the status of the message.
+	//    Statuses will be enumerated as such:
+	//     Sent 		- 0
+	//     Delivered 	- 1
+	//     Failed 		- 2
+	ReceiveReply(channelID []byte, messageID []byte,
+		reactionTo []byte, senderUsername string,
+		text string, timestamp int64, lease int64,
+		roundId int64, status int64)
+
+	// ReceiveReaction is called whenever a reaction to a message is received
+	// on a given channel. It may be called multiple times on the same reaction,
+	// it is incumbent on the user of the API to filter such called by message ID
+	// Messages may arrive our of order, so a reply in theory can arrive before
+	// the initial message, as a result it may be important to buffer reactions.
+	//
+	// Parameters: //todo: enumerate all arguments
+	//  - ChannelID is the marshalled channel ID.
+	//  - MessageID is the marshalled message ID of the received message.
+	//  - reactionTo is the message ID for the message that received a reaction.
+	//  - senderUsername is the username of the sender of the message.
+	//  - reaction is the content of the message, in this case a reaction.
+	//  - Timestamp is time the message was received, represented as
+	//    nanoseconds since unix epoch.
+	//  - Lease is a number of nanoseconds that the message is valid for.
+	//  - Status is the status of the message.
+	//    Statuses will be enumerated as such:
+	//     Sent 		- 0
+	//     Delivered 	- 1
+	//     Failed 		- 2
+	ReceiveReaction(channelID []byte, messageID []byte,
+		reactionTo []byte, senderUsername string,
+		reaction string, timestamp int64, lease int64,
+		round int64, status int64)
+
+	// UpdateSentStatus is called whenever the sent status of a message
+	// has changed.
+	//
+	//  - Status is the status of the message.
+	//    Statuses will be enumerated as such:
+	//     Sent 		- 0
+	//     Delivered 	- 1
+	//     Failed 		- 2
+	UpdateSentStatus(messageID []byte, status int64)
+
+	//unimplemented
+	//IgnoreMessage(ChannelID *id.ID, MessageID cryptoChannel.MessageID)
+	//UnIgnoreMessage(ChannelID *id.ID, MessageID cryptoChannel.MessageID)
+	//PinMessage(ChannelID *id.ID, MessageID cryptoChannel.MessageID, end time.Time)
+	//UnPinMessage(ChannelID *id.ID, MessageID cryptoChannel.MessageID)
+}
+
+// toEventModel is a wrapper which wraps an existing EventModel object.
+type toEventModel struct {
+	em EventModel
+}
+
+// NewEventModel is a constructor for a toEventModel. This will take in the
+// passed EventModel and wraps it.
+func NewEventModel(em EventModel) *toEventModel {
+	return &toEventModel{em: em}
+}
+
+// JoinChannel is called whenever a channel is joined locally.
+func (tem *toEventModel) JoinChannel(channel *cryptoBroadcast.Channel) {
+	tem.em.JoinChannel(channel.PrettyPrint())
+}
+
+// LeaveChannel is called whenever a channel is left locally.
+func (tem *toEventModel) LeaveChannel(channelID *id.ID) {
+	tem.em.LeaveChannel(channelID[:])
+}
+
+// ReceiveMessage is called whenever a message is received on a given channel
+// It may be called multiple times on the same message, it is incumbent on
+// the user of the API to filter such called by message ID.
+func (tem *toEventModel) ReceiveMessage(channelID *id.ID,
+	messageID cryptoChannel.MessageID, senderUsername string, text string,
+	timestamp time.Time, lease time.Duration, round rounds.Round,
+	status channels.SentStatus) {
+
+	tem.em.ReceiveMessage(channelID[:], messageID[:], senderUsername, text,
+		timestamp.UnixNano(), int64(lease), int64(round.ID), int64(status))
+}
+
+// ReceiveReply is called whenever a message is received which is a reply
+// on a given channel. It may be called multiple times on the same message,
+// it is incumbent on the user of the API to filter such called by message ID
+// Messages may arrive our of order, so a reply in theory can arrive before
+// the initial message, as a result it may be important to buffer replies.
+func (tem *toEventModel) ReceiveReply(channelID *id.ID,
+	messageID cryptoChannel.MessageID,
+	reactionTo cryptoChannel.MessageID, senderUsername string,
+	text string, timestamp time.Time, lease time.Duration,
+	round rounds.Round, status channels.SentStatus) {
+
+	tem.em.ReceiveReply(channelID[:], messageID[:], reactionTo[:],
+		senderUsername, text, timestamp.UnixNano(), int64(lease),
+		int64(round.ID), int64(status))
+
+}
+
+// ReceiveReaction is called whenever a reaction to a message is received
+// on a given channel. It may be called multiple times on the same reaction,
+// it is incumbent on the user of the API to filter such called by message ID
+// Messages may arrive our of order, so a reply in theory can arrive before
+// the initial message, as a result it may be important to buffer reactions.
+func (tem *toEventModel) ReceiveReaction(channelID *id.ID,
+	messageID cryptoChannel.MessageID, reactionTo cryptoChannel.MessageID,
+	senderUsername string, reaction string, timestamp time.Time,
+	lease time.Duration, round rounds.Round, status channels.SentStatus) {
+
+	tem.em.ReceiveReaction(channelID[:], messageID[:], reactionTo[:],
+		senderUsername, reaction, timestamp.UnixNano(), int64(lease),
+		int64(round.ID), int64(status))
+}
+
+// UpdateSentStatus is called whenever the sent status of a message
+// has changed.
+func (tem *toEventModel) UpdateSentStatus(messageID cryptoChannel.MessageID,
+	status channels.SentStatus) {
+	tem.em.UpdateSentStatus(messageID[:], int64(status))
+}
diff --git a/go.mod b/go.mod
index 9ae5d293a28e75f720e602688149c0f011bf6ed2..be1f897dd2c64c1c6559681d8034e8926d1c5a71 100644
--- a/go.mod
+++ b/go.mod
@@ -15,7 +15,7 @@ require (
 	github.com/stretchr/testify v1.8.0
 	gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f
 	gitlab.com/elixxir/comms v0.0.4-0.20220913220502-eed192f654bd
-	gitlab.com/elixxir/crypto v0.0.7-0.20220919174648-8d1b7f5cacc4
+	gitlab.com/elixxir/crypto v0.0.7-0.20220919221444-cb6c054c9fcd
 	gitlab.com/elixxir/ekv v0.2.1
 	gitlab.com/elixxir/primitives v0.0.3-0.20220901220638-1acc75fabdc6
 	gitlab.com/xx_network/comms v0.0.4-0.20220913215811-c4bf83b27de3
diff --git a/go.sum b/go.sum
index fe9874ef3c78d9e1734ce774e87408df3ca997b2..0b49183c949beb397cac32e79af9562f0dd47354 100644
--- a/go.sum
+++ b/go.sum
@@ -647,6 +647,8 @@ gitlab.com/elixxir/crypto v0.0.7-0.20220919170559-538d10454d07 h1:zIUAxKXpGnAejP
 gitlab.com/elixxir/crypto v0.0.7-0.20220919170559-538d10454d07/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok=
 gitlab.com/elixxir/crypto v0.0.7-0.20220919174648-8d1b7f5cacc4 h1:Gou55kAKhwWlK9hKFYAfOMrwgk04qpOsB5/tZa8OWlc=
 gitlab.com/elixxir/crypto v0.0.7-0.20220919174648-8d1b7f5cacc4/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok=
+gitlab.com/elixxir/crypto v0.0.7-0.20220919221444-cb6c054c9fcd h1:uWcp0aokdBnaZhNhlbXiDYusecIP5AaFbJfBtuzEg5A=
+gitlab.com/elixxir/crypto v0.0.7-0.20220919221444-cb6c054c9fcd/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok=
 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/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=