diff --git a/sdk/typescript/examples/plain-html/src/dom-utils.ts b/sdk/typescript/examples/plain-html/src/dom-utils.ts index 202f68c302..b2926cbcec 100644 --- a/sdk/typescript/examples/plain-html/src/dom-utils.ts +++ b/sdk/typescript/examples/plain-html/src/dom-utils.ts @@ -7,12 +7,12 @@ import { NymMixnetClient } from '@nymproject/sdk'; * * @param {Client} nymClient the nym client to use for message sending */ -export async function sendMessageTo(client: NymMixnetClient) { - const message = (document.getElementById('message') as HTMLFormElement).value; +export async function sendMessageTo(nym: NymMixnetClient) { + const payload = (document.getElementById('message') as HTMLFormElement).value; const recipient = (document.getElementById('recipient') as HTMLFormElement).value; - await client.client.sendMessage({ message, recipient }); - displaySend(message); + await nym.client.sendMessage({ payload, recipient }); + displaySend(payload); } /** diff --git a/sdk/typescript/examples/plain-html/src/index.ts b/sdk/typescript/examples/plain-html/src/index.ts index 236ef6aefc..16f53c380c 100644 --- a/sdk/typescript/examples/plain-html/src/index.ts +++ b/sdk/typescript/examples/plain-html/src/index.ts @@ -31,7 +31,7 @@ async function main() { // subscribe to message received events and show any string messages received nym.events.subscribeToTextMessageReceivedEvent((e) => { - displayReceived(e.args.message); + displayReceived(e.args.payload); }); const sendButton: HTMLButtonElement = document.querySelector('#send-button') as HTMLButtonElement; diff --git a/sdk/typescript/examples/react-webpack-with-theme-example/src/App.tsx b/sdk/typescript/examples/react-webpack-with-theme-example/src/App.tsx index e11d260ab3..be0ec30f44 100644 --- a/sdk/typescript/examples/react-webpack-with-theme-example/src/App.tsx +++ b/sdk/typescript/examples/react-webpack-with-theme-example/src/App.tsx @@ -80,7 +80,7 @@ export const Content: React.FC = () => { log.current.push({ kind: 'rx', timestamp: new Date(), - message: e.args.message, + message: e.args.payload, }); setLogTrigger(Date.now()); }); @@ -109,7 +109,7 @@ export const Content: React.FC = () => { message, }); setLogTrigger(Date.now()); - await sendTextMessage({ message, recipient }); + await sendTextMessage({ payload: message, recipient }); }; return ( diff --git a/sdk/typescript/examples/react-webpack-with-theme-example/src/context/mixnet.tsx b/sdk/typescript/examples/react-webpack-with-theme-example/src/context/mixnet.tsx index e65a11297c..74d05cb6d8 100644 --- a/sdk/typescript/examples/react-webpack-with-theme-example/src/context/mixnet.tsx +++ b/sdk/typescript/examples/react-webpack-with-theme-example/src/context/mixnet.tsx @@ -9,7 +9,7 @@ interface State { // methods connect: (config: NymClientConfig) => Promise; - sendTextMessage: (args: { message: string; recipient: string }) => Promise; + sendTextMessage: (args: { payload: string; recipient: string }) => Promise; } const MixnetContext = React.createContext(undefined); @@ -53,7 +53,7 @@ export const MixnetContextProvider: React.FC = ({ children }) => { await nym.current.client.start(config); }; - const sendTextMessage = async (args: { message: string; recipient: string }) => { + const sendTextMessage = async (args: { payload: string; recipient: string }) => { if (!nym.current?.client) { console.error('Nym client has not initialised. Please wrap in useEffect on `isReady` prop of this context.'); return; diff --git a/sdk/typescript/packages/sdk/package.json b/sdk/typescript/packages/sdk/package.json index d23ab39fe3..465a6920a8 100644 --- a/sdk/typescript/packages/sdk/package.json +++ b/sdk/typescript/packages/sdk/package.json @@ -22,7 +22,12 @@ "typecheck": "tsc --noEmit true", "lint": "eslint src", "lint:fix": "eslint src --fix", + "build:dependencies": "run-s build:dependencies:nym-client-wasm build:dependencies:ts-packages", + "build:dependencies:ts-packages": "cd ../../../.. && yarn && yarn build", + "build:dependencies:nym-client-wasm": "../nym-client-wasm/scripts/build.sh", + "prebuild": "yarn build:dependencies", "build": "tsc", + "build:only-this": "tsc", "postbuild": "cp ../nym-client-wasm/nym_client_wasm* dist/mixnet/wasm" }, "dependencies": { diff --git a/sdk/typescript/packages/sdk/src/mixnet/wasm/index.ts b/sdk/typescript/packages/sdk/src/mixnet/wasm/index.ts index 33572577d0..24d6472d7e 100644 --- a/sdk/typescript/packages/sdk/src/mixnet/wasm/index.ts +++ b/sdk/typescript/packages/sdk/src/mixnet/wasm/index.ts @@ -6,7 +6,7 @@ import { IWebWorkerEvents, ConnectedEvent, LoadedEvent, - TextMessageReceivedEvent, + StringMessageReceivedEvent, BinaryMessageReceivedEvent, } from './types'; @@ -73,9 +73,9 @@ export const createNymMixnetClient = async (): Promise => { }; }, subscribeToTextMessageReceivedEvent: (handler) => { - getSubscriptions(EventKinds.TextMessageReceived).push(handler); + getSubscriptions(EventKinds.StringMessageReceived).push(handler); return () => { - getSubscriptions(EventKinds.TextMessageReceived).unshift(handler); + getSubscriptions(EventKinds.StringMessageReceived).unshift(handler); }; }, subscribeToBinaryMessageReceivedEvent: (handler) => { diff --git a/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts b/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts index 53eee8bcd2..0f8c5c8f53 100644 --- a/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts +++ b/sdk/typescript/packages/sdk/src/mixnet/wasm/types.ts @@ -1,6 +1,8 @@ /// -export type OnMessageFn = (message: string) => void; +export type OnStringMessageFn = (message: string) => void; + +export type OnBinaryMessageFn = (message: Uint8Array) => void; export type OnConnectFn = (address?: string) => void; @@ -35,14 +37,14 @@ export interface NymClientConfig { export interface IWebWorker { start: (config: NymClientConfig) => void; selfAddress: () => string | undefined; - sendMessage: (args: { message: string; recipient: string }) => void; - sendBinaryMessage: (args: { message: Uint8Array; recipient: string }) => void; + sendMessage: (args: { payload: string; recipient: string }) => void; + sendBinaryMessage: (args: { payload: Uint8Array; recipient: string }) => void; } export enum EventKinds { Loaded = 'Loaded', Connected = 'Connected', - TextMessageReceived = 'TextMessageReceived', + StringMessageReceived = 'StringMessageReceived', BinaryMessageReceived = 'BinaryMessageReceived', } @@ -60,23 +62,25 @@ export interface ConnectedEvent { }; } -export interface TextMessageReceivedEvent { - kind: EventKinds.TextMessageReceived; +export interface StringMessageReceivedEvent { + kind: EventKinds.StringMessageReceived; args: { - message: string; + kind: number; + payload: string; }; } export interface BinaryMessageReceivedEvent { - kind: EventKinds.TextMessageReceived; + kind: EventKinds.BinaryMessageReceived; args: { - message: Uint8Array; + kind: number; + payload: Uint8Array; }; } export interface IWebWorkerEvents { subscribeToLoaded: EventHandlerSubscribeFn; subscribeToConnected: EventHandlerSubscribeFn; - subscribeToTextMessageReceivedEvent: EventHandlerSubscribeFn; + subscribeToTextMessageReceivedEvent: EventHandlerSubscribeFn; subscribeToBinaryMessageReceivedEvent: EventHandlerSubscribeFn; } diff --git a/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts b/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts index d78288359c..f8f3a0a053 100644 --- a/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts +++ b/sdk/typescript/packages/sdk/src/mixnet/wasm/worker.ts @@ -10,9 +10,11 @@ import type { ConnectedEvent, IWebWorker, LoadedEvent, - OnMessageFn, + OnStringMessageFn, + OnBinaryMessageFn, OnConnectFn, - TextMessageReceivedEvent, + StringMessageReceivedEvent, + BinaryMessageReceivedEvent, NymClientConfig, } from './types'; import { EventKinds } from './types'; @@ -31,6 +33,10 @@ const wasmUrl = new URL('./nym_client_wasm_bg.wasm', import.meta.url); */ const postMessageWithType = (event: E) => self.postMessage(event); +// ------------ the 1st byte of messages is the kind from the list below ------------ +const PAYLOAD_KIND_TEXT = 0; +const PAYLOAD_KIND_BINARY = 1; + /** * This class holds the state of the Nym WASM client and provides any interop needed. */ @@ -40,9 +46,22 @@ class ClientWrapper { /** * Creates the WASM client and initialises it. */ - init = (config: wasm_bindgen.Config, onConnectHandler: OnConnectFn, onMessageHandler: OnMessageFn) => { + init = ( + config: wasm_bindgen.Config, + onConnectHandler: OnConnectFn, + onStringMessageHandler?: OnStringMessageFn, + onBinaryMessageHandler?: OnBinaryMessageFn, + ) => { this.client = new wasm_bindgen.NymClient(config); - this.client.set_on_message(onMessageHandler); + if (onBinaryMessageHandler) { + this.client.set_on_binary_message(onBinaryMessageHandler); + } + + // NB: because we set the `kind` byte in the message payload first, we don't need to bother to try to parse + // all messages as string + // if (onStringMessageHandler) { + // this.client.set_on_message(onStringMessageHandler); + // } }; /** @@ -72,21 +91,21 @@ class ClientWrapper { this.client = await this.client.start(); }; - sendMessage = async ({ message, recipient }: { recipient: string; message: string }) => { + sendMessage = async ({ payload, recipient }: { recipient: string; payload: string }) => { if (!this.client) { console.error('Client has not been initialised. Please call `init` first.'); return; } - - this.client = await this.client.send_message(message, recipient); + const message = wasm_bindgen.create_binary_message_from_string(PAYLOAD_KIND_TEXT, payload); + this.client = await this.client.send_binary_message(message, recipient); }; - sendBinaryMessage = async ({ message, recipient }: { recipient: string; message: Uint8Array }) => { + sendBinaryMessage = async ({ payload, recipient }: { recipient: string; payload: Uint8Array }) => { if (!this.client) { console.error('Client has not been initialised. Please call `init` first.'); return; } - + const message = wasm_bindgen.create_binary_message(PAYLOAD_KIND_BINARY, payload); this.client = await this.client.send_binary_message(message, recipient); }; } @@ -118,8 +137,31 @@ wasm_bindgen(wasmUrl) () => { console.log(); }, - (message) => { - postMessageWithType({ kind: EventKinds.TextMessageReceived, args: { message } }); + undefined, + async (message) => { + try { + const { kind, payload } = await wasm_bindgen.parse_binary_message(message); + switch (kind) { + case PAYLOAD_KIND_TEXT: { + const stringMessage = await wasm_bindgen.parse_string_message(message); + postMessageWithType({ + kind: EventKinds.StringMessageReceived, + args: { kind, payload: stringMessage.payload }, + }); + break; + } + case PAYLOAD_KIND_BINARY: + postMessageWithType({ + kind: EventKinds.BinaryMessageReceived, + args: { kind, payload }, + }); + break; + default: + console.error('Could not determine message kind from 1st byte of message', { message, kind, payload }); + } + } catch (e) { + console.error('Failed to parse binary message', e); + } }, );