diff --git a/.github/workflows/typescript-lint.yml b/.github/workflows/typescript-lint.yml
index 829ffb22e9..dcaa905f5d 100644
--- a/.github/workflows/typescript-lint.yml
+++ b/.github/workflows/typescript-lint.yml
@@ -3,64 +3,70 @@ name: CI for linting Typescript
on:
push:
paths:
- - 'ts-packages/**'
- - 'sdk/typescript/**'
- - 'nym-connect/desktop/src/**'
- - 'nym-connect/desktop/package.json'
- - 'nym-connect/mobile/src/**'
- - 'nym-connect/mobile/package.json'
- - 'nym-wallet/src/**'
- - 'nym-wallet/package.json'
- - 'explorer/**'
+ - "ts-packages/**"
+ - "sdk/typescript/**"
+ - "nym-connect/desktop/src/**"
+ - "nym-connect/desktop/package.json"
+ - "nym-connect/mobile/src/**"
+ - "nym-connect/mobile/package.json"
+ - "nym-wallet/src/**"
+ - "nym-wallet/package.json"
+ - "explorer/**"
pull_request:
paths:
- - 'ts-packages/**'
- - 'sdk/typescript/**'
- - 'nym-connect/desktop/src/**'
- - 'nym-connect/desktop/package.json'
- - 'nym-connect/mobile/src/**'
- - 'nym-connect/mobile/package.json'
- - 'nym-wallet/src/**'
- - 'nym-wallet/package.json'
- - 'explorer/**'
+ - "ts-packages/**"
+ - "sdk/typescript/**"
+ - "nym-connect/desktop/src/**"
+ - "nym-connect/desktop/package.json"
+ - "nym-connect/mobile/src/**"
+ - "nym-connect/mobile/package.json"
+ - "nym-wallet/src/**"
+ - "nym-wallet/package.json"
+ - "explorer/**"
jobs:
build:
runs-on: custom-runner-linux
steps:
- - uses: actions/checkout@v2
- - name: Install rsync
- run: sudo apt-get install rsync
- continue-on-error: true
- - uses: rlespinasse/github-slug-action@v3.x
- - uses: actions/setup-node@v3
- with:
- node-version: 18
- - name: Setup yarn
- run: npm install -g yarn
- - name: Install
- run: yarn
- - name: Build packages
- run: yarn build
- - name: Lint
- run: yarn lint && yarn tsc
- - name: Matrix - Node Install
- run: npm install
- working-directory: .github/workflows/support-files
- - name: Matrix - Send Notification
- env:
- NYM_NOTIFICATION_KIND: ts-packages
- NYM_PROJECT_NAME: "ts-packages"
- NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
- NYM_CI_WWW_LOCATION: "ts-${{ env.GITHUB_REF_SLUG }}"
- GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
- GIT_BRANCH: "${GITHUB_REF##*/}"
- IS_SUCCESS: "${{ job.status == 'success' }}"
- MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
- MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
- MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
- MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
- MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
- uses: docker://keybaseio/client:stable-node
- with:
- args: .github/workflows/support-files/notifications/entry_point.sh
+ - uses: actions/checkout@v2
+ - name: Install rsync
+ run: sudo apt-get install rsync
+ continue-on-error: true
+ - uses: rlespinasse/github-slug-action@v3.x
+ - uses: actions/setup-node@v3
+ with:
+ node-version: 18
+ - name: Install Rust stable
+ uses: actions-rs/toolchain@v1
+ with:
+ toolchain: stable
+ - name: Install wasm-pack
+ run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
+ - name: Setup yarn
+ run: npm install -g yarn
+ - name: Install
+ run: yarn
+ - name: Build packages
+ run: yarn build
+ - name: Lint
+ run: yarn lint && yarn tsc
+ - name: Matrix - Node Install
+ run: npm install
+ working-directory: .github/workflows/support-files
+ - name: Matrix - Send Notification
+ env:
+ NYM_NOTIFICATION_KIND: ts-packages
+ NYM_PROJECT_NAME: "ts-packages"
+ NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
+ NYM_CI_WWW_LOCATION: "ts-${{ env.GITHUB_REF_SLUG }}"
+ GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
+ GIT_BRANCH: "${GITHUB_REF##*/}"
+ IS_SUCCESS: "${{ job.status == 'success' }}"
+ MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
+ MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
+ MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
+ MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
+ MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
+ uses: docker://keybaseio/client:stable-node
+ with:
+ args: .github/workflows/support-files/notifications/entry_point.sh
diff --git a/Cargo.toml b/Cargo.toml
index 9b2a13c7ef..4f0e80d599 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -102,7 +102,7 @@ default-members = [
"explorer-api",
]
-exclude = ["explorer", "contracts", "clients/webassembly", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "cpu-cycles"]
+exclude = ["explorer", "contracts", "clients/webassembly", "nym-wallet", "nym-connect/mobile/src-tauri", "nym-connect/desktop", "nym-browser-extension/storage", "cpu-cycles"]
[workspace.package]
authors = ["Nym Technologies SA"]
diff --git a/assets/logo/logo-bw.svg b/assets/logo/logo-bw.svg
new file mode 100644
index 0000000000..42b752d8d0
--- /dev/null
+++ b/assets/logo/logo-bw.svg
@@ -0,0 +1,53 @@
+
diff --git a/clients/validator/package.json b/clients/validator/package.json
index 8887605fe7..386a94fe23 100644
--- a/clients/validator/package.json
+++ b/clients/validator/package.json
@@ -3,11 +3,11 @@
"version": "0.19.0",
"description": "A TypeScript client for interacting with smart contracts in Nym validators",
"repository": "https://github.com/nymtech/nym",
- "main": "./dist/index.js",
- "types": "./dist/index.d.ts",
+ "main": "dist/index.js",
+ "types": "dist/index.d.ts",
"scripts": {
"build": "rollup -c ./rollup.config.mjs",
- "build:types": "rollup-type-bundler --dist ./dist/nym-validator-client",
+ "build:types": "rollup-type-bundler --dist ./dist",
"build:prod": "sh ./scripts/build-prod.sh",
"test": "ts-mocha -p ./tsconfig.test.json ./src/tests/**/*.test.ts",
"testmock": "ts-mocha -p ./tsconfig.test.json ./src/tests/mock/*.test.ts",
@@ -29,16 +29,23 @@
],
"license": "Apache-2.0",
"devDependencies": {
+ "@cosmjs/cosmwasm-stargate": "^0.29.5",
+ "@cosmjs/crypto": "^0.29.5",
+ "@cosmjs/math": "^0.29.5",
+ "@cosmjs/proto-signing": "^0.29.5",
+ "@cosmjs/stargate": "^0.29.5",
+ "@cosmjs/tendermint-rpc": "^0.29.5",
"@favware/rollup-type-bundler": "^2.0.0",
"@nymproject/types": "^1.0.0",
"@rollup/plugin-commonjs": "^24.0.1",
"@rollup/plugin-json": "^6.0.0",
- "@rollup/plugin-typescript": "^11.0.0",
"@rollup/plugin-node-resolve": "^15.0.1",
- "rollup": "^3.17.2",
- "rollup-plugin-dts": "^5.2.0",
+ "@rollup/plugin-typescript": "^11.0.0",
"@typescript-eslint/eslint-plugin": "^5.7.0",
"@typescript-eslint/parser": "^5.7.0",
+ "axios": "^1.3.3",
+ "cosmjs-types": "^0.4.1",
+ "dotenv": "^16.0.3",
"eslint": "^7.18.0",
"eslint-config-airbnb": "^19.0.2",
"eslint-config-airbnb-typescript": "^16.1.0",
@@ -47,21 +54,15 @@
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-mocha": "^10.0.3",
"eslint-plugin-prettier": "^4.0.0",
+ "expect": "^28.1.3",
"mocha": "^10.0.0",
+ "moq.ts": "^7.3.4",
"prettier": "^2.8.7",
+ "rollup": "^3.17.2",
+ "rollup-plugin-dts": "^5.2.0",
+ "rollup-plugin-node-polyfills": "^0.2.1",
"ts-mocha": "^10.0.0",
"typedoc": "^0.22.13",
- "typescript": "^4.6.2",
- "cosmjs-types": "^0.4.1",
- "dotenv": "^16.0.3",
- "expect": "^28.1.3",
- "moq.ts": "^7.3.4",
- "@cosmjs/cosmwasm-stargate": "^0.29.5",
- "@cosmjs/crypto": "^0.29.5",
- "@cosmjs/math": "^0.29.5",
- "@cosmjs/proto-signing": "^0.29.5",
- "@cosmjs/stargate": "^0.29.5",
- "@cosmjs/tendermint-rpc": "^0.29.5",
- "axios": "^1.3.3"
+ "typescript": "^4.6.2"
}
}
diff --git a/clients/validator/rollup.config.mjs b/clients/validator/rollup.config.mjs
index f78cf449cf..e97c06bee2 100644
--- a/clients/validator/rollup.config.mjs
+++ b/clients/validator/rollup.config.mjs
@@ -1,15 +1,15 @@
import typescript from '@rollup/plugin-typescript';
-import resolve from '@rollup/plugin-node-resolve';
+import nodePolyfills from 'rollup-plugin-node-polyfills';
import json from '@rollup/plugin-json';
import commonjs from '@rollup/plugin-commonjs';
export default [
{
- input: './src/index.ts',
+ input: 'src/index.ts',
output: {
- dir: 'dist/nym-validator-client',
+ dir: 'dist',
format: 'cjs',
},
- plugins: [resolve(), typescript(), commonjs(), json()],
+ plugins: [nodePolyfills(), typescript(), commonjs(), json()],
},
];
diff --git a/clients/validator/scripts/build-prod.sh b/clients/validator/scripts/build-prod.sh
index 06188652b0..7eb161d192 100644
--- a/clients/validator/scripts/build-prod.sh
+++ b/clients/validator/scripts/build-prod.sh
@@ -21,7 +21,7 @@ node ./scripts/buildPackageJson.mjs
# Copy README
-cp README.md dist/nym-validator-client
+cp README.md dist/
# move the output outside of the yarn/npm workspaces
diff --git a/clients/validator/scripts/buildPackageJson.mjs b/clients/validator/scripts/buildPackageJson.mjs
index da95f10e9d..6da8d289a5 100644
--- a/clients/validator/scripts/buildPackageJson.mjs
+++ b/clients/validator/scripts/buildPackageJson.mjs
@@ -17,4 +17,4 @@ const packageJson = {
types,
};
-fs.writeFileSync('./dist/nym-validator-client/package.json', JSON.stringify(packageJson, null, 2));
+fs.writeFileSync('./dist/package.json', JSON.stringify(packageJson, null, 2));
diff --git a/clients/validator/src/index.ts b/clients/validator/src/index.ts
index d09a202561..6f00d7f76a 100644
--- a/clients/validator/src/index.ts
+++ b/clients/validator/src/index.ts
@@ -45,7 +45,6 @@ import {
} from '@nymproject/types';
import QueryClient from './query-client';
import SigningClient, { ISigningClient } from './signing-client';
-// import { DelegationBlock } from './types/shared';
export interface INymClient {
readonly mixnetContract: string;
@@ -626,7 +625,17 @@ export default class ValidatorClient implements INymClient {
// SIMULATE
- public async simulateSend(signingAddress: string, from: string, to: string, amount: Coin[]) {
- return (this.client as SigningClient).simulateSend(signingAddress, from, to, amount);
+ public async simulateSend({
+ signingAddress,
+ from,
+ to,
+ amount,
+ }: {
+ signingAddress: string;
+ from: string;
+ to: string;
+ amount: Coin[];
+ }) {
+ return (this.client as ISigningClient).simulateSend(signingAddress, from, to, amount);
}
}
diff --git a/clients/validator/src/tests/simulate/simulateTx.test.ts b/clients/validator/src/tests/simulate/simulateTx.test.ts
index eefed5c8fb..cb6df7899e 100644
--- a/clients/validator/src/tests/simulate/simulateTx.test.ts
+++ b/clients/validator/src/tests/simulate/simulateTx.test.ts
@@ -22,9 +22,12 @@ describe('Simualtions', () => {
});
it('can simulate sending tokens', async () => {
- const res = await client.simulateSend(client.address, client.address, client.address, [
- { amount: '400000', denom: 'unym' },
- ]);
+ const res = await client.simulateSend({
+ signingAddress: client.address,
+ from: client.address,
+ to: client.address,
+ amount: [{ amount: '400000', denom: 'unym' }],
+ });
expect(typeof res).toBe('number');
}).timeout(10000);
diff --git a/clients/validator/tsconfig.json b/clients/validator/tsconfig.json
index 0a2ce0f074..1249657c46 100644
--- a/clients/validator/tsconfig.json
+++ b/clients/validator/tsconfig.json
@@ -1,6 +1,6 @@
{
"compilerOptions": {
- "outDir": "./dist/nym-validator-client",
+ "outDir": "dist",
"module": "ES2020",
"target": "es2021",
"allowJs": false,
diff --git a/clients/webassembly/src/error.rs b/clients/webassembly/src/error.rs
index 0526e03ed4..9cf2369994 100644
--- a/clients/webassembly/src/error.rs
+++ b/clients/webassembly/src/error.rs
@@ -1,7 +1,7 @@
// Copyright 2023 - Nym Technologies SA
// SPDX-License-Identifier: Apache-2.0
-use crate::storage::errors::ClientStorageError;
+use crate::storage::error::ClientStorageError;
use crate::topology::WasmTopologyError;
use js_sys::Promise;
use nym_client_core::config::GatewayEndpointConfig;
diff --git a/clients/webassembly/src/storage/errors.rs b/clients/webassembly/src/storage/error.rs
similarity index 100%
rename from clients/webassembly/src/storage/errors.rs
rename to clients/webassembly/src/storage/error.rs
diff --git a/clients/webassembly/src/storage/mod.rs b/clients/webassembly/src/storage/mod.rs
index d13e27e6e9..f4ab912657 100644
--- a/clients/webassembly/src/storage/mod.rs
+++ b/clients/webassembly/src/storage/mod.rs
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use crate::client::config::Config;
-use crate::storage::errors::ClientStorageError;
+use crate::storage::error::ClientStorageError;
use js_sys::Promise;
use nym_client_core::client::base_client::storage::gateway_details::PersistedGatewayDetails;
use nym_crypto::asymmetric::{encryption, identity};
@@ -15,7 +15,7 @@ use wasm_utils::storage::{IdbVersionChangeEvent, WasmStorage};
use wasm_utils::PromisableResult;
use zeroize::Zeroizing;
-pub(crate) mod errors;
+pub(crate) mod error;
pub(crate) mod traits;
const STORAGE_NAME_PREFIX: &str = "wasm-client-storage";
diff --git a/clients/webassembly/src/storage/traits.rs b/clients/webassembly/src/storage/traits.rs
index ed56dda969..f4a4c35742 100644
--- a/clients/webassembly/src/storage/traits.rs
+++ b/clients/webassembly/src/storage/traits.rs
@@ -1,7 +1,7 @@
// Copyright 2023 - Nym Technologies SA
// SPDX-License-Identifier: Apache-2.0
-use crate::storage::errors::ClientStorageError;
+use crate::storage::error::ClientStorageError;
use crate::storage::ClientStorage;
use async_trait::async_trait;
use nym_client_core::client::base_client::storage::gateway_details::{
diff --git a/common/wasm-utils/src/storage/error.rs b/common/wasm-utils/src/storage/error.rs
index 45b16a2d8e..9ead907c08 100644
--- a/common/wasm-utils/src/storage/error.rs
+++ b/common/wasm-utils/src/storage/error.rs
@@ -22,6 +22,9 @@ pub enum StorageError {
message: String,
},
+ #[error("FATAL ERROR: storage key is somehow present {count} times in the table!")]
+ DuplicateKey { count: u32 },
+
#[error("encountered issue with our storage encryption layer: {source}")]
CryptoStorageError {
#[from]
diff --git a/common/wasm-utils/src/storage/mod.rs b/common/wasm-utils/src/storage/mod.rs
index 3863c354fd..1a5b601ce6 100644
--- a/common/wasm-utils/src/storage/mod.rs
+++ b/common/wasm-utils/src/storage/mod.rs
@@ -4,6 +4,7 @@
use crate::console_log;
use crate::storage::cipher_export::StoredExportedStoreCipher;
use crate::storage::error::StorageError;
+use futures::TryFutureExt;
use indexed_db_futures::IdbDatabase;
use nym_store_cipher::{
Aes256Gcm, Algorithm, EncryptedData, KdfInfo, KeySizeUser, Params, StoreCipher, Unsigned,
@@ -87,6 +88,23 @@ impl WasmStorage {
})
}
+ pub async fn exists(db_name: &str) -> Result {
+ let db_req: OpenDbRequest = IdbDatabase::open(db_name)?;
+ let db: IdbDatabase = db_req.into_future().await?;
+
+ // if the db was already created before, at the very least cipher info store should exist,
+ // thus the iterator should return at least one value
+ let some_stores_exist = db.object_store_names().next().is_some();
+
+ // that's super annoying - we have to do cleanup because opening db creates it
+ // (if it didn't exist before)
+ if !some_stores_exist {
+ db.delete()?.into_future().await?
+ }
+
+ Ok(some_stores_exist)
+ }
+
pub fn serialize_value(&self, value: &T) -> Result {
if let Some(cipher) = &self.store_cipher {
let encrypted = cipher.encrypt_json_value(value)?;
@@ -134,6 +152,35 @@ impl WasmStorage {
.store_value_raw(store, key, &self.serialize_value(&value)?)
.await
}
+
+ pub async fn remove_value(&self, store: &str, key: K) -> Result<(), StorageError>
+ where
+ K: wasm_bindgen::JsCast,
+ {
+ self.inner.remove_value_raw(store, key).await
+ }
+
+ pub async fn has_value(&self, store: &str, key: K) -> Result
+ where
+ K: wasm_bindgen::JsCast,
+ {
+ match self.key_count(store, key).await? {
+ n if n == 0 => Ok(false),
+ n if n == 1 => Ok(true),
+ n => Err(StorageError::DuplicateKey { count: n }),
+ }
+ }
+
+ pub async fn key_count(&self, store: &str, key: K) -> Result
+ where
+ K: wasm_bindgen::JsCast,
+ {
+ self.inner.get_key_count(store, key).await
+ }
+
+ pub async fn get_all_keys(&self, store: &str) -> Result {
+ self.inner.get_all_keys(store).await
+ }
}
struct IdbWrapper(IdbDatabase);
@@ -169,6 +216,42 @@ impl IdbWrapper {
.map_err(Into::into)
}
+ async fn remove_value_raw(&self, store: &str, key: K) -> Result<(), StorageError>
+ where
+ K: wasm_bindgen::JsCast,
+ {
+ self.0
+ .transaction_on_one_with_mode(store, IdbTransactionMode::Readwrite)?
+ .object_store(store)?
+ .delete_owned(key)?
+ .into_future()
+ .await
+ .map_err(Into::into)
+ }
+
+ async fn get_key_count(&self, store: &str, key: K) -> Result
+ where
+ K: wasm_bindgen::JsCast,
+ {
+ self.0
+ .transaction_on_one_with_mode(store, IdbTransactionMode::Readwrite)?
+ .object_store(store)?
+ .count_with_key_owned(key)?
+ .into_future()
+ .await
+ .map_err(Into::into)
+ }
+
+ async fn get_all_keys(&self, store: &str) -> Result {
+ self.0
+ .transaction_on_one_with_mode(store, IdbTransactionMode::Readonly)?
+ .object_store(store)?
+ .get_all_keys()?
+ .into_future()
+ .await
+ .map_err(Into::into)
+ }
+
async fn read_exported_cipher_store(
&self,
) -> Result