diff --git a/Makefile b/Makefile index 117f48a3a54be1a5a4ed6dd976d193e03adfbcdc..ef9bc2a690b2397ea8342e79aa5d5217fff7d4c7 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ build: update_release: GOFLAGS="" go get -d gitlab.com/elixxir/client@release GOFLAGS="" go get gitlab.com/elixxir/crypto@release + GOFLAGS="" go get gitlab.com/elixxir/primitives@release GOFLAGS="" go get gitlab.com/xx_network/primitives@release update_master: diff --git a/go.mod b/go.mod index c7017f57c4c9508a34a02966a60e9fb2da5df669..7ad5bd5a28679e5085b85792726e4bc68b0ce78c 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 gitlab.com/elixxir/client v1.5.1-0.20220924203712-7d4b1dce86b8 gitlab.com/elixxir/crypto v0.0.7-0.20220923233816-0364f1b203c6 + gitlab.com/elixxir/primitives v0.0.3-0.20220901220638-1acc75fabdc6 gitlab.com/xx_network/primitives v0.0.4-0.20220809193445-9fc0a5209548 ) @@ -54,7 +55,6 @@ require ( gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f // indirect gitlab.com/elixxir/comms v0.0.4-0.20220916185715-f1e9a5eda939 // 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.20220916185248-8a984b8594de // indirect gitlab.com/xx_network/crypto v0.0.5-0.20220913213008-98764f5b3287 // indirect gitlab.com/xx_network/ring v0.0.3-0.20220222211904-da613960ad93 // indirect diff --git a/go.sum b/go.sum index 05a97d5a1b6cb0dc391c88db0a90a8b37814f441..a6b844fe56cad8ffc710ab66934718a32b34ef1e 100644 --- a/go.sum +++ b/go.sum @@ -628,19 +628,13 @@ 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.20220920212200-25ceacdcbd31 h1:+Di3jF1Vdmr+gQGYwJOSKqbpRylTzLVP81fzkdkpegw= -gitlab.com/elixxir/client v1.5.1-0.20220920212200-25ceacdcbd31/go.mod h1:pX1uLFS8v6pNVzJEcfbMUrYPTWLPl8p71ghqW2Xm0Ns= gitlab.com/elixxir/client v1.5.1-0.20220924203712-7d4b1dce86b8 h1:A1x9EJOWm6YiaAJG5SPHXiwsDvik2XGSjeSylJbDBBk= gitlab.com/elixxir/client v1.5.1-0.20220924203712-7d4b1dce86b8/go.mod h1:z1Bdlja75CF3UrzifMC0LQwjlEdOcJCfXEX5k9AKQTQ= -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/comms v0.0.4-0.20220916185715-f1e9a5eda939 h1:+VRx2ULHKs040bBhDAOKNCZnbcXxUk3jD9JoKQzQpLk= gitlab.com/elixxir/comms v0.0.4-0.20220916185715-f1e9a5eda939/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/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok= -gitlab.com/elixxir/crypto v0.0.7-0.20220920002307-5541473e9aa7 h1:9IsBtL8zcUG86XcfNUVIKcnlL5tyKlyQt1cJ5nogr1U= -gitlab.com/elixxir/crypto v0.0.7-0.20220920002307-5541473e9aa7/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok= gitlab.com/elixxir/crypto v0.0.7-0.20220923233816-0364f1b203c6 h1:ZCMqzKB86nrs9ldIoF2ZHvcExrkXIIIeH2RlNVwZx2A= gitlab.com/elixxir/crypto v0.0.7-0.20220923233816-0364f1b203c6/go.mod h1:QF8SzsrYh9Elip9EUYUDAhPjqO9DGrrrQxYHvn+VXok= gitlab.com/elixxir/ekv v0.2.1 h1:dtwbt6KmAXG2Tik5d60iDz2fLhoFBgWwST03p7T+9Is= @@ -654,7 +648,6 @@ gitlab.com/elixxir/primitives v0.0.3-0.20220810173935-592f34a88326/go.mod h1:9Bb gitlab.com/elixxir/primitives v0.0.3-0.20220901220638-1acc75fabdc6 h1:/cxxZBP5jTPDpC3zgOx9vV1ojmJyG8pYtkl3IbcewNQ= gitlab.com/elixxir/primitives v0.0.3-0.20220901220638-1acc75fabdc6/go.mod h1:9Bb2+u+CDSwsEU5Droo6saDAXuBDvLRjexpBhPAYxhA= gitlab.com/xx_network/comms v0.0.0-20200805174823-841427dd5023/go.mod h1:owEcxTRl7gsoM8c3RQ5KAm5GstxrJp5tn+6JfQ4z5Hw= -gitlab.com/xx_network/comms v0.0.4-0.20220913215811-c4bf83b27de3 h1:7mReTvEUVoI5Qpltcmbodc/j6rdPPHDIvenY4ZmWP7o= gitlab.com/xx_network/comms v0.0.4-0.20220913215811-c4bf83b27de3/go.mod h1:E2QKOKyPKLRjLUwMxgZpTKueEsHDEqshfqOHJ54ttxU= gitlab.com/xx_network/comms v0.0.4-0.20220916185248-8a984b8594de h1:44VKuVgT6X1l+MX8/oNmYORA+pa4nkOWV8hYxi4SCzc= gitlab.com/xx_network/comms v0.0.4-0.20220916185248-8a984b8594de/go.mod h1:E2QKOKyPKLRjLUwMxgZpTKueEsHDEqshfqOHJ54ttxU= diff --git a/main.go b/main.go index 53347e1fcec7d7e8552e7c824472ee50176d391d..072ea2537c4f595b85dd1d923187239026735f9e 100644 --- a/main.go +++ b/main.go @@ -42,16 +42,19 @@ func main() { js.Global().Set("ResumeBackup", js.FuncOf(wasm.ResumeBackup)) // wasm/channels.go + js.Global().Set("GenerateChannelIdentity", + js.FuncOf(wasm.GenerateChannelIdentity)) + js.Global().Set("GetPublicChannelIdentity", + js.FuncOf(wasm.GetPublicChannelIdentity)) + js.Global().Set("GetPublicChannelIdentityFromPrivate", + js.FuncOf(wasm.GetPublicChannelIdentityFromPrivate)) js.Global().Set("NewChannelsManager", js.FuncOf(wasm.NewChannelsManager)) js.Global().Set("NewChannelsManagerWithIndexedDb", js.FuncOf(wasm.NewChannelsManagerWithIndexedDb)) - js.Global().Set("NewChannelsManagerWithIndexedDbDummyNameService", - js.FuncOf(wasm.NewChannelsManagerWithIndexedDbDummyNameService)) - js.Global().Set("NewChannelsManagerDummyNameService", - js.FuncOf(wasm.NewChannelsManagerDummyNameService)) - js.Global().Set("GenerateChannel", - js.FuncOf(wasm.GenerateChannel)) + js.Global().Set("LoadChannelsManager", js.FuncOf(wasm.LoadChannelsManager)) + js.Global().Set("GenerateChannel", js.FuncOf(wasm.GenerateChannel)) js.Global().Set("GetChannelInfo", js.FuncOf(wasm.GetChannelInfo)) + js.Global().Set("IsNicknameValid", js.FuncOf(wasm.IsNicknameValid)) // wasm/cmix.go js.Global().Set("NewCmix", js.FuncOf(wasm.NewCmix)) diff --git a/wasm/channels.go b/wasm/channels.go index a50c91cdd7a0e9015b9052d7711dcc76de77a520..e72e300f9a53c4cf27de2a6022a907598c3acbef 100644 --- a/wasm/channels.go +++ b/wasm/channels.go @@ -45,6 +45,11 @@ func newChannelsManagerJS(api *bindings.ChannelsManager) map[string]interface{} "SendMessage": js.FuncOf(cm.SendMessage), "SendReply": js.FuncOf(cm.SendReply), "SendReaction": js.FuncOf(cm.SendReaction), + "GetIdentity": js.FuncOf(cm.GetIdentity), + "GetStorageTag": js.FuncOf(cm.GetStorageTag), + "SetNickname": js.FuncOf(cm.SetNickname), + "DeleteNickname": js.FuncOf(cm.DeleteNickname), + "GetNickname": js.FuncOf(cm.GetNickname), // Channel Receiving Logic and Callback Registration "RegisterReceiveHandler": js.FuncOf(cm.RegisterReceiveHandler), @@ -62,50 +67,99 @@ func (ch *ChannelsManager) GetID(js.Value, []js.Value) interface{} { return ch.api.GetID() } -// NewChannelsManager constructs a [ChannelsManager]. +// GenerateChannelIdentity creates a new private channel identity +// ([channel.PrivateIdentity]). The public component can be retrieved as JSON +// via [GetPublicChannelIdentityFromPrivate]. // // Parameters: -// - 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[0] - ID of [Cmix] object in tracker (int). // // Returns: -// - 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()) +// - JSON of [channel.PrivateIdentity] (Uint8Array). +// - Throws a TypeError if generating the identity fails. +func GenerateChannelIdentity(_ js.Value, args []js.Value) interface{} { + pi, err := bindings.GenerateChannelIdentity(args[0].Int()) if err != nil { utils.Throw(utils.TypeError, err) - return nil } - return newChannelsManagerJS(cm) + return utils.CopyBytesToJS(pi) } -// NewChannelsManagerWithIndexedDb constructs a [ChannelsManager] using an -// indexedDb backend. +// GetPublicChannelIdentity constructs a public identity ([channel.Identity]) +// from a bytes version and returns it JSON marshaled. // // Parameters: -// - 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] - Codename (string). +// - args[0] - Bytes of the public identity ([channel.Identity]) (Uint8Array). // // Returns: -// - 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()) +// - JSON of the constructed [channel.Identity] (Uint8Array). +// - Throws a TypeError if unmarshalling the bytes or marshalling the identity +// fails. +func GetPublicChannelIdentity(_ js.Value, args []js.Value) interface{} { + marshaledPublic := utils.CopyBytesToGo(args[0]) + pi, err := bindings.GetPublicChannelIdentity(marshaledPublic) if err != nil { utils.Throw(utils.TypeError, err) - return nil } - cm, err := bindings.NewChannelsManagerGoEventModel( - args[0].Int(), args[1].Int(), em) + return utils.CopyBytesToJS(pi) +} + +// GetPublicChannelIdentityFromPrivate returns the public identity +// ([channel.Identity]) contained in the given private identity +// ([channel.PrivateIdentity]). +// +// Parameters: +// - args[0] - Bytes of the private identity +// (channel.PrivateIdentity]) (Uint8Array). +// +// Returns: +// - JSON of the public identity ([channel.Identity]) (Uint8Array). +// - Throws a TypeError if unmarshalling the bytes or marshalling the identity +// fails. +func GetPublicChannelIdentityFromPrivate(_ js.Value, args []js.Value) interface{} { + marshaledPrivate := utils.CopyBytesToGo(args[0]) + identity, err := bindings.GetPublicChannelIdentityFromPrivate( + marshaledPrivate) + if err != nil { + utils.Throw(utils.TypeError, err) + } + + return utils.CopyBytesToJS(identity) +} + +// NewChannelsManager creates a new [ChannelsManager] from a new private +// identity ([channel.PrivateIdentity]). +// +// This is for creating a manager for an identity for the first time. For +// generating a new one channel identity, use [GenerateChannelIdentity]. To +// reload this channel manager, use [LoadChannelsManager], passing in the +// storage tag retrieved by [ChannelsManager.GetStorageTag]. +// +// Parameters: +// - args[0] - ID of [Cmix] object in tracker (int). This can be retrieved +// using [Cmix.GetID]. +// - args[1] - Bytes of a private identity ([channel.PrivateIdentity]) that is +// generated by [GenerateChannelIdentity] (Uint8Array). +// - args[2] - Javascript object that matches the [bindings.EventModel] +// interface. +// +// Returns: +// - Javascript representation of the [ChannelsManager] object. +// - Throws a TypeError if creating the manager fails. +func NewChannelsManager(_ js.Value, args []js.Value) interface{} { + privateIdentity := utils.CopyBytesToGo(args[1]) + em := &eventModel{ + joinChannel: utils.WrapCB(args[2], "JoinChannel"), + leaveChannel: utils.WrapCB(args[2], "LeaveChannel"), + receiveMessage: utils.WrapCB(args[2], "ReceiveMessage"), + receiveReply: utils.WrapCB(args[2], "ReceiveReply"), + receiveReaction: utils.WrapCB(args[2], "ReceiveReaction"), + updateSentStatus: utils.WrapCB(args[2], "UpdateSentStatus"), + } + + cm, err := bindings.NewChannelsManager(args[0].Int(), privateIdentity, em) if err != nil { utils.Throw(utils.TypeError, err) return nil @@ -114,30 +168,38 @@ func NewChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) interface{} { return newChannelsManagerJS(cm) } -// NewChannelsManagerWithIndexedDbDummyNameService constructs a -// [ChannelsManager] using an indexedDb backend and a dummy name server instead -// of UD. +// NewChannelsManagerWithIndexedDb creates a new [ChannelsManager] from a new +// private identity ([channel.PrivateIdentity]) and using indexedDb as a backend +// to manage the event model. +// +// This is for creating a manager for an identity for the first time. For +// generating a new one channel identity, use [GenerateChannelIdentity]. To +// reload this channel manager, use [LoadChannelsManagerGoEventModel], passing +// in the storage tag retrieved by [ChannelsManager.GetStorageTag]. // // This function initialises an indexedDb database. // // Parameters: // - args[0] - ID of [Cmix] object in tracker (int). This can be retrieved // using [Cmix.GetID]. -// - args[1] - Username (string). +// - args[1] - Bytes of a private identity ([channel.PrivateIdentity]) that is +// generated by [GenerateChannelIdentity] (Uint8Array). +// - args[2] - Username (string). // // Returns: -// - Javascript representation of the [bindings.ChannelsManager] object. +// - Javascript representation of the [ChannelsManager] object. // - Throws a TypeError if initialising indexedDb or created the new channel // manager fails. -func NewChannelsManagerWithIndexedDbDummyNameService(_ js.Value, args []js.Value) interface{} { - em, err := indexedDb.NewWasmEventModel(args[1].String()) +func NewChannelsManagerWithIndexedDb(_ js.Value, args []js.Value) interface{} { + privateIdentity := utils.CopyBytesToGo(args[1]) + em, err := indexedDb.NewWasmEventModel(args[2].String()) if err != nil { utils.Throw(utils.TypeError, err) return nil } - cm, err := bindings.NewChannelsManagerGoEventModelDummyNameService( - args[0].Int(), args[1].String(), em) + cm, err := bindings.NewChannelsManagerGoEventModel( + args[0].Int(), privateIdentity, em) if err != nil { utils.Throw(utils.TypeError, err) return nil @@ -146,21 +208,25 @@ func NewChannelsManagerWithIndexedDbDummyNameService(_ js.Value, args []js.Value return newChannelsManagerJS(cm) } -// NewChannelsManagerDummyNameService constructs a [ChannelsManager] -// using a Javascript event model backend and a dummy name server instead of UD. +// LoadChannelsManager loads an existing [ChannelsManager]. +// +// This is for loading a manager for an identity that has already been created. +// The channel manager should have previously been created with +// [NewChannelsManager] and the storage is retrievable with +// [ChannelsManager.GetStorageTag]. // // Parameters: -// - args[0] - ID of [Cmix] object in tracker (int). This can be retrieved +// - args[0] - ID of [Cmix] object in tracker (int). This can be retrieved // using [Cmix.GetID]. -// - args[1] - Username (string). +// - args[1] - The storage tag associated with the previously created channel +// manager and retrieved with [ChannelsManager.GetStorageTag] (string). // - args[2] - Javascript object that matches the [bindings.EventModel] // interface. // // Returns: -// - Javascript representation of the [bindings.ChannelsManager] object. -// - Throws a TypeError if initialising indexedDb or created the new channel -// manager fails. -func NewChannelsManagerDummyNameService(_ js.Value, args []js.Value) interface{} { +// - Javascript representation of the [ChannelsManager] object. +// - Throws a TypeError if loading the manager fails. +func LoadChannelsManager(_ js.Value, args []js.Value) interface{} { em := &eventModel{ joinChannel: utils.WrapCB(args[2], "JoinChannel"), leaveChannel: utils.WrapCB(args[2], "LeaveChannel"), @@ -170,8 +236,7 @@ func NewChannelsManagerDummyNameService(_ js.Value, args []js.Value) interface{} updateSentStatus: utils.WrapCB(args[2], "UpdateSentStatus"), } - cm, err := bindings.NewChannelsManagerGoEventModelDummyNameService( - args[0].Int(), args[1].String(), bindings.NewEventModel(em)) + cm, err := bindings.LoadChannelsManager(args[0].Int(), args[1].String(), em) if err != nil { utils.Throw(utils.TypeError, err) return nil @@ -180,21 +245,19 @@ func NewChannelsManagerDummyNameService(_ js.Value, args []js.Value) interface{} return newChannelsManagerJS(cm) } -// 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. +// GenerateChannel is used to create a channel 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. +// 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). +// 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). @@ -541,6 +604,106 @@ func (ch *ChannelsManager) SendReaction(_ js.Value, args []js.Value) interface{} return utils.CreatePromise(promiseFn) } +// GetIdentity returns the marshaled public identity ([channel.Identity]) that +// the channel is using. +// +// Returns: +// - JSON of the [channel.Identity] (Uint8Array). +// - Throws TypeError if marshalling the identity fails. +func (ch *ChannelsManager) GetIdentity(js.Value, []js.Value) interface{} { + i, err := ch.api.GetIdentity() + if err != nil { + utils.Throw(utils.TypeError, err) + return nil + } + + return utils.CopyBytesToJS(i) +} + +// GetStorageTag returns the storage tag needed to reload the manager. +// +// Returns: +// - Storage tag (string). +func (ch *ChannelsManager) GetStorageTag(js.Value, []js.Value) interface{} { + return ch.api.GetStorageTag() +} + +// SetNickname sets the nickname for a given channel. The nickname must be valid +// according to [IsNicknameValid]. +// +// Parameters: +// - args[0] - The nickname to set (string). +// - args[1] - Marshalled bytes if the channel's [id.ID] (Uint8Array). +// +// Returns: +// - Throws TypeError if unmarshalling the ID fails or the nickname is invalid. +func (ch *ChannelsManager) SetNickname(_ js.Value, args []js.Value) interface{} { + err := ch.api.SetNickname(args[0].String(), utils.CopyBytesToGo(args[1])) + if err != nil { + utils.Throw(utils.TypeError, err) + return nil + } + + return nil +} + +// DeleteNickname deletes the nickname for a given channel. +// +// Parameters: +// - args[0] - Marshalled bytes if the channel's [id.ID] (Uint8Array). +// +// Returns: +// - Throws TypeError if deleting the nickname fails. +func (ch *ChannelsManager) DeleteNickname(_ js.Value, args []js.Value) interface{} { + err := ch.api.DeleteNickname(utils.CopyBytesToGo(args[0])) + if err != nil { + utils.Throw(utils.TypeError, err) + return nil + } + + return nil +} + +// GetNickname returns the nickname set for a given channel. Returns an error if +// there is no nickname set. +// +// Parameters: +// - args[0] - Marshalled bytes if the channel's [id.ID] (Uint8Array). +// +// Returns: +// - The nickname (string). +// - Throws TypeError if the channel has no nickname set. +func (ch *ChannelsManager) GetNickname(_ js.Value, args []js.Value) interface{} { + nickname, err := ch.api.GetNickname(utils.CopyBytesToGo(args[0])) + if err != nil { + utils.Throw(utils.TypeError, err) + return nil + } + + return nickname +} + +// IsNicknameValid checks if a nickname is valid. +// +// Rules: +// 1. A nickname must not be longer than 24 characters. +// 2. A nickname must not be shorter than 1 character. +// +// Parameters: +// - args[0] - Nickname to check (string). +// +// Returns: +// - A Javascript Error object if the nickname is invalid with the reason why. +// - Null if the nickname is valid. +func IsNicknameValid(_ js.Value, args []js.Value) interface{} { + err := bindings.IsNicknameValid(args[0].String()) + if err != nil { + return utils.JsError(err) + } + + return nil +} + //////////////////////////////////////////////////////////////////////////////// // Channel Receiving Logic and Callback Registration // //////////////////////////////////////////////////////////////////////////////// @@ -557,10 +720,16 @@ type channelMessageReceptionCallback struct { // - receivedChannelMessageReport - Returns the JSON of // [bindings.ReceivedChannelMessageReport] (Uint8Array). // - err - Returns an error on failure (Error). +// +// Returns: +// - It must return a unique UUID for the message that it can be referenced by +// later (int). func (cmrCB *channelMessageReceptionCallback) Callback( - receivedChannelMessageReport []byte, err error) { - cmrCB.callback(utils.CopyBytesToJS(receivedChannelMessageReport), - utils.JsTrace(err)) + receivedChannelMessageReport []byte, err error) int { + uuid := cmrCB.callback( + utils.CopyBytesToJS(receivedChannelMessageReport), utils.JsTrace(err)) + + return uuid.Int() } // RegisterReceiveHandler is used to register handlers for non-default message @@ -632,8 +801,9 @@ func (em *eventModel) LeaveChannel(channelID []byte) { // - channelID - Marshalled bytes of the channel [id.ID] (Uint8Array). // - messageID - The bytes of the [channel.MessageID] of the received message // (Uint8Array). -// - senderUsername - The username of the sender of the message (string). +// - nickname - The nickname of the sender of the message (string). // - text - The content of the message (string). +// - identity - JSON of the sender's public ([channel.Identity]) (Uint8Array). // - timestamp - Time the message was received; represented as nanoseconds // since unix epoch (int). // - lease - The number of nanoseconds that the message is valid for (int). @@ -644,11 +814,17 @@ func (em *eventModel) LeaveChannel(channelID []byte) { // Sent = 0 // Delivered = 1 // Failed = 2 -func (em *eventModel) ReceiveMessage(channelID, messageID []byte, - senderUsername, text string, timestamp, lease, roundId, status int64) { - em.receiveMessage(utils.CopyBytesToJS(channelID), - utils.CopyBytesToJS(messageID), - senderUsername, text, timestamp, lease, roundId, status) +// +// Returns: +// - A non-negative unique UUID for the message that it can be referenced by +// later with [eventModel.UpdateSentStatus]. +func (em *eventModel) ReceiveMessage(channelID, messageID []byte, nickname, + text string, identity []byte, timestamp, lease, roundId, status int64) int64 { + uuid := em.receiveMessage(utils.CopyBytesToJS(channelID), + utils.CopyBytesToJS(messageID), nickname, text, + utils.CopyBytesToJS(identity), timestamp, lease, roundId, status) + + return int64(uuid.Int()) } // ReceiveReply is called whenever a message is received that is a reply on a @@ -666,6 +842,7 @@ func (em *eventModel) ReceiveMessage(channelID, messageID []byte, // (Uint8Array). // - senderUsername - The username of the sender of the message (string). // - text - The content of the message (string). +// - identity - JSON of the sender's public ([channel.Identity]) (Uint8Array). // - timestamp - Time the message was received; represented as nanoseconds // since unix epoch (int). // - lease - The number of nanoseconds that the message is valid for (int). @@ -676,11 +853,19 @@ func (em *eventModel) ReceiveMessage(channelID, messageID []byte, // Sent = 0 // Delivered = 1 // Failed = 2 +// +// Returns: +// - A non-negative unique UUID for the message that it can be referenced by +// later with [eventModel.UpdateSentStatus]. func (em *eventModel) ReceiveReply(channelID, messageID, reactionTo []byte, - senderUsername, text string, timestamp, lease, roundId, status int64) { - em.receiveReply(utils.CopyBytesToJS(channelID), + senderUsername, text string, identity []byte, timestamp, lease, roundId, + status int64) int64 { + uuid := em.receiveReply(utils.CopyBytesToJS(channelID), utils.CopyBytesToJS(messageID), utils.CopyBytesToJS(reactionTo), - senderUsername, text, timestamp, lease, roundId, status) + senderUsername, text, utils.CopyBytesToJS(identity), + timestamp, lease, roundId, status) + + return int64(uuid.Int()) } // ReceiveReaction is called whenever a reaction to a message is received on a @@ -698,6 +883,7 @@ func (em *eventModel) ReceiveReply(channelID, messageID, reactionTo []byte, // (Uint8Array). // - senderUsername - The username of the sender of the message (string). // - reaction - The contents of the reaction message (string). +// - identity - JSON of the sender's public ([channel.Identity]) (Uint8Array). // - timestamp - Time the message was received; represented as nanoseconds // since unix epoch (int). // - lease - The number of nanoseconds that the message is valid for (int). @@ -708,25 +894,39 @@ func (em *eventModel) ReceiveReply(channelID, messageID, reactionTo []byte, // Sent = 0 // Delivered = 1 // Failed = 2 +// +// Returns: +// - A non-negative unique UUID for the message that it can be referenced by +// later with [eventModel.UpdateSentStatus]. func (em *eventModel) ReceiveReaction(channelID, messageID, reactionTo []byte, - senderUsername, reaction string, timestamp, lease, roundId, status int64) { - em.receiveReaction(utils.CopyBytesToJS(channelID), + senderUsername, reaction string, identity []byte, timestamp, lease, roundId, + status int64) int64 { + uuid := em.receiveReaction(utils.CopyBytesToJS(channelID), utils.CopyBytesToJS(messageID), utils.CopyBytesToJS(reactionTo), - senderUsername, reaction, timestamp, lease, roundId, status) + senderUsername, reaction, utils.CopyBytesToJS(identity), + timestamp, lease, roundId, status) + + return int64(uuid.Int()) } // UpdateSentStatus is called whenever the sent status of a message has // changed. // // Parameters: +// - uuid - The unique identifier for the message (int). // - messageID - The bytes of the [channel.MessageID] of the received message // (Uint8Array). +// - timestamp - Time the message was received; represented as nanoseconds +// since unix epoch (int). +// - roundId - The ID of the round that the message was received on (int). // - status - The [channels.SentStatus] of the message (int). // // Statuses will be enumerated as such: // Sent = 0 // Delivered = 1 // Failed = 2 -func (em *eventModel) UpdateSentStatus(messageID []byte, status int64) { - em.updateSentStatus(utils.CopyBytesToJS(messageID), status) +func (em *eventModel) UpdateSentStatus( + uuid int64, messageID []byte, timestamp, roundID, status int64) { + em.updateSentStatus( + uuid, utils.CopyBytesToJS(messageID), timestamp, roundID, status) } diff --git a/wasm_test.go b/wasm_test.go index d256a93a4d72b0396f9cbda758fa06ab9605dc1e..c17d1df49b02f5ea433b862ddbda430d50314618 100644 --- a/wasm_test.go +++ b/wasm_test.go @@ -39,9 +39,9 @@ func TestPublicFunctions(t *testing.T) { // These functions are used internally by the WASM bindings but are not // exposed - "NewEventModel": {}, - "NewChannelsManagerGoEventModel": {}, - "NewChannelsManagerGoEventModelDummyNameService": {}, + "NewEventModel": {}, + "NewChannelsManagerGoEventModel": {}, + "LoadChannelsManagerGoEventModel": {}, } wasmFuncs := getPublicFunctions("wasm", t) bindingsFuncs := getPublicFunctions(