From 8a1d2af3cfa8b4b3925afc22441df7867be18d5b Mon Sep 17 00:00:00 2001 From: Gala Date: Thu, 22 Dec 2022 14:44:58 +0100 Subject: [PATCH 01/44] adding changes --- explorer/src/api/index.ts | 7 +++++++ explorer/src/components/MobileNav.tsx | 29 ++++++++++++++++++++------- explorer/src/components/Nav.tsx | 21 +++++++++++++++++-- explorer/src/components/Switch.tsx | 2 +- explorer/src/context/main.tsx | 11 ++++++++-- explorer/src/typeDefs/explorer-api.ts | 2 ++ 6 files changed, 60 insertions(+), 12 deletions(-) diff --git a/explorer/src/api/index.ts b/explorer/src/api/index.ts index 37e68b8096..f5ee0216df 100644 --- a/explorer/src/api/index.ts +++ b/explorer/src/api/index.ts @@ -1,4 +1,5 @@ import { + API_BASE_URL, BLOCK_API, COUNTRY_DATA_API, GATEWAYS_API, @@ -27,6 +28,7 @@ import { StatusResponse, SummaryOverviewResponse, ValidatorsResponse, + Environment, } from '../typeDefs/explorer-api'; function getFromCache(key: string) { @@ -143,3 +145,8 @@ export class Api { static fetchUptimeStoryById = async (id: string): Promise => (await fetch(`${UPTIME_STORY_API}/${id}/history`)).json(); } + +export const getEnvironment = (): Environment => { + const matchEnv = (env: Environment) => API_BASE_URL?.toLocaleLowerCase().includes(env) && env; + return matchEnv('sandbox') || matchEnv('qa') || 'mainnet'; +}; \ No newline at end of file diff --git a/explorer/src/components/MobileNav.tsx b/explorer/src/components/MobileNav.tsx index cb44210e9d..e3515dff7f 100644 --- a/explorer/src/components/MobileNav.tsx +++ b/explorer/src/components/MobileNav.tsx @@ -31,11 +31,18 @@ type MobileNavProps = { export const MobileNav: React.FC<{ children: React.ReactNode }> = ({ children }: MobileNavProps) => { const theme = useTheme(); - const { navState, updateNavState } = useMainContext(); + const { navState, updateNavState, environment } = useMainContext(); const [drawerOpen, setDrawerOpen] = React.useState(false); // Set maintenance banner to false by default to don't display it const [openMaintenance, setOpenMaintenance] = React.useState(false); + const explorerName = + `${environment && environment.charAt(0).toUpperCase() + environment.slice(1)} Explorer` || 'Mainnet Explorer'; + + const switchNetworkText = environment === 'mainnet' ? 'Switch to Testnet' : 'Switch to Mainnet'; + const switchNetworkLink = + environment === 'mainnet' ? 'https://sandbox-explorer.nymtech.net' : 'https://explorer.nymtech.net'; + const toggleDrawer = () => { setDrawerOpen(!drawerOpen); }; @@ -76,7 +83,7 @@ export const MobileNav: React.FC<{ children: React.ReactNode }> = ({ children }: }} > - + = ({ children }: color: theme.palette.nym.networkExplorer.nav.text, fontSize: '18px', fontWeight: 600, - ml: 2, }} > - - Network Explorer + + {explorerName} + - + - diff --git a/explorer/src/components/Nav.tsx b/explorer/src/components/Nav.tsx index e2808871a0..93ea445a33 100644 --- a/explorer/src/components/Nav.tsx +++ b/explorer/src/components/Nav.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { Link } from 'react-router-dom'; import { ExpandLess, ExpandMore, Menu } from '@mui/icons-material'; import { CSSObject, styled, Theme, useTheme } from '@mui/material/styles'; +import Button from '@mui/material/Button'; import MuiLink from '@mui/material/Link'; import Box from '@mui/material/Box'; import ListItem from '@mui/material/ListItem'; @@ -231,13 +232,20 @@ ExpandableButton.defaultProps = { }; export const Nav: React.FC = ({ children }) => { - const { updateNavState, navState } = useMainContext(); + const { updateNavState, navState, environment } = useMainContext(); const [drawerIsOpen, setDrawerToOpen] = React.useState(false); const [fixedOpen, setFixedOpen] = React.useState(false); // Set maintenance banner to false by default to don't display it const [openMaintenance, setOpenMaintenance] = React.useState(false); const theme = useTheme(); + const explorerName = + `${environment && environment.charAt(0).toUpperCase() + environment.slice(1)} Explorer` || 'Mainnet Explorer'; + + const switchNetworkText = environment === 'mainnet' ? 'Switch to Testnet' : 'Switch to Mainnet'; + const switchNetworkLink = + environment === 'mainnet' ? 'https://sandbox-explorer.nymtech.net' : 'https://explorer.nymtech.net'; + const setToActive = (id: number) => { updateNavState(id); }; @@ -302,8 +310,17 @@ export const Nav: React.FC = ({ children }) => { }} > - Network Explorer + {explorerName} + ({ export const DarkLightSwitchMobile: React.FC = () => { const { toggleMode } = useMainContext(); return ( - ); diff --git a/explorer/src/context/main.tsx b/explorer/src/context/main.tsx index 42e89b32ee..7d9287d0bf 100644 --- a/explorer/src/context/main.tsx +++ b/explorer/src/context/main.tsx @@ -9,9 +9,10 @@ import { MixnodeStatus, SummaryOverviewResponse, ValidatorsResponse, + Environment, } from '../typeDefs/explorer-api'; import { EnumFilterKey } from '../typeDefs/filters'; -import { Api } from '../api'; +import { Api, getEnvironment } from '../api'; import { NavOptionType, originalNavOptions } from './nav'; interface StateData { @@ -24,6 +25,7 @@ interface StateData { mode: PaletteMode; navState: NavOptionType[]; validators?: ApiState; + environment?: Environment; } interface StateApi { @@ -47,6 +49,9 @@ export const MainContext = React.createContext({ export const useMainContext = (): React.ContextType => React.useContext(MainContext); export const MainContextProvider: React.FC = ({ children }) => { + // network explorer environment + const [environment, setEnvironment] = React.useState('mainnet'); + // light/dark mode const [mode, setMode] = React.useState('dark'); @@ -166,10 +171,12 @@ export const MainContextProvider: React.FC = ({ children }) => { React.useEffect(() => { Promise.all([fetchOverviewSummary(), fetchGateways(), fetchValidators(), fetchBlock(), fetchCountryData()]); + setEnvironment(getEnvironment()); }, []); const state = React.useMemo( () => ({ + environment, block, countryData, fetchMixnodes, @@ -184,7 +191,7 @@ export const MainContextProvider: React.FC = ({ children }) => { updateNavState, validators, }), - [block, countryData, gateways, globalError, mixnodes, mode, navState, summaryOverview, validators], + [environment, block, countryData, gateways, globalError, mixnodes, mode, navState, summaryOverview, validators], ); return {children}; diff --git a/explorer/src/typeDefs/explorer-api.ts b/explorer/src/typeDefs/explorer-api.ts index f8350775c4..0f832b9f59 100644 --- a/explorer/src/typeDefs/explorer-api.ts +++ b/explorer/src/typeDefs/explorer-api.ts @@ -224,3 +224,5 @@ export type MixNodeEconomicDynamicsStatsResponse = { estimated_delegators_reward: number; current_interval_uptime: number; }; + +export type Environment = 'mainnet' | 'sandbox' | 'qa'; From 4f59678ded67b6123c41582cf683f7107dbc4e35 Mon Sep 17 00:00:00 2001 From: Gala Date: Thu, 22 Dec 2022 15:31:35 +0100 Subject: [PATCH 02/44] center layout --- explorer/src/components/MobileNav.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/explorer/src/components/MobileNav.tsx b/explorer/src/components/MobileNav.tsx index e3515dff7f..1e37800894 100644 --- a/explorer/src/components/MobileNav.tsx +++ b/explorer/src/components/MobileNav.tsx @@ -70,6 +70,7 @@ export const MobileNav: React.FC<{ children: React.ReactNode }> = ({ children }: sx={{ display: 'flex', justifyContent: 'space-between', + alignItems: 'center', width: '100%', }} > @@ -111,7 +112,7 @@ export const MobileNav: React.FC<{ children: React.ReactNode }> = ({ children }: - From 5b81510325d530768706ef1365a05bfee510dff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 1 Mar 2023 09:12:47 +0000 Subject: [PATCH 03/44] added additional makefile targets that skip mobile-related steps (#3127) --- Makefile | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index a3a51f4e6b..7a012f7ba2 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,22 @@ test: clippy-all cargo-test wasm fmt +test-no-mobile: clippy-all-no-mobile cargo-test-no-mobile wasm fmt-no-mobile test-all: test cargo-test-expensive +test-all-no-mobile: test-no-mobile cargo-test-expensive no-clippy: build cargo-test wasm fmt +no-clippy-no-mobile: build-no-mobile cargo-test-no-mobile wasm fmt-no-mobile happy: fmt clippy-happy test -clippy-all: clippy-main clippy-main-examples clippy-all-contracts clippy-all-wallet clippy-all-connect clippy-all-connect-mobile clippy-all-wasm-client -clippy-happy: clippy-happy-main clippy-happy-contracts clippy-happy-wallet clippy-happy-connect clippy-happy-connect-mobile -cargo-test: test-main test-contracts test-wallet test-connect test-connect-mobile +happy-no-mobile: fmt-no-mobile clippy-happy-no-mobile test-no-mobile +clippy-all: clippy-all-no-mobile clippy-all-connect-mobile +clippy-all-no-mobile: clippy-main clippy-main-examples clippy-all-contracts clippy-all-wallet clippy-all-connect clippy-all-wasm-client +clippy-happy: clippy-happy-no-mobile clippy-happy-connect-mobile +clippy-happy-no-mobile: clippy-happy-main clippy-happy-contracts clippy-happy-wallet clippy-happy-connect +cargo-test: cargo-test-no-mobile test-connect-mobile +cargo-test-no-mobile: test-main test-contracts test-wallet test-connect cargo-test-expensive: test-main-expensive test-contracts-expensive test-wallet-expensive test-connect-expensive -build: build-contracts build-wallet build-main build-main-examples build-connect build-connect-mobile build-wasm-client -fmt: fmt-main fmt-contracts fmt-wallet fmt-connect fmt-connect-mobile fmt-wasm-client +build: build-no-mobile build-connect-mobile +build-no-mobile: build-contracts build-wallet build-main build-main-examples build-connect build-wasm-client +fmt: fmt-no-mobile fmt-connect-mobile +fmt-no-mobile: fmt-main fmt-contracts fmt-wallet fmt-connect fmt-wasm-client clippy-happy-main: cargo clippy From a477b007e1cc9f5d975080e732acaba089f410c2 Mon Sep 17 00:00:00 2001 From: Fouad Date: Wed, 1 Mar 2023 09:22:35 +0000 Subject: [PATCH 04/44] TS Validator Client updates (#3085) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Squashed clients/validator content from old branch * fix up tests fix up linting * add bundle script * add build prod script to package json update tests * update readme + copy to dist output update global types update types and tests! * update package build * move types and tests into src * Squashed clients/validator content from old branch fix up tests fix up linting * add bundle script * add build prod script to package json update tests * update readme + copy to dist output update global types update types and tests! update package build * move types and tests into src * build to sub-dir * Fixing the few broken tests --------- Co-authored-by: Jon Häggblad Co-authored-by: benedettadavico --- clients/validator/.eslintrc.json | 148 ++++---- clients/validator/.gitignore | 3 +- clients/validator/.npmignore | 4 +- clients/validator/README.md | 49 ++- clients/validator/package.json | 52 ++- clients/validator/rollup.config.mjs | 15 + clients/validator/scripts/build-prod.sh | 31 ++ .../validator/scripts/buildPackageJson.mjs | 20 ++ clients/validator/src/currency.ts | 10 +- clients/validator/src/index.ts | 208 +++++++---- clients/validator/src/nym-api-querier.ts | 7 +- clients/validator/src/nyxd-querier.ts | 128 ++++--- clients/validator/src/query-client.ts | 177 +++++---- clients/validator/src/signing-client.ts | 120 ++++--- .../validator/src/tests/expectedResponses.ts | 178 ++++++++++ clients/validator/src/tests/mock/client.ts | 19 + .../src/tests/mock/delegation.mock.test.ts | 40 +++ .../src/tests/mock/gateway.mock.test.ts | 24 ++ .../src/tests/mock/mixnet.mock.test.ts | 65 ++++ .../src/tests/mock/mixnode.mock.test.ts | 71 ++++ clients/validator/src/tests/mock/testData.ts | 8 + .../src/tests/query/mixnetQueries.test.ts | 180 ++++++++++ .../src/tests/query/vestingQueries.test.ts | 28 ++ .../src/tests/sign/mixnetActions.test.ts | 107 ++++++ clients/validator/src/tsconfig.json | 15 - clients/validator/src/types.ts | 157 -------- clients/validator/src/types/global.d.ts | 11 + clients/validator/src/types/shared.ts | 259 ++++++++++++++ clients/validator/tests/query/balance.test.ts | 11 - clients/validator/tests/sign/send.test.ts | 14 - clients/validator/tsconfig.json | 43 ++- clients/validator/tsconfig.test.json | 6 + ts-packages/types/src/types/global.ts | 123 ++++++- yarn.lock | 335 +++++++++++------- 34 files changed, 1917 insertions(+), 749 deletions(-) create mode 100644 clients/validator/rollup.config.mjs create mode 100644 clients/validator/scripts/build-prod.sh create mode 100644 clients/validator/scripts/buildPackageJson.mjs create mode 100644 clients/validator/src/tests/expectedResponses.ts create mode 100644 clients/validator/src/tests/mock/client.ts create mode 100644 clients/validator/src/tests/mock/delegation.mock.test.ts create mode 100644 clients/validator/src/tests/mock/gateway.mock.test.ts create mode 100644 clients/validator/src/tests/mock/mixnet.mock.test.ts create mode 100644 clients/validator/src/tests/mock/mixnode.mock.test.ts create mode 100644 clients/validator/src/tests/mock/testData.ts create mode 100644 clients/validator/src/tests/query/mixnetQueries.test.ts create mode 100644 clients/validator/src/tests/query/vestingQueries.test.ts create mode 100644 clients/validator/src/tests/sign/mixnetActions.test.ts delete mode 100644 clients/validator/src/tsconfig.json delete mode 100644 clients/validator/src/types.ts create mode 100644 clients/validator/src/types/global.d.ts create mode 100644 clients/validator/src/types/shared.ts delete mode 100644 clients/validator/tests/query/balance.test.ts delete mode 100644 clients/validator/tests/sign/send.test.ts create mode 100644 clients/validator/tsconfig.test.json diff --git a/clients/validator/.eslintrc.json b/clients/validator/.eslintrc.json index 985f191ff5..1069570078 100644 --- a/clients/validator/.eslintrc.json +++ b/clients/validator/.eslintrc.json @@ -1,83 +1,71 @@ { - "root": true, - "env": { - "browser": true, - "es6": true, - "node": true - }, - "parserOptions": { - "ecmaVersion": 2019, - "sourceType": "module" - }, - "globals": { - "Atomics": "readonly", - "SharedArrayBuffer": "readonly" - }, - "plugins": ["prettier", "mocha"], - "extends": [ - "airbnb-base", - "airbnb-typescript/base", - "prettier"], - "rules": { - "prettier/prettier": "error", - "import/prefer-default-export": "off", - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": [ - "**/*.test.[jt]s", - "**/*.spec.[jt]s" - ] - } - ], - "import/extensions": [ - "error", - "ignorePackages", - { - "ts": "never", - "js": "never" - } - ] - }, - "overrides": [ - { - "files": "**/*.ts", - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json" - }, - "plugins": ["@typescript-eslint/eslint-plugin"], - "extends": [ - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended", - "prettier" - ], - "rules": { - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-var-requires": "off", - "no-use-before-define": [0], - "@typescript-eslint/no-use-before-define": [1], - "import/no-unresolved": 0, - "import/no-extraneous-dependencies": [ - "error", - { - "devDependencies": [ - "**/*.test.ts", - "**/*.spec.ts" - ] - } - ], - "quotes": "off", - "@typescript-eslint/quotes": [ - 2, - "single", - { - "avoidEscape": true - } - ], - "@typescript-eslint/no-unused-vars": [2, { "argsIgnorePattern": "^_" }] - } - } + "root": true, + "env": { + "browser": true, + "es6": true, + "node": true + }, + "parserOptions": { + "ecmaVersion": 2019, + "sourceType": "module" + }, + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + }, + "plugins": ["prettier", "mocha"], + "extends": ["airbnb-base", "airbnb-typescript/base", "prettier"], + "rules": { + "prettier/prettier": "error", + "import/prefer-default-export": "off", + "import/no-extraneous-dependencies": [ + "error", + { + "devDependencies": ["**/*.test.[jt]s", "**/*.spec.[jt]s"] + } + ], + "import/extensions": [ + "error", + "ignorePackages", + { + "ts": "never", + "js": "never" + } ] + }, + "overrides": [ + { + "files": "**/*.ts", + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "./tsconfig.json" + }, + "plugins": ["@typescript-eslint/eslint-plugin"], + "extends": ["plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended", "prettier"], + "rules": { + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-var-requires": "off", + "no-use-before-define": [0], + "@typescript-eslint/no-use-before-define": [1], + "import/no-unresolved": 0, + "import/no-extraneous-dependencies": [ + "error", + { + "devDependencies": ["**/*.test.ts", "**/*.spec.ts"] + } + ], + "quotes": "off", + "@typescript-eslint/quotes": [ + 2, + "single", + { + "avoidEscape": true + } + ], + "@typescript-eslint/no-unused-vars": [2, { "argsIgnorePattern": "^_" }] + } + } + ], + "ignorePatterns": ["tsconfig.json", "*.d.ts", "dist/**/*", "dist", "node_modules"] } diff --git a/clients/validator/.gitignore b/clients/validator/.gitignore index 5a4946114d..ee82866c85 100644 --- a/clients/validator/.gitignore +++ b/clients/validator/.gitignore @@ -4,4 +4,5 @@ coverage dist docs examples/accounts -node_modules \ No newline at end of file +node_modules +.env \ No newline at end of file diff --git a/clients/validator/.npmignore b/clients/validator/.npmignore index 62ab11e57c..298aabc724 100644 --- a/clients/validator/.npmignore +++ b/clients/validator/.npmignore @@ -1,3 +1,5 @@ coverage node_modules -tests \ No newline at end of file +tests +src +type diff --git a/clients/validator/README.md b/clients/validator/README.md index d54ebe7c77..41c1ae73af 100644 --- a/clients/validator/README.md +++ b/clients/validator/README.md @@ -1,40 +1,39 @@ -Nym Validator Client -==================== +# Nym Validator Client (Typescript) -A TypeScript client for interacting with CosmWasm smart contracts in Nym validators. +A TypeScript client for interacting with CosmWasm smart contracts in Nym validators. -Running examples ------------------ - -With the code checked out, `cd examples`. This folder contains runnable example code that will set up a blockchain and allow you to interact with it through the client. - -Running tests -------------- +Include the Nym Validator in your project: ``` -npm test +yarn add @nymproject/nym-validator-client ``` -You can also trigger test execution with a test watcher. I don't have the centuries of life left to me that are needed to fight through the arcana of wiring up a working TypeScript mocha triggered execution setup, so for now my Cargo-based hack is: - +Connect to validator and make queries ``` -cargo watch -s "cd clients/validator && npm test" +import Validator from '@nymproject/nym-validator-client' + +const main = async () => { + + const client = await Validator.connectForQuery(rpcAddress, validatorAddress, prefix, mixnetContractAddress, vestingContractAddress, denom) + + client.getBalance(address) + +} + ``` -It's ugly but works fine if you have Cargo installed. TypeScript setup help happily accepted here. +Connect to validator for performing actions -Generating Documentation ------------------------- +``` +import Validator from '@nymproject/nym-validator-client' -You can generate docs by running `npm run docs`. Generated output will appear in the `docs` directory. +const main = async () => { -Packaging ------------------------- + const client = await Validator.connect(mnemonic, rpcAddress, validatorAddress, prefix, mixnetContractAddress, vestingContractAddress, denom) -If you're a Nym platform developer who's made changes to the client and wants to re-publish the package to NPM, here's how you do it: + const res = await client.send(address, [{ amount: '10000000', denom: 'unym' }]); -1. Bump the version number (use SemVer) -1. `npm run build` -1. `npm login` (if you haven't already) -1. `npm publish` \ No newline at end of file +} + +``` diff --git a/clients/validator/package.json b/clients/validator/package.json index 6179e11b19..47766a842b 100644 --- a/clients/validator/package.json +++ b/clients/validator/package.json @@ -4,15 +4,23 @@ "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", + "types": "./dist/index.d.ts", "scripts": { - "build": "tsc", - "test": "ts-mocha tests/**/*.test.ts", + "build": "rollup -c ./rollup.config.mjs", + "build:types": "rollup-type-bundler --dist ./dist/nym-validator-client", + "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", "coverage": "nyc npm test", - "lint": "eslint src", - "lint:fix": "eslint src --fix", + "clean": "rm -rf ./dist", + "lint": "eslint", + "lint:fix": "eslint --fix", + "lint:tsc": "tsc --noEmit", "docs": "typedoc --out docs src/index.ts" }, + "files": [ + "./dist/*" + ], "keywords": [], "author": "Nym Technologies SA (https://nymtech.net)", "contributors": [ @@ -21,6 +29,14 @@ ], "license": "Apache-2.0", "devDependencies": { + "@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", "@typescript-eslint/eslint-plugin": "^5.7.0", "@typescript-eslint/parser": "^5.7.0", "eslint": "^7.18.0", @@ -31,21 +47,21 @@ "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", "prettier": "^2.5.1", - "typedoc": "^0.22.13", "ts-mocha": "^10.0.0", - "typescript": "^4.6.2" - }, - "dependencies": { - "@cosmjs/cosmwasm-stargate": "^0.28.0", - "@cosmjs/crypto": "^0.28.0", - "@cosmjs/math": "^0.28.0", - "@cosmjs/proto-signing": "^0.28.0", - "@cosmjs/stargate": "^0.28.0", - "@cosmjs/tendermint-rpc": "^0.28.0", - "axios": "^0.26.1", - "cosmjs-types": "^0.4.1" + "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" } } diff --git a/clients/validator/rollup.config.mjs b/clients/validator/rollup.config.mjs new file mode 100644 index 0000000000..f78cf449cf --- /dev/null +++ b/clients/validator/rollup.config.mjs @@ -0,0 +1,15 @@ +import typescript from '@rollup/plugin-typescript'; +import resolve from '@rollup/plugin-node-resolve'; +import json from '@rollup/plugin-json'; +import commonjs from '@rollup/plugin-commonjs'; + +export default [ + { + input: './src/index.ts', + output: { + dir: 'dist/nym-validator-client', + format: 'cjs', + }, + plugins: [resolve(), typescript(), commonjs(), json()], + }, +]; diff --git a/clients/validator/scripts/build-prod.sh b/clients/validator/scripts/build-prod.sh new file mode 100644 index 0000000000..06188652b0 --- /dev/null +++ b/clients/validator/scripts/build-prod.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset + +rm -rf ./dist || true +rm -rf ../../dist || true + + +# Bundle application + +yarn build + +# Bundle types + +yarn build:types + +# Build package.json for bundle + +node ./scripts/buildPackageJson.mjs + +# Copy README + +cp README.md dist/nym-validator-client + +# move the output outside of the yarn/npm workspaces + +mv ./dist ../../ + +echo "Output can be found in:" +realpath ../../dist \ No newline at end of file diff --git a/clients/validator/scripts/buildPackageJson.mjs b/clients/validator/scripts/buildPackageJson.mjs new file mode 100644 index 0000000000..da95f10e9d --- /dev/null +++ b/clients/validator/scripts/buildPackageJson.mjs @@ -0,0 +1,20 @@ +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 main = 'index.js'; +const types = 'index.d.ts'; + +// make a package.json for the bundle +const packageJson = { + name: json.name, + version: json.version, + license: json.license, + author: json.author, + main, + types, +}; + +fs.writeFileSync('./dist/nym-validator-client/package.json', JSON.stringify(packageJson, null, 2)); diff --git a/clients/validator/src/currency.ts b/clients/validator/src/currency.ts index 483d13b408..216905f8b1 100644 --- a/clients/validator/src/currency.ts +++ b/clients/validator/src/currency.ts @@ -1,5 +1,6 @@ import { Decimal } from '@cosmjs/math'; import { Coin } from '@cosmjs/stargate'; +import { CoinMap } from './types/shared'; // NARROW NO-BREAK SPACE (U+202F) const thinSpace = '\u202F'; @@ -34,15 +35,6 @@ export function nativeToPrintable(nativeValue: string): string { return Decimal.fromAtomics(nativeValue, 6).toString(); } -export interface MappedCoin { - readonly denom: string; - readonly fractionalDigits: number; -} - -export interface CoinMap { - readonly [key: string]: MappedCoin; -} - export function nativeCoinToDisplay(coin: Coin, coinMap: CoinMap): Coin { if (!coinMap) return coin; diff --git a/clients/validator/src/index.ts b/clients/validator/src/index.ts index dac29371c3..e11d24525f 100644 --- a/clients/validator/src/index.ts +++ b/clients/validator/src/index.ts @@ -1,6 +1,3 @@ -import { Bip39, Random } from '@cosmjs/crypto'; -import { DirectSecp256k1HdWallet, EncodeObject } from '@cosmjs/proto-signing'; -import { coin as cosmosCoin, Coin, DeliverTxResponse, isDeliverTxFailure, StdFee } from '@cosmjs/stargate'; import { ExecuteResult, InstantiateOptions, @@ -8,45 +5,37 @@ import { MigrateResult, UploadResult, } from '@cosmjs/cosmwasm-stargate'; -import SigningClient, { ISigningClient } from './signing-client'; +import { Bip39, Random } from '@cosmjs/crypto'; +import { DirectSecp256k1HdWallet, EncodeObject } from '@cosmjs/proto-signing'; +import { Coin, coin as cosmosCoin, DeliverTxResponse, isDeliverTxFailure, StdFee } from '@cosmjs/stargate'; import { ContractStateParams, Delegation, Gateway, GatewayBond, + GatewayOwnershipResponse, + LayerDistribution, MixnetContractVersion, MixNode, MixNodeBond, + MixNodeCostParams, + MixNodeDetails, + MixNodeRewarding, + MixOwnershipResponse, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse, PagedGatewayResponse, PagedMixDelegationsResponse, - PagedMixnodeResponse, -} from './types'; -import { - CoinMap, - displayAmountToNative, - MappedCoin, - nativeCoinToDisplay, - nativeToPrintable, - printableBalance, - printableCoin, -} from './currency'; + PagedMixNodeBondResponse, + PagedMixNodeDetailsResponse, + PagedUnbondedMixnodesResponse, + RewardingParams, + StakeSaturationResponse, + UnbondedMixnodeResponse, +} from '@nymproject/types'; import QueryClient from './query-client'; -import { nymGasPrice } from './stargate-helper'; - -export { coins, coin } from '@cosmjs/stargate'; -export { Coin }; -export { - displayAmountToNative, - nativeCoinToDisplay, - printableCoin, - printableBalance, - nativeToPrintable, - MappedCoin, - CoinMap, -}; -export { nymGasPrice }; +import SigningClient, { ISigningClient } from './signing-client'; +import { ContractState } from './types/shared'; export interface INymClient { readonly mixnetContract: string; @@ -147,7 +136,7 @@ export default class ValidatorClient implements INymClient { return DirectSecp256k1HdWallet.fromMnemonic(mnemonic, signerOptions); } - getBalance(address: string): Promise { + async getBalance(address: string): Promise { return this.client.getBalance(address, this.denom); } @@ -159,15 +148,39 @@ export default class ValidatorClient implements INymClient { return this.client.getCachedMixnodes(); } - async getActiveMixnodes(): Promise { + async getStakeSaturation(mixId: number): Promise { + return this.client.getStakeSaturation(this.mixnetContract, mixId); + } + + async getActiveMixnodes(): Promise { return this.client.getActiveMixnodes(); } + async getUnbondedMixNodeInformation(mixId: number): Promise { + return this.client.getUnbondedMixNodeInformation(this.mixnetContract, mixId); + } + async getRewardedMixnodes(): Promise { return this.client.getRewardedMixnodes(); } - public async getMixnetContractSettings(): Promise { + async getMixnodeRewardingDetails(mixId: number): Promise { + return this.client.getMixnodeRewardingDetails(this.mixnetContract, mixId); + } + + async getOwnedMixnode(address: string): Promise { + return this.client.getOwnedMixnode(this.mixnetContract, address); + } + + async ownsGateway(address: string): Promise { + return this.client.ownsGateway(this.mixnetContract, address); + } + + async getLayerDistribution(): Promise { + return this.client.getLayerDistribution(this.mixnetContract); + } + + public async getMixnetContractSettings(): Promise { return this.client.getStateParams(this.mixnetContract); } @@ -175,29 +188,74 @@ export default class ValidatorClient implements INymClient { return this.client.getContractVersion(this.mixnetContract); } - public async getRewardPool(): Promise { - return this.client.getRewardPool(this.mixnetContract); + public async getVestingContractVersion(): Promise { + return this.client.getContractVersion(this.vestingContract); } - public async getCirculatingSupply(): Promise { - return this.client.getCirculatingSupply(this.mixnetContract); + public async getSpendableCoins(vestingAccountAddress: string): Promise { + return this.client.getSpendableCoins(this.vestingContract, vestingAccountAddress); } - public async getSybilResistancePercent(): Promise { - return this.client.getSybilResistancePercent(this.mixnetContract); + public async getRewardParams(): Promise { + return this.client.getRewardParams(this.mixnetContract); } - public async getIntervalRewardPercent(): Promise { - return this.client.getIntervalRewardPercent(this.mixnetContract); + async getUnbondedMixNodes(): Promise { + let mixNodes: UnbondedMixnodeResponse[] = []; + const limit = 50; + let startAfter; + for (;;) { + // eslint-disable-next-line no-await-in-loop + const pagedResponse: PagedUnbondedMixnodesResponse = await this.client.getUnbondedMixNodes( + this.mixnetContract, + limit, + startAfter, + ); + + mixNodes = mixNodes.concat(pagedResponse.nodes); + startAfter = pagedResponse.start_next_after; + // if `start_next_after` is not set, we're done + if (!startAfter) { + break; + } + } + + return mixNodes; } - public async getAllNyxdMixnodes(): Promise { + public async getMixNodeBonds(): Promise { let mixNodes: MixNodeBond[] = []; const limit = 50; let startAfter; - for (; ;) { + for (;;) { // eslint-disable-next-line no-await-in-loop - const pagedResponse: PagedMixnodeResponse = await this.client.getMixNodesPaged(this.mixnetContract, limit); + const pagedResponse: PagedMixNodeBondResponse = await this.client.getMixNodeBonds( + this.mixnetContract, + limit, + startAfter, + ); + mixNodes = mixNodes.concat(pagedResponse.nodes); + startAfter = pagedResponse.start_next_after; + // if `start_next_after` is not set, we're done + if (!startAfter) { + break; + } + } + + return mixNodes; + } + + public async getMixNodesDetailed(): Promise { + let mixNodes: MixNodeDetails[] = []; + const limit = 50; + let startAfter; + for (;;) { + // eslint-disable-next-line no-await-in-loop + const pagedResponse: PagedMixNodeDetailsResponse = await this.client.getMixNodesDetailed( + this.mixnetContract, + limit, + startAfter, + ); mixNodes = mixNodes.concat(pagedResponse.nodes); startAfter = pagedResponse.start_next_after; // if `start_next_after` is not set, we're done @@ -210,37 +268,24 @@ export default class ValidatorClient implements INymClient { } public async getAllNyxdGateways(): Promise { - let gateways: GatewayBond[] = []; - const limit = 50; - let startAfter; - for (; ;) { - // eslint-disable-next-line no-await-in-loop - const pagedResponse: PagedGatewayResponse = await this.client.getGatewaysPaged(this.mixnetContract, limit); - gateways = gateways.concat(pagedResponse.nodes); - startAfter = pagedResponse.start_next_after; - // if `start_next_after` is not set, we're done - if (!startAfter) { - break; - } - } - - return gateways; + const pagedResponse: PagedGatewayResponse = await this.client.getGatewaysPaged(this.mixnetContract); + return pagedResponse.nodes; } /** * Gets list of all delegations towards particular mixnode. * - * @param mixIdentity identity of the node to which the delegation was sent + * @param mix_id identity of the node to which the delegation was sent */ - public async getAllNyxdSingleMixnodeDelegations(mixIdentity: string): Promise { + public async getAllNyxdSingleMixnodeDelegations(mix_id: number): Promise { let delegations: Delegation[] = []; const limit = 250; let startAfter; - for (; ;) { + for (;;) { // eslint-disable-next-line no-await-in-loop const pagedResponse: PagedMixDelegationsResponse = await this.client.getMixNodeDelegationsPaged( this.mixnetContract, - mixIdentity, + mix_id, limit, startAfter, ); @@ -259,7 +304,7 @@ export default class ValidatorClient implements INymClient { let delegations: Delegation[] = []; const limit = 250; let startAfter; - for (; ;) { + for (;;) { // eslint-disable-next-line no-await-in-loop const pagedResponse: PagedDelegatorDelegationsResponse = await this.client.getDelegatorDelegationsPaged( this.mixnetContract, @@ -278,13 +323,13 @@ export default class ValidatorClient implements INymClient { return delegations; } - public async getAllNyxdNetworkDelegations(): Promise { + public async getAllNyxdDelegations(): Promise { let delegations: Delegation[] = []; const limit = 250; let startAfter; - for (; ;) { + for (;;) { // eslint-disable-next-line no-await-in-loop - const pagedResponse: PagedAllDelegationsResponse = await this.client.getAllNetworkDelegationsPaged( + const pagedResponse: PagedAllDelegationsResponse = await this.client.getAllDelegationsPaged( this.mixnetContract, limit, startAfter, @@ -300,6 +345,10 @@ export default class ValidatorClient implements INymClient { return delegations; } + public async getDelegationDetails(mix_id: number, delegator: string): Promise { + return this.client.getDelegationDetails(this.mixnetContract, mix_id, delegator); + } + /** * Generate a minimum gateway bond required to create a fresh mixnode. * @@ -308,7 +357,7 @@ export default class ValidatorClient implements INymClient { public async minimumMixnodePledge(): Promise { const stateParams = await this.getMixnetContractSettings(); // we trust the contract to return a valid number - return cosmosCoin(stateParams.minimum_mixnode_pledge, this.prefix); + return cosmosCoin(stateParams.params.minimum_mixnode_pledge, this.prefix); } /** @@ -319,7 +368,7 @@ export default class ValidatorClient implements INymClient { public async minimumGatewayPledge(): Promise { const stateParams = await this.getMixnetContractSettings(); // we trust the contract to return a valid number - return cosmosCoin(stateParams.minimum_gateway_pledge, this.prefix); + return cosmosCoin(stateParams.params.minimum_gateway_pledge, this.prefix); } public async send( @@ -393,12 +442,21 @@ export default class ValidatorClient implements INymClient { public async bondMixNode( mixNode: MixNode, ownerSignature: string, + costParams: MixNodeCostParams, pledge: Coin, fee?: StdFee | 'auto' | number, memo?: string, ): Promise { this.assertSigning(); - return (this.client as ISigningClient).bondMixNode(this.mixnetContract, mixNode, ownerSignature, pledge, fee, memo); + return (this.client as ISigningClient).bondMixNode( + this.mixnetContract, + mixNode, + costParams, + ownerSignature, + pledge, + fee, + memo, + ); } public async unbondMixNode(fee?: StdFee | 'auto' | number, memo?: string): Promise { @@ -423,29 +481,29 @@ export default class ValidatorClient implements INymClient { } public async delegateToMixNode( - mixIdentity: string, + mixId: number, amount: Coin, fee?: StdFee | 'auto' | number, memo?: string, ): Promise { this.assertSigning(); - return (this.client as ISigningClient).delegateToMixNode(this.mixnetContract, mixIdentity, amount, fee, memo); + return (this.client as ISigningClient).delegateToMixNode(this.mixnetContract, mixId, amount, fee, memo); } public async undelegateFromMixNode( - mixIdentity: string, + mixId: number, fee?: StdFee | 'auto' | number, memo?: string, ): Promise { - return (this.client as ISigningClient).undelegateFromMixNode(this.mixnetContract, mixIdentity, fee, memo); + return (this.client as ISigningClient).undelegateFromMixNode(this.mixnetContract, mixId, fee, memo); } public async updateMixnodeConfig( - mixIdentity: string, + mixId: number, fee: StdFee | 'auto' | number, profitPercentage: number, ): Promise { - return (this.client as ISigningClient).updateMixnodeConfig(this.mixnetContract, mixIdentity, profitPercentage, fee); + return (this.client as ISigningClient).updateMixnodeConfig(this.mixnetContract, mixId, profitPercentage, fee); } public async updateContractStateParams( diff --git a/clients/validator/src/nym-api-querier.ts b/clients/validator/src/nym-api-querier.ts index 3fa0471804..e66c93c41f 100644 --- a/clients/validator/src/nym-api-querier.ts +++ b/clients/validator/src/nym-api-querier.ts @@ -2,9 +2,8 @@ * Copyright 2021 - Nym Technologies SA * SPDX-License-Identifier: Apache-2.0 */ - import axios from 'axios'; -import { GatewayBond, MixNodeBond } from './types'; +import { GatewayBond, MixNodeBond, MixNodeDetails } from '@nymproject/types'; export const NYM_API_VERSION = '/v1'; export const NYM_API_GATEWAYS_PATH = `${NYM_API_VERSION}/gateways`; @@ -17,7 +16,7 @@ export interface INymApiQuery { getCachedGateways(): Promise; - getActiveMixnodes(): Promise; + getActiveMixnodes(): Promise; getRewardedMixnodes(): Promise; } @@ -51,7 +50,7 @@ export default class NymApiQuerier implements INymApiQuery { throw new Error('None of the provided validator APIs seem to be alive'); } - async getActiveMixnodes(): Promise { + async getActiveMixnodes(): Promise { const url = new URL(this.nymApiUrl); url.pathname += NYM_API_ACTIVE_MIXNODES_PATH; diff --git a/clients/validator/src/nyxd-querier.ts b/clients/validator/src/nyxd-querier.ts index edd791a8fe..0e34493c2e 100644 --- a/clients/validator/src/nyxd-querier.ts +++ b/clients/validator/src/nyxd-querier.ts @@ -2,28 +2,24 @@ * Copyright 2021 - Nym Technologies SA * SPDX-License-Identifier: Apache-2.0 */ - -import { JsonObject } from '@cosmjs/cosmwasm-stargate'; // eslint-disable-next-line import/no-cycle import { INyxdQuery } from './query-client'; +import { Delegation, RewardingParams, StakeSaturationResponse } from '@nymproject/types'; import { - ContractStateParams, - Delegation, + UnbondedMixnodeResponse, GatewayOwnershipResponse, - LayerDistribution, MixnetContractVersion, MixOwnershipResponse, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse, PagedGatewayResponse, PagedMixDelegationsResponse, - PagedMixnodeResponse, - RewardingStatus, -} from './types'; - -interface SmartContractQuery { - queryContractSmart(address: string, queryMsg: Record): Promise; -} + PagedMixNodeBondResponse, + PagedMixNodeDetailsResponse, + PagedUnbondedMixnodesResponse, + LayerDistribution, +} from '@nymproject/types'; +import { ContractState, SmartContractQuery } from './types/shared'; export default class NyxdQuerier implements INyxdQuery { client: SmartContractQuery; @@ -38,15 +34,44 @@ export default class NyxdQuerier implements INyxdQuery { }); } - getMixNodesPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise { + getMixNodeBonds( + mixnetContractAddress: string, + limit?: number, + startAfter?: string, + ): Promise { return this.client.queryContractSmart(mixnetContractAddress, { - get_mix_nodes: { + get_mix_node_bonds: { limit, start_after: startAfter, }, }); } + getMixNodesDetailed( + mixnetContractAddress: string, + limit?: number, + startAfter?: string, + ): Promise { + return this.client.queryContractSmart(mixnetContractAddress, { + get_mix_nodes_detailed: { + limit, + start_after: startAfter, + }, + }); + } + + getStakeSaturation(mixnetContractAddress: string, mixId: number): Promise { + return this.client.queryContractSmart(mixnetContractAddress, { + get_stake_saturation: { mix_id: mixId }, + }); + } + + getMixnodeRewardingDetails(mixnetContractAddress: string, mixId: number): Promise { + return this.client.queryContractSmart(mixnetContractAddress, { + get_mixnode_rewarding_details: { mix_id: mixId }, + }); + } + getGatewaysPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise { return this.client.queryContractSmart(mixnetContractAddress, { get_gateways: { @@ -56,35 +81,51 @@ export default class NyxdQuerier implements INyxdQuery { }); } - ownsMixNode(mixnetContractAddress: string, address: string): Promise { + getOwnedMixnode(mixnetContractAddress: string, address: string): Promise { return this.client.queryContractSmart(mixnetContractAddress, { - owns_mixnode: { + get_owned_mixnode: { address, }, }); } + getUnbondedMixNodes( + mixnetContractAddress: string, + limit?: number, + startAfter?: string, + ): Promise { + return this.client.queryContractSmart(mixnetContractAddress, { + get_unbonded_mix_nodes: { limit, start_after: startAfter }, + }); + } + + getUnbondedMixNodeInformation(mixnetContractAddress: string, mixId: number): Promise { + return this.client.queryContractSmart(mixnetContractAddress, { + get_unbonded_mix_node_information: { mix_id: mixId }, + }); + } + ownsGateway(mixnetContractAddress: string, address: string): Promise { return this.client.queryContractSmart(mixnetContractAddress, { - owns_gateway: { + get_owned_gateway: { address, }, }); } - getStateParams(mixnetContractAddress: string): Promise { + getStateParams(mixnetContractAddress: string): Promise { return this.client.queryContractSmart(mixnetContractAddress, { - state_params: {}, + get_state: {}, }); } - getAllNetworkDelegationsPaged( + getAllDelegationsPaged( mixnetContractAddress: string, limit?: number, startAfter?: [string, string], ): Promise { return this.client.queryContractSmart(mixnetContractAddress, { - get_all_network_delegations: { + get_all_delegations: { start_after: startAfter, limit, }, @@ -93,13 +134,13 @@ export default class NyxdQuerier implements INyxdQuery { getMixNodeDelegationsPaged( mixnetContractAddress: string, - mixIdentity: string, + mix_id: number, limit?: number, startAfter?: string, ): Promise { return this.client.queryContractSmart(mixnetContractAddress, { get_mixnode_delegations: { - mix_identity: mixIdentity, + mix_id: mix_id, start_after: startAfter, limit, }, @@ -121,10 +162,10 @@ export default class NyxdQuerier implements INyxdQuery { }); } - getDelegationDetails(mixnetContractAddress: string, mixIdentity: string, delegator: string): Promise { + getDelegationDetails(mixnetContractAddress: string, mix_id: number, delegator: string): Promise { return this.client.queryContractSmart(mixnetContractAddress, { get_delegation_details: { - mix_identity: mixIdentity, + mix_id: mix_id, delegator, }, }); @@ -132,44 +173,19 @@ export default class NyxdQuerier implements INyxdQuery { getLayerDistribution(mixnetContractAddress: string): Promise { return this.client.queryContractSmart(mixnetContractAddress, { - layer_distribution: {}, + get_layer_distribution: {}, }); } - getRewardPool(mixnetContractAddress: string): Promise { + getRewardParams(mixnetContractAddress: string): Promise { return this.client.queryContractSmart(mixnetContractAddress, { - get_reward_pool: {}, + get_rewarding_params: {}, }); } - getCirculatingSupply(mixnetContractAddress: string): Promise { - return this.client.queryContractSmart(mixnetContractAddress, { - get_circulating_supply: {}, - }); - } - - getIntervalRewardPercent(mixnetContractAddress: string): Promise { - return this.client.queryContractSmart(mixnetContractAddress, { - get_interval_reward_percent: {}, - }); - } - - getSybilResistancePercent(mixnetContractAddress: string): Promise { - return this.client.queryContractSmart(mixnetContractAddress, { - get_sybil_resistance_percent: {}, - }); - } - - getRewardingStatus( - mixnetContractAddress: string, - mixIdentity: string, - rewardingIntervalNonce: number, - ): Promise { - return this.client.queryContractSmart(mixnetContractAddress, { - get_rewarding_status: { - mix_identity: mixIdentity, - rewarding_interval_nonce: rewardingIntervalNonce, - }, + getSpendableCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise { + return this.client.queryContractSmart(vestingContractAddress, { + vesting_account_address: vestingAccountAddress, }); } } diff --git a/clients/validator/src/query-client.ts b/clients/validator/src/query-client.ts index c78237cdb4..319c46f80e 100644 --- a/clients/validator/src/query-client.ts +++ b/clients/validator/src/query-client.ts @@ -1,75 +1,56 @@ -import { CosmWasmClient, JsonObject } from '@cosmjs/cosmwasm-stargate'; -import { Tendermint34Client } from '@cosmjs/tendermint-rpc'; -import { - Account, - Block, - Coin, - DeliverTxResponse, - IndexedTx, - SearchTxFilter, - SearchTxQuery, - SequenceResponse, -} from '@cosmjs/stargate'; -import { Code, CodeDetails, Contract, ContractCodeHistoryEntry } from '@cosmjs/cosmwasm-stargate/build/cosmwasmclient'; +import { CosmWasmClient } from '@cosmjs/cosmwasm-stargate'; // eslint-disable-next-line import/no-cycle import NyxdQuerier from './nyxd-querier'; import { - ContractStateParams, Delegation, GatewayBond, GatewayOwnershipResponse, LayerDistribution, MixnetContractVersion, - MixNodeBond, + MixNodeDetails, MixOwnershipResponse, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse, PagedGatewayResponse, PagedMixDelegationsResponse, - PagedMixnodeResponse, - RewardingStatus, -} from './types'; -import NymApiQuerier, { INymApiQuery as INymApiQuery } from './nym-api-querier'; - -export interface ICosmWasmQuery { - // methods exposed by `CosmWasmClient` - getChainId(): Promise; - getHeight(): Promise; - getAccount(searchAddress: string): Promise; - getSequence(address: string): Promise; - getBlock(height?: number): Promise; - getBalance(address: string, searchDenom: string): Promise; - getTx(id: string): Promise; - searchTx(query: SearchTxQuery, filter?: SearchTxFilter): Promise; - disconnect(): void; - broadcastTx(tx: Uint8Array, timeoutMs?: number, pollIntervalMs?: number): Promise; - getCodes(): Promise; - getCodeDetails(codeId: number): Promise; - getContracts(codeId: number): Promise; - getContract(address: string): Promise; - getContractCodeHistory(address: string): Promise; - queryContractRaw(address: string, key: Uint8Array): Promise; - queryContractSmart(address: string, queryMsg: Record): Promise; -} + PagedMixNodeBondResponse, + PagedMixNodeDetailsResponse, + PagedUnbondedMixnodesResponse, + StakeSaturationResponse, + UnbondedMixnodeResponse, + MixNodeBond, + MixNodeRewarding, +} from '@nymproject/types'; +import NymApiQuerier, { INymApiQuery } from './nym-api-querier'; +import { ContractState, ICosmWasmQuery } from './types/shared'; +import { RewardingParams } from '@nymproject/types'; +import { Tendermint34Client } from '@cosmjs/tendermint-rpc'; export interface INyxdQuery { // nym-specific implemented inside NymQuerier getContractVersion(mixnetContractAddress: string): Promise; - - getMixNodesPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise; + getMixNodeBonds( + mixnetContractAddress: string, + limit?: number, + startAfter?: string, + ): Promise; + getMixNodesDetailed( + mixnetContractAddress: string, + limit?: number, + startAfter?: string, + ): Promise; getGatewaysPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise; - ownsMixNode(mixnetContractAddress: string, address: string): Promise; + getOwnedMixnode(mixnetContractAddress: string, address: string): Promise; ownsGateway(mixnetContractAddress: string, address: string): Promise; - getStateParams(mixnetContractAddress: string): Promise; - - getAllNetworkDelegationsPaged( + getStateParams(mixnetContractAddress: string): Promise; + getAllDelegationsPaged( mixnetContractAddress: string, limit?: number, startAfter?: [string, string], ): Promise; getMixNodeDelegationsPaged( mixnetContractAddress: string, - mixIdentity: string, + mix_id: number, limit?: number, startAfter?: string, ): Promise; @@ -79,21 +60,15 @@ export interface INyxdQuery { limit?: number, startAfter?: string, ): Promise; - getDelegationDetails(mixnetContractAddress: string, mixIdentity: string, delegator: string): Promise; - + getDelegationDetails(mixnetContractAddress: string, mix_id: number, delegator: string): Promise; getLayerDistribution(mixnetContractAddress: string): Promise; - getRewardPool(mixnetContractAddress: string): Promise; - getCirculatingSupply(mixnetContractAddress: string): Promise; - getIntervalRewardPercent(mixnetContractAddress: string): Promise; - getSybilResistancePercent(mixnetContractAddress: string): Promise; - getRewardingStatus( - mixnetContractAddress: string, - mixIdentity: string, - rewardingIntervalNonce: number, - ): Promise; + getRewardParams(mixnetContractAddress: string): Promise; + getStakeSaturation(mixnetContractAddress: string, mixId: number): Promise; + getUnbondedMixNodeInformation(mixnetContractAddress: string, mixId: number): Promise; + getMixnodeRewardingDetails(mixnetContractAddress: string, mixId: number): Promise; } -export interface IQueryClient extends ICosmWasmQuery, INyxdQuery, INymApiQuery { } +export interface IQueryClient extends ICosmWasmQuery, INyxdQuery, INymApiQuery {} export default class QueryClient extends CosmWasmClient implements IQueryClient { private nyxdQuerier: NyxdQuerier; @@ -115,41 +90,73 @@ export default class QueryClient extends CosmWasmClient implements IQueryClient return this.nyxdQuerier.getContractVersion(mixnetContractAddress); } - getMixNodesPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise { - return this.nyxdQuerier.getMixNodesPaged(mixnetContractAddress, limit, startAfter); + getMixNodeBonds( + mixnetContractAddress: string, + limit?: number, + startAfter?: string, + ): Promise { + return this.nyxdQuerier.getMixNodeBonds(mixnetContractAddress, limit, startAfter); + } + + getMixNodesDetailed( + mixnetContractAddress: string, + limit?: number, + startAfter?: string, + ): Promise { + return this.nyxdQuerier.getMixNodesDetailed(mixnetContractAddress, limit, startAfter); + } + + getStakeSaturation(mixnetContractAddress: string, mixId: number): Promise { + return this.nyxdQuerier.getStakeSaturation(mixnetContractAddress, mixId); + } + + getMixnodeRewardingDetails(mixnetContractAddress: string, mixId: number): Promise { + return this.nyxdQuerier.getMixnodeRewardingDetails(mixnetContractAddress, mixId); } getGatewaysPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise { return this.nyxdQuerier.getGatewaysPaged(mixnetContractAddress, limit, startAfter); } - ownsMixNode(mixnetContractAddress: string, address: string): Promise { - return this.nyxdQuerier.ownsMixNode(mixnetContractAddress, address); + getOwnedMixnode(mixnetContractAddress: string, address: string): Promise { + return this.nyxdQuerier.getOwnedMixnode(mixnetContractAddress, address); } ownsGateway(mixnetContractAddress: string, address: string): Promise { return this.nyxdQuerier.ownsGateway(mixnetContractAddress, address); } - getStateParams(mixnetContractAddress: string): Promise { + getUnbondedMixNodes( + mixnetContractAddress: string, + limit?: number, + startAfter?: string, + ): Promise { + return this.nyxdQuerier.getUnbondedMixNodes(mixnetContractAddress, limit, startAfter); + } + + getUnbondedMixNodeInformation(mixnetContractAddress: string, mixId: number): Promise { + return this.nyxdQuerier.getUnbondedMixNodeInformation(mixnetContractAddress, mixId); + } + + getStateParams(mixnetContractAddress: string): Promise { return this.nyxdQuerier.getStateParams(mixnetContractAddress); } - getAllNetworkDelegationsPaged( + getAllDelegationsPaged( mixnetContractAddress: string, limit?: number, startAfter?: [string, string], ): Promise { - return this.nyxdQuerier.getAllNetworkDelegationsPaged(mixnetContractAddress, limit, startAfter); + return this.nyxdQuerier.getAllDelegationsPaged(mixnetContractAddress, limit, startAfter); } getMixNodeDelegationsPaged( mixnetContractAddress: string, - mixIdentity: string, + mix_id: number, limit?: number, startAfter?: string, ): Promise { - return this.nyxdQuerier.getMixNodeDelegationsPaged(mixnetContractAddress, mixIdentity, limit, startAfter); + return this.nyxdQuerier.getMixNodeDelegationsPaged(mixnetContractAddress, mix_id, limit, startAfter); } getDelegatorDelegationsPaged( @@ -161,36 +168,16 @@ export default class QueryClient extends CosmWasmClient implements IQueryClient return this.nyxdQuerier.getDelegatorDelegationsPaged(mixnetContractAddress, delegator, limit, startAfter); } - getDelegationDetails(mixnetContractAddress: string, mixIdentity: string, delegator: string): Promise { - return this.nyxdQuerier.getDelegationDetails(mixnetContractAddress, mixIdentity, delegator); + getDelegationDetails(mixnetContractAddress: string, mix_id: number, delegator: string): Promise { + return this.nyxdQuerier.getDelegationDetails(mixnetContractAddress, mix_id, delegator); } getLayerDistribution(mixnetContractAddress: string): Promise { return this.nyxdQuerier.getLayerDistribution(mixnetContractAddress); } - getRewardPool(mixnetContractAddress: string): Promise { - return this.nyxdQuerier.getRewardPool(mixnetContractAddress); - } - - getCirculatingSupply(mixnetContractAddress: string): Promise { - return this.nyxdQuerier.getCirculatingSupply(mixnetContractAddress); - } - - getIntervalRewardPercent(mixnetContractAddress: string): Promise { - return this.nyxdQuerier.getIntervalRewardPercent(mixnetContractAddress); - } - - getSybilResistancePercent(mixnetContractAddress: string): Promise { - return this.nyxdQuerier.getSybilResistancePercent(mixnetContractAddress); - } - - getRewardingStatus( - mixnetContractAddress: string, - mixIdentity: string, - rewardingIntervalNonce: number, - ): Promise { - return this.nyxdQuerier.getRewardingStatus(mixnetContractAddress, mixIdentity, rewardingIntervalNonce); + getRewardParams(mixnetContractAddress: string): Promise { + return this.nyxdQuerier.getRewardParams(mixnetContractAddress); } getCachedGateways(): Promise { @@ -201,11 +188,15 @@ export default class QueryClient extends CosmWasmClient implements IQueryClient return this.nymApiQuerier.getCachedMixnodes(); } - getActiveMixnodes(): Promise { + getActiveMixnodes(): Promise { return this.nymApiQuerier.getActiveMixnodes(); } getRewardedMixnodes(): Promise { return this.nymApiQuerier.getRewardedMixnodes(); } + + getSpendableCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise { + return this.nyxdQuerier.getSpendableCoins(vestingContractAddress, vestingAccountAddress); + } } diff --git a/clients/validator/src/signing-client.ts b/clients/validator/src/signing-client.ts index 8cb589cd0e..d750eefcd2 100644 --- a/clients/validator/src/signing-client.ts +++ b/clients/validator/src/signing-client.ts @@ -25,15 +25,22 @@ import { MixnetContractVersion, MixNode, MixNodeBond, + MixNodeCostParams, + MixNodeDetails, + MixNodeRewarding, MixOwnershipResponse, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse, PagedGatewayResponse, PagedMixDelegationsResponse, - PagedMixnodeResponse, - RewardingStatus, -} from './types'; + PagedMixNodeBondResponse, + PagedMixNodeDetailsResponse, + PagedUnbondedMixnodesResponse, + RewardingParams, + UnbondedMixnodeResponse, +} from '@nymproject/types'; import NymApiQuerier from './nym-api-querier'; +import { ContractState } from './types/shared'; // methods exposed by `SigningCosmWasmClient` export interface ICosmWasmSigning { @@ -143,6 +150,7 @@ export interface ISigningClient extends IQueryClient, ICosmWasmSigning, INymSign bondMixNode( mixnetContractAddress: string, mixNode: MixNode, + costParams: MixNodeCostParams, ownerSignature: string, pledge: Coin, fee?: StdFee | 'auto' | number, @@ -164,7 +172,7 @@ export interface ISigningClient extends IQueryClient, ICosmWasmSigning, INymSign delegateToMixNode( mixnetContractAddress: string, - mixIdentity: string, + mixId: number, amount: Coin, fee?: StdFee | 'auto' | number, memo?: string, @@ -172,14 +180,14 @@ export interface ISigningClient extends IQueryClient, ICosmWasmSigning, INymSign undelegateFromMixNode( mixnetContractAddress: string, - mixIdentity: string, + mixId: number, fee?: StdFee | 'auto' | number, memo?: string, ): Promise; updateMixnodeConfig( mixnetContractAddress: string, - mixIdentity: string, + mixId: number, profitMarginPercent: number, fee: StdFee | 'auto' | number, ): Promise; @@ -235,44 +243,76 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig // query related: getContractVersion(mixnetContractAddress: string): Promise { - return this.nyxdQuerier.getContractVersion(mixnetContractAddress); + return this.getContractVersion(mixnetContractAddress); } - getMixNodesPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise { - return this.nyxdQuerier.getMixNodesPaged(mixnetContractAddress, limit, startAfter); + getMixNodeBonds( + mixnetContractAddress: string, + limit?: number, + startAfter?: string, + ): Promise { + return this.nyxdQuerier.getMixNodeBonds(mixnetContractAddress, limit, startAfter); + } + + getMixNodesDetailed( + mixnetContractAddress: string, + limit?: number, + startAfter?: string, + ): Promise { + return this.nyxdQuerier.getMixNodesDetailed(mixnetContractAddress, limit, startAfter); + } + + getStakeSaturation(mixnetContractAddress: string, mixId: number) { + return this.nyxdQuerier.getStakeSaturation(mixnetContractAddress, mixId); + } + + getUnbondedMixNodeInformation(mixnetContractAddress: string, mixId: number): Promise { + return this.nyxdQuerier.getUnbondedMixNodeInformation(mixnetContractAddress, mixId); + } + + getMixnodeRewardingDetails(mixnetContractAddress: string, mixId: number): Promise { + return this.nyxdQuerier.getMixnodeRewardingDetails(mixnetContractAddress, mixId); } getGatewaysPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise { return this.nyxdQuerier.getGatewaysPaged(mixnetContractAddress, limit, startAfter); } - ownsMixNode(mixnetContractAddress: string, address: string): Promise { - return this.nyxdQuerier.ownsMixNode(mixnetContractAddress, address); + getOwnedMixnode(mixnetContractAddress: string, address: string): Promise { + return this.nyxdQuerier.getOwnedMixnode(mixnetContractAddress, address); } ownsGateway(mixnetContractAddress: string, address: string): Promise { return this.nyxdQuerier.ownsGateway(mixnetContractAddress, address); } - getStateParams(mixnetContractAddress: string): Promise { + getStateParams(mixnetContractAddress: string): Promise { return this.nyxdQuerier.getStateParams(mixnetContractAddress); } - getAllNetworkDelegationsPaged( + getAllDelegationsPaged( mixnetContractAddress: string, limit?: number, startAfter?: [string, string], ): Promise { - return this.nyxdQuerier.getAllNetworkDelegationsPaged(mixnetContractAddress, limit, startAfter); + return this.getAllDelegationsPaged(mixnetContractAddress, limit, startAfter); + } + + getUnbondedMixNodes( + mixnetContractAddress: string, + limit?: number, + startAfter?: string, + ): Promise { + return this.nyxdQuerier.getUnbondedMixNodes(mixnetContractAddress, limit, startAfter); } getMixNodeDelegationsPaged( mixnetContractAddress: string, - mixIdentity: string, + mix_id: number, limit?: number, startAfter?: string, ): Promise { - return this.nyxdQuerier.getMixNodeDelegationsPaged(mixnetContractAddress, mixIdentity, limit, startAfter); + return this.nyxdQuerier.getMixNodeDelegationsPaged(mixnetContractAddress, mix_id, limit, startAfter); } getDelegatorDelegationsPaged( @@ -284,36 +324,16 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig return this.nyxdQuerier.getDelegatorDelegationsPaged(mixnetContractAddress, delegator, limit, startAfter); } - getDelegationDetails(mixnetContractAddress: string, mixIdentity: string, delegator: string): Promise { - return this.nyxdQuerier.getDelegationDetails(mixnetContractAddress, mixIdentity, delegator); + getDelegationDetails(mixnetContractAddress: string, mix_id: number, delegator: string): Promise { + return this.nyxdQuerier.getDelegationDetails(mixnetContractAddress, mix_id, delegator); } getLayerDistribution(mixnetContractAddress: string): Promise { return this.nyxdQuerier.getLayerDistribution(mixnetContractAddress); } - getRewardPool(mixnetContractAddress: string): Promise { - return this.nyxdQuerier.getRewardPool(mixnetContractAddress); - } - - getCirculatingSupply(mixnetContractAddress: string): Promise { - return this.nyxdQuerier.getCirculatingSupply(mixnetContractAddress); - } - - getIntervalRewardPercent(mixnetContractAddress: string): Promise { - return this.nyxdQuerier.getIntervalRewardPercent(mixnetContractAddress); - } - - getSybilResistancePercent(mixnetContractAddress: string): Promise { - return this.nyxdQuerier.getSybilResistancePercent(mixnetContractAddress); - } - - getRewardingStatus( - mixnetContractAddress: string, - mixIdentity: string, - rewardingIntervalNonce: number, - ): Promise { - return this.nyxdQuerier.getRewardingStatus(mixnetContractAddress, mixIdentity, rewardingIntervalNonce); + getRewardParams(mixnetContractAddress: string): Promise { + return this.nyxdQuerier.getRewardParams(mixnetContractAddress); } getCachedGateways(): Promise { @@ -324,7 +344,7 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig return this.nymApiQuerier.getCachedMixnodes(); } - getActiveMixnodes(): Promise { + getActiveMixnodes(): Promise { return this.nymApiQuerier.getActiveMixnodes(); } @@ -332,11 +352,16 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig return this.nymApiQuerier.getRewardedMixnodes(); } + getSpendableCoins(vestingContractAddress: string, vestingAccountAddress: string): Promise { + return this.nyxdQuerier.getSpendableCoins(vestingContractAddress, vestingAccountAddress); + } + // signing related: bondMixNode( mixnetContractAddress: string, mixNode: MixNode, + costParams: MixNodeCostParams, ownerSignature: string, pledge: Coin, fee: StdFee | 'auto' | number = 'auto', @@ -348,6 +373,7 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig { bond_mixnode: { mix_node: mixNode, + cost_params: costParams, owner_signature: ownerSignature, }, }, @@ -414,7 +440,7 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig delegateToMixNode( mixnetContractAddress: string, - mixIdentity: string, + mixId: number, amount: Coin, fee: StdFee | 'auto' | number = 'auto', memo = 'Default MixNode Delegation from Typescript', @@ -424,7 +450,7 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig mixnetContractAddress, { delegate_to_mixnode: { - mix_identity: mixIdentity, + mix_id: mixId, }, }, fee, @@ -435,7 +461,7 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig undelegateFromMixNode( mixnetContractAddress: string, - mixIdentity: string, + mixId: number, fee: StdFee | 'auto' | number = 'auto', memo = 'Default MixNode Undelegation from Typescript', ): Promise { @@ -444,7 +470,7 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig mixnetContractAddress, { undelegate_from_mixnode: { - mix_identity: mixIdentity, + mix_id: mixId, }, }, fee, @@ -454,14 +480,14 @@ export default class SigningClient extends SigningCosmWasmClient implements ISig updateMixnodeConfig( mixnetContractAddress: string, - mixIdentity: string, + mixId: number, profitMarginPercent: number, fee: StdFee | 'auto' | number, ): Promise { return this.execute( this.clientAddress, mixnetContractAddress, - { update_mixnode_config: { profit_margin_percent: profitMarginPercent, mix_identity: mixIdentity } }, + { update_mixnode_config: { profit_margin_percent: profitMarginPercent, mix_id: mixId } }, fee, ); } diff --git a/clients/validator/src/tests/expectedResponses.ts b/clients/validator/src/tests/expectedResponses.ts new file mode 100644 index 0000000000..876f61e866 --- /dev/null +++ b/clients/validator/src/tests/expectedResponses.ts @@ -0,0 +1,178 @@ +import expect from 'expect'; + +export const amountDemon = { + amount: expect.any(String), + denom: expect.any(String) +} + +export const delegation = { + owner: expect.any(String), + mix_id: expect.any(Number), + cumulative_reward_ratio: expect.any(String), + amount: amountDemon, + height: expect.any(Number || BigInt), + proxy: expect.any(String || null) +} + +export const detailedDelegation = { + delegation: delegation, + mixnode_still_bonded: expect.any(Boolean) +} + +export const gateway = { + pledge_amount: amountDemon, + owner: expect.any(String), + block_height: expect.any(Number || BigInt), + gateway: { + host: expect.any(String), + mix_port: expect.any(Number), + clients_port: expect.any(Number), + location: expect.any(String), + sphinx_key: expect.any(String), + identity_key: expect.any(String), + version: expect.any(String), + }, + proxy: expect.any(String || null) +} + +export const pagedGateway = { + nodes: gateway, + per_page: expect.any(Number), + start_next_after: expect.any(Number) +} + +export const ownGateway = { + address: expect.any(String), + gateway: gateway +} + +export const rewardingdetails = { + cost_params: { + profit_margin_percent: expect.any(String), + interval_operating_cost: { + denom: expect.any(String), + amount: expect.any(String) + } + }, + operator: expect.any(String), + delegates: expect.any(String), + total_unit_reward: expect.any(String), + unit_delegation: expect.any(String), + last_rewarded_epoch: expect.any(Number), + unique_delegations: expect.any(Number) +} + +export const mix_node = { + host: expect.any(String), + mix_port: expect.any(Number), + verloc_port: expect.any(Number), + http_api_port: expect.any(Number), + sphinx_key: expect.any(String), + identity_key: expect.any(String), + version: expect.any(String) +} + +export const mixnodebond = { + mix_id: expect.any(Number), + owner: expect.any(String), + original_pledge: { + denom: expect.any(String), + amount: expect.any(String) + }, + layer: expect.any(String), + mix_node: mix_node, + proxy: expect.any(String) || null, + bonding_height: expect.any(Number || BigInt), + is_unbonding: expect.any(Boolean) +} + +export const mixnode = { + bond_information: mixnodebond, + rewarding_details: rewardingdetails +} + +export const ownedNode = { + address: expect.any(String), + mixnode_details: { + bond_information: mixnodebond, + rewarding_details: rewardingdetails + } +} + +export const saturation = { + mix_id: expect.any(Number), + current_saturation: expect.any(String), + uncapped_saturation: expect.any(String) +} + +export const contractVersion = { + build_timestamp: expect.any(String), + build_version: expect.any(String), + commit_sha: expect.any(String), + commit_timestamp: expect.any(String), + commit_branch: expect.any(String), + rustc_version: expect.any(String) +}; + +export const stateParams = { + minimum_gateway_pledge: amountDemon, + minimum_mixnode_pledge: expect.any(String), + mixnode_rewarded_set_size: expect.any(Number), + mixnode_active_set_size: expect.any(Number) +} + +export const contract = { + owner: expect.any(Number), + rewarding_validator_address: expect.any(Number), + vesting_contract_address: expect.any(Number), + rewarding_denom: expect.any(String), + params: stateParams +} + +export const rewardingnode = { + mix_id: expect.any(Number), + rewarding_details: rewardingdetails +} + +export const unbondednode = { + mix_id: expect.any(Number), + unbonded_info: { + identity_key: expect.any(String), + owner: expect.any(String), + proxy: expect.any(String) || null, + unbonding_height: expect.any(Number) + } +} + +export const allunbondednodes = [ + expect.any(Number), { + identity_key: expect.any(String), + owner: expect.any(String), + proxy: expect.any(String) || null, + unbonding_height: expect.any(Number) + } +] + +export const layerDistribution = { + layer1: expect.any(Number), + layer2: expect.any(Number), + layer3: expect.any(Number) +} + + +export const intervalRewardParams = { + reward_pool: expect.any(Number), + staking_supply: expect.any(Number), + staking_supply_scale_factor: expect.any(Number), + epoch_reward_budget: expect.any(Number), + stake_saturation_point: expect.any(Number), + sybil_resistance: expect.any(Number), + active_set_work_factor: expect.any(Number), + interval_pool_emission: expect.any(Number) +} + +export const rewardingParams = { + interval: intervalRewardParams, + rewarded_set_size: expect.any(Number), + active_set_size: expect.any(Number) +} diff --git a/clients/validator/src/tests/mock/client.ts b/clients/validator/src/tests/mock/client.ts new file mode 100644 index 0000000000..c5633d2ed0 --- /dev/null +++ b/clients/validator/src/tests/mock/client.ts @@ -0,0 +1,19 @@ +import { Mock, Times } from 'moq.ts'; +import expect from 'expect'; +import { INyxdQuery } from '../../query-client'; + +export class TestHelper { + buildMethod = async (methodName: string, args: any[], expectedResult: any): Promise => { + const client = new Mock() + .setup((nym) => nym[methodName](...args)) + .returns(Promise.resolve(expectedResult)); + const obj = client.object(); + const actualDetails = await obj[methodName](...args); + + client.verify((nym) => nym[methodName](...args), Times.Exactly(1)); + expect(Object.keys([actualDetails])).toEqual(Object.keys(expectedResult)); + expect(actualDetails).toBeDefined(); + + return actualDetails; + }; +} diff --git a/clients/validator/src/tests/mock/delegation.mock.test.ts b/clients/validator/src/tests/mock/delegation.mock.test.ts new file mode 100644 index 0000000000..69fffcc53b --- /dev/null +++ b/clients/validator/src/tests/mock/delegation.mock.test.ts @@ -0,0 +1,40 @@ +import expect from 'expect'; +import { Delegation } from '@nymproject/types'; +import { PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse } from '../../types/shared-types'; +import { TestHelper } from './client'; +import { mixnet, mixnodeowneraddress, mix_id } from './testData'; + +describe('Delegation mock tests', () => { + const testHelper = new TestHelper(); + + it('get Delegation Details', () => { + const execute = testHelper.buildMethod('getDelegationDetails', [mixnet, mix_id, mixnodeowneraddress], { + owner: mixnodeowneraddress, + mix_id: 0, + cumulative_reward_ratio: '', + amount: { + denom: 'nym', + amount: '10', + }, + height: 1314134144132n, + proxy: 'null', + }); + expect(execute).toBeTruthy(); + }); + + it('get All Delegations Paged', () => { + const execute = testHelper.buildMethod('getAllDelegationsPaged', [mixnet], { + delegations: [], + }); + expect(execute).toBeTruthy(); + }); + + it('get Delegator Delegations Paged', () => { + const execute = testHelper.buildMethod('getDelegatorDelegationsPaged', [mixnet, mixnodeowneraddress], < + PagedDelegatorDelegationsResponse + >{ + delegations: [], + }); + expect(execute).toBeTruthy(); + }); +}); diff --git a/clients/validator/src/tests/mock/gateway.mock.test.ts b/clients/validator/src/tests/mock/gateway.mock.test.ts new file mode 100644 index 0000000000..5c7f277a41 --- /dev/null +++ b/clients/validator/src/tests/mock/gateway.mock.test.ts @@ -0,0 +1,24 @@ +import expect from 'expect'; +import { GatewayOwnershipResponse, PagedGatewayResponse } from '../../types/shared-types'; +import { TestHelper } from './client'; +import { gatewayowneraddress, mixnet } from './testData'; + +describe('Gateway mock tests', () => { + const testHelper = new TestHelper(); + + it('get Gateways Paged', () => { + const execute = testHelper.buildMethod('getGatewaysPaged', [mixnet], { + nodes: [], + per_page: 25, + }); + expect(execute).toBeTruthy(); + }); + + it('owns Gateway', () => { + const execute = testHelper.buildMethod('ownsGateway', [mixnet, gatewayowneraddress], { + address: gatewayowneraddress, + gateway: {}, + }); + expect(execute).toBeTruthy(); + }); +}); diff --git a/clients/validator/src/tests/mock/mixnet.mock.test.ts b/clients/validator/src/tests/mock/mixnet.mock.test.ts new file mode 100644 index 0000000000..8d84d4eecc --- /dev/null +++ b/clients/validator/src/tests/mock/mixnet.mock.test.ts @@ -0,0 +1,65 @@ +import expect from 'expect'; +import { LayerDistribution, MixnetContractVersion, StakeSaturationResponse } from '@nymproject/types'; +import { TestHelper } from './client'; +import { mixnet, mix_id } from './testData'; +import { RewardingParams } from '@nymproject/types'; +import { ContractState } from '../../types/shared'; + +describe('Mixnet mock tests', () => { + const testHelper = new TestHelper(); + + it('get Layer Distribution', () => { + const execute = testHelper.buildMethod('getLayerDistribution', [mixnet], { + layer1: 2, + layer2: 2, + layer3: 5, + }); + expect(execute).toBeTruthy(); + }); + + it('get Reward Params', () => { + const execute = testHelper.buildMethod('getRewardParams', [mixnet], { + interval: {}, + rewarded_set_size: 0, + active_set_size: 0, + }); + expect(execute).toBeTruthy(); + }); + + it('get Stake Saturation', () => { + const execute = testHelper.buildMethod('getStakeSaturation', [mixnet, mix_id], { + mix_id: 0, + current_saturation: '', + uncapped_saturation: '', + }); + expect(execute).toBeTruthy(); + }); + + it('get State Params', () => { + const execute = testHelper.buildMethod('getStateParams', [mixnet], { + owner: '', + rewarding_validator_address: '', + vesting_contract_address: '', + rewarding_denom: 'unym', + params: { + minimum_mixnode_pledge: '', + minimum_gateway_pledge: '', + mixnode_rewarded_set_size: 240, + mixnode_active_set_size: 240, + }, + }); + expect(execute).toBeTruthy(); + }); + + it('get Contract Version', () => { + const execute = testHelper.buildMethod('getContractVersion', [mixnet], { + build_timestamp: 'test', + commit_branch: 'test', + build_version: 'test', + rustc_version: 'test', + commit_sha: 'test', + commit_timestamp: 'test', + }); + expect(execute).toBeTruthy(); + }); +}); diff --git a/clients/validator/src/tests/mock/mixnode.mock.test.ts b/clients/validator/src/tests/mock/mixnode.mock.test.ts new file mode 100644 index 0000000000..c4d9e4519b --- /dev/null +++ b/clients/validator/src/tests/mock/mixnode.mock.test.ts @@ -0,0 +1,71 @@ +import expect from 'expect'; +import { + MixNodeRewarding, + MixOwnershipResponse, + PagedMixDelegationsResponse, + PagedMixNodeBondResponse, + PagedMixNodeDetailsResponse, + UnbondedMixnodeResponse, +} from '@nymproject/types'; +import { TestHelper } from './client'; +import { mixnet, mixnodeowneraddress, mix_id } from './testData'; + +describe('Mixnode mock tests', () => { + const testHelper = new TestHelper(); + + it('get Mixnode Bonds', () => { + const execute = testHelper.buildMethod('getMixNodeBonds', [mixnet], { + nodes: [], + per_page: 25, + }); + expect(execute).toBeTruthy(); + }); + + it('get Mixnode Delegations Paged', () => { + const execute = testHelper.buildMethod('getMixNodeDelegationsPaged', [mixnet, mix_id], < + PagedMixDelegationsResponse + >{ + delegations: [], + per_page: 25, + }); + expect(execute).toBeTruthy(); + }); + + it('get Mixnodes Detailed', () => { + const execute = testHelper.buildMethod('getMixNodesDetailed', [mixnet], { + nodes: [], + per_page: 25, + }); + expect(execute).toBeTruthy(); + }); + + it('get Mixnode Rewarding Details', () => { + const execute = testHelper.buildMethod('getMixnodeRewardingDetails', [mixnet, mix_id], { + cost_params: {}, + operator: '', + delegates: '', + total_unit_reward: '', + unit_delegation: '', + last_rewarded_epoch: 1, + unique_delegations: 1, + }); + expect(execute).toBeTruthy(); + }); + + it('get Owned Mixnode', () => { + const execute = testHelper.buildMethod('getOwnedMixnode', [mixnet, mixnodeowneraddress], { + address: '', + mixnode: {}, + }); + expect(execute).toBeTruthy(); + }); + + it('get Unbonded Mixnode Information', () => { + const execute = testHelper.buildMethod( + 'getUnbondedMixNodeInformation', + [mixnet, mix_id], + {}, + ); + expect(execute).toBeTruthy(); + }); +}); diff --git a/clients/validator/src/tests/mock/testData.ts b/clients/validator/src/tests/mock/testData.ts new file mode 100644 index 0000000000..28df1557f7 --- /dev/null +++ b/clients/validator/src/tests/mock/testData.ts @@ -0,0 +1,8 @@ +export const mixnet = 'n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g'; +export const gatewayowneraddress = 'n16evnn8glr0sham3matj8rg2s24m6x56ayk87ts'; +// export const mixId = 436207616; +export const mix_id = 26; +export const nodeIdentityKey = 'ATmVJknZarDF6Yj53M7h8NS9LLCUvWuToXpk3pDvYUH1'; +export const mixnodeowneraddress = 'n1fzv4jc7fanl9s0qj02ge2ezk3kts545kjtek47'; +export const delegatorAddress = 'n1lemst75va9700tsrxq58adzujrh6h9s5x60h9h'; +export const rewardingIntervalNonce = 1; diff --git a/clients/validator/src/tests/query/mixnetQueries.test.ts b/clients/validator/src/tests/query/mixnetQueries.test.ts new file mode 100644 index 0000000000..391f8aaf0d --- /dev/null +++ b/clients/validator/src/tests/query/mixnetQueries.test.ts @@ -0,0 +1,180 @@ +import expect from 'expect'; +import ValidatorClient from '../../index'; + +import { + allunbondednodes, + contract, + delegation, + gateway, + layerDistribution, + mixnode, + mixnodebond, + ownedNode, + ownGateway, + rewardingnode, + saturation, + unbondednode, +} from '../expectedResponses'; +import { delegatorAddress, gatewayowneraddress } from '../mock/testData'; + +const dotenv = require('dotenv'); + +dotenv.config(); + +describe('Mixnet queries', () => { + let client: ValidatorClient; + + beforeEach(async () => { + client = await ValidatorClient.connectForQuery( + process.env.rpcAddress || '', + process.env.validatorAddress || '', + process.env.prefix || '', + process.env.mixnetContractAddress || '', + process.env.vestingContractAddress || '', + process.env.denom || '', + ); + }); + + // + // CONTRACT + // + + it('can query for an account balance', async () => { + const balance = await client.getBalance('n1ptg680vnmef2cd8l0s9uyc4f0hgf3x8sed6w77'); + expect(Number.parseFloat(balance.amount)).toBeGreaterThan(0); + }); + + it('can query for stake saturation', async () => { + const stakeSaturation = await client.getStakeSaturation(7); + expect(Object.keys(stakeSaturation)).toEqual(Object.keys(saturation)); + expect(stakeSaturation).toBeTruthy(); + expect(stakeSaturation?.current_saturation).toBeTruthy(); + }); + + it('can query for contract version', async () => { + const contractV = await client.getMixnetContractVersion(); + expect(contractV).toBeTruthy(); + }); + + it('can query for mixnet contract settings', async () => { + const settings = await client.getMixnetContractSettings(); + expect(Object.keys(settings)).toEqual(Object.keys(contract)); + expect(settings).toBeTruthy(); + }); + + it('can query for reward pool', async () => { + const rewardPool = await client.getRewardParams(); + // TODO add velidation here + expect(rewardPool).toBeTruthy(); + }); + + it('can query for layer distribution', async () => { + const layer = await client.getLayerDistribution(); + expect(Object.keys(layer)).toEqual(Object.keys(layerDistribution)); + expect(layer).toBeTruthy(); + }); + + // + // MIXNODES + // + + it('can query for unbonded mixnodes', async () => { + const unbondedNodes = await client.getUnbondedMixNodes(); + for (let i = 0; i < unbondedNodes.length; i++) { + expect(Object.keys(unbondedNodes[0])).toEqual(Object.keys(allunbondednodes)); + expect(unbondedNodes).toBeTruthy(); + } + }); + + it('can query for unbonded mixnode information', async () => { + const unbondedMixnodeInfo = await client.getUnbondedMixNodeInformation(1); + expect(Object.keys(unbondedMixnodeInfo)).toEqual(Object.keys(unbondednode)); + expect(unbondedMixnodeInfo).toBeTruthy(); + }); + + it('can query for mixnode rewarding details', async () => { + const rewardingDetails = await client.getMixnodeRewardingDetails(1); + expect(Object.keys(rewardingDetails)).toEqual(Object.keys(rewardingnode)); + expect(rewardingDetails).toBeTruthy(); + }); + + it('can query for owned mixnode', async () => { + const ownedMixnode = await client.getOwnedMixnode('n1ptg680vnmef2cd8l0s9uyc4f0hgf3x8sed6w77'); + expect(Object.keys(ownedMixnode)).toEqual(Object.keys(ownedNode)); + expect(ownedMixnode).toBeTruthy(); + }); + + it('can query for all mixnode bonds', async () => { + const mixnodeBonds = await client.getMixNodeBonds(); + expect(Object.keys(mixnodeBonds[0])).toEqual(Object.keys(mixnodebond)); + expect(mixnodeBonds).toBeTruthy(); + expect(Array.isArray(mixnodeBonds)).toBeTruthy(); + }); + + it('can query for all mixnode details', async () => { + const mixnodeDetails = await client.getMixNodesDetailed(); + expect(Object.keys(mixnodeDetails[0])).toEqual(Object.keys(mixnode)); + expect(mixnodeDetails).toBeTruthy(); + expect(Array.isArray(mixnodeDetails)).toBeTruthy(); + }); + + it('can query for all active mixnodes', async () => { + const activeNodes = await client.getActiveMixnodes(); + expect(Object.keys(activeNodes[0])).toEqual(Object.keys(mixnode)); + expect(activeNodes).toBeTruthy(); + expect(Array.isArray(activeNodes)).toBeTruthy(); + }); + + it('can query for rewarded mixnodes', async () => { + const rewardNodes = await client.getRewardedMixnodes(); + expect(Object.keys(rewardNodes[0])).toEqual(Object.keys(mixnode)); + expect(rewardNodes).toBeTruthy(); + }); + + // + // DELEGATIONS + // + + it('can query for account delegations', async () => { + const delegations = await client.getAllNyxdDelegatorDelegations('n1fzv4jc7fanl9s0qj02ge2ezk3kts545kjtek47'); + expect(Object.keys(delegations[0])).toEqual(Object.keys(delegation)); + expect(delegations).toBeTruthy(); + expect(Array.isArray(delegations)).toBeTruthy(); + }); + + it('can query for all delegations', async () => { + const allDelegations = await client.getAllNyxdDelegations(); + expect(Object.keys(allDelegations[0])).toEqual(Object.keys(delegation)); + expect(allDelegations).toBeTruthy(); + expect(Array.isArray(allDelegations)).toBeTruthy(); + }); + + it('can query for all delegations on a node', async () => { + const mixnodeDelegations = await client.getAllNyxdSingleMixnodeDelegations(1); + expect(Object.keys(mixnodeDelegations[0])).toEqual(Object.keys(delegation)); + expect(mixnodeDelegations).toBeTruthy(); + }); + + it('can query for detailed delegations', async () => { + const detailedDelegation = await client.getDelegationDetails(7, delegatorAddress); + expect(Object.keys(detailedDelegation)).toEqual(Object.keys(detailedDelegation)); + expect(detailedDelegation).toBeTruthy(); + }); + + // + // GATEWAYS + // + + it('can query for all gateways', async () => { + const gateways = await client.getAllNyxdGateways(); + expect(Object.keys(gateways[0])).toEqual(Object.keys(gateway)); + expect(gateways).toBeTruthy(); + expect(Array.isArray(gateways)).toBeTruthy(); + }).timeout(10000); + + it('can query for owned gateway', async () => { + const gateway = await client.ownsGateway(gatewayowneraddress); + expect(Object.keys(gateway)).toEqual(Object.keys(ownGateway)); + expect(gateway).toBeTruthy(); + }).timeout(10000); +}); diff --git a/clients/validator/src/tests/query/vestingQueries.test.ts b/clients/validator/src/tests/query/vestingQueries.test.ts new file mode 100644 index 0000000000..2cbe4f5088 --- /dev/null +++ b/clients/validator/src/tests/query/vestingQueries.test.ts @@ -0,0 +1,28 @@ +import expect from 'expect'; +import ValidatorClient from '../../index'; + +const dotenv = require('dotenv'); + +dotenv.config(); + +describe('Vesting queries', () => { + let client: ValidatorClient; + + beforeEach(async () => { + client = await ValidatorClient.connectForQuery( + process.env.rpcAddress || '', + process.env.validatorAddress || '', + process.env.prefix || '', + process.env.mixnetContractAddress || '', + process.env.vestingContractAddress || '', + process.env.denom || '', + ); + }); + + it('can query for contract version', async () => { + const contract = await client.getVestingContractVersion(); + expect(contract).toBeTruthy(); + }); + + it('can get the balance on the account', () => {}); +}); diff --git a/clients/validator/src/tests/sign/mixnetActions.test.ts b/clients/validator/src/tests/sign/mixnetActions.test.ts new file mode 100644 index 0000000000..1b535f6f2d --- /dev/null +++ b/clients/validator/src/tests/sign/mixnetActions.test.ts @@ -0,0 +1,107 @@ +import expect from 'expect'; +import ValidatorClient from '../../'; + +const dotenv = require('dotenv'); + +dotenv.config(); + +// TODO: implement for QA with .env for mnemonics +describe('Mixnet actions', () => { + let client: ValidatorClient; + + beforeEach(async () => { + client = await ValidatorClient.connect( + process.env.mnemonic || '', + process.env.rpcAddress || '', + process.env.validatorAddress || '', + process.env.prefix || '', + process.env.mixnetContractAddress || '', + process.env.vestingContractAddress || '', + process.env.denom || '', + ); + }); + + it('can send tokens', async () => { + const res = await client.send(client.address, [{ amount: '10000000', denom: 'unym' }]); + expect(res.transactionHash).toBeDefined(); + }).timeout(10000); + + it.skip('can delegate tokens', async () => { + const [_, secondMixnode] = await client.getActiveMixnodes(); + + if (secondMixnode) { + const res = await client.delegateToMixNode( + secondMixnode.bond_information.mix_id, + { + amount: '15000000', + denom: 'unym', + }, + { gas: '1000000', amount: [{ amount: '100000', denom: 'unym' }] }, + ); + expect(res.transactionHash).toBeDefined(); + } + }).timeout(10000); + + // Need to provide a mix id that can be undelegated from + it.skip('can undelegate from a mixnode', async () => { + const mixId = 8; + const res = await client.undelegateFromMixNode(mixId); + expect(res.transactionHash).toBeDefined(); + }); + + it.skip('Can unbond a mixnode', async () => { + const res = await client.unbondMixNode(); + expect(res.transactionHash).toBeDefined(); + }).timeout(10000); + + it.skip('Can bond a mixnode', async () => { + const res = await client.bondMixNode( + { + identity_key: '3P6pAcF2p3pYMqWdpHqhbavu3ifyaBs5Qw5UmmCGwimx', + sphinx_key: 'GQMQKwUThaggatA6oZteSWTsCQoUfmLtamJ7o9YkP9aE', + host: '109.74.195.67', + mix_port: 1789, + verloc_port: 1790, + http_api_port: 8000, + version: '1.1.4', + }, + '3rXWCQBUj5JQB3UBUkZcXhCk9Zh3cjduMF8aFHPTG7KTkkhZzDJTNmE2p2Ph1g6iQW5vRGTpQzjXF33WDwvhzHk6', + { profit_margin_percent: '0.1', interval_operating_cost: { amount: '40', denom: 'nym' } }, + { amount: '100_000_000', denom: 'unym' }, + { gas: '1000000', amount: [{ amount: '100000', denom: 'unym' }] }, + ); + expect(res.transactionHash).toBeDefined(); + }).timeout(10000); + + it.skip('can unbond a gateway', async () => { + const res = await client.unbondGateway(); + expect(res.transactionHash).toBeDefined(); + }); + + it.skip('can bond a gateway', async () => { + const res = await client.bondGateway( + { + identity_key: '36vfvEyBzo5cWEFbnP7fqgY39kFw9PQhvwzbispeNaxL', + sphinx_key: 'G65Fwc2JNAotuHQFqmDKhQNQL5rn3r9pupUdmxMygNUZ', + host: '151.236.220.82', + version: '1.1.4', + mix_port: 1789, + clients_port: 9000, + location: 'Cuba', + }, + '3ipSJksWHehZm1YfuH5Ahtg7b22NnrP9hEs6iEDXfUS5uiUhpWmCjGR3b3NDHuxeGjpZYJNYJ52D8WCPK5ZR7Szj', + { amount: '100_000_000', denom: 'unym' }, + ); + expect(res.transactionHash).toBeDefined(); + }); + + it.skip('can update contract state params', async () => { + const res = await client.updateContractStateParams({ + minimum_mixnode_pledge: '', + minimum_gateway_pledge: '', + mixnode_rewarded_set_size: 2, + mixnode_active_set_size: 2, + }); + expect(res.transactionHash).toBeDefined(); + }); +}); diff --git a/clients/validator/src/tsconfig.json b/clients/validator/src/tsconfig.json deleted file mode 100644 index 7990d8ef90..0000000000 --- a/clients/validator/src/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - "target": "es6", - "module": "commonjs", - "esModuleInterop": true, - "strict": true, - "declaration": true, - "outDir": "./dist" - }, - "exclude": [ - "tests", - "dist", - "node_modules" - ] -} \ No newline at end of file diff --git a/clients/validator/src/types.ts b/clients/validator/src/types.ts deleted file mode 100644 index 575702ec45..0000000000 --- a/clients/validator/src/types.ts +++ /dev/null @@ -1,157 +0,0 @@ -import { Coin } from '@cosmjs/stargate'; - -// TODO: ideally we'd have re-exported those using that fancy crate that builds ts types from rust - -export type MixnetContractVersion = { - build_timestamp: string; - build_version: string; - commit_sha: string; - commit_timestamp: string; - commit_branch: string; - rustc_version: string; -}; - -export type PagedMixnodeResponse = { - nodes: MixNodeBond[]; - per_page: number; - start_next_after?: string; -}; - -export type PagedGatewayResponse = { - nodes: GatewayBond[]; - per_page: number; - start_next_after?: string; -}; - -export type MixOwnershipResponse = { - address: string; - mixnode?: MixNodeBond; -}; - -export type GatewayOwnershipResponse = { - address: string; - gateway?: GatewayBond; -}; - -export type ContractStateParams = { - // ideally I'd want to define those as `number` rather than `string`, but - // rust-side they are defined as Uint128 and that don't have - // native javascript representations and therefore are interpreted as strings after deserialization - minimum_mixnode_pledge: string; - minimum_gateway_pledge: string; - mixnode_rewarded_set_size: number; - mixnode_active_set_size: number; -}; - -export type LayerDistribution = { - gateways: number; - layer1: number; - layer2: number; - layer3: number; -}; - -export type Delegation = { - owner: string; - node_identity: string; - amount: Coin; - block_height: number; - proxy?: string; -}; - -export type PagedMixDelegationsResponse = { - delegations: Delegation[]; - start_next_after?: string; -}; - -export type PagedDelegatorDelegationsResponse = { - delegations: Delegation[]; - start_next_after?: string; -}; - -export type PagedAllDelegationsResponse = { - delegations: Delegation[]; - start_next_after?: [string, string]; -}; - -export type RewardingResult = { - operator_reward: string; - total_delegator_reward: string; -}; - -export type NodeRewardParams = { - period_reward_pool: string; - k: string; - reward_blockstamp: number; - circulating_supply: string; - uptime: string; - sybil_resistance_percent: number; -}; - -export type DelegatorRewardParams = { - node_reward_params: NodeRewardParams; - sigma: number; - profit_margin: number; - node_profit: number; -}; - -export type PendingDelegatorRewarding = { - running_results: RewardingResult; - next_start: string; - rewarding_params: DelegatorRewardParams; -}; - -export type RewardingStatus = { Complete: RewardingResult } | { PendingNextDelegatorPage: PendingDelegatorRewarding }; - -export type MixnodeRewardingStatusResponse = { - status?: RewardingStatus; -}; - -export enum Layer { - Gateway, - One, - Two, - Three, -} - -export type MixNodeBond = { - owner: string; - mix_node: MixNode; - layer: Layer; - bond_amount: Coin; - total_delegation: Coin; -}; - -export type MixNode = { - host: string; - mix_port: number; - verloc_port: number; - http_api_port: number; - sphinx_key: string; - identity_key: string; - version: string; - profit_margin_percent: number; -}; - -export type GatewayBond = { - owner: string; - gateway: Gateway; - - bond_amount: Coin; - total_delegation: Coin; -}; - -export type Gateway = { - host: string; - mix_port: number; - clients_port: number; - location: string; - sphinx_key: string; - identity_key: string; - version: string; -}; - -export type SendRequest = { - senderAddress: string; - recipientAddress: string; - transferAmount: readonly Coin[]; -}; diff --git a/clients/validator/src/types/global.d.ts b/clients/validator/src/types/global.d.ts new file mode 100644 index 0000000000..a6eb7c3521 --- /dev/null +++ b/clients/validator/src/types/global.d.ts @@ -0,0 +1,11 @@ +declare namespace NodeJS { + interface ProcessEnv { + rpcAddress: string; + validatorAddress: string; + prefix: string; + mixnetContractAddress: string; + vestingContractAddress: string; + denom: string; + mnemonic: string; + } +} diff --git a/clients/validator/src/types/shared.ts b/clients/validator/src/types/shared.ts new file mode 100644 index 0000000000..d8db5ad0e5 --- /dev/null +++ b/clients/validator/src/types/shared.ts @@ -0,0 +1,259 @@ +import { JsonObject } from '@cosmjs/cosmwasm-stargate'; +import { Code, CodeDetails, Contract, ContractCodeHistoryEntry } from '@cosmjs/cosmwasm-stargate/build/cosmwasmclient'; +import { + Account, + Block, + Coin, + DeliverTxResponse, + IndexedTx, + SearchTxFilter, + SearchTxQuery, + SequenceResponse, +} from '@cosmjs/stargate'; +import { + MixNodeRewarding, + PagedMixNodeBondResponse, + PagedMixNodeDetailsResponse, + StakeSaturationResponse, + UnbondedMixnodeResponse, +} from '@nymproject/types'; + +export type MixnetContractVersion = { + build_timestamp: string; + build_version: string; + commit_sha: string; + commit_timestamp: string; + commit_branch: string; + rustc_version: string; +}; + +export type PagedMixnodeResponse = { + nodes: MixNodeBond[]; + per_page: number; + start_next_after?: string; +}; + +export type PagedGatewayResponse = { + nodes: GatewayBond[]; + per_page: number; + start_next_after?: string; +}; + +export type MixOwnershipResponse = { + address: string; + mixnode?: MixNodeBond; +}; + +export type GatewayOwnershipResponse = { + address: string; + gateway?: GatewayBond; +}; + +export type ContractStateParams = { + // ideally I'd want to define those as `number` rather than `string`, but + // rust-side they are defined as Uint128 and that don't have + // native javascript representations and therefore are interpreted as strings after deserialization + minimum_mixnode_pledge: string; + minimum_gateway_pledge: string; + mixnode_rewarded_set_size: number; + mixnode_active_set_size: number; +}; + +export type LayerDistribution = { + gateways: number; + layer1: number; + layer2: number; + layer3: number; +}; + +export type Delegation = { + owner: string; + node_identity: string; + amount: Coin; + block_height: number; + proxy?: string; +}; + +export type PagedMixDelegationsResponse = { + delegations: Delegation[]; + start_next_after?: string; +}; + +export type PagedDelegatorDelegationsResponse = { + delegations: Delegation[]; + start_next_after?: string; +}; + +export type PagedAllDelegationsResponse = { + delegations: Delegation[]; + start_next_after?: [string, string]; +}; + +export type RewardingResult = { + operator_reward: string; + total_delegator_reward: string; +}; + +export type NodeRewardParams = { + period_reward_pool: string; + k: string; + reward_blockstamp: number; + circulating_supply: string; + uptime: string; + sybil_resistance_percent: number; +}; + +export type DelegatorRewardParams = { + node_reward_params: NodeRewardParams; + sigma: number; + profit_margin: number; + node_profit: number; +}; + +export type PendingDelegatorRewarding = { + running_results: RewardingResult; + next_start: string; + rewarding_params: DelegatorRewardParams; +}; + +export type RewardingStatus = { Complete: RewardingResult } | { PendingNextDelegatorPage: PendingDelegatorRewarding }; + +export type MixnodeRewardingStatusResponse = { + status?: RewardingStatus; +}; + +export enum Layer { + Gateway, + One, + Two, + Three, +} + +export type MixNodeBond = { + owner: string; + mix_node: MixNode; + layer: Layer; + bond_amount: Coin; + total_delegation: Coin; +}; + +export type MixNode = { + host: string; + mix_port: number; + verloc_port: number; + http_api_port: number; + sphinx_key: string; + identity_key: string; + version: string; + profit_margin_percent: number; +}; + +export type GatewayBond = { + owner: string; + gateway: Gateway; + + bond_amount: Coin; + total_delegation: Coin; +}; + +export type Gateway = { + host: string; + mix_port: number; + clients_port: number; + location: string; + sphinx_key: string; + identity_key: string; + version: string; +}; + +export type SendRequest = { + senderAddress: string; + recipientAddress: string; + transferAmount: readonly Coin[]; +}; + +export interface SmartContractQuery { + queryContractSmart(address: string, queryMsg: Record): Promise; +} +export interface ICosmWasmQuery { + // methods exposed by `CosmWasmClient` + getChainId(): Promise; + getHeight(): Promise; + getAccount(searchAddress: string): Promise; + getSequence(address: string): Promise; + getBlock(height?: number): Promise; + getBalance(address: string, searchDenom: string): Promise; + getTx(id: string): Promise; + searchTx(query: SearchTxQuery, filter?: SearchTxFilter): Promise; + disconnect(): void; + broadcastTx(tx: Uint8Array, timeoutMs?: number, pollIntervalMs?: number): Promise; + getCodes(): Promise; + getCodeDetails(codeId: number): Promise; + getContracts(codeId: number): Promise; + getContract(address: string): Promise; + getContractCodeHistory(address: string): Promise; + queryContractRaw(address: string, key: Uint8Array): Promise; + queryContractSmart(address: string, queryMsg: Record): Promise; +} + +export interface INymdQuery { + // nym-specific implemented inside NymQuerier + getContractVersion(mixnetContractAddress: string): Promise; + getMixNodeBonds( + mixnetContractAddress: string, + limit?: number, + startAfter?: string, + ): Promise; + getMixNodesDetailed( + mixnetContractAddress: string, + limit?: number, + startAfter?: string, + ): Promise; + getGatewaysPaged(mixnetContractAddress: string, limit?: number, startAfter?: string): Promise; + getOwnedMixnode(mixnetContractAddress: string, address: string): Promise; + ownsGateway(mixnetContractAddress: string, address: string): Promise; + getStateParams(mixnetContractAddress: string): Promise; + getAllNetworkDelegationsPaged( + mixnetContractAddress: string, + limit?: number, + startAfter?: [string, string], + ): Promise; + getMixNodeDelegationsPaged( + mixnetContractAddress: string, + mix_id: number, + limit?: number, + startAfter?: string, + ): Promise; + getDelegatorDelegationsPaged( + mixnetContractAddress: string, + delegator: string, + limit?: number, + startAfter?: string, + ): Promise; + getDelegationDetails(mixnetContractAddress: string, mix_id: number, delegator: string): Promise; + getLayerDistribution(mixnetContractAddress: string): Promise; + getStakeSaturation(mixnetContractAddress: string, mixId: number): Promise; + getUnbondedMixNodeInformation(mixnetContractAddress: string, mixId: number): Promise; + getMixnodeRewardingDetails(mixnetContractAddress: string, mixId: number): Promise; +} + +export interface IVestingQuerier { + getVestingContractVersion(mixnetContractAddress: string): Promise; +} + +export interface MappedCoin { + readonly denom: string; + readonly fractionalDigits: number; +} + +export interface CoinMap { + readonly [key: string]: MappedCoin; +} + +export interface ContractState { + owner: string; + rewarding_validator_address: string; + vesting_contract_address: string; + rewarding_denom: string; + params: ContractStateParams; +} diff --git a/clients/validator/tests/query/balance.test.ts b/clients/validator/tests/query/balance.test.ts deleted file mode 100644 index 97be47c2ce..0000000000 --- a/clients/validator/tests/query/balance.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import ValidatorClient from '../../validator/index'; -import expect from 'expect'; - -describe('Query: balances', () => { - it('can query for an account balance', async () => { - const client = await ValidatorClient.connectForQuery( - 'https://rpc.nymtech.net/', 'https://validator.nymtech.net/api/', 'n', 'n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g', 'n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw', 'nym'); - const balance = await client.getBalance('n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy'); - expect(Number.parseFloat(balance.amount)).toBeGreaterThan(0); - }).timeout(5000); -}) diff --git a/clients/validator/tests/sign/send.test.ts b/clients/validator/tests/sign/send.test.ts deleted file mode 100644 index 197d5bd4ef..0000000000 --- a/clients/validator/tests/sign/send.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import ValidatorClient from '../../dist'; -import expect from 'expect'; - -// TODO: implement for QA with .env for mnemonics -// describe('Sign: send', () => { -// it('can send tokens', async () => { -// const client = await ValidatorClient.connect( -// '', -// 'https://rpc.nyx.nodes.guru/', 'https://validator.nymtech.net/api/', 'n', 'n14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9sjyvg3g', 'n1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrq73f2nw', 'nym'); -// await client.send('') -// const balance = await client.getBalance('n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy'); -// expect(Number.parseFloat(balance.amount)).toBeGreaterThan(0); -// }).timeout(5000); -// }) \ No newline at end of file diff --git a/clients/validator/tsconfig.json b/clients/validator/tsconfig.json index ec8e7c1fb0..0a2ce0f074 100644 --- a/clients/validator/tsconfig.json +++ b/clients/validator/tsconfig.json @@ -1,23 +1,22 @@ { - "compilerOptions": { - "target": "es6", - "module": "commonjs", - "esModuleInterop": true, - "strict": true, - "declaration": true, - "outDir": "./dist", - "skipLibCheck": true - }, - "typedocOptions": { - "entryPoints": [ - "src/index.ts" - ], - "out": "docs" - }, - "exclude": [ - "dist", - "examples", - "tests", - "node_modules" - ] -} \ No newline at end of file + "compilerOptions": { + "outDir": "./dist/nym-validator-client", + "module": "ES2020", + "target": "es2021", + "allowJs": false, + "strict": true, + "lib": ["es2021", "dom", "dom.iterable", "esnext"], + "moduleResolution": "node", + "skipDefaultLibCheck": true, + "esModuleInterop": true, + "declaration": true, + "skipLibCheck": true, + "noImplicitAny": true, + "typeRoots": ["./src/types/global.d.ts"] + }, + "typedocOptions": { + "entryPoints": ["./src/index.ts"], + "out": "docs" + }, + "exclude": ["dist", "./src/tests/**/*", "node_module"] +} diff --git a/clients/validator/tsconfig.test.json b/clients/validator/tsconfig.test.json new file mode 100644 index 0000000000..7048c297c8 --- /dev/null +++ b/clients/validator/tsconfig.test.json @@ -0,0 +1,6 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "CommonJS" + } +} diff --git a/ts-packages/types/src/types/global.ts b/ts-packages/types/src/types/global.ts index 1ec545138c..c949456494 100644 --- a/ts-packages/types/src/types/global.ts +++ b/ts-packages/types/src/types/global.ts @@ -1,4 +1,4 @@ -import { MixNode, DecCoin } from './rust'; +import { MixNode, DecCoin, GatewayBond, MixNodeBond, MixNodeDetails, Delegation, Coin, UnbondedMixnode } from './rust'; export type TNodeType = 'mixnode' | 'gateway'; @@ -29,3 +29,124 @@ export type TMixnodeBondDetails = { mix_node: MixNode; proxy: any; }; + +export type MixnetContractVersion = { + build_timestamp: string; + build_version: string; + commit_sha: string; + commit_timestamp: string; + commit_branch: string; + rustc_version: string; +}; + +export type PagedMixNodeBondResponse = { + nodes: MixNodeBond[]; + per_page: number; + start_next_after?: string; +}; + +export type PagedMixNodeDetailsResponse = { + nodes: MixNodeDetails[]; + per_page: number; + start_next_after?: string; +}; + +export type PagedGatewayResponse = { + nodes: GatewayBond[]; + per_page: number; + start_next_after?: string; +}; + +export type MixOwnershipResponse = { + address: string; + mixnode?: MixNodeBond; +}; + +export type GatewayOwnershipResponse = { + address: string; + gateway?: GatewayBond; +}; + +export type ContractStateParams = { + // ideally I'd want to define those as `number` rather than `string`, but + // rust-side they are defined as Uint128 and that don't have + // native javascript representations and therefore are interpreted as strings after deserialization + minimum_mixnode_pledge: string; + minimum_gateway_pledge: string; + mixnode_rewarded_set_size: number; + mixnode_active_set_size: number; +}; + +export type PagedMixDelegationsResponse = { + delegations: Delegation[]; + start_next_after?: string; +}; + +export type PagedDelegatorDelegationsResponse = { + delegations: Delegation[]; + start_next_after?: string; +}; + +export type PagedAllDelegationsResponse = { + delegations: Delegation[]; + start_next_after?: [string, string]; +}; + +export type RewardingResult = { + operator_reward: string; + total_delegator_reward: string; +}; + +export type NodeRewardParams = { + period_reward_pool: string; + k: string; + reward_blockstamp: number; + circulating_supply: string; + uptime: string; + sybil_resistance_percent: number; +}; + +export type DelegatorRewardParams = { + node_reward_params: NodeRewardParams; + sigma: number; + profit_margin: number; + node_profit: number; +}; + +export type PendingDelegatorRewarding = { + running_results: RewardingResult; + next_start: string; + rewarding_params: DelegatorRewardParams; +}; + +export type RewardingStatus = { Complete: RewardingResult } | { PendingNextDelegatorPage: PendingDelegatorRewarding }; + +export type MixnodeRewardingStatusResponse = { + status?: RewardingStatus; +}; + +export type SendRequest = { + senderAddress: string; + recipientAddress: string; + transferAmount: readonly Coin[]; +}; + +export type UnbondedMixnodeResponse = [mix_id: number, unbonded_info?: UnbondedMixnode]; + +export type PagedUnbondedMixnodesResponse = { + nodes: UnbondedMixnodeResponse[]; + per_page: number; + start_next_after: string; +}; + +export type MappedCoin = { + readonly denom: string; + readonly fractionalDigits: number; +}; + +export type LayerDistribution = { + gateways: number; + layer1: number; + layer2: number; + layer3: number; +}; diff --git a/yarn.lock b/yarn.lock index 72e807cd97..27522a4f8d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1205,16 +1205,6 @@ "@noble/hashes" "^1.0.0" protobufjs "^6.8.8" -"@cosmjs/amino@0.28.13": - version "0.28.13" - resolved "https://registry.yarnpkg.com/@cosmjs/amino/-/amino-0.28.13.tgz#b51417a23c1ff8ef8b85a6862eba8492c6c44f38" - integrity sha512-IHnH2zGwaY69qT4mVAavr/pfzx6YE+ud1NHJbvVePlbGiz68CXTi5LHR+K0lrKB5mQ7E+ZErWz2mw5U/x+V1wQ== - dependencies: - "@cosmjs/crypto" "0.28.13" - "@cosmjs/encoding" "0.28.13" - "@cosmjs/math" "0.28.13" - "@cosmjs/utils" "0.28.13" - "@cosmjs/amino@^0.25.6": version "0.25.6" resolved "https://registry.yarnpkg.com/@cosmjs/amino/-/amino-0.25.6.tgz#cdf9632253bfab7b1d2ef967124953d7bf16351f" @@ -1225,6 +1215,16 @@ "@cosmjs/math" "^0.25.6" "@cosmjs/utils" "^0.25.6" +"@cosmjs/amino@^0.29.5": + version "0.29.5" + resolved "https://registry.yarnpkg.com/@cosmjs/amino/-/amino-0.29.5.tgz#053b4739a90b15b9e2b781ccd484faf64bd49aec" + integrity sha512-Qo8jpC0BiziTSUqpkNatBcwtKNhCovUnFul9SlT/74JUCdLYaeG5hxr3q1cssQt++l4LvlcpF+OUXL48XjNjLw== + dependencies: + "@cosmjs/crypto" "^0.29.5" + "@cosmjs/encoding" "^0.29.5" + "@cosmjs/math" "^0.29.5" + "@cosmjs/utils" "^0.29.5" + "@cosmjs/cosmwasm-launchpad@^0.25.6": version "0.25.6" resolved "https://registry.yarnpkg.com/@cosmjs/cosmwasm-launchpad/-/cosmwasm-launchpad-0.25.6.tgz#b03a96c8d5b5b4742ec4c56b4a01b1f4f33f7f57" @@ -1255,36 +1255,23 @@ pako "^2.0.2" protobufjs "~6.10.2" -"@cosmjs/cosmwasm-stargate@^0.28.0": - version "0.28.13" - resolved "https://registry.yarnpkg.com/@cosmjs/cosmwasm-stargate/-/cosmwasm-stargate-0.28.13.tgz#bea77bc999aaafdb677f446465f648cd000c5b4a" - integrity sha512-dVZNOiRd8btQreRUabncGhVXGCS2wToXqxi9l3KEHwCJQ2RWTshuqV+EZAdCaYHE5W6823s2Ol2W/ukA9AXJPw== +"@cosmjs/cosmwasm-stargate@^0.29.5": + version "0.29.5" + resolved "https://registry.yarnpkg.com/@cosmjs/cosmwasm-stargate/-/cosmwasm-stargate-0.29.5.tgz#3f257da682658833e0f4eb9e8ff758e4d927663a" + integrity sha512-TNdSvm2tEE3XMCuxHxquzls56t40hC8qnLeYJWHsY2ECZmRK3KrnpRReEr7N7bLtODToK7X/riYrV0JaYxjrYA== dependencies: - "@cosmjs/amino" "0.28.13" - "@cosmjs/crypto" "0.28.13" - "@cosmjs/encoding" "0.28.13" - "@cosmjs/math" "0.28.13" - "@cosmjs/proto-signing" "0.28.13" - "@cosmjs/stargate" "0.28.13" - "@cosmjs/tendermint-rpc" "0.28.13" - "@cosmjs/utils" "0.28.13" - cosmjs-types "^0.4.0" + "@cosmjs/amino" "^0.29.5" + "@cosmjs/crypto" "^0.29.5" + "@cosmjs/encoding" "^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" + "@cosmjs/utils" "^0.29.5" + cosmjs-types "^0.5.2" long "^4.0.0" pako "^2.0.2" -"@cosmjs/crypto@0.28.13", "@cosmjs/crypto@^0.28.0": - version "0.28.13" - resolved "https://registry.yarnpkg.com/@cosmjs/crypto/-/crypto-0.28.13.tgz#541b6a36f616b2da5a568ead46d4e83841ceb412" - integrity sha512-ynKfM0q/tMBQMHJby6ad8lR3gkgBKaelQhIsCZTjClsnuC7oYT9y3ThSZCUWr7Pa9h0J8ahU2YV2oFWFVWJQzQ== - dependencies: - "@cosmjs/encoding" "0.28.13" - "@cosmjs/math" "0.28.13" - "@cosmjs/utils" "0.28.13" - "@noble/hashes" "^1" - bn.js "^5.2.0" - elliptic "^6.5.3" - libsodium-wrappers "^0.7.6" - "@cosmjs/crypto@^0.25.6": version "0.25.6" resolved "https://registry.yarnpkg.com/@cosmjs/crypto/-/crypto-0.25.6.tgz#695d2d0d2195bdbdd5825d415385646244900bbb" @@ -1301,14 +1288,18 @@ ripemd160 "^2.0.2" sha.js "^2.4.11" -"@cosmjs/encoding@0.28.13": - version "0.28.13" - resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.28.13.tgz#7994e8e2c435beaf0690296ffb0f7f3eaec8150b" - integrity sha512-jtXbAYtV77rLHxoIrjGFsvgGjeTKttuHRv6cvuy3toCZzY7JzTclKH5O2g36IIE4lXwD9xwuhGJ2aa6A3dhNkA== +"@cosmjs/crypto@^0.29.5": + version "0.29.5" + resolved "https://registry.yarnpkg.com/@cosmjs/crypto/-/crypto-0.29.5.tgz#ab99fc382b93d8a8db075780cf07487a0f9519fd" + integrity sha512-2bKkaLGictaNL0UipQCL6C1afaisv6k8Wr/GCLx9FqiyFkh9ZgRHDyetD64ZsjnWV/N/D44s/esI+k6oPREaiQ== dependencies: - base64-js "^1.3.0" - bech32 "^1.1.4" - readonly-date "^1.0.0" + "@cosmjs/encoding" "^0.29.5" + "@cosmjs/math" "^0.29.5" + "@cosmjs/utils" "^0.29.5" + "@noble/hashes" "^1" + bn.js "^5.2.0" + elliptic "^6.5.4" + libsodium-wrappers "^0.7.6" "@cosmjs/encoding@^0.25.6": version "0.25.6" @@ -1319,13 +1310,14 @@ bech32 "^1.1.4" readonly-date "^1.0.0" -"@cosmjs/json-rpc@0.28.13": - version "0.28.13" - resolved "https://registry.yarnpkg.com/@cosmjs/json-rpc/-/json-rpc-0.28.13.tgz#ff3f0c4a2f363b1a2c6779f8624a897e217fe297" - integrity sha512-fInSvg7x9P6p+GWqet+TMhrMTM3OWWdLJOGS5w2ryubMjgpR1rLiAx77MdTNkArW+/6sUwku0sN4veM4ENQu6A== +"@cosmjs/encoding@^0.29.5": + version "0.29.5" + resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.29.5.tgz#009a4b1c596cdfd326f30ccfa79f5e56daa264f2" + integrity sha512-G4rGl/Jg4dMCw5u6PEZHZcoHnUBlukZODHbm/wcL4Uu91fkn5jVo5cXXZcvs4VCkArVGrEj/52eUgTZCmOBGWQ== dependencies: - "@cosmjs/stream" "0.28.13" - xstream "^11.14.0" + base64-js "^1.3.0" + bech32 "^1.1.4" + readonly-date "^1.0.0" "@cosmjs/json-rpc@^0.25.6": version "0.25.6" @@ -1335,6 +1327,14 @@ "@cosmjs/stream" "^0.25.6" xstream "^11.14.0" +"@cosmjs/json-rpc@^0.29.5": + version "0.29.5" + resolved "https://registry.yarnpkg.com/@cosmjs/json-rpc/-/json-rpc-0.29.5.tgz#5e483a9bd98a6270f935adf0dfd8a1e7eb777fe4" + integrity sha512-C78+X06l+r9xwdM1yFWIpGl03LhB9NdM1xvZpQHwgCOl0Ir/WV8pw48y3Ez2awAoUBRfTeejPe4KvrE6NoIi/w== + dependencies: + "@cosmjs/stream" "^0.29.5" + xstream "^11.14.0" + "@cosmjs/launchpad@^0.25.6": version "0.25.6" resolved "https://registry.yarnpkg.com/@cosmjs/launchpad/-/launchpad-0.25.6.tgz#c75f5d21be57af55fcb892f929520fa97f2d5bcc" @@ -1348,13 +1348,6 @@ axios "^0.21.1" fast-deep-equal "^3.1.3" -"@cosmjs/math@0.28.13", "@cosmjs/math@^0.28.0": - version "0.28.13" - resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.28.13.tgz#50c05bc67007a04216f7f5e0c93f57270f8cc077" - integrity sha512-PDpL8W/kbyeWi0mQ2OruyqE8ZUAdxPs1xCbDX3WXJwy2oU+X2UTbkuweJHVpS9CIqmZulBoWQAmlf6t6zr1N/g== - dependencies: - bn.js "^5.2.0" - "@cosmjs/math@^0.25.5", "@cosmjs/math@^0.25.6": version "0.25.6" resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.25.6.tgz#25c7b106aaded889a5b80784693caa9e654b0c28" @@ -1369,18 +1362,12 @@ dependencies: bn.js "^5.2.0" -"@cosmjs/proto-signing@0.28.13", "@cosmjs/proto-signing@^0.28.0": - version "0.28.13" - resolved "https://registry.yarnpkg.com/@cosmjs/proto-signing/-/proto-signing-0.28.13.tgz#95ac12f0da0f0814f348f5ae996c3e96d015df61" - integrity sha512-nSl/2ZLsUJYz3Ad0RY3ihZUgRHIow2OnYqKsESMu+3RA/jTi9bDYhiBu8mNMHI0xrEJry918B2CyI56pOUHdPQ== +"@cosmjs/math@^0.29.5": + version "0.29.5" + resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.29.5.tgz#722c96e080d6c2b62215ce9f4c70da7625b241b6" + integrity sha512-2GjKcv+A9f86MAWYLUkjhw1/WpRl2R1BTb3m9qPG7lzMA7ioYff9jY5SPCfafKdxM4TIQGxXQlYGewQL16O68Q== dependencies: - "@cosmjs/amino" "0.28.13" - "@cosmjs/crypto" "0.28.13" - "@cosmjs/encoding" "0.28.13" - "@cosmjs/math" "0.28.13" - "@cosmjs/utils" "0.28.13" - cosmjs-types "^0.4.0" - long "^4.0.0" + bn.js "^5.2.0" "@cosmjs/proto-signing@^0.25.5", "@cosmjs/proto-signing@^0.25.6": version "0.25.6" @@ -1391,15 +1378,18 @@ long "^4.0.0" protobufjs "~6.10.2" -"@cosmjs/socket@0.28.13": - version "0.28.13" - resolved "https://registry.yarnpkg.com/@cosmjs/socket/-/socket-0.28.13.tgz#d8443ad6e91d080fc6b80a7e9cf297a56b1f6833" - integrity sha512-lavwGxQ5VdeltyhpFtwCRVfxeWjH5D5mmN7jgx9nuCf3XSFbTcOYxrk2pQ4usenu1Q1KZdL4Yl5RCNrJuHD9Ug== +"@cosmjs/proto-signing@^0.29.5": + version "0.29.5" + resolved "https://registry.yarnpkg.com/@cosmjs/proto-signing/-/proto-signing-0.29.5.tgz#af3b62a46c2c2f1d2327d678b13b7262db1fe87c" + integrity sha512-QRrS7CiKaoETdgIqvi/7JC2qCwCR7lnWaUsTzh/XfRy3McLkEd+cXbKAW3cygykv7IN0VAEIhZd2lyIfT8KwNA== dependencies: - "@cosmjs/stream" "0.28.13" - isomorphic-ws "^4.0.1" - ws "^7" - xstream "^11.14.0" + "@cosmjs/amino" "^0.29.5" + "@cosmjs/crypto" "^0.29.5" + "@cosmjs/encoding" "^0.29.5" + "@cosmjs/math" "^0.29.5" + "@cosmjs/utils" "^0.29.5" + cosmjs-types "^0.5.2" + long "^4.0.0" "@cosmjs/socket@^0.25.6": version "0.25.6" @@ -1411,22 +1401,14 @@ ws "^7" xstream "^11.14.0" -"@cosmjs/stargate@0.28.13", "@cosmjs/stargate@^0.28.0": - version "0.28.13" - resolved "https://registry.yarnpkg.com/@cosmjs/stargate/-/stargate-0.28.13.tgz#a73d837a46ee8944e6eafe162f2ff6943c14350e" - integrity sha512-dVBMazDz8/eActHsRcZjDHHptOBMqvibj5CFgEtZBp22gP6ASzoAUXTlkSVk5FBf4sfuUHoff6st134/+PGMAg== +"@cosmjs/socket@^0.29.5": + version "0.29.5" + resolved "https://registry.yarnpkg.com/@cosmjs/socket/-/socket-0.29.5.tgz#a48df6b4c45dc6a6ef8e47232725dd4aa556ac2d" + integrity sha512-5VYDupIWbIXq3ftPV1LkS5Ya/T7Ol/AzWVhNxZ79hPe/mBfv1bGau/LqIYOm2zxGlgm9hBHOTmWGqNYDwr9LNQ== dependencies: - "@confio/ics23" "^0.6.8" - "@cosmjs/amino" "0.28.13" - "@cosmjs/encoding" "0.28.13" - "@cosmjs/math" "0.28.13" - "@cosmjs/proto-signing" "0.28.13" - "@cosmjs/stream" "0.28.13" - "@cosmjs/tendermint-rpc" "0.28.13" - "@cosmjs/utils" "0.28.13" - cosmjs-types "^0.4.0" - long "^4.0.0" - protobufjs "~6.11.3" + "@cosmjs/stream" "^0.29.5" + isomorphic-ws "^4.0.1" + ws "^7" xstream "^11.14.0" "@cosmjs/stargate@^0.25.5", "@cosmjs/stargate@^0.25.6": @@ -1445,11 +1427,22 @@ long "^4.0.0" protobufjs "~6.10.2" -"@cosmjs/stream@0.28.13": - version "0.28.13" - resolved "https://registry.yarnpkg.com/@cosmjs/stream/-/stream-0.28.13.tgz#1e79d1116fda1e63e5ecddbd9d803d403942b1fa" - integrity sha512-AnjtfwT8NwPPkd3lhZhjOlOzT0Kn9bgEu2IPOZjQ1nmG2bplsr6TJmnwn0dJxHT7UGtex17h6whKB5N4wU37Wg== +"@cosmjs/stargate@^0.29.5": + version "0.29.5" + resolved "https://registry.yarnpkg.com/@cosmjs/stargate/-/stargate-0.29.5.tgz#d597af1c85a3c2af7b5bdbec34d5d40692cc09e4" + integrity sha512-hjEv8UUlJruLrYGJcUZXM/CziaINOKwfVm2BoSdUnNTMxGvY/jC1ABHKeZUYt9oXHxEJ1n9+pDqzbKc8pT0nBw== dependencies: + "@confio/ics23" "^0.6.8" + "@cosmjs/amino" "^0.29.5" + "@cosmjs/encoding" "^0.29.5" + "@cosmjs/math" "^0.29.5" + "@cosmjs/proto-signing" "^0.29.5" + "@cosmjs/stream" "^0.29.5" + "@cosmjs/tendermint-rpc" "^0.29.5" + "@cosmjs/utils" "^0.29.5" + cosmjs-types "^0.5.2" + long "^4.0.0" + protobufjs "~6.11.3" xstream "^11.14.0" "@cosmjs/stream@^0.25.6": @@ -1459,20 +1452,11 @@ dependencies: xstream "^11.14.0" -"@cosmjs/tendermint-rpc@0.28.13", "@cosmjs/tendermint-rpc@^0.28.0": - version "0.28.13" - resolved "https://registry.yarnpkg.com/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.28.13.tgz#0bf587ae66fa3f88319edbd258492d28e73f9f29" - integrity sha512-GB+ZmfuJIGQm0hsRtLYjeR3lOxF7Z6XyCBR0cX5AAYOZzSEBJjevPgUHD6tLn8zIhvzxaW3/VKnMB+WmlxdH4w== +"@cosmjs/stream@^0.29.5": + version "0.29.5" + resolved "https://registry.yarnpkg.com/@cosmjs/stream/-/stream-0.29.5.tgz#350981cac496d04939b92ee793b9b19f44bc1d4e" + integrity sha512-TToTDWyH1p05GBtF0Y8jFw2C+4783ueDCmDyxOMM6EU82IqpmIbfwcdMOCAm0JhnyMh+ocdebbFvnX/sGKzRAA== dependencies: - "@cosmjs/crypto" "0.28.13" - "@cosmjs/encoding" "0.28.13" - "@cosmjs/json-rpc" "0.28.13" - "@cosmjs/math" "0.28.13" - "@cosmjs/socket" "0.28.13" - "@cosmjs/stream" "0.28.13" - "@cosmjs/utils" "0.28.13" - axios "^0.21.2" - readonly-date "^1.0.0" xstream "^11.14.0" "@cosmjs/tendermint-rpc@^0.25.6": @@ -1490,16 +1474,32 @@ readonly-date "^1.0.0" xstream "^11.14.0" -"@cosmjs/utils@0.28.13": - version "0.28.13" - resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.28.13.tgz#2fd2844ec832d7833811e2ae1691305d09791a08" - integrity sha512-dVeMBiyg+46x7XBZEfJK8yTihphbCFpjVYmLJVqmTsHfJwymQ65cpyW/C+V/LgWARGK8hWQ/aX9HM5Ao8QmMSg== +"@cosmjs/tendermint-rpc@^0.29.5": + version "0.29.5" + resolved "https://registry.yarnpkg.com/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.29.5.tgz#f205c10464212bdf843f91bb2e4a093b618cb5c2" + integrity sha512-ar80twieuAxsy0x2za/aO3kBr2DFPAXDmk2ikDbmkda+qqfXgl35l9CVAAjKRqd9d+cRvbQyb5M4wy6XQpEV6w== + dependencies: + "@cosmjs/crypto" "^0.29.5" + "@cosmjs/encoding" "^0.29.5" + "@cosmjs/json-rpc" "^0.29.5" + "@cosmjs/math" "^0.29.5" + "@cosmjs/socket" "^0.29.5" + "@cosmjs/stream" "^0.29.5" + "@cosmjs/utils" "^0.29.5" + axios "^0.21.2" + readonly-date "^1.0.0" + xstream "^11.14.0" "@cosmjs/utils@^0.25.6": version "0.25.6" resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.25.6.tgz#934d9a967180baa66163847616a74358732227ca" integrity sha512-ofOYiuxVKNo238vCPPlaDzqPXy2AQ/5/nashBo5rvPZJkxt9LciGfUEQWPCOb1BIJDNx2Dzu0z4XCf/dwzl0Dg== +"@cosmjs/utils@^0.29.5": + version "0.29.5" + resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.29.5.tgz#3fed1b3528ae8c5f1eb5d29b68755bebfd3294ee" + integrity sha512-m7h+RXDUxOzEOGt4P+3OVPX7PuakZT3GBmaM/Y2u+abN3xZkziykD/NvedYFvvCCdQo714XcGl33bwifS9FZPQ== + "@design-systems/utils@2.12.0": version "2.12.0" resolved "https://registry.yarnpkg.com/@design-systems/utils/-/utils-2.12.0.tgz#955c108be07cb8f01532207cbfea8f848fa760c9" @@ -1689,6 +1689,19 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" +"@favware/rollup-type-bundler@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@favware/rollup-type-bundler/-/rollup-type-bundler-2.0.0.tgz#5594ee64b40dc64eb02eb68a30943ff4255d25dd" + integrity sha512-RTMvx6v3b4D9V9iXHTogYjHa5fCmcUR3Bu0pFreo+80v2tD+7MSJm24nR1P/SkeTCy+zHKC1JOFQa04fcWZozg== + dependencies: + "@sapphire/utilities" "^3.11.0" + colorette "^2.0.19" + commander "^9.4.1" + js-yaml "^4.1.0" + rollup "^3.2.1" + rollup-plugin-dts "^5.0.0" + typescript "^4.8.4" + "@floating-ui/core@^1.0.5": version "1.1.0" resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.1.0.tgz#0a1dee4bbce87ff71602625d33f711cafd8afc08" @@ -3333,6 +3346,14 @@ "@rollup/pluginutils" "^5.0.1" resolve "^1.22.1" +"@rollup/plugin-typescript@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-11.0.0.tgz#f136272d1df5209daca0cb6f171c574b1d505545" + integrity sha512-goPyCWBiimk1iJgSTgsehFD5OOFHiAknrRJjqFCudcW8JtWiBlK284Xnn4flqMqg6YAjVG/EE+3aVzrL5qNSzQ== + dependencies: + "@rollup/pluginutils" "^5.0.1" + resolve "^1.22.1" + "@rollup/plugin-wasm@^6.1.1": version "6.1.2" resolved "https://registry.yarnpkg.com/@rollup/plugin-wasm/-/plugin-wasm-6.1.2.tgz#faf57f8e2ed12b9e0e898ba67963c52e1cd5f4c3" @@ -3356,6 +3377,11 @@ estree-walker "^2.0.2" picomatch "^2.3.1" +"@sapphire/utilities@^3.11.0": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@sapphire/utilities/-/utilities-3.11.0.tgz#2dccfb332dc5c119e1425cce6b2c64160b770bad" + integrity sha512-ich7J+329UTEgWxgk8b871rMhbFW/hvXdabdiKaUKd6g10eIMkIakWf+EGkDQsiDSiebIXll9TIPPmWtN3cVSw== + "@sinclair/typebox@^0.24.1": version "0.24.51" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f" @@ -6290,12 +6316,14 @@ axios@^0.21.1, axios@^0.21.2: dependencies: follow-redirects "^1.14.0" -axios@^0.26.1: - version "0.26.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" - integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== +axios@^1.3.3: + version "1.3.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.4.tgz#f5760cefd9cfb51fd2481acf88c05f67c4523024" + integrity sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ== dependencies: - follow-redirects "^1.14.8" + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" axobject-query@^3.1.1: version "3.1.1" @@ -7409,7 +7437,7 @@ colorette@^1.2.2: resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== -colorette@^2.0.10, colorette@^2.0.14: +colorette@^2.0.10, colorette@^2.0.14, colorette@^2.0.19: version "2.0.19" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== @@ -7479,6 +7507,11 @@ commander@^8.3.0: resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== +commander@^9.4.1: + version "9.5.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" + integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== + common-path-prefix@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" @@ -7755,7 +7788,7 @@ cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: path-type "^4.0.0" yaml "^1.10.0" -cosmjs-types@^0.4.0, cosmjs-types@^0.4.1: +cosmjs-types@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/cosmjs-types/-/cosmjs-types-0.4.1.tgz#3b2a53ba60d33159dd075596ce8267cfa7027063" integrity sha512-I7E/cHkIgoJzMNQdFF0YVqPlaTqrqKHrskuSTIqlEyxfB5Lf3WKCajSXVK2yHOfOFfSux/RxEdpMzw/eO4DIog== @@ -7763,6 +7796,14 @@ cosmjs-types@^0.4.0, cosmjs-types@^0.4.1: long "^4.0.0" protobufjs "~6.11.2" +cosmjs-types@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/cosmjs-types/-/cosmjs-types-0.5.2.tgz#2d42b354946f330dfb5c90a87fdc2a36f97b965d" + integrity sha512-zxCtIJj8v3Di7s39uN4LNcN3HIE1z0B9Z0SPE8ZNQR0oSzsuSe1ACgxoFkvhkS7WBasCAFcglS11G2hyfd5tPg== + dependencies: + long "^4.0.0" + protobufjs "~6.11.2" + cp-file@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-7.0.0.tgz#b9454cfd07fe3b974ab9ea0e5f29655791a9b8cd" @@ -8731,6 +8772,11 @@ dotenv-webpack@^7.0.3: dependencies: dotenv-defaults "^2.0.2" +dotenv@^16.0.3: + version "16.0.3" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" + integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== + dotenv@^8.0.0, dotenv@^8.2.0: version "8.6.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" @@ -8769,7 +8815,7 @@ electron-to-chromium@^1.4.251: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== -elliptic@^6.5.3: +elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -9937,7 +9983,7 @@ focus-lock@^0.8.0: dependencies: tslib "^1.9.3" -follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.8: +follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.15.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== @@ -10026,6 +10072,15 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -13015,6 +13070,13 @@ magic-string@^0.27.0: dependencies: "@jridgewell/sourcemap-codec" "^1.4.13" +magic-string@^0.29.0: + version "0.29.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.29.0.tgz#f034f79f8c43dba4ae1730ffb5e8c4e084b16cf3" + integrity sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.13" + make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -13995,6 +14057,13 @@ modify-values@^1.0.0: resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== +moq.ts@^7.3.4: + version "7.4.1" + resolved "https://registry.yarnpkg.com/moq.ts/-/moq.ts-7.4.1.tgz#1bb7e808324dc5b0143fa8b1a94f539203d475cb" + integrity sha512-P97MjGUkkMKQrAHbNScyJvSv3S7pMxnuxd3HgaOrPuoC6okwPqru3ZX8W/mTdU7Ms74622MeeWHqoDaGyYKonw== + dependencies: + tslib "2.1.0" + move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -15774,6 +15843,11 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" @@ -16785,11 +16859,27 @@ rollup-plugin-base64@^1.0.1: dependencies: "@rollup/pluginutils" "^3.1.0" +rollup-plugin-dts@^5.0.0, rollup-plugin-dts@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-dts/-/rollup-plugin-dts-5.2.0.tgz#1970edb69cfa3ead285ff4289d8fe273b87a5af3" + integrity sha512-B68T/haEu2MKcz4kNUhXB8/h5sq4gpplHAJIYNHbh8cp4ZkvzDvNca/11KQdFrB9ZeKucegQIotzo5T0JUtM8w== + dependencies: + magic-string "^0.29.0" + optionalDependencies: + "@babel/code-frame" "^7.18.6" + rollup-plugin-web-worker-loader@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/rollup-plugin-web-worker-loader/-/rollup-plugin-web-worker-loader-1.6.1.tgz#9d7a27575b64b0780fe4e8b3bc87470d217e485f" integrity sha512-4QywQSz1NXFHKdyiou16mH3ijpcfLtLGOrAqvAqu1Gx+P8+zj+3gwC2BSL/VW1d+LW4nIHC8F7d7OXhs9UdR2A== +rollup@^3.17.2, rollup@^3.2.1: + version "3.17.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.17.2.tgz#a4ecd29c488672a0606e41ef57474fad715750a9" + integrity sha512-qMNZdlQPCkWodrAZ3qnJtvCAl4vpQ8q77uEujVCCbC/6CLB7Lcmvjq7HyiOSnf4fxTT9XgsE36oLHJBH49xjqA== + optionalDependencies: + fsevents "~2.3.2" + rollup@^3.9.1: version "3.10.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.10.1.tgz#56278901ed11fc2898421e8e3e2c8155bc7b40b4" @@ -18345,6 +18435,11 @@ tsconfig-paths@^3.14.1, tsconfig-paths@^3.5.0, tsconfig-paths@^3.9.0: minimist "^1.2.6" strip-bom "^3.0.0" +tslib@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" + integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== + tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" From 63524eceffb9b3914f9c7c2dd144120ceb85ec3e Mon Sep 17 00:00:00 2001 From: farbanas Date: Tue, 28 Feb 2023 17:27:58 +0100 Subject: [PATCH 05/44] fix: update versions of the latest release in changelogs from 1.0.11 to 1.1.11 --- CHANGELOG.md | 2 +- nym-connect/desktop/CHANGELOG.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7db3d58a71..4d045624c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ Post 1.0.0 release, the changelog format is based on [Keep a Changelog](https:// ## [Unreleased] -## [v1.0.11] (2023-02-28) +## [v1.1.11] (2023-02-28) - Fix empty dealer set loop ([#3105]) - The nym-api db.sqlite is broken when trying to run against it it in `enabled-credentials-mode true` there is an ordering issue with migrations when using the credential binary to purchase bandwidth ([#3100]) diff --git a/nym-connect/desktop/CHANGELOG.md b/nym-connect/desktop/CHANGELOG.md index 9e6f08fe2d..4bfd4a39e8 100644 --- a/nym-connect/desktop/CHANGELOG.md +++ b/nym-connect/desktop/CHANGELOG.md @@ -2,7 +2,7 @@ ## [Unreleased] -## [v1.0.11] (2023-02-28) +## [v1.1.11] (2023-02-28) - NC - add the option to manually select and use a specific Service Provider ([#2953]) From 4a80cd301bb57a8c0029b22184f9a20ff2908fae Mon Sep 17 00:00:00 2001 From: farbanas Date: Wed, 1 Mar 2023 11:06:21 +0100 Subject: [PATCH 06/44] fix: add step to install wasm-opt to our CI for building and uploading binaries --- .github/workflows/build-and-upload-binaries-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build-and-upload-binaries-ci.yml b/.github/workflows/build-and-upload-binaries-ci.yml index 812c24f16e..a78eadfff4 100644 --- a/.github/workflows/build-and-upload-binaries-ci.yml +++ b/.github/workflows/build-and-upload-binaries-ci.yml @@ -79,6 +79,9 @@ jobs: override: true components: rustfmt, clippy + - name: Install wasm-opt + run: cargo install wasm-opt + - name: Build release contracts run: make wasm From 8f8cec07853c6319419243f67c367014ba45a838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Wed, 1 Mar 2023 10:37:44 +0000 Subject: [PATCH 07/44] Fixed the build badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 96409f6e0e..3a7f37ca33 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The platform is composed of multiple Rust crates. Top-level executable binary cr * nym-wallet - a desktop wallet implemented using the [Tauri](https://tauri.studio/en/docs/about/intro) framework. [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg?style=for-the-badge)](https://opensource.org/licenses/Apache-2.0) -[![Build Status](https://img.shields.io/github/workflow/status/nymtech/nym/Continuous%20integration/develop?style=for-the-badge&logo=github-actions)](https://github.com/nymtech/nym/actions?query=branch%3Adevelop) +[![Build Status](https://img.shields.io/github/actions/workflow/status/nymtech/nym/build.yml?branch=develop&style=for-the-badge&logo=github-actions)](https://github.com/nymtech/nym/actions?query=branch%3Adevelop) ### Building From 2ec790e8518dccd955cf362ff7d8fe09d017b11f Mon Sep 17 00:00:00 2001 From: Pierre Dommerc Date: Wed, 1 Mar 2023 15:16:40 +0100 Subject: [PATCH 08/44] fix(explorer): fix layout responsiveness in mixnode details view (#3130) --- .../src/components/MixNodes/DetailSection.tsx | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/explorer/src/components/MixNodes/DetailSection.tsx b/explorer/src/components/MixNodes/DetailSection.tsx index dcf0f830b5..a07a6fb7d8 100644 --- a/explorer/src/components/MixNodes/DetailSection.tsx +++ b/explorer/src/components/MixNodes/DetailSection.tsx @@ -18,8 +18,8 @@ export const MixNodeDetailSection: FCWithChildren = ({ mixNo const statusText = React.useMemo(() => getMixNodeStatusText(mixNodeRow.status), [mixNodeRow.status]); return ( - - + + = ({ mixNo > - + {mixnodeDescription.name} {(mixnodeDescription.description || '').slice(0, 1000)}