diff --git a/go.mod b/go.mod
index 2dafdb0efb19d313011db460766d1afba0039306..c5a0f25b914d42151fc9deaa19808f492a8ae298 100644
--- a/go.mod
+++ b/go.mod
@@ -7,8 +7,8 @@ require (
 	github.com/hack-pad/go-indexeddb v0.2.0
 	github.com/pkg/errors v0.9.1
 	github.com/spf13/jwalterweatherman v1.1.0
-	gitlab.com/elixxir/client v1.5.1-0.20220915201734-388210df879d
-	gitlab.com/elixxir/crypto v0.0.7-0.20220913220142-ab0771bad0af
+	gitlab.com/elixxir/client v1.5.1-0.20220919182956-8e7459d57631
+	gitlab.com/elixxir/crypto v0.0.7-0.20220919183519-5bbca98a2c00
 	gitlab.com/xx_network/primitives v0.0.4-0.20220809193445-9fc0a5209548
 )
 
diff --git a/go.sum b/go.sum
index a874f99fb854d0afc1aee90cb68c7e1e957e36be..f606452c35a4cac0bfc2be8bf50019f3c80a76bb 100644
--- a/go.sum
+++ b/go.sum
@@ -614,14 +614,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.20220915201734-388210df879d h1:pD9VVvD/7/4vf0ieP/7DjvoVRkvdrYmlS+d6BxDw0i4=
-gitlab.com/elixxir/client v1.5.1-0.20220915201734-388210df879d/go.mod h1:N8GdwIkvdgc/cz2i5JY+t+QoNDRnYM1HL5XbMJvR9b0=
+gitlab.com/elixxir/client v1.5.1-0.20220919182956-8e7459d57631 h1:xzMTOJ0nohwFIo2PT017q84feCHdDGTct+rGz8zr4ac=
+gitlab.com/elixxir/client v1.5.1-0.20220919182956-8e7459d57631/go.mod h1:x6QH8UsPUXpKB/B7byWwsCTBCjx+qiiE7hMvA3rK6v8=
 gitlab.com/elixxir/comms v0.0.4-0.20220913220502-eed192f654bd h1:2nHE7EoptSTBFjCxMeAveKT6urbguCwgg8Jx7XYEVe4=
 gitlab.com/elixxir/comms v0.0.4-0.20220913220502-eed192f654bd/go.mod h1:AO6XkMhaHJW8eXlgL5m3UUcJqsSP8F5Wm1GX+wyq/rw=
 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.20220913220142-ab0771bad0af h1:L1eOTS6m8dlCheAFOf/S3C+IcORd2R8f5qdyVRVelWA=
 gitlab.com/elixxir/crypto v0.0.7-0.20220913220142-ab0771bad0af/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok=
+gitlab.com/elixxir/crypto v0.0.7-0.20220919174648-8d1b7f5cacc4/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok=
+gitlab.com/elixxir/crypto v0.0.7-0.20220919183519-5bbca98a2c00 h1:BZ2v6dfdYOUQHbssWJyHv+jNZheORvz4O1nPT8Y2S94=
+gitlab.com/elixxir/crypto v0.0.7-0.20220919183519-5bbca98a2c00/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok=
 gitlab.com/elixxir/ekv v0.2.1 h1:dtwbt6KmAXG2Tik5d60iDz2fLhoFBgWwST03p7T+9Is=
 gitlab.com/elixxir/ekv v0.2.1/go.mod h1:USLD7xeDnuZEavygdrgzNEwZXeLQJK/w1a+htpN+JEU=
 gitlab.com/elixxir/primitives v0.0.0-20200731184040-494269b53b4d/go.mod h1:OQgUZq7SjnE0b+8+iIAT2eqQF+2IFHn73tOo+aV11mg=
diff --git a/indexedDb/implementation_test.go b/indexedDb/implementation_test.go
index a9efbcd182f56b77ddeab1127a5de2a2d58fe9be..3f008359d7ff0eac2f134d8f718e0dd75f57f6cb 100644
--- a/indexedDb/implementation_test.go
+++ b/indexedDb/implementation_test.go
@@ -89,14 +89,12 @@ func TestWasmModel_JoinChannel_LeaveChannel(t *testing.T) {
 		Name:        "test",
 		Description: "test",
 		Salt:        nil,
-		RsaPubKey:   nil,
 	}
 	testChannel2 := &cryptoBroadcast.Channel{
 		ReceptionID: id.NewIdFromString("test2", id.Generic, t),
 		Name:        "test2",
 		Description: "test2",
 		Salt:        nil,
-		RsaPubKey:   nil,
 	}
 	eventModel.JoinChannel(testChannel)
 	eventModel.JoinChannel(testChannel2)
diff --git a/main.go b/main.go
index 45c1bc9439a40937500b611a320efa49d292197a..6dbce96e9cb2372b3521d5f33b884fd9b33709cd 100644
--- a/main.go
+++ b/main.go
@@ -41,11 +41,13 @@ func main() {
 	js.Global().Set("InitializeBackup", js.FuncOf(wasm.InitializeBackup))
 	js.Global().Set("ResumeBackup", js.FuncOf(wasm.ResumeBackup))
 
-	// wasm/broadcast.go
-	js.Global().Set("NewBroadcastChannel", js.FuncOf(wasm.NewBroadcastChannel))
-
 	// wasm/channels.go
 	js.Global().Set("NewChannelsManager", js.FuncOf(wasm.NewChannelsManager))
+	js.Global().Set("NewChannelsManagerWithIndexedDb",
+		js.FuncOf(wasm.NewChannelsManagerWithIndexedDb))
+	js.Global().Set("NewChannelsManagerWithIndexedDb",
+		js.FuncOf(wasm.GenerateChannel))
+	js.Global().Set("GetChannelInfo", js.FuncOf(wasm.GetChannelInfo))
 
 	// wasm/cmix.go
 	js.Global().Set("NewCmix", js.FuncOf(wasm.NewCmix))
diff --git a/wasm/broadcast.go b/wasm/broadcast.go
deleted file mode 100644
index f87f43f69666e4f0c29099dcccb42b02a15c20ea..0000000000000000000000000000000000000000
--- a/wasm/broadcast.go
+++ /dev/null
@@ -1,193 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright © 2022 xx foundation                                             //
-//                                                                            //
-// Use of this source code is governed by a license that can be found in the  //
-// LICENSE file.                                                              //
-////////////////////////////////////////////////////////////////////////////////
-
-//go:build js && wasm
-
-package wasm
-
-import (
-	"gitlab.com/elixxir/client/bindings"
-	"gitlab.com/elixxir/xxdk-wasm/utils"
-	"syscall/js"
-)
-
-// Channel wraps the [bindings.Channel] object so its methods can be wrapped to
-// be Javascript compatible.
-type Channel struct {
-	api *bindings.Channel
-}
-
-// newE2eJS creates a new Javascript compatible object (map[string]interface{})
-// that matches the E2e structure.
-func newChannelJS(api *bindings.Channel) map[string]interface{} {
-	c := Channel{api}
-	chMap := map[string]interface{}{
-		"Listen":                   c.Listen,
-		"Broadcast":                c.Broadcast,
-		"BroadcastAsymmetric":      c.BroadcastAsymmetric,
-		"MaxPayloadSize":           c.MaxPayloadSize,
-		"MaxAsymmetricPayloadSize": c.MaxAsymmetricPayloadSize,
-		"Get":                      c.Get,
-		"Stop":                     c.Stop,
-	}
-
-	return chMap
-}
-
-// NewBroadcastChannel creates a bindings-layer broadcast channel and starts
-// listening for new messages
-//
-// Parameters:
-//  - args[0] - ID of Cmix object in tracker (int).
-//  - args[1] - JSON of [bindings.ChannelDef] (Uint8Array).
-//
-// Returns:
-//  - Javascript representation of the Channel object.
-//  - Throws a TypeError if creation fails.
-func NewBroadcastChannel(_ js.Value, args []js.Value) interface{} {
-	channelDefinition := utils.CopyBytesToGo(args[1])
-
-	api, err := bindings.NewBroadcastChannel(args[0].Int(), channelDefinition)
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
-	}
-
-	return newChannelJS(api)
-}
-
-// broadcastListener wraps Javascript callbacks to adhere to the
-// [bindings.BroadcastListener] interface.
-type broadcastListener struct {
-	callback func(args ...interface{}) js.Value
-}
-
-// Callback is used to listen for broadcast messages.
-//
-// Parameters:
-//  - payload - returns the JSON of [bindings.E2ESendReport], which can be
-//    passed into cmix.WaitForRoundResult to see if the send succeeded
-//    (Uint8Array).
-//  - err - returns an error on failure (Error).
-func (bl *broadcastListener) Callback(payload []byte, err error) {
-	bl.callback(utils.CopyBytesToJS(payload), utils.JsTrace(err))
-}
-
-// Listen registers a BroadcastListener for a given method. This allows users to
-// handle incoming broadcast messages.
-//
-// Parameters:
-//  - args[0] - Javascript object that has functions that implement the
-//    [bindings.BroadcastListener] interface.
-//  - args[1] - number corresponding to broadcast.Method constant, 0 for
-//    symmetric or 1 for asymmetric (int).
-//
-// Returns:
-//  - Throws a TypeError if registering the listener fails.
-func (c *Channel) Listen(_ js.Value, args []js.Value) interface{} {
-	err := c.api.Listen(
-		&broadcastListener{utils.WrapCB(args[0], "Callback")}, args[1].Int())
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
-	}
-
-	return nil
-}
-
-// Broadcast sends a given payload over the broadcast channel using symmetric
-// broadcast.
-//
-// Parameters:
-//  - args[0] - payload (Uint8Array).
-//
-// 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{} {
-	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.CreatePromise(promiseFn)
-}
-
-// BroadcastAsymmetric sends a given payload over the broadcast channel using
-// asymmetric broadcast. This mode of encryption requires a private key.
-//
-// Parameters:
-//  - args[0] - payload (Uint8Array).
-//  - args[1] - private key (Uint8Array).
-//
-// 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{} {
-	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.CreatePromise(promiseFn)
-}
-
-// MaxPayloadSize returns the maximum possible payload size which can be
-// broadcast.
-//
-// Returns:
-//  - int
-func (c *Channel) MaxPayloadSize(js.Value, []js.Value) interface{} {
-	return c.api.MaxPayloadSize()
-}
-
-// MaxAsymmetricPayloadSize returns the maximum possible payload size which can
-// be broadcast.
-//
-// Returns:
-//  - int
-func (c *Channel) MaxAsymmetricPayloadSize(js.Value, []js.Value) interface{} {
-	return c.api.MaxAsymmetricPayloadSize()
-}
-
-// Get returns the JSON of the channel definition.
-//
-// Returns:
-//  - JSON of [bindings.ChannelDef] (Uint8Array).
-//  - Throws a TypeError if marshalling fails.
-func (c *Channel) Get(js.Value, []js.Value) interface{} {
-	def, err := c.api.Get()
-	if err != nil {
-		utils.Throw(utils.TypeError, err)
-		return nil
-	}
-
-	return utils.CopyBytesToJS(def)
-}
-
-// Stop stops the channel from listening for more messages.
-func (c *Channel) Stop(js.Value, []js.Value) interface{} {
-	c.api.Stop()
-	return nil
-}
diff --git a/wasm/broadcast_test.go b/wasm/broadcast_test.go
deleted file mode 100644
index 3541c5c09084b29e37c7ef37328969dc27b03d1b..0000000000000000000000000000000000000000
--- a/wasm/broadcast_test.go
+++ /dev/null
@@ -1,56 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// Copyright © 2022 xx foundation                                             //
-//                                                                            //
-// Use of this source code is governed by a license that can be found in the  //
-// LICENSE file.                                                              //
-////////////////////////////////////////////////////////////////////////////////
-
-//go:build js && wasm
-
-package wasm
-
-import (
-	"gitlab.com/elixxir/client/bindings"
-	"reflect"
-	"testing"
-)
-
-// Tests that the map representing Channel returned by newChannelJS contains
-// all of the methods on Channel.
-func Test_newChannelJS(t *testing.T) {
-	chanType := reflect.TypeOf(&Channel{})
-
-	ch := newChannelJS(&bindings.Channel{})
-	if len(ch) != chanType.NumMethod() {
-		t.Errorf("Channel JS object does not have all methods."+
-			"\nexpected: %d\nreceived: %d", chanType.NumMethod(), len(ch))
-	}
-
-	for i := 0; i < chanType.NumMethod(); i++ {
-		method := chanType.Method(i)
-
-		if _, exists := ch[method.Name]; !exists {
-			t.Errorf("Method %s does not exist.", method.Name)
-		}
-	}
-}
-
-// Tests that Channel has all the methods that [bindings.Channel] has.
-func Test_ChannelMethods(t *testing.T) {
-	chanType := reflect.TypeOf(&Channel{})
-	binChanType := reflect.TypeOf(&bindings.Channel{})
-
-	if binChanType.NumMethod() != chanType.NumMethod() {
-		t.Errorf("WASM Channel object does not have all methods from bindings."+
-			"\nexpected: %d\nreceived: %d",
-			binChanType.NumMethod(), chanType.NumMethod())
-	}
-
-	for i := 0; i < binChanType.NumMethod(); i++ {
-		method := binChanType.Method(i)
-
-		if _, exists := chanType.MethodByName(method.Name); !exists {
-			t.Errorf("Method %s does not exist.", method.Name)
-		}
-	}
-}
diff --git a/wasm/channels.go b/wasm/channels.go
index 431df0eabb5e9db2145d335c3cd13a694ff67711..329275ce2a53b03684c7a944daa4c191e18eed3b 100644
--- a/wasm/channels.go
+++ b/wasm/channels.go
@@ -9,6 +9,7 @@ package wasm
 
 import (
 	"gitlab.com/elixxir/client/bindings"
+	"gitlab.com/elixxir/xxdk-wasm/indexedDb"
 	"gitlab.com/elixxir/xxdk-wasm/utils"
 	"syscall/js"
 )
@@ -32,8 +33,6 @@ func newChannelsManagerJS(api *bindings.ChannelsManager) map[string]interface{}
 		"GetID":         js.FuncOf(cm.GetID),
 		"JoinChannel":   js.FuncOf(cm.JoinChannel),
 		"GetChannels":   js.FuncOf(cm.GetChannels),
-		"GetChannelId":  js.FuncOf(cm.GetChannelId),
-		"GetChannel":    js.FuncOf(cm.GetChannel),
 		"LeaveChannel":  js.FuncOf(cm.LeaveChannel),
 		"ReplayChannel": js.FuncOf(cm.ReplayChannel),
 
@@ -62,13 +61,13 @@ func (ch *ChannelsManager) GetID(js.Value, []js.Value) interface{} {
 // NewChannelsManager constructs a ChannelsManager.
 //
 // Parameters:
-//  - args[0] - ID of ChannelsManager object in tracker (int). This can be
-//    retrieved using [E2e.GetID].
+//  - args[0] - ID of E2e object in tracker (int). This can be retrieved using
+//    [E2e.GetID].
 //  - args[1] - ID of UserDiscovery object in tracker (int). This can be
 //    retrieved using [UserDiscovery.GetID].
 //
 // Returns:
-//  - Javascript representation of the ChannelsManager object.
+//  - Javascript representation of the [bindings.ChannelsManager] object.
 //  - Throws a TypeError if logging in fails.
 func NewChannelsManager(_ js.Value, args []js.Value) interface{} {
 	cm, err := bindings.NewChannelsManager(args[0].Int(), args[1].Int())
@@ -80,91 +79,144 @@ func NewChannelsManager(_ js.Value, args []js.Value) interface{} {
 	return newChannelsManagerJS(cm)
 }
 
-// JoinChannel joins the given channel. It will fail if the channel has already
-// been joined.
+// NewChannelsManagerWithIndexedDb constructs a ChannelsManager using an
+// indexedDb backend.
 //
 // Parameters:
-//  - args[0] - JSON of [bindings.ChannelDef] (Uint8Array).
+//  - args[0] - ID of E2e object in tracker (int). This can be retrieved using
+//    [E2e.GetID].
+//  - args[1] - ID of UserDiscovery object in tracker (int). This can be
+//    retrieved using [UserDiscovery.GetID].
+//  - args[2] - username (string).
 //
 // Returns:
-//  - Throws a TypeError if joining the channel fails.
-func (ch *ChannelsManager) JoinChannel(_ js.Value, args []js.Value) interface{} {
-	channelJson := utils.CopyBytesToGo(args[0])
+//  - Javascript representation of the [bindings.ChannelsManager] object.
+//  - Throws a TypeError if initialising indexedDb or created the new channel
+//    manager fails.
+func NewChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) interface{} {
+	em, err := indexedDb.NewWasmEventModel(args[2].String())
+	if err != nil {
+		utils.Throw(utils.TypeError, err)
+		return nil
+	}
 
-	err := ch.api.JoinChannel(channelJson)
+	cm, err := bindings.NewChannelsManagerGoEventModel(
+		args[0].Int(), args[1].Int(), em)
 	if err != nil {
 		utils.Throw(utils.TypeError, err)
 		return nil
 	}
 
-	return nil
+	return newChannelsManagerJS(cm)
 }
 
-// GetChannels returns the IDs of all channels that have been joined.
+// GenerateChannel is used to create a channel. This makes a new channel of
+// which you are the admin. It is only for making new channels, not joining
+// existing ones.
+//
+// It returns a pretty print of the channel and the private key.
+//
+// The name cannot be longer that ____ characters.
+//
+// The description cannot be longer than ___ and can only use ______ characters.
+//
+// Parameters:
+//  - args[0] - ID of Cmix object in tracker (int).
+//  - args[1] - The name of the new channel. The name cannot be longer than __
+//    characters and must contain only __ characters. It cannot be changed once
+//    a channel is created (string).
+//  - args[2] - The description of a channel. The description cannot be longer
+//    than __ characters and must contain only __ characters. It cannot be
+//    changed once a channel is created (string).
 //
 // Returns:
-//  - JSON of an array of marshalled [id.ID] (Uint8Array).
-//  - Throws a TypeError if getting the channels fails.
-func (ch *ChannelsManager) GetChannels(js.Value, []js.Value) interface{} {
-	channelList, err := ch.api.GetChannels()
+//  - JSON of [bindings.ChannelGeneration], which describes a generated channel.
+//    It contains both the public channel info and the private key for the
+//    channel in PEM format (Uint8Array).
+//  - Throws a TypeError if generating the channel fails.
+func GenerateChannel(_ js.Value, args []js.Value) interface{} {
+	gen, err := bindings.GenerateChannel(
+		args[0].Int(), args[1].String(), args[2].String())
 	if err != nil {
 		utils.Throw(utils.TypeError, err)
 		return nil
 	}
 
-	return utils.CopyBytesToJS(channelList)
+	return utils.CopyBytesToJS(gen)
 }
 
-// GetChannelId returns the ID of the channel given the channel's cryptographic
-// information.
+// GetChannelInfo returns the info about a channel from its public description.
 //
 // Parameters:
-//  - args[0] - JSON of [bindings.ChannelDef] (Uint8Array). This can be
-//    retrieved using [Channel.Get].
+//  - args[0] - The pretty print of the channel (string).
+//
+// The pretty print will be of the format:
+//  <XXChannel-v1:Test Channel,description:This is a test channel,secrets:pn0kIs6P1pHvAe7u8kUyf33GYVKmkoCX9LhCtvKJZQI=,3A5eB5pzSHyxN09w1kOVrTIEr5UyBbzmmd9Ga5Dx0XA=,0,0,/zChIlLr2p3Vsm2X4+3TiFapoapaTi8EJIisJSqwfGc=>
 //
 // Returns:
-//  - JSON of the channel [id.ID] (Uint8Array).
-//  - Throws a TypeError if getting the channel's ID fails.
-func (ch *ChannelsManager) GetChannelId(_ js.Value, args []js.Value) interface{} {
-	channelJson := utils.CopyBytesToGo(args[0])
-
-	chanID, err := ch.api.GetChannelId(channelJson)
+//  - JSON of [bindings.ChannelInfo], which describes all relevant channel info
+//    (Uint8Array).
+//  - Throws a TypeError if getting the channel info fails.
+func GetChannelInfo(_ js.Value, args []js.Value) interface{} {
+	ci, err := bindings.GetChannelInfo(args[1].String())
 	if err != nil {
 		utils.Throw(utils.TypeError, err)
 		return nil
 	}
 
-	return utils.CopyBytesToJS(chanID)
+	return utils.CopyBytesToJS(ci)
 }
 
-// GetChannel returns the underlying cryptographic structure for a given
-// channel.
+// JoinChannel joins the given channel. It will fail if the channel has already
+// been joined.
 //
 // Parameters:
-//  - args[0] - JSON of the channel [id.ID] (Uint8Array). This can be retrieved
-//    using [ChannelsManager.GetChannelId].
+//  - args[0] - A portable channel string. Should be received from another user
+//    or generated via GenerateChannel (string).
+//
+// The pretty print will be of the format:
+//  <XXChannel-v1:Test Channel,description:This is a test channel,secrets:pn0kIs6P1pHvAe7u8kUyf33GYVKmkoCX9LhCtvKJZQI=,3A5eB5pzSHyxN09w1kOVrTIEr5UyBbzmmd9Ga5Dx0XA=,0,0,/zChIlLr2p3Vsm2X4+3TiFapoapaTi8EJIisJSqwfGc=>"
 //
 // Returns:
-//  - JSON of [bindings.ChannelDef] (Uint8Array).
-//  - Throws a TypeError if getting the channel fails.
-func (ch *ChannelsManager) GetChannel(_ js.Value, args []js.Value) interface{} {
-	marshalledChanId := utils.CopyBytesToGo(args[0])
+//  - JSON of [bindings.ChannelInfo], which describes all relevant channel info
+//    (Uint8Array).
+//  - Throws a TypeError if joining the channel fails.
+func (ch *ChannelsManager) JoinChannel(_ js.Value, args []js.Value) interface{} {
+	ci, err := ch.api.JoinChannel(args[0].String())
+	if err != nil {
+		utils.Throw(utils.TypeError, err)
+		return nil
+	}
 
-	def, err := ch.api.GetChannel(marshalledChanId)
+	return utils.CopyBytesToJS(ci)
+}
+
+// GetChannels returns the IDs of all channels that have been joined.
+//
+// Returns:
+//  - JSON of an array of marshalled [id.ID] (Uint8Array).
+//  - Throws a TypeError if getting the channels fails.
+//
+// JSON Example:
+//  {
+//    U4x/lrFkvxuXu59LtHLon1sUhPJSCcnZND6SugndnVID",
+//    "15tNdkKbYXoMn58NO6VbDMDWFEyIhTWEGsvgcJsHWAgD"
+//  }
+func (ch *ChannelsManager) GetChannels(js.Value, []js.Value) interface{} {
+	channelList, err := ch.api.GetChannels()
 	if err != nil {
 		utils.Throw(utils.TypeError, err)
 		return nil
 	}
 
-	return utils.CopyBytesToJS(def)
+	return utils.CopyBytesToJS(channelList)
 }
 
 // LeaveChannel leaves the given channel. It will return an error if the channel
 // was not previously joined.
 //
 // Parameters:
-//  - args[0] - JSON of the channel [id.ID] (Uint8Array). This can be retrieved
-//    using [ChannelsManager.GetChannelId].
+//  - args[0] - JSON of the channel [id.ID] (Uint8Array).
 //
 // Returns:
 //  - Throws a TypeError if the channel does not exist.
@@ -184,8 +236,7 @@ func (ch *ChannelsManager) LeaveChannel(_ js.Value, args []js.Value) interface{}
 // memory (~3 weeks) over the event model.
 //
 // Parameters:
-//  - args[0] - JSON of the channel [id.ID] (Uint8Array). This can be retrieved
-//    using [ChannelsManager.GetChannelId].
+//  - args[0] - JSON of the channel [id.ID] (Uint8Array).
 //
 // Returns:
 //  - Throws a TypeError if the replay fails.
@@ -214,8 +265,7 @@ func (ch *ChannelsManager) ReplayChannel(_ js.Value, args []js.Value) interface{
 // on the use case.
 //
 // Parameters:
-//  - args[0] - JSON of the channel [id.ID] (Uint8Array). This can be retrieved
-//    using [ChannelsManager.GetChannelId].
+//  - args[0] - JSON of the channel [id.ID] (Uint8Array).
 //  - args[1] - The message type of the message. This will be a valid
 //    [channels.MessageType] (int).
 //  - args[2] - The contents of the message (Uint8Array).
@@ -257,8 +307,7 @@ func (ch *ChannelsManager) SendGeneric(_ js.Value, args []js.Value) interface{}
 //
 // Parameters:
 //  - args[0] - The PEM-encode admin RSA private key (Uint8Array).
-//  - args[1] - JSON of the channel [id.ID] (Uint8Array). This can be retrieved
-//    using [ChannelsManager.GetChannelId].
+//  - args[1] - JSON of the channel [id.ID] (Uint8Array).
 //  - args[2] - The message type of the message. This will be a valid
 //    [channels.MessageType] (int).
 //  - args[3] - The contents of the message (Uint8Array).
@@ -302,8 +351,7 @@ func (ch *ChannelsManager) SendAdminGeneric(_ js.Value, args []js.Value) interfa
 // lasting forever if [channels.ValidForever] is used.
 //
 // Parameters:
-//  - args[0] - JSON of the channel [id.ID] (Uint8Array). This can be retrieved
-//    using [ChannelsManager.GetChannelId].
+//  - args[0] - JSON of the channel [id.ID] (Uint8Array).
 //  - args[1] - The contents of the message (string).
 //  - args[2] - The lease of the message. This will be how long the message is
 //    valid until, in milliseconds. As per the [channels.Manager] documentation,
@@ -345,8 +393,7 @@ func (ch *ChannelsManager) SendMessage(_ js.Value, args []js.Value) interface{}
 // lasting forever if ValidForever is used.
 //
 // Parameters:
-//  - args[0] - JSON of the channel [id.ID] (Uint8Array). This can be retrieved
-//    using [ChannelsManager.GetChannelId].
+//  - args[0] - JSON of the channel [id.ID] (Uint8Array).
 //  - args[1] - The contents of the message. The message should be at most 510
 //    bytes. This is expected to be Unicode, and thus a string data type is
 //    expected (string).
@@ -391,8 +438,7 @@ func (ch *ChannelsManager) SendReply(_ js.Value, args []js.Value) interface{} {
 // Users will drop the reaction if they do not recognize the reactTo message.
 //
 // Parameters:
-//  - args[0] - JSON of the channel [id.ID] (Uint8Array). This can be retrieved
-//    using [ChannelsManager.GetChannelId].
+//  - args[0] - JSON of the channel [id.ID] (Uint8Array).
 //  - args[1] - The user's reaction. This should be a single emoji with no
 //    other characters. As such, a Unicode string is expected (string).
 //  - args[2] - JSON of [channel.MessageID] of the message you wish to reply to.
diff --git a/wasm/fileTransfer.go b/wasm/fileTransfer.go
index 1ca91aa4600444440457faaf7ad58c1a9d537139..2c2320f8d38f23eea1bfd9c54dd6583513f69c9e 100644
--- a/wasm/fileTransfer.go
+++ b/wasm/fileTransfer.go
@@ -148,8 +148,8 @@ func InitFileTransfer(_ js.Value, args []js.Value) interface{} {
 //  - args[2] - number of retries allowed (float)
 //  - args[3] - Javascript object that has functions that implement the
 //    [bindings.FileTransferSentProgressCallback] interface.
-//  - args[4] - duration to wait between progress callbacks triggering (string).
-//    Reference [time.ParseDuration] for info on valid duration strings.
+//  - args[4] - Duration, in milliseconds, to wait between progress callbacks
+//    triggering (int).
 //
 // Returns a promise:
 //  - Resolves to a unique ID for this file transfer (Uint8Array).
@@ -161,7 +161,7 @@ func (f *FileTransfer) Send(_ js.Value, args []js.Value) interface{} {
 	spc := &fileTransferSentProgressCallback{utils.WrapCB(args[3], "Callback")}
 
 	promiseFn := func(resolve, reject func(args ...interface{}) js.Value) {
-		ftID, err := f.api.Send(payload, recipientID, retry, spc, args[4].String())
+		ftID, err := f.api.Send(payload, recipientID, retry, spc, args[4].Int())
 		if err != nil {
 			reject(utils.JsTrace(err))
 		} else {
@@ -233,8 +233,8 @@ func (f *FileTransfer) CloseSend(_ js.Value, args []js.Value) interface{} {
 //  - args[0] - file transfer ID (Uint8Array).
 //  - args[1] - Javascript object that has functions that implement the
 //    [bindings.FileTransferSentProgressCallback] interface.
-//  - args[2] - duration to wait between progress callbacks triggering (string).
-//    Reference [time.ParseDuration] for info on valid duration strings.
+//  - args[2] - Duration, in milliseconds, to wait between progress callbacks
+//    triggering (int).
 //
 // Returns:
 //  - Throws a TypeError if registering the callback fails.
@@ -243,7 +243,7 @@ func (f *FileTransfer) RegisterSentProgressCallback(
 	tidBytes := utils.CopyBytesToGo(args[0])
 	spc := &fileTransferSentProgressCallback{utils.WrapCB(args[1], "Callback")}
 
-	err := f.api.RegisterSentProgressCallback(tidBytes, spc, args[2].String())
+	err := f.api.RegisterSentProgressCallback(tidBytes, spc, args[2].Int())
 	if err != nil {
 		utils.Throw(utils.TypeError, err)
 		return nil
@@ -261,8 +261,8 @@ func (f *FileTransfer) RegisterSentProgressCallback(
 //  - args[0] - file transfer ID (Uint8Array).
 //  - args[1] - Javascript object that has functions that implement the
 //    [bindings.FileTransferReceiveProgressCallback] interface.
-//  - args[2] - duration to wait between progress callbacks triggering (string).
-//    Reference [time.ParseDuration] for info on valid duration strings.
+//  - args[2] - Duration, in milliseconds, to wait between progress callbacks
+//    triggering (int).
 //
 // Returns:
 //  - Throws a TypeError if registering the callback fails.
@@ -272,7 +272,7 @@ func (f *FileTransfer) RegisterReceivedProgressCallback(
 	rpc := &fileTransferReceiveProgressCallback{utils.WrapCB(args[1], "Callback")}
 
 	err := f.api.RegisterReceivedProgressCallback(
-		tidBytes, rpc, args[2].String())
+		tidBytes, rpc, args[2].Int())
 	if err != nil {
 		utils.Throw(utils.TypeError, err)
 		return nil
diff --git a/wasm/group.go b/wasm/group.go
index 81708c452dfba0f92a307f58a46a9814a551560f..9e0249e8ebc76632e5c09deb639b289c6f197f9b 100644
--- a/wasm/group.go
+++ b/wasm/group.go
@@ -131,13 +131,13 @@ func (g *GroupChat) ResendRequest(_ js.Value, args []js.Value) interface{} {
 // with the same trackedGroupId.
 //
 // Parameters:
-//  - args[0] - ID of the Group object in tracker (int). This is received by
-//    [bindings.GroupRequest.Callback].
+//  - args[0] - The result of calling Group.Serialize on any [bindings.Group]
+//    object returned over the bindings (Uint8Array).
 //
 // Returns:
 //  - Throws a TypeError if joining the group fails.
 func (g *GroupChat) JoinGroup(_ js.Value, args []js.Value) interface{} {
-	err := g.api.JoinGroup(args[0].Int())
+	err := g.api.JoinGroup(utils.CopyBytesToGo(args[0]))
 	if err != nil {
 		utils.Throw(utils.TypeError, err)
 		return nil
@@ -256,7 +256,6 @@ func newGroupJS(api *bindings.Group) map[string]interface{} {
 	gMap := map[string]interface{}{
 		"GetName":        js.FuncOf(g.GetName),
 		"GetID":          js.FuncOf(g.GetID),
-		"GetTrackedID":   js.FuncOf(g.GetTrackedID),
 		"GetInitMessage": js.FuncOf(g.GetInitMessage),
 		"GetCreatedNano": js.FuncOf(g.GetCreatedNano),
 		"GetCreatedMS":   js.FuncOf(g.GetCreatedMS),
@@ -283,15 +282,6 @@ func (g *Group) GetID(js.Value, []js.Value) interface{} {
 	return utils.CopyBytesToJS(g.api.GetID())
 }
 
-// GetTrackedID returns the tracked ID of the Group object. This is used by the
-// backend tracker.
-//
-// Returns:
-//  - int
-func (g *Group) GetTrackedID(js.Value, []js.Value) interface{} {
-	return g.api.GetTrackedID()
-}
-
 // GetInitMessage returns initial message sent with the group request.
 //
 // Returns: