Skip to content
Snippets Groups Projects
main.go 11.1 KiB
Newer Older
////////////////////////////////////////////////////////////////////////////////
// Copyright © 2022 xx foundation                                             //
//                                                                            //
// Use of this source code is governed by a license that can be found in the  //
// LICENSE file.                                                              //
////////////////////////////////////////////////////////////////////////////////
Jono Wenger's avatar
Jono Wenger committed

//go:build js && wasm

package main

import (
	"fmt"
	"github.com/spf13/cobra"

Jono Wenger's avatar
Jono Wenger committed
	jww "github.com/spf13/jwalterweatherman"
	"gitlab.com/elixxir/wasm-utils/utils"
	"gitlab.com/elixxir/xxdk-wasm/logging"
	"gitlab.com/elixxir/xxdk-wasm/storage"
Jono Wenger's avatar
Jono Wenger committed
	"gitlab.com/elixxir/xxdk-wasm/wasm"
Jono Wenger's avatar
Jono Wenger committed
)

func main() {
	// Set to os.Args because the default is os.Args[1:] and in WASM, args start
	// at 0, not 1.
	wasmCmd.SetArgs(os.Args)
Jono Wenger's avatar
Jono Wenger committed

	err := wasmCmd.Execute()
Jono Wenger's avatar
Jono Wenger committed
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
Jono Wenger's avatar
Jono Wenger committed
	}
var wasmCmd = &cobra.Command{
	Use:     "xxdk-wasm",
	Short:   "WebAssembly bindings for xxDK.",
	Example: "const go = new Go();\ngo.argv = [\"--logLevel=1\"]",
	Run: func(cmd *cobra.Command, args []string) {
		// Start logger first to capture all logging events
		err := logging.EnableLogging(logLevel, fileLogLevel, maxLogFileSizeMB,
			workerScriptURL, workerName)
		if err != nil {
			fmt.Printf("Failed to intialize logging: %+v", err)
			os.Exit(1)
		}

		// Check that the WASM binary version is correct
		err = storage.CheckAndStoreVersions()
		if err != nil {
			jww.FATAL.Panicf("WASM binary version error: %+v", err)
		}

		// Enable all top level bindings functions
		setGlobals()

		// Indicate to the Javascript caller that the WASM is ready by resolving
		// a promise created by the caller, as shown below:
		//
		//  let isReady = new Promise((resolve) => {
		//    window.onWasmInitialized = resolve;
		//  });
		//
		//  const go = new Go();
		//  go.run(result.instance);
		//  await isReady;
		//
		// Source: https://github.com/golang/go/issues/49710#issuecomment-986484758
		js.Global().Get("onWasmInitialized").Invoke()

		<-make(chan bool)
		os.Exit(0)
	},
}
Jono Wenger's avatar
Jono Wenger committed

// setGlobals enables all global functions to be accessible to Javascript.
func setGlobals() {
	jww.INFO.Printf("Starting xxDK WebAssembly bindings.")
Jono Wenger's avatar
Jono Wenger committed

	// storage/password.go
	js.Global().Set("GetOrInitPassword", js.FuncOf(storage.GetOrInitPassword))
	js.Global().Set("ChangeExternalPassword",
		js.FuncOf(storage.ChangeExternalPassword))
	js.Global().Set("VerifyPassword", js.FuncOf(storage.VerifyPassword))
Jono Wenger's avatar
Jono Wenger committed
	// storage/purge.go
	js.Global().Set("Purge", js.FuncOf(storage.Purge))

Jono Wenger's avatar
Jono Wenger committed
	// utils/array.go
	js.Global().Set("Uint8ArrayToBase64", js.FuncOf(utils.Uint8ArrayToBase64))
	js.Global().Set("Base64ToUint8Array", js.FuncOf(utils.Base64ToUint8Array))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("Uint8ArrayEquals", js.FuncOf(utils.Uint8ArrayEquals))
Jono Wenger's avatar
Jono Wenger committed

Jono Wenger's avatar
Jono Wenger committed
	// wasm/backup.go
	js.Global().Set("NewCmixFromBackup", js.FuncOf(wasm.NewCmixFromBackup))
	js.Global().Set("InitializeBackup", js.FuncOf(wasm.InitializeBackup))
	js.Global().Set("ResumeBackup", js.FuncOf(wasm.ResumeBackup))

	// wasm/notifications.go
	js.Global().Set("LoadNotifications", js.FuncOf(wasm.LoadNotifications))
	js.Global().Set("LoadNotificationsDummy",
		js.FuncOf(wasm.LoadNotificationsDummy))

Jono Wenger's avatar
Jono Wenger committed
	// wasm/channels.go
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("GenerateChannelIdentity",
		js.FuncOf(wasm.GenerateChannelIdentity))
	js.Global().Set("ConstructIdentity", js.FuncOf(wasm.ConstructIdentity))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("ImportPrivateIdentity",
		js.FuncOf(wasm.ImportPrivateIdentity))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("GetPublicChannelIdentity",
		js.FuncOf(wasm.GetPublicChannelIdentity))
	js.Global().Set("GetPublicChannelIdentityFromPrivate",
		js.FuncOf(wasm.GetPublicChannelIdentityFromPrivate))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("NewChannelsManager", js.FuncOf(wasm.NewChannelsManager))
	js.Global().Set("LoadChannelsManager", js.FuncOf(wasm.LoadChannelsManager))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("NewChannelsManagerWithIndexedDb",
		js.FuncOf(wasm.NewChannelsManagerWithIndexedDb))
	js.Global().Set("LoadChannelsManagerWithIndexedDb",
		js.FuncOf(wasm.LoadChannelsManagerWithIndexedDb))
	js.Global().Set("LoadChannelsManagerWithIndexedDbUnsafe",
		js.FuncOf(wasm.LoadChannelsManagerWithIndexedDbUnsafe))
	js.Global().Set("NewChannelsManagerWithIndexedDbUnsafe",
		js.FuncOf(wasm.NewChannelsManagerWithIndexedDbUnsafe))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("DecodePublicURL", js.FuncOf(wasm.DecodePublicURL))
	js.Global().Set("DecodePrivateURL", js.FuncOf(wasm.DecodePrivateURL))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("DecodeInviteURL", js.FuncOf(wasm.DecodeInviteURL))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("GetChannelJSON", js.FuncOf(wasm.GetChannelJSON))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("GetChannelInfo", js.FuncOf(wasm.GetChannelInfo))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("GetShareUrlType", js.FuncOf(wasm.GetShareUrlType))
	js.Global().Set("ValidForever", js.FuncOf(wasm.ValidForever))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("IsNicknameValid", js.FuncOf(wasm.IsNicknameValid))
	js.Global().Set("GetChannelNotificationReportsForMe",
		js.FuncOf(wasm.GetChannelNotificationReportsForMe))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("GetNoMessageErr", js.FuncOf(wasm.GetNoMessageErr))
	js.Global().Set("CheckNoMessageErr", js.FuncOf(wasm.CheckNoMessageErr))
Jake Taylor's avatar
Jake Taylor committed
	js.Global().Set("GetNotificationReportsForMe",
		js.FuncOf(wasm.GetChannelNotificationReportsForMe))

	// wasm/cipher.go
Jonah Husson's avatar
Jonah Husson committed
	js.Global().Set("NewDatabaseCipher",
		js.FuncOf(wasm.NewDatabaseCipher))
Jono Wenger's avatar
Jono Wenger committed
	// wasm/channelsFileTransfer.go
	js.Global().Set("InitChannelsFileTransfer",
		js.FuncOf(wasm.InitChannelsFileTransfer))

	// wasm/dm.go
	js.Global().Set("NewDMClient", js.FuncOf(wasm.NewDMClient))
	js.Global().Set("NewDMClientWithIndexedDb",
		js.FuncOf(wasm.NewDMClientWithIndexedDb))
	js.Global().Set("NewDMClientWithIndexedDbUnsafe",
		js.FuncOf(wasm.NewDMClientWithIndexedDbUnsafe))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("NewDMsDatabaseCipher", js.FuncOf(wasm.NewDatabaseCipher))
	js.Global().Set("DecodeDMShareURL", js.FuncOf(wasm.DecodeDMShareURL))
	js.Global().Set("GetDmNotificationReportsForMe",
		js.FuncOf(wasm.GetDmNotificationReportsForMe))
Jono Wenger's avatar
Jono Wenger committed
	// wasm/cmix.go
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("NewCmix", js.FuncOf(wasm.NewCmix))
	js.Global().Set("NewSynchronizedCmix",
		js.FuncOf(wasm.NewSynchronizedCmix))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("LoadCmix", js.FuncOf(wasm.LoadCmix))
	js.Global().Set("LoadSynchronizedCmix",
		js.FuncOf(wasm.LoadSynchronizedCmix))
Jono Wenger's avatar
Jono Wenger committed

	// wasm/delivery.go
	js.Global().Set("SetDashboardURL", js.FuncOf(wasm.SetDashboardURL))

Jono Wenger's avatar
Jono Wenger committed
	// wasm/dummy.go
	js.Global().Set("NewDummyTrafficManager",
		js.FuncOf(wasm.NewDummyTrafficManager))

Jono Wenger's avatar
Jono Wenger committed
	// wasm/e2e.go
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("Login", js.FuncOf(wasm.Login))
	js.Global().Set("LoginEphemeral", js.FuncOf(wasm.LoginEphemeral))
Jono Wenger's avatar
Jono Wenger committed

Josh Brooks's avatar
Josh Brooks committed
	// wasm/emoji.go
	js.Global().Set("SupportedEmojis", js.FuncOf(wasm.SupportedEmojis))
	js.Global().Set("SupportedEmojisMap", js.FuncOf(wasm.SupportedEmojisMap))
Josh Brooks's avatar
Josh Brooks committed
	js.Global().Set("ValidateReaction", js.FuncOf(wasm.ValidateReaction))

Jono Wenger's avatar
Jono Wenger committed
	// wasm/errors.go
	js.Global().Set("CreateUserFriendlyErrorMessage",
		js.FuncOf(wasm.CreateUserFriendlyErrorMessage))
	js.Global().Set("UpdateCommonErrors",
		js.FuncOf(wasm.UpdateCommonErrors))

	// wasm/fileTransfer.go
	js.Global().Set("InitFileTransfer", js.FuncOf(wasm.InitFileTransfer))

	// wasm/group.go
	js.Global().Set("NewGroupChat", js.FuncOf(wasm.NewGroupChat))
	js.Global().Set("DeserializeGroup", js.FuncOf(wasm.DeserializeGroup))
Jono Wenger's avatar
Jono Wenger committed

Jono Wenger's avatar
Jono Wenger committed
	// wasm/identity.go
	js.Global().Set("StoreReceptionIdentity",
Jono Wenger's avatar
Jono Wenger committed
		js.FuncOf(wasm.StoreReceptionIdentity))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("LoadReceptionIdentity",
Jono Wenger's avatar
Jono Wenger committed
		js.FuncOf(wasm.LoadReceptionIdentity))
	js.Global().Set("GetContactFromReceptionIdentity",
		js.FuncOf(wasm.GetContactFromReceptionIdentity))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("GetIDFromContact",
Jono Wenger's avatar
Jono Wenger committed
		js.FuncOf(wasm.GetIDFromContact))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("GetPubkeyFromContact",
Jono Wenger's avatar
Jono Wenger committed
		js.FuncOf(wasm.GetPubkeyFromContact))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("SetFactsOnContact",
Jono Wenger's avatar
Jono Wenger committed
		js.FuncOf(wasm.SetFactsOnContact))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("GetFactsFromContact",
Jono Wenger's avatar
Jono Wenger committed
		js.FuncOf(wasm.GetFactsFromContact))
Jono Wenger's avatar
Jono Wenger committed

Jono Wenger's avatar
Jono Wenger committed
	// wasm/logging.go
	js.Global().Set("RegisterLogWriter", js.FuncOf(wasm.RegisterLogWriter))
	js.Global().Set("EnableGrpcLogs", js.FuncOf(wasm.EnableGrpcLogs))

	// wasm/ndf.go
	js.Global().Set("DownloadAndVerifySignedNdfWithUrl",
		js.FuncOf(wasm.DownloadAndVerifySignedNdfWithUrl))

Jono Wenger's avatar
Jono Wenger committed
	// wasm/params.go
	js.Global().Set("GetDefaultCMixParams",
Jono Wenger's avatar
Jono Wenger committed
		js.FuncOf(wasm.GetDefaultCMixParams))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("GetDefaultE2EParams",
Jono Wenger's avatar
Jono Wenger committed
		js.FuncOf(wasm.GetDefaultE2EParams))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("GetDefaultFileTransferParams",
Jono Wenger's avatar
Jono Wenger committed
		js.FuncOf(wasm.GetDefaultFileTransferParams))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("GetDefaultSingleUseParams",
Jono Wenger's avatar
Jono Wenger committed
		js.FuncOf(wasm.GetDefaultSingleUseParams))
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("GetDefaultE2eFileTransferParams",
Jono Wenger's avatar
Jono Wenger committed
		js.FuncOf(wasm.GetDefaultE2eFileTransferParams))
Jono Wenger's avatar
Jono Wenger committed

Jono Wenger's avatar
Jono Wenger committed
	// wasm/restlike.go
	js.Global().Set("RestlikeRequest", js.FuncOf(wasm.RestlikeRequest))
	js.Global().Set("RestlikeRequestAuth", js.FuncOf(wasm.RestlikeRequestAuth))

Jono Wenger's avatar
Jono Wenger committed
	// wasm/restlikeSingle.go
	js.Global().Set("RequestRestLike",
		js.FuncOf(wasm.RequestRestLike))
	js.Global().Set("AsyncRequestRestLike",
		js.FuncOf(wasm.AsyncRequestRestLike))

Jono Wenger's avatar
Jono Wenger committed
	// wasm/secrets.go
	js.Global().Set("GenerateSecret", js.FuncOf(wasm.GenerateSecret))

	// wasm/single.go
Jono Wenger's avatar
Jono Wenger committed
	js.Global().Set("TransmitSingleUse", js.FuncOf(wasm.TransmitSingleUse))
	js.Global().Set("Listen", js.FuncOf(wasm.Listen))

	// wasm/sync.go

Jono Wenger's avatar
Jono Wenger committed
	// wasm/timeNow.go
	js.Global().Set("SetTimeSource", js.FuncOf(wasm.SetTimeSource))
	js.Global().Set("SetOffset", js.FuncOf(wasm.SetOffset))

Jono Wenger's avatar
Jono Wenger committed
	// wasm/ud.go
	js.Global().Set("NewOrLoadUd", js.FuncOf(wasm.NewOrLoadUd))
	js.Global().Set("NewUdManagerFromBackup",
		js.FuncOf(wasm.NewUdManagerFromBackup))
	js.Global().Set("LookupUD", js.FuncOf(wasm.LookupUD))
	js.Global().Set("SearchUD", js.FuncOf(wasm.SearchUD))

	// wasm/version.go
	js.Global().Set("GetVersion", js.FuncOf(wasm.GetVersion))
	js.Global().Set("GetClientVersion", js.FuncOf(wasm.GetClientVersion))
	js.Global().Set("GetClientGitVersion", js.FuncOf(wasm.GetClientGitVersion))
	js.Global().Set("GetClientDependencies", js.FuncOf(wasm.GetClientDependencies))
	js.Global().Set("GetWasmSemanticVersion", js.FuncOf(wasm.GetWasmSemanticVersion))
	js.Global().Set("GetXXDKSemanticVersion", js.FuncOf(wasm.GetXXDKSemanticVersion))
Jono Wenger's avatar
Jono Wenger committed

var (
	logLevel, fileLogLevel      jww.Threshold
	maxLogFileSizeMB            int
	workerScriptURL, workerName string
)
Jono Wenger's avatar
Jono Wenger committed

func init() {
	// Initialize all startup flags
	wasmCmd.Flags().IntVarP((*int)(&logLevel), "logLevel", "l", 2,
		"Sets the log level output when outputting to the Javascript console. "+
			"0 = TRACE, 1 = DEBUG, 2 = INFO, 3 = WARN, 4 = ERROR, "+
			"5 = CRITICAL, 6 = FATAL, -1 = disabled.")
	wasmCmd.Flags().IntVarP((*int)(&fileLogLevel), "fileLogLevel", "m", -1,
		"The log level when outputting to the file buffer. "+
			"0 = TRACE, 1 = DEBUG, 2 = INFO, 3 = WARN, 4 = ERROR, "+
			"5 = CRITICAL, 6 = FATAL, -1 = disabled.")
	wasmCmd.Flags().IntVarP(&maxLogFileSizeMB, "maxLogFileSize", "s", 5,
		"Max file size, in MB, for the file buffer before it rolls over "+
			"and starts overwriting the oldest entries.")
	wasmCmd.Flags().StringVarP(&workerScriptURL, "workerScriptURL", "w", "",
		"URL to the script that executes the worker. If set, it enables the "+
			"saving of log file to buffer in Worker instead of in the local "+
			"thread. This allows logging to be available after the main WASM "+
			"thread crashes.")
	wasmCmd.Flags().StringVar(&workerName, "workerName", "xxdkLogFileWorker",
		"Name of the logger worker.")
Jono Wenger's avatar
Jono Wenger committed
}