diff --git a/e2eClient/auth.go b/e2eClient/auth.go
index aa5e78d799728c67556aee06796b38be69257e25..6fd77dcf98e99758b7f1b5ad22c93233c8b2427c 100644
--- a/e2eClient/auth.go
+++ b/e2eClient/auth.go
@@ -9,7 +9,9 @@ import (
 )
 
 // auth implements the xxdk.AuthCallbacks interface
-type auth struct{}
+type auth struct {
+	confirmChan chan contact.Contact
+}
 
 // Request is called when requests are received
 // Currently confirms all incoming auth requests
@@ -21,8 +23,11 @@ func (a *auth) Request(partner contact.Contact, receptionID receptionID.Ephemera
 	}
 }
 
+// Confirm is called when an e2e request is confirmed.
+// Currently passes the confirmed contact over a channel to notify the main thread of the confirmation
 func (a *auth) Confirm(partner contact.Contact, receptionID receptionID.EphemeralIdentity,
 	round rounds.Round, e2e *xxdk.E2e) {
+	a.confirmChan <- partner
 }
 
 func (a *auth) Reset(partner contact.Contact, receptionID receptionID.EphemeralIdentity,
diff --git a/e2eClient/go.mod b/e2eClient/go.mod
index 5de226dceb68b7407e41639f7dc172a0169dd8e5..7ebb423adc13b2de438222d3569996b88378bb7b 100644
--- a/e2eClient/go.mod
+++ b/e2eClient/go.mod
@@ -6,6 +6,8 @@ require (
 	github.com/spf13/jwalterweatherman v1.1.0
 	gitlab.com/elixxir/client v1.5.1-0.20220706193049-a0b718049663
 	gitlab.com/elixxir/crypto v0.0.7-0.20220606201132-c370d5039cea
+	gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f
+	gitlab.com/xx_network/primitives v0.0.4-0.20220630163313-7890038258c6
 )
 
 require (
@@ -24,10 +26,8 @@ require (
 	gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f // indirect
 	gitlab.com/elixxir/comms v0.0.4-0.20220603231314-e47e4af13326 // indirect
 	gitlab.com/elixxir/ekv v0.1.7 // indirect
-	gitlab.com/elixxir/primitives v0.0.3-0.20220606195757-40f7a589347f // indirect
 	gitlab.com/xx_network/comms v0.0.4-0.20220630163702-f3d372ef6acd // indirect
 	gitlab.com/xx_network/crypto v0.0.5-0.20220606200528-3f886fe49e81 // indirect
-	gitlab.com/xx_network/primitives v0.0.4-0.20220630163313-7890038258c6 // indirect
 	gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93 // indirect
 	golang.org/x/crypto v0.0.0-20220128200615-198e4374d7ed // indirect
 	golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
diff --git a/e2eClient/main.go b/e2eClient/main.go
index 63a93c3e2ecf275c97dae27919420acf7f07e2d2..719a50df723c34b8ff7acc1b34c329d2c507ae07 100644
--- a/e2eClient/main.go
+++ b/e2eClient/main.go
@@ -20,15 +20,16 @@ import (
 
 func main() {
 	// Logging
-	initLog(1, "client.log")
+	initLog(1, "client2.log")
 
 	// Create a new client object-------------------------------------------------------
 
 	// Path to the recipient contact file
-	recipientContactPath := "recipient.xxc"
+	recipientContactPath := "contact.xxc"
+	myContactPath := "recipient.xxc"
 
 	// You would ideally use a configuration tool to acquire these parameters
-	statePath := "statePath"
+	statePath := "statePathRecipient"
 	statePass := "password"
 	// The following connects to mainnet. For historical reasons it is called a json file
 	// but it is actually a marshalled file with a cryptographic signature attached.
@@ -90,11 +91,17 @@ func main() {
 		}
 	}
 
+	err = ioutil.WriteFile(myContactPath, identity.GetContact().Marshal(), fs.ModePerm)
+	if err != nil {
+		jww.FATAL.Panicf("Failed to write contact to file at %s: %+v", myContactPath, err)
+	}
+
 	// Create an E2E client
 	// Pass in auth object which controls auth callbacks for this client
 	params := xxdk.GetDefaultE2EParams()
 	jww.INFO.Printf("Using E2E parameters: %+v", params)
-	xxdkClient, err := xxdk.Login(baseClient, &auth{}, identity, params)
+	confirmChan := make(chan contact.Contact)
+	xxdkClient, err := xxdk.Login(baseClient, &auth{confirmChan: confirmChan}, identity, params)
 	if err != nil {
 		jww.FATAL.Panicf("Unable to Login: %+v", err)
 	}
@@ -138,28 +145,53 @@ func main() {
 
 	// Connect with the recipient--------------------------------------------------
 
-	// Recipient's contact (read from a Client CLI-generated contact file)
-	contactData, err := ioutil.ReadFile(recipientContactPath)
-	if err != nil {
-		jww.FATAL.Panicf("Failed to read recipient contact file: %+v", err)
-	}
+	if recipientContactPath != "" {
+		// Wait for 30 seconds to ensure network connectivity
+		time.Sleep(30 * time.Second)
 
-	// Imported "gitlab.com/elixxir/crypto/contact"
-	// which provides an `Unmarshal` function to convert the byte slice ([]byte) output
-	// of `ioutil.ReadFile()` to the `Contact` type expected by `RequestAuthenticatedChannel()`
-	recipientContact, err := contact.Unmarshal(contactData)
-	if err != nil {
-		jww.FATAL.Panicf("Failed to get contact data: %+v", err)
-	}
-	jww.INFO.Printf("Recipient contact: %+v", recipientContact)
+		// Recipient's contact (read from a Client CLI-generated contact file)
+		contactData, err := ioutil.ReadFile(recipientContactPath)
+		if err != nil {
+			jww.FATAL.Panicf("Failed to read recipient contact file: %+v", err)
+		}
 
-	// Check that the partner exists, if not send a request
-	_, err = e2eClient.GetPartner(recipientContact.ID)
-	if err != nil {
-		_, err = xxdkClient.GetAuth().Request(recipientContact, fact.FactList{})
+		// Imported "gitlab.com/elixxir/crypto/contact"
+		// which provides an `Unmarshal` function to convert the byte slice ([]byte) output
+		// of `ioutil.ReadFile()` to the `Contact` type expected by `RequestAuthenticatedChannel()`
+		recipientContact, err := contact.Unmarshal(contactData)
+		if err != nil {
+			jww.FATAL.Panicf("Failed to get contact data: %+v", err)
+		}
+		jww.INFO.Printf("Recipient contact: %+v", recipientContact)
+
+		// Check that the partner exists, if not send a request
+		_, err = e2eClient.GetPartner(recipientContact.ID)
 		if err != nil {
-			jww.FATAL.Panicf("Failed to send contact request to %s: %+v", recipientContact.ID.String(), err)
+			_, err = xxdkClient.GetAuth().Request(recipientContact, fact.FactList{})
+			if err != nil {
+				jww.FATAL.Panicf("Failed to send contact request to %s: %+v", recipientContact.ID.String(), err)
+			}
+			timeout := time.NewTimer(30 * time.Second)
+			select {
+			case pc := <-confirmChan:
+				if !pc.ID.Cmp(recipientContact.ID) {
+					jww.FATAL.Panicf("Did not receive confirmation for the requested contact")
+				}
+				break
+			case <-timeout.C:
+				jww.FATAL.Panicf("Timed out waiting to receive confirmation of e2e relationship with partner")
+			}
 		}
+
+		// Send a message to the recipient----------------------------------------------------
+
+		// Test message
+		msgBody := "If this message is sent successfully, we'll have established contact with the recipient."
+		roundIDs, messageID, timeSent, err := e2eClient.SendE2E(catalog.XxMessage, recipientContact.ID, []byte(msgBody), params.Base)
+		if err != nil {
+			jww.FATAL.Panicf("Failed to send message: %+v", err)
+		}
+		jww.INFO.Printf("Message %v sent in RoundIDs: %+v at %v", messageID, roundIDs, timeSent)
 	}
 
 	// Register a listener for messages--------------------------------------------------
@@ -169,16 +201,6 @@ func main() {
 	// User-defined behavior for message reception goes in the listener
 	_ = e2eClient.RegisterListener(&id.ZeroUser, catalog.NoType, listener{name: "e2e Message Listener"})
 
-	// Send a message to the recipient----------------------------------------------------
-
-	// Test message
-	msgBody := "If this message is sent successfully, we'll have established contact with the recipient."
-	roundIDs, messageID, timeSent, err := e2eClient.SendE2E(catalog.XxMessage, recipientContact.ID, []byte(msgBody), params.Base)
-	if err != nil {
-		jww.FATAL.Panicf("Failed to send message: %+v", err)
-	}
-	jww.INFO.Printf("Message %v sent in RoundIDs: %+v at %v", messageID, roundIDs, timeSent)
-
 	// Keep app running to receive messages-----------------------------------------------
 
 	// Wait until the user terminates the program