diff --git a/nym-wallet/src/context/bonding.tsx b/nym-wallet/src/context/bonding.tsx
index cf5ffa3114..d7a584e533 100644
--- a/nym-wallet/src/context/bonding.tsx
+++ b/nym-wallet/src/context/bonding.tsx
@@ -1,4 +1,4 @@
-import { TransactionExecuteResult } from '@nymproject/types';
+import { MajorCurrencyAmount, TransactionExecuteResult } from '@nymproject/types';
import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import type { Network } from 'src/types';
import { TBondGatewayArgs, TBondMixNodeArgs } from 'src/types';
@@ -15,12 +15,12 @@ import {
export interface BondedMixnode {
key: string;
ip: string;
- stake: number;
- bond: number;
+ stake: MajorCurrencyAmount;
+ bond: MajorCurrencyAmount;
stakeSaturation: number;
profitMargin: number;
- nodeRewards: number;
- operatorRewards: number;
+ nodeRewards: MajorCurrencyAmount;
+ operatorRewards: MajorCurrencyAmount;
delegators: number;
}
@@ -28,7 +28,7 @@ export interface BondedMixnode {
export interface BondedGateway {
key: string;
ip: string;
- bond: number;
+ bond: MajorCurrencyAmount;
location?: string; // TODO not yet available, only available in Network Explorer API
}
@@ -89,7 +89,17 @@ export const BondingContextProvider = ({
};
const refresh = useCallback(async () => {
- const bounded = null;
+ const bounded: BondedMixnode = {
+ bond: { denom: 'NYM', amount: '1234' },
+ key: 'B2Xx4haarLWMajX8w259oHjtRZsC7nHwagbWrJNiA3QC',
+ delegators: 123,
+ ip: '1.2.34.5',
+ nodeRewards: { denom: 'NYM', amount: '123' },
+ operatorRewards: { denom: 'NYM', amount: '12' },
+ profitMargin: 10,
+ stake: { denom: 'NYM', amount: '99' },
+ stakeSaturation: 99,
+ };
// TODO fetch bondedMixnode and bondedGatway via tauri dedicated requests
/* try {
bounded = await fetchBondingData();
@@ -181,6 +191,7 @@ export const BondingContextProvider = ({
isLoading,
error,
bondMixnode,
+ bondedMixnode,
bondGateway,
unbondMixnode,
unbondGateway,
diff --git a/nym-wallet/src/context/mocks/bonding.tsx b/nym-wallet/src/context/mocks/bonding.tsx
index 72d7e9927c..0fddce84a7 100644
--- a/nym-wallet/src/context/mocks/bonding.tsx
+++ b/nym-wallet/src/context/mocks/bonding.tsx
@@ -6,22 +6,22 @@ import { mockSleep } from './utils';
const SLEEP_MS = 1000;
-const bondedMixnodeMock = {
+const bondedMixnodeMock: BondedMixnode = {
key: '7mjM2fYbtN6kxMwp1TrmQ4VwPks3URR5pBgWPWhzT98F',
ip: '112.43.234.56',
- stake: 35847.221,
- bond: 12576.32745,
+ stake: { denom: 'NYM', amount: '1234' },
+ bond: { denom: 'NYM', amount: '1234' },
stakeSaturation: 95,
profitMargin: 15,
- nodeRewards: 12576.32745,
- operatorRewards: 12576.32,
+ nodeRewards: { denom: 'NYM', amount: '1234' },
+ operatorRewards: { denom: 'NYM', amount: '1234' },
delegators: 5423,
};
-const bondedGatewayMock = {
+const bondedGatewayMock: BondedGateway = {
key: 'WayM2fYbtN6kxMwp1TrmQ4VwPks3URR5pBgWPWhzT98F',
ip: '112.43.234.57',
- bond: 12576.32745,
+ bond: { denom: 'NYM', amount: '1234' },
};
const TxResultMock: TransactionExecuteResult = {
diff --git a/nym-wallet/src/pages/bonding/BondingCard.tsx b/nym-wallet/src/pages/bonding/BondingCard.tsx
index acae090c76..e685704047 100644
--- a/nym-wallet/src/pages/bonding/BondingCard.tsx
+++ b/nym-wallet/src/pages/bonding/BondingCard.tsx
@@ -1,15 +1,17 @@
import React, { useContext, useEffect, useReducer } from 'react';
import { Box, Button, Typography } from '@mui/material';
+import { Link } from '@nymproject/react/link/Link';
import { Gateway, MajorCurrencyAmount, MixNode } from '@nymproject/types';
import { NymCard } from '../../components';
import { NodeIdentityModal } from './NodeIdentityModal';
import { ACTIONTYPE, AmountData, BondState, FormStep, NodeData, NodeType } from './types';
import { AmountModal } from './AmountModal';
-import { AppContext } from '../../context';
+import { AppContext, urls } from '../../context';
import { SummaryModal } from './SummaryModal';
import { bond, vestingBond } from '../../requests';
import { TBondArgs } from '../../types';
-import { SimpleModal } from '../../components/Modals/SimpleModal';
+import { Console } from '../../utils/console';
+import { SimpleDialog } from './SimpleDialog';
const initialState: BondState = {
showModal: false,
@@ -51,7 +53,7 @@ export const BondingCard = () => {
const { formStep, showModal } = state;
console.log(state);
- const { userBalance, clientDetails } = useContext(AppContext);
+ const { userBalance, clientDetails, network } = useContext(AppContext);
useEffect(() => {
dispatch({ type: 'reset' });
@@ -101,11 +103,17 @@ export const BondingCard = () => {
dispatch({ type: 'set_tx', payload: tx });
dispatch({ type: 'next_step' });
})
- .catch(() => {
+ .catch((e: any) => {
+ Console.error('Failed to bond', e);
// TODO do something
});
};
+ const onConfirm = () => {
+ dispatch({ type: 'close_modal' });
+ dispatch({ type: 'reset' });
+ };
+
return (
{
/>
)}
{formStep === 4 && showModal && (
- {
- dispatch({ type: 'close_modal' });
- dispatch({ type: 'reset' });
- }}
- header="Bonding successful"
- okLabel="Done"
+ onClose={onConfirm}
+ title="Bonding successful"
+ confirmText="Done"
>
- Link to transaction on network explorer
-
+
+ View on blockchain
+
+
)}
);
diff --git a/nym-wallet/src/pages/bonding/BoundedMixnodeCard.tsx b/nym-wallet/src/pages/bonding/BoundedMixnodeCard.tsx
deleted file mode 100644
index ba4f9ecc7d..0000000000
--- a/nym-wallet/src/pages/bonding/BoundedMixnodeCard.tsx
+++ /dev/null
@@ -1,11 +0,0 @@
-import React from 'react';
-import { Alert, Button, Grid, Link, Typography } from '@mui/material';
-import { NymCard } from '../../components';
-
-export const BondedMixnodeCard = () => (
-
-
- bonded mixnode data table
-
-
-);
diff --git a/nym-wallet/src/pages/bonding/BoundedGatewayCard.tsx b/nym-wallet/src/pages/bonding/GatewayCard.tsx
similarity index 86%
rename from nym-wallet/src/pages/bonding/BoundedGatewayCard.tsx
rename to nym-wallet/src/pages/bonding/GatewayCard.tsx
index 26c6cd1dca..08794d4f82 100644
--- a/nym-wallet/src/pages/bonding/BoundedGatewayCard.tsx
+++ b/nym-wallet/src/pages/bonding/GatewayCard.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import { Grid } from '@mui/material';
import { NymCard } from '../../components';
-export const BondedGatewayCard = () => (
+export const GatewayCard = () => (
bonded gateway data table
diff --git a/nym-wallet/src/pages/bonding/MixnodeCard.tsx b/nym-wallet/src/pages/bonding/MixnodeCard.tsx
new file mode 100644
index 0000000000..ba38302f6a
--- /dev/null
+++ b/nym-wallet/src/pages/bonding/MixnodeCard.tsx
@@ -0,0 +1,110 @@
+import React, { useMemo } from 'react';
+import { IconButton, Typography } from '@mui/material';
+import { MoreVert } from '@mui/icons-material';
+import { Link } from '@nymproject/react/link/Link';
+import { NymCard } from '../../components';
+import { BondedMixnode } from '../../context';
+import { Cell, Header, NodeTable } from './NodeTable';
+
+const headers: Header[] = [
+ {
+ header: 'Stake',
+ id: 'stake',
+ sx: { pl: 0 },
+ },
+ {
+ header: 'Bond',
+ id: 'bond',
+ },
+ {
+ header: 'Stake saturation',
+ id: 'stake-saturation',
+ tooltip: 'TODO',
+ },
+ {
+ header: 'PM',
+ id: 'profit-margin',
+ tooltip:
+ 'The percentage of the node rewards that you as the node operator will take before the rest of the reward is shared between you and the delegators.',
+ },
+ {
+ header: 'Node rewards',
+ id: 'node-rewards',
+ tooltip: 'This is the total rewards for this node in this epoch including delegates and the operators share.',
+ },
+ {
+ header: 'Operator rewards',
+ id: 'operator-rewards',
+ tooltip:
+ 'This is your (operator) new rewards including the PM and cost. You can compound your rewards manually every epoch or unbond your node to redeem them.',
+ },
+ {
+ header: 'No. delegators',
+ id: 'delegators',
+ },
+ {
+ id: 'menu-button',
+ size: 'small',
+ sx: { pr: 0 },
+ },
+];
+
+export const MixnodeCard = ({ mixnode }: { mixnode: BondedMixnode }) => {
+ const { stake, bond, stakeSaturation, profitMargin, nodeRewards, operatorRewards, delegators } = mixnode;
+ const cells: Cell[] = useMemo(
+ () => [
+ {
+ cell: `${stake.amount} ${stake.denom}`,
+ id: 'stake-cell',
+ sx: { pl: 0 },
+ },
+ {
+ cell: `${bond.amount} ${bond.denom}`,
+ id: 'bond-cell',
+ },
+ {
+ cell: `${stakeSaturation}%`,
+ id: 'stake-saturation-cell',
+ },
+ {
+ cell: `${profitMargin}%`,
+ id: 'pm-cell',
+ },
+ {
+ cell: `${nodeRewards.amount} ${nodeRewards.denom}`,
+ id: 'node-rewards-cell',
+ },
+ {
+ cell: `${operatorRewards.amount} ${operatorRewards.denom}`,
+ id: 'operator-rewards-cell',
+ },
+ {
+ cell: delegators,
+ id: 'delegators-cell',
+ },
+ {
+ cell: (
+
+
+
+ ),
+ id: 'menu-button-cell',
+ align: 'center',
+ size: 'small',
+ sx: { pr: 0 },
+ },
+ ],
+ [mixnode],
+ );
+ return (
+
+
+
+ Check more stats of your node on the{' '}
+
+ explorer
+
+
+
+ );
+};
diff --git a/nym-wallet/src/pages/bonding/NodeTable.tsx b/nym-wallet/src/pages/bonding/NodeTable.tsx
new file mode 100644
index 0000000000..4dcc45fe29
--- /dev/null
+++ b/nym-wallet/src/pages/bonding/NodeTable.tsx
@@ -0,0 +1,79 @@
+import React from 'react';
+import {
+ Box,
+ Stack,
+ SxProps,
+ Table,
+ TableBody,
+ TableCell as MUITableCell,
+ TableContainer,
+ TableHead,
+ TableRow,
+ Tooltip,
+ Typography,
+} from '@mui/material';
+import { InfoOutlined } from '@mui/icons-material';
+
+export interface TableCell {
+ children: React.ReactNode;
+ color?: string;
+ align?: 'center' | 'inherit' | 'justify' | 'left' | 'right';
+ size?: 'small' | 'medium';
+ sx?: SxProps;
+}
+
+export type TableHeader = TableCell & { tooltip?: React.ReactNode };
+
+const CellHeader = ({ children, tooltip, sx, size, align, color }: TableHeader) => (
+
+ {tooltip ? (
+
+
+
+ {children}
+
+
+ ) : (
+ {children}
+ )}
+
+);
+
+const CellValue = ({ children, align, size, color, sx }: TableCell) => (
+
+ {children}
+
+);
+
+export type Header = Omit & { header?: React.ReactNode; id: string };
+export type Cell = Omit & { cell: React.ReactNode; id: string };
+
+export interface TableProps {
+ headers: Header[];
+ cells: Cell[];
+}
+
+export const NodeTable = ({ headers, cells }: TableProps) => (
+
+
+
+
+ {headers.map(({ header, id, tooltip, sx }) => (
+
+ {header}
+
+ ))}
+
+
+
+
+ {cells.map(({ cell, id, align, size, color, sx }) => (
+
+ {cell}
+
+ ))}
+
+
+
+
+);
diff --git a/nym-wallet/src/pages/bonding/SimpleDialog.tsx b/nym-wallet/src/pages/bonding/SimpleDialog.tsx
new file mode 100644
index 0000000000..44175cbc62
--- /dev/null
+++ b/nym-wallet/src/pages/bonding/SimpleDialog.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import { Button, Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material';
+
+interface Props {
+ open: boolean;
+ onClose: () => void;
+ children?: React.ReactNode;
+ title: string;
+ confirmText: string;
+}
+
+export const SimpleDialog = ({ open, onClose, children, title, confirmText }: Props) => (
+
+);
diff --git a/nym-wallet/src/pages/bonding/SummaryModal.tsx b/nym-wallet/src/pages/bonding/SummaryModal.tsx
index c236b57637..88a0b506ac 100644
--- a/nym-wallet/src/pages/bonding/SummaryModal.tsx
+++ b/nym-wallet/src/pages/bonding/SummaryModal.tsx
@@ -34,18 +34,18 @@ export const SummaryModal = ({ open, onClose, onSubmit, header, buttonText, iden
return (
- Identity Key
- {identityKey}
+ Identity Key
+ {identityKey}
-
- Amount
- {`${amount.amount} ${amount.denom}`}
+
+ Amount
+ {`${amount.amount} ${amount.denom}`}
-
- Fee for this operation
- {fee}
+
+ Fee for this operation
+ {fee}
);
diff --git a/nym-wallet/src/pages/bonding/index.tsx b/nym-wallet/src/pages/bonding/index.tsx
index f4109ec65e..8a6746a471 100644
--- a/nym-wallet/src/pages/bonding/index.tsx
+++ b/nym-wallet/src/pages/bonding/index.tsx
@@ -4,8 +4,8 @@ import { Box } from '@mui/material';
import { useBondingContext, BondingContextProvider } from '../../context';
import { PageLayout } from '../../layouts';
import { BondingCard } from './BondingCard';
-import { BondedMixnodeCard } from './BoundedMixnodeCard';
-import { BondedGatewayCard } from './BoundedGatewayCard';
+import { MixnodeCard } from './MixnodeCard';
+import { GatewayCard } from './GatewayCard';
import { EnumRequestStatus } from '../../components';
import { useCheckOwnership } from '../../hooks/useCheckOwnership';
@@ -26,13 +26,7 @@ const Bonding = () => {
return (
- {!bondedMixnode &&
- !bondedGateway &&
- status === EnumRequestStatus.initial &&
- !ownership.hasOwnership &&
- !isLoading && }
- {bondedMixnode && }
- {bondedGateway && }
+ {bondedMixnode && }
);