diff --git a/nym-wallet/src/assets/test-node-illustration.jpg b/nym-wallet/src/assets/test-node-illustration.jpg
new file mode 100644
index 0000000000..edc79e8dbb
Binary files /dev/null and b/nym-wallet/src/assets/test-node-illustration.jpg differ
diff --git a/nym-wallet/src/components/Nav.tsx b/nym-wallet/src/components/Nav.tsx
index ccb1dcd10d..1f8fbab42a 100644
--- a/nym-wallet/src/components/Nav.tsx
+++ b/nym-wallet/src/components/Nav.tsx
@@ -40,6 +40,12 @@ export const Nav = () => {
Icon: Delegate,
onClick: () => navigate('/delegation'),
},
+ {
+ label: 'Test my node',
+ route: '/test-my-node',
+ Icon: Delegate,
+ onClick: () => navigate('/test-my-node'),
+ },
{
label: 'Docs',
route: '/admin',
diff --git a/nym-wallet/src/components/TestMyNode/Overview/index.tsx b/nym-wallet/src/components/TestMyNode/Overview/index.tsx
new file mode 100644
index 0000000000..735c8dcdb8
--- /dev/null
+++ b/nym-wallet/src/components/TestMyNode/Overview/index.tsx
@@ -0,0 +1,40 @@
+import React from 'react';
+import { Button, Grid, Stack } from '@mui/material';
+import testNode from 'src/assets/test-node-illustration.jpg';
+import { DescriptionItem } from '../components/overview';
+
+const content = [
+ {
+ title: 'How is works',
+ description:
+ 'This is your APY playground - play with the parameters on left to see estimated rewards on the right side',
+ },
+ {
+ title: 'Test path',
+ description:
+ 'This is your APY playground - play with the parameters on left to see estimated rewards on the right side',
+ },
+ {
+ title: 'Results',
+ description:
+ 'This is your APY playground - play with the parameters on left to see estimated rewards on the right side',
+ },
+];
+
+export const Overview = ({ onStartTest }: { onStartTest: () => void }) => (
+
+
+
+
+
+
+ {content.map(DescriptionItem)}
+
+
+
+
+
+
+);
diff --git a/nym-wallet/src/components/TestMyNode/Results/index.tsx b/nym-wallet/src/components/TestMyNode/Results/index.tsx
new file mode 100644
index 0000000000..0784ec83b1
--- /dev/null
+++ b/nym-wallet/src/components/TestMyNode/Results/index.tsx
@@ -0,0 +1,90 @@
+import React from 'react';
+import { ArrowForward, CheckCircleOutline, Description, Download } from '@mui/icons-material';
+import { Box, Button, Card, Chip, CircularProgress, Divider, Grid, Stack, Typography } from '@mui/material';
+import format from 'date-fns/format';
+import { ResultsCard } from '../components/ResultsCard';
+import { ResultsCardDetail } from '../components/ResultsCardDetail';
+import { PathChip } from '../components/PathChip';
+
+const NodeSpeed = ({ Mbps, performance }: { Mbps: number; performance: 'poor' | 'fair' | 'good' }) => (
+
+
+
+
+
+ {Mbps}
+
+ Mbps
+
+
+
+);
+
+const Packets = ({ sent, received }: { sent: string; received: string }) => (
+
+
+
+
+
+
+);
+
+const Path = ({ layer }: { layer: number }) => (
+
+
+
+
+
+
+
+
+
+
+
+);
+
+export const Results = () => (
+ <>
+
+
+
+ Test date
+
+ {format(new Date(), 'dd/MM/yyyy HH:mm')}
+
+ }>Save to PDF
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+);
diff --git a/nym-wallet/src/components/TestMyNode/TestProgress/index.tsx b/nym-wallet/src/components/TestMyNode/TestProgress/index.tsx
new file mode 100644
index 0000000000..3e910855a3
--- /dev/null
+++ b/nym-wallet/src/components/TestMyNode/TestProgress/index.tsx
@@ -0,0 +1,34 @@
+import React from 'react';
+import { Box, CircularProgress, Stack, Typography } from '@mui/material';
+
+export const TestProgress = ({ totalPackets, packetsSent }: { totalPackets: number; packetsSent: number }) => {
+ const percentage = Math.round((packetsSent / totalPackets) * 100);
+
+ return (
+
+ Test in progress
+
+
+
+ {percentage}%
+
+
+ Sending packets...
+ {`${packetsSent} / ${totalPackets}`}
+
+ );
+};
diff --git a/nym-wallet/src/components/TestMyNode/components/PathChip.tsx b/nym-wallet/src/components/TestMyNode/components/PathChip.tsx
new file mode 100644
index 0000000000..f6154cfc4b
--- /dev/null
+++ b/nym-wallet/src/components/TestMyNode/components/PathChip.tsx
@@ -0,0 +1,6 @@
+import React from 'react';
+import { Chip } from '@mui/material';
+
+export const PathChip = ({ label, highlight }: { label: string; highlight: boolean }) => (
+
+);
diff --git a/nym-wallet/src/components/TestMyNode/components/ResultsCard.tsx b/nym-wallet/src/components/TestMyNode/components/ResultsCard.tsx
new file mode 100644
index 0000000000..c6837fea0f
--- /dev/null
+++ b/nym-wallet/src/components/TestMyNode/components/ResultsCard.tsx
@@ -0,0 +1,21 @@
+import React from 'react';
+import { CheckCircleOutline } from '@mui/icons-material';
+import { Card } from '@mui/material';
+import { ResultsCardDetail } from './ResultsCardDetail';
+
+export const ResultsCard: React.FC<{ label: string; detail: string; isOk: boolean }> = ({
+ label,
+ detail,
+ isOk,
+ children,
+}) => (
+
+ }
+ />
+ {children}
+
+);
diff --git a/nym-wallet/src/components/TestMyNode/components/ResultsCardDetail.tsx b/nym-wallet/src/components/TestMyNode/components/ResultsCardDetail.tsx
new file mode 100644
index 0000000000..8819baf335
--- /dev/null
+++ b/nym-wallet/src/components/TestMyNode/components/ResultsCardDetail.tsx
@@ -0,0 +1,22 @@
+import React from 'react';
+import { Box, Stack, Typography } from '@mui/material';
+
+export const ResultsCardDetail = ({
+ label,
+ detail,
+ DescriptionIcon,
+ boldLabel,
+}: {
+ label: string;
+ detail: string;
+ DescriptionIcon?: React.ReactNode;
+ boldLabel?: boolean;
+}) => (
+
+ {label}
+
+ {detail}
+ {DescriptionIcon}
+
+
+);
diff --git a/nym-wallet/src/components/TestMyNode/components/overview.tsx b/nym-wallet/src/components/TestMyNode/components/overview.tsx
new file mode 100644
index 0000000000..973aec987b
--- /dev/null
+++ b/nym-wallet/src/components/TestMyNode/components/overview.tsx
@@ -0,0 +1,13 @@
+import React from 'react';
+import { Box, Typography } from '@mui/material';
+
+export const DescriptionItem = ({ title, description }: { title: string; description: string }) => (
+
+
+ {title}
+
+
+ {description}
+
+
+);
diff --git a/nym-wallet/src/pages/index.ts b/nym-wallet/src/pages/index.ts
index 2976b7890a..325fe541a2 100644
--- a/nym-wallet/src/pages/index.ts
+++ b/nym-wallet/src/pages/index.ts
@@ -5,3 +5,4 @@ export * from './bonding';
export * from './delegation';
export * from './internal-docs';
export * from './unbond';
+export * from './test-my-node';
diff --git a/nym-wallet/src/pages/test-my-node/index.tsx b/nym-wallet/src/pages/test-my-node/index.tsx
new file mode 100644
index 0000000000..237edb4385
--- /dev/null
+++ b/nym-wallet/src/pages/test-my-node/index.tsx
@@ -0,0 +1,36 @@
+import React, { useState } from 'react';
+import { NymCard } from 'src/components';
+import { Overview } from 'src/components/TestMyNode/Overview';
+import { Results } from 'src/components/TestMyNode/Results';
+import { TestProgress } from 'src/components/TestMyNode/TestProgress';
+
+export const TestNode = () => {
+ const [view, setView] = useState('overview');
+ const [packetsSent, setPacketsSent] = useState(0);
+ const totalPackets = 500;
+
+ const mockPacketTransfer = (sent: number) => {
+ if (sent - 1 < totalPackets) {
+ setPacketsSent(sent);
+ setTimeout(() => {
+ mockPacketTransfer(sent + 1);
+ }, 12.5);
+ }
+ if (sent === totalPackets) {
+ setView('results');
+ }
+ };
+
+ const startTest = () => {
+ setView('start-test');
+ mockPacketTransfer(0);
+ };
+
+ return (
+
+ {view === 'overview' && }
+ {view === 'start-test' && }
+ {view === 'results' && }
+
+ );
+};
diff --git a/nym-wallet/src/routes/app.tsx b/nym-wallet/src/routes/app.tsx
index f7cafe8b89..4be436364b 100644
--- a/nym-wallet/src/routes/app.tsx
+++ b/nym-wallet/src/routes/app.tsx
@@ -4,7 +4,7 @@ import { ApplicationLayout } from 'src/layouts';
import { Terminal } from 'src/pages/terminal';
import { Send } from 'src/components/Send';
import { Receive } from '../components/Receive';
-import { Balance, InternalDocs, Unbond, DelegationPage, Admin, BondingPage } from '../pages';
+import { Balance, InternalDocs, Unbond, DelegationPage, Admin, BondingPage, TestNode } from '../pages';
export const AppRoutes = () => (
@@ -16,6 +16,7 @@ export const AppRoutes = () => (
} />
} />
} />
+ } />
} />
} />