diff --git a/nym-wallet/src/pages/bonding/Bonding.tsx b/nym-wallet/src/pages/bonding/Bonding.tsx new file mode 100644 index 0000000000..519b491b20 --- /dev/null +++ b/nym-wallet/src/pages/bonding/Bonding.tsx @@ -0,0 +1,255 @@ +import React, { useContext, useEffect, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { FeeDetails } from '@nymproject/types'; +import { TPoolOption } from 'src/components'; +import { Bond } from 'src/components/Bonding/Bond'; +import { BondedMixnode } from 'src/components/Bonding/BondedMixnode'; +import { TBondedMixnodeActions } from 'src/components/Bonding/BondedMixnodeActions'; +import { BondGatewayModal } from 'src/components/Bonding/modals/BondGatewayModal'; +import { BondMixnodeModal } from 'src/components/Bonding/modals/BondMixnodeModal'; +import { ConfirmationDetailProps, ConfirmationDetailsModal } from 'src/components/Bonding/modals/ConfirmationModal'; +import { NodeSettings } from 'src/components/Bonding/modals/NodeSettingsModal'; +import { UnbondModal } from 'src/components/Bonding/modals/UnbondModal'; +import { ErrorModal } from 'src/components/Modals/ErrorModal'; +import { LoadingModal } from 'src/components/Modals/LoadingModal'; +import { AppContext, urls } from 'src/context/main'; +import { isGateway, isMixnode, TBondGatewayArgs, TBondMixNodeArgs } from 'src/types'; +import { BondedGateway } from 'src/components/Bonding/BondedGateway'; +import { RedeemRewardsModal } from 'src/components/Bonding/modals/RedeemRewardsModal'; +import { CompoundRewardsModal } from 'src/components/Bonding/modals/CompoundRewardsModal'; +import { BondingContextProvider, useBondingContext } from '../../context'; +import { Box, Button } from '@mui/material'; + +const Bonding = () => { + const [showModal, setShowModal] = useState< + 'bond-mixnode' | 'bond-gateway' | 'bond-more' | 'unbond' | 'redeem' | 'compound' | 'node-settings' + >(); + const [confirmationDetails, setConfirmationDetails] = useState(); + + const { + network, + clientDetails, + userBalance: { originalVesting }, + } = useContext(AppContext); + + const { + bondedNode, + bondMixnode, + bondGateway, + unbond, + updateMixnode, + redeemRewards, + compoundRewards, + isLoading, + checkOwnership, + } = useBondingContext(); + + const navigate = useNavigate(); + + const handleCloseModal = async () => { + setShowModal(undefined); + await checkOwnership(); + }; + + const handleError = (error: string) => { + setShowModal(undefined); + setConfirmationDetails({ + status: 'error', + title: 'An error occurred', + subtitle: error, + }); + }; + + const handleBondMixnode = async (data: TBondMixNodeArgs, tokenPool: TPoolOption) => { + setShowModal(undefined); + const tx = await bondMixnode(data, tokenPool); + setConfirmationDetails({ + status: 'success', + title: 'Bond successful', + txUrl: `${urls(network).blockExplorer}/transaction/${tx?.transaction_hash}`, + }); + return undefined; + }; + + const handleBondGateway = async (data: TBondGatewayArgs, tokenPool: TPoolOption) => { + setShowModal(undefined); + const tx = await bondGateway(data, tokenPool); + setConfirmationDetails({ + status: 'success', + title: 'Bond successful', + txUrl: `${urls(network).blockExplorer}/transaction/${tx?.transaction_hash}`, + }); + }; + + const handleUnbond = async (fee?: FeeDetails) => { + setShowModal(undefined); + const tx = await unbond(fee); + setConfirmationDetails({ + status: 'success', + title: 'Unbond successful', + txUrl: `${urls(network).blockExplorer}/transaction/${tx?.transaction_hash}`, + }); + }; + + const handleUpdateProfitMargin = async (profitMargin: number, fee?: FeeDetails) => { + setShowModal(undefined); + const tx = await updateMixnode(profitMargin, fee); + setConfirmationDetails({ + status: 'success', + title: 'Profit margin update successful', + txUrl: `${urls(network).blockExplorer}/transaction/${tx?.transaction_hash}`, + }); + }; + + const handleRedeemReward = async (fee?: FeeDetails) => { + setShowModal(undefined); + const tx = await redeemRewards(fee); + setConfirmationDetails({ + status: 'success', + title: 'Rewards redeemed successfully', + txUrl: `${urls(network).blockExplorer}/transaction/${tx?.transaction_hash}`, + }); + }; + + const handleCompoundReward = async (fee?: FeeDetails) => { + setShowModal(undefined); + const tx = await compoundRewards(fee); + setConfirmationDetails({ + status: 'success', + title: 'Rewards compounded successfully', + txUrl: `${urls(network).blockExplorer}/transaction/${tx?.transaction_hash}`, + }); + return undefined; + }; + + const handleBondedMixnodeAction = (action: TBondedMixnodeActions) => { + switch (action) { + case 'bondMore': { + setShowModal('bond-more'); + break; + } + case 'unbond': { + setShowModal('unbond'); + break; + } + case 'redeem': { + setShowModal('redeem'); + break; + } + case 'compound': { + setShowModal('compound'); + break; + } + case 'nodeSettings': { + setShowModal('node-settings'); + break; + } + default: { + return undefined; + } + } + return undefined; + }; + + return ( + + + {!bondedNode && setShowModal('bond-mixnode')} />} + + {bondedNode && isMixnode(bondedNode) && ( + handleBondedMixnodeAction(action)} + /> + )} + + {bondedNode && isGateway(bondedNode) && ( + + )} + {showModal === 'bond-mixnode' && ( + setShowModal('bond-gateway')} + onClose={() => setShowModal(undefined)} + onError={handleError} + /> + )} + + {showModal === 'bond-gateway' && ( + setShowModal('bond-mixnode')} + onClose={() => setShowModal(undefined)} + onError={handleError} + /> + )} + + {showModal === 'unbond' && bondedNode && ( + setShowModal(undefined)} + onConfirm={handleUnbond} + onError={handleError} + /> + )} + + {showModal === 'redeem' && bondedNode && isMixnode(bondedNode) && ( + setShowModal(undefined)} + onConfirm={handleRedeemReward} + onError={handleError} + /> + )} + + {showModal === 'compound' && bondedNode && isMixnode(bondedNode) && ( + setShowModal(undefined)} + onConfirm={handleCompoundReward} + onError={handleError} + /> + )} + + {showModal === 'node-settings' && bondedNode && isMixnode(bondedNode) && ( + setShowModal(undefined)} + onError={handleError} + currentPm={bondedNode.profitMargin} + isVesting={Boolean(bondedNode.proxy)} + /> + )} + + {confirmationDetails && confirmationDetails.status === 'success' && ( + { + setConfirmationDetails(undefined); + handleCloseModal(); + }} + /> + )} + + {confirmationDetails && confirmationDetails.status === 'error' && ( + setConfirmationDetails(undefined)} /> + )} + + {isLoading && } + + ); +}; + +export const BondingPage = () => ( + + + +); diff --git a/nym-wallet/src/pages/bonding/BondingPage.stories.tsx b/nym-wallet/src/pages/bonding/BondingPage.stories.tsx index ede7eaa20a..1a2caa1f2e 100644 --- a/nym-wallet/src/pages/bonding/BondingPage.stories.tsx +++ b/nym-wallet/src/pages/bonding/BondingPage.stories.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { BondingPage } from './index'; +import { BondingPage } from './Bonding'; import { MockBondingContextProvider } from '../../context/mocks/bonding'; export default { diff --git a/nym-wallet/src/pages/bonding/index.tsx b/nym-wallet/src/pages/bonding/index.tsx index 519b491b20..1e98989887 100644 --- a/nym-wallet/src/pages/bonding/index.tsx +++ b/nym-wallet/src/pages/bonding/index.tsx @@ -1,255 +1,2 @@ -import React, { useContext, useEffect, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { FeeDetails } from '@nymproject/types'; -import { TPoolOption } from 'src/components'; -import { Bond } from 'src/components/Bonding/Bond'; -import { BondedMixnode } from 'src/components/Bonding/BondedMixnode'; -import { TBondedMixnodeActions } from 'src/components/Bonding/BondedMixnodeActions'; -import { BondGatewayModal } from 'src/components/Bonding/modals/BondGatewayModal'; -import { BondMixnodeModal } from 'src/components/Bonding/modals/BondMixnodeModal'; -import { ConfirmationDetailProps, ConfirmationDetailsModal } from 'src/components/Bonding/modals/ConfirmationModal'; -import { NodeSettings } from 'src/components/Bonding/modals/NodeSettingsModal'; -import { UnbondModal } from 'src/components/Bonding/modals/UnbondModal'; -import { ErrorModal } from 'src/components/Modals/ErrorModal'; -import { LoadingModal } from 'src/components/Modals/LoadingModal'; -import { AppContext, urls } from 'src/context/main'; -import { isGateway, isMixnode, TBondGatewayArgs, TBondMixNodeArgs } from 'src/types'; -import { BondedGateway } from 'src/components/Bonding/BondedGateway'; -import { RedeemRewardsModal } from 'src/components/Bonding/modals/RedeemRewardsModal'; -import { CompoundRewardsModal } from 'src/components/Bonding/modals/CompoundRewardsModal'; -import { BondingContextProvider, useBondingContext } from '../../context'; -import { Box, Button } from '@mui/material'; - -const Bonding = () => { - const [showModal, setShowModal] = useState< - 'bond-mixnode' | 'bond-gateway' | 'bond-more' | 'unbond' | 'redeem' | 'compound' | 'node-settings' - >(); - const [confirmationDetails, setConfirmationDetails] = useState(); - - const { - network, - clientDetails, - userBalance: { originalVesting }, - } = useContext(AppContext); - - const { - bondedNode, - bondMixnode, - bondGateway, - unbond, - updateMixnode, - redeemRewards, - compoundRewards, - isLoading, - checkOwnership, - } = useBondingContext(); - - const navigate = useNavigate(); - - const handleCloseModal = async () => { - setShowModal(undefined); - await checkOwnership(); - }; - - const handleError = (error: string) => { - setShowModal(undefined); - setConfirmationDetails({ - status: 'error', - title: 'An error occurred', - subtitle: error, - }); - }; - - const handleBondMixnode = async (data: TBondMixNodeArgs, tokenPool: TPoolOption) => { - setShowModal(undefined); - const tx = await bondMixnode(data, tokenPool); - setConfirmationDetails({ - status: 'success', - title: 'Bond successful', - txUrl: `${urls(network).blockExplorer}/transaction/${tx?.transaction_hash}`, - }); - return undefined; - }; - - const handleBondGateway = async (data: TBondGatewayArgs, tokenPool: TPoolOption) => { - setShowModal(undefined); - const tx = await bondGateway(data, tokenPool); - setConfirmationDetails({ - status: 'success', - title: 'Bond successful', - txUrl: `${urls(network).blockExplorer}/transaction/${tx?.transaction_hash}`, - }); - }; - - const handleUnbond = async (fee?: FeeDetails) => { - setShowModal(undefined); - const tx = await unbond(fee); - setConfirmationDetails({ - status: 'success', - title: 'Unbond successful', - txUrl: `${urls(network).blockExplorer}/transaction/${tx?.transaction_hash}`, - }); - }; - - const handleUpdateProfitMargin = async (profitMargin: number, fee?: FeeDetails) => { - setShowModal(undefined); - const tx = await updateMixnode(profitMargin, fee); - setConfirmationDetails({ - status: 'success', - title: 'Profit margin update successful', - txUrl: `${urls(network).blockExplorer}/transaction/${tx?.transaction_hash}`, - }); - }; - - const handleRedeemReward = async (fee?: FeeDetails) => { - setShowModal(undefined); - const tx = await redeemRewards(fee); - setConfirmationDetails({ - status: 'success', - title: 'Rewards redeemed successfully', - txUrl: `${urls(network).blockExplorer}/transaction/${tx?.transaction_hash}`, - }); - }; - - const handleCompoundReward = async (fee?: FeeDetails) => { - setShowModal(undefined); - const tx = await compoundRewards(fee); - setConfirmationDetails({ - status: 'success', - title: 'Rewards compounded successfully', - txUrl: `${urls(network).blockExplorer}/transaction/${tx?.transaction_hash}`, - }); - return undefined; - }; - - const handleBondedMixnodeAction = (action: TBondedMixnodeActions) => { - switch (action) { - case 'bondMore': { - setShowModal('bond-more'); - break; - } - case 'unbond': { - setShowModal('unbond'); - break; - } - case 'redeem': { - setShowModal('redeem'); - break; - } - case 'compound': { - setShowModal('compound'); - break; - } - case 'nodeSettings': { - setShowModal('node-settings'); - break; - } - default: { - return undefined; - } - } - return undefined; - }; - - return ( - - - {!bondedNode && setShowModal('bond-mixnode')} />} - - {bondedNode && isMixnode(bondedNode) && ( - handleBondedMixnodeAction(action)} - /> - )} - - {bondedNode && isGateway(bondedNode) && ( - - )} - {showModal === 'bond-mixnode' && ( - setShowModal('bond-gateway')} - onClose={() => setShowModal(undefined)} - onError={handleError} - /> - )} - - {showModal === 'bond-gateway' && ( - setShowModal('bond-mixnode')} - onClose={() => setShowModal(undefined)} - onError={handleError} - /> - )} - - {showModal === 'unbond' && bondedNode && ( - setShowModal(undefined)} - onConfirm={handleUnbond} - onError={handleError} - /> - )} - - {showModal === 'redeem' && bondedNode && isMixnode(bondedNode) && ( - setShowModal(undefined)} - onConfirm={handleRedeemReward} - onError={handleError} - /> - )} - - {showModal === 'compound' && bondedNode && isMixnode(bondedNode) && ( - setShowModal(undefined)} - onConfirm={handleCompoundReward} - onError={handleError} - /> - )} - - {showModal === 'node-settings' && bondedNode && isMixnode(bondedNode) && ( - setShowModal(undefined)} - onError={handleError} - currentPm={bondedNode.profitMargin} - isVesting={Boolean(bondedNode.proxy)} - /> - )} - - {confirmationDetails && confirmationDetails.status === 'success' && ( - { - setConfirmationDetails(undefined); - handleCloseModal(); - }} - /> - )} - - {confirmationDetails && confirmationDetails.status === 'error' && ( - setConfirmationDetails(undefined)} /> - )} - - {isLoading && } - - ); -}; - -export const BondingPage = () => ( - - - -); +export * from './Bonding'; +export * from './node-settings'; diff --git a/nym-wallet/src/pages/bonding/node-settings/general-settings/InfoSettings.tsx b/nym-wallet/src/pages/bonding/node-settings/general-settings/InfoSettings.tsx new file mode 100644 index 0000000000..553912c52a --- /dev/null +++ b/nym-wallet/src/pages/bonding/node-settings/general-settings/InfoSettings.tsx @@ -0,0 +1,96 @@ +import React, { useContext, useEffect, useState } from 'react'; +import { Box, Button, Divider, Typography, TextField, Grid } from '@mui/material'; + +const ModifiedTextField = ({ field }: { field: { id: string; title: string; value: string } }) => { + return ( + + {field.title} + console.log(`Field ${field.id} has change`, e.target.value)} + autoFocus + fullWidth + /> + + ); +}; + +export const InfoSettings = ({ onSaveChanges }: { onSaveChanges: () => void }) => { + const [valueChanged, setValueChanged] = useState(false); + const [mixPortValue, setMixPortValue] = useState('1789'); + + useEffect(() => { + console.log(Object.entries(portSettings)); + }, []); + const portSettings = [ + { id: 'mixPort', title: 'Mix port', value: '1789' }, + { id: 'verlocPort', title: 'Verloc Port', value: '1790' }, + { id: 'httpPort', title: 'HTTP Port', value: '8000' }, + ]; + + const hostSettings = [{ id: 'host', title: 'Host', value: '95.216.92.229' }]; + const versionSettings = [{ id: 'version', title: 'Version', value: '95.216.92.229' }]; + return ( + + + + + Port + Change profit margin of your node + + + {portSettings.map((item) => ( + + console.log(`Field ${item.id} has change`, e.target.value)} + autoFocus + fullWidth + /> + + ))} + + + + + + Host + Lock wallet after certain time + + + {hostSettings.map((item) => ( + + ))} + + + + + + Version + Lock wallet after certain time + + + {versionSettings.map((item) => ( + + ))} + + + + + + + ); +}; diff --git a/nym-wallet/src/pages/bonding/node-settings/general-settings/ParametersSettings.tsx b/nym-wallet/src/pages/bonding/node-settings/general-settings/ParametersSettings.tsx new file mode 100644 index 0000000000..dcce36bf27 --- /dev/null +++ b/nym-wallet/src/pages/bonding/node-settings/general-settings/ParametersSettings.tsx @@ -0,0 +1,62 @@ +import React, { useContext, useEffect } from 'react'; +import { Alert, Grid, Typography } from '@mui/material'; +import { Link } from '@nymproject/react/link/Link'; +import { NymCard, ClientAddress } from '../../../../components'; +import { AppContext, urls } from '../../../../context/main'; + +export const ParametersSettings = ({ + onChange, + onSaveChanges, +}: { + onChange: () => void; + onSaveChanges: () => void; +}) => { + const { userBalance, clientDetails, network } = useContext(AppContext); + + useEffect(() => { + userBalance.fetchBalance(); + }, []); + + return ( + } + > + + + {userBalance.error && ( + + {userBalance.error} + + )} + {!userBalance.error && ( + (theme.palette.mode === 'light' ? '600' : '400'), + fontSize: 28, + }} + variant="h5" + > + {userBalance.balance?.printable_balance} + + )} + + {network && ( + + + + )} + + + ); +}; diff --git a/nym-wallet/src/pages/bonding/node-settings/general-settings/index.tsx b/nym-wallet/src/pages/bonding/node-settings/general-settings/index.tsx new file mode 100644 index 0000000000..5abf66ba07 --- /dev/null +++ b/nym-wallet/src/pages/bonding/node-settings/general-settings/index.tsx @@ -0,0 +1,38 @@ +import React, { useContext, useEffect, useState } from 'react'; +import { Box, Button, Divider, Grid } from '@mui/material'; +import { InfoSettings } from './InfoSettings'; +import { ParametersSettings } from './ParametersSettings'; +import { AppContext } from '../../../../context/main'; + +const nodeGeneralNav = ['Info', 'Parameters']; + +export const NodeGeneralSettings = ({ onSaveChanges }: { onSaveChanges: () => void }) => { + const [settingsCard, setSettingsCard] = useState(nodeGeneralNav[0]); + + const { userBalance } = useContext(AppContext); + + useEffect(() => { + console.log('a'); + }, [userBalance]); + + return ( + + + + {nodeGeneralNav.map((item) => ( + + ))} + + + {settingsCard === nodeGeneralNav[0] && console.log('saving...')} />} + {settingsCard === nodeGeneralNav[1] &&

bye

} +
+
+ ); +}; diff --git a/nym-wallet/src/pages/bonding/node-settings/index.tsx b/nym-wallet/src/pages/bonding/node-settings/index.tsx new file mode 100644 index 0000000000..18245bb6ca --- /dev/null +++ b/nym-wallet/src/pages/bonding/node-settings/index.tsx @@ -0,0 +1,71 @@ +import React, { useContext, useEffect, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { Box, Typography, Stack, IconButton, Toolbar, Button, Divider } from '@mui/material'; +import { Close } from '@mui/icons-material'; +import { Node as NodeIcon } from 'src/svg-icons/node'; +import { NymCard } from '../../../components'; +import { PageLayout } from '../../../layouts'; +// import { AppContext } from '../../context/main'; + +import { NodeGeneralSettings } from './general-settings'; +// import { NodeParametersCard } from './InfoSettings'; +// import { UnbondModal } from '../../modals'; + +const nodeSettingsNav = ['General', 'Unbond']; + +export const NodeSettingsPage = () => { + const [settingsCard, setSettingsCard] = useState(nodeSettingsNav[0]); + + const navigate = useNavigate(); + + return ( + + + + + + + Node Settings + + + navigate('/bonding')} + size="small" + sx={{ + color: 'text.primary', + }} + > + + + + + {nodeSettingsNav.map((item) => ( + + ))} + + + } + > + + {settingsCard === nodeSettingsNav[0] && ( + console.log('save changes')} /> + )} + {settingsCard === nodeSettingsNav[1] && ( + console.log('save changes')} /> + )} + + + ); +}; diff --git a/nym-wallet/src/pages/index.ts b/nym-wallet/src/pages/index.ts index 12cb6c092d..2976b7890a 100644 --- a/nym-wallet/src/pages/index.ts +++ b/nym-wallet/src/pages/index.ts @@ -5,4 +5,3 @@ export * from './bonding'; export * from './delegation'; export * from './internal-docs'; export * from './unbond'; -export * from './settings'; diff --git a/nym-wallet/src/pages/settings/index.ts b/nym-wallet/src/pages/settings/index.ts deleted file mode 100644 index 162957508f..0000000000 --- a/nym-wallet/src/pages/settings/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './node-settings'; diff --git a/nym-wallet/src/pages/settings/node-settings.tsx b/nym-wallet/src/pages/settings/node-settings.tsx deleted file mode 100644 index 9830dbc0b4..0000000000 --- a/nym-wallet/src/pages/settings/node-settings.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import React, { useContext, useEffect, useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { Box, Button } from '@mui/material'; -import { AppContext } from '../../context/main'; - -import { PageLayout } from '../../layouts'; - -export const NodeSettingsPage = () => { - // const [showTransferModal, setShowTransferModal] = useState(false); - // const [showVestingCard, setShowVestingCard] = useState(false); - - const { userBalance } = useContext(AppContext); - - const navigate = useNavigate(); - - useEffect(() => { - const { originalVesting, currentVestingPeriod, tokenAllocation } = userBalance; - // if ( - // originalVesting && - // currentVestingPeriod === 'After' && - // tokenAllocation?.locked === '0' && - // tokenAllocation?.vesting === '0' && - // tokenAllocation?.spendable === '0' - // ) { - // setShowVestingCard(false); - // } else if (originalVesting) { - // setShowVestingCard(true); - // } - }, [userBalance]); - - const handleShowTransferModal = async () => { - await userBalance.refreshBalances(); - // setShowTransferModal(true); - }; - - return ( - - -

hello

- -
-
- ); -};