Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding some documentation to the webassembly client #244

Merged
merged 2 commits into from
May 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion clients/webassembly/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "nym-client-wasm"
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jedrzej Stuczynski <andrew@nymtech.net>"]
version = "0.7.2"
version = "0.7.3"
edition = "2018"
keywords = ["nym", "sphinx", "wasm", "webassembly", "privacy", "client"]
license = "Apache-2.0"
Expand Down
104 changes: 92 additions & 12 deletions clients/webassembly/client.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import * as wasm from ".";

/**
* A Nym identity, consisting of a public/private keypair and a Nym
* gateway address.
*/
export class Identity {
// in the future this should allow for loading from local storage
constructor() {
Expand All @@ -10,6 +14,10 @@ export class Identity {
}
}

/**
* A Client which connects to a Nym gateway via websocket. All communication
* with the Nym network happens through this connection.
*/
export class Client {
constructor(directoryUrl, identity, authToken) {
this.authToken = authToken
Expand All @@ -19,10 +27,17 @@ export class Client {
this.topologyEndpoint = directoryUrl + "/api/presence/topology";
}

/**
* @return {string} a user-pubkey@nym-gateway recipient address
*/
formatAsRecipient() {
return `${this.identity.address}@${this.gateway.mixAddress}`
}

/**
* Get the current network topology, then connect to this client's Nym gateway
* via websocket.
*/
async start() {
await this.updateTopology();
this._getInitialGateway();
Expand All @@ -34,6 +49,11 @@ export class Client {
return this.authToken !== null
}

/**
* Update the Nym network topology.
*
* @returns an object containing the current Nym network topology
*/
async updateTopology() {
let response = await http('get', this.topologyEndpoint);
let topology = JSON.parse(response); // make sure it's a valid json
Expand All @@ -42,9 +62,11 @@ export class Client {
return topology;
}

/* Gets the address of a Nym gateway to send the Sphinx packet to.
At present we choose the first gateway as the network should only be running
one. Later, we will implement multiple gateways. */
/**
* Gets the address of a Nym gateway to send the Sphinx packet to.
* At present we choose the first gateway as the network should only be
* running one. Later, we will implement multiple gateways.
*/
_getInitialGateway() {
if (this.gateway !== null) {
console.error("tried to re-initialise gateway data");
Expand All @@ -60,6 +82,9 @@ export class Client {
}
}

/**
* Connect to the client's defined Nym gateway via websocket.
*/
connect() {
return new Promise((resolve, reject) => {
const conn = new WebSocket(this.gateway.socketAddress);
Expand All @@ -84,22 +109,39 @@ export class Client {
})
}

/**
* Sends a registration request to a Nym gateway node. Use it only if you
* haven't registered this client before.
*/
sendRegisterRequest() {
const registerReq = makeRegisterRequest(this.identity.address);
const registerReq = buildRegisterRequest(this.identity.address);
this.gateway.conn.send(registerReq);
this.onRegisterRequestSend();
}

/**
* Authenticates with a Nym gateway for this client.
*
* @param {string} token
*/
sendAuthenticateRequest(token) {
const authenticateReq = makeAuthenticateRequest(this.identity.address, token);
const authenticateReq = buildAuthenticateRequest(this.identity.address, token);
this.conn.send(authenticateReq);
this.onAuthenticateRequestSend();
}

/*
NOTE: this currently does not implement chunking and messages over ~1KB
will cause a panic. This will be fixed in a future version.
*/
/**
* Sends a message up the websocket to this client's Nym gateway.
*
* NOTE: this currently does not implement chunking and messages over ~1KB
* will cause a panic. This will be fixed in a future version.
*
* `message` must be text at the moment. Binary `Blob` and `ArrayBuffer`
* will be supported soon.
*
* @param {*} message
* @param {string} recipient
*/
sendMessage(message, recipient) {
if (this.gateway === null || this.gateway.conn === null) {
console.error("Client was not initialised");
Expand All @@ -116,6 +158,15 @@ export class Client {
this.onMessageSend();
}

/**
* A callback triggered when a message is received from this client's Nym
* gateway.
*
* The `event` may be a binary blob which was the payload of a Sphinx packet,
* or it may be a JSON control message (for example, the result of an
* authenticate request).
* @param {*} event
*/
onMessage(event) {
if (event.data instanceof Blob) {
this.onBlobResponse(event);
Expand All @@ -133,10 +184,17 @@ export class Client {

// all the callbacks that can be overwritten

/**
* A callback that fires when network topology is updated.
*/
onUpdatedTopology() {
console.log("Default: Updated topology")
}

/**
*
* @param {*} event
*/
onConnect(event) {
console.log("Default: Established gateway connection", event);
}
Expand Down Expand Up @@ -200,20 +258,42 @@ export class Client {
reader.readAsText(event.data);
}

// Alternatively you may use default implementation and treat everything as text
/**
* @callback that makes a best-effort attempt to return decrypted Sphinx bytes as text.
*
* Note that no checks are performed to determine whether something is
* really text. If the received data is in fact binary, you'll get
* binary-as-text from this callback.
*/
onText(data) {
console.log("Default: parsed the following data", data);
}
}

function makeRegisterRequest(address) {
/**
* Build a JSON registration request.
*
* @param {string} address
*/
function buildRegisterRequest(address) {
return JSON.stringify({ "type": "register", "address": address });
}

function makeAuthenticateRequest(address, token) {
/**
* Build a JSON authentication request.
*
* @param {string} address
* @param {string} token
*/
function buildAuthenticateRequest(address, token) {
return JSON.stringify({ "type": "authenticate", "address": address, "token": token });
}

/**
* Make an HTTP request.
* @param {string} method
* @param {string} url
*/
function http(method, url) {
return new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest();
Expand Down
26 changes: 23 additions & 3 deletions clients/webassembly/js-example/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,30 +36,50 @@ async function main() {
await nymClient.start();
}

// Create a Sphinx packet and send it to the mixnet through the gateway node.
/**
* Create a Sphinx packet and send it to the mixnet through the gateway node.
*
* Message and recipient are taken from the values in the user interface.
*
* @param {Client} nymClient the nym client to use for message sending
*/
function sendMessageTo(nymClient) {
var message = document.getElementById("message").value;
var recipient = document.getElementById("recipient").value;
nymClient.sendMessage(message, recipient);
displaySend(message);
}

/**
* Display messages that have been sent up the websocket. Colours them blue.
*
* @param {string} message
*/
function displaySend(message) {
let timestamp = new Date().toISOString().substr(11, 12);
let out = "<p style='color: blue; word-break: break-all;'>" + timestamp + " <b>sent</b> >>> " + message + "</p >";
document.getElementById("output").innerHTML = out + document.getElementById("output").innerHTML;
}

/**
* Display received text messages in the browser. Colour them green.
*
* @param {string} message
*/
function displayReceived(message) {
let timestamp = new Date().toISOString().substr(11, 12);
let out = "<p style='color: green; word-break: break-all;'>" + timestamp + " <b>received</b> >>> " + message + "</p >";
document.getElementById("output").innerHTML = out + document.getElementById("output").innerHTML;
}


/**
* Display the nymClient's sender address in the user interface
*
* @param {Client} nymClient
*/
function displaySenderAddress(nymClient) {
document.getElementById("sender").value = nymClient.formatAsRecipient();
}


// Let's get started!
main();
9 changes: 3 additions & 6 deletions clients/webassembly/js-example/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion clients/webassembly/js-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@
"webpack-dev-server": "^3.11.0"
},
"dependencies": {
"@nymproject/nym-client-wasm": "^0.7.2"
"@nymproject/nym-client-wasm": "^0.7.3"
}
}