diff --git a/explorer/src/components/Delegations/components/DelegateIconButton.tsx b/explorer/src/components/Delegations/components/DelegateIconButton.tsx new file mode 100644 index 0000000000..c367d9b98b --- /dev/null +++ b/explorer/src/components/Delegations/components/DelegateIconButton.tsx @@ -0,0 +1,24 @@ +import * as React from 'react'; +import { useClipboard } from 'use-clipboard-copy'; +import ContentCopyIcon from '@mui/icons-material/ContentCopy'; +import DoneIcon from '@mui/icons-material/Done'; +import { Box, Tooltip } from '@mui/material'; +import { SxProps } from '@mui/system'; +import { DelegateSVG } from '../../../icons/DelevateSVG'; + +export const DelegateIconButton: FCWithChildren<{ + tooltip?: React.ReactNode; + onDelegate: () => void; + sx?: SxProps; +}> = ({ tooltip, onDelegate, sx }) => { + const handleDelegateClick = () => { + onDelegate(); + }; + return ( + + + + + + ); +}; diff --git a/explorer/src/components/Delegations/components/DelegateModal.tsx b/explorer/src/components/Delegations/components/DelegateModal.tsx index bc4030c7f2..50bda7b3df 100644 --- a/explorer/src/components/Delegations/components/DelegateModal.tsx +++ b/explorer/src/components/Delegations/components/DelegateModal.tsx @@ -20,7 +20,8 @@ export const DelegateModal: FCWithChildren<{ open: boolean; onClose: () => void; onOk?: (delegationModalProps: DelegationModalProps) => void; - identityKey?: string; + initialIdentityKey?: string; + initialMixId?: number; onIdentityKeyChanged?: (identityKey: string) => void; onAmountChanged?: (amount: string) => void; header?: string; @@ -43,13 +44,14 @@ export const DelegateModal: FCWithChildren<{ onOk, header, buttonText, - identityKey: initialIdentityKey, + initialIdentityKey, + initialMixId, // accountBalance, denom, sx, backdropProps, }) => { - const [mixId, setMixId] = useState(); + const [mixId, setMixId] = useState(initialMixId); const [identityKey, setIdentityKey] = useState(initialIdentityKey); const [amount, setAmount] = useState(); const [isValidated, setValidated] = useState(false); @@ -62,18 +64,7 @@ export const DelegateModal: FCWithChildren<{ data?: string; }>({ status: 'loading', data: undefined }); - const { - username, - connect, - disconnect, - wallet, - openView, - address, - getCosmWasmClient, - isWalletConnected, - getSigningCosmWasmClient, - estimateFee, - } = useChain('nyx'); + const { address, getCosmWasmClient, isWalletConnected, getSigningCosmWasmClient } = useChain('nyx'); useEffect(() => { const getClient = async () => { @@ -154,6 +145,7 @@ export const DelegateModal: FCWithChildren<{ ): Promise => { const amount = (Number(funds![0].amount) * 1000000).toString(); const uNymFunds = [{ amount: amount, denom: 'unym' }]; + console.log('cosmWasmSignerClient :>> ', cosmWasmSignerClient); return await cosmWasmSignerClient.execute( address, MIXNET_CONTRACT_ADDRESS, @@ -271,6 +263,7 @@ export const DelegateModal: FCWithChildren<{ helperText={mixIdError} onChange={handleMixIDChanged} InputLabelProps={{ shrink: true }} + value={mixId?.toString() || ''} /> diff --git a/explorer/src/components/MixNodes/DetailSection.tsx b/explorer/src/components/MixNodes/DetailSection.tsx index a07a6fb7d8..6592e28f4f 100644 --- a/explorer/src/components/MixNodes/DetailSection.tsx +++ b/explorer/src/components/MixNodes/DetailSection.tsx @@ -16,6 +16,7 @@ export const MixNodeDetailSection: FCWithChildren = ({ mixNo const palette = [theme.palette.text.primary]; const isMobile = useIsMobile(); const statusText = React.useMemo(() => getMixNodeStatusText(mixNodeRow.status), [mixNodeRow.status]); + console.log('mixNodeRow :>> ', mixNodeRow); return ( diff --git a/explorer/src/icons/DelevateSVG.tsx b/explorer/src/icons/DelevateSVG.tsx new file mode 100644 index 0000000000..49957c3e63 --- /dev/null +++ b/explorer/src/icons/DelevateSVG.tsx @@ -0,0 +1,23 @@ +import * as React from 'react'; +import { useTheme } from '@mui/material/styles'; + +export const DelegateSVG: FCWithChildren = () => { + const theme = useTheme(); + const color = theme.palette.text.primary; + + return ( + + + + + + + + ); +}; diff --git a/explorer/src/pages/Mixnodes/index.tsx b/explorer/src/pages/Mixnodes/index.tsx index 04a9384b61..222dcb0d61 100644 --- a/explorer/src/pages/Mixnodes/index.tsx +++ b/explorer/src/pages/Mixnodes/index.tsx @@ -19,6 +19,13 @@ import { splice } from '../../utils'; import { getMixNodeStatusColor } from '../../components/MixNodes/Status'; import { MixNodeStatusDropdown } from '../../components/MixNodes/StatusDropdown'; import { Tooltip } from '../../components/Tooltip'; +import { DelegateIconButton } from '../../components/Delegations/components/DelegateIconButton'; +import { ChainProvider } from '@cosmos-kit/react'; +import { assets, chains } from 'chain-registry'; +import { wallets as keplr } from '@cosmos-kit/keplr'; +import { DelegationModal, DelegationModalProps } from '../../components/Delegations/components/DelegationModal'; +import { useMemo, useState } from 'react'; +import { DelegateModal } from '../../components/Delegations/components/DelegateModal'; const getCellFontStyle = (theme: Theme, row: MixnodeRowType, textColor?: string) => { const color = textColor || getMixNodeStatusColor(theme, row.status); @@ -40,10 +47,59 @@ export const PageMixnodes: FCWithChildren = () => { const [filteredMixnodes, setFilteredMixnodes] = React.useState([]); const [pageSize, setPageSize] = React.useState('10'); const [searchTerm, setSearchTerm] = React.useState(''); + const [mixId, setMixId] = useState(); + const [identityKey, setIdentityKey] = useState(); + const [showNewDelegationModal, setShowNewDelegationModal] = useState(false); + const [confirmationModalProps, setConfirmationModalProps] = useState(); const theme = useTheme(); const { status } = useParams<{ status: MixnodeStatusWithAll | undefined }>(); const navigate = useNavigate(); + const assetsFixedUp = useMemo(() => { + const nyx = assets.find((a) => a.chain_name === 'nyx'); + if (nyx) { + const nyxCoin = nyx.assets.find((a) => a.name === 'nyx'); + if (nyxCoin) { + nyxCoin.coingecko_id = 'nyx'; + } + nyx.assets = nyx.assets.reverse(); + } + return assets; + }, [assets]); + + const chainsFixedUp = useMemo(() => { + const nyx = chains.find((c) => c.chain_id === 'nyx'); + if (nyx) { + if (!nyx.staking) { + nyx.staking = { + staking_tokens: [{ denom: 'unyx' }], + lock_duration: { + blocks: 10000, + }, + }; + if (nyx.apis) nyx.apis.rpc = [{ address: 'https://rpc.nymtech.net', provider: 'nym' }]; + } + } + return chains; + }, [chains]); + 3; + + const openDelegationModal = (identityKey: string, mixId: number) => { + setMixId(mixId); + setIdentityKey(identityKey); + }; + + React.useEffect(() => { + if (identityKey && mixId) { + setShowNewDelegationModal(true); + } + }, [identityKey, mixId]); + + const handleNewDelegation = (delegationModalProps: DelegationModalProps) => { + setShowNewDelegationModal(false); + setConfirmationModalProps(delegationModalProps); + }; + const handleSearch = (str: string) => { setSearchTerm(str.toLowerCase()); }; @@ -88,7 +144,7 @@ export const PageMixnodes: FCWithChildren = () => { disableColumnMenu: true, renderHeader: () => , headerClassName: 'MuiDataGrid-header-override', - width: 100, + width: 70, headerAlign: 'left', renderCell: (params: GridRenderCellParams) => ( { disableColumnMenu: true, renderHeader: () => , headerClassName: 'MuiDataGrid-header-override', - width: 170, + width: 190, headerAlign: 'left', renderCell: (params: GridRenderCellParams) => ( <> + onDelegate(params.value.identityKey, params.value.mixId)} + onDelegate={() => { + openDelegationModal(params.value, params.row.mix_id); + console.log('object :>> ', params.value, params.row.mix_id); + }} + /> { + + {showNewDelegationModal && ( + 'amino', + }} + > + setShowNewDelegationModal(false)} + header="Delegate" + buttonText="Delegate stake" + denom={'nym'} // clientDetails?.display_mix_denom || 'nym'} + onOk={(delegationModalProps: DelegationModalProps) => handleNewDelegation(delegationModalProps)} + // accountBalance={balance?.printable_balance} + initialIdentityKey={identityKey} + initialMixId={mixId} + /> + + )} + + {confirmationModalProps && ( + { + setConfirmationModalProps(undefined); + // await fetchBalance(); + }} + /> + )} ); };