Typescript: fix eslint errors and add GitHub Action for linting (#2886)
* Fix eslint errors * GitHub Actions: add Typescript project linting * Fix dependency * Revert changes and exclude rule Co-authored-by: Mark Sinclair <mmsinclair@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
name: CI for linting Typescript
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'ts-packages/**'
|
||||
- 'sdk/typescript/**'
|
||||
- nym-connect
|
||||
- nym-wallet
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: custom-runner-linux
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install rsync
|
||||
run: sudo apt-get install rsync
|
||||
- uses: rlespinasse/github-slug-action@v3.x
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Setup yarn
|
||||
run: npm install -g yarn
|
||||
- name: Lint
|
||||
run: yarn && yarn lint
|
||||
- name: Keybase - Node Install
|
||||
run: npm install
|
||||
working-directory: .github/workflows/support-files
|
||||
- name: Keybase - Send Notification
|
||||
env:
|
||||
NYM_NOTIFICATION_KIND: ts-packages
|
||||
NYM_PROJECT_NAME: "ts-packages"
|
||||
NYM_CI_WWW_BASE: "${{ secrets.NYM_CI_WWW_BASE }}"
|
||||
NYM_CI_WWW_LOCATION: "ts-${{ env.GITHUB_REF_SLUG }}"
|
||||
GIT_COMMIT_MESSAGE: "${{ github.event.head_commit.message }}"
|
||||
GIT_BRANCH: "${GITHUB_REF##*/}"
|
||||
KEYBASE_NYMBOT_USERNAME: "${{ secrets.KEYBASE_NYMBOT_USERNAME }}"
|
||||
KEYBASE_NYMBOT_PAPERKEY: "${{ secrets.KEYBASE_NYMBOT_PAPERKEY }}"
|
||||
KEYBASE_NYMBOT_TEAM: "${{ secrets.KEYBASE_NYMBOT_TEAM }}"
|
||||
KEYBASE_NYM_CHANNEL: "ci-ts-packages"
|
||||
IS_SUCCESS: "${{ job.status == 'success' }}"
|
||||
MATRIX_SERVER: "${{ secrets.MATRIX_SERVER }}"
|
||||
MATRIX_ROOM: "${{ secrets.MATRIX_ROOM }}"
|
||||
MATRIX_USER_ID: "${{ secrets.MATRIX_USER_ID }}"
|
||||
MATRIX_TOKEN: "${{ secrets.MATRIX_TOKEN }}"
|
||||
MATRIX_DEVICE_ID: "${{ secrets.MATRIX_DEVICE_ID }}"
|
||||
uses: docker://keybaseio/client:stable-node
|
||||
with:
|
||||
args: .github/workflows/support-files/notifications/entry_point.sh
|
||||
+3
-1
@@ -1,7 +1,9 @@
|
||||
{
|
||||
"packages": [
|
||||
"ts-packages/*",
|
||||
"nym-wallet"
|
||||
"nym-wallet",
|
||||
"nym-connect",
|
||||
"sdk/typescript/**"
|
||||
],
|
||||
"version": "0.0.0"
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
"@mui/icons-material": "^5.2.0",
|
||||
"@mui/material": "^5.2.2",
|
||||
"@mui/styles": "^5.2.2",
|
||||
"@mui/system": ">= 5",
|
||||
"@mui/lab": "^5.0.0-alpha.72",
|
||||
"@nymproject/react": "^1.0.0",
|
||||
"@tauri-apps/api": "^1.2.0",
|
||||
"@tauri-apps/tauri-forage": "^1.0.0-beta.2",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Typography, Box } from '@mui/material';
|
||||
import { Box } from '@mui/material';
|
||||
import { useClientContext } from 'src/context/main';
|
||||
|
||||
export const AppVersion = () => {
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
import React from 'react';
|
||||
import { ConnectionStatusKind } from '../types';
|
||||
|
||||
const getBusyFillColor = (color: string): string => {
|
||||
if (color === '#F4B02D') {
|
||||
return '#21D072';
|
||||
}
|
||||
return '#F4B02D';
|
||||
};
|
||||
|
||||
const getStatusFillColor = (status: ConnectionStatusKind, hover: boolean, isError: boolean): string => {
|
||||
if (isError && hover) {
|
||||
return '#21D072';
|
||||
@@ -57,7 +50,7 @@ export const ConnectionButton: FCWithChildren<{
|
||||
busy?: boolean;
|
||||
isError?: boolean;
|
||||
onClick?: (status: ConnectionStatusKind) => void;
|
||||
}> = ({ status, disabled, isError, onClick, busy }) => {
|
||||
}> = ({ status, disabled, isError, onClick }) => {
|
||||
const [hover, setHover] = React.useState<boolean>(false);
|
||||
|
||||
const handleClick = React.useCallback(() => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Box, CircularProgress, Divider, Stack, Tooltip, Typography } from '@mui/material';
|
||||
import { Box, CircularProgress, Tooltip, Typography } from '@mui/material';
|
||||
import { DateTime } from 'luxon';
|
||||
import { ConnectionStatusKind, GatewayPerformance } from '../types';
|
||||
import { ServiceProvider } from '../types/directory';
|
||||
|
||||
@@ -18,6 +18,7 @@ export const Wrapper: FCWithChildren<{ disabled: boolean }> = ({ disabled, child
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-pascal-case */
|
||||
import * as React from 'react';
|
||||
import { ComponentMeta } from '@storybook/react';
|
||||
import { NymShipyardTheme } from 'src/theme';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-no-useless-fragment */
|
||||
import React from 'react';
|
||||
import LoadingButton from '@mui/lab/LoadingButton';
|
||||
import {
|
||||
@@ -134,7 +135,7 @@ const StatusText: FCWithChildren<{ entry: DrawEntry }> = ({ entry }) => {
|
||||
|
||||
export const TestAndEarnDraws: FCWithChildren<{
|
||||
sx?: SxProps;
|
||||
}> = ({ sx }) => {
|
||||
}> = () => {
|
||||
const context = useTestAndEarnContext();
|
||||
|
||||
const draws = React.useMemo<DrawEntry[]>(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { WalletAddressFormField } from '@nymproject/react/account/WalletAddressFormField';
|
||||
import { SxProps } from '@mui/system';
|
||||
import { Paper, Stack, Button, Box } from '@mui/material';
|
||||
import { Box, Button, Paper, Stack } from '@mui/material';
|
||||
import ArrowCircleRightIcon from '@mui/icons-material/ArrowCircleRight';
|
||||
import { useTestAndEarnContext } from './context/TestAndEarnContext';
|
||||
|
||||
@@ -10,7 +10,7 @@ export const TestAndEarnEnterWalletAddress: FCWithChildren<{
|
||||
placeholder?: string;
|
||||
onSubmit?: () => Promise<void> | void;
|
||||
sx?: SxProps;
|
||||
}> = ({ initialValue, placeholder, onSubmit, sx }) => {
|
||||
}> = ({ initialValue, placeholder, onSubmit }) => {
|
||||
const context = useTestAndEarnContext();
|
||||
const [isAddressValid, setAddressIsValid] = React.useState(false);
|
||||
return (
|
||||
|
||||
@@ -7,13 +7,8 @@ import { TestAndEarnPopup, TestAndEarnPopupContent } from './TestAndEarnPopup';
|
||||
import { TestAndEarnContextProvider } from './context/TestAndEarnContext';
|
||||
import { MockProvider } from '../../context/mocks/main';
|
||||
import { ConnectionStatusKind } from '../../types';
|
||||
import { TestAndEarnCurrentDraw } from './TestAndEarnCurrentDraw';
|
||||
import { TestAndEarnWinner } from './TestAndEarnWinner';
|
||||
import { TestAndEarnDraws } from './TestAndEarnDraws';
|
||||
import { TestAndEarnWinnerWalletAddress } from './TestAndEarnWinnerWalletAddress';
|
||||
import {
|
||||
MockTestAndEarnProvider_NotRegistered,
|
||||
MockTestAndEarnProvider_Registered,
|
||||
MockTestAndEarnProvider_RegisteredAndError,
|
||||
MockTestAndEarnProvider_RegisteredWithDraws,
|
||||
MockTestAndEarnProvider_RegisteredWithDrawsAndEntry,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { SxProps } from '@mui/system';
|
||||
import ArrowCircleRightIcon from '@mui/icons-material/ArrowCircleRight';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import { useTestAndEarnContext } from './context/TestAndEarnContext';
|
||||
import { ClientId, Registration } from './context/types';
|
||||
import { Registration } from './context/types';
|
||||
|
||||
export const TestAndEarnTakePart: FCWithChildren<{
|
||||
websiteLinkUrl: string;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/jsx-pascal-case */
|
||||
import * as React from 'react';
|
||||
import { ComponentMeta } from '@storybook/react';
|
||||
import { NymShipyardTheme } from 'src/theme';
|
||||
|
||||
@@ -11,7 +11,7 @@ import Content from './content/en.yaml';
|
||||
export const TestAndEarnWinner: FCWithChildren<{
|
||||
sx?: SxProps;
|
||||
entry?: DrawEntry;
|
||||
}> = ({ sx, entry }) => {
|
||||
}> = ({ entry }) => {
|
||||
const context = useTestAndEarnContext();
|
||||
const [busy, setBusy] = React.useState(false);
|
||||
const [error, setError] = React.useState<string>();
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React from 'react';
|
||||
import { Box, Button, Card, CardContent, CardMedia, Typography } from '@mui/material';
|
||||
import { Box } from '@mui/material';
|
||||
import { SxProps } from '@mui/system';
|
||||
import Content from './content/TestAndEarn/WinnerEntersWalletAddress.mdx';
|
||||
|
||||
export const TestAndEarnWinnerWalletAddress: FCWithChildren<{
|
||||
sx?: SxProps;
|
||||
}> = ({ sx }) => (
|
||||
}> = () => (
|
||||
<Box>
|
||||
<Content />
|
||||
</Box>
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
export interface ClientId {
|
||||
client_id: string;
|
||||
client_id_signature: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Autocomplete, Box, Chip, Dialog, DialogProps, TextField, Typography } from '@mui/material';
|
||||
import { ServiceProvider, Service, Services } from '../types/directory';
|
||||
import { Autocomplete, Box, Dialog, DialogProps, TextField, Typography } from '@mui/material';
|
||||
import { Service, ServiceProvider, Services } from '../types/directory';
|
||||
|
||||
export const ServiceProviderPopup: FCWithChildren<
|
||||
DialogProps & { services: Services; onServiceProviderChanged: (sp?: ServiceProvider, s?: Service) => void }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { Box, CircularProgress, Stack, TextField, Tooltip, Typography, MenuItem, ListItemIcon } from '@mui/material';
|
||||
import { ServiceProvider, Service, Services } from '../types/directory';
|
||||
import { Box, CircularProgress, MenuItem, Stack, TextField, Tooltip, Typography } from '@mui/material';
|
||||
import { Service, ServiceProvider, Services } from '../types/directory';
|
||||
import { useTauriEvents } from '../utils';
|
||||
|
||||
type ServiceWithRandomSp = {
|
||||
|
||||
@@ -4,12 +4,12 @@ import { invoke } from '@tauri-apps/api';
|
||||
import type { UnlistenFn } from '@tauri-apps/api/event';
|
||||
import { listen } from '@tauri-apps/api/event';
|
||||
import { forage } from '@tauri-apps/tauri-forage';
|
||||
import { ConnectionStatusKind, GatewayPerformance } from '../types';
|
||||
import { ConnectionStatsItem } from '../components/ConnectionStats';
|
||||
import { ServiceProvider, Services } from '../types/directory';
|
||||
import { Error } from 'src/types/error';
|
||||
import { TauriEvent } from 'src/types/event';
|
||||
import { getVersion } from '@tauri-apps/api/app';
|
||||
import { ConnectionStatusKind, GatewayPerformance } from '../types';
|
||||
import { ConnectionStatsItem } from '../components/ConnectionStats';
|
||||
import { ServiceProvider, Services } from '../types/directory';
|
||||
|
||||
const TAURI_EVENT_STATUS_CHANGED = 'app:connection-status-changed';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import { ConnectionStatusKind } from 'src/types';
|
||||
import { ClientContext, TClientContext } from '../main';
|
||||
|
||||
@@ -24,6 +24,7 @@ const mockValues: TClientContext = {
|
||||
export const MockProvider: FCWithChildren<{
|
||||
children?: React.ReactNode;
|
||||
connectionStatus?: ConnectionStatusKind;
|
||||
}> = ({ connectionStatus = ConnectionStatusKind.disconnected, children }) => (
|
||||
<ClientContext.Provider value={{ ...mockValues, connectionStatus }}>{children}</ClientContext.Provider>
|
||||
);
|
||||
}> = ({ connectionStatus = ConnectionStatusKind.disconnected, children }) => {
|
||||
const value = useMemo(() => ({ ...mockValues, connectionStatus }), [connectionStatus]);
|
||||
return <ClientContext.Provider value={value}>{children}</ClientContext.Provider>;
|
||||
};
|
||||
|
||||
@@ -8,7 +8,6 @@ import { ConnectionStatusKind } from '../types';
|
||||
import { DefaultLayout } from '../layouts/DefaultLayout';
|
||||
import { ConnectedLayout } from '../layouts/ConnectedLayout';
|
||||
import { Services } from '../types/directory';
|
||||
import { TestAndEarnButtonArea } from '../components/Growth/TestAndEarnButtonArea';
|
||||
|
||||
export default {
|
||||
title: 'App/Flow',
|
||||
@@ -90,9 +89,7 @@ export const Mock: ComponentStory<typeof AppWindowFrame> = () => {
|
||||
<ConnectedLayout
|
||||
gatewayPerformance="Good"
|
||||
showInfoModal={false}
|
||||
handleCloseInfoModal={() => {
|
||||
return undefined;
|
||||
}}
|
||||
handleCloseInfoModal={() => undefined}
|
||||
status={context.connectionStatus}
|
||||
busy={busy}
|
||||
onConnectClick={handleConnectClick}
|
||||
|
||||
@@ -15,9 +15,7 @@ export const Default: ComponentStory<typeof ConnectedLayout> = () => (
|
||||
<ConnectedLayout
|
||||
showInfoModal={false}
|
||||
gatewayPerformance="Good"
|
||||
handleCloseInfoModal={() => {
|
||||
return undefined;
|
||||
}}
|
||||
handleCloseInfoModal={() => undefined}
|
||||
status={ConnectionStatusKind.connected}
|
||||
connectedSince={DateTime.now()}
|
||||
ipAddress="127.0.0.1"
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
||||
import { CssBaseline } from '@mui/material';
|
||||
import { getDesignTokens } from './theme';
|
||||
// eslint-disable-next-line import/no-relative-packages
|
||||
import '../../../assets/fonts/non-variable/fonts.css';
|
||||
|
||||
/**
|
||||
|
||||
@@ -73,6 +73,7 @@ const lightMode: NymPaletteVariant = {
|
||||
* IMPORTANT: do not export this constant, always use the MUI `useTheme` hook to get the correct
|
||||
* colours for dark/light mode.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const nymMixnetPalette = (variant: NymPaletteVariant): NymMixnetPalette => ({
|
||||
nymMixnet: {},
|
||||
});
|
||||
|
||||
@@ -3,18 +3,16 @@ import {
|
||||
Box,
|
||||
Button,
|
||||
CircularProgress,
|
||||
Paper,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
IconButton,
|
||||
Paper,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { ArrowBackSharp } from '@mui/icons-material';
|
||||
import { AccountsContext } from 'src/context';
|
||||
import { useClipboard } from 'use-clipboard-copy';
|
||||
import { PasswordInput, Mnemonic } from 'src/components';
|
||||
import { Mnemonic, PasswordInput } from 'src/components';
|
||||
import { StyledBackButton } from 'src/components/StyledBackButton';
|
||||
|
||||
export const MnemonicModal = () => {
|
||||
|
||||
@@ -7,11 +7,11 @@ import { TBondedMixnode, urls } from 'src/context';
|
||||
import { NymCard } from 'src/components';
|
||||
import { IdentityKey } from 'src/components/IdentityKey';
|
||||
import { NodeStatus } from 'src/components/NodeStatus';
|
||||
import { getIntervalAsDate } from 'src/utils';
|
||||
import { Node as NodeIcon } from '../../svg-icons/node';
|
||||
import { Cell, Header, NodeTable } from './NodeTable';
|
||||
import { BondedMixnodeActions, TBondedMixnodeActions } from './BondedMixnodeActions';
|
||||
import { NodeStats } from './NodeStats';
|
||||
import { getIntervalAsDate } from 'src/utils';
|
||||
|
||||
const textWhenNotName = 'This node has not yet set a name';
|
||||
|
||||
@@ -85,8 +85,8 @@ export const BondedMixnode = ({
|
||||
|
||||
const getNextInterval = async () => {
|
||||
try {
|
||||
const { nextEpoch } = await getIntervalAsDate();
|
||||
setNextEpoch(nextEpoch);
|
||||
const { nextEpoch: newNextEpoch } = await getIntervalAsDate();
|
||||
setNextEpoch(newNextEpoch);
|
||||
} catch {
|
||||
setNextEpoch(Error());
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ import { checkHasEnoughFunds, checkHasEnoughLockedTokens } from 'src/utils';
|
||||
import { NodeTypeSelector, TokenPoolSelector } from 'src/components';
|
||||
import { MixnodeAmount, MixnodeData } from 'src/pages/bonding/types';
|
||||
import { ModalListItem } from 'src/components/Modals/ModalListItem';
|
||||
import { amountSchema, mixnodeValidationSchema } from './mixnodeValidationSchema';
|
||||
import { AppContext } from 'src/context';
|
||||
import { amountSchema, mixnodeValidationSchema } from './mixnodeValidationSchema';
|
||||
|
||||
const NodeFormData = ({ mixnodeData, onNext }: { mixnodeData: MixnodeData; onNext: (data: any) => void }) => {
|
||||
const [showAdvancedOptions, setShowAdvancedOptions] = useState(false);
|
||||
|
||||
@@ -60,6 +60,7 @@ export const amountSchema = Yup.object().shape({
|
||||
operatorCost: Yup.object().shape({
|
||||
amount: Yup.string()
|
||||
.required('An operating cost is required')
|
||||
// eslint-disable-next-line
|
||||
.test('valid-operating-cost', 'A valid amount is required (min 40)', async function isValidAmount(this, value) {
|
||||
if (value && (!Number(value) || isLessThan(+value, 40))) {
|
||||
return false;
|
||||
|
||||
@@ -40,6 +40,7 @@ const operatingCostAndPmValidation = {
|
||||
operatorCost: Yup.object().shape({
|
||||
amount: Yup.string()
|
||||
.required('An operating cost is required')
|
||||
// eslint-disable-next-line prefer-arrow-callback
|
||||
.test('valid-operating-cost', 'A valid amount is required (min 40)', async function isValidAmount(this, value) {
|
||||
if (value && (!Number(value) || isLessThan(+value, 40))) {
|
||||
return false;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { CurrencyFormField } from '@nymproject/react/currency/CurrencyFormField'
|
||||
import { ModalListItem } from 'src/components/Modals/ModalListItem';
|
||||
import { SimpleModal } from 'src/components/Modals/SimpleModal';
|
||||
import { DecCoin } from '@nymproject/types';
|
||||
import { TokenPoolSelector, TPoolOption } from 'src/components/TokenPoolSelector';
|
||||
import { TPoolOption } from 'src/components/TokenPoolSelector';
|
||||
import { ConfirmTx } from 'src/components/ConfirmTX';
|
||||
import { useGetFee } from 'src/hooks/useGetFee';
|
||||
import { validateAmount } from 'src/utils';
|
||||
|
||||
@@ -12,7 +12,7 @@ import { simulateUpdateMixnodeCostParams, simulateVestingUpdateMixnodeCostParams
|
||||
import { LoadingModal } from 'src/components/Modals/LoadingModal';
|
||||
import { FeeDetails } from '@nymproject/types';
|
||||
|
||||
//Now we are using the node setting page instead of this modal
|
||||
// Now we are using the node setting page instead of this modal
|
||||
export const NodeSettings = ({
|
||||
currentPm,
|
||||
isVesting,
|
||||
@@ -108,7 +108,7 @@ export const NodeSettings = ({
|
||||
okLabel="Next"
|
||||
onClose={onClose}
|
||||
>
|
||||
<Tabs tabs={['System variables']} selectedTab={'System variables'} disableActiveTabHighlight />
|
||||
<Tabs tabs={['System variables']} selectedTab="System variables" disableActiveTabHighlight />
|
||||
<Box sx={{ p: 3 }}>
|
||||
<Typography fontWeight={600} sx={{ mb: 1 }}>
|
||||
Set profit margin
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { Typography } from '@mui/material';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { TBondedGateway, TBondedMixnode } from 'src/context';
|
||||
import { useGetFee } from 'src/hooks/useGetFee';
|
||||
import { isGateway, isMixnode } from 'src/types';
|
||||
|
||||
@@ -2,10 +2,10 @@ import React, { useContext, useState } from 'react';
|
||||
import { Button, Stack, Typography, Grid, useMediaQuery, useTheme } from '@mui/material';
|
||||
import { Tune as TuneIcon, BorderColor as BorderColorIcon } from '@mui/icons-material';
|
||||
import { CoinMark } from '@nymproject/react/coins/CoinMark';
|
||||
import { NymCard, ClientAddress } from '../../components';
|
||||
import { SignMessageModal } from './SignMessageModal';
|
||||
import { PoweredByBity } from 'src/svg-icons';
|
||||
import { AppContext } from 'src/context';
|
||||
import { NymCard, ClientAddress } from '..';
|
||||
import { SignMessageModal } from './SignMessageModal';
|
||||
|
||||
// TODO retrieve this value from env
|
||||
const EXCHANGE_URL = 'https://buy.nymtech.net';
|
||||
@@ -114,7 +114,8 @@ export const Tutorial = () => {
|
||||
icon={<CoinMark width={20} height={20} />}
|
||||
text={
|
||||
<Typography fontSize={14} lineHeight="24px" sx={{ color: (t) => t.palette.nym.text.muted }}>
|
||||
{`Send the defined BTC amount to Bity's address that's given to you. As soon as your BTC tx has 4 confirmations, Bity will send the purchased NYM tokens to your wallet.`}
|
||||
{`Send the defined BTC amount to Bity's address that's given to you. As soon as your BTC tx has 4
|
||||
confirmations, Bity will send the purchased NYM tokens to your wallet.`}
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -6,11 +6,13 @@ import { splice } from '../utils';
|
||||
|
||||
const AddressTooltip: FCWithChildren<{ visible?: boolean; address?: string }> = ({ visible, address, children }) => {
|
||||
if (!visible || !address) {
|
||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip title={address} arrow>
|
||||
{/* eslint-disable-next-line react/jsx-no-useless-fragment */}
|
||||
<>{children}</>
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Box, Button, Stack, Tooltip, Typography } from '@mui/material';
|
||||
import { DelegationEventKind } from '@nymproject/types';
|
||||
import { Delegate, Undelegate } from '../../svg-icons';
|
||||
import { ActionsMenu, ActionsMenuItem } from '../ActionsMenu';
|
||||
import { DelegateListItemPending } from './types';
|
||||
|
||||
@@ -12,6 +12,7 @@ const getStakeSaturation = (item: DelegationWithEverything) =>
|
||||
!item.stake_saturation ? '-' : `${decimalToPercentage(item.stake_saturation)}%`;
|
||||
|
||||
const getRewardValue = (item: DelegationWithEverything) => {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const { unclaimed_rewards } = item;
|
||||
return !unclaimed_rewards ? '-' : `${unclaimed_rewards.amount} ${unclaimed_rewards.denom}`;
|
||||
};
|
||||
@@ -32,11 +33,11 @@ export const DelegationItem = ({
|
||||
const tooltipText = () => {
|
||||
if (nodeIsUnbonded) {
|
||||
return 'This node has unbonded and it does not exist anymore. You need to undelegate from it to get your stake and outstanding rewards (if any) back.';
|
||||
} else if (item.uses_vesting_contract_tokens) {
|
||||
return 'Delegation made with locked tockens';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
if (item.uses_vesting_contract_tokens) {
|
||||
return 'Delegation made with locked tockens';
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Box, SxProps } from '@mui/material';
|
||||
import { IdentityKeyFormField } from '@nymproject/react/mixnodes/IdentityKeyFormField';
|
||||
import React, { useEffect } from 'react';
|
||||
import { FeeDetails } from '@nymproject/types';
|
||||
import { useGetFee } from 'src/hooks/useGetFee';
|
||||
|
||||
@@ -42,6 +42,7 @@ export const LogViewer: FC = () => {
|
||||
|
||||
useEffect(() => {
|
||||
listen('log://log', (event) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(event.payload);
|
||||
const payload = event.payload as RecordPayload;
|
||||
messages.current.unshift(payload);
|
||||
|
||||
@@ -27,11 +27,9 @@ export const ModalFee = ({ fee, isLoading, error, divider }: TFeeProps) => (
|
||||
</>
|
||||
);
|
||||
|
||||
export const ModalTotalAmount = ({ fee, amount, isLoading, error, divider }: TTotalAmountProps) => {
|
||||
return (
|
||||
<>
|
||||
<ModalListItem label="Total amount" value={getValue({ fee, amount, isLoading, error })} fontWeight={600} />
|
||||
{divider && <ModalDivider />}
|
||||
</>
|
||||
);
|
||||
};
|
||||
export const ModalTotalAmount = ({ fee, amount, isLoading, error, divider }: TTotalAmountProps) => (
|
||||
<>
|
||||
<ModalListItem label="Total amount" value={getValue({ fee, amount, isLoading, error })} fontWeight={600} />
|
||||
{divider && <ModalDivider />}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -24,7 +24,7 @@ export const NodeDetails = ({ saturation }: { saturation?: string }) => {
|
||||
<Divider sx={{ my: 1 }} />
|
||||
<Stack direction="row" justifyContent="space-between">
|
||||
<Typography fontWeight="medium">Selection probability</Typography>
|
||||
<InclusionProbability probability={computeSelectionProbability(parseInt(saturation))} />
|
||||
<InclusionProbability probability={computeSelectionProbability(parseInt(saturation, 10))} />
|
||||
</Stack>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { Stack, Typography, SxProps } from '@mui/material';
|
||||
import { Link } from '@nymproject/react/link/Link';
|
||||
import { AppContext } from 'src/context';
|
||||
import { TTransactionDetails } from './types';
|
||||
import { ConfirmationModal } from '../Modals/ConfirmationModal';
|
||||
import { AppContext } from 'src/context';
|
||||
|
||||
export const SendSuccessModal = ({
|
||||
txDetails,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import {
|
||||
FeeDetails,
|
||||
DecCoin,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import React, { createContext, FC, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import { getDelegationSummary, undelegateAllFromMixnode, undelegateFromMixnode } from 'src/requests/delegation';
|
||||
import { getDelegationSummary, undelegateFromMixnode } from 'src/requests/delegation';
|
||||
import {
|
||||
DelegationWithEverything,
|
||||
FeeDetails,
|
||||
DecCoin,
|
||||
DelegationWithEverything,
|
||||
Fee,
|
||||
FeeDetails,
|
||||
TransactionExecuteResult,
|
||||
WrappedDelegationEvent,
|
||||
Fee,
|
||||
} from '@nymproject/types';
|
||||
import type { Network } from 'src/types';
|
||||
import {
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { createContext, useEffect, useMemo, useState } from 'react';
|
||||
import { forage } from '@tauri-apps/tauri-forage';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useSnackbar } from 'notistack';
|
||||
import { Account, AccountEntry, MixNodeBond, MixNodeDetails } from '@nymproject/types';
|
||||
import { Account, AccountEntry, MixNodeDetails } from '@nymproject/types';
|
||||
import { getVersion } from '@tauri-apps/api/app';
|
||||
import { AppEnv, Network } from '../types';
|
||||
import { TUseuserBalance, useGetBalance } from '../hooks/useGetBalance';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { FeeDetails, DecCoin, TransactionExecuteResult } from '@nymproject/types';
|
||||
import { FeeDetails, TransactionExecuteResult } from '@nymproject/types';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import type { Network } from 'src/types';
|
||||
import { TBondedGateway, TBondedMixnode, BondingContext } from '../bonding';
|
||||
import { BondingContext, TBondedGateway, TBondedMixnode } from '../bonding';
|
||||
import { mockSleep } from './utils';
|
||||
|
||||
const SLEEP_MS = 1000;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import {
|
||||
DelegationWithEverything,
|
||||
DecCoin,
|
||||
TransactionExecuteResult,
|
||||
FeeDetails,
|
||||
Fee,
|
||||
CurrencyDenom,
|
||||
DecCoin,
|
||||
DelegationWithEverything,
|
||||
Fee,
|
||||
FeeDetails,
|
||||
TransactionExecuteResult,
|
||||
} from '@nymproject/types';
|
||||
import { DelegationContext, TDelegationTransaction } from '../delegations';
|
||||
|
||||
@@ -190,18 +190,17 @@ export const MockDelegationContextProvider: FCWithChildren = ({ children }) => {
|
||||
};
|
||||
};
|
||||
|
||||
const undelegateVesting = async (mix_id: number, _fee?: FeeDetails) => {
|
||||
return {
|
||||
logs_json: '',
|
||||
data_json: '',
|
||||
transaction_hash: '',
|
||||
gas_info: {
|
||||
gas_wanted: { gas_units: BigInt(1) },
|
||||
gas_used: { gas_units: BigInt(1) },
|
||||
},
|
||||
fee: { amount: '1', denom: 'nym' as CurrencyDenom },
|
||||
};
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const undelegateVesting = async (mix_id: number, _fee?: FeeDetails) => ({
|
||||
logs_json: '',
|
||||
data_json: '',
|
||||
transaction_hash: '',
|
||||
gas_info: {
|
||||
gas_wanted: { gas_units: BigInt(1) },
|
||||
gas_used: { gas_units: BigInt(1) },
|
||||
},
|
||||
fee: { amount: '1', denom: 'nym' as CurrencyDenom },
|
||||
});
|
||||
|
||||
const resetState = () => {
|
||||
setIsLoading(true);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { FC, useMemo } from 'react';
|
||||
import React, { useMemo } from 'react';
|
||||
import type { TAppContext } from '../main';
|
||||
import { AppContext } from '../main';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { DelegationWithEverything, TransactionExecuteResult } from '@nymproject/types';
|
||||
import { RewardsContext, TRewardsTransaction } from '../rewards';
|
||||
import { useDelegationContext } from '../delegations';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { createContext, FC, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import { FeeDetails, TransactionExecuteResult } from '@nymproject/types';
|
||||
import { useDelegationContext } from './delegations';
|
||||
import { claimDelegatorRewards } from '../requests';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import React, { useContext, useState } from 'react';
|
||||
import { Box } from '@mui/material';
|
||||
import { AppContext } from '../../context/main';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { Refresh } from '@mui/icons-material';
|
||||
import {
|
||||
Box,
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { useSnackbar } from 'notistack';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import { NymCard } from 'src/components';
|
||||
import { AppContext } from 'src/context/main';
|
||||
import { Period } from 'src/types';
|
||||
|
||||
@@ -99,8 +99,8 @@ const Bonding = () => {
|
||||
(await getMixnodeStakeSaturation(newMixId)).uncapped_saturation,
|
||||
);
|
||||
if (newSaturation && newSaturation > 1) {
|
||||
const saturationPercentage = Math.round(newSaturation * 100);
|
||||
return { isOverSaturated: true, saturationPercentage };
|
||||
const newSaturationPercentage = Math.round(newSaturation * 100);
|
||||
return { isOverSaturated: true, saturationPercentage: newSaturationPercentage };
|
||||
}
|
||||
return { isOverSaturated: false, saturationPercentage: undefined };
|
||||
} catch (e) {
|
||||
@@ -113,10 +113,12 @@ const Bonding = () => {
|
||||
switch (action) {
|
||||
case 'bondMore': {
|
||||
if (bondedNode && isMixnode(bondedNode)) {
|
||||
const { isOverSaturated, saturationPercentage } = await handleCheckStakeSaturation(bondedNode.mixId);
|
||||
if (isOverSaturated && saturationPercentage) {
|
||||
const { isOverSaturated, saturationPercentage: newSaturationPercentage } = await handleCheckStakeSaturation(
|
||||
bondedNode.mixId,
|
||||
);
|
||||
if (isOverSaturated && newSaturationPercentage) {
|
||||
setShowModal('bond-more-oversaturated');
|
||||
setSaturationPercentage(saturationPercentage.toString());
|
||||
setSaturationPercentage(newSaturationPercentage.toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -178,7 +180,7 @@ const Bonding = () => {
|
||||
|
||||
{showModal === 'bond-more-oversaturated' && saturationPercentage && (
|
||||
<BondOversaturatedModal
|
||||
open={true}
|
||||
open
|
||||
onClose={() => setShowModal(undefined)}
|
||||
onContinue={() => setShowModal('bond-more')}
|
||||
saturationPercentage={saturationPercentage}
|
||||
|
||||
@@ -13,12 +13,12 @@ import { Tabs } from 'src/components/Tabs';
|
||||
import { useBondingContext, BondingContextProvider, TBondedMixnode } from 'src/context';
|
||||
import { AppContext, urls } from 'src/context/main';
|
||||
|
||||
import { isMixnode } from 'src/types';
|
||||
import { getIntervalAsDate } from 'src/utils';
|
||||
import { NodeGeneralSettings } from './settings-pages/general-settings';
|
||||
import { NodeUnbondPage } from './settings-pages/NodeUnbondPage';
|
||||
import { createNavItems } from './node-settings.constant';
|
||||
import { isMixnode } from 'src/types';
|
||||
import { ApyPlayground } from './apy-playground';
|
||||
import { getIntervalAsDate } from 'src/utils';
|
||||
|
||||
export const NodeSettings = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import React, { useState, useEffect, useContext } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Box, Card, CardContent, CardHeader, Grid, Typography } from '@mui/material';
|
||||
import { decimalToPercentage, percentToDecimal } from '@nymproject/types';
|
||||
import { ResultsTable } from 'src/components/RewardsPlayground/ResultsTable';
|
||||
import { getDelegationSummary } from 'src/requests';
|
||||
import { NodeDetails } from 'src/components/RewardsPlayground/NodeDetail';
|
||||
import { Inputs, CalculateArgs } from 'src/components/RewardsPlayground/Inputs';
|
||||
import { AppContext, TBondedMixnode } from 'src/context';
|
||||
import { computeEstimate, computeStakeSaturation, handleCalculatePeriodRewards } from './utils';
|
||||
import { CalculateArgs, Inputs } from 'src/components/RewardsPlayground/Inputs';
|
||||
import { TBondedMixnode } from 'src/context';
|
||||
import { useSnackbar } from 'notistack';
|
||||
import { LoadingModal } from 'src/components/Modals/LoadingModal';
|
||||
import { computeEstimate, computeStakeSaturation, handleCalculatePeriodRewards } from './utils';
|
||||
|
||||
export type DefaultInputValues = {
|
||||
profitMargin: string;
|
||||
@@ -76,11 +75,12 @@ export const ApyPlayground = ({ bondedNode }: { bondedNode: TBondedMixnode }) =>
|
||||
|
||||
const handleCalculateEstimate = async ({ bond, delegations, uptime, profitMargin, operatorCost }: CalculateArgs) => {
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
const { estimation, reward_params } = await computeEstimate({
|
||||
mixId: bondedNode.mixId,
|
||||
uptime: uptime,
|
||||
profitMargin: profitMargin,
|
||||
operatorCost: operatorCost,
|
||||
uptime,
|
||||
profitMargin,
|
||||
operatorCost,
|
||||
totalDelegation: delegations,
|
||||
pledgeAmount: bond,
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@ export const computeEstimate = async ({
|
||||
operatorCost: string;
|
||||
}) => {
|
||||
const computedEstimate = await computeMixnodeRewardEstimation({
|
||||
mixId: mixId,
|
||||
mixId,
|
||||
performance: percentToDecimal(uptime),
|
||||
pledgeAmount: Math.round(+pledgeAmount * SCALE_FACTOR),
|
||||
totalDelegation: Math.round(+totalDelegation * SCALE_FACTOR),
|
||||
|
||||
@@ -4,6 +4,7 @@ import { TBondedMixnode, TBondedGateway } from 'src/context/bonding';
|
||||
import { Error } from 'src/components/Error';
|
||||
import { UnbondModal } from 'src/components/Bonding/modals/UnbondModal';
|
||||
import { isMixnode } from 'src/types';
|
||||
|
||||
interface Props {
|
||||
bondedNode: TBondedMixnode | TBondedGateway;
|
||||
|
||||
@@ -13,7 +14,7 @@ interface Props {
|
||||
export const NodeUnbondPage = ({ bondedNode, onConfirm, onError }: Props) => {
|
||||
const [confirmField, setConfirmField] = useState('');
|
||||
const [isConfirmed, setIsConfirmed] = useState(false);
|
||||
//TODO: Check what happens with a gateway
|
||||
// TODO: Check what happens with a gateway
|
||||
return (
|
||||
<Box sx={{ p: 3, minHeight: '450px' }}>
|
||||
<Grid container justifyContent="space-between">
|
||||
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
import { useState } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { Button, Divider, Typography, TextField, Grid, CircularProgress, Box } from '@mui/material';
|
||||
import { Box, Button, Divider, Grid, TextField, Typography } from '@mui/material';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { isMixnode } from 'src/types';
|
||||
import { simulateUpdateMixnodeConfig, simulateVestingUpdateMixnodeConfig, updateMixnodeConfig } from 'src/requests';
|
||||
import { TBondedMixnode, TBondedGateway } from 'src/context/bonding';
|
||||
import { TBondedGateway, TBondedMixnode } from 'src/context/bonding';
|
||||
import { SimpleModal } from 'src/components/Modals/SimpleModal';
|
||||
import { bondedInfoParametersValidationSchema } from 'src/components/Bonding/forms/mixnodeValidationSchema';
|
||||
import { Console } from 'src/utils/console';
|
||||
|
||||
+5
-11
@@ -1,7 +1,7 @@
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { Button, Divider, Typography, TextField, InputAdornment, Grid, Box, FormHelperText } from '@mui/material';
|
||||
import { Box, Button, Divider, FormHelperText, Grid, InputAdornment, TextField, Typography } from '@mui/material';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import { CurrencyDenom, MixNodeCostParams } from '@nymproject/types';
|
||||
import { CurrencyFormField } from '@nymproject/react/currency/CurrencyFormField';
|
||||
@@ -88,7 +88,7 @@ export const ParametersSettings = ({ bondedNode }: { bondedNode: TBondedMixnode
|
||||
const onSubmit = async (data: { operatorCost: { amount: string; denom: CurrencyDenom }; profitMargin: string }) => {
|
||||
resetFeeState();
|
||||
if (data.operatorCost && data.profitMargin) {
|
||||
const MixNodeCostParams = {
|
||||
const mixNodeCostParams = {
|
||||
profit_margin_percent: (+data.profitMargin / 100).toString(),
|
||||
interval_operating_cost: {
|
||||
amount: data.operatorCost.amount,
|
||||
@@ -97,9 +97,9 @@ export const ParametersSettings = ({ bondedNode }: { bondedNode: TBondedMixnode
|
||||
};
|
||||
try {
|
||||
if (bondedNode.proxy) {
|
||||
await vestingUpdateMixnodeCostParams(MixNodeCostParams);
|
||||
await vestingUpdateMixnodeCostParams(mixNodeCostParams);
|
||||
} else {
|
||||
await updateMixnodeCostParams(MixNodeCostParams);
|
||||
await updateMixnodeCostParams(mixNodeCostParams);
|
||||
}
|
||||
await getPendingEvents();
|
||||
reset();
|
||||
@@ -132,13 +132,7 @@ export const ParametersSettings = ({ bondedNode }: { bondedNode: TBondedMixnode
|
||||
/>
|
||||
)}
|
||||
{isSubmitting && <LoadingModal />}
|
||||
<Alert
|
||||
title={
|
||||
<>
|
||||
<Box component="span" sx={{ fontWeight: 600 }}>{`Next interval: ${intervalTime}`}</Box>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<Alert title={<Box component="span" sx={{ fontWeight: 600 }}>{`Next interval: ${intervalTime}`}</Box>} />
|
||||
<Grid container direction="column">
|
||||
<Grid item container alignItems="left" justifyContent="space-between" padding={3} spacing={1}>
|
||||
<Grid item xl={6}>
|
||||
|
||||
+2
-2
@@ -1,15 +1,15 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Box, Button, Divider, Grid } from '@mui/material';
|
||||
import { isMixnode } from 'src/types';
|
||||
import { TBondedMixnode, TBondedGateway } from '../../../../../context/bonding';
|
||||
import { InfoSettings } from './InfoSettings';
|
||||
import { ParametersSettings } from './ParametersSettings';
|
||||
import { isMixnode } from 'src/types';
|
||||
|
||||
const nodeGeneralNav = ['Info', 'Parameters'];
|
||||
|
||||
export const NodeGeneralSettings = ({ bondedNode }: { bondedNode: TBondedMixnode | TBondedGateway }) => {
|
||||
const [settingsCard, setSettingsCard] = useState<string>(nodeGeneralNav[0]);
|
||||
//TODO: Check what happens with a gateway
|
||||
// TODO: Check what happens with a gateway
|
||||
return (
|
||||
<Box sx={{ pl: 3, pt: 3 }}>
|
||||
<Grid container direction="row" spacing={3}>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { FC, useContext, useEffect, useState } from 'react';
|
||||
import { Box, Button, Paper, Stack, Typography, CircularProgress } from '@mui/material';
|
||||
import { useTheme, Theme } from '@mui/material/styles';
|
||||
import { Box, Button, CircularProgress, Paper, Stack, Typography } from '@mui/material';
|
||||
import { Theme, useTheme } from '@mui/material/styles';
|
||||
import { DecCoin, decimalToFloatApproximation, DelegationWithEverything, FeeDetails } from '@nymproject/types';
|
||||
import { Link } from '@nymproject/react/link/Link';
|
||||
import { AppContext, urls } from 'src/context/main';
|
||||
@@ -9,8 +9,9 @@ import { TPoolOption } from 'src/components';
|
||||
import { Console } from 'src/utils/console';
|
||||
import { OverSaturatedBlockerModal } from 'src/components/Delegation/DelegateBlocker';
|
||||
import { getSpendableCoins, userBalance } from 'src/requests';
|
||||
import { getIntervalAsDate, toPercentIntegerString } from 'src/utils';
|
||||
import { RewardsSummary } from '../../components/Rewards/RewardsSummary';
|
||||
import { DelegationContextProvider, useDelegationContext, TDelegations } from '../../context/delegations';
|
||||
import { DelegationContextProvider, TDelegations, useDelegationContext } from '../../context/delegations';
|
||||
import { RewardsContextProvider, useRewardsContext } from '../../context/rewards';
|
||||
import { DelegateModal } from '../../components/Delegation/DelegateModal';
|
||||
import { UndelegateModal } from '../../components/Delegation/UndelegateModal';
|
||||
@@ -18,7 +19,6 @@ import { DelegationListItemActions } from '../../components/Delegation/Delegatio
|
||||
import { RedeemModal } from '../../components/Rewards/RedeemModal';
|
||||
import { DelegationModal, DelegationModalProps } from '../../components/Delegation/DelegationModal';
|
||||
import { backDropStyles, modalStyles } from '../../../.storybook/storiesStyles';
|
||||
import { toPercentIntegerString, getIntervalAsDate } from 'src/utils';
|
||||
|
||||
const storybookStyles = (theme: Theme, isStorybook?: boolean, backdropProps?: object) =>
|
||||
isStorybook
|
||||
@@ -77,8 +77,8 @@ export const Delegation: FC<{ isStorybook?: boolean }> = ({ isStorybook }) => {
|
||||
|
||||
const getNextInterval = async () => {
|
||||
try {
|
||||
const { nextEpoch } = await getIntervalAsDate();
|
||||
setNextEpoch(nextEpoch);
|
||||
const { nextEpoch: newNextEpoch } = await getIntervalAsDate();
|
||||
setNextEpoch(newNextEpoch);
|
||||
} catch {
|
||||
setNextEpoch(Error());
|
||||
}
|
||||
|
||||
@@ -33,5 +33,4 @@ export const unbond = async (type: EnumNodeType) => {
|
||||
return unbondGateway();
|
||||
};
|
||||
|
||||
export const bondMore = async (args: TBondMoreArgs) =>
|
||||
invokeWrapper<TransactionExecuteResult>('pledge_more', args);
|
||||
export const bondMore = async (args: TBondMoreArgs) => invokeWrapper<TransactionExecuteResult>('pledge_more', args);
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import {
|
||||
StakeSaturationResponse,
|
||||
MixnodeStatusResponse,
|
||||
InclusionProbabilityResponse,
|
||||
DecCoin,
|
||||
MixNodeDetails,
|
||||
GatewayBond,
|
||||
RewardEstimationResponse,
|
||||
WrappedDelegationEvent,
|
||||
InclusionProbabilityResponse,
|
||||
MixNodeDetails,
|
||||
MixnodeStatusResponse,
|
||||
PendingIntervalEvent,
|
||||
Coin,
|
||||
RewardEstimationResponse,
|
||||
StakeSaturationResponse,
|
||||
WrappedDelegationEvent,
|
||||
} from '@nymproject/types';
|
||||
import { Interval, TGatewayReport, TNodeDescription } from 'src/types';
|
||||
import { invokeWrapper } from './wrapper';
|
||||
|
||||
@@ -64,8 +64,7 @@ export const simulateClaimOperatorReward = async () => invokeWrapper<FeeDetails>
|
||||
export const simulateVestingClaimOperatorReward = async () =>
|
||||
invokeWrapper<FeeDetails>('simulate_vesting_claim_operator_reward');
|
||||
|
||||
export const simulateBondMore = async (args: any) =>
|
||||
invokeWrapper<FeeDetails>('simulate_pledge_more', args);
|
||||
export const simulateBondMore = async (args: any) => invokeWrapper<FeeDetails>('simulate_pledge_more', args);
|
||||
|
||||
export const simulateVestingBondMore = async (args: any) =>
|
||||
invokeWrapper<FeeDetails>('simulate_vesting_pledge_more', args);
|
||||
|
||||
@@ -106,13 +106,8 @@ export const vestingClaimOperatorReward = async (fee?: Fee) =>
|
||||
export const vestingClaimDelegatorRewards = async (mixId: number) =>
|
||||
invokeWrapper<TransactionExecuteResult>('vesting_claim_delegator_reward', { mixId });
|
||||
|
||||
export const vestingBondMore = async ({
|
||||
fee,
|
||||
additionalPledge,
|
||||
}: {
|
||||
fee?: Fee;
|
||||
additionalPledge: DecCoin;
|
||||
}) => invokeWrapper<TransactionExecuteResult>('vesting_pledge_more', {
|
||||
fee,
|
||||
additionalPledge,
|
||||
});
|
||||
export const vestingBondMore = async ({ fee, additionalPledge }: { fee?: Fee; additionalPledge: DecCoin }) =>
|
||||
invokeWrapper<TransactionExecuteResult>('vesting_pledge_more', {
|
||||
fee,
|
||||
additionalPledge,
|
||||
});
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,12 +1,4 @@
|
||||
import {
|
||||
Gateway,
|
||||
DecCoin,
|
||||
MixNode,
|
||||
PledgeData,
|
||||
MixNodeCostParams,
|
||||
PendingIntervalEventData,
|
||||
PendingEpochEventData,
|
||||
} from '@nymproject/types';
|
||||
import { DecCoin, Gateway, MixNode, MixNodeCostParams, PledgeData } from '@nymproject/types';
|
||||
import { Fee } from '@nymproject/types/dist/types/rust/Fee';
|
||||
import { TBondedGateway, TBondedMixnode } from 'src/context';
|
||||
|
||||
@@ -52,7 +44,6 @@ export type TBondMixNodeArgs = {
|
||||
export type TBondMoreArgs = {
|
||||
additionalPledge: DecCoin;
|
||||
fee?: Fee;
|
||||
|
||||
};
|
||||
|
||||
export type TNodeDescription = {
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export interface Epoch { id: number, start: bigint, end: bigint, duration_seconds: bigint, }
|
||||
export interface Epoch {
|
||||
id: number;
|
||||
start: bigint;
|
||||
end: bigint;
|
||||
duration_seconds: bigint;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { DecCoin } from '../../../../ts-packages/types/src/types/rust/DecCoin';
|
||||
import type { DecCoin } from '@nymproject/types';
|
||||
|
||||
export interface TauriContractStateParams {
|
||||
minimum_mixnode_pledge: DecCoin;
|
||||
|
||||
@@ -3,7 +3,7 @@ import bs58 from 'bs58';
|
||||
import Big from 'big.js';
|
||||
import { valid } from 'semver';
|
||||
import { add, format, fromUnixTime } from 'date-fns';
|
||||
import { isValidRawCoin, DecCoin, MixNodeCostParams } from '@nymproject/types';
|
||||
import { DecCoin, isValidRawCoin, MixNodeCostParams } from '@nymproject/types';
|
||||
import { TPoolOption } from 'src/components';
|
||||
import {
|
||||
getCurrentInterval,
|
||||
@@ -14,8 +14,6 @@ import {
|
||||
} from '../requests';
|
||||
import { Console } from './console';
|
||||
|
||||
export * from './nextEpoch';
|
||||
|
||||
export const validateKey = (key: string, bytesLength: number): boolean => {
|
||||
// it must be a valid base58 key
|
||||
try {
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { getCurrentInterval } from 'src/requests';
|
||||
import { add, format, fromUnixTime } from 'date-fns';
|
||||
|
||||
export const getIntervalAsDate = async () => {
|
||||
const interval = await getCurrentInterval();
|
||||
const secondsToNextInterval =
|
||||
Number(interval.epochs_in_interval - interval.current_epoch_id) * Number(interval.epoch_length_seconds);
|
||||
|
||||
const intervalTime = format(
|
||||
add(new Date(), {
|
||||
seconds: secondsToNextInterval,
|
||||
}),
|
||||
'dd/MM/yyyy, HH:mm',
|
||||
);
|
||||
const nextEpoch = format(
|
||||
add(fromUnixTime(Number(interval.current_epoch_start_unix)), {
|
||||
seconds: Number(interval.epoch_length_seconds),
|
||||
}),
|
||||
'HH:mm',
|
||||
);
|
||||
|
||||
return { intervalTime, nextEpoch };
|
||||
};
|
||||
@@ -69,7 +69,8 @@ export const Content: FCWithChildren = () => {
|
||||
};
|
||||
|
||||
const log = React.useRef<Log[]>([]);
|
||||
const [_logTrigger, setLogTrigger] = React.useState(Date.now());
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [logTrigger, setLogTrigger] = React.useState(Date.now());
|
||||
|
||||
const [uploadState, setUploadState] = React.useState<UploadState>({
|
||||
dialogOpen: false,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import { Debug } from '@nymproject/nym-client-wasm';
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,8 +11,10 @@ import * as Comlink from 'comlink';
|
||||
// Doing it this way, saves having to support a large variety of bundlers and their quirks.
|
||||
//
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import wasmBytes from '@nymproject/nym-client-wasm/nym_client_wasm_bg.wasm';
|
||||
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import init, {
|
||||
NymClient,
|
||||
NymClientBuilder,
|
||||
@@ -46,6 +48,7 @@ console.log('[Nym WASM client] Starting Nym WASM web worker...');
|
||||
* Helper method to send typed messages.
|
||||
* @param event The strongly typed message to send back to the calling thread.
|
||||
*/
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
const postMessageWithType = <E>(event: E) => self.postMessage(event);
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Color, PaletteMode } from '@mui/material';
|
||||
import { PaletteMode } from '@mui/material';
|
||||
import { createTheme, ThemeOptions } from '@mui/material/styles';
|
||||
import { darkMode, nymPalette, NymPaletteVariant } from './common';
|
||||
import { createDarkModePalette, createLightModePalette } from './theme';
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import { createDarkModePalette, createLightModePalette } from './utils';
|
||||
|
||||
/**
|
||||
* A palette definition only for the Network Explorer that extends the Nym palette
|
||||
@@ -53,7 +54,7 @@ export interface NetworkExplorerPalette {
|
||||
backgroud: string;
|
||||
color: string;
|
||||
border: string;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -111,7 +112,7 @@ export const networkExplorerPalette = (variant: NymPaletteVariant): NetworkExplo
|
||||
backgroud: variant.mode === 'light' ? '#FAFAFA' : '#C7C9CD',
|
||||
color: variant.mode === 'light' ? '#7D7D7D' : '#636466',
|
||||
border: variant.mode === 'light' ? '#DFDEDE' : '#DDDDDD',
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { createTheme, Palette, PaletteOptions, ThemeOptions } from '@mui/material/styles';
|
||||
import { createTheme, Palette, ThemeOptions } from '@mui/material/styles';
|
||||
import { PaletteMode } from '@mui/material';
|
||||
import { darkMode, lightMode, nymPalette, NymPalette, variantToMUIPalette } from './common';
|
||||
import { NymWalletPalette, nymWalletPallete } from './wallet';
|
||||
import { networkExplorerPalette, NetworkExplorerPalette } from './network-explorer';
|
||||
import { nymPalette, NymPalette } from './common';
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import { NymWalletPalette } from './wallet';
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import { NetworkExplorerPalette } from './network-explorer';
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import { createDarkModePalette, createLightModePalette } from './utils';
|
||||
|
||||
/**
|
||||
* To use the theme, copy the file in `../../template/mui-theme.d.ts` into `src/typings/mui-theme.d.ts` in your project.
|
||||
@@ -30,30 +34,6 @@ export interface NymTheme {
|
||||
*/
|
||||
export type NymPaletteWithExtensionsOptions = Partial<NymPaletteWithExtensions>;
|
||||
|
||||
/**
|
||||
* Returns the Nym palette for light mode.
|
||||
*/
|
||||
export const createLightModePalette = (): PaletteOptions & NymPaletteWithExtensionsOptions => ({
|
||||
nym: {
|
||||
...nymPalette,
|
||||
...nymWalletPallete(lightMode),
|
||||
...networkExplorerPalette(lightMode),
|
||||
},
|
||||
...variantToMUIPalette(lightMode),
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns the Nym palette for dark mode.
|
||||
*/
|
||||
export const createDarkModePalette = (): PaletteOptions & NymPaletteWithExtensionsOptions => ({
|
||||
nym: {
|
||||
...nymPalette,
|
||||
...nymWalletPallete(darkMode),
|
||||
...networkExplorerPalette(darkMode),
|
||||
},
|
||||
...variantToMUIPalette(darkMode),
|
||||
});
|
||||
|
||||
/**
|
||||
* Gets the theme options to be passed to `createTheme`.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { PaletteOptions } from '@mui/material/styles';
|
||||
import { darkMode, lightMode, nymPalette, variantToMUIPalette } from './common';
|
||||
import { nymWalletPallete } from './wallet';
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import { networkExplorerPalette } from './network-explorer';
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import { NymPaletteWithExtensionsOptions } from './theme';
|
||||
|
||||
/**
|
||||
* Returns the Nym palette for light mode.
|
||||
*/
|
||||
export const createLightModePalette = (): PaletteOptions & NymPaletteWithExtensionsOptions => ({
|
||||
nym: {
|
||||
...nymPalette,
|
||||
...nymWalletPallete(lightMode),
|
||||
...networkExplorerPalette(lightMode),
|
||||
},
|
||||
...variantToMUIPalette(lightMode),
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns the Nym palette for dark mode.
|
||||
*/
|
||||
export const createDarkModePalette = (): PaletteOptions & NymPaletteWithExtensionsOptions => ({
|
||||
nym: {
|
||||
...nymPalette,
|
||||
...nymWalletPallete(darkMode),
|
||||
...networkExplorerPalette(darkMode),
|
||||
},
|
||||
...variantToMUIPalette(darkMode),
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import { Box, Collapse, Alert, IconButton, Typography, Divider } from '@mui/material';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import { SxProps } from '@mui/system';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { ComponentMeta } from '@storybook/react';
|
||||
import { Stack, Typography } from '@mui/material';
|
||||
import { CoinMark } from './CoinMark';
|
||||
import { CoinMarkTestnet } from './CoinMarkTestnet';
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import type { DecCoin } from '@nymproject/types';
|
||||
import { Stack, SxProps, Typography } from '@mui/material';
|
||||
import { Stack, SxProps } from '@mui/material';
|
||||
import { CurrencyWithCoinMark } from './CurrencyWithCoinMark';
|
||||
import { CURRENCY_AMOUNT_SPACING, CurrencyAmount } from './CurrencyAmount';
|
||||
|
||||
|
||||
@@ -9,16 +9,14 @@ export default {
|
||||
|
||||
export const Default = () => <Tooltip title="tooltip" id="field-name" placement="top-start" arrow />;
|
||||
|
||||
export const NEStyle = () => {
|
||||
return (
|
||||
<Tooltip
|
||||
title="Level of stake saturation for this node. Nodes receive more rewards the higher their saturation level, up to 100%. Beyond 100% no additional rewards are granted. The current stake saturation level is: 1 million NYM, computed as S/K where S is total amount of tokens available to stakeholders and K is the number of nodes in the reward set."
|
||||
id="field-name"
|
||||
placement="top-start"
|
||||
textColor="#111826"
|
||||
bgColor="#A0AED1"
|
||||
maxWidth={230}
|
||||
arrow
|
||||
/>
|
||||
);
|
||||
};
|
||||
export const NEStyle = () => (
|
||||
<Tooltip
|
||||
title="Level of stake saturation for this node. Nodes receive more rewards the higher their saturation level, up to 100%. Beyond 100% no additional rewards are granted. The current stake saturation level is: 1 million NYM, computed as S/K where S is total amount of tokens available to stakeholders and K is the number of nodes in the reward set."
|
||||
id="field-name"
|
||||
placement="top-start"
|
||||
textColor="#111826"
|
||||
bgColor="#A0AED1"
|
||||
maxWidth={230}
|
||||
arrow
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
import * as React from 'react';
|
||||
import { Tooltip as MUITooltip, TooltipProps, IconButton } from '@mui/material';
|
||||
import { IconButton, Tooltip as MUITooltip } from '@mui/material';
|
||||
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
|
||||
|
||||
export interface CustomTooltipProps {
|
||||
title: string;
|
||||
arrow?: boolean;
|
||||
id: string;
|
||||
placement?: "bottom" | "left" | "right" | "top" | "bottom-end" | "bottom-start" | "left-end" | "left-start" | "right-end" | "right-start" | "top-end" | "top-start";
|
||||
placement?:
|
||||
| 'bottom'
|
||||
| 'left'
|
||||
| 'right'
|
||||
| 'top'
|
||||
| 'bottom-end'
|
||||
| 'bottom-start'
|
||||
| 'left-end'
|
||||
| 'left-start'
|
||||
| 'right-end'
|
||||
| 'right-start'
|
||||
| 'top-end'
|
||||
| 'top-start';
|
||||
textColor?: string;
|
||||
bgColor?: string;
|
||||
maxWidth?: number;
|
||||
@@ -42,7 +54,7 @@ export const Tooltip = (props: CustomTooltipProps) => {
|
||||
componentsProps={{
|
||||
tooltip: {
|
||||
sx: {
|
||||
maxWidth: maxWidth,
|
||||
maxWidth,
|
||||
background: bgColor,
|
||||
color: textColor,
|
||||
'& .MuiTooltip-arrow': {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type {PendingEpochEventData} from "./PendingEpochEventData";
|
||||
import type { PendingEpochEventData } from './PendingEpochEventData';
|
||||
|
||||
export interface PendingEpochEvent {
|
||||
id: number,
|
||||
created_at: bigint,
|
||||
event: PendingEpochEventData,
|
||||
id: number;
|
||||
created_at: bigint;
|
||||
event: PendingEpochEventData;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type {PendingIntervalEventData} from "./PendingIntervalEventData";
|
||||
import type { PendingIntervalEventData } from './PendingIntervalEventData';
|
||||
|
||||
export interface PendingIntervalEvent {
|
||||
id: number,
|
||||
created_at: bigint,
|
||||
event: PendingIntervalEventData,
|
||||
id: number;
|
||||
created_at: bigint;
|
||||
event: PendingIntervalEventData;
|
||||
}
|
||||
|
||||
@@ -61,17 +61,14 @@ module.exports = (baseDir, htmlPath) => ({
|
||||
plugins: [
|
||||
// new CleanWebpackPlugin(),
|
||||
|
||||
... Array.isArray(htmlPath)
|
||||
? htmlPath.map(
|
||||
(item) =>
|
||||
new HtmlWebpackPlugin(item),
|
||||
)
|
||||
...(Array.isArray(htmlPath)
|
||||
? htmlPath.map((item) => new HtmlWebpackPlugin(item))
|
||||
: [
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
template: path.resolve(baseDir, htmlPath || 'src/index.html'),
|
||||
})
|
||||
],
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
template: path.resolve(baseDir, htmlPath || 'src/index.html'),
|
||||
}),
|
||||
]),
|
||||
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
typescript: {
|
||||
|
||||
Reference in New Issue
Block a user