Switch from yarn to pnpm (#6779)

* switch from yarn to pnpm

* Remove full-nym-wasm (#6796)

* Remove nym-browser-extension (#6798)

* Remove nym-browser-extension

* remove unused from makefile

* Remove Node tester (#6800)

* Remove dom-utils (#6801)

* gh-actions: remove pnpm version

* nuke dist and pkg

* add missing dependency

* set node version to 24 and pnpm version to 11

* upgrade lock file from pnpm version 9 to 11

* pnpm add approved builds

* yarn -> pnpm

* upgrade jest version

* yarn -> pnpm

* Remove unused cfg; clippy!

* pnpm: when dev mode is on, unfreeze the lock file

* pnpm approve more scripts

* pnpm syntax error

* add `pnpm i`

* disable eslint temporarily while switching to biome in later PR

---------

Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
Co-authored-by: mfahampshire <maxhampshire@pm.me>
This commit is contained in:
Mark Sinclair
2026-05-22 20:29:51 +01:00
committed by GitHub
parent 28b22f6b22
commit 626d013547
195 changed files with 34745 additions and 34438 deletions
@@ -7,7 +7,7 @@
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"@nymproject/contract-clients": "file:.."
"@nymproject/contract-clients": "workspace:*"
},
"author": "",
"license": "ISC"
@@ -15,12 +15,12 @@
"docs:generate:prod": "typedoc --basePath ./docs/tsdoc/nymproject/contract-clients/",
"docs:prod:build": "scripts/build-prod-docs-collect.sh",
"docs:serve": "reload -b -d ./docs -p 3000",
"docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"yarn docs:generate\""
"docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"pnpm docs:generate\""
},
"devDependencies": {
"@cosmwasm/ts-codegen": "^1.13.3",
"nodemon": "3.0.1",
"npm-run-all": "^4.1.5",
"npm-run-all": "catalog:",
"reload": "^3.2.1",
"typedoc": "^0.24.8",
"typescript": "^4.6.2"
@@ -7,7 +7,7 @@ set -o pipefail
rm -rf ../../../../dist/ts/docs/tsdoc/nymproject/contract-clients || true
# run the build
yarn docs:generate:prod
pnpm docs:generate:prod
# move the output outside of the yarn/npm workspaces
mkdir -p ../../../../dist/ts/docs/tsdoc/nymproject
@@ -20,22 +20,22 @@
"devDependencies": {
"@types/jest": "^27.0.1",
"@types/node": "^16.7.13",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"@typescript-eslint/eslint-plugin": "catalog:",
"@typescript-eslint/parser": "catalog:",
"eslint": "^8.10.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^27.1.0",
"mini-css-extract-plugin": "^2.2.2",
"npm-run-all": "^4.1.5",
"prettier": "^2.8.7",
"ts-jest": "^27.0.5",
"eslint-config-airbnb": "catalog:",
"eslint-config-airbnb-typescript": "catalog:",
"eslint-config-prettier": "catalog:",
"eslint-import-resolver-root-import": "catalog:",
"eslint-plugin-import": "catalog:",
"eslint-plugin-jest": "catalog:",
"eslint-plugin-jsx-a11y": "catalog:",
"eslint-plugin-prettier": "catalog:",
"jest": "catalog:",
"mini-css-extract-plugin": "catalog:",
"npm-run-all": "catalog:",
"prettier": "catalog:",
"ts-jest": "catalog:",
"typescript": "^4.6.2"
},
"private": false,
@@ -19,47 +19,47 @@
"@nymproject/sdk": ">=1.4.1-rc1 || ^1"
},
"devDependencies": {
"@babel/core": "^7.15.0",
"@babel/plugin-transform-async-to-generator": "^7.14.5",
"@babel/preset-env": "^7.15.0",
"@babel/preset-typescript": "^7.15.0",
"@babel/core": "catalog:",
"@babel/plugin-transform-async-to-generator": "catalog:",
"@babel/preset-env": "catalog:",
"@babel/preset-typescript": "catalog:",
"@types/jest": "^27.0.1",
"@types/node": "^16.7.13",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"babel-loader": "^8.3.0",
"@typescript-eslint/eslint-plugin": "catalog:",
"@typescript-eslint/parser": "catalog:",
"babel-loader": "catalog:",
"babel-plugin-root-import": "^5.1.0",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^6.7.3",
"clean-webpack-plugin": "catalog:",
"css-loader": "catalog:",
"css-minimizer-webpack-plugin": "^3.0.2",
"dotenv-webpack": "^7.0.3",
"dotenv-webpack": "catalog:",
"eslint": "^8.10.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"file-loader": "^6.2.0",
"fork-ts-checker-webpack-plugin": "^7.2.1",
"html-webpack-plugin": "^5.3.2",
"jest": "^27.1.0",
"mini-css-extract-plugin": "^2.2.2",
"npm-run-all": "^4.1.5",
"prettier": "^2.8.7",
"style-loader": "^3.3.1",
"eslint-config-airbnb": "catalog:",
"eslint-config-airbnb-typescript": "catalog:",
"eslint-config-prettier": "catalog:",
"eslint-import-resolver-root-import": "catalog:",
"eslint-plugin-import": "catalog:",
"eslint-plugin-jest": "catalog:",
"eslint-plugin-jsx-a11y": "catalog:",
"eslint-plugin-prettier": "catalog:",
"file-loader": "catalog:",
"fork-ts-checker-webpack-plugin": "catalog:",
"html-webpack-plugin": "catalog:",
"jest": "catalog:",
"mini-css-extract-plugin": "catalog:",
"npm-run-all": "catalog:",
"prettier": "catalog:",
"style-loader": "catalog:",
"thread-loader": "^3.0.4",
"ts-jest": "^27.0.5",
"ts-loader": "^9.4.2",
"tsconfig-paths-webpack-plugin": "^3.5.2",
"ts-jest": "catalog:",
"ts-loader": "catalog:",
"tsconfig-paths-webpack-plugin": "catalog:",
"typescript": "^4.6.2",
"url-loader": "^4.1.1",
"webpack": "^5.75.0",
"webpack-cli": "^4.8.0",
"webpack-dev-server": "^4.5.0",
"webpack-merge": "^5.8.0"
"url-loader": "catalog:",
"webpack": "catalog:",
"webpack-cli": "catalog:",
"webpack-dev-server": "catalog:",
"webpack-merge": "catalog:"
},
"private": false
}
@@ -16,78 +16,78 @@
"tsc:watch": "tsc --watch"
},
"dependencies": {
"@mui/icons-material": "^5.5.0",
"@mui/icons-material": "catalog:",
"@mui/lab": "^5.0.0-alpha.72",
"@mui/material": "^5.0.1",
"@mui/styles": "^5.0.1",
"@nymproject/sdk": ">=1.4.1-rc1 || ^1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "catalog:",
"react-dom": "catalog:",
"react-dropzone": "^14.2.3",
"react-mui-dropzone": "^4.0.6",
"use-clipboard-copy": "^0.2.0"
},
"devDependencies": {
"@babel/core": "^7.15.0",
"@babel/plugin-transform-async-to-generator": "^7.14.5",
"@babel/preset-env": "^7.15.0",
"@babel/preset-react": "^7.14.5",
"@babel/preset-typescript": "^7.15.0",
"@babel/core": "catalog:",
"@babel/plugin-transform-async-to-generator": "catalog:",
"@babel/preset-env": "catalog:",
"@babel/preset-react": "catalog:",
"@babel/preset-typescript": "catalog:",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.4",
"@svgr/webpack": "^6.1.1",
"@svgr/webpack": "catalog:",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.0.0",
"@types/jest": "^27.0.1",
"@types/node": "^16.7.13",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.10",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"babel-loader": "^8.3.0",
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
"@typescript-eslint/eslint-plugin": "catalog:",
"@typescript-eslint/parser": "catalog:",
"babel-loader": "catalog:",
"babel-plugin-root-import": "^5.1.0",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^6.7.3",
"clean-webpack-plugin": "catalog:",
"css-loader": "catalog:",
"css-minimizer-webpack-plugin": "^3.0.2",
"dotenv-webpack": "^7.0.3",
"dotenv-webpack": "catalog:",
"eslint": "^8.10.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.29.2",
"eslint-plugin-react-hooks": "^4.3.0",
"favicons": "^7.0.2",
"favicons-webpack-plugin": "^5.0.2",
"file-loader": "^6.2.0",
"fork-ts-checker-webpack-plugin": "^7.2.1",
"html-webpack-plugin": "^5.3.2",
"jest": "^27.1.0",
"mini-css-extract-plugin": "^2.2.2",
"npm-run-all": "^4.1.5",
"prettier": "^2.8.7",
"eslint-config-airbnb": "catalog:",
"eslint-config-airbnb-typescript": "catalog:",
"eslint-config-prettier": "catalog:",
"eslint-import-resolver-root-import": "catalog:",
"eslint-plugin-import": "catalog:",
"eslint-plugin-jest": "catalog:",
"eslint-plugin-jsx-a11y": "catalog:",
"eslint-plugin-prettier": "catalog:",
"eslint-plugin-react": "catalog:",
"eslint-plugin-react-hooks": "catalog:",
"favicons": "catalog:",
"favicons-webpack-plugin": "catalog:",
"file-loader": "catalog:",
"fork-ts-checker-webpack-plugin": "catalog:",
"html-webpack-plugin": "catalog:",
"jest": "catalog:",
"mini-css-extract-plugin": "catalog:",
"npm-run-all": "catalog:",
"prettier": "catalog:",
"react-refresh-typescript": "^2.0.3",
"style-loader": "^3.3.1",
"style-loader": "catalog:",
"thread-loader": "^3.0.4",
"ts-jest": "^27.0.5",
"ts-loader": "^9.4.2",
"tsconfig-paths-webpack-plugin": "^3.5.2",
"ts-jest": "catalog:",
"ts-loader": "catalog:",
"tsconfig-paths-webpack-plugin": "catalog:",
"typescript": "^4.6.2",
"url-loader": "^4.1.1",
"webpack": "^5.75.0",
"webpack-cli": "^4.8.0",
"webpack-dev-server": "^4.5.0",
"webpack-favicons": "^1.3.8",
"webpack-merge": "^5.8.0"
"url-loader": "catalog:",
"webpack": "catalog:",
"webpack-cli": "catalog:",
"webpack-dev-server": "catalog:",
"webpack-favicons": "catalog:",
"webpack-merge": "catalog:"
},
"private": false,
"overrides": {
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.10",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"react": "^19.2.6",
"react-dom": "^19.2.6"
}
}
@@ -1,22 +0,0 @@
# Nym Chrome Extension Example
This is an example of how Nym can be used within the context of a Chrome extension.
## Running the example
1. Copy a build of the Nym TypeScript SDK (ESM version) into `./sdk`.
2. Navigate to `chrome://extensions` in Google Chrome.
3. Enable "Developer mode" (top right of the page).
4. Click on "Load unpacked" (top left of the page).
5. Load this extension folder.
## How does it work?
The Nym Mixnet Client runs a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) that wraps
a WASM library that builds and encrypts Sphinx packets in the browser to send over the Nym mixnet:
![Sphinx packet](../docs/worker.svg)
The WASM code encrypts each layer of the Sphinx packet in the browser, before sending the Sphinx packet over a websocket to the ingress gateway:
![Sphinx packet](../docs/sphinx.svg)
@@ -1,17 +0,0 @@
{
"name": "Nym Chrome Extension Example",
"description": "An example demonstrating how to integrate the Nym TypeScript SDK in the context of a Google Chrome browser extension.",
"version": "1.0",
"manifest_version": 3,
"icons": {
"48": "icon.png"
},
"content_security_policy": {
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';"
},
"action": {
"default_title": "Nym Chrome Extension Example",
"default_icon": "icon.png",
"default_popup": "popup.html"
}
}
@@ -1,21 +0,0 @@
{
"name": "@nymproject/sdk-example-chrome-extension",
"version": "1.0.5",
"description": "This is an example of how Nym can be used within the context of a Chrome extension.",
"license": "ISC",
"author": "",
"main": "index.js",
"scripts": {
"build": "webpack"
},
"dependencies": {
"@nymproject/sdk": ">=1.4.1-rc1 || ^1"
},
"devDependencies": {
"clean-webpack-plugin": "^4.0.0",
"copy-webpack-plugin": "^11.0.0",
"webpack": "^5.88.1",
"webpack-cli": "^5.1.4"
},
"private": false
}
@@ -1,8 +0,0 @@
body {
width: 800px;
min-height: 400px;
}
#editdialog input {
width: 100%;
}
@@ -1,23 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="popup.css" />
<script type="module" src="main.js"></script>
</head>
<body>
<p><label>Sender:</label><input disabled="true" size="85" id="sender" value="" /></p>
<p><label>Recipient:</label><input size="85" id="recipient" value="" /></p>
<p><label>Message:</label><input id="message" value="Hello mixnet!" /></p>
<p><button id="send-button">Send</button></p>
<p>Send messages from your browser, through the mixnet, and to the recipient using the "send" button.</p>
<p>
<span style="color: blue">Sent</span> messages show in blue, <span style="color: green">received</span> messages
show in green.
</p>
<hr />
<p></p>
<div id="output"></div>
<p></p>
</body>
</html>
@@ -1,66 +0,0 @@
// dom-utils.js
// Contains utility functionality to help manipulate the DOM elements necessary to demonstrate the Nym example.
/**
* 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
*/
async function sendMessageTo(nym) {
const message = document.getElementById('message').value;
const recipient = document.getElementById('recipient').value;
await nym.client.send({
payload: {
message,
mimeType: 'text/plain'
},
recipient
});
displaySend(message);
}
/**
* Display messages that have been sent up the websocket. Colours them blue.
*
* @param {string} message
*/
function displaySend(message) {
const timestamp = new Date().toISOString().substr(11, 12);
const sendDiv = document.createElement('div');
const paragraph = document.createElement('p');
paragraph.setAttribute('style', 'color: blue');
const paragraphContent = document.createTextNode(`${timestamp} sent >>> ${message}`);
paragraph.appendChild(paragraphContent);
sendDiv.appendChild(paragraph);
document.getElementById('output')?.appendChild(sendDiv);
}
/**
* Display received text messages in the browser. Colour them green.
*
* @param {string} message
*/
function displayReceived(message) {
const content = message;
const timestamp = new Date().toLocaleTimeString();
const receivedDiv = document.createElement('div');
const paragraph = document.createElement('p');
paragraph.setAttribute('style', 'color: green');
const paragraphContent = document.createTextNode(`${timestamp} received >>> ${content}`);
paragraph.appendChild(paragraphContent);
receivedDiv.appendChild(paragraph);
document.getElementById('output')?.appendChild(receivedDiv);
}
/**
* Display the nymClient's sender address in the user interface
*
* @param {Client} nymClient
*/
function displaySenderAddress(address) {
document.getElementById('sender').value = address;
}
export { sendMessageTo, displaySend, displayReceived , displaySenderAddress }
@@ -1,53 +0,0 @@
// main.js
// Simple example of how to load Nym's TypeScript SDK and bind it to a DOM.
// Look at dom-utils.js for the DOM utility functionality referenced here.
// Import the Nym mixnet ESM module.
import { createNymMixnetClient } from '@nymproject/sdk';
// Import the DOM utility functionality.
import { displaySenderAddress, displayReceived, sendMessageTo } from './dom-utils.js';
async function main() {
// Initialize the Nym mixnet client.
let nymClient = await createNymMixnetClient();
if (!nymClient) {
console.error('Oh no! Could not create client');
return;
}
const nymApiUrl = 'https://validator.nymtech.net/api';
const preferredGatewayIdentityKey = 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM';
// subscribe to connect event, so that we can show the client's address
nymClient.events.subscribeToConnected((e) => {
if (e.args.address) {
displaySenderAddress(e.args.address);
}
});
// subscribe to message received events and show any string messages received
nymClient.events.subscribeToTextMessageReceivedEvent((e) => {
displayReceived(e.args.payload);
});
const sendButton = document.querySelector('#send-button');
if (sendButton) {
sendButton.onclick = function () {
if (nymClient) {
sendMessageTo(nymClient);
}
};
}
nymClient.events.subscribeToRawMessageReceivedEvent((e) => console.log('Received: ', e.args.payload));
await nymClient.client.start({
clientId: 'My awesome client',
nymApiUrl,
preferredGatewayIdentityKey,
});
}
window.addEventListener('DOMContentLoaded', () => {
main();
});
@@ -1,9 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"declaration": false,
"declarationMap": false
},
"exclude": ["node_modules", "dist"]
}
@@ -1,25 +0,0 @@
// Webpack configuration for the Chrome extension example
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
mode: 'production',
entry: {
main: './src/main.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new CleanWebpackPlugin(),
new CopyWebpackPlugin({
patterns: [
'manifest.json',
'popup.html',
{ from: path.resolve(__dirname, '../../../../assets/favicon/favicon.png'), to: 'icon.png' },
],
}),
],
};
@@ -1 +0,0 @@
sdk/index.js
@@ -1,35 +0,0 @@
# Nym Firefox Extension Example
This is an example of how Nym can be used within the context of a Mozilla Firefox extension.
## Running the example
First, build the Nym SDK:
From the SDK directory `sdk/typescript/packages/sdk` run:
```js
npm run build:local
```
Then, from the example directory `sdk/typescript/examples/firefox-extension` run:
```js
npm install
npm run build
```
## Workers
Firefox browser extensions cannot run inline web workers. In order to overcome this limitation, the Nym Firefox Extension Example imports workers from the SDK and uses Webpack's `worker-loader` to allow the worker's to be bundled inline into the extension. In order for webpack to include the workers in the build, they are imported as modules in the `src/index.js` file:
## How does it work?
The Nym Mixnet Client runs a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) that wraps
a WASM library that builds and encrypts Sphinx packets in the browser to send over the Nym mixnet:
![Sphinx packet](../docs/worker.svg)
The WASM code encrypts each layer of the Sphinx packet in the browser, before sending the Sphinx packet over a websocket to the ingress gateway:
![Sphinx packet](../docs/sphinx.svg)
@@ -1,23 +0,0 @@
{
"manifest_version": 3,
"name": "Nym Firefox Extension Example",
"version": "1.0",
"description": "An example demonstrating how to integrate the Nym TypeScript SDK in the context of a Mozilla Firefox browser extension.",
"icons": {
"48": "icon.png"
},
"permissions": [],
"content_security_policy": {
"extension_pages": "script-src 'self' 'wasm-unsafe-eval';"
},
"background": {
"scripts": ["background.js"]
},
"action": {
"default_icon": {
"32": "icon.png"
},
"default_title": "Nym Firefox Extension Example",
"default_popup": "popup.html"
}
}
@@ -1,21 +0,0 @@
{
"name": "@nymproject/sdk-example-firefox-extension",
"version": "1.0.5",
"description": "This is an example of how Nym can be used within the context of a Firefox extension.",
"license": "ISC",
"author": "",
"main": "index.js",
"scripts": {
"build": "yarn webpack"
},
"dependencies": {
"@nymproject/sdk": ">=1.4.1-rc1 || ^1"
},
"devDependencies": {
"copy-webpack-plugin": "^11.0.0",
"webpack": "^5.88.1",
"webpack-cli": "^5.1.4",
"worker-loader": "^3.0.8"
},
"private": false
}
@@ -1,8 +0,0 @@
body {
width: 800px;
min-height: 400px;
}
#editdialog input {
width: 100%;
}
@@ -1,23 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="popup.css" />
<script type="module" src="popup.js"></script>
</head>
<body>
<p><label>Sender:</label><input disabled="true" size="85" id="sender" value="" /></p>
<p><label>Recipient:</label><input size="85" id="recipient" value="" /></p>
<p><label>Message:</label><input id="message" value="Hello mixnet!" /></p>
<p><button id="send-button">Send</button></p>
<p>Send messages from your browser, through the mixnet, and to the recipient using the "send" button.</p>
<p>
<span style="color: blue">Sent</span> messages show in blue, <span style="color: green">received</span> messages
show in green.
</p>
<hr />
<p></p>
<div id="output"></div>
<p></p>
</body>
</html>
@@ -1,107 +0,0 @@
// main.js
// Simple example of how to load Nym's TypeScript SDK and bind it to a DOM.
// Look at dom-utils.js for the DOM utility functionality referenced here.
// Import the Nym mixnet ESM module.
// Import The web workers for the Nym mixnet ESM module.These are required for to run the Nym mixnet client.
import { createNymMixnetClient } from '../../../packages/sdk/dist/full-fat/index.js';
import '../../../packages/sdk/dist/full-fat/web-worker-0.js';
import '../../../packages/sdk/dist/full-fat/web-worker-1.js';
const backgroundState = {
isReady: false,
address: '',
recipient: '',
messageLog: [],
};
async function initBackground() {
// Initialize the Nym mixnet client.
let nymClient = await createNymMixnetClient().catch((err) => {
console.log(err);
});
if (!nymClient) {
console.error('Oh no! Could not create client');
return;
}
const nymApiUrl = 'https://validator.nymtech.net/api';
const preferredGatewayIdentityKey = 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM';
// subscribe to connect event, so that we can show the client's address
nymClient.events.subscribeToConnected((e) => {
if (e.args.address) {
backgroundState.address = e.args.address;
browser.runtime.sendMessage({
type: 'displaySenderAddress',
message: backgroundState.address,
});
}
});
// subscribe to message received events and show any string messages received
nymClient.events.subscribeToTextMessageReceivedEvent((e) => {
backgroundState.messageLog.push({
type: 'received',
message: e.args.payload,
});
browser.runtime.sendMessage({
type: 'displayReceived',
message: e.args.payload,
});
});
nymClient.events.subscribeToRawMessageReceivedEvent((e) => console.log('Received: ', e.args.payload));
await nymClient.client.start({
clientId: 'My awesome client',
nymApiUrl,
preferredGatewayIdentityKey,
});
browser.runtime.onMessage.addListener(async (data) => {
switch (data.type) {
case 'nymClientSendMessage':
if (nymClient) {
await nymClient.client.send({
payload: {
message: data.message,
mimeType: 'text/plain',
},
recipient: data.recipient,
});
backgroundState.messageLog.push({
type: 'sent',
message: data.message,
});
break;
}
}
});
backgroundState.isReady = true;
}
window.addEventListener('DOMContentLoaded', () => {
browser.runtime.onMessage.addListener((data) => {
switch (data.type) {
case 'popupReady':
if (backgroundState.isReady) {
browser.runtime.sendMessage({
type: 'displaySenderAddress',
message: backgroundState.address,
});
browser.runtime.sendMessage({
type: 'displayMessageLog',
message: backgroundState.messageLog,
});
browser.runtime.sendMessage({
type: 'updateRecipient',
message: backgroundState.recipient,
});
} else {
initBackground();
}
break;
case 'updateRecipient':
backgroundState.recipient = data.message;
}
});
});
@@ -1,114 +0,0 @@
// main.js
// Simple example of how to load Nym's TypeScript SDK and bind it to a DOM.
// Look at dom-utils.js for the DOM utility functionality referenced here.
// Import the Nym mixnet ESM module.
// Import The web workers for the Nym mixnet ESM module.These are required for to run the Nym mixnet client.
import { createNymMixnetClient } from '../../../packages/sdk/dist/full-fat/index.js';
import '../../../packages/sdk/dist/full-fat/web-worker-0.js';
import '../../../packages/sdk/dist/full-fat/web-worker-1.js';
export type BackgroundState = {
isReady: boolean;
address: string;
recipient: string;
messageLog: { type: string; message: string }[];
};
const backgroundState: BackgroundState = {
isReady: false,
address: '',
recipient: '',
messageLog: [],
};
async function initBackground() {
// Initialize the Nym mixnet client.
let nymClient = await createNymMixnetClient().catch((err) => {
console.log(err);
});
if (!nymClient) {
console.error('Oh no! Could not create client');
return;
}
const nymApiUrl = 'https://validator.nymtech.net/api';
const preferredGatewayIdentityKey = 'E3mvZTHQCdBvhfr178Swx9g4QG3kkRUun7YnToLMcMbM';
// subscribe to connect event, so that we can show the client's address
nymClient.events.subscribeToConnected((e) => {
if (e.args.address) {
backgroundState.address = e.args.address;
browser.runtime.sendMessage({
type: 'displaySenderAddress',
message: backgroundState.address,
});
}
});
// subscribe to message received events and show any string messages received
nymClient.events.subscribeToTextMessageReceivedEvent((e) => {
backgroundState.messageLog.push({
type: 'received',
message: e.args.payload,
});
browser.runtime.sendMessage({
type: 'displayReceived',
message: e.args.payload,
});
});
nymClient.events.subscribeToRawMessageReceivedEvent((e) => console.log('Received: ', e.args.payload));
await nymClient.client.start({
clientId: 'My awesome client',
nymApiUrl,
preferredGatewayIdentityKey,
});
browser.runtime.onMessage.addListener(async (data) => {
switch (data.type) {
case 'nymClientSendMessage':
if (nymClient) {
await nymClient.client.send({
payload: {
message: data.message,
mimeType: 'text/plain',
},
recipient: data.recipient,
});
backgroundState.messageLog.push({
type: 'sent',
message: data.message,
});
break;
}
}
});
backgroundState.isReady = true;
}
window.addEventListener('DOMContentLoaded', () => {
browser.runtime.onMessage.addListener((data) => {
switch (data.type) {
case 'popupReady':
if (backgroundState.isReady) {
browser.runtime.sendMessage({
type: 'displaySenderAddress',
message: backgroundState.address,
});
browser.runtime.sendMessage({
type: 'displayMessageLog',
message: backgroundState.messageLog,
});
browser.runtime.sendMessage({
type: 'updateRecipient',
message: backgroundState.recipient,
});
} else {
initBackground();
}
break;
case 'updateRecipient':
backgroundState.recipient = data.message;
}
});
});
@@ -1,74 +0,0 @@
// dom-utils.js
// Contains utility functionality to help manipulate the DOM elements necessary to demonstrate the Nym example.
/**
* 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
*/
async function sendMessageTo() {
const message = document.getElementById('message').value;
const recipient = document.getElementById('recipient').value;
browser.runtime.sendMessage({
type: 'nymClientSendMessage',
message,
recipient,
});
displaySend(message);
}
/**
* Display messages that have been sent up the websocket. Colours them blue.
*
* @param {string} message
*/
function displaySend(message) {
const timestamp = new Date().toISOString().substr(11, 12);
const sendDiv = document.createElement('div');
const paragraph = document.createElement('p');
paragraph.setAttribute('style', 'color: blue');
const paragraphContent = document.createTextNode(`${timestamp} sent >>> ${message}`);
paragraph.appendChild(paragraphContent);
sendDiv.appendChild(paragraph);
document.getElementById('output')?.appendChild(sendDiv);
}
/**
* Display received text messages in the browser. Colour them green.
*
* @param {string} message
*/
function displayReceived(message) {
const content = message;
const timestamp = new Date().toLocaleTimeString();
const receivedDiv = document.createElement('div');
const paragraph = document.createElement('p');
paragraph.setAttribute('style', 'color: green');
const paragraphContent = document.createTextNode(`${timestamp} received >>> ${content}`);
paragraph.appendChild(paragraphContent);
receivedDiv.appendChild(paragraph);
document.getElementById('output')?.appendChild(receivedDiv);
}
/**
* Display the nymClient's sender address in the user interface
*
* @param {Client} nymClient
*/
function displaySenderAddress(address) {
document.getElementById('sender').value = address;
}
function displayMessageLog(messageLog) {
for (let i = 0; i < messageLog.length; i++) {
if (messageLog[i].type === 'sent') {
displaySend(messageLog[i].message);
} else if (messageLog[i].type === 'received') {
displayReceived(messageLog[i].message);
}
}
}
export { sendMessageTo, displaySend, displayReceived, displaySenderAddress, displayMessageLog };
@@ -1,35 +0,0 @@
// dom-utils.js
// Contains utility functionality to help manipulate the DOM elements necessary to demonstrate the Nym example.
import { BackgroundState } from './background';
import { displayReceived, displaySend, displaySenderAddress } from '../../shared/dom-utils';
/**
* 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
*/
async function sendMessageTo() {
const message = (document.getElementById('message') as HTMLFormElement).value;
const recipient = (document.getElementById('recipient') as HTMLFormElement).value;
browser.runtime.sendMessage({
type: 'nymClientSendMessage',
message,
recipient,
});
displaySend(message);
}
function displayMessageLog(messageLog: BackgroundState['messageLog']) {
for (let i = 0; i < messageLog.length; i++) {
if (messageLog[i].type === 'sent') {
displaySend(messageLog[i].message);
} else if (messageLog[i].type === 'received') {
displayReceived(messageLog[i].message);
}
}
}
export { sendMessageTo, displaySend, displayReceived, displaySenderAddress, displayMessageLog };
@@ -1,40 +0,0 @@
// Import the DOM utility functionality.
import { displaySenderAddress, displayReceived, sendMessageTo, displayMessageLog } from './dom-utils.js';
window.addEventListener('DOMContentLoaded', () => {
const sendButton = document.querySelector('#send-button');
if (sendButton) {
sendButton.onclick = function () {
sendMessageTo();
};
}
const recipient = document.getElementById('recipient');
recipient.onchange = () => {
browser.runtime.sendMessage({
type: 'updateRecipient',
message: recipient.value,
});
};
browser.runtime.onMessage.addListener((data) => {
switch (data.type) {
case 'displaySenderAddress':
displaySenderAddress(data.message);
break;
case 'displayReceived':
displayReceived(data.message);
break;
case 'sendMessageTo':
sendMessageTo(data.message);
break;
case 'displayMessageLog':
displayMessageLog(data.message);
break;
case 'updateRecipient':
recipient.value = data.message;
}
});
browser.runtime.sendMessage({
type: 'popupReady',
message: '',
});
});
@@ -1,40 +0,0 @@
// Import the DOM utility functionality.
import { displaySenderAddress, displayReceived, sendMessageTo, displayMessageLog } from './dom-utils';
window.addEventListener('DOMContentLoaded', () => {
const sendButton = document.querySelector('#send-button') as HTMLButtonElement;
if (sendButton) {
sendButton.onclick = function () {
sendMessageTo();
};
}
const recipient = document.getElementById('recipient') as HTMLFormElement;
recipient.onchange = () => {
browser.runtime.sendMessage({
type: 'updateRecipient',
message: recipient.value,
});
};
browser.runtime.onMessage.addListener((data) => {
switch (data.type) {
case 'displaySenderAddress':
displaySenderAddress(data.message);
break;
case 'displayReceived':
displayReceived(data.message);
break;
// case 'sendMessageTo':
// sendMessageTo(data.message);
// break;
case 'displayMessageLog':
displayMessageLog(data.message);
break;
case 'updateRecipient':
recipient.value = data.message;
}
});
browser.runtime.sendMessage({
type: 'popupReady',
message: '',
});
});
@@ -1,9 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"declaration": false,
"declarationMap": false
},
"exclude": ["node_modules", "dist"]
}
@@ -1,38 +0,0 @@
// Webpack configuration for the Firefox extension example
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
mode: 'production',
entry: {
background: './src/background.js',
popup: './src/popup.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new CleanWebpackPlugin(),
new CopyWebpackPlugin({
patterns: [
'manifest.json',
'popup.html',
{ from: path.resolve(__dirname, '../../../../assets/favicon/favicon.png'), to: 'icon.png' },
],
}),
],
module: {
rules: [
{
test: /web-worker.*\.js$/,
loader: 'worker-loader',
options: {
filename: '[name].js',
inline: 'fallback',
},
},
],
},
};
@@ -1,14 +0,0 @@
# Nym Node Tester - Parcel bundler
This is an example of using the Nym Mixnet node tester.
You can use this example as a seed for a new project.
## Running the example
Try out the node tester app by running:
```
npm install
npm start
```
@@ -1,44 +0,0 @@
{
"name": "@nymproject/sdk-example-node-tester-plain-html-parcel",
"version": "1.0.5",
"description": "An example project that uses WASM and plain HTML bundled with Parcel v2",
"license": "Apache-2.0",
"scripts": {
"build": "npx parcel build",
"build:serve": "npx serve dist",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"start": "npx parcel",
"test": "jest",
"test:watch": "jest --watch",
"tsc": "tsc",
"tsc:watch": "tsc --watch"
},
"dependencies": {
"@nymproject/sdk": ">=1.4.1-rc1 || ^1"
},
"devDependencies": {
"@types/jest": "^27.0.1",
"@types/node": "^16.7.13",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"eslint": "^8.10.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^27.1.0",
"mini-css-extract-plugin": "^2.2.2",
"npm-run-all": "^4.1.5",
"prettier": "^2.8.7",
"ts-jest": "^27.0.5",
"typescript": "^4.6.2"
},
"private": false,
"browserslist": "> 0.5%, last 2 versions, not dead",
"source": "src/index.html"
}
@@ -1,29 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nym Node Tester Demo</title>
</head>
<body>
<p>
<label>Mixnode Id: </label><input size="85" type="text" id="mixnodeId" value="">
</p>
<p>
<button id="test-button">Test</button>
<button id="disconnect-button">Disconnect from Gateway</button>
<button id="reconnect-button">Reconnect to Gateway</button>
<button id="terminate-button">Terminate worker</button>
</p>
<p>Test a mixnode by entering the mixnode id above and click the Test button</p>
<hr>
<p>
<div id="output"></div>
</p>
<script src="./index.ts" type="module"></script>
</body>
</html>
@@ -1,118 +0,0 @@
import { createNodeTesterClient, NodeTester } from '@nymproject/sdk';
let nodeTester: NodeTester | null = null;
/**
* Display messages that have been sent up the websocket. Colours them blue.
*
* @param {string} message
*/
function displayOutput(message: string, color?: string) {
const timestamp = new Date().toISOString().substr(11, 12);
const sendDiv = document.createElement('div');
const paragraph = document.createElement('p');
paragraph.setAttribute('style', `color: ${color || 'blue'}`);
const paragraphContent = document.createTextNode(`${timestamp} >>> ${message}`);
paragraph.appendChild(paragraphContent);
sendDiv.appendChild(paragraph);
document.getElementById('output')?.appendChild(sendDiv);
}
/**
* The main entry point
*/
async function main() {
nodeTester = await createNodeTesterClient();
// add node tester to the Window globally, so that it can be used from the dev tools console
(window as any).nodeTester = nodeTester;
if (!nodeTester) {
console.error('Oh no! Could not the node test');
return;
}
const nymApiUrl = 'https://validator.nymtech.net/api';
const nodeTesterId = new Date().toISOString(); // make a new tester id for each session
await nodeTester.tester.init(nymApiUrl, nodeTesterId);
const mixnodes = await (await fetch(`${nymApiUrl}/v1/mixnodes/active`)).json();
const exampleMixnodeIdentityKey = mixnodes[0].bond_information.mix_node.identity_key;
const testButton: HTMLButtonElement = document.querySelector('#test-button') as HTMLButtonElement;
const reconnectButton: HTMLButtonElement = document.querySelector('#reconnect-button') as HTMLButtonElement;
const disconnectButton: HTMLButtonElement = document.querySelector('#disconnect-button') as HTMLButtonElement;
const terminateButton: HTMLButtonElement = document.querySelector('#terminate-button') as HTMLButtonElement;
const mixnodeIdInput = document.getElementById('mixnodeId') as HTMLFormElement;
mixnodeIdInput.value = exampleMixnodeIdentityKey;
reconnectButton.onclick = async function () {
try {
await nodeTester?.tester.reconnectToGateway();
} catch (e: any) {
console.error('Error', e);
displayOutput(`ERROR: ${e.message}`, 'red');
}
};
disconnectButton.onclick = async function () {
try {
await nodeTester?.tester.disconnectFromGateway();
} catch (e: any) {
console.error('Error', e);
displayOutput(`ERROR: ${e.message}`, 'red');
}
};
terminateButton.onclick = async function () {
try {
await nodeTester?.terminate();
} catch (e: any) {
console.error('Error', e);
displayOutput(`ERROR: ${e.message}`, 'red');
}
};
if (testButton) {
testButton.onclick = async function () {
console.log('clicked');
const mixnodeId = mixnodeIdInput.value;
if (!nodeTester) {
displayOutput('ERROR: The node tester is not defined');
console.error('The node tester is not defined');
return;
}
if (!mixnodeId) {
displayOutput('ERROR: No mix id specified');
console.error('No mix id specified');
return;
}
if (nodeTester && mixnodeId) {
displayOutput('Starting test...');
try {
const response = await nodeTester.tester.startTest(mixnodeId);
displayOutput('Done!');
if (response) {
displayOutput(JSON.stringify(response, null, 2), 'green');
}
} catch (e: any) {
console.error('Error', e);
displayOutput(`ERROR: ${e.message}`, 'red');
}
}
};
}
}
// wait for the html to load
window.addEventListener('DOMContentLoaded', () => {
// let's do this!
main();
});
@@ -1,8 +0,0 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules", "build", "dist"]
}
@@ -1,14 +0,0 @@
# Nym Node Tester - HTML
This is an example of using the Nym Mixnet node tester.
You can use this example as a seed for a new project.
## Running the example
Try out the node tester app by running:
```
npm install
npm start
```
@@ -1,65 +0,0 @@
{
"name": "@nymproject/sdk-example-node-tester-plain-html",
"version": "1.0.5",
"description": "An example project that uses WASM node tester and plain HTML",
"license": "Apache-2.0",
"scripts": {
"build": "webpack build --progress --config webpack.prod.js",
"build:dev": "webpack build --progress",
"build:serve": "npx serve dist",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"start": "webpack serve --progress --port 3000",
"test": "jest",
"test:watch": "jest --watch",
"tsc": "tsc",
"tsc:watch": "tsc --watch"
},
"dependencies": {
"@nymproject/sdk": ">=1.4.1-rc1 || ^1"
},
"devDependencies": {
"@babel/core": "^7.15.0",
"@babel/plugin-transform-async-to-generator": "^7.14.5",
"@babel/preset-env": "^7.15.0",
"@babel/preset-typescript": "^7.15.0",
"@types/jest": "^27.0.1",
"@types/node": "^16.7.13",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"babel-loader": "^8.3.0",
"babel-plugin-root-import": "^5.1.0",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^6.7.3",
"css-minimizer-webpack-plugin": "^3.0.2",
"dotenv-webpack": "^7.0.3",
"eslint": "^8.10.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"file-loader": "^6.2.0",
"fork-ts-checker-webpack-plugin": "^7.2.1",
"html-webpack-plugin": "^5.3.2",
"jest": "^27.1.0",
"mini-css-extract-plugin": "^2.2.2",
"npm-run-all": "^4.1.5",
"prettier": "^2.8.7",
"style-loader": "^3.3.1",
"thread-loader": "^3.0.4",
"ts-jest": "^27.0.5",
"ts-loader": "^9.4.2",
"tsconfig-paths-webpack-plugin": "^3.5.2",
"typescript": "^4.6.2",
"url-loader": "^4.1.1",
"webpack": "^5.75.0",
"webpack-cli": "^4.8.0",
"webpack-dev-server": "^4.5.0",
"webpack-merge": "^5.8.0"
},
"private": false
}
@@ -1,29 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nym Node Tester Demo</title>
</head>
<body>
<p>
<label>Mixnode Id: </label><input size="85" type="text" id="mixnodeId" value="">
</p>
<p>
<button id="send-button">Test</button>
<button id="disconnect-button">Disconnect from Gateway</button>
<button id="reconnect-button">Reconnect to Gateway</button>
<button id="terminate-button">Terminate worker</button>
</p>
<p>Test a mixnode by entering the mixnode id above and click the Test button</p>
<hr>
<p>
<div id="output"></div>
</p>
</body>
</html>
@@ -1,116 +0,0 @@
import { createNodeTesterClient, NodeTester } from '@nymproject/sdk';
let nodeTester: NodeTester | null = null;
/**
* Display messages that have been sent up the websocket. Colours them blue.
*
* @param {string} message
*/
function displayOutput(message: string, color?: string) {
const timestamp = new Date().toISOString().substr(11, 12);
const sendDiv = document.createElement('div');
const paragraph = document.createElement('p');
paragraph.setAttribute('style', `color: ${color || 'blue'}`);
const paragraphContent = document.createTextNode(`${timestamp} >>> ${message}`);
paragraph.appendChild(paragraphContent);
sendDiv.appendChild(paragraph);
document.getElementById('output')?.appendChild(sendDiv);
}
/**
* The main entry point
*/
async function main() {
nodeTester = await createNodeTesterClient();
// add node tester to the Window globally, so that it can be used from the dev tools console
(window as any).nodeTester = nodeTester;
if (!nodeTester) {
console.error('Oh no! Could not the node test');
return;
}
const nymApiUrl = 'https://validator.nymtech.net/api';
const nodeTesterId = new Date().toISOString(); // make a new tester id for each session
await nodeTester.tester.init(nymApiUrl, nodeTesterId);
const mixnodes = await (await fetch(`${nymApiUrl}/v1/mixnodes/active`)).json();
const exampleMixnodeIdentityKey = mixnodes[0].bond_information.mix_node.identity_key;
const sendButton: HTMLButtonElement = document.querySelector('#send-button') as HTMLButtonElement;
const reconnectButton: HTMLButtonElement = document.querySelector('#reconnect-button') as HTMLButtonElement;
const disconnectButton: HTMLButtonElement = document.querySelector('#disconnect-button') as HTMLButtonElement;
const terminateButton: HTMLButtonElement = document.querySelector('#terminate-button') as HTMLButtonElement;
const mixnodeIdInput = document.getElementById('mixnodeId') as HTMLFormElement;
mixnodeIdInput.value = exampleMixnodeIdentityKey;
reconnectButton.onclick = async function () {
try {
await nodeTester?.tester.reconnectToGateway();
} catch (e: any) {
console.error('Error', e);
displayOutput(`ERROR: ${e.message}`, 'red');
}
};
disconnectButton.onclick = async function () {
try {
await nodeTester?.tester.disconnectFromGateway();
} catch (e: any) {
console.error('Error', e);
displayOutput(`ERROR: ${e.message}`, 'red');
}
};
terminateButton.onclick = async function () {
try {
await nodeTester?.terminate();
} catch (e: any) {
console.error('Error', e);
displayOutput(`ERROR: ${e.message}`, 'red');
}
};
if (sendButton) {
sendButton.onclick = async function () {
const mixnodeId = mixnodeIdInput.value;
if (!nodeTester) {
displayOutput('ERROR: The node tester is not defined');
console.error('The node tester is not defined');
return;
}
if (!mixnodeId) {
displayOutput('ERROR: No mix id specified');
console.error('No mix id specified');
return;
}
if (nodeTester && mixnodeId) {
displayOutput('Starting test...');
try {
const response = await nodeTester.tester.startTest(mixnodeId);
displayOutput('Done!');
if (response) {
displayOutput(JSON.stringify(response, null, 2), 'green');
}
} catch (e: any) {
console.error('Error', e);
displayOutput(`ERROR: ${e.message}`, 'red');
}
}
};
}
}
// wait for the html to load
window.addEventListener('DOMContentLoaded', () => {
// let's do this!
main();
});
@@ -1,8 +0,0 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules", "build", "dist"]
}
@@ -1,10 +0,0 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"jsx": "react-jsx",
"outDir": "./dist",
"declaration": false
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules", "build", "dist", "**/*.stories.*", "**/*.test.*", "**/*.spec.*"]
}
@@ -1,30 +0,0 @@
const path = require('path');
const { mergeWithRules } = require('webpack-merge');
const { webpackCommon } = require('../../.webpack/webpack.base');
module.exports = mergeWithRules({
module: {
rules: {
test: 'match',
use: 'replace',
},
},
})(
webpackCommon(__dirname, [
{
inject: true,
filename: 'index.html',
template: path.resolve(__dirname, 'src/index.html'),
chunks: ['index'],
},
]),
{
entry: {
index: path.resolve(__dirname, 'src/index.ts'),
},
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
},
},
);
@@ -1,67 +0,0 @@
const { mergeWithRules } = require('webpack-merge');
const webpack = require('webpack');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const ReactRefreshTypeScript = require('react-refresh-typescript');
const commonConfig = require('./webpack.common');
module.exports = mergeWithRules({
module: {
rules: {
test: 'match',
use: 'replace',
},
},
})(commonConfig, {
mode: 'development',
devtool: 'inline-source-map',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
options: {
getCustomTransformers: () => ({
before: [ReactRefreshTypeScript()],
}),
// `ts-loader` does not work with HMR unless `transpileOnly` is used.
// If you need type checking, `ForkTsCheckerWebpackPlugin` is an alternative.
transpileOnly: true,
},
},
],
},
plugins: [
new ReactRefreshWebpackPlugin(),
// this can be included automatically by the dev server, however build mode fails if missing
new webpack.HotModuleReplacementPlugin(),
],
target: 'web',
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
},
historyApiFallback: true,
},
// recommended for faster rebuild
optimization: {
runtimeChunk: true,
removeAvailableModules: false,
removeEmptyChunks: false,
splitChunks: false,
},
cache: {
type: 'filesystem',
buildDependencies: {
// restart on config change
config: ['./webpack.config.js'],
},
},
});
@@ -1,42 +0,0 @@
const { mergeWithRules } = require('webpack-merge');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const commonConfig = require('./webpack.common');
module.exports = mergeWithRules({
module: {
rules: {
test: 'match',
use: 'replace',
},
},
})(commonConfig, {
mode: 'production',
// TODO: no source maps, add back
devtool: false,
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
optimization: {
minimizer: ['...', new CssMinimizerPlugin()],
splitChunks: {
chunks: 'all',
},
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
}),
],
output: {
pathinfo: false,
filename: '[name].[contenthash].js',
},
});
@@ -1,14 +0,0 @@
# Nym Node Tester - React
This is an example of using the Nym Mixnet node tester.
You can use this example as a seed for a new project.
## Running the example
Try out the node tester app by running:
```
npm install
npm start
```
@@ -1,13 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="shortcut icon" href="../../../../../assets/favicon/favicon.png" />
<title>Nym Node Tester Example</title>
</head>
<body>
<div id="root"></div>
<script src="src/index.tsx" type="module"></script>
</body>
</html>
@@ -1,20 +0,0 @@
{
"name": "@nymproject/sdk-example-node-tester-react",
"version": "1.0.5",
"description": "An example project that uses WASM node tester and React",
"license": "Apache-2.0",
"scripts": {
"start": "parcel index.html"
},
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.14.0",
"@mui/material": "^5.14.0",
"@nymproject/sdk": ">=1.4.1-rc1 || ^1",
"parcel": "^2.9.3",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"private": false
}
@@ -1,127 +0,0 @@
import React, { useState } from 'react';
import {
Button,
Card,
CardActions,
CardContent,
CardHeader,
CircularProgress,
Grid,
List,
ListItem,
ListItemText,
TextField,
Typography,
} from '@mui/material';
import { NodeTestResultResponse } from '@nymproject/sdk';
import { ScoreIndicator } from 'src/components/ScoreIndicator';
import { useNodeTesterClient } from 'src/hooks/useNodeTesterClient';
import { BasicPageLayout } from 'src/layouts';
import { TestStatusLabel } from 'src/components/TestStatusLabel';
import Icon from '../../../../../../assets/appicon/appicon.png';
export const App = () => {
const { testState, error, testNode, disconnectFromGateway, reconnectToGateway } = useNodeTesterClient();
const [mixnodeIdentity, setMixnodeIdentity] = useState<string>('');
const [results, setResults] = React.useState<NodeTestResultResponse>();
console.log({ testState, error, testNode });
const handleTestNode = async () => {
setResults(undefined);
try {
const result = await testNode(mixnodeIdentity);
setResults(result);
} catch (e) {
console.error(e);
}
};
return (
<BasicPageLayout>
<Card variant="outlined" sx={{ mt: 15, p: 4 }}>
<CardHeader
title={<Typography variant="h6">Nym Mixnode Testnet Node Tester</Typography>}
action={<TestStatusLabel state={testState} />}
avatar={<img src={Icon} width={40} />}
/>
<CardContent sx={{ mb: 2 }}>
<Grid container spacing={2}>
<Grid item xs={12} sm={6}>
<ScoreIndicator score={results?.score || 0} />
</Grid>
<Grid item xs={12} sm={6}>
<List>
<ListItem>
<ListItemText primary="Packets sent" secondary={results?.sentPackets.toString() || '-'} />
</ListItem>
<ListItem>
<ListItemText primary="Packets received" secondary={results?.receivedPackets.toString() || '-'} />
</ListItem>
<ListItem>
<ListItemText
primary="Duplicate packets received"
secondary={results?.duplicatePackets.toString() || '-'}
/>
</ListItem>
</List>
</Grid>
</Grid>
</CardContent>
<CardActions>
<Grid container spacing={2}>
<Grid item xs={12}>
<TextField
label="Enter a Mixnode Identity to test"
value={mixnodeIdentity}
onChange={(e) => {
setMixnodeIdentity(e.target.value);
}}
fullWidth
/>
</Grid>
<Grid item xs={12} sm={4}>
<Button
disabled={!disconnectFromGateway || testState === 'Disconnected' || testState === 'Testing'}
onClick={disconnectFromGateway}
variant="outlined"
disableElevation
size="large"
fullWidth
sx={{ mr: 2 }}
>
Disconnect
</Button>
</Grid>
<Grid item xs={12} sm={4}>
<Button
disabled={!reconnectToGateway || testState === 'Ready' || testState === 'Testing'}
onClick={reconnectToGateway}
variant="outlined"
disableElevation
size="large"
fullWidth
sx={{ mr: 2 }}
>
Reconnect
</Button>
</Grid>
<Grid item xs={12} sm={4}>
<Button
disabled={!testNode || !mixnodeIdentity || testState === 'Testing' || testState === 'Disconnected'}
onClick={handleTestNode}
variant="contained"
disableElevation
fullWidth
size="large"
endIcon={testState === 'Testing' && <CircularProgress size={25} />}
>
Start test
</Button>
</Grid>
</Grid>
</CardActions>
</Card>
</BasicPageLayout>
);
};
@@ -1,61 +0,0 @@
import React from 'react';
import { Box, CircularProgress, CircularProgressProps, Stack, Typography } from '@mui/material';
const getPerformanceDescriptionAndColor = (score: number) => {
const res: { description: string; color: CircularProgressProps['color'] } = { description: '', color: 'warning' };
if (score >= 90) {
res.description = 'Reliable node';
res.color = 'success';
}
if (score >= 75 && score < 90) {
res.description = 'Average node';
res.color = 'warning';
}
if (score > 0 && score < 75) {
res.description = 'Unreliable node';
res.color = 'error';
}
return res;
};
export const ScoreIndicator = ({ score }) => {
const { color } = getPerformanceDescriptionAndColor(score);
return (
<Box
sx={{
display: 'flex',
position: 'relative',
width: 250,
height: 250,
justifyContent: 'center',
alignItems: 'center',
mx: 'auto',
mt: 4,
}}
>
<CircularProgress
variant="determinate"
value={100}
size={250}
sx={{ position: 'absolute', top: 0, left: 0, color: 'grey.200' }}
/>
<CircularProgress
variant="determinate"
value={score}
size={250}
sx={{ position: 'absolute', top: 0, left: 0 }}
color={color}
/>
<Stack alignItems="center" gap={1}>
<Typography fontWeight="bold" variant="h4">
{Math.round(score)}%
</Typography>
<Typography>Performance Score</Typography>
</Stack>
</Box>
);
};
@@ -1,34 +0,0 @@
import React from 'react';
import { Chip } from '@mui/material';
import { HourglassTop, ErrorOutline, CheckCircleOutline, WarningAmber } from '@mui/icons-material';
import { TestState } from 'src/hooks/useNodeTesterClient';
const getColor = (state: TestState) => {
switch (state) {
case 'Connecting':
return 'warning';
case 'Error':
return 'error';
case 'Ready':
return 'success';
default:
return 'warning';
}
};
const getIcon = (state: TestState) => {
switch (state) {
case 'Connecting':
return <HourglassTop />;
case 'Error':
return <ErrorOutline />;
case 'Ready':
return <CheckCircleOutline />;
default:
return <WarningAmber />;
}
};
export const TestStatusLabel = ({ state }: { state: TestState }) => (
<Chip label={state} color={getColor(state)} icon={getIcon(state)} sx={{ color: 'white' }} />
);
@@ -1,71 +0,0 @@
import { useState, useEffect } from 'react';
import { createNodeTesterClient, NodeTester } from '@nymproject/sdk';
export type TestState = 'Ready' | 'Connecting' | 'Disconnected' | 'Disconnecting' | 'Error' | 'Testing' | 'Stopped';
export const useNodeTesterClient = () => {
const [client, setClient] = useState<NodeTester>();
const [error, setError] = useState<string>();
const [testState, setTestState] = useState<TestState>('Disconnected');
const createClient = async () => {
setTestState('Connecting');
try {
const validator = 'https://validator.nymtech.net/api';
const nodeTesterClient = await createNodeTesterClient();
await nodeTesterClient.tester.init(validator);
setClient(nodeTesterClient);
} catch (e) {
console.log(e);
setError('Failed to load node tester client, please try again');
} finally {
setTestState('Ready');
}
};
useEffect(() => {
createClient();
}, []);
const testNode = !client
? undefined
: async (mixnodeIdentity: string) => {
try {
setTestState('Testing');
const result = await client.tester.startTest(mixnodeIdentity);
setTestState('Ready');
return result;
} catch (e) {
console.log(e);
setError('Failed to test node, please try again');
setTestState('Error');
}
};
const disconnectFromGateway = !client
? undefined
: async () => {
setTestState('Disconnecting');
await client.tester.disconnectFromGateway();
setTestState('Disconnected');
};
const reconnectToGateway = !client
? undefined
: async () => {
setTestState('Connecting');
await client.tester.reconnectToGateway();
setTestState('Ready');
};
const terminateWorker = !client
? undefined
: async () => {
setTestState('Disconnecting');
await client.terminate();
setTestState('Disconnected');
};
return { testNode, disconnectFromGateway, reconnectToGateway, terminateWorker, testState, error };
};
@@ -1,14 +0,0 @@
import React from 'react';
import { createRoot } from 'react-dom/client';
import { App } from './App';
import { NymThemeProvider } from './theme/theme';
const rootDOMElem = document.getElementById('root');
if (!rootDOMElem) throw new Error('Root element not found');
const root = createRoot(rootDOMElem);
root.render(
<NymThemeProvider>
<App />
</NymThemeProvider>,
);
@@ -1,6 +0,0 @@
import React from 'react';
import { Container } from '@mui/material';
export const BasicPageLayout = ({ children }: { children: React.ReactNode }) => (
<Container maxWidth="md">{children}</Container>
);
@@ -1,28 +0,0 @@
import * as React from 'react';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import { CssBaseline } from '@mui/material';
export const NymThemeProvider = ({ children }: { children: React.ReactNode }) => {
const theme = createTheme({
palette: {
mode: 'dark',
primary: {
main: '#FB6E4E',
},
success: {
main: '#21D073',
},
background: {
default: '#1D2125',
paper: '#292E34',
},
},
});
return (
<ThemeProvider theme={theme}>
<CssBaseline />
{children}
</ThemeProvider>
);
};
@@ -1,4 +0,0 @@
declare module '*.png' {
const content: any;
export default content;
}
@@ -1,16 +0,0 @@
{
"compilerOptions": {
"jsx": "react",
"baseUrl": ".",
"paths": {
"react": ["node_modules/react"],
"react-dom": ["node_modules/react-dom"]
},
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
},
"include": ["src"],
"paths": {
"@assets/*": ["../../../../../../assets"]
}
}
@@ -7,15 +7,15 @@ You can use this example as a seed for a new project.
Remember to build the dependency packages from the root of this repo by running:
```
yarn
yarn build
pnpm i
pnpm build
```
If you need to make changes to the dependency packages, you can run `yarn watch` in that package to watch for chagnes and build them. This project will pick up the changes in the built package and hot-reload / recompile.
## Features
### Yarn workspaces
### pnpm workspaces
Packages from `ts-packages` are shared using Yarn workspaces. Make sure you add you new project to [package.json](../../package.json) to use the shared packages.
@@ -4,70 +4,70 @@
"version": "1.0.0",
"license": "Apache-2.0",
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "catalog:",
"react-dom": "catalog:",
"@mui/material": "^5.0.1",
"@mui/styles": "^5.0.1",
"@mui/icons-material": "^5.5.0",
"@mui/icons-material": "catalog:",
"@mui/lab": "^5.0.0-alpha.72",
"@nymproject/mui-theme": "^1.0.0",
"@nymproject/react": "^1.0.0"
"@nymproject/mui-theme": "workspace:*",
"@nymproject/react": "workspace:*"
},
"devDependencies": {
"@babel/core": "^7.15.0",
"@babel/plugin-transform-async-to-generator": "^7.14.5",
"@babel/preset-env": "^7.15.0",
"@babel/preset-react": "^7.14.5",
"@babel/preset-typescript": "^7.15.0",
"@nymproject/eslint-config-react-typescript": "^1.0.0",
"@nymproject/webpack": "^1.0.0",
"@babel/core": "catalog:",
"@babel/plugin-transform-async-to-generator": "catalog:",
"@babel/preset-env": "catalog:",
"@babel/preset-react": "catalog:",
"@babel/preset-typescript": "catalog:",
"@nymproject/eslint-config-react-typescript": "workspace:*",
"@nymproject/webpack": "workspace:*",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.4",
"@svgr/webpack": "^6.1.1",
"@svgr/webpack": "catalog:",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.0.0",
"@types/jest": "^27.0.1",
"@types/node": "^16.7.13",
"@types/react": "^18.0.26",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"babel-loader": "^8.3.0",
"@types/react": "catalog:",
"@typescript-eslint/eslint-plugin": "catalog:",
"@typescript-eslint/parser": "catalog:",
"babel-loader": "catalog:",
"babel-plugin-root-import": "^5.1.0",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^6.7.3",
"clean-webpack-plugin": "catalog:",
"css-loader": "catalog:",
"css-minimizer-webpack-plugin": "^3.0.2",
"dotenv-webpack": "^7.0.3",
"dotenv-webpack": "catalog:",
"eslint": "^8.10.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.29.2",
"eslint-plugin-react-hooks": "^4.3.0",
"favicons": "^7.0.2",
"favicons-webpack-plugin": "^5.0.2",
"file-loader": "^6.2.0",
"fork-ts-checker-webpack-plugin": "^7.2.1",
"html-webpack-plugin": "^5.3.2",
"jest": "^27.1.0",
"mini-css-extract-plugin": "^2.2.2",
"prettier": "^2.8.7",
"eslint-config-airbnb": "catalog:",
"eslint-config-airbnb-typescript": "catalog:",
"eslint-config-prettier": "catalog:",
"eslint-import-resolver-root-import": "catalog:",
"eslint-plugin-import": "catalog:",
"eslint-plugin-jest": "catalog:",
"eslint-plugin-jsx-a11y": "catalog:",
"eslint-plugin-prettier": "catalog:",
"eslint-plugin-react": "catalog:",
"eslint-plugin-react-hooks": "catalog:",
"favicons": "catalog:",
"favicons-webpack-plugin": "catalog:",
"file-loader": "catalog:",
"fork-ts-checker-webpack-plugin": "catalog:",
"html-webpack-plugin": "catalog:",
"jest": "catalog:",
"mini-css-extract-plugin": "catalog:",
"prettier": "catalog:",
"react-refresh-typescript": "^2.0.3",
"style-loader": "^3.3.1",
"style-loader": "catalog:",
"thread-loader": "^3.0.4",
"ts-jest": "^27.0.5",
"ts-loader": "^9.4.2",
"tsconfig-paths-webpack-plugin": "^3.5.2",
"ts-jest": "catalog:",
"ts-loader": "catalog:",
"tsconfig-paths-webpack-plugin": "catalog:",
"typescript": "^4.6.2",
"url-loader": "^4.1.1",
"webpack": "^5.75.0",
"webpack-cli": "^4.8.0",
"webpack-dev-server": "^4.5.0",
"webpack-favicons": "^1.3.8",
"webpack-merge": "^5.8.0"
"url-loader": "catalog:",
"webpack": "catalog:",
"webpack-cli": "catalog:",
"webpack-dev-server": "catalog:",
"webpack-favicons": "catalog:",
"webpack-merge": "catalog:"
},
"scripts": {
"start": "webpack serve --progress --port 3000",
@@ -11,22 +11,22 @@
"devDependencies": {
"@types/jest": "^27.0.1",
"@types/node": "^16.7.13",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"@typescript-eslint/eslint-plugin": "catalog:",
"@typescript-eslint/parser": "catalog:",
"eslint": "^8.10.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^27.1.0",
"mini-css-extract-plugin": "^2.2.2",
"npm-run-all": "^4.1.5",
"prettier": "^2.8.7",
"ts-jest": "^27.0.5",
"eslint-config-airbnb": "catalog:",
"eslint-config-airbnb-typescript": "catalog:",
"eslint-config-prettier": "catalog:",
"eslint-import-resolver-root-import": "catalog:",
"eslint-plugin-import": "catalog:",
"eslint-plugin-jest": "catalog:",
"eslint-plugin-jsx-a11y": "catalog:",
"eslint-plugin-prettier": "catalog:",
"jest": "catalog:",
"mini-css-extract-plugin": "catalog:",
"npm-run-all": "catalog:",
"prettier": "catalog:",
"ts-jest": "catalog:",
"typescript": "^4.6.2"
},
"scripts": {
@@ -1,7 +0,0 @@
# Nym DOM Utils
This package manipulates the DOM without any frameworks.
## Usage
TODO
@@ -1,61 +0,0 @@
import { NymMixnetClient, MimeTypes } from '@nymproject/sdk';
/**
* 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
*/
export async function sendMessageTo(nym: NymMixnetClient) {
const message = (document.getElementById('message') as HTMLFormElement).value;
const recipient = (document.getElementById('recipient') as HTMLFormElement).value;
await nym.client.send({ payload: { message, mimeType: MimeTypes.TextPlain }, recipient });
createChatEntry({message, sendOrReceive: "SEND"});
}
const createISOTimeStamp = () => new Date().toISOString().substring(11, 12);
const createChatEntry = ({message, sendOrReceive}: {message: string, sendOrReceive: "SEND" | "RECEIVE"}) => {
const timestamp = createISOTimeStamp();
const sendDiv = document.createElement('div');
const paragraph = document.createElement('p');
paragraph.setAttribute('style', `color: ${sendOrReceive === "SEND" ? "blue" : "green"}`);
const paragraphContent = document.createTextNode(`${timestamp} sent >>> ${message}`);
paragraph.appendChild(paragraphContent);
sendDiv.appendChild(paragraph);
document.getElementById('output')?.appendChild(sendDiv);
/**
* Display messages that have been sent up the websocket. Colours them blue.
*
* @param {string} message
*/
function displaySend(message: string) {
createChatEntry({message, sendOrReceive: "SEND"});
return undefined
}
/**
* Display received text messages in the browser. Colour them green.
*
* @param {string} message
*/
export function displayReceived(message: string) {
return createChatEntry({message, sendOrReceive: "RECEIVE"});
return undefined
}
/**
* Display the nymClient's sender address in the user interface
*
* @param {Client} nymClient
*/
export function displaySenderAddress(address: string) {
(document.getElementById('sender') as HTMLFormElement).value = address;
}
@@ -19,11 +19,11 @@
"docs:generate:prod": "typedoc --basePath ./docs/tsdoc/nymproject/sdk/",
"docs:prod:build": "scripts/build-prod-docs-collect.sh",
"docs:serve": "reload -b -d ./docs -p 3000",
"docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"yarn docs:generate\"",
"docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"pnpm docs:generate\"",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"start": "tsc -w",
"start:dev": "nodemon --watch src -e ts,json --exec 'yarn build:dev:esm'",
"start:dev": "nodemon --watch src -e ts,json --exec 'pnpm build:dev:esm'",
"test": "node --experimental-fetch --experimental-vm-modules node_modules/jest/bin/jest.js -c=jest.config.mjs --no-cache",
"tsc": "tsc --noEmit true"
},
@@ -42,30 +42,32 @@
"@rollup/plugin-wasm": "^6.1.1",
"@types/jest": "^27.0.1",
"@types/node": "^16.7.13",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"@types/ws": "catalog:",
"@typescript-eslint/eslint-plugin": "catalog:",
"@typescript-eslint/parser": "catalog:",
"eslint": "^8.10.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-config-airbnb": "catalog:",
"eslint-config-airbnb-typescript": "catalog:",
"eslint-config-prettier": "catalog:",
"eslint-import-resolver-root-import": "catalog:",
"eslint-plugin-import": "catalog:",
"eslint-plugin-jest": "catalog:",
"eslint-plugin-jsx-a11y": "catalog:",
"eslint-plugin-prettier": "catalog:",
"jest": "^29.5.0",
"nodemon": "^2.0.21",
"reload": "^3.2.1",
"rimraf": "^3.0.2",
"rimraf": "catalog:",
"rollup": "^3.9.1",
"rollup-plugin-base64": "^1.0.1",
"rollup-plugin-modify": "^3.0.0",
"rollup-plugin-web-worker-loader": "^1.6.1",
"ts-jest": "^29.1.0",
"ts-loader": "^9.4.2",
"ts-loader": "catalog:",
"tslib": "catalog:",
"typedoc": "^0.24.8",
"typescript": "^4.8.4"
},
"private": false,
"types": "./dist/cjs/index.d.ts"
}
}
@@ -7,7 +7,7 @@ This project is for use by Nym developers only. Use at your own risk!
From the root of this repository run:
```
yarn
pnpm i
make sdk-wasm-build
```
@@ -20,25 +20,25 @@ cd sdk/typescript/packages/mix-fetch
You can run in watch mode:
```
yarn start
pnpm start
```
Or do a single build:
```
yarn build:dev:esm-no-inline
pnpm build:dev:esm-no-inline
```
Then, in another terminal:
```
cd sdk/typescript/packages/mix-fetch/internal-dev/parcel
yarn && yarn start
pnpm i && pnpm start
```
If you have trouble with changes not propagating:
```
rm -rf node_modules && yarn && yarn start
rm -rf node_modules && pnpm i && pnpm start
```
@@ -11,48 +11,48 @@
"@nymproject/mix-fetch": ">=1.4.2-rc.0 || ^1"
},
"devDependencies": {
"@babel/core": "^7.22.10",
"@babel/plugin-transform-async-to-generator": "^7.22.5",
"@babel/preset-env": "^7.22.10",
"@babel/preset-typescript": "^7.22.5",
"@babel/core": "catalog:",
"@babel/plugin-transform-async-to-generator": "catalog:",
"@babel/preset-env": "catalog:",
"@babel/preset-typescript": "catalog:",
"@types/jest": "^27.0.1",
"@types/node": "^16.7.13",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"@typescript-eslint/eslint-plugin": "catalog:",
"@typescript-eslint/parser": "catalog:",
"babel-loader": "^9.1.3",
"babel-plugin-root-import": "^6.6.0",
"clean-webpack-plugin": "^4.0.0",
"clean-webpack-plugin": "catalog:",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.8.1",
"css-loader": "catalog:",
"css-minimizer-webpack-plugin": "^5.0.1",
"dotenv-webpack": "^8.0.1",
"eslint": "^9.26.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"file-loader": "^6.2.0",
"eslint": "catalog:",
"eslint-config-airbnb": "catalog:",
"eslint-config-airbnb-typescript": "catalog:",
"eslint-config-prettier": "catalog:",
"eslint-import-resolver-root-import": "catalog:",
"eslint-plugin-import": "catalog:",
"eslint-plugin-jest": "catalog:",
"eslint-plugin-jsx-a11y": "catalog:",
"eslint-plugin-prettier": "catalog:",
"file-loader": "catalog:",
"fork-ts-checker-webpack-plugin": "^8.0.0",
"html-webpack-plugin": "^5.5.3",
"jest": "^27.1.0",
"mini-css-extract-plugin": "^2.7.6",
"npm-run-all": "^4.1.5",
"prettier": "^2.8.7",
"style-loader": "^3.3.3",
"html-webpack-plugin": "catalog:",
"jest": "catalog:",
"mini-css-extract-plugin": "catalog:",
"npm-run-all": "catalog:",
"prettier": "catalog:",
"style-loader": "catalog:",
"thread-loader": "^4.0.2",
"ts-jest": "^27.0.5",
"ts-loader": "^9.4.4",
"ts-jest": "catalog:",
"ts-loader": "catalog:",
"tsconfig-paths-webpack-plugin": "^4.1.0",
"typescript": "^4.6.2",
"url-loader": "^4.1.1",
"webpack": "^5.88.2",
"url-loader": "catalog:",
"webpack": "catalog:",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1",
"webpack-merge": "^5.9.0"
"webpack-dev-server": "catalog:",
"webpack-merge": "catalog:"
},
"private": false
}
}
+24 -23
View File
@@ -24,12 +24,12 @@
"docs:generate:prod": "typedoc --basePath ./docs/tsdoc/nymproject/sdk/",
"docs:prod:build": "scripts/build-prod-docs-collect.sh",
"docs:serve": "reload -b -d ./docs -p 3000",
"docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"yarn docs:generate\"",
"docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"pnpm docs:generate\"",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"prebuild": "node scripts/showDependencyLocation.cjs",
"start": "tsc -w",
"start:dev": "nodemon --watch src -e ts,json --exec 'yarn build:dev:esm'",
"start:dev": "nodemon --watch src -e ts,json --exec 'pnpm build:dev:esm'",
"test": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js -c=jest.config.mjs --no-cache",
"tsc": "tsc --noEmit true"
},
@@ -38,12 +38,12 @@
"comlink": "^4.3.1"
},
"devDependencies": {
"@babel/core": "^7.15.0",
"@babel/plugin-transform-async-to-generator": "^7.14.5",
"@babel/preset-env": "^7.15.0",
"@babel/preset-react": "^7.14.5",
"@babel/preset-typescript": "^7.15.0",
"@nymproject/eslint-config-react-typescript": "^1.0.0",
"@babel/core": "catalog:",
"@babel/plugin-transform-async-to-generator": "catalog:",
"@babel/preset-env": "catalog:",
"@babel/preset-react": "catalog:",
"@babel/preset-typescript": "catalog:",
"@nymproject/eslint-config-react-typescript": "workspace:*",
"@rollup/plugin-commonjs": "^24.0.1",
"@rollup/plugin-inject": "^5.0.3",
"@rollup/plugin-json": "^6.0.0",
@@ -54,32 +54,33 @@
"@rollup/plugin-wasm": "^6.1.1",
"@types/jest": "^27.0.1",
"@types/node": "^16.7.13",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"@typescript-eslint/eslint-plugin": "catalog:",
"@typescript-eslint/parser": "catalog:",
"eslint": "^8.10.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.29.2",
"eslint-plugin-react-hooks": "^4.3.0",
"eslint-config-airbnb": "catalog:",
"eslint-config-airbnb-typescript": "catalog:",
"eslint-config-prettier": "catalog:",
"eslint-import-resolver-root-import": "catalog:",
"eslint-plugin-import": "catalog:",
"eslint-plugin-jest": "catalog:",
"eslint-plugin-jsx-a11y": "catalog:",
"eslint-plugin-prettier": "catalog:",
"eslint-plugin-react": "catalog:",
"eslint-plugin-react-hooks": "catalog:",
"jest": "^29.5.0",
"nodemon": "^2.0.21",
"reload": "^3.2.1",
"rimraf": "^3.0.2",
"rimraf": "catalog:",
"rollup": "^3.9.1",
"rollup-plugin-base64": "^1.0.1",
"rollup-plugin-web-worker-loader": "^1.6.1",
"ts-jest": "^29.1.0",
"ts-loader": "^9.4.2",
"ts-loader": "catalog:",
"tslib": "catalog:",
"typedoc": "^0.24.8",
"typescript": "^4.8.4"
},
"private": false,
"type": "module",
"types": "./dist/esm/index.d.ts"
}
}
@@ -7,7 +7,7 @@ set -o pipefail
rm -rf ../../../../dist/ts/docs/tsdoc/nymproject/mix-fetch || true
# run the build
yarn docs:generate:prod
pnpm docs:generate:prod
# move the output outside of the yarn/npm workspaces
mkdir -p ../../../../dist/ts/docs/tsdoc/nymproject
+4 -4
View File
@@ -51,8 +51,8 @@ export const Content: FCWithChildren = () => {
The best way to make changes to the theme is to:
1. Run this package in watch mode with `yarn watch`
2. Run Storybook from [react-components](../react-components/README.md) with `yarn storybook`
1. Run this package in watch mode with `pnpm watch`
2. Run Storybook from [react-components](../react-components/README.md) with `pnpm storybook`
3. Make sure the component you are changing is included in the [playground](../react-components/src/playground/index.tsx)
4. Watch for changes in the [Playground story](../react-components/src/stories/Playground.stories.tsx)
@@ -63,8 +63,8 @@ Also remember to check light mode and dark mode!
This package should be built from the root of the repository as follows:
```
yarn
yarn build
pnpm i
pnpm build
```
## Publishing
+22 -22
View File
@@ -5,33 +5,33 @@
"main": "dist/index.js",
"types": "dist/index.d.ts",
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "catalog:",
"react-dom": "catalog:",
"@mui/material": "^5.2.2",
"@mui/styles": "^5.2.2"
},
"devDependencies": {
"@nymproject/eslint-config-react-typescript": "^1.0.0",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"eslint": "^9.26.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.29.2",
"eslint-plugin-react-hooks": "^4.3.0",
"prettier": "^2.8.7",
"typescript": "^4.6.2",
"ts-jest": "^27.0.5",
"jest": "^27.1.0",
"@nymproject/eslint-config-react-typescript": "workspace:*",
"@types/react": "catalog:",
"@typescript-eslint/eslint-plugin": "catalog:",
"@typescript-eslint/parser": "catalog:",
"babel-plugin-root-import": "^5.1.0",
"@types/react": "^18.0.26",
"rimraf": "^3.0.2"
"eslint": "catalog:",
"eslint-config-airbnb": "catalog:",
"eslint-config-airbnb-typescript": "catalog:",
"eslint-config-prettier": "catalog:",
"eslint-import-resolver-root-import": "catalog:",
"eslint-plugin-import": "catalog:",
"eslint-plugin-jest": "catalog:",
"eslint-plugin-jsx-a11y": "catalog:",
"eslint-plugin-prettier": "catalog:",
"eslint-plugin-react": "catalog:",
"eslint-plugin-react-hooks": "catalog:",
"jest": "catalog:",
"prettier": "catalog:",
"rimraf": "catalog:",
"ts-jest": "catalog:",
"typescript": "^4.6.2"
},
"scripts": {
"clean": "rimraf dist",
@@ -1,3 +0,0 @@
{
"presets": ["@babel/env"]
}
@@ -1 +0,0 @@
src/worker.js
@@ -1,7 +0,0 @@
# Nym Node Tester
This package provides a WASM library to test if a Nym node can process packets.
## Usage
TODO
@@ -1,7 +0,0 @@
# Nym Node Tester
This package provides a WASM library to test if a Nym node can process packets.
## Usage
TODO
@@ -1,7 +0,0 @@
# Nym Node Tester
This package provides a WASM library to test if a Nym node can process packets.
## Usage
TODO
@@ -1,7 +0,0 @@
# Nym Node Tester
This package provides a WASM library to test if a Nym node can process packets.
## Usage
TODO
@@ -1,15 +0,0 @@
import preset from 'ts-jest/presets/index.js'
/** @type {import('ts-jest').JestConfigWithTsJest} */
export default {
...preset.defaults,
transform: {
'^.+\\.(ts|tsx)$': [
'ts-jest',
{
tsconfig: 'tsconfig.jest.json',
useESM: true,
},
],
},
}
@@ -1,74 +0,0 @@
{
"name": "@nymproject/node-tester",
"version": "1.3.1",
"description": "This package provides a tester that can send test packets to mixnode that is part of the Nym Mixnet.",
"license": "Apache-2.0",
"author": "Nym Technologies SA",
"files": [
"dist/esm/worker.js",
"dist/cjs/worker.js",
"dist/**/*"
],
"main": "dist/cjs/index.js",
"browser": "dist/esm/index.js",
"scripts": {
"build": "scripts/build-prod.sh",
"build:dev": "scripts/build.sh",
"build:dev:esm": "scripts/build-dev-esm.sh",
"build:worker": "rollup -c rollup-worker.config.mjs",
"clean": "rimraf dist",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"start": "tsc -w",
"start:dev": "nodemon --watch src -e ts,json --exec 'yarn build:dev:esm'",
"test": "node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js -c=jest.config.mjs --no-cache",
"tsc": "tsc --noEmit true"
},
"dependencies": {
"@nymproject/nym-node-tester-wasm": ">=1.3.1-rc.0 || ^1",
"comlink": "^4.3.1"
},
"devDependencies": {
"@babel/core": "^7.15.0",
"@babel/plugin-transform-async-to-generator": "^7.14.5",
"@babel/preset-env": "^7.15.0",
"@babel/preset-react": "^7.14.5",
"@babel/preset-typescript": "^7.15.0",
"@nymproject/eslint-config-react-typescript": "^1.0.0",
"@rollup/plugin-commonjs": "^24.0.1",
"@rollup/plugin-inject": "^5.0.3",
"@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-replace": "^5.0.2",
"@rollup/plugin-terser": "^0.2.1",
"@rollup/plugin-typescript": "^10.0.1",
"@rollup/plugin-wasm": "^6.1.1",
"@types/jest": "^27.0.1",
"@types/node": "^16.7.13",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"eslint": "^8.10.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.29.2",
"eslint-plugin-react-hooks": "^4.3.0",
"jest": "^29.5.0",
"nodemon": "^2.0.21",
"rimraf": "^3.0.2",
"rollup": "^3.9.1",
"rollup-plugin-base64": "^1.0.1",
"rollup-plugin-web-worker-loader": "^1.6.1",
"ts-jest": "^29.1.0",
"ts-loader": "^9.4.2",
"typescript": "^4.8.4"
},
"private": false,
"type": "module",
"types": "./dist/esm/index.d.ts"
}
@@ -1,8 +0,0 @@
import { getConfig } from './rollup/cjs.mjs';
export default {
...getConfig({
inline: true,
outputDir: 'dist/cjs-full-fat',
}),
};
@@ -1,5 +0,0 @@
import { getConfig } from './rollup/cjs.mjs';
export default {
...getConfig({ inline: false }),
};
@@ -1,8 +0,0 @@
import { getConfig } from './rollup/esm.mjs';
export default {
...getConfig({
inline: true,
outputDir: 'dist/esm-full-fat',
}),
};
@@ -1,8 +0,0 @@
import { getConfig } from './rollup/esm.mjs';
export default {
...getConfig({
// by default, the web worker will not be inlined, in local development mode it will be
inline: process.env.MIX_FETCH_DEV_MODE === 'true',
}),
};
@@ -1,28 +0,0 @@
import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';
import { wasm } from '@rollup/plugin-wasm';
import replace from '@rollup/plugin-replace';
const extensions = [
'.js', '.jsx', '.ts', '.tsx',
];
export default {
input: 'src/worker.ts',
output: {
dir: 'dist',
format: 'cjs',
},
plugins: [
resolve({ extensions }),
// this is some nasty monkey patching that removes the WASM URL (because it is handled by the `wasm` plugin)
replace({
values: { 'input = new URL(\'mix_fetch_wasm_bg.wasm\', import.meta.url);': 'input = undefined;' },
delimiters: ['', ''],
preventAssignment: true,
}),
// force the wasm plugin to embed the wasm bundle - this means no downstream bundlers have to worry about handling it
wasm({ maxFileSize: 10000000, targetEnv: 'browser' }),
typescript({ compilerOptions: { declaration: false, target: 'es5' } }),
],
};
@@ -1,30 +0,0 @@
import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';
import { wasm } from '@rollup/plugin-wasm';
import webWorkerLoader from 'rollup-plugin-web-worker-loader';
const extensions = ['.js', '.jsx', '.ts', '.tsx'];
/**
* Gets the config for bundling the package as a CommonJS module.
*
* @param opts Options:
* `{ inline: boolean }` - set inline to true to inline the web worker in the main bundle
* `{ outputDir: string }` - override the destination
*/
export const getConfig = (opts) => ({
input: 'src/index.ts',
output: {
dir: opts.outputDir || 'dist/cjs',
format: 'cjs',
},
plugins: [
webWorkerLoader({ targetPlatform: 'browser', inline: opts.inline }), // the inline param is used here
resolve({ extensions }),
wasm({ maxFileSize: 10000000, targetEnv: 'browser' }),
typescript({
compilerOptions: { outDir: opts.outputDir || 'dist/cjs', target: 'es5' },
exclude: ['worker.ts'],
}),
],
});
@@ -1,28 +0,0 @@
import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';
import webWorkerLoader from 'rollup-plugin-web-worker-loader';
const extensions = ['.js', '.jsx', '.ts', '.tsx'];
/**
* Gets the config for bundling the package as an ES Module.
*
* @param opts Options:
* `{ inline: boolean }` - set inline to true to inline the web worker in the main bundle
* `{ outputDir: string }` - override the destination *
*/
export const getConfig = (opts) => ({
input: 'src/index.ts',
output: {
dir: opts.outputDir || 'dist/esm',
format: 'es',
},
plugins: [
webWorkerLoader({ targetPlatform: 'browser', inline: opts.inline }), // the inline param is used here
resolve({ extensions }),
typescript({
exclude: ['worker.ts'],
compilerOptions: { outDir: opts.outputDir || 'dist/esm' },
}),
],
});
@@ -1,33 +0,0 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
#-------------------------------------------------------
# WEB WORKER (node-tester WASM)
#-------------------------------------------------------
# The web worker needs to be bundled because the WASM bundle needs to be loaded synchronously and all dependencies
# must be included in the worker script (because it is not loaded as an ES Module)
# build the worker
rollup -c rollup-worker.config.mjs
# move it next to the Typescript `src/index.ts` so it can be inlined by rollup
cp dist/worker.js src/worker.js
rm dist/worker.js
#-------------------------------------------------------
# ESM
#-------------------------------------------------------
# build the SDK as a ESM bundle
rollup -c rollup-esm.config.mjs
#-------------------------------------------------------
# CLEAN UP
#-------------------------------------------------------
rm -rf dist/esm/worker
@@ -1,20 +0,0 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
rm -rf dist || true
rm -rf ../../../../dist/ts/sdk/node-tester || true
# run the build
scripts/build.sh
node scripts/buildPackageJson.mjs
# move the output outside of the yarn/npm workspaces
mkdir -p ../../../../dist/ts/sdk
mv dist ../../../../dist/ts/sdk
mv ../../../../dist/ts/sdk/dist ../../../../dist/ts/sdk/node-tester
echo "Output can be found in:"
realpath ../../../../dist/ts/sdk/node-tester
@@ -1,69 +0,0 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
rm -rf dist || true
#-------------------------------------------------------
# WEB WORKER (mix-fetch WASM)
#-------------------------------------------------------
# The web worker needs to be bundled because the WASM bundle needs to be loaded synchronously and all dependencies
# must be included in the worker script (because it is not loaded as an ES Module)
# build the worker
rollup -c rollup-worker.config.mjs
# move it next to the Typescript `src/index.ts` so it can be inlined by rollup
rm -f src/worker.js
mv dist/worker.js src/worker.js
#-------------------------------------------------------
# ESM
#-------------------------------------------------------
# build the SDK as a ESM bundle
rollup -c rollup-esm.config.mjs
#-------------------------------------------------------
# COMMON JS
#-------------------------------------------------------
# Some old build systems cannot fully handle ESM or ES2021, so build
# a CommonJS bundle targeting ES5
# build the SDK as a CommonJS bundle
rollup -c rollup-cjs.config.mjs
#-------------------------------------------------------
# ESM (full-fat)
#-------------------------------------------------------
# build the SDK as a ESM bundle (with worker inlined as a blob)
rollup -c rollup-esm-full-fat.config.mjs
#-------------------------------------------------------
# COMMON JS (full-fat)
#-------------------------------------------------------
# Some old build systems cannot fully handle ESM or ES2021, so build
# a CommonJS bundle targeting ES5
# build the SDK as a CommonJS bundle (with worker inlined as a blob)
rollup -c rollup-cjs-full-fat.config.mjs
#-------------------------------------------------------
# CLEAN UP
#-------------------------------------------------------
rm -rf dist/cjs/worker
rm -rf dist/esm/worker
rm -rf dist/cjs-full-fat/worker
rm -rf dist/esm-full-fat/worker
# copy README
cp README.md dist/esm
cp README-CommonJS.md dist/cjs/README.md
cp README-CommonJS-full-fat.md dist/cjs-full-fat/README.md
cp README-full-fat.md dist/esm-full-fat/README.md
@@ -1,29 +0,0 @@
import * as fs from 'fs';
// parse the package.json from the SDK, so we can keep fields like the name and version
const json = JSON.parse(fs.readFileSync('package.json').toString());
// defaults (NB: these are in the output file locations)
const browser = 'index.js';
const main = 'index.js';
const types = 'index.d.ts';
const getPackageJson = (type, suffix) => ({
name: `${json.name}${suffix ? `-${suffix}` : ''}`,
version: json.version,
license: json.license,
author: json.author,
type,
browser,
main,
types,
});
fs.writeFileSync('dist/cjs/package.json', JSON.stringify(getPackageJson('commonjs', 'commonjs'), null, 2));
fs.writeFileSync('dist/esm/package.json', JSON.stringify(getPackageJson('module'), null, 2));
fs.writeFileSync(
'dist/cjs-full-fat/package.json',
JSON.stringify(getPackageJson('commonjs', 'commonjs-full-fat'), null, 2),
);
fs.writeFileSync('dist/esm-full-fat/package.json', JSON.stringify(getPackageJson('module', 'full-fat'), null, 2));
@@ -1,19 +0,0 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
yarn
yarn build
cd ../../../../dist/ts/sdk/node-tester
cd cjs
echo "Publishing CommonJS package to NPM.."
npm publish --access=public
cd ..
cd esm
echo "Publishing ESM package to NPM.."
npm publish --access=public
cd ..
@@ -1,52 +0,0 @@
import InlineWasmWebWorker from 'web-worker:./worker';
import * as Comlink from 'comlink';
import { INodeTesterWorkerAsync, NodeTester, NodeTesterEventKinds } from './types';
/**
* Client for the Nym node tester.
*/
export const createNodeTesterClient = async (): Promise<NodeTester> => {
// eslint-disable-next-line @typescript-eslint/no-use-before-define
const worker = await createWorker();
// let comlink handle interop with the web worker
const tester = Comlink.wrap<INodeTesterWorkerAsync>(worker);
// expose the method to terminate the worker
const terminate = async () => {
worker.terminate();
};
return { tester, terminate };
};
/**
* Async method to create a web worker that runs the Nym node tester client on another thread. It will only return once the worker
* has passed back a `Loaded` event to the calling thread.
*
* @return The instance of the web worker.
*/
const createWorker = async () =>
new Promise<Worker>((resolve, reject) => {
// rollup will inline the built worker script, so that when the SDK is used in
// other projects, they will not need to mess around trying to bundle it
// however, it will make this SDK bundle bigger because of Base64 inline data
const worker = new InlineWasmWebWorker();
worker.addEventListener('error', reject);
worker.addEventListener(
'message',
(msg) => {
worker.removeEventListener('error', reject);
if (msg.data?.kind === NodeTesterEventKinds.Loaded) {
resolve(worker);
} else {
reject(msg);
}
},
{ once: true },
);
});
export * from './types';
@@ -1,35 +0,0 @@
export interface INodeTesterWorkerAsync {
init: (validatorUrl: string, nodeTesterId?: string) => Promise<void>;
reconnectToGateway: () => Promise<void>;
disconnectFromGateway: () => Promise<void>;
startTest: (mixnodeIdentityKey: string) => Promise<NodeTestResultResponse | undefined>;
}
export interface INodeTesterWorkerDisposableAsync {
terminate: () => Promise<void>;
}
export interface NodeTester extends INodeTesterWorkerDisposableAsync {
tester: INodeTesterWorkerAsync;
}
export enum NodeTesterEventKinds {
Loaded = 'Loaded',
Connected = 'Connected',
}
export interface NodeTesterLoadedEvent {
kind: NodeTesterEventKinds.Loaded;
args: {
loaded: true;
};
}
export type NodeTestResultResponse = {
score: number;
sentPackets: number;
receivedPackets: number;
receivedAcks: number;
duplicatePackets: number;
duplicateAcks: number;
};
File diff suppressed because one or more lines are too long
@@ -1,103 +0,0 @@
// Copyright 2020-2023 Nym Technologies SA
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import * as Comlink from 'comlink';
//
// Rollup will replace wasmBytes with a function that loads the WASM bundle from a base64 string embedded in the output.
//
// Doing it this way, saves having to support a large variety of bundlers and their quirks.
//
// @ts-ignore
// eslint-disable-next-line import/no-extraneous-dependencies
import wasmBytes from '@nymproject/nym-node-tester-wasm/nym_node_tester_wasm_bg.wasm';
/* eslint-disable no-restricted-globals */
import init, { NymNodeTester, NodeTestResult } from '@nymproject/nym-node-tester-wasm/nym_node_tester_wasm';
import type { INodeTesterWorkerAsync, NodeTesterLoadedEvent } from './types';
import { NodeTesterEventKinds } from './types';
/**
* Helper method to send typed messages.
* @param event The strongly typed message to send back to the calling thread.
*/
// eslint-disable-next-line no-restricted-globals
const postMessageWithType = <E>(event: E) => self.postMessage(event);
console.log('[Nym WASM client] Starting Nym WASM web worker...');
const buildTester = async (validatorUrl: string, nodeTesterId?: string): Promise<NymNodeTester> =>
new NymNodeTester({ nymApi: validatorUrl, id: nodeTesterId });
async function main() {
const importResult = await init(wasmBytes());
importResult.set_panic_hook();
let nodeTester: NymNodeTester | null = null;
const webWorker: INodeTesterWorkerAsync = {
async init(validatorUrl: string, nodeTesterId?: string) {
nodeTester = await buildTester(validatorUrl, nodeTesterId);
},
async reconnectToGateway() {
if (!nodeTester) {
throw Error('Please run init first');
}
await nodeTester.reconnect_to_gateway();
},
async disconnectFromGateway() {
if (!nodeTester) {
throw Error('Please run init first');
}
await nodeTester.disconnect_from_gateway();
},
async startTest(mixnodeIdentityKey: string) {
if (!nodeTester) {
throw Error('Please run init first');
}
console.log(`Testing mixnode with identity key = ${mixnodeIdentityKey}`);
// TODO: fix typing in Rust code
const result = (await nodeTester.test_node(mixnodeIdentityKey)) as NodeTestResult | undefined;
// return early if there was an error
if (!result) {
return result;
}
// log the result in the worker so that the packet stats are visible somewhere and extract the score
result.log_details();
// eslint-disable-next-line @typescript-eslint/naming-convention
const { duplicate_acks, duplicate_packets, received_acks, received_packets, sent_packets } = result;
// construct the response to avoid any weird proxy effects
return {
score: result.score(),
sentPackets: sent_packets,
receivedPackets: received_packets,
receivedAcks: received_acks,
duplicatePackets: duplicate_packets,
duplicateAcks: duplicate_acks,
};
},
};
// start comlink listening for messages and handle them above
Comlink.expose(webWorker);
// notify any listeners that the web worker has loaded and is ready for testing
postMessageWithType<NodeTesterLoadedEvent>({ kind: NodeTesterEventKinds.Loaded, args: { loaded: true } });
}
main();
@@ -1,43 +0,0 @@
{
"compileOnSave": false,
"compilerOptions": {
"lib": [
"es2021",
"dom",
"dom.iterable",
"esnext",
"webworker"
],
"module": "CommonJS",
"target": "es5",
"strict": true,
"moduleResolution": "node",
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"declaration": true,
"baseUrl": ".",
"esModuleInterop": true,
"allowJs": true,
"downlevelIteration": true
},
"include": [
"src/**/*.ts"
],
"exclude": [
"jest.*",
"webpack.config.js",
"webpack.prod.js",
"webpack.common.js",
"node_modules",
"**/node_modules",
"dist",
"**/dist",
"scripts",
"jest",
"__tests__",
"**/__tests__",
"__jest__",
"**/__jest__",
"config/*"
]
}
@@ -1,45 +0,0 @@
{
"compileOnSave": false,
"compilerOptions": {
"lib": [
"es2021",
"dom",
"dom.iterable",
"esnext",
"webworker"
],
"outDir": "./dist/",
"module": "esnext",
"target": "esnext",
"allowJs": false,
"strict": true,
"moduleResolution": "node",
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"declaration": true,
"baseUrl": ".",
"downlevelIteration": true
},
"include": [
"src/**/*.ts",
"src/*.ts",
"typings"
],
"exclude": [
"jest.config.js",
"webpack.config.js",
"webpack.prod.js",
"webpack.common.js",
"node_modules",
"**/node_modules",
"dist",
"**/dist",
"scripts",
"jest",
"__tests__",
"**/__tests__",
"__jest__",
"**/__jest__",
"config/*",
]
}
@@ -1,4 +0,0 @@
declare module 'web-worker:*' {
const WorkerFactory: new () => Worker;
export default WorkerFactory;
}
@@ -17,11 +17,11 @@
"docs:generate:prod": "typedoc --basePath ./docs/tsdoc/nymproject/sdk/",
"docs:prod:build": "scripts/build-prod-docs-collect.sh",
"docs:serve": "reload -b -d ./docs -p 3000",
"docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"yarn docs:generate\"",
"docs:watch": "nodemon --ext ts --watch './src/**/*' --watch './typedoc.json' --exec \"pnpm docs:generate\"",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
"start": "tsc -w",
"start:dev": "nodemon --watch src -e ts,json --exec 'yarn build:dev:esm'",
"start:dev": "nodemon --watch src -e ts,json --exec 'pnpm build:dev:esm'",
"tsc": "tsc --noEmit true"
},
"dependencies": {
@@ -40,27 +40,29 @@
"@rollup/plugin-url": "^8.0.1",
"@rollup/plugin-wasm": "^6.1.1",
"@types/node": "^16.7.13",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"@types/ws": "catalog:",
"@typescript-eslint/eslint-plugin": "catalog:",
"@typescript-eslint/parser": "catalog:",
"eslint": "^8.10.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.29.2",
"eslint-plugin-react-hooks": "^4.3.0",
"eslint-config-airbnb": "catalog:",
"eslint-config-airbnb-typescript": "catalog:",
"eslint-config-prettier": "catalog:",
"eslint-import-resolver-root-import": "catalog:",
"eslint-plugin-import": "catalog:",
"eslint-plugin-jest": "catalog:",
"eslint-plugin-jsx-a11y": "catalog:",
"eslint-plugin-prettier": "catalog:",
"eslint-plugin-react": "catalog:",
"eslint-plugin-react-hooks": "catalog:",
"nodemon": "3.0.1",
"reload": "^3.2.1",
"rimraf": "^3.0.2",
"rimraf": "catalog:",
"rollup": "^3.9.1",
"rollup-plugin-base64": "^1.0.1",
"rollup-plugin-modify": "^3.0.0",
"rollup-plugin-web-worker-loader": "^1.6.1",
"ts-loader": "^9.4.2",
"ts-loader": "catalog:",
"tslib": "catalog:",
"typedoc": "^0.24.8",
"typescript": "^4.8.4"
},
@@ -7,7 +7,7 @@ set -o pipefail
rm -rf ../../../../dist/ts/docs/tsdoc/nymproject/sdk || true
# run the build
yarn docs:generate:prod
pnpm docs:generate:prod
# move the output outside of the yarn/npm workspaces
mkdir -p ../../../../dist/ts/docs/tsdoc/nymproject
@@ -29,57 +29,59 @@
"@mui/material": "5",
"@mui/styles": "5",
"@mui/system": "5",
"@nymproject/mui-theme": "1",
"@nymproject/mui-theme": "workspace:*",
"@nymproject/nym-validator-client": "^0.18.0",
"@nymproject/types": "1",
"base58": "4",
"@nymproject/types": "workspace:*",
"base58": "2",
"bech32": "^1.1.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "catalog:",
"react-dom": "catalog:",
"zxcvbn": "^4.4.2"
},
"dependencies": {
"@mui/lab": "5.0.0-alpha.170",
"@mui/x-tree-view": "^7.11.1",
"flat": "^5.0.2",
"use-clipboard-copy": "^0.2.0"
"@mui/lab": "catalog:",
"@mui/x-tree-view": "catalog:",
"flat": "catalog:",
"use-clipboard-copy": "catalog:"
},
"devDependencies": {
"@babel/core": "^7.17.5",
"@nymproject/eslint-config-react-typescript": "^1.0.0",
"@storybook/addon-actions": "^6.5.8",
"@storybook/addon-essentials": "^6.5.8",
"@storybook/addon-interactions": "^6.5.8",
"@storybook/addon-links": "^6.5.8",
"@storybook/builder-webpack5": "^6.5.8",
"@storybook/manager-webpack5": "^6.5.8",
"@storybook/react": "^6.5.15",
"@storybook/testing-library": "^0.0.9",
"@svgr/webpack": "^6.1.1",
"@types/flat": "^5.0.2",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.10",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"babel-loader": "^8.2.3",
"@babel/core": "catalog:",
"@nymproject/eslint-config-react-typescript": "workspace:*",
"@storybook/addon-actions": "catalog:",
"@storybook/addon-docs": "catalog:",
"@storybook/addon-essentials": "catalog:",
"@storybook/addon-interactions": "catalog:",
"@storybook/addon-links": "catalog:",
"@storybook/builder-webpack5": "catalog:",
"@storybook/manager-webpack5": "catalog:",
"@storybook/react": "catalog:",
"@storybook/testing-library": "catalog:",
"@svgr/webpack": "catalog:",
"@types/flat": "catalog:",
"@types/zxcvbn": "catalog:",
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
"@typescript-eslint/eslint-plugin": "catalog:",
"@typescript-eslint/parser": "catalog:",
"babel-loader": "catalog:",
"babel-plugin-root-import": "^5.1.0",
"eslint": "^9.26.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.29.2",
"eslint-plugin-react-hooks": "^4.3.0",
"eslint-plugin-storybook": "^0.5.12",
"jest": "^27.1.0",
"prettier": "^2.8.7",
"rimraf": "^3.0.2",
"ts-jest": "^27.0.5",
"tsconfig-paths-webpack-plugin": "^3.5.2",
"eslint": "catalog:",
"eslint-config-airbnb": "catalog:",
"eslint-config-airbnb-typescript": "catalog:",
"eslint-config-prettier": "catalog:",
"eslint-import-resolver-root-import": "catalog:",
"eslint-plugin-import": "catalog:",
"eslint-plugin-jest": "catalog:",
"eslint-plugin-jsx-a11y": "catalog:",
"eslint-plugin-prettier": "catalog:",
"eslint-plugin-react": "catalog:",
"eslint-plugin-react-hooks": "catalog:",
"eslint-plugin-storybook": "catalog:",
"jest": "catalog:",
"prettier": "catalog:",
"rimraf": "catalog:",
"ts-jest": "catalog:",
"tsconfig-paths-webpack-plugin": "catalog:",
"typescript": "^4.6.2"
},
"scripts": {
+35 -35
View File
@@ -23,46 +23,46 @@
"@nymproject/sdk": ">=1.4.1-rc.3 || ^1"
},
"devDependencies": {
"@babel/core": "^7.17.5",
"@nymproject/eslint-config-react-typescript": "^1.0.0",
"@storybook/addon-actions": "^6.5.8",
"@storybook/addon-essentials": "^6.5.8",
"@storybook/addon-interactions": "^6.5.8",
"@storybook/addon-links": "^6.5.8",
"@storybook/builder-webpack5": "^6.5.8",
"@storybook/manager-webpack5": "^6.5.8",
"@storybook/react": "^6.5.15",
"@storybook/testing-library": "^0.0.9",
"@svgr/webpack": "^6.1.1",
"@types/flat": "^5.0.2",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.10",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"babel-loader": "^8.2.3",
"@babel/core": "catalog:",
"@nymproject/eslint-config-react-typescript": "workspace:*",
"@storybook/addon-actions": "catalog:",
"@storybook/addon-essentials": "catalog:",
"@storybook/addon-interactions": "catalog:",
"@storybook/addon-links": "catalog:",
"@storybook/builder-webpack5": "catalog:",
"@storybook/manager-webpack5": "catalog:",
"@storybook/react": "catalog:",
"@storybook/testing-library": "catalog:",
"@svgr/webpack": "catalog:",
"@types/flat": "catalog:",
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
"@typescript-eslint/eslint-plugin": "catalog:",
"@typescript-eslint/parser": "catalog:",
"babel-loader": "catalog:",
"babel-plugin-root-import": "^5.1.0",
"eslint": "^8.10.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^16.1.0",
"eslint-config-prettier": "^8.5.0",
"eslint-import-resolver-root-import": "^1.0.4",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-jest": "^26.1.1",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.29.2",
"eslint-plugin-react-hooks": "^4.3.0",
"eslint-plugin-storybook": "^0.5.12",
"jest": "^27.1.0",
"prettier": "^2.8.7",
"rimraf": "^3.0.2",
"ts-jest": "^27.0.5",
"tsconfig-paths-webpack-plugin": "^3.5.2",
"eslint-config-airbnb": "catalog:",
"eslint-config-airbnb-typescript": "catalog:",
"eslint-config-prettier": "catalog:",
"eslint-import-resolver-root-import": "catalog:",
"eslint-plugin-import": "catalog:",
"eslint-plugin-jest": "catalog:",
"eslint-plugin-jsx-a11y": "catalog:",
"eslint-plugin-prettier": "catalog:",
"eslint-plugin-react": "catalog:",
"eslint-plugin-react-hooks": "catalog:",
"eslint-plugin-storybook": "catalog:",
"jest": "catalog:",
"prettier": "catalog:",
"rimraf": "catalog:",
"ts-jest": "catalog:",
"tsconfig-paths-webpack-plugin": "catalog:",
"typescript": "^4.6.2"
},
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react": "catalog:",
"react-dom": "catalog:"
},
"private": false,
"type": "module",
+10 -10
View File
@@ -14,17 +14,17 @@ The SDK depends on WASM packages that must be built from Rust first.
From the **root of the monorepo**:
```bash
yarn dev:on # add dev workspaces to root package.json
yarn # install dependencies
yarn build:wasm # build Rust -> WASM packages
pnpm dev:on # add dev workspaces to root package.json
pnpm i # install dependencies
pnpm build:wasm # build Rust -> WASM packages
```
Then from `sdk/typescript/packages/sdk`:
```bash
yarn build:dev # full dev build -> dist/
yarn build:dev:esm # ESM-only (faster iteration)
yarn start:dev # watch mode, rebuilds ESM on changes
pnpm build:dev # full dev build -> dist/
pnpm build:dev:esm # ESM-only (faster iteration)
pnpm start:dev # watch mode, rebuilds ESM on changes
```
## Local mixFetch development
@@ -45,14 +45,14 @@ The `publish-sdk-npm` GitHub Actions workflow (`.github/workflows/publish-sdk-np
1. Bump versions, commit, and push:
```bash
yarn sdk:versions:bump
pnpm sdk:versions:bump
git add -A && git commit -m "chore: bump sdk versions"
git push
```
2. Trigger the `publish-sdk-npm` workflow from GitHub Actions.
3. After the workflow succeeds, add the RC suffix, commit, and push:
```bash
yarn sdk:versions:add-rc
pnpm sdk:versions:add-rc
git add -A && git commit -m "chore: add rc suffix"
git push
```
@@ -65,7 +65,7 @@ The `publish-sdk-npm` GitHub Actions workflow (`.github/workflows/publish-sdk-np
```
2. Bump version numbers:
```bash
yarn sdk:versions:bump
pnpm sdk:versions:bump
```
3. Build and publish:
```bash
@@ -73,5 +73,5 @@ The `publish-sdk-npm` GitHub Actions workflow (`.github/workflows/publish-sdk-np
```
4. Add RC suffix and commit:
```bash
yarn sdk:versions:add-rc
pnpm sdk:versions:add-rc
```
@@ -1,17 +1,17 @@
## Install dependencies
run `yarn install` to install dependencies
run `pnpm i` to install dependencies
## Generate docs
We use TypeDoc for document generation https://typedoc.org/
To generate docs run `yarn docs:generate`. Generated docs can be found the `./docs` directory.
To generate docs run `pnpm docs:generate`. Generated docs can be found the `./docs` directory.
To view the generated docs in a webpage run `yarn docs:serve`. The docs will be available to view at `http://localhost:3000`.
To view the generated docs in a webpage run `pnpm docs:serve`. The docs will be available to view at `http://localhost:3000`.
## Local document development
To support the development process we have a local server that will watch for changes to the src files and update the docs in real time.
Run `yarn docs:dev` to start a local server to view the docs. Again, The docs will be available to view at `http://localhost:3000`.
Run `pnpm docs:dev` to start a local server to view the docs. Again, The docs will be available to view at `http://localhost:3000`.

Some files were not shown because too many files have changed in this diff Show More