diff --git a/bindings/group.go b/bindings/group.go
index 3f2976941070fe7aedfc1f7d01bda91df22385e1..3fce2e43b790c06dc64e0eb15490b5d795746060 100644
--- a/bindings/group.go
+++ b/bindings/group.go
@@ -47,23 +47,18 @@ func NewGroupManager(client *Client, requestFunc GroupRequestFunc,
 	}
 
 	// Create a new group chat manager
+	// TODO: Need things from storage, services, etc?
 	m, err := gc.NewManager(&client.api, requestCallback, receiveCallback)
 	if err != nil {
 		return nil, err
 	}
 
-	// Start group request and message retrieval workers
-	err = client.api.AddService(m.StartProcesses)
-	if err != nil {
-		return nil, err
-	}
-
 	return &GroupChat{m}, nil
 }
 
 // MakeGroup creates a new group and sends a group request to all members in the
 // group. The ID of the new group, the rounds the requests were sent on, and the
-// status of the send are contained in NewGroupReport.
+// status of the sends are contained in NewGroupReport.
 func (g *GroupChat) MakeGroup(membership *IdList, name, message []byte) *NewGroupReport {
 	grp, rounds, status, err := g.m.MakeGroup(membership.list, name, message)
 	errStr := ""
@@ -346,6 +341,7 @@ func (gm *GroupMembership) Get(i int) (*GroupMember, error) {
 ////
 // Member Structure
 ////
+
 // GroupMember represents a member in the group membership list.
 type GroupMember struct {
 	group.Member
diff --git a/groupChat/makeGroup.go b/groupChat/makeGroup.go
index 513ba3643713fd88668ce14a0a46ac91ee3e573d..65fb48a66deffbbbd9c70713fcf377dfe6d14a3e 100644
--- a/groupChat/makeGroup.go
+++ b/groupChat/makeGroup.go
@@ -10,9 +10,7 @@ package groupChat
 import (
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
-	"gitlab.com/elixxir/client/catalog"
 	gs "gitlab.com/elixxir/client/groupChat/groupStore"
-	"gitlab.com/elixxir/client/storage/edge"
 	"gitlab.com/elixxir/crypto/contact"
 	"gitlab.com/elixxir/crypto/fastRNG"
 	"gitlab.com/elixxir/crypto/group"
@@ -94,12 +92,7 @@ func (m Manager) MakeGroup(membership []*id.ID, name, msg []byte) (gs.Group,
 	roundIDs, status, err := m.sendRequests(g)
 
 	if err == nil {
-		edgeStore := m.store.GetEdge()
-		edgeStore.Add(edge.Preimage{
-			Data:   g.ID[:],
-			Type:   catalog.Group,
-			Source: g.ID[:],
-		}, m.store.GetUser().ReceptionID)
+		err = m.JoinGroup(g)
 	}
 
 	return g, roundIDs, status, err
@@ -119,14 +112,13 @@ func (m Manager) buildMembership(members []*id.ID) (group.Membership,
 			errors.Errorf(maxMembersErr, len(members), group.MaxParticipants)
 	}
 
-	grp := m.store.E2e().GetGroup()
 	dkl := make(gs.DhKeyList, len(members))
 
 	// Lookup partner contact objects from their ID
 	contacts := make([]contact.Contact, len(members))
 	var err error
 	for i, uid := range members {
-		partner, err := m.store.E2e().GetPartner(uid)
+		partner, err := m.e2e.GetPartner(uid, m.receptionId)
 		if err != nil {
 			return nil, nil, errors.Errorf(getPartnerErr, uid, err)
 		}
@@ -139,7 +131,7 @@ func (m Manager) buildMembership(members []*id.ID) (group.Membership,
 		dkl.Add(partner.GetMyOriginPrivateKey(), group.Member{
 			ID:    partner.GetPartnerID(),
 			DhKey: partner.GetPartnerOriginPublicKey(),
-		}, grp)
+		}, m.grp)
 	}
 
 	// Create new Membership from contact list and client's own contact.
diff --git a/groupChat/manager.go b/groupChat/manager.go
index b79631f9553ab792f54380814c9c99527b0062c2..7c038c16070820ebdfe6e746c0978e6992cb424d 100644
--- a/groupChat/manager.go
+++ b/groupChat/manager.go
@@ -10,14 +10,12 @@ package groupChat
 import (
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
-	"gitlab.com/elixxir/client/api"
 	"gitlab.com/elixxir/client/catalog"
+	"gitlab.com/elixxir/client/e2e"
 	gs "gitlab.com/elixxir/client/groupChat/groupStore"
 	"gitlab.com/elixxir/client/interfaces"
-	"gitlab.com/elixxir/client/interfaces/message"
-	"gitlab.com/elixxir/client/stoppable"
-	"gitlab.com/elixxir/client/storage"
-	"gitlab.com/elixxir/client/storage/edge"
+	"gitlab.com/elixxir/client/network"
+	"gitlab.com/elixxir/client/network/message"
 	"gitlab.com/elixxir/client/storage/versioned"
 	"gitlab.com/elixxir/crypto/cyclic"
 	"gitlab.com/elixxir/crypto/fastRNG"
@@ -25,15 +23,6 @@ import (
 	"gitlab.com/xx_network/primitives/id"
 )
 
-const (
-	rawMessageBuffSize   = 100
-	receiveStoppableName = "GroupChatReceive"
-	receiveListenerName  = "GroupChatReceiveListener"
-	requestStoppableName = "GroupChatRequest"
-	requestListenerName  = "GroupChatRequestListener"
-	groupStoppableName   = "GroupChat"
-)
-
 // Error messages.
 const (
 	newGroupStoreErr = "failed to create new group store: %+v"
@@ -43,84 +32,68 @@ const (
 
 // Manager handles the list of groups a user is a part of.
 type Manager struct {
-	client *api.Client
-	store  *storage.Session
-	swb    interfaces.Switchboard
-	net    interfaces.NetworkManager
-	rng    *fastRNG.StreamGenerator
-	gs     *gs.Store
+	e2e e2e.Handler
+	net interfaces.NetworkManager
+
+	receptionId *id.ID
+	rng         *fastRNG.StreamGenerator
+	grp         *cyclic.Group
+	gs          *gs.Store
+	services    network.Manager
 
 	requestFunc RequestCallback
 	receiveFunc ReceiveCallback
 }
 
-// NewManager generates a new group chat manager. This functions satisfies the
-// GroupChat interface.
-func NewManager(client *api.Client, requestFunc RequestCallback,
-	receiveFunc ReceiveCallback) (*Manager, error) {
-	return newManager(
-		client,
-		client.GetUser().ReceptionID.DeepCopy(),
-		client.GetStorage().E2e().GetDHPublicKey(),
-		client.GetStorage(),
-		client.GetSwitchboard(),
-		client.GetNetworkInterface(),
-		client.GetRng(),
-		client.GetStorage().GetKV(),
-		requestFunc,
-		receiveFunc,
-	)
-}
-
-// newManager creates a new group chat manager from api.Client parts for easier
-// testing.
-func newManager(client *api.Client, userID *id.ID, userDhKey *cyclic.Int,
-	store *storage.Session, swb interfaces.Switchboard,
-	net interfaces.NetworkManager, rng *fastRNG.StreamGenerator,
-	kv *versioned.KV, requestFunc RequestCallback,
-	receiveFunc ReceiveCallback) (*Manager, error) {
+// NewManager creates a new group chat manager
+func NewManager(services network.Manager, e2e e2e.Handler, net interfaces.NetworkManager, receptionId *id.ID,
+	rng *fastRNG.StreamGenerator, grp *cyclic.Group, userDhKey *cyclic.Int,
+	kv *versioned.KV, requestFunc RequestCallback, receiveFunc ReceiveCallback) (*Manager, error) {
 
 	// Load the group chat storage or create one if one does not exist
 	gStore, err := gs.NewOrLoadStore(
-		kv, group.Member{ID: userID, DhKey: userDhKey})
+		kv, group.Member{ID: receptionId, DhKey: userDhKey})
 	if err != nil {
 		return nil, errors.Errorf(newGroupStoreErr, err)
 	}
 
-	return &Manager{
-		client:      client,
-		store:       store,
-		swb:         swb,
+	// Define the manager object
+	m := &Manager{
+		e2e:         e2e,
 		net:         net,
 		rng:         rng,
+		receptionId: receptionId,
+		grp:         grp,
 		gs:          gStore,
+		services:    services,
 		requestFunc: requestFunc,
 		receiveFunc: receiveFunc,
-	}, nil
-}
+	}
 
-// StartProcesses starts the reception worker.
-func (m *Manager) StartProcesses() (stoppable.Stoppable, error) {
-	// Start group reception worker
-	receiveStop := stoppable.NewSingle(receiveStoppableName)
-	receiveChan := make(chan message.Receive, rawMessageBuffSize)
-	m.swb.RegisterChannel(receiveListenerName, &id.ID{},
-		message.Raw, receiveChan)
-	go m.receive(receiveChan, receiveStop)
-
-	// Start group request worker
-	requestStop := stoppable.NewSingle(requestStoppableName)
-	requestChan := make(chan message.Receive, rawMessageBuffSize)
-	m.swb.RegisterChannel(requestListenerName, &id.ID{},
-		message.GroupCreationRequest, requestChan)
-	go m.receiveRequest(requestChan, requestStop)
-
-	// Create a multi stoppable
-	multiStoppable := stoppable.NewMulti(groupStoppableName)
-	multiStoppable.Add(receiveStop)
-	multiStoppable.Add(requestStop)
-
-	return multiStoppable, nil
+	// Register listener for incoming e2e group chat requests
+	e2e.RegisterListener(&id.ZeroUser, catalog.GroupCreationRequest, &requestListener{m: m})
+
+	// Register notifications listener for incoming e2e group chat requests
+	err = e2e.AddService(catalog.GroupRq, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	// Register all groups
+	for _, gId := range m.GetGroups() {
+		g, exists := m.GetGroup(gId)
+		if !exists {
+			jww.WARN.Printf("Unexpected failure to locate GroupID %s", gId.String())
+			continue
+		}
+
+		err = m.JoinGroup(g)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return m, nil
 }
 
 // JoinGroup adds the group to the list of group chats the user is a part of.
@@ -131,15 +104,14 @@ func (m Manager) JoinGroup(g gs.Group) error {
 		return errors.Errorf(joinGroupErr, g.ID, err)
 	}
 
-	edgeStore := m.store.GetEdge()
-	edgeStore.Add(edge.Preimage{
-		Data:   g.ID[:],
-		Type:   catalog.Group,
-		Source: g.ID[:],
-	}, m.store.GetUser().ReceptionID)
+	newService := message.Service{
+		Identifier: g.ID[:],
+		Tag:        catalog.Group,
+		Metadata:   g.ID[:],
+	}
+	m.services.AddService(m.receptionId, newService, &receptionProcessor{m: &m, g: g})
 
 	jww.DEBUG.Printf("Joined group %q with ID %s.", g.Name, g.ID)
-
 	return nil
 }
 
@@ -149,16 +121,14 @@ func (m Manager) LeaveGroup(groupID *id.ID) error {
 		return errors.Errorf(leaveGroupErr, groupID, err)
 	}
 
-	edgeStore := m.store.GetEdge()
-	err := edgeStore.Remove(edge.Preimage{
-		Data:   groupID[:],
-		Type:   catalog.Group,
-		Source: groupID[:],
-	}, m.store.GetUser().ReceptionID)
+	delService := message.Service{
+		Identifier: groupID.Bytes(),
+		Tag:        catalog.Group,
+	}
+	m.services.DeleteService(m.receptionId, delService, nil)
 
 	jww.DEBUG.Printf("Left group with ID %s.", groupID)
-
-	return err
+	return nil
 }
 
 // GetGroups returns a list of all registered groupChat IDs.
diff --git a/groupChat/receive.go b/groupChat/receive.go
index f17cac039d4a9facfb7d3774c21e8371e03ea197..58b4aff88078e6f0a816b66be542576468044341 100644
--- a/groupChat/receive.go
+++ b/groupChat/receive.go
@@ -11,10 +11,11 @@ import (
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
 	gs "gitlab.com/elixxir/client/groupChat/groupStore"
-	"gitlab.com/elixxir/client/interfaces/message"
-	"gitlab.com/elixxir/client/stoppable"
+	"gitlab.com/elixxir/client/network/historical"
+	"gitlab.com/elixxir/client/network/identity/receptionID"
 	"gitlab.com/elixxir/crypto/group"
 	"gitlab.com/elixxir/primitives/format"
+	"gitlab.com/elixxir/primitives/states"
 	"gitlab.com/xx_network/primitives/id"
 	"time"
 )
@@ -30,104 +31,64 @@ const (
 		"cMix message because MAC verification failed (epoch %d could be off)"
 )
 
-// receive starts the group message reception worker that waits for new group
-// messages to arrive.
-func (m Manager) receive(rawMsgs chan message.Receive, stop *stoppable.Single) {
-	jww.DEBUG.Print("Starting group message reception worker.")
-
-	for {
-		select {
-		case <-stop.Quit():
-			jww.DEBUG.Print("Stopping group message reception worker.")
-			stop.ToStopped()
-			return
-		case receiveMsg := <-rawMsgs:
-			jww.TRACE.Print("Group message reception received cMix message.")
-
-			// Attempt to read the message
-			g, msgID, timestamp, senderID, msg, noFpMatch, err :=
-				m.readMessage(receiveMsg)
-			if err != nil {
-				if noFpMatch {
-					jww.TRACE.Printf("Received message not for group chat: %+v",
-						err)
-				} else {
-					jww.WARN.Printf("Group message reception failed to read "+
-						"cMix message: %+v", err)
-				}
-				continue
-			}
-
-			jww.DEBUG.Printf("Received group message with ID %s from sender "+
-				"%s in group %s with ID %s at %s.", msgID, senderID, g.Name,
-				g.ID, timestamp)
-
-			// If the message was read correctly, send it to the callback
-			go m.receiveFunc(MessageReceive{
-				GroupID:        g.ID,
-				ID:             msgID,
-				Payload:        msg,
-				SenderID:       senderID,
-				RecipientID:    receiveMsg.RecipientID,
-				EphemeralID:    receiveMsg.EphemeralID,
-				Timestamp:      timestamp,
-				RoundID:        receiveMsg.RoundId,
-				RoundTimestamp: receiveMsg.RoundTimestamp,
-			})
-		}
-	}
+// Adheres to network.Manager interface for reception processing
+type receptionProcessor struct {
+	m *Manager
+	g gs.Group
 }
 
-// readMessage returns the group, message ID, timestamp, sender ID, and message
-// of a group message. The encrypted group message data is unmarshalled from a
-// cMix message in the message.Receive and then decrypted and the MAC is
-// verified. The group is found by finding the group with a matching key
-// fingerprint. Returns true if the key fingerprint cannot be found; in this
-// case no warning or error should be printed.
-func (m *Manager) readMessage(msg message.Receive) (gs.Group, group.MessageID,
-	time.Time, *id.ID, []byte, bool, error) {
-	// Unmarshal payload into cMix message
-	cMixMsg, err := format.Unmarshal(msg.Payload)
-	if err != nil {
-		return gs.Group{}, group.MessageID{}, time.Time{}, nil, nil,
-			false, err
-	}
-	// Unmarshal cMix message contents to get public message format
-	pubMsg, err := unmarshalPublicMsg(cMixMsg.GetContents())
-	if err != nil {
-		return gs.Group{}, group.MessageID{}, time.Time{}, nil, nil, false,
-			errors.Errorf(unmarshalPublicMsgErr, err)
-	}
+// Process incoming group chat messages
+func (p *receptionProcessor) Process(message format.Message, receptionID receptionID.EphemeralIdentity, round historical.Round) {
+	jww.TRACE.Print("Group message reception received cMix message.")
 
-	// get the group from storage via key fingerprint lookup
-	g, exists := m.gs.GetByKeyFp(cMixMsg.GetKeyFP(), pubMsg.GetSalt())
-	if !exists {
-		return gs.Group{}, group.MessageID{}, time.Time{}, nil, nil, true,
-			errors.Errorf(findGroupKeyFpErr, cMixMsg.GetKeyFP())
+	// Attempt to read the message
+	roundTimeStamp := round.Timestamps[states.QUEUED]
+	msgID, timestamp, senderID, msg, err := decryptMessage(p.g, message, roundTimeStamp)
+	if err != nil {
+		jww.WARN.Printf("Group message reception failed to read "+
+			"cMix message: %+v", err)
+		return
 	}
 
-	// Decrypt the payload and return the messages timestamp, sender ID, and
-	// message contents
-	messageID, timestamp, senderID, contents, err := m.decryptMessage(
-		g, cMixMsg, pubMsg, msg.RoundTimestamp)
-	return g, messageID, timestamp, senderID, contents, false, err
+	jww.DEBUG.Printf("Received group message with ID %s from sender "+
+		"%s in group %s with ID %s at %s.", msgID, senderID, p.g.Name,
+		p.g.ID, timestamp)
+
+	// If the message was read correctly, send it to the callback
+	go p.m.receiveFunc(MessageReceive{
+		GroupID:        p.g.ID,
+		ID:             msgID,
+		Payload:        msg,
+		SenderID:       senderID,
+		RecipientID:    receptionID.Source,
+		EphemeralID:    receptionID.EphId,
+		Timestamp:      timestamp,
+		RoundID:        round.ID,
+		RoundTimestamp: roundTimeStamp,
+	})
 }
 
 // decryptMessage decrypts the group message payload and returns its message ID,
 // timestamp, sender ID, and message contents.
-func (m *Manager) decryptMessage(g gs.Group, cMixMsg format.Message,
-	publicMsg publicMsg, roundTimestamp time.Time) (group.MessageID, time.Time,
-	*id.ID, []byte, error) {
+func decryptMessage(g gs.Group, cMixMsg format.Message, roundTimestamp time.Time) (
+	group.MessageID, time.Time, *id.ID, []byte, error) {
+
+	// Unmarshal cMix message contents to get public message format
+	pubMsg, err := unmarshalPublicMsg(cMixMsg.GetContents())
+	if err != nil {
+		return group.MessageID{}, time.Time{}, nil, nil,
+			errors.Errorf(unmarshalPublicMsgErr, err)
+	}
 
-	key, err := getCryptKey(g.Key, publicMsg.GetSalt(), cMixMsg.GetMac(),
-		publicMsg.GetPayload(), g.DhKeys, roundTimestamp)
+	key, err := getCryptKey(g.Key, pubMsg.GetSalt(), cMixMsg.GetMac(),
+		pubMsg.GetPayload(), g.DhKeys, roundTimestamp)
 	if err != nil {
 		return group.MessageID{}, time.Time{}, nil, nil, err
 	}
 
 	// Decrypt internal message
 	decryptedPayload := group.Decrypt(key, cMixMsg.GetKeyFP(),
-		publicMsg.GetPayload())
+		pubMsg.GetPayload())
 
 	// Unmarshal internal message
 	intlMsg, err := unmarshalInternalMsg(decryptedPayload)
diff --git a/groupChat/receiveRequest.go b/groupChat/receiveRequest.go
index 5cd9f57425f47b92347270f83a4e3428f81ac0e6..eaacd5981f6009d79806438300389943f0e94df9 100644
--- a/groupChat/receiveRequest.go
+++ b/groupChat/receiveRequest.go
@@ -11,60 +11,56 @@ import (
 	"github.com/golang/protobuf/proto"
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/catalog"
+	"gitlab.com/elixxir/client/e2e/receive"
 	gs "gitlab.com/elixxir/client/groupChat/groupStore"
-	"gitlab.com/elixxir/client/interfaces/message"
-	"gitlab.com/elixxir/client/stoppable"
 	"gitlab.com/elixxir/crypto/group"
 	"time"
 )
 
-// Error message.
+// Error messages
 const (
 	sendMessageTypeErr       = "message not of type GroupCreationRequest"
 	protoUnmarshalErr        = "failed to unmarshal request: %+v"
 	deserializeMembershipErr = "failed to deserialize membership: %+v"
 )
 
-// receiveRequest starts the group request reception worker that waits for new
-// group requests to arrive.
-func (m Manager) receiveRequest(rawMsgs chan message.Receive,
-	stop *stoppable.Single) {
-	jww.DEBUG.Print("Starting group message request reception worker.")
-
-	for {
-		select {
-		case <-stop.Quit():
-			jww.DEBUG.Print("Stopping group message request reception worker.")
-			stop.ToStopped()
-			return
-		case sendMsg := <-rawMsgs:
-			jww.DEBUG.Print("Group message request received message.")
-
-			// Generate the group from the request message
-			g, err := m.readRequest(sendMsg)
-			if err != nil {
-				jww.WARN.Printf("Failed to read message as group request: %+v",
-					err)
-				continue
-			}
-
-			// Call request callback with the new group if it does not already
-			// exist
-			if _, exists := m.GetGroup(g.ID); !exists {
-				jww.DEBUG.Printf("Received group request from sender %s for "+
-					"group %s with ID %s.", sendMsg.Sender, g.Name, g.ID)
-
-				go m.requestFunc(g)
-			}
-		}
+// Adheres to receive.Listener interface
+type requestListener struct {
+	m *Manager
+}
+
+// Hear waits for new group requests to arrive
+func (l *requestListener) Hear(item receive.Message) {
+	jww.DEBUG.Print("Group message request received message.")
+
+	// Generate the group from the request message
+	g, err := l.m.readRequest(item)
+	if err != nil {
+		jww.WARN.Printf("Failed to read message as group request: %+v", err)
+		return
 	}
+
+	// Call request callback with the new group if it does not already
+	// exist
+	if _, exists := l.m.GetGroup(g.ID); !exists {
+		jww.DEBUG.Printf("Received group request for "+
+			"group %s with ID %s.", g.Name, g.ID)
+
+		go l.m.requestFunc(g)
+	}
+}
+
+// Name returns a name, used for debugging
+func (l *requestListener) Name() string {
+	return catalog.GroupRq
 }
 
 // readRequest returns the group describes in the group request message. An
 // error is returned if the request is of the wrong type or cannot be read.
-func (m *Manager) readRequest(msg message.Receive) (gs.Group, error) {
+func (m *Manager) readRequest(msg receive.Message) (gs.Group, error) {
 	// Return an error if the message is not of the right type
-	if msg.MessageType != message.GroupCreationRequest {
+	if msg.MessageType != catalog.GroupCreationRequest {
 		return gs.Group{}, errors.New(sendMessageTypeErr)
 	}
 
@@ -82,7 +78,7 @@ func (m *Manager) readRequest(msg message.Receive) (gs.Group, error) {
 	}
 
 	// get the relationship with the group leader
-	partner, err := m.store.E2e().GetPartner(membership[0].ID)
+	partner, err := m.e2e.GetPartner(membership[0].ID, m.receptionId)
 	if err != nil {
 		return gs.Group{}, errors.Errorf(getPrivKeyErr, err)
 	}
@@ -93,8 +89,7 @@ func (m *Manager) readRequest(msg message.Receive) (gs.Group, error) {
 
 	// Generate the DH keys with each group member
 	privKey := partner.GetMyOriginPrivateKey()
-	grp := m.store.E2e().GetGroup()
-	dkl := gs.GenerateDhKeyList(m.gs.GetUser().ID, privKey, membership, grp)
+	dkl := gs.GenerateDhKeyList(m.gs.GetUser().ID, privKey, membership, m.grp)
 
 	// Restore the original public key for the leader so that the membership
 	// digest generated later is correct
diff --git a/groupChat/send.go b/groupChat/send.go
index 4101576ec7d3863768a82fa5c1ea1d20d57d6d4c..fd947073d15d1e357dd0fe012718f34a99773140 100644
--- a/groupChat/send.go
+++ b/groupChat/send.go
@@ -10,9 +10,10 @@ package groupChat
 import (
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/catalog"
 	gs "gitlab.com/elixxir/client/groupChat/groupStore"
-	"gitlab.com/elixxir/client/interfaces/message"
-	"gitlab.com/elixxir/client/interfaces/params"
+	"gitlab.com/elixxir/client/network"
+	"gitlab.com/elixxir/client/network/message"
 	"gitlab.com/elixxir/crypto/group"
 	"gitlab.com/elixxir/primitives/format"
 	"gitlab.com/xx_network/primitives/id"
@@ -48,8 +49,7 @@ func (m *Manager) Send(groupID *id.ID, message []byte) (id.Round, time.Time, gro
 		return 0, time.Time{}, group.MessageID{}, errors.Errorf(newCmixMsgErr, err)
 	}
 
-	param := params.GetDefaultCMIX()
-	param.IdentityPreimage = groupID[:]
+	param := network.GetDefaultCMIXParams()
 	param.DebugTag = "group.Message"
 
 	rid, _, err := m.net.SendManyCMIX(messages, param)
@@ -67,10 +67,10 @@ func (m *Manager) Send(groupID *id.ID, message []byte) (id.Round, time.Time, gro
 // createMessages generates a list of cMix messages and a list of corresponding
 // recipient IDs.
 func (m *Manager) createMessages(groupID *id.ID, msg []byte, timestamp time.Time) (
-	[]message.TargetedCmixMessage, group.MessageID, error) {
+	[]network.TargetedCmixMessage, group.MessageID, error) {
 
 	//make the message ID
-	cmixMsg := format.NewMessage(m.store.Cmix().GetGroup().GetP().ByteLen())
+	cmixMsg := format.NewMessage(m.grp.GetP().ByteLen())
 	_, intlMsg, err := newMessageParts(cmixMsg.ContentsSize())
 	if err != nil {
 		return nil, group.MessageID{}, errors.WithMessage(err, "Failed to make message parts for message ID")
@@ -79,7 +79,7 @@ func (m *Manager) createMessages(groupID *id.ID, msg []byte, timestamp time.Time
 
 	g, exists := m.gs.Get(groupID)
 	if !exists {
-		return []message.TargetedCmixMessage{}, group.MessageID{},
+		return []network.TargetedCmixMessage{}, group.MessageID{},
 			errors.Errorf(newNoGroupErr, groupID)
 	}
 
@@ -91,16 +91,16 @@ func (m *Manager) createMessages(groupID *id.ID, msg []byte, timestamp time.Time
 // newMessages is a private function that allows the passing in of a timestamp
 // and streamGen instead of a fastRNG.StreamGenerator for easier testing.
 func (m *Manager) newMessages(g gs.Group, msg []byte, timestamp time.Time) (
-	[]message.TargetedCmixMessage, error) {
+	[]network.TargetedCmixMessage, error) {
 	// Create list of cMix messages
-	messages := make([]message.TargetedCmixMessage, 0, len(g.Members))
+	messages := make([]network.TargetedCmixMessage, 0, len(g.Members))
 
 	// Create channels to receive messages and errors on
 	type msgInfo struct {
 		msg format.Message
 		id  *id.ID
 	}
-	msgChan := make(chan msgInfo, len(g.Members)-1)
+	msgChan := make(chan network.TargetedCmixMessage, len(g.Members)-1)
 	errChan := make(chan error, len(g.Members)-1)
 
 	// Create cMix messages in parallel
@@ -117,11 +117,15 @@ func (m *Manager) newMessages(g gs.Group, msg []byte, timestamp time.Time) (
 			defer rng.Close()
 
 			// Add cMix message to list
-			cMixMsg, err := m.newCmixMsg(g, msg, timestamp, member, rng)
-			if err != nil {
-				errChan <- errors.Errorf(newCmixErr, i, member.ID, g.ID, err)
+			msgChan <- network.TargetedCmixMessage{
+				Recipient: member.ID,
+				Payload:   msg,
+				Service: message.Service{
+					Identifier: g.ID[:],
+					Tag:        catalog.Group,
+					Metadata:   g.ID[:],
+				},
 			}
-			msgChan <- msgInfo{cMixMsg, member.ID}
 
 		}(member, i)
 	}
@@ -133,10 +137,7 @@ func (m *Manager) newMessages(g gs.Group, msg []byte, timestamp time.Time) (
 			// Return on the first error that occurs
 			return nil, err
 		case info := <-msgChan:
-			messages = append(messages, message.TargetedCmixMessage{
-				Recipient: info.id,
-				Message:   info.msg,
-			})
+			messages = append(messages, info)
 		}
 	}
 
@@ -148,7 +149,7 @@ func (m *Manager) newCmixMsg(g gs.Group, msg []byte, timestamp time.Time,
 	mem group.Member, rng io.Reader) (format.Message, error) {
 
 	// Create three message layers
-	cmixMsg := format.NewMessage(m.store.Cmix().GetGroup().GetP().ByteLen())
+	cmixMsg := format.NewMessage(m.grp.GetP().ByteLen())
 	pubMsg, intlMsg, err := newMessageParts(cmixMsg.ContentsSize())
 	if err != nil {
 		return cmixMsg, err
diff --git a/groupChat/sendRequests.go b/groupChat/sendRequests.go
index 6318e6420cf558034c9ac1dfa36f0db715ba677d..d5871731f5473befd146af36fc317ce4db2a82fb 100644
--- a/groupChat/sendRequests.go
+++ b/groupChat/sendRequests.go
@@ -11,9 +11,9 @@ import (
 	"github.com/golang/protobuf/proto"
 	"github.com/pkg/errors"
 	jww "github.com/spf13/jwalterweatherman"
+	"gitlab.com/elixxir/client/catalog"
+	"gitlab.com/elixxir/client/e2e"
 	gs "gitlab.com/elixxir/client/groupChat/groupStore"
-	"gitlab.com/elixxir/client/interfaces/message"
-	"gitlab.com/elixxir/client/interfaces/params"
 	"gitlab.com/elixxir/crypto/group"
 	"gitlab.com/xx_network/primitives/id"
 	"strings"
@@ -111,23 +111,11 @@ func (m Manager) sendRequests(g gs.Group) ([]id.Round, RequestStatus, error) {
 
 // sendRequest sends the group request to the user via E2E.
 func (m Manager) sendRequest(memberID *id.ID, request []byte) ([]id.Round, error) {
-	sendMsg := message.Send{
-		Recipient:   memberID,
-		Payload:     request,
-		MessageType: message.GroupCreationRequest,
-	}
-
-	recipent, err := m.store.E2e().GetPartner(memberID)
-	if err != nil {
-		return nil, errors.WithMessagef(err, "Failed to send request to %s "+
-			"because e2e relationship could not be found", memberID)
-	}
-
-	p := params.GetDefaultE2E()
-	p.IdentityPreimage = recipent.GetGroupRequestPreimage()
-	p.DebugTag = "group.Request"
+	p := e2e.GetDefaultParams()
+	p.LastServiceTag = catalog.GroupRq
+	p.CMIX.DebugTag = "group.Request"
 
-	rounds, _, _, err := m.net.SendE2E(sendMsg, p, nil)
+	rounds, _, _, err := m.e2e.SendE2E(catalog.GroupCreationRequest, m.receptionId, request, p)
 	if err != nil {
 		return nil, errors.Errorf(sendE2eErr, memberID, err)
 	}