From 4028bf2218f4fe0461a4fade88d335ba3b491538 Mon Sep 17 00:00:00 2001 From: fmtabbara Date: Mon, 31 Jul 2023 15:48:45 +0100 Subject: [PATCH 1/4] link wallet to external node tester --- .../src/components/Bonding/NodeStats.tsx | 23 +++++++++---- nym-wallet/src/constants.ts | 26 +++++++++++++-- .../examples/node-tester/react/src/App.tsx | 32 +++++++++++++++++-- .../react/src/hooks/useNodeTesterClient.ts | 19 ++++------- 4 files changed, 76 insertions(+), 24 deletions(-) diff --git a/nym-wallet/src/components/Bonding/NodeStats.tsx b/nym-wallet/src/components/Bonding/NodeStats.tsx index eb22b507278..27401b986c8 100644 --- a/nym-wallet/src/components/Bonding/NodeStats.tsx +++ b/nym-wallet/src/components/Bonding/NodeStats.tsx @@ -1,9 +1,10 @@ -import React from 'react'; +import React, { useContext } from 'react'; import { Stack, Typography, Box, useTheme, Grid, LinearProgress, LinearProgressProps, Button } from '@mui/material'; -import { useNavigate } from 'react-router-dom'; -import { TBondedMixnode } from 'src/context'; -import { Cell, Pie, PieChart, Legend, ResponsiveContainer } from 'recharts'; +import { open as openLink } from '@tauri-apps/api/shell'; import { SelectionChance } from '@nymproject/types'; +import { AppContext, TBondedMixnode } from 'src/context'; +import { validatorApiFromNetwork } from 'src/constants'; +import { Cell, Pie, PieChart, Legend, ResponsiveContainer } from 'recharts'; import { NymCard } from '../NymCard'; import { InfoTooltip } from '../InfoToolTip'; @@ -50,7 +51,7 @@ const StatRow = ({ export const NodeStats = ({ mixnode }: { mixnode: TBondedMixnode }) => { const { activeSetProbability, routingScore } = mixnode; const theme = useTheme(); - const navigate = useNavigate(); + const { network } = useContext(AppContext); // clamp routing score to [0-100] const score = Math.min(Math.max(routingScore, 0), 100); @@ -74,8 +75,16 @@ export const NodeStats = ({ mixnode }: { mixnode: TBondedMixnode }) => { } }; - const handleGoToTestNode = () => { - navigate('/bonding/node-settings', { state: 'test-node' }); + const handleGoToTestNode = async () => { + if (network) { + let validatorUrl = validatorApiFromNetwork(network); + + //TODO need to change URL to the deployed node-tester (once deployed) + const url = new window.URL( + `http://localhost:1234/?validator-address=${validatorUrl}&mixnode-identity=${mixnode.identityKey}`, + ); + openLink(url.toString()); + } }; const renderLegend = () => ( diff --git a/nym-wallet/src/constants.ts b/nym-wallet/src/constants.ts index 55770cd39bd..78fe92caa20 100644 --- a/nym-wallet/src/constants.ts +++ b/nym-wallet/src/constants.ts @@ -1,5 +1,27 @@ +import { Network } from './types'; + const QA_VALIDATOR_URL = 'https://qa-nym-api.qa.nymte.ch/api'; const QWERTY_VALIDATOR_URL = 'https://qwerty-validator-api.qa.nymte.ch/api'; -const MAINNET_VALIDATOR_URL = 'https://validator.nymtech.net/api/'; +const SANDBOX_VALIDATOR_URL = 'https://sandbox-nym-api1.nymtech.net/api'; +const MAINNET_VALIDATOR_URL = 'https://validator.nymtech.net/api'; + +const validatorApiFromNetwork = (network: Network) => { + switch (network) { + case 'QA': + return QA_VALIDATOR_URL; + case 'SANDBOX': + return SANDBOX_VALIDATOR_URL; + case 'MAINNET': + return MAINNET_VALIDATOR_URL; + default: + throw new Error(`Unknown network: ${network}`); + } +}; -export { QA_VALIDATOR_URL, QWERTY_VALIDATOR_URL, MAINNET_VALIDATOR_URL }; +export { + QA_VALIDATOR_URL, + QWERTY_VALIDATOR_URL, + MAINNET_VALIDATOR_URL, + SANDBOX_VALIDATOR_URL, + validatorApiFromNetwork, +}; diff --git a/sdk/typescript/examples/node-tester/react/src/App.tsx b/sdk/typescript/examples/node-tester/react/src/App.tsx index eb0bd1927a6..c95dd7a5f1f 100644 --- a/sdk/typescript/examples/node-tester/react/src/App.tsx +++ b/sdk/typescript/examples/node-tester/react/src/App.tsx @@ -1,5 +1,6 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { + Alert, Button, Card, CardActions, @@ -21,8 +22,8 @@ import { TestStatusLabel } from 'src/components/TestStatusLabel'; import Icon from '../../../../../../assets/appicon/appicon.png'; export const App = () => { - const { testState, error, testNode, disconnectFromGateway, reconnectToGateway } = useNodeTesterClient(); - const [mixnodeIdentity, setMixnodeIdentity] = useState(''); + const { createClient, testState, error, testNode, disconnectFromGateway, reconnectToGateway } = useNodeTesterClient(); + const [mixnodeIdentity, setMixnodeIdentity] = useState(''); const [results, setResults] = React.useState(); console.log({ testState, error, testNode }); @@ -37,6 +38,26 @@ export const App = () => { } }; + const getParams = () => { + const urlParams = new URLSearchParams(window.location.search); + return { + mixnodeIdentity: urlParams.get('mixnode-identity'), + validatorAddress: urlParams.get('validator-address'), + }; + }; + + const initApp = async () => { + const { mixnodeIdentity, validatorAddress } = getParams(); + if (mixnodeIdentity) { + setMixnodeIdentity(mixnodeIdentity); + } + await createClient(validatorAddress || 'https://validator.nymtech.net/api'); + }; + + useEffect(() => { + initApp(); + }, []); + return ( @@ -66,6 +87,11 @@ export const App = () => { + {error && ( + + {error} + + )} diff --git a/sdk/typescript/examples/node-tester/react/src/hooks/useNodeTesterClient.ts b/sdk/typescript/examples/node-tester/react/src/hooks/useNodeTesterClient.ts index fcd6f929379..cd601d8ecb6 100644 --- a/sdk/typescript/examples/node-tester/react/src/hooks/useNodeTesterClient.ts +++ b/sdk/typescript/examples/node-tester/react/src/hooks/useNodeTesterClient.ts @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react'; +import { useState } from 'react'; import { createNodeTesterClient, NodeTester } from '@nymproject/sdk'; export type TestState = 'Ready' | 'Connecting' | 'Disconnected' | 'Disconnecting' | 'Error' | 'Testing' | 'Stopped'; @@ -8,26 +8,21 @@ export const useNodeTesterClient = () => { const [error, setError] = useState(); const [testState, setTestState] = useState('Disconnected'); - const createClient = async () => { + const createClient = async (validator: string) => { setTestState('Connecting'); try { - const validator = 'https://validator.nymtech.net/api'; const nodeTesterClient = await createNodeTesterClient(); await nodeTesterClient.tester.init(validator); setClient(nodeTesterClient); + setTestState('Ready'); } catch (e) { console.log(e); - setError('Failed to load node tester client, please try again'); - } finally { - setTestState('Ready'); + setError('Failed to load node tester client, please try again. Error: ' + e.message); + setTestState('Error'); } }; - useEffect(() => { - createClient(); - }, []); - const testNode = !client ? undefined : async (mixnodeIdentity: string) => { @@ -38,7 +33,7 @@ export const useNodeTesterClient = () => { return result; } catch (e) { console.log(e); - setError('Failed to test node, please try again'); + setError('Failed to test node, please try again. Error: ' + e.message); setTestState('Error'); } }; @@ -67,5 +62,5 @@ export const useNodeTesterClient = () => { setTestState('Disconnected'); }; - return { testNode, disconnectFromGateway, reconnectToGateway, terminateWorker, testState, error }; + return { createClient, testNode, disconnectFromGateway, reconnectToGateway, terminateWorker, testState, error }; }; From efd1999117dbe694e189cdcb4447d75f33155c1b Mon Sep 17 00:00:00 2001 From: fmtabbara Date: Mon, 31 Jul 2023 16:10:57 +0100 Subject: [PATCH 2/4] re-work url params --- nym-wallet/src/components/Bonding/NodeStats.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/nym-wallet/src/components/Bonding/NodeStats.tsx b/nym-wallet/src/components/Bonding/NodeStats.tsx index 27401b986c8..6ac91c91045 100644 --- a/nym-wallet/src/components/Bonding/NodeStats.tsx +++ b/nym-wallet/src/components/Bonding/NodeStats.tsx @@ -76,13 +76,19 @@ export const NodeStats = ({ mixnode }: { mixnode: TBondedMixnode }) => { }; const handleGoToTestNode = async () => { + //TODO Change URL to the deployed node-tester (once deployed) + const url = new window.URL('http://localhost:1234'); + if (network) { let validatorUrl = validatorApiFromNetwork(network); - //TODO need to change URL to the deployed node-tester (once deployed) - const url = new window.URL( - `http://localhost:1234/?validator-address=${validatorUrl}&mixnode-identity=${mixnode.identityKey}`, - ); + const urlParams = { + 'validator-address': validatorUrl, + 'mixnode-identity': mixnode.identityKey, + }; + + Object.entries(urlParams).forEach(([key, value]) => url.searchParams.append(key, value)); + openLink(url.toString()); } }; From 8c2810fd27fbb11dfa9c0a9c9d3ba029f5652018 Mon Sep 17 00:00:00 2001 From: fmtabbara Date: Mon, 31 Jul 2023 16:34:07 +0100 Subject: [PATCH 3/4] fix linting --- nym-wallet/src/components/Bonding/NodeStats.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nym-wallet/src/components/Bonding/NodeStats.tsx b/nym-wallet/src/components/Bonding/NodeStats.tsx index 6ac91c91045..088b9f0c847 100644 --- a/nym-wallet/src/components/Bonding/NodeStats.tsx +++ b/nym-wallet/src/components/Bonding/NodeStats.tsx @@ -76,11 +76,11 @@ export const NodeStats = ({ mixnode }: { mixnode: TBondedMixnode }) => { }; const handleGoToTestNode = async () => { - //TODO Change URL to the deployed node-tester (once deployed) + // TODO Change URL to the deployed node-tester (once deployed) const url = new window.URL('http://localhost:1234'); if (network) { - let validatorUrl = validatorApiFromNetwork(network); + const validatorUrl = validatorApiFromNetwork(network); const urlParams = { 'validator-address': validatorUrl, From d5ea5e53afb1bac3aabaf55c9da73bac12e3badd Mon Sep 17 00:00:00 2001 From: fmtabbara Date: Tue, 1 Aug 2023 10:42:06 +0100 Subject: [PATCH 4/4] add tauri shell mock to fix storybook --- nym-wallet/.storybook/mocks/tauri/shell.js | 8 ++++++++ .../node-tester/react/src/hooks/useNodeTesterClient.ts | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 nym-wallet/.storybook/mocks/tauri/shell.js diff --git a/nym-wallet/.storybook/mocks/tauri/shell.js b/nym-wallet/.storybook/mocks/tauri/shell.js new file mode 100644 index 00000000000..7bb835d708a --- /dev/null +++ b/nym-wallet/.storybook/mocks/tauri/shell.js @@ -0,0 +1,8 @@ +/** + * This is a mock for Tauri's API package (@tauri-apps/api/shell), to prevent stories from being excluded, because they either use + * or import dependencies that use Tauri. + */ + +module.exports = { + open: () => undefined, +}; diff --git a/sdk/typescript/examples/node-tester/react/src/hooks/useNodeTesterClient.ts b/sdk/typescript/examples/node-tester/react/src/hooks/useNodeTesterClient.ts index cd601d8ecb6..6ebab1c379e 100644 --- a/sdk/typescript/examples/node-tester/react/src/hooks/useNodeTesterClient.ts +++ b/sdk/typescript/examples/node-tester/react/src/hooks/useNodeTesterClient.ts @@ -13,7 +13,7 @@ export const useNodeTesterClient = () => { try { const nodeTesterClient = await createNodeTesterClient(); - await nodeTesterClient.tester.init(validator); + await nodeTesterClient.tester.init(validator, validator); setClient(nodeTesterClient); setTestState('Ready'); } catch (e) {