diff --git a/go.mod b/go.mod
index a93bc52713c69ac1897a5ebe63f05d506e882264..5495e7a4880657ba152dcc758a33e7cdf45a7d84 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,7 @@ require (
 	github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2
 	github.com/pkg/errors v0.9.1
 	github.com/spf13/jwalterweatherman v1.1.0
-	gitlab.com/elixxir/client v1.5.1-0.20220909222059-b7c62b408d55
+	gitlab.com/elixxir/client v1.5.1-0.20220913182014-e5c929eee8c8
 )
 
 require (
@@ -37,7 +37,7 @@ require (
 	gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f // indirect
 	gitlab.com/elixxir/comms v0.0.4-0.20220908220232-4755ca5e8bcc // indirect
 	gitlab.com/elixxir/crypto v0.0.7-0.20220902165412-5c5e3e990e84 // indirect
-	gitlab.com/elixxir/ekv v0.2.1-0.20220901224437-ab4cbf94bf8b // indirect
+	gitlab.com/elixxir/ekv v0.2.1 // indirect
 	gitlab.com/elixxir/primitives v0.0.3-0.20220901220638-1acc75fabdc6 // indirect
 	gitlab.com/xx_network/comms v0.0.4-0.20220908215521-17222b8efc87 // indirect
 	gitlab.com/xx_network/crypto v0.0.5-0.20220902182733-69aad094b487 // indirect
diff --git a/go.sum b/go.sum
index 620e3efdd5bc2b40b3cef5626038b2f788712688..8f36c50362e2b6b331d185c6e8a6f66c615f02a8 100644
--- a/go.sum
+++ b/go.sum
@@ -613,16 +613,16 @@ 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-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.20220909222059-b7c62b408d55 h1:UwhQ2QA2dSBO/9v2ydTi4rgw1BZN38IUVKh7cpFR0mU=
-gitlab.com/elixxir/client v1.5.1-0.20220909222059-b7c62b408d55/go.mod h1:NNHMHtOHRAOgd6QinkRZoJTNN5j6lI8fDvvnuUEOcv0=
+gitlab.com/elixxir/client v1.5.1-0.20220913182014-e5c929eee8c8 h1:rYfuO3mnrB4bjBYaFMTbhTFD8DN7LjJMB56YSnTstv8=
+gitlab.com/elixxir/client v1.5.1-0.20220913182014-e5c929eee8c8/go.mod h1:6AQZOwpk9U+RlDSjkE10Rc1idaHMSt9Z08m4x2n/RnM=
 gitlab.com/elixxir/comms v0.0.4-0.20220908220232-4755ca5e8bcc h1:sD4o87jVG3zX47QDViHim3SR7NyvX/pJL6gqC7IVMrQ=
 gitlab.com/elixxir/comms v0.0.4-0.20220908220232-4755ca5e8bcc/go.mod h1:hCC0OOdJI/PQRs9jMCrxKcRmY0fL8Mu5iJGBhsmjHyU=
 gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c=
 gitlab.com/elixxir/crypto v0.0.3/go.mod h1:ZNgBOblhYToR4m8tj4cMvJ9UsJAUKq+p0gCp07WQmhA=
 gitlab.com/elixxir/crypto v0.0.7-0.20220902165412-5c5e3e990e84 h1:sQCoZ+w09X/8LjQo9m7bg51IoX4AXSrXBtU8eblM/II=
 gitlab.com/elixxir/crypto v0.0.7-0.20220902165412-5c5e3e990e84/go.mod h1:Sfb4ceEoWLLYNT8V6isZa5k87NfUecM8i34Z+hDYTgg=
-gitlab.com/elixxir/ekv v0.2.1-0.20220901224437-ab4cbf94bf8b h1:0cN/WHbFaonJEN+odqyjtSrkuEbBnEnWfggT91svPGc=
-gitlab.com/elixxir/ekv v0.2.1-0.20220901224437-ab4cbf94bf8b/go.mod h1:USLD7xeDnuZEavygdrgzNEwZXeLQJK/w1a+htpN+JEU=
+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=
 gitlab.com/elixxir/primitives v0.0.0-20200804170709-a1896d262cd9/go.mod h1:p0VelQda72OzoUckr1O+vPW0AiFe0nyKQ6gYcmFSuF8=
 gitlab.com/elixxir/primitives v0.0.0-20200804182913-788f47bded40/go.mod h1:tzdFFvb1ESmuTCOl1z6+yf6oAICDxH2NPUemVgoNLxc=
diff --git a/wasm/authenticatedConnection.go b/wasm/authenticatedConnection.go
index 0f47cb36eaa9e50c87f137b36a5c07f53f6b6996..ea2fffd45760c474ce053f015c6b596360422f8b 100644
--- a/wasm/authenticatedConnection.go
+++ b/wasm/authenticatedConnection.go
@@ -38,6 +38,10 @@ func newAuthenticatedConnectionJS(
 	return acMap
 }
 
+// IsAuthenticated returns true.
+//
+// Returns:
+//  - true (boolean).
 func (ac *AuthenticatedConnection) IsAuthenticated(js.Value, []js.Value) interface{} {
 	return ac.api.IsAuthenticated()
 }
@@ -62,17 +66,23 @@ func (ac *AuthenticatedConnection) GetId(js.Value, []js.Value) interface{} {
 //  - args[0] - message type from [catalog.MessageType] (int)
 //  - args[1] - message payload (Uint8Array)
 //
-// Returns:
-//  - JSON of [bindings.E2ESendReport], which can be passed into
-//    cmix.WaitForRoundResult to see if the send succeeded (Uint8Array)
-//  - throws a TypeError if sending fails
+// Returns a promise:
+//  - Resolves to the JSON of [bindings.E2ESendReport], which can be passed into
+//    cmix.WaitForRoundResult to see if the send succeeded (Uint8Array).
+//  - Rejected with an error if sending fails.
 func (ac *AuthenticatedConnection) SendE2E(_ js.Value, args []js.Value) interface{} {
-	sendReport, err := ac.api.SendE2E(args[0].Int(), utils.CopyBytesToGo(args[1]))
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	payload := utils.CopyBytesToGo(args[2])
+
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		sendReport, err := ac.api.SendE2E(args[0].Int(), payload)
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(sendReport))
+		}
 	}
-	return utils.CopyBytesToJS(sendReport)
+
+	return utils.CreatePromise(promiseFn)
 }
 
 // Close deletes this AuthenticatedConnection's partner.Manager and releases
@@ -123,19 +133,22 @@ func (ac *AuthenticatedConnection) RegisterListener(
 //  - args[1] - marshalled recipient [contact.Contact] (Uint8Array).
 //  - args[3] - JSON of [xxdk.E2EParams] (Uint8Array).
 //
-// Returns:
-//  - Javascript representation of the Connection object
-//  - throws a TypeError if creating loading the parameters or connecting fails
+// Returns a promise:
+//  - Resolves to a Javascript representation of the Connection object.
+//  - Rejected with an error if loading the parameters or connecting fails.
 func (c *Cmix) ConnectWithAuthentication(_ js.Value, args []js.Value) interface{} {
 	recipientContact := utils.CopyBytesToGo(args[1])
 	e2eParamsJSON := utils.CopyBytesToGo(args[2])
 
-	ac, err := c.api.ConnectWithAuthentication(
-		args[0].Int(), recipientContact, e2eParamsJSON)
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		ac, err := c.api.ConnectWithAuthentication(
+			args[0].Int(), recipientContact, e2eParamsJSON)
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(newAuthenticatedConnectionJS(ac))
+		}
 	}
 
-	return newAuthenticatedConnectionJS(ac)
+	return utils.CreatePromise(promiseFn)
 }
diff --git a/wasm/broadcast.go b/wasm/broadcast.go
index e3f05e416e38918e636100bf47b504200716b191..9c14cec1414549eae1fee68872f68f34fa920e80 100644
--- a/wasm/broadcast.go
+++ b/wasm/broadcast.go
@@ -98,18 +98,24 @@ func (c *Channel) Listen(_ js.Value, args []js.Value) interface{} {
 // Parameters:
 //  - args[0] - payload (Uint8Array).
 //
-// Returns:
-//  - JSON of [bindings.BroadcastReport], which can be passed into
-//    Cmix.WaitForRoundResult to see if the broadcast succeeded (Uint8Array).
-//  - Throws a TypeError if broadcasting fails.
+// Returns a promise:
+//  - Resolves to the JSON of the [bindings.BroadcastReport], which can be
+//    passed into Cmix.WaitForRoundResult to see if the send succeeded
+//    (Uint8Array).
+//  - Rejected with an error if broadcasting fails.
 func (c *Channel) Broadcast(_ js.Value, args []js.Value) interface{} {
-	report, err := c.api.Broadcast(utils.CopyBytesToGo(args[0]))
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	payload := utils.CopyBytesToGo(args[0])
+
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		sendReport, err := c.api.Broadcast(payload)
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(sendReport))
+		}
 	}
 
-	return utils.CopyBytesToJS(report)
+	return utils.CreatePromise(promiseFn)
 }
 
 // BroadcastAsymmetric sends a given payload over the broadcast channel using
@@ -119,19 +125,25 @@ func (c *Channel) Broadcast(_ js.Value, args []js.Value) interface{} {
 //  - args[0] - payload (Uint8Array).
 //  - args[1] - private key (Uint8Array).
 //
-// Returns:
-//  - JSON of [bindings.BroadcastReport], which can be passed into
-//    Cmix.WaitForRoundResult to see if the broadcast succeeded (Uint8Array).
-//  - Throws a TypeError if broadcasting fails.
+// Returns a promise:
+//  - Resolves to the JSON of the [bindings.BroadcastReport], which can be
+//    passed into Cmix.WaitForRoundResult to see if the send succeeded
+//    (Uint8Array).
+//  - Rejected with an error if broadcasting fails.
 func (c *Channel) BroadcastAsymmetric(_ js.Value, args []js.Value) interface{} {
-	report, err := c.api.BroadcastAsymmetric(
-		utils.CopyBytesToGo(args[0]), utils.CopyBytesToGo(args[1]))
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	payload := utils.CopyBytesToGo(args[0])
+	privateKey := utils.CopyBytesToGo(args[1])
+
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		sendReport, err := c.api.BroadcastAsymmetric(payload, privateKey)
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(sendReport))
+		}
 	}
 
-	return utils.CopyBytesToJS(report)
+	return utils.CreatePromise(promiseFn)
 }
 
 // MaxPayloadSize returns the maximum possible payload size which can be
diff --git a/wasm/cmix.go b/wasm/cmix.go
index 219f99ab0b6c928a6c7ce5d2c133ccf2d35674aa..3b5a050e8ffadf88fe8d23bea8ce3e985e48b013 100644
--- a/wasm/cmix.go
+++ b/wasm/cmix.go
@@ -103,9 +103,9 @@ func NewCmix(_ js.Value, args []js.Value) interface{} {
 //  - args[1] - password used for storage (Uint8Array)
 //  - args[2] - JSON of [xxdk.CMIXParams] (Uint8Array)
 //
-// Returns:
-//  - A promise that returns a Javascript representation of the Cmix object.
-//  - Throws a error if loading Cmix fails.
+// Returns a promise:
+//  - Resolves to a Javascript representation of the Cmix object.
+//  - Rejected with an error if loading Cmix fails.
 func LoadCmix(_ js.Value, args []js.Value) interface{} {
 	storageDir := args[0].String()
 	password := utils.CopyBytesToGo(args[1])
diff --git a/wasm/connect.go b/wasm/connect.go
index b7e5ba566cd9339ebc31dbb56f98192884094695..92e4bed661e8928884f3bdc31aef59a50a92dfe0 100644
--- a/wasm/connect.go
+++ b/wasm/connect.go
@@ -56,19 +56,23 @@ func (c *Connection) GetId(js.Value, []js.Value) interface{} {
 //  - args[1] - marshalled recipient [contact.Contact] (Uint8Array).
 //  - args[3] - JSON of [xxdk.E2EParams] (Uint8Array).
 //
-// Returns:
-//  - Javascript representation of the Connection object
-//  - throws a TypeError if creating loading the parameters or connecting fails
+// Returns a promise:
+//  - Resolves to a Javascript representation of the Connection object.
+//  - Rejected with an error if loading the parameters or connecting fails.
 func (c *Cmix) Connect(_ js.Value, args []js.Value) interface{} {
 	recipientContact := utils.CopyBytesToGo(args[1])
 	e2eParamsJSON := utils.CopyBytesToGo(args[2])
-	api, err := c.api.Connect(args[0].Int(), recipientContact, e2eParamsJSON)
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		api, err := c.api.Connect(args[0].Int(), recipientContact, e2eParamsJSON)
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(newConnectJS(api))
+		}
 	}
 
-	return newConnectJS(api)
+	return utils.CreatePromise(promiseFn)
 }
 
 // SendE2E is a wrapper for sending specifically to the Connection's
@@ -82,17 +86,23 @@ func (c *Cmix) Connect(_ js.Value, args []js.Value) interface{} {
 //  - args[0] - message type from [catalog.MessageType] (int)
 //  - args[1] - message payload (Uint8Array)
 //
-// Returns:
-//  - JSON of [bindings.E2ESendReport], which can be passed into
-//    cmix.WaitForRoundResult to see if the send succeeded (Uint8Array)
-//  - throws a TypeError if sending fails
+// Returns a promise:
+//  - Resolves to the JSON of the [bindings.E2ESendReport], which can be passed
+//    into Cmix.WaitForRoundResult to see if the send succeeded (Uint8Array).
+//  - Rejected with an error if sending fails.
 func (c *Connection) SendE2E(_ js.Value, args []js.Value) interface{} {
-	sendReport, err := c.api.SendE2E(args[0].Int(), utils.CopyBytesToGo(args[1]))
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	payload := utils.CopyBytesToGo(args[1])
+
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		sendReport, err := c.api.SendE2E(args[0].Int(), payload)
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(sendReport))
+		}
 	}
-	return utils.CopyBytesToJS(sendReport)
+
+	return utils.CreatePromise(promiseFn)
 }
 
 // Close deletes this Connection's partner.Manager and releases resources.
diff --git a/wasm/delivery.go b/wasm/delivery.go
index b0f340978e6a92ccb510bc36c60a8875b309c77f..f6748f22681b9f665f5b02ec04aba8468dec8ef3 100644
--- a/wasm/delivery.go
+++ b/wasm/delivery.go
@@ -34,20 +34,20 @@ func (mdc *messageDeliveryCallback) EventCallback(
 // not occur as a result of both sides of the bindings holding a reference to
 // the same pointer.
 //
-// roundList is a JSON marshalled RoundsList or any JSON marshalled send report
-// that inherits a RoundsList object.
+// roundList is a JSON marshalled [bindings.RoundsList] or any JSON marshalled
+// send report that inherits a [bindings.RoundsList] object.
 //
 // Parameters:
 //  - args[0] - JSON of [bindings.RoundsList] or JSON of any send report that
-//    inherits a [bindings.RoundsList] object (Uint8Array)
+//    inherits a [bindings.RoundsList] object (Uint8Array).
 //  - args[1] - Javascript object that has functions that implement the
-//    [bindings.MessageDeliveryCallback] interface
+//    [bindings.MessageDeliveryCallback] interface.
 //  - args[2] - timeout when the callback will return if no state update occurs,
-//    in milliseconds (int)
+//    in milliseconds (int).
 //
 // Returns:
-//  - throws a TypeError if the parameters are invalid or getting round results
-//    fails
+//  - Throws a TypeError if the parameters are invalid or getting round results
+//    fails.
 func (c *Cmix) WaitForRoundResult(_ js.Value, args []js.Value) interface{} {
 	roundList := utils.CopyBytesToGo(args[0])
 	mdc := &messageDeliveryCallback{utils.WrapCB(args[1], "EventCallback")}
diff --git a/wasm/e2eAuth.go b/wasm/e2eAuth.go
index 3d6efa4343e7441a51c328e99defa1fb75873625..45b3b9450e2317e9da79c1b356d1abd50790a6fe 100644
--- a/wasm/e2eAuth.go
+++ b/wasm/e2eAuth.go
@@ -36,9 +36,9 @@ import (
 //  - args[0] - marshalled bytes of the partner [contact.Contact] (Uint8Array).
 //  - args[1] - JSON of [fact.FactList] (Uint8Array).
 //
-// Returns:
-//  - A promise that returns the ID of the round (int).
-//  - Throws an error if the request fails.
+// Returns a promise:
+//  - Resolves to the ID of the round (int).
+//  - Rejected with an error if sending the request fails.
 func (e *E2e) Request(_ js.Value, args []js.Value) interface{} {
 	partnerContact := utils.CopyBytesToGo(args[0])
 	factsListJson := utils.CopyBytesToGo(args[1])
@@ -74,9 +74,9 @@ func (e *E2e) Request(_ js.Value, args []js.Value) interface{} {
 // Parameters:
 //  - args[0] - marshalled bytes of the partner [contact.Contact] (Uint8Array).
 //
-// Returns:
-//  - A promise that returns the ID of the round (int).
-//  - Throws an error if the confirmation fails.
+// Returns a promise:
+//  - Resolves to the ID of the round (int).
+//  - Rejected with an error if sending the confirmation fails.
 func (e *E2e) Confirm(_ js.Value, args []js.Value) interface{} {
 	partnerContact := utils.CopyBytesToGo(args[0])
 
@@ -109,9 +109,9 @@ func (e *E2e) Confirm(_ js.Value, args []js.Value) interface{} {
 // Parameters:
 //  - args[0] - marshalled bytes of the partner [contact.Contact] (Uint8Array).
 //
-// Returns:
-//  - A promise that returns the ID of the round (int).
-//  - Throws an error if the reset fails.
+// Returns a promise:
+//  - Resolves to the ID of the round (int).
+//  - Rejected with an error if sending the reset fails.
 func (e *E2e) Reset(_ js.Value, args []js.Value) interface{} {
 	partnerContact := utils.CopyBytesToGo(args[0])
 
@@ -138,9 +138,9 @@ func (e *E2e) Reset(_ js.Value, args []js.Value) interface{} {
 // Parameters:
 //  - args[0] - marshalled bytes of the partner [contact.Contact] (Uint8Array).
 //
-// Returns:
-//  - A promise that returns the ID of the round (int).
-//  - Throws an error if the confirmation fails.
+// Returns a promise:
+//  - Resolves to the ID of the round (int).
+//  - Rejected with an error if resending the confirmation fails.
 func (e *E2e) ReplayConfirm(_ js.Value, args []js.Value) interface{} {
 	partnerContact := utils.CopyBytesToGo(args[0])
 
diff --git a/wasm/e2eHandler.go b/wasm/e2eHandler.go
index d542994582332cf7c8cccc5d3953e2403ed7a845..a186be2bac661ec9ec0dbfad164998c6bcf176c6 100644
--- a/wasm/e2eHandler.go
+++ b/wasm/e2eHandler.go
@@ -160,16 +160,15 @@ func (e *E2e) RemoveService(_ js.Value, args []js.Value) interface{} {
 // message type, per the given parameters--encrypted with end-to-end encryption.
 //
 // Parameters:
-//  - args[0] - message type from [catalog.MessageType] (int)
-//  - args[1] - JSON of [id.ID] (Uint8Array)
-//  - args[2] - message payload (Uint8Array)
-//  - args[3] - JSON [e2e.Params] (Uint8Array)
+//  - args[0] - message type from [catalog.MessageType] (int).
+//  - args[1] - JSON of [id.ID] (Uint8Array).
+//  - args[2] - message payload (Uint8Array).
+//  - args[3] - JSON [e2e.Params] (Uint8Array).
 //
-// Returns:
-//  - A promise that returns the JSON of the [bindings.E2ESendReport], which can
-//    be passed into Cmix.WaitForRoundResult to see if the send succeeded
-//    (Uint8Array).
-//  - Throws error if sending fails.
+// Returns a promise:
+//  - Resolves to the JSON of the [bindings.E2ESendReport], which can be passed
+//    into Cmix.WaitForRoundResult to see if the send succeeded (Uint8Array).
+//  - Rejected with an error if sending fails.
 func (e *E2e) SendE2E(_ js.Value, args []js.Value) interface{} {
 	recipientId := utils.CopyBytesToGo(args[1])
 	payload := utils.CopyBytesToGo(args[2])
diff --git a/wasm/fileTransfer.go b/wasm/fileTransfer.go
index 1e2fa842359874994dd57723bfec0466d0efeb5b..24a1767b8b96151ba13c6f0aea3f0cca740ef9df 100644
--- a/wasm/fileTransfer.go
+++ b/wasm/fileTransfer.go
@@ -125,22 +125,25 @@ func InitFileTransfer(_ js.Value, args []js.Value) interface{} {
 //  - args[4] - duration to wait between progress callbacks triggering (string).
 //    Reference [time.ParseDuration] for info on valid duration strings.
 //
-// Returns:
-//  - A unique ID for this file transfer (Uint8Array).
-//  - Throws a TypeError if sending fails.
+// Returns a promise:
+//  - Resolves to a unique ID for this file transfer (Uint8Array).
+//  - Rejected with an error if sending fails.
 func (f *FileTransfer) Send(_ js.Value, args []js.Value) interface{} {
 	payload := utils.CopyBytesToGo(args[0])
 	recipientID := utils.CopyBytesToGo(args[1])
 	retry := float32(args[2].Float())
 	spc := &fileTransferSentProgressCallback{utils.WrapCB(args[3], "Callback")}
 
-	ftID, err := f.api.Send(payload, recipientID, retry, spc, args[4].String())
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		ftID, err := f.api.Send(payload, recipientID, retry, spc, args[4].String())
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(ftID))
+		}
 	}
 
-	return utils.CopyBytesToJS(ftID)
+	return utils.CreatePromise(promiseFn)
 }
 
 // Receive returns the full file on the completion of the transfer. It deletes
diff --git a/wasm/follow.go b/wasm/follow.go
index f3a4e7bd6f3745ac7e1c1dcd0dd10f23dd36c662..c4d6cbf46bc6533d6ed99dd293f88d6e8d51cc5f 100644
--- a/wasm/follow.go
+++ b/wasm/follow.go
@@ -87,7 +87,7 @@ func (c *Cmix) StopNetworkFollower(js.Value, []js.Value) interface{} {
 // Parameters:
 //  - args[0] - timeout when stopping threads in milliseconds (int)
 //
-// Returns:
+// Returns a promise:
 //  - A promise that resolves if the network is healthy and rejects if the
 //    network is not healthy.
 func (c *Cmix) WaitForNetwork(_ js.Value, args []js.Value) interface{} {
diff --git a/wasm/group.go b/wasm/group.go
index b60dcb0b15c02502bec9c8c8e9d5049894b50258..12f8f6d688fa8bb537f364a15cdd3ba5a1cd0043 100644
--- a/wasm/group.go
+++ b/wasm/group.go
@@ -81,24 +81,26 @@ func NewGroupChat(_ js.Value, args []js.Value) interface{} {
 //    optional  parameter and may be nil. If nil the group will be assigned the
 //    default name (Uint8Array).
 //
-// Returns:
-//  - JSON of [bindings.GroupReport], which can be passed into
-//    Cmix.WaitForRoundResult to see if the group request message send
-//    succeeded.
-//  - Throws a TypeError if making the group fails.
+// Returns a promise:
+//  - Resolves to the JSON of the [bindings.GroupReport], which can be passed
+//    into Cmix.WaitForRoundResult to see if the send succeeded (Uint8Array).
+//  - Rejected with an error if making the group fails.
 func (g *GroupChat) MakeGroup(_ js.Value, args []js.Value) interface{} {
 	// (membershipBytes, message, name []byte) ([]byte, error)
 	membershipBytes := utils.CopyBytesToGo(args[0])
 	message := utils.CopyBytesToGo(args[1])
 	name := utils.CopyBytesToGo(args[2])
 
-	report, err := g.api.MakeGroup(membershipBytes, message, name)
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		sendReport, err := g.api.MakeGroup(membershipBytes, message, name)
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(sendReport))
+		}
 	}
 
-	return utils.CopyBytesToJS(report)
+	return utils.CreatePromise(promiseFn)
 }
 
 // ResendRequest resends a group request to all members in the group.
@@ -107,19 +109,21 @@ func (g *GroupChat) MakeGroup(_ js.Value, args []js.Value) interface{} {
 //  - args[0] - group's ID (Uint8Array). This can be found in the report
 //  returned by GroupChat.MakeGroup.
 //
-// Returns:
-//  - JSON of [bindings.GroupReport] (Uint8Array), which can be passed into
-//    Cmix.WaitForRoundResult to see if the group request message send
-//    succeeded.
-//  - Throws a TypeError if resending the request fails.
+// Returns a promise:
+//  - Resolves to the JSON of the [bindings.GroupReport], which can be passed
+//    into Cmix.WaitForRoundResult to see if the send succeeded (Uint8Array).
+//  - Rejected with an error if resending the request fails.
 func (g *GroupChat) ResendRequest(_ js.Value, args []js.Value) interface{} {
-	report, err := g.api.ResendRequest(utils.CopyBytesToGo(args[0]))
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		sendReport, err := g.api.ResendRequest(utils.CopyBytesToGo(args[0]))
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(sendReport))
+		}
 	}
 
-	return utils.CopyBytesToJS(report)
+	return utils.CreatePromise(promiseFn)
 }
 
 // JoinGroup allows a user to join a group when a request is received.
@@ -170,20 +174,25 @@ func (g *GroupChat) LeaveGroup(_ js.Value, args []js.Value) interface{} {
 //  - args[2] - the tag associated with the message (string). This tag may be
 //    empty.
 //
-// Returns:
-//  - JSON of [bindings.GroupSendReport] (Uint8Array), which can be passed into
-//    Cmix.WaitForRoundResult to see if the group message send succeeded.
+// Returns a promise:
+//  - Resolves to the JSON of the [bindings.GroupSendReport], which can be
+//    passed into Cmix.WaitForRoundResult to see if the send succeeded
+//    (Uint8Array).
+//  - Rejected with an error if sending the message to the group fails.
 func (g *GroupChat) Send(_ js.Value, args []js.Value) interface{} {
 	groupId := utils.CopyBytesToGo(args[0])
 	message := utils.CopyBytesToGo(args[1])
 
-	report, err := g.api.Send(groupId, message, args[2].String())
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		sendReport, err := g.api.Send(groupId, message, args[2].String())
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(sendReport))
+		}
 	}
 
-	return utils.CopyBytesToJS(report)
+	return utils.CreatePromise(promiseFn)
 }
 
 // GetGroups returns a list of group IDs that the user is a member of.
diff --git a/wasm/identity.go b/wasm/identity.go
index 83911a93b9ca67db58c57fa6b6a6a8ba26e0d262..2b0f2d392217bdc789da0be953c10b443e0fe818 100644
--- a/wasm/identity.go
+++ b/wasm/identity.go
@@ -68,33 +68,39 @@ func LoadReceptionIdentity(_ js.Value, args []js.Value) interface{} {
 // MakeReceptionIdentity generates a new cryptographic identity for receiving
 // messages.
 //
-// Returns:
-//  - JSON of the [xxdk.ReceptionIdentity] object (Uint8Array)
-//  - throws a TypeError if creating a new identity fails
+// Returns a promise:
+//  - Resolves to the JSON of the [xxdk.ReceptionIdentity] object (Uint8Array).
+//  - Rejected with an error if creating a new identity fails.
 func (c *Cmix) MakeReceptionIdentity(js.Value, []js.Value) interface{} {
-	ri, err := c.api.MakeReceptionIdentity()
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		ri, err := c.api.MakeReceptionIdentity()
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(ri))
+		}
 	}
 
-	return utils.CopyBytesToJS(ri)
+	return utils.CreatePromise(promiseFn)
 }
 
 // MakeLegacyReceptionIdentity generates the legacy identity for receiving
 // messages.
 //
-// Returns:
-//  - JSON of the [xxdk.ReceptionIdentity] object (Uint8Array)
-//  - throws a TypeError if creating a new legacy identity fails
+// Returns a promise:
+//  - Resolves to the JSON of the [xxdk.ReceptionIdentity] object (Uint8Array).
+//  - Rejected with an error if creating a new legacy identity fails.
 func (c *Cmix) MakeLegacyReceptionIdentity(js.Value, []js.Value) interface{} {
-	ri, err := c.api.MakeLegacyReceptionIdentity()
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		ri, err := c.api.MakeLegacyReceptionIdentity()
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(ri))
+		}
 	}
 
-	return utils.CopyBytesToJS(ri)
+	return utils.CreatePromise(promiseFn)
 }
 
 // GetReceptionRegistrationValidationSignature returns the signature provided by
@@ -104,7 +110,8 @@ func (c *Cmix) MakeLegacyReceptionIdentity(js.Value, []js.Value) interface{} {
 //  - signature (Uint8Array)
 func (c *Cmix) GetReceptionRegistrationValidationSignature(
 	js.Value, []js.Value) interface{} {
-	return utils.CopyBytesToJS(c.api.GetReceptionRegistrationValidationSignature())
+	return utils.CopyBytesToJS(
+		c.api.GetReceptionRegistrationValidationSignature())
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/wasm/logging.go b/wasm/logging.go
index 15aed1a96d8e4fe93aae7ca372a8c66aca648430..450d813709ec059f4ad392f320f9666a70211ede 100644
--- a/wasm/logging.go
+++ b/wasm/logging.go
@@ -100,14 +100,13 @@ func LogToFile(_ js.Value, args []js.Value) interface{} {
 		return nil
 	}
 
-	// Create new buffer of the specified size
-	b, err := circbuf.NewBuffer(int64(args[2].Int()))
+	// Create new log file output
+	ll, err := NewLogFile(args[1].String(), threshold, args[2].Int())
 	if err != nil {
 		utils.Throw(utils.TypeError, err)
 		return nil
 	}
 
-	ll := &LogFile{args[1].String(), threshold, b}
 	logListeners = append(logListeners, ll.Listen)
 	jww.SetLogListeners(logListeners...)
 
@@ -251,6 +250,20 @@ type LogFile struct {
 	b         *circbuf.Buffer
 }
 
+func NewLogFile(name string, threshold jww.Threshold, maxSize int) (*LogFile, error) {
+	// Create new buffer of the specified size
+	b, err := circbuf.NewBuffer(int64(maxSize))
+	if err != nil {
+		return nil, err
+	}
+
+	return &LogFile{
+		name:      name,
+		threshold: threshold,
+		b:         b,
+	}, nil
+}
+
 // newLogFileJS creates a new Javascript compatible object
 // (map[string]interface{}) that matches the LogFile structure.
 func newLogFileJS(lf *LogFile) map[string]interface{} {
@@ -272,8 +285,6 @@ func (lf *LogFile) Listen(t jww.Threshold) io.Writer {
 		return nil
 	}
 
-	lf.b.TotalWritten()
-
 	return lf.b
 }
 
diff --git a/wasm/ndf.go b/wasm/ndf.go
index 7e00d3d988973c444afef910876cbecc67606fe5..0d99bc9e58f4680a232d86d29956c51d5be5a85c 100644
--- a/wasm/ndf.go
+++ b/wasm/ndf.go
@@ -23,15 +23,20 @@ import (
 // Parameters:
 //  - args[0] - The URL to download from (string).
 //  - args[1] - The NDF certificate (string).
-// Returns:
-//  - JSON of the NDF (Uint8Array).
+//
+// Returns a promise:
+//  - Resolves to the JSON of the NDF ([ndf.NetworkDefinition]) (Uint8Array).
+//  - Rejected with an error if downloading fails.
 func DownloadAndVerifySignedNdfWithUrl(_ js.Value, args []js.Value) interface{} {
-	ndf, err := bindings.DownloadAndVerifySignedNdfWithUrl(
-		args[0].String(), args[1].String())
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		ndf, err := bindings.DownloadAndVerifySignedNdfWithUrl(
+			args[0].String(), args[1].String())
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(ndf))
+		}
 	}
 
-	return utils.CopyBytesToJS(ndf)
+	return utils.CreatePromise(promiseFn)
 }
diff --git a/wasm/params.go b/wasm/params.go
index accafbc3166e80f6d489510e7cc5f9fc0beabae2..71c7331642a6411dfb56cacaa1bccfabb3259ddf 100644
--- a/wasm/params.go
+++ b/wasm/params.go
@@ -20,7 +20,7 @@ import (
 // to change cMix settings.
 //
 // Returns:
-//  - JSON of [xxdk.CMIXParams] (Uint8Array)
+//  - JSON of [xxdk.CMIXParams] (Uint8Array).
 func GetDefaultCMixParams(js.Value, []js.Value) interface{} {
 	return utils.CopyBytesToJS(bindings.GetDefaultCMixParams())
 }
@@ -30,7 +30,7 @@ func GetDefaultCMixParams(js.Value, []js.Value) interface{} {
 // to change E2E settings.
 //
 // Returns:
-//  - JSON of [xxdk.E2EParams] (Uint8Array)
+//  - JSON of [xxdk.E2EParams] (Uint8Array).
 func GetDefaultE2EParams(js.Value, []js.Value) interface{} {
 	return utils.CopyBytesToJS(bindings.GetDefaultE2EParams())
 }
@@ -40,7 +40,7 @@ func GetDefaultE2EParams(js.Value, []js.Value) interface{} {
 // modify the JSON to change file transfer settings.
 //
 // Returns:
-//  - JSON of [fileTransfer.Params] (Uint8Array)
+//  - JSON of [fileTransfer.Params] (Uint8Array).
 func GetDefaultFileTransferParams(js.Value, []js.Value) interface{} {
 	return utils.CopyBytesToJS(bindings.GetDefaultFileTransferParams())
 }
@@ -50,7 +50,7 @@ func GetDefaultFileTransferParams(js.Value, []js.Value) interface{} {
 // the JSON to change single use settings.
 //
 // Returns:
-//  - JSON of [single.RequestParams] (Uint8Array)
+//  - JSON of [single.RequestParams] (Uint8Array).
 func GetDefaultSingleUseParams(js.Value, []js.Value) interface{} {
 	return utils.CopyBytesToJS(bindings.GetDefaultSingleUseParams())
 }
@@ -60,7 +60,7 @@ func GetDefaultSingleUseParams(js.Value, []js.Value) interface{} {
 // modify the JSON to change single use settings.
 //
 // Returns:
-//  - JSON of [fileTransfer.e2e.Params] (Uint8Array)
+//  - JSON of [fileTransfer.e2e.Params] (Uint8Array).
 func GetDefaultE2eFileTransferParams(js.Value, []js.Value) interface{} {
 	return utils.CopyBytesToJS(bindings.GetDefaultSingleUseParams())
 }
diff --git a/wasm/restlike.go b/wasm/restlike.go
index a12d8ee19b5e6e5501174a88f94ae40ce345f955..94c789b1a8a6852363d0e0afaf277264d7dff52b 100644
--- a/wasm/restlike.go
+++ b/wasm/restlike.go
@@ -23,23 +23,29 @@ import (
 //  - args[2] - JSON of [bindings.RestlikeMessage] (Uint8Array).
 //  - args[3] - JSON of [xxdk.E2EParams] (Uint8Array).
 //
-// Returns:
-//  - JSON of [bindings.RestlikeMessage] (Uint8Array).
-//  - Throws a TypeError if parsing the parameters or making the request fails.
+// Returns a promise:
+//  - Resolves to the JSON of the [bindings.RestlikeMessage], which can be
+//    passed into Cmix.WaitForRoundResult to see if the send succeeded
+//    (Uint8Array).
+//  - Rejected with an error if parsing the parameters or making the request
+//    fails.
 func RestlikeRequest(_ js.Value, args []js.Value) interface{} {
 	cmixId := args[0].Int()
 	connectionID := args[1].Int()
 	request := utils.CopyBytesToGo(args[2])
 	e2eParamsJSON := utils.CopyBytesToGo(args[3])
 
-	msg, err := bindings.RestlikeRequest(
-		cmixId, connectionID, request, e2eParamsJSON)
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		msg, err := bindings.RestlikeRequest(
+			cmixId, connectionID, request, e2eParamsJSON)
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(msg))
+		}
 	}
 
-	return utils.CopyBytesToJS(msg)
+	return utils.CreatePromise(promiseFn)
 }
 
 // RestlikeRequestAuth performs an authenticated restlike request.
@@ -50,21 +56,27 @@ func RestlikeRequest(_ js.Value, args []js.Value) interface{} {
 //  - args[2] - JSON of [bindings.RestlikeMessage] (Uint8Array).
 //  - args[3] - JSON of [xxdk.E2EParams] (Uint8Array).
 //
-// Returns:
-//  - JSON of [bindings.RestlikeMessage] (Uint8Array).
-//  - Throws a TypeError if parsing the parameters or making the request fails.
+// Returns a promise:
+//  - Resolves to the JSON of the [bindings.RestlikeMessage], which can be
+//    passed into Cmix.WaitForRoundResult to see if the send succeeded
+//    (Uint8Array).
+//  - Rejected with an error if parsing the parameters or making the request
+//    fails.
 func RestlikeRequestAuth(_ js.Value, args []js.Value) interface{} {
 	cmixId := args[0].Int()
 	authConnectionID := args[1].Int()
 	request := utils.CopyBytesToGo(args[2])
 	e2eParamsJSON := utils.CopyBytesToGo(args[3])
 
-	msg, err := bindings.RestlikeRequestAuth(
-		cmixId, authConnectionID, request, e2eParamsJSON)
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		msg, err := bindings.RestlikeRequestAuth(
+			cmixId, authConnectionID, request, e2eParamsJSON)
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(msg))
+		}
 	}
 
-	return utils.CopyBytesToJS(msg)
+	return utils.CreatePromise(promiseFn)
 }
diff --git a/wasm/restlikeSingle.go b/wasm/restlikeSingle.go
index 53f5070f25d86baa60f6d4172553ffcd603be1ea..c446da67dcbf127076ba5c50f085026a1e29f17d 100644
--- a/wasm/restlikeSingle.go
+++ b/wasm/restlikeSingle.go
@@ -33,22 +33,28 @@ func (rlc *restlikeCallback) Callback(payload []byte, err error) {
 //  - args[2] - JSON of [bindings.RestlikeMessage] (Uint8Array).
 //  - args[3] - JSON of [single.RequestParams] (Uint8Array).
 //
-// Returns:
-//  - JSON of [restlike.Message] (Uint8Array).
-//  - Throws a TypeError if parsing the parameters or making the request fails.
+// Returns a promise:
+//  - Resolves to the JSON of the [bindings.Message], which can be passed into
+//    Cmix.WaitForRoundResult to see if the send succeeded (Uint8Array).
+//  - Rejected with an error if parsing the parameters or making the request
+//    fails.
 func RequestRestLike(_ js.Value, args []js.Value) interface{} {
 	e2eID := args[0].Int()
 	recipient := utils.CopyBytesToGo(args[1])
 	request := utils.CopyBytesToGo(args[2])
 	paramsJSON := utils.CopyBytesToGo(args[3])
 
-	msg, err := bindings.RequestRestLike(e2eID, recipient, request, paramsJSON)
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		msg, err := bindings.RequestRestLike(
+			e2eID, recipient, request, paramsJSON)
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(msg))
+		}
 	}
 
-	return utils.CopyBytesToJS(msg)
+	return utils.CreatePromise(promiseFn)
 }
 
 // AsyncRequestRestLike sends an asynchronous restlike request to a given
@@ -74,12 +80,13 @@ func AsyncRequestRestLike(_ js.Value, args []js.Value) interface{} {
 	paramsJSON := utils.CopyBytesToGo(args[3])
 	cb := &restlikeCallback{utils.WrapCB(args[4], "Callback")}
 
-	err := bindings.AsyncRequestRestLike(
-		e2eID, recipient, request, paramsJSON, cb)
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
-	}
+	go func() {
+		err := bindings.AsyncRequestRestLike(
+			e2eID, recipient, request, paramsJSON, cb)
+		if err != nil {
+			utils.Throw(utils.TypeError, err)
+		}
+	}()
 
 	return nil
 }
diff --git a/wasm/secrets.go b/wasm/secrets.go
index 5a7b7127af4cfa5d5292f941553580fc672c086c..cf7275efaa2dc01b26257868c60f27d05779317e 100644
--- a/wasm/secrets.go
+++ b/wasm/secrets.go
@@ -20,7 +20,7 @@ import (
 //
 // Parameters:
 //  - args[0] - The size of secret. It should be set to 32, but can be set
-//   higher in certain cases, but not lower (int).
+//    higher in certain cases, but not lower (int).
 //
 // Returns:
 //  - secret password (Uint8Array).
diff --git a/wasm/single.go b/wasm/single.go
index a322d55d21209ce52e05209617429233b47e7516..f14509967745f601499901bff6c7ed3052467d0e 100644
--- a/wasm/single.go
+++ b/wasm/single.go
@@ -31,10 +31,11 @@ import (
 //    is a Javascript object that has functions that implement the
 //    [bindings.SingleUseResponse] interface.
 //
-// Returns:
-//  - JSON [bindings.SingleUseSendReport], which can be passed into
-//    Cmix.WaitForRoundResult to see if the send succeeded (Uint8Array).
-//  - Throws a TypeError if transmission fails.
+// Returns a promise:
+//  - Resolves to the JSON of the [bindings.SingleUseSendReport], which can be
+//    passed into Cmix.WaitForRoundResult to see if the send succeeded
+//    (Uint8Array).
+//  - Rejected with an error if transmission fails.
 func TransmitSingleUse(_ js.Value, args []js.Value) interface{} {
 	e2eID := args[0].Int()
 	recipient := utils.CopyBytesToGo(args[1])
@@ -43,14 +44,17 @@ func TransmitSingleUse(_ js.Value, args []js.Value) interface{} {
 	paramsJSON := utils.CopyBytesToGo(args[4])
 	responseCB := &singleUseResponse{utils.WrapCB(args[5], "Callback")}
 
-	report, err := bindings.TransmitSingleUse(
-		e2eID, recipient, tag, payload, paramsJSON, responseCB)
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		sendReport, err := bindings.TransmitSingleUse(
+			e2eID, recipient, tag, payload, paramsJSON, responseCB)
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(sendReport))
+		}
 	}
 
-	return utils.CopyBytesToJS(report)
+	return utils.CreatePromise(promiseFn)
 }
 
 // Listen starts a single-use listener on a given tag using the passed in E2e
diff --git a/wasm/ud.go b/wasm/ud.go
index f57b31ac6ef130a2c57ebe2c78b4da54ea87d6f2..570419544ff518b22096e87ab8a5e4176c426306 100644
--- a/wasm/ud.go
+++ b/wasm/ud.go
@@ -300,10 +300,11 @@ func (ulc *udLookupCallback) Callback(contactBytes []byte, err error) {
 //  - args[3] - JSON of [id.ID] for the user to look up (Uint8Array).
 //  - args[4] - JSON of [single.RequestParams] (Uint8Array).
 //
-// Returns:
-//  - JSON of [bindings.SingleUseSendReport], which can be passed into
-//    Cmix.WaitForRoundResult to see if the send succeeded.
-//  - Throws a TypeError if the lookup fails.
+// Returns a promise:
+//  - Resolves to the JSON of the [bindings.SingleUseSendReport], which can be
+//    passed into Cmix.WaitForRoundResult to see if the send succeeded
+//    (Uint8Array).
+//  - Rejected with an error if the lookup fails.
 func LookupUD(_ js.Value, args []js.Value) interface{} {
 	e2eID := args[0].Int()
 	udContact := utils.CopyBytesToGo(args[1])
@@ -311,14 +312,17 @@ func LookupUD(_ js.Value, args []js.Value) interface{} {
 	lookupId := utils.CopyBytesToGo(args[3])
 	singleRequestParamsJSON := utils.CopyBytesToGo(args[4])
 
-	report, err := bindings.LookupUD(
-		e2eID, udContact, cb, lookupId, singleRequestParamsJSON)
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		sendReport, err := bindings.LookupUD(
+			e2eID, udContact, cb, lookupId, singleRequestParamsJSON)
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(sendReport))
+		}
 	}
 
-	return utils.CopyBytesToJS(report)
+	return utils.CreatePromise(promiseFn)
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -347,10 +351,11 @@ func (usc *udSearchCallback) Callback(contactListJSON []byte, err error) {
 //  - args[2] - JSON of [fact.FactList] (Uint8Array).
 //  - args[4] - JSON of [single.RequestParams] (Uint8Array).
 //
-// Returns:
-//  - JSON of [bindings.SingleUseSendReport], which can be passed into
-//    Cmix.WaitForRoundResult to see if the send succeeded.
-//  - Throws a TypeError if the search fails.
+// Returns a promise:
+//  - Resolves to the JSON of the [bindings.SingleUseSendReport], which can be
+//    passed into Cmix.WaitForRoundResult to see if the send succeeded
+//    (Uint8Array).
+//  - Rejected with an error if the search fails.
 func SearchUD(_ js.Value, args []js.Value) interface{} {
 	e2eID := args[0].Int()
 	udContact := utils.CopyBytesToGo(args[1])
@@ -358,12 +363,15 @@ func SearchUD(_ js.Value, args []js.Value) interface{} {
 	factListJSON := utils.CopyBytesToGo(args[3])
 	singleRequestParamsJSON := utils.CopyBytesToGo(args[4])
 
-	report, err := bindings.SearchUD(
-		e2eID, udContact, cb, factListJSON, singleRequestParamsJSON)
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
+	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
+		sendReport, err := bindings.SearchUD(
+			e2eID, udContact, cb, factListJSON, singleRequestParamsJSON)
+		if err != nil {
+			reject(utils.JsTrace(err))
+		} else {
+			resolve(utils.CopyBytesToJS(sendReport))
+		}
 	}
 
-	return utils.CopyBytesToJS(report)
+	return utils.CreatePromise(promiseFn)
 }