diff --git a/fileTransferConnectClient/go.mod b/fileTransferConnectClient/go.mod
index b18f620c36ce719517882aeba1104cf0c1bd5537..0e127606e3ed526130bdecddc538949847b62bcb 100644
--- a/fileTransferConnectClient/go.mod
+++ b/fileTransferConnectClient/go.mod
@@ -4,9 +4,9 @@ go 1.17
 
 require (
 	github.com/spf13/jwalterweatherman v1.1.0
-	gitlab.com/elixxir/client v1.5.1-0.20220706193049-a0b718049663
+	gitlab.com/elixxir/client v1.5.1-0.20220725224450-9068bb702293
 	gitlab.com/elixxir/crypto v0.0.7-0.20220606201132-c370d5039cea
-	gitlab.com/xx_network/primitives v0.0.4-0.20220630163313-7890038258c6
+	gitlab.com/xx_network/primitives v0.0.4-0.20220712193914-aebd8544396e
 )
 
 require (
diff --git a/fileTransferConnectClient/go.sum b/fileTransferConnectClient/go.sum
index 93cffb8b3c37acb12e8cdc99e49fc16ea6b0526f..c91e856994de2a02ec7dd16399be3307fed9ca92 100644
--- a/fileTransferConnectClient/go.sum
+++ b/fileTransferConnectClient/go.sum
@@ -254,8 +254,8 @@ github.com/zeebo/pcg v0.0.0-20181207190024-3cdc6b625a05/go.mod h1:Gr+78ptB0MwXxm
 github.com/zeebo/pcg v1.0.0/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
 gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f h1:yXGvNBqzZwAhDYlSnxPRbgor6JWoOt1Z7s3z1O9JR40=
 gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f/go.mod h1:H6jztdm0k+wEV2QGK/KYA+MY9nj9Zzatux/qIvDDv3k=
-gitlab.com/elixxir/client v1.5.1-0.20220706193049-a0b718049663 h1:7bhDI2jg/aKkYNGiSsFUGkDykb1H43/+5mBCEvmnkjA=
-gitlab.com/elixxir/client v1.5.1-0.20220706193049-a0b718049663/go.mod h1:GCevkp2aa+vpIsSrlF/HsRlTjf107jgCglZ/0JKqW7E=
+gitlab.com/elixxir/client v1.5.1-0.20220725224450-9068bb702293 h1:RJX27KLhVu/ulF/DaZCB+wNz7IFISD3hyQxlL7mP2z8=
+gitlab.com/elixxir/client v1.5.1-0.20220725224450-9068bb702293/go.mod h1:dRCeFJrIj5zuxSfcnsAYOCodyPrKVparJUREBIWKRcw=
 gitlab.com/elixxir/comms v0.0.4-0.20220603231314-e47e4af13326 h1:Zid8oNHtbOqF6ebrcGIccvIMabFNGh9dzY1b7mgIcF0=
 gitlab.com/elixxir/comms v0.0.4-0.20220603231314-e47e4af13326/go.mod h1:tlHSrtSliKWUxsck8z/Ql/VJkMdSONV2BeWaUAAXzgk=
 gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c=
@@ -289,8 +289,9 @@ gitlab.com/xx_network/primitives v0.0.2/go.mod h1:cs0QlFpdMDI6lAo61lDRH2JZz+3aVk
 gitlab.com/xx_network/primitives v0.0.4-0.20220222211843-901fa4a2d72b/go.mod h1:9imZHvYwNFobxueSvVtHneZLk9wTK7HQTzxPm+zhFhE=
 gitlab.com/xx_network/primitives v0.0.4-0.20220317172007-4d2a53e6e669/go.mod h1:AXVVFt7dDAeIUpOGPiStCcUIKsBXLWbmV/BgZ4T+tOo=
 gitlab.com/xx_network/primitives v0.0.4-0.20220324193139-b292d1ae6e7e/go.mod h1:AXVVFt7dDAeIUpOGPiStCcUIKsBXLWbmV/BgZ4T+tOo=
-gitlab.com/xx_network/primitives v0.0.4-0.20220630163313-7890038258c6 h1:3It6ILDHn/9J/Oi7MfMjkidKPe7vbFCy5JQtXx8EfYM=
 gitlab.com/xx_network/primitives v0.0.4-0.20220630163313-7890038258c6/go.mod h1:AXVVFt7dDAeIUpOGPiStCcUIKsBXLWbmV/BgZ4T+tOo=
+gitlab.com/xx_network/primitives v0.0.4-0.20220712193914-aebd8544396e h1:zRRo/v3KUo3MtpjNJaB03LR+Zi2g1afYF8yKWl1t19o=
+gitlab.com/xx_network/primitives v0.0.4-0.20220712193914-aebd8544396e/go.mod h1:AXVVFt7dDAeIUpOGPiStCcUIKsBXLWbmV/BgZ4T+tOo=
 gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93 h1:eJZrXqHsMmmejEPWw8gNAt0I8CGAMNO/7C339Zco3TM=
 gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93/go.mod h1:aLzpP2TiZTQut/PVHR40EJAomzugDdHXetbieRClXIM=
 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@@ -298,6 +299,7 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA=
diff --git a/fileTransferConnectClient/main.go b/fileTransferConnectClient/main.go
index 44f8eec198cc01a77f7765d605bf82e1a060b9fd..f94f3d5a75287f48db9dbe47b747751f48354aaf 100644
--- a/fileTransferConnectClient/main.go
+++ b/fileTransferConnectClient/main.go
@@ -101,8 +101,7 @@ func main() {
 	// xxdk.DefaultAuthCallbacks is fine here
 	params := xxdk.GetDefaultE2EParams()
 	jww.INFO.Printf("Using E2E parameters: %+v", params)
-	messenger, err := xxdk.Login(net, xxdk.DefaultAuthCallbacks{},
-		identity, params)
+	user, err := xxdk.Login(net, xxdk.DefaultAuthCallbacks{}, identity, params)
 	if err != nil {
 		jww.FATAL.Panicf("Unable to Login: %+v", err)
 	}
@@ -111,7 +110,7 @@ func main() {
 
 	// Set networkFollowerTimeout to a value of your choice (seconds)
 	networkFollowerTimeout := 5 * time.Second
-	err = messenger.StartNetworkFollower(networkFollowerTimeout)
+	err = user.StartNetworkFollower(networkFollowerTimeout)
 	if err != nil {
 		jww.FATAL.Panicf("Failed to start network follower: %+v", err)
 	}
@@ -137,7 +136,7 @@ func main() {
 	connected := make(chan bool, 10)
 	// Provide a callback that will be signalled when network
 	// health status changes
-	messenger.GetCmix().AddHealthCallback(
+	user.GetCmix().AddHealthCallback(
 		func(isConnected bool) {
 			connected <- isConnected
 		})
@@ -163,7 +162,7 @@ func main() {
 	jww.INFO.Printf("Recipient contact: %+v", recipientContact)
 
 	// Create the connection
-	handler, err := connect.Connect(recipientContact, messenger, params)
+	handler, err := connect.Connect(recipientContact, user, params)
 	if err != nil {
 		jww.FATAL.Panicf("Failed to create connection object: %+v", err)
 	}
@@ -174,15 +173,14 @@ func main() {
 
 	// Create general file transfer manager
 	ftParams := fileTransfer.DefaultParams()
-	ftManager, err := fileTransfer.NewManager(ftParams, identity.ID,
-		messenger.GetCmix(), messenger.GetStorage(), messenger.GetRng())
+	ftManager, err := fileTransfer.NewManager(ftParams, user)
 	if err != nil {
 		jww.FATAL.Panicf("Failed to create file transfer manager: %+v", err)
 	}
 
-	err = messenger.AddService(ftManager.StartProcesses)
+	err = user.AddService(ftManager.StartProcesses)
 	if err != nil {
-		jww.FATAL.Panicf("Failed to start file transfer pcoesses: %+v", err)
+		jww.FATAL.Panicf("Failed to start file transfer possesses: %+v", err)
 	}
 
 	// Create ReceiveCallback that is called when a new file transfer is received
@@ -214,7 +212,7 @@ func main() {
 	// Wrap the file transfer in the connection wrapper
 	ftConnectParams := ftConnect.DefaultParams()
 	ftWrapper, err := ftConnect.NewWrapper(
-		receiveCB, ftConnectParams, ftManager, handler, messenger.GetCmix())
+		receiveCB, ftConnectParams, ftManager, handler, user.GetCmix())
 	if err != nil {
 		jww.FATAL.Panicf("Failed to create file transfer manager: %+v", err)
 	}
@@ -245,9 +243,14 @@ func main() {
 	// allows for half the parts to be resent on failure.
 	retryRate := float32(1.5)
 
+	// Period is the duration to wait between calls to the progress callback.
+	// This prevents spamming of the progress callback when many updates occur
+	// in a short period of time.
+	period := 1 * time.Millisecond
+
 	// Send file
-	tid, err := ftWrapper.Send(recipientContact.ID, fileName, fileType,
-		fileData, retryRate, preview, progressCB, 0)
+	tid, err := ftWrapper.Send(
+		fileName, fileType, fileData, retryRate, preview, progressCB, period)
 	if err != nil {
 		jww.FATAL.Panicf("Failed to send file: %+v", err)
 	}
@@ -260,7 +263,7 @@ func main() {
 	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
 	<-c
 
-	err = messenger.StopNetworkFollower()
+	err = user.StopNetworkFollower()
 	if err != nil {
 		jww.ERROR.Printf("Failed to stop network follower: %+v", err)
 	} else {
diff --git a/fileTransferConnectServer/go.mod b/fileTransferConnectServer/go.mod
index 23e35b92784d7f28582ebf23c19364a4ca850280..eb3813383301f28643652f96792098ef6f0e5183 100644
--- a/fileTransferConnectServer/go.mod
+++ b/fileTransferConnectServer/go.mod
@@ -4,7 +4,7 @@ go 1.17
 
 require (
 	github.com/spf13/jwalterweatherman v1.1.0
-	gitlab.com/elixxir/client v1.5.1-0.20220713213756-95ed0fc8e7cf
+	gitlab.com/elixxir/client v1.5.1-0.20220725224450-9068bb702293
 	gitlab.com/elixxir/crypto v0.0.7-0.20220606201132-c370d5039cea
 	gitlab.com/xx_network/primitives v0.0.4-0.20220712193914-aebd8544396e
 )
diff --git a/fileTransferConnectServer/go.sum b/fileTransferConnectServer/go.sum
index 5886be4fc7b269a333b1a9b4123825e8eab1baa1..c91e856994de2a02ec7dd16399be3307fed9ca92 100644
--- a/fileTransferConnectServer/go.sum
+++ b/fileTransferConnectServer/go.sum
@@ -254,8 +254,8 @@ github.com/zeebo/pcg v0.0.0-20181207190024-3cdc6b625a05/go.mod h1:Gr+78ptB0MwXxm
 github.com/zeebo/pcg v1.0.0/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
 gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f h1:yXGvNBqzZwAhDYlSnxPRbgor6JWoOt1Z7s3z1O9JR40=
 gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f/go.mod h1:H6jztdm0k+wEV2QGK/KYA+MY9nj9Zzatux/qIvDDv3k=
-gitlab.com/elixxir/client v1.5.1-0.20220713213756-95ed0fc8e7cf h1:mt92NfMLwhOharsKlN2dZE3NTPwBgOC4IchdtZjcfhQ=
-gitlab.com/elixxir/client v1.5.1-0.20220713213756-95ed0fc8e7cf/go.mod h1:dRCeFJrIj5zuxSfcnsAYOCodyPrKVparJUREBIWKRcw=
+gitlab.com/elixxir/client v1.5.1-0.20220725224450-9068bb702293 h1:RJX27KLhVu/ulF/DaZCB+wNz7IFISD3hyQxlL7mP2z8=
+gitlab.com/elixxir/client v1.5.1-0.20220725224450-9068bb702293/go.mod h1:dRCeFJrIj5zuxSfcnsAYOCodyPrKVparJUREBIWKRcw=
 gitlab.com/elixxir/comms v0.0.4-0.20220603231314-e47e4af13326 h1:Zid8oNHtbOqF6ebrcGIccvIMabFNGh9dzY1b7mgIcF0=
 gitlab.com/elixxir/comms v0.0.4-0.20220603231314-e47e4af13326/go.mod h1:tlHSrtSliKWUxsck8z/Ql/VJkMdSONV2BeWaUAAXzgk=
 gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c=
@@ -299,6 +299,7 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA=
diff --git a/fileTransferConnectServer/main.go b/fileTransferConnectServer/main.go
index 92abf00c341f13fec7342610dea7683cb7b06ffe..a29dad5fec6ad176e85cca984b0ebbdc98883d14 100644
--- a/fileTransferConnectServer/main.go
+++ b/fileTransferConnectServer/main.go
@@ -103,70 +103,15 @@ func main() {
 	// Save the contact file so that client can connect to this server
 	writeContact(contactFilePath, identity.GetContact())
 
-	// Handle incoming connections and create file transfer manager------------
+	// Handle incoming connections---------------------------------------------
+
+	// When a channel is received, a new file transfer wrapper will be created
+	// to wait for new file transfers
+	connectionCh := make(chan connect.Connection, 10)
 
 	// Create callback for incoming connections
 	cb := func(connection connect.Connection) {
-
-		// Create general file transfer manager
-		ftParams := fileTransfer.DefaultParams()
-		ftManager, err := fileTransfer.NewManager(ftParams, identity.ID,
-			net.GetCmix(), net.GetStorage(), net.GetRng())
-		if err != nil {
-			jww.FATAL.Panicf("Failed to create file transfer manager: %+v", err)
-		}
-
-		err = net.AddService(ftManager.StartProcesses)
-		if err != nil {
-			jww.FATAL.Panicf("Failed to start file transfer pcoesses: %+v", err)
-		}
-
-		// Create ReceiveCallback that is called when a new file transfer is received
-		receiveCB := func(tid *ftCrypto.TransferID, fileName, fileType string,
-			sender *id.ID, size uint32, preview []byte) {
-			// Inform the user that a new file transfer has been received
-			jww.INFO.Printf("Received new file %q transfer %s of type %s from %s "+
-				"of size %d bytes with preview: %q",
-				fileName, tid, fileType, sender, size, preview)
-
-			receivedProgressCB := func(completed bool, received, total uint16,
-				rt fileTransfer.ReceivedTransfer, t fileTransfer.FilePartTracker,
-				err error) {
-				// Show the file transfer progress to the user.
-				jww.INFO.Printf("Received progress callback for %q "+
-					"{completed: %t, received: %d, total: %d, err: %v}",
-					fileName, completed, received, total, err)
-
-				// Once the file is complete, receive the full file.
-				if completed {
-
-					fileData, err := ftManager.Receive(tid)
-					if err != nil {
-						jww.FATAL.Panicf("Failed to receive full file: %+v", err)
-					}
-
-					jww.INFO.Printf("Completed receiving file %q: %q",
-						fileName, fileData)
-				}
-			}
-
-			// Register received progress callback
-			err = ftManager.RegisterReceivedProgressCallback(
-				tid, receivedProgressCB, 0)
-			if err != nil {
-				jww.FATAL.Panicf(
-					"Failed to register received progress callback: %+v", err)
-			}
-		}
-
-		// Wrap the file transfer in the connection wrapper
-		ftConnectParams := ftConnect.DefaultParams()
-		_, err = ftConnect.NewWrapper(
-			receiveCB, ftConnectParams, ftManager, connection, net.GetCmix())
-		if err != nil {
-			jww.FATAL.Panicf("Failed to create file transfer manager: %+v", err)
-		}
-
+		connectionCh <- connection
 	}
 
 	// Start connection server-------------------------------------------------
@@ -183,7 +128,7 @@ func main() {
 
 	// Set networkFollowerTimeout to a value of your choice (seconds)
 	networkFollowerTimeout := 5 * time.Second
-	err = connectServer.E2e.StartNetworkFollower(networkFollowerTimeout)
+	err = connectServer.User.StartNetworkFollower(networkFollowerTimeout)
 	if err != nil {
 		jww.FATAL.Panicf("Failed to start network follower: %+v", err)
 	}
@@ -209,13 +154,83 @@ func main() {
 	connected := make(chan bool, 10)
 	// Provide a callback that will be signalled when network health
 	// status changes
-	connectServer.E2e.GetCmix().AddHealthCallback(
+	connectServer.User.GetCmix().AddHealthCallback(
 		func(isConnected bool) {
 			connected <- isConnected
 		})
 	// Wait until connected or crash on timeout
 	waitUntilConnected(connected)
 
+	// Create file transfer manager--------------------------------------------
+
+	// Create general file transfer manager
+	ftParams := fileTransfer.DefaultParams()
+	ftManager, err := fileTransfer.NewManager(ftParams, connectServer.User)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to create file transfer manager: %+v", err)
+	}
+
+	err = net.AddService(ftManager.StartProcesses)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to start file transfer possesses: %+v", err)
+	}
+
+	// Create ReceiveCallback that is called when a new file transfer is received
+	receiveCB := func(tid *ftCrypto.TransferID, fileName, fileType string,
+		sender *id.ID, size uint32, preview []byte) {
+		// Inform the user that a new file transfer has been received
+		jww.INFO.Printf("Received new file %q transfer %s of type %s from %s "+
+			"of size %d bytes with preview: %q",
+			fileName, tid, fileType, sender, size, preview)
+
+		receivedProgressCB := func(completed bool, received, total uint16,
+			rt fileTransfer.ReceivedTransfer, t fileTransfer.FilePartTracker,
+			err error) {
+			// Show the file transfer progress to the user.
+			jww.INFO.Printf("Received progress callback for %q "+
+				"{completed: %t, received: %d, total: %d, err: %v}",
+				fileName, completed, received, total, err)
+
+			// Once the file is complete, receive the full file.
+			if completed {
+
+				fileData, err := ftManager.Receive(tid)
+				if err != nil {
+					jww.FATAL.Panicf("Failed to receive full file: %+v", err)
+				}
+
+				jww.INFO.Printf("Completed receiving file %q: %q",
+					fileName, fileData)
+			}
+		}
+
+		// Period is the duration to wait between calls to the progress
+		// callback. This prevents spamming of the progress callback when
+		// many updates occur in a short period of time.
+		period := 1 * time.Millisecond
+
+		// Register received progress callback
+		err = ftManager.RegisterReceivedProgressCallback(
+			tid, receivedProgressCB, period)
+		if err != nil {
+			jww.FATAL.Panicf(
+				"Failed to register received progress callback: %+v", err)
+		}
+	}
+
+	select {
+	case connection := <-connectionCh:
+		// Wrap the file transfer in the connection wrapper
+		ftConnectParams := ftConnect.DefaultParams()
+		_, err = ftConnect.NewWrapper(
+			receiveCB, ftConnectParams, ftManager, connection, net.GetCmix())
+		if err != nil {
+			jww.FATAL.Panicf("Failed to create file transfer manager: %+v", err)
+		}
+	case <-time.After(5 * time.Minute):
+		jww.FATAL.Panicf("Failed to receive connection.")
+	}
+
 	// Keep app running to receive messages------------------------------------
 
 	// Wait until the user terminates the program
@@ -223,7 +238,7 @@ func main() {
 	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
 	<-c
 
-	err = connectServer.E2e.StopNetworkFollower()
+	err = connectServer.User.StopNetworkFollower()
 	if err != nil {
 		jww.ERROR.Printf("Failed to stop network follower: %+v", err)
 	} else {