From f51318f84a19584bf55692038743f551cdd51d08 Mon Sep 17 00:00:00 2001 From: eliasmpw Date: Mon, 3 Jan 2022 19:44:39 -0500 Subject: [PATCH] Bugfixes (#7) * #4 Show block number diff in block time tab * #5 Fix average block time duplicated entry * Add .editorconfig file and format files --- .editorconfig | 11 + src/App.less | 14 +- src/App.test.tsx | 14 +- src/App.tsx | 14 +- .../AddressBook/AddAddressModal.tsx | 77 +++--- src/components/AddressBook/AddressBook.less | 2 +- src/components/AddressBook/AddressBook.tsx | 73 ++---- .../AddressBook/ViewFormatsModal.tsx | 54 ++-- .../AverageBlockTime/AverageBlockTime.less | 4 +- .../AverageBlockTime/AverageBlockTime.tsx | 232 +++++++--------- src/components/BlockAuthor/BlockAuthor.less | 4 +- src/components/BlockAuthor/BlockAuthor.tsx | 233 +++++++--------- src/components/BlockTime/BlockTime.less | 4 +- src/components/BlockTime/BlockTime.tsx | 248 +++++++----------- src/components/Config/AddEndpointModal.tsx | 70 ++--- src/components/Config/AddNetworkModal.tsx | 73 +++--- src/components/Config/Configuration.less | 9 +- src/components/Config/Configuration.tsx | 143 +++------- src/components/Navbar/Navbar.less | 2 +- src/components/Navbar/Navbar.tsx | 49 ++-- src/components/ParachainUtilities.tsx | 55 ++-- src/components/utils/ApiProvider.tsx | 41 ++- src/components/utils/CustomSpinner.tsx | 8 +- src/index.css | 8 +- src/index.tsx | 19 +- src/reportWebVitals.ts | 18 +- src/setupTests.ts | 2 +- src/store/actions/addressActions.tsx | 10 +- src/store/actions/configActions.tsx | 43 ++- src/store/hooks.ts | 11 +- src/store/index.ts | 21 +- src/store/reducers/addressReducer.tsx | 19 +- src/store/reducers/configReducer.tsx | 36 ++- src/store/reducers/index.tsx | 20 +- src/types.ts | 26 +- src/utils/UtilsFunctions.ts | 54 ++-- 36 files changed, 717 insertions(+), 1004 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9dbae7a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true +[*] +indent_style=space +indent_size=2 +tab_width=2 +end_of_line=lf +charset=utf-8 +trim_trailing_whitespace=true +max_line_length=120 +insert_final_newline=true +quote_type=single diff --git a/src/App.less b/src/App.less index 9a99b6f..ab74148 100644 --- a/src/App.less +++ b/src/App.less @@ -1,19 +1,17 @@ -@import "~antd/dist/antd.less"; -@import "styles/variables.less"; -@import "styles/spacing.less"; +@import '~antd/dist/antd.less'; +@import 'styles/variables.less'; +@import 'styles/spacing.less'; body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Work Sans", "Segoe UI", - "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", - "Helvetica Neue", sans-serif; + font-family: -apple-system, BlinkMacSystemFont, 'Work Sans', 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', + 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } .app-layout { diff --git a/src/App.test.tsx b/src/App.test.tsx index 2a68616..3a7a8cc 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -1,9 +1,9 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import App from './App'; +import React from 'react' +import { render, screen } from '@testing-library/react' +import App from './App' test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); + render() + const linkElement = screen.getByText(/learn react/i) + expect(linkElement).toBeInTheDocument() +}) diff --git a/src/App.tsx b/src/App.tsx index 675bc26..b5543a2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,10 +1,10 @@ -import React from "react" -import "./App.less" -import { Provider } from "react-redux" -import setupStore from "./store" -import { PersistGate } from "redux-persist/integration/react" -import ParachainUtilities from "./components/ParachainUtilities" -import { ApiProvider } from "./components/utils/ApiProvider" +import React from 'react' +import './App.less' +import { Provider } from 'react-redux' +import setupStore from './store' +import { PersistGate } from 'redux-persist/integration/react' +import ParachainUtilities from './components/ParachainUtilities' +import { ApiProvider } from './components/utils/ApiProvider' const { store, persistor } = setupStore() diff --git a/src/components/AddressBook/AddAddressModal.tsx b/src/components/AddressBook/AddAddressModal.tsx index 7b58ca9..16b2ed5 100644 --- a/src/components/AddressBook/AddAddressModal.tsx +++ b/src/components/AddressBook/AddAddressModal.tsx @@ -1,10 +1,10 @@ -import { Button, Form, Input, Modal, Row, Space, message } from "antd" -import React, { useEffect } from "react" -import { addAddress } from "../../store/actions/addressActions" -import { useAppDispatch, useAppSelector } from "../../store/hooks" -import { SubstrateAddress } from "../../types" -import { decodeAddress } from "@polkadot/util-crypto/address" -import { transformAddress } from "../../utils/UtilsFunctions" +import { Button, Form, Input, Modal, Row, Space, message } from 'antd' +import React, { useEffect } from 'react' +import { addAddress } from '../../store/actions/addressActions' +import { useAppDispatch, useAppSelector } from '../../store/hooks' +import { SubstrateAddress } from '../../types' +import { decodeAddress } from '@polkadot/util-crypto/address' +import { transformAddress } from '../../utils/UtilsFunctions' type AddAddressModalProps = { showModal: boolean @@ -14,7 +14,7 @@ type AddAddressModalProps = { function AddAddressModal(props: AddAddressModalProps): React.ReactElement { const [form] = Form.useForm() const dispatch = useAppDispatch() - const addresses = useAppSelector(state => state.address.list) + const addresses = useAppSelector((state) => state.address.list) const { showModal, setShowModal } = props useEffect(() => { @@ -24,10 +24,8 @@ function AddAddressModal(props: AddAddressModalProps): React.ReactElement { const onFormSubmit = (address: SubstrateAddress) => { try { const decodedValue = decodeAddress(address.key) - const hexValue = "0x" + Buffer.from(decodedValue).toString("hex") - const checkExisting = addresses.find( - auxAddress => auxAddress.key === hexValue - ) + const hexValue = '0x' + Buffer.from(decodedValue).toString('hex') + const checkExisting = addresses.find((auxAddress) => auxAddress.key === hexValue) if (checkExisting) { message.error(`Address already exists with name ${checkExisting.name}`) return @@ -41,7 +39,7 @@ function AddAddressModal(props: AddAddressModalProps): React.ReactElement { ) handleClose() } catch (err) { - message.error("Error: Invalid address") + message.error('Error: Invalid address') } } @@ -51,54 +49,59 @@ function AddAddressModal(props: AddAddressModalProps): React.ReactElement { return ( + footer={null} + >
+ onFinish={onFormSubmit} + > - + ]} + > + - + ]} + > + - - + + - diff --git a/src/components/AddressBook/AddressBook.less b/src/components/AddressBook/AddressBook.less index 3153ae3..12ba59d 100644 --- a/src/components/AddressBook/AddressBook.less +++ b/src/components/AddressBook/AddressBook.less @@ -1,3 +1,3 @@ .address-book-container { padding: 25px; -} \ No newline at end of file +} diff --git a/src/components/AddressBook/AddressBook.tsx b/src/components/AddressBook/AddressBook.tsx index 27d1351..f8326eb 100644 --- a/src/components/AddressBook/AddressBook.tsx +++ b/src/components/AddressBook/AddressBook.tsx @@ -1,25 +1,19 @@ -import { - DeleteOutlined, - DotChartOutlined, - PlusOutlined, -} from "@ant-design/icons" -import { Button, Row, Space, Table } from "antd" -import React, { useState } from "react" -import { deleteAddress } from "../../store/actions/addressActions" -import { useAppDispatch, useAppSelector } from "../../store/hooks" -import { SubstrateAddress } from "../../types" -import AddAddressModal from "./AddAddressModal" -import "./AddressBook.less" -import ViewFormatsModal from "./ViewFormatsModal" +import { DeleteOutlined, DotChartOutlined, PlusOutlined } from '@ant-design/icons' +import { Button, Row, Space, Table } from 'antd' +import React, { useState } from 'react' +import { deleteAddress } from '../../store/actions/addressActions' +import { useAppDispatch, useAppSelector } from '../../store/hooks' +import { SubstrateAddress } from '../../types' +import AddAddressModal from './AddAddressModal' +import './AddressBook.less' +import ViewFormatsModal from './ViewFormatsModal' function AddressBook(): React.ReactElement { const [showAddAddressModal, setShowAddAddressModal] = useState(false) const [showViewFormatsModal, setShowViewFormatsModal] = useState(false) - const [selectedAddress, setSelectedAddress] = useState< - SubstrateAddress | undefined - >() + const [selectedAddress, setSelectedAddress] = useState() const dispatch = useAppDispatch() - const addresses = useAppSelector(state => state.address.list) + const addresses = useAppSelector((state) => state.address.list) const handleAddAddress = () => { setShowAddAddressModal(true) @@ -37,19 +31,10 @@ function AddressBook(): React.ReactElement { const renderAddressActions = (row: SubstrateAddress) => { return ( - - @@ -58,37 +43,31 @@ function AddressBook(): React.ReactElement { const columns = [ { - title: "Name", - dataIndex: "name", - key: "name", + title: 'Name', + dataIndex: 'name', + key: 'name', }, { - title: "Public key of Address", - dataIndex: "key", - key: "key", + title: 'Public key of Address', + dataIndex: 'key', + key: 'key', }, { - title: "Actions", - key: "action", + title: 'Actions', + key: 'action', render: renderAddressActions, }, ] return ( -
- - - - +
+ { return ( - message.success("Address copied to Clipboard!")} - text={row.value}> -
+
) } diff --git a/src/components/AverageBlockTime/AverageBlockTime.less b/src/components/AverageBlockTime/AverageBlockTime.less index 11e6cb0..8b54a00 100644 --- a/src/components/AverageBlockTime/AverageBlockTime.less +++ b/src/components/AverageBlockTime/AverageBlockTime.less @@ -29,10 +29,10 @@ .fill-start-block-btn, .reset-block-time-btn { - background-color: #FFE3F1; + background-color: #ffe3f1; border-color: #444444; &:disabled { border-color: inherit; } } -} \ No newline at end of file +} diff --git a/src/components/AverageBlockTime/AverageBlockTime.tsx b/src/components/AverageBlockTime/AverageBlockTime.tsx index ce8cedf..c19003c 100644 --- a/src/components/AverageBlockTime/AverageBlockTime.tsx +++ b/src/components/AverageBlockTime/AverageBlockTime.tsx @@ -1,26 +1,11 @@ -import { BarChartOutlined } from "@ant-design/icons" -import { - Button, - Col, - Form, - InputNumber, - message, - Row, - Select, - Space, - Spin, - Table, -} from "antd" -import React, { useContext, useEffect, useState } from "react" -import { useAppSelector } from "../../store/hooks" -import { PolkadotNetwork } from "../../types" -import { - estimateStartBlockNumber, - formatDate, - getExpectedBlockTime, -} from "../../utils/UtilsFunctions" -import { ApiContext, ApiContextData, connectToApi } from "../utils/ApiProvider" -import "./AverageBlockTime.less" +import { BarChartOutlined } from '@ant-design/icons' +import { Button, Col, Form, InputNumber, message, Row, Select, Space, Spin, Table } from 'antd' +import React, { useContext, useEffect, useState } from 'react' +import { useAppSelector } from '../../store/hooks' +import { PolkadotNetwork } from '../../types' +import { estimateStartBlockNumber, formatDate, getExpectedBlockTime } from '../../utils/UtilsFunctions' +import { ApiContext, ApiContextData, connectToApi } from '../utils/ApiProvider' +import './AverageBlockTime.less' interface AvgBlockTimeFormValues { startBlock: number @@ -29,6 +14,7 @@ interface AvgBlockTimeFormValues { } interface AvgBlockTimeResult { + index: number startBlock: number startBlockTime: string endBlock: number @@ -40,7 +26,7 @@ interface AvgBlockTimeResult { function AverageBlockTime(): React.ReactElement { const { apiConnections, apiStatus } = useContext(ApiContext) const [formBlocks] = Form.useForm() - const config = useAppSelector(state => state.config) + const config = useAppSelector((state) => state.config) const [results, setResults] = useState>([]) const [isDefaultLoading, setIsDefaultLoading] = useState(false) const [defaultBlockTime, setDefaultBlockTime] = useState() @@ -54,18 +40,12 @@ function AverageBlockTime(): React.ReactElement { const loadDefaults = async (overwriteValues = false) => { try { setIsDefaultLoading(true) - const selectedChain = formBlocks.getFieldValue("chain") + const selectedChain = formBlocks.getFieldValue('chain') - const network = config.networks.find( - auxNetwork => auxNetwork.networkName === selectedChain - ) + const network = config.networks.find((auxNetwork) => auxNetwork.networkName === selectedChain) // Get default block time - const auxApi = await connectToApi( - apiConnections, - apiStatus, - network || ({} as PolkadotNetwork) - ) + const auxApi = await connectToApi(apiConnections, apiStatus, network || ({} as PolkadotNetwork)) const timeMs = getExpectedBlockTime(auxApi) @@ -73,19 +53,13 @@ function AverageBlockTime(): React.ReactElement { const latestBlock = await auxApi.rpc.chain.getHeader() const currentBlockNumber = latestBlock.number.toNumber() - if ( - timeMs && - (overwriteValues || !formBlocks.getFieldValue("expectedBlockTime")) - ) { + if (timeMs && (overwriteValues || !formBlocks.getFieldValue('expectedBlockTime'))) { formBlocks.setFieldsValue({ expectedBlockTime: timeMs, }) } - if ( - currentBlockNumber && - (overwriteValues || !formBlocks.getFieldValue("endBlock")) - ) { + if (currentBlockNumber && (overwriteValues || !formBlocks.getFieldValue('endBlock'))) { formBlocks.setFieldsValue({ endBlock: currentBlockNumber, }) @@ -94,7 +68,7 @@ function AverageBlockTime(): React.ReactElement { setIsDefaultLoading(false) } catch (err) { console.log(err) - message.error("An error ocurred when trying to load end block.") + message.error('An error ocurred when trying to load end block.') setIsDefaultLoading(false) } } @@ -103,23 +77,20 @@ function AverageBlockTime(): React.ReactElement { loadDefaults(true) } - const checkBlockRange = ( - changedValues: Record, - values: AvgBlockTimeFormValues - ) => { + const checkBlockRange = (changedValues: Record, values: AvgBlockTimeFormValues) => { // Validate that start block is less than end block if (changedValues && Number(values.startBlock) >= Number(values.endBlock)) { setIsBlockRangeValid(false) formBlocks.setFields([ { - name: "startBlock", + name: 'startBlock', value: values.startBlock, - errors: ["Start Block must be less than End Block"], + errors: ['Start Block must be less than End Block'], }, { - name: "endBlock", + name: 'endBlock', value: values.endBlock, - errors: ["End Block must be greater than Start Block"], + errors: ['End Block must be greater than Start Block'], }, ]) } else { @@ -133,23 +104,16 @@ function AverageBlockTime(): React.ReactElement { } const fillStartBlock = (hours = 0, days = 0, weeks = 0, months = 0) => { - const endBlock = formBlocks.getFieldValue("endBlock") - const expectedBlockTime = formBlocks.getFieldValue("expectedBlockTime") + const endBlock = formBlocks.getFieldValue('endBlock') + const expectedBlockTime = formBlocks.getFieldValue('expectedBlockTime') if (!endBlock || !expectedBlockTime) { - message.error("Please set End block and Expected block time") + message.error('Please set End block and Expected block time') return } formBlocks.setFieldsValue({ - startBlock: estimateStartBlockNumber( - endBlock, - expectedBlockTime, - hours, - days, - weeks, - months - ), + startBlock: estimateStartBlockNumber(endBlock, expectedBlockTime, hours, days, weeks, months), }) setIsBlockRangeValid(true) @@ -169,9 +133,7 @@ function AverageBlockTime(): React.ReactElement { setIsLoading(true) - const auxNetwork = config.networks.find( - auxNetwork => auxNetwork.networkName === chain - ) + const auxNetwork = config.networks.find((auxNetwork) => auxNetwork.networkName === chain) if (!auxNetwork) return @@ -189,8 +151,9 @@ function AverageBlockTime(): React.ReactElement { const timePassed = endBlockTime.toNumber() - startBlockTime.toNumber() const avgBlockTime = timePassed / (endBlock - startBlock) / 1000 - setResults(oldValue => [ + setResults((oldValue) => [ { + index: oldValue.length, startBlock, startBlockTime: formatDate(startBlockTime.toNumber(), config.utcTime), endBlock, @@ -203,7 +166,7 @@ function AverageBlockTime(): React.ReactElement { setIsLoading(false) } catch (err) { console.log(err) - message.error("An error ocurred when loading block data.") + message.error('An error ocurred when loading block data.') setIsLoading(false) } } @@ -211,8 +174,8 @@ function AverageBlockTime(): React.ReactElement { const renderStartBlock = (value: number, row: AvgBlockTimeResult) => { return ( <> -
{value}
-
{row.startBlockTime}
+
{value}
+
{row.startBlockTime}
) } @@ -220,8 +183,8 @@ function AverageBlockTime(): React.ReactElement { const renderEndBlock = (value: number, row: AvgBlockTimeResult) => { return ( <> -
{value}
-
{row.endBlockTime}
+
{value}
+
{row.endBlockTime}
) } @@ -232,148 +195,142 @@ function AverageBlockTime(): React.ReactElement { const columns = [ { - title: "Start Block", - dataIndex: "startBlock", - key: "startBlock", + title: 'Start Block', + dataIndex: 'startBlock', + key: 'startBlock', render: renderStartBlock, }, { - title: "End Block", - dataIndex: "endBlock", - key: "endBlock", + title: 'End Block', + dataIndex: 'endBlock', + key: 'endBlock', render: renderEndBlock, }, { - title: "Chain", - dataIndex: "chain", - key: "chain", + title: 'Chain', + dataIndex: 'chain', + key: 'chain', }, { - title: "Average Block Time", - dataIndex: "avgBlockTime", - key: "avgBlockTime", + title: 'Average Block Time', + dataIndex: 'avgBlockTime', + key: 'avgBlockTime', render: renderAverageBlockTime, }, ] return ( -
+
+ onFinish={handleOnCalculate} + > -
+ + ]} + > - - - - - + + ]} + > - - + + - -
+
+
{isDefaultLoading && ( -
+
)} {defaultBlockTime !== undefined && ( -
- {defaultBlockTime === 0 - ? "No default value" - : `Default value: ${defaultBlockTime} ms`} +
+ {defaultBlockTime === 0 ? 'No default value' : `Default value: ${defaultBlockTime} ms`}
)}
-
+
- {config.networks - .filter(network => network.enabled) + .filter((network) => network.enabled) .map((network, index) => ( {network.networkName} @@ -383,18 +340,19 @@ function AverageBlockTime(): React.ReactElement {

Results:

-
+
) } diff --git a/src/components/BlockAuthor/BlockAuthor.less b/src/components/BlockAuthor/BlockAuthor.less index 3819c7b..4b61d21 100644 --- a/src/components/BlockAuthor/BlockAuthor.less +++ b/src/components/BlockAuthor/BlockAuthor.less @@ -37,11 +37,11 @@ .fill-start-block-btn, .reset-block-time-btn { - background-color: #FFE3F1; + background-color: #ffe3f1; border-color: #444444; &:disabled { border-color: inherit; } } -} \ No newline at end of file +} diff --git a/src/components/BlockAuthor/BlockAuthor.tsx b/src/components/BlockAuthor/BlockAuthor.tsx index 1016fa4..d7800c8 100644 --- a/src/components/BlockAuthor/BlockAuthor.tsx +++ b/src/components/BlockAuthor/BlockAuthor.tsx @@ -1,24 +1,11 @@ -import { BarChartOutlined, CaretRightOutlined } from "@ant-design/icons" -import { - Button, - Col, - Collapse, - Form, - InputNumber, - List, - message, - Row, - Select, - Space, - Spin, - Table, -} from "antd" -import React, { useContext, useEffect, useState } from "react" -import { useAppSelector } from "../../store/hooks" -import { PolkadotNetwork } from "../../types" -import { estimateStartBlockNumber, findAuthorName, getExpectedBlockTime } from "../../utils/UtilsFunctions" -import { ApiContext, ApiContextData, connectToApi } from "../utils/ApiProvider" -import "./BlockAuthor.less" +import { BarChartOutlined, CaretRightOutlined } from '@ant-design/icons' +import { Button, Col, Collapse, Form, InputNumber, List, message, Row, Select, Space, Spin, Table } from 'antd' +import React, { useContext, useEffect, useState } from 'react' +import { useAppSelector } from '../../store/hooks' +import { PolkadotNetwork } from '../../types' +import { estimateStartBlockNumber, findAuthorName, getExpectedBlockTime } from '../../utils/UtilsFunctions' +import { ApiContext, ApiContextData, connectToApi } from '../utils/ApiProvider' +import './BlockAuthor.less' interface BlockAuthorFormValues { startBlock: number @@ -40,8 +27,8 @@ interface BlockInfo { function BlockAuthor(): React.ReactElement { const { apiConnections, apiStatus } = useContext(ApiContext) const [formBlocks] = Form.useForm() - const addresses = useAppSelector(state => state.address.list) - const config = useAppSelector(state => state.config) + const addresses = useAppSelector((state) => state.address.list) + const config = useAppSelector((state) => state.config) const [results, setResults] = useState>([]) const [isDefaultLoading, setIsDefaultLoading] = useState(false) const [defaultBlockTime, setDefaultBlockTime] = useState() @@ -55,18 +42,12 @@ function BlockAuthor(): React.ReactElement { const loadDefaults = async (overwriteValues = false) => { try { setIsDefaultLoading(true) - const selectedChain = formBlocks.getFieldValue("chain") + const selectedChain = formBlocks.getFieldValue('chain') - const network = config.networks.find( - auxNetwork => auxNetwork.networkName === selectedChain - ) + const network = config.networks.find((auxNetwork) => auxNetwork.networkName === selectedChain) // Get default block time - const auxApi = await connectToApi( - apiConnections, - apiStatus, - network || ({} as PolkadotNetwork) - ) + const auxApi = await connectToApi(apiConnections, apiStatus, network || ({} as PolkadotNetwork)) const timeMs = getExpectedBlockTime(auxApi) @@ -74,19 +55,13 @@ function BlockAuthor(): React.ReactElement { const latestBlock = await auxApi.rpc.chain.getHeader() const currentBlockNumber = latestBlock.number.toNumber() - if ( - timeMs && - (overwriteValues || !formBlocks.getFieldValue("expectedBlockTime")) - ) { + if (timeMs && (overwriteValues || !formBlocks.getFieldValue('expectedBlockTime'))) { formBlocks.setFieldsValue({ expectedBlockTime: timeMs, }) } - if ( - currentBlockNumber && - (overwriteValues || !formBlocks.getFieldValue("endBlock")) - ) { + if (currentBlockNumber && (overwriteValues || !formBlocks.getFieldValue('endBlock'))) { formBlocks.setFieldsValue({ endBlock: currentBlockNumber, }) @@ -95,7 +70,7 @@ function BlockAuthor(): React.ReactElement { setIsDefaultLoading(false) } catch (err) { console.log(err) - message.error("An error ocurred when trying to load end block.") + message.error('An error ocurred when trying to load end block.') setIsDefaultLoading(false) } } @@ -104,23 +79,20 @@ function BlockAuthor(): React.ReactElement { loadDefaults(true) } - const checkBlockRange = ( - changedValues: Record, - values: BlockAuthorFormValues - ) => { + const checkBlockRange = (changedValues: Record, values: BlockAuthorFormValues) => { // Validate that start block is less than or equal to end block if (changedValues && Number(values.startBlock) > Number(values.endBlock)) { setIsBlockRangeValid(false) formBlocks.setFields([ { - name: "startBlock", + name: 'startBlock', value: values.startBlock, - errors: ["Start Block must be less than or equal to End Block"], + errors: ['Start Block must be less than or equal to End Block'], }, { - name: "endBlock", + name: 'endBlock', value: values.endBlock, - errors: ["End Block must be greater than or equal to Start Block"], + errors: ['End Block must be greater than or equal to Start Block'], }, ]) } else { @@ -135,23 +107,16 @@ function BlockAuthor(): React.ReactElement { } const fillStartBlock = (hours = 0, days = 0, weeks = 0, months = 0) => { - const endBlock = formBlocks.getFieldValue("endBlock") - const expectedBlockTime = formBlocks.getFieldValue("expectedBlockTime") + const endBlock = formBlocks.getFieldValue('endBlock') + const expectedBlockTime = formBlocks.getFieldValue('expectedBlockTime') if (!endBlock || !expectedBlockTime) { - message.error("Please set End block and Expected block time") + message.error('Please set End block and Expected block time') return } formBlocks.setFieldsValue({ - startBlock: estimateStartBlockNumber( - endBlock, - expectedBlockTime, - hours, - days, - weeks, - months - ), + startBlock: estimateStartBlockNumber(endBlock, expectedBlockTime, hours, days, weeks, months), }) setIsBlockRangeValid(true) @@ -171,9 +136,7 @@ function BlockAuthor(): React.ReactElement { setIsLoading(true) - const auxNetwork = config.networks.find( - auxNetwork => auxNetwork.networkName === chain - ) + const auxNetwork = config.networks.find((auxNetwork) => auxNetwork.networkName === chain) if (!auxNetwork) return @@ -186,13 +149,8 @@ function BlockAuthor(): React.ReactElement { let promiseCount = 0 const allowedParallel = 10 let promises = [] - while ( - promiseCount < allowedParallel && - loadedUntil + promiseCount <= endBlock - ) { - promises.push( - auxApi.rpc.chain.getBlockHash(loadedUntil + promiseCount) - ) + while (promiseCount < allowedParallel && loadedUntil + promiseCount <= endBlock) { + promises.push(auxApi.rpc.chain.getBlockHash(loadedUntil + promiseCount)) promiseCount += 1 } const newHashes = await Promise.all(promises) @@ -231,7 +189,7 @@ function BlockAuthor(): React.ReactElement { setIsLoading(false) } catch (err) { console.log(err) - message.error("An error ocurred when loading block data.") + message.error('An error ocurred when loading block data.') setIsLoading(false) } } @@ -239,7 +197,7 @@ function BlockAuthor(): React.ReactElement { const renderAuthor = (row: BlockAuthorResult) => { return ( <> - {row.authorName && {row.authorName}} + {row.authorName && {row.authorName}} {row.authorAddress} ) @@ -247,22 +205,14 @@ function BlockAuthor(): React.ReactElement { const renderBlocks = (row: BlockAuthorResult) => { return ( - ( - - )}> - + }> + ( + renderItem={(item) => ( - {item.number} -{" "} - {item.hash} + {item.number} - {item.hash} )} /> @@ -273,135 +223,129 @@ function BlockAuthor(): React.ReactElement { const columns = [ { - title: "Author", - key: "author", + title: 'Author', + key: 'author', render: renderAuthor, }, { - title: "Number of Blocks", - key: "numberOfBlocks", + title: 'Number of Blocks', + key: 'numberOfBlocks', render: renderBlocks, }, ] return ( -
+
+ onFinish={handleOnCalculate} + > -
+ + ]} + > - - - - - + + ]} + > - - + + - -
+
+
{isDefaultLoading && ( -
+
)} {defaultBlockTime !== undefined && ( -
- {defaultBlockTime === 0 - ? "No default value" - : `Default value: ${defaultBlockTime} ms`} +
+ {defaultBlockTime === 0 ? 'No default value' : `Default value: ${defaultBlockTime} ms`}
)}
-
+
- {config.networks - .filter(network => network.enabled) + .filter((network) => network.enabled) .map((network, index) => ( {network.networkName} @@ -411,18 +355,19 @@ function BlockAuthor(): React.ReactElement {

Results:

-
+
) } diff --git a/src/components/BlockTime/BlockTime.less b/src/components/BlockTime/BlockTime.less index a419dad..c9b82e5 100644 --- a/src/components/BlockTime/BlockTime.less +++ b/src/components/BlockTime/BlockTime.less @@ -10,10 +10,10 @@ } .reset-block-time-btn { - background-color: #FFE3F1; + background-color: #ffe3f1; border-color: #444444; &:disabled { border-color: inherit; } } -} \ No newline at end of file +} diff --git a/src/components/BlockTime/BlockTime.tsx b/src/components/BlockTime/BlockTime.tsx index 668bbef..e3110f4 100644 --- a/src/components/BlockTime/BlockTime.tsx +++ b/src/components/BlockTime/BlockTime.tsx @@ -1,23 +1,12 @@ -import { BarChartOutlined } from "@ant-design/icons" -import { ApiPromise } from "@polkadot/api" -import { - Button, - Col, - DatePicker, - Form, - InputNumber, - message, - Row, - Space, - Spin, - Table, -} from "antd" -import { Moment } from "moment" -import React, { useContext, useEffect, useState } from "react" -import { useAppSelector } from "../../store/hooks" -import { formatDate, getExpectedBlockTime, toUnixTimestamp } from "../../utils/UtilsFunctions" -import { ApiContext, ApiContextData, connectToApi } from "../utils/ApiProvider" -import "./BlockTime.less" +import { BarChartOutlined } from '@ant-design/icons' +import { ApiPromise } from '@polkadot/api' +import { Button, Col, DatePicker, Form, InputNumber, message, Row, Space, Spin, Table } from 'antd' +import { Moment } from 'moment' +import React, { useContext, useEffect, useState } from 'react' +import { useAppSelector } from '../../store/hooks' +import { formatDate, getExpectedBlockTime, toUnixTimestamp } from '../../utils/UtilsFunctions' +import { ApiContext, ApiContextData, connectToApi } from '../utils/ApiProvider' +import './BlockTime.less' interface BlockTimeFormValues { datetime: Moment @@ -29,21 +18,20 @@ interface BlockTimeResult { chainName: string estimateResult?: number | string type: string + blocksDifference: number } function BlockTime(): React.ReactElement { const { apiConnections, apiStatus } = useContext(ApiContext) const [formBlocks] = Form.useForm() - const config = useAppSelector(state => state.config) - const selectedNetworks = config.networks.filter( - auxNetwork => auxNetwork.enabled - ) + const config = useAppSelector((state) => state.config) + const selectedNetworks = config.networks.filter((auxNetwork) => auxNetwork.enabled) const [results, setResults] = useState>([]) const [isOptionalFieldsValid, setIsOptionalFieldsValid] = useState(false) const [isExpectedTimeLoading, setIsExpectedTimeLoading] = useState(false) - const [defaultBlockTimes, setDefaultBlockTimes] = useState< - (number | undefined)[] - >(selectedNetworks.map(() => undefined)) + const [defaultBlockTimes, setDefaultBlockTimes] = useState<(number | undefined)[]>( + selectedNetworks.map(() => undefined) + ) const [isLoading, setIsLoading] = useState(false) useEffect(() => { @@ -55,75 +43,67 @@ function BlockTime(): React.ReactElement { setIsExpectedTimeLoading(true) const apis = await Promise.all( - selectedNetworks.map(auxNetwork => { + selectedNetworks.map((auxNetwork) => { return connectToApi(apiConnections, apiStatus, auxNetwork) }) ) - const newDefaults = apis.map(auxApi => - getExpectedBlockTime(auxApi) - ) + const newDefaults = apis.map((auxApi) => getExpectedBlockTime(auxApi)) formBlocks.setFieldsValue({ - blockTimes: newDefaults.map( - (auxDefault, index) => - formBlocks.getFieldValue("blockTimes")[index] || auxDefault - ), + blockTimes: newDefaults.map((auxDefault, index) => formBlocks.getFieldValue('blockTimes')[index] || auxDefault), }) - setDefaultBlockTimes(newDefaults.map(auxDefault => auxDefault || 0)) + setDefaultBlockTimes(newDefaults.map((auxDefault) => auxDefault || 0)) setIsExpectedTimeLoading(false) } catch (err) { console.log(err) - message.error("An error ocurred when trying to load expected block time.") + message.error('An error ocurred when trying to load expected block time.') setIsExpectedTimeLoading(false) } } const resetAllBlockTimes = () => { - const blockTimes = defaultBlockTimes.map(auxTime => auxTime || 6000) + const blockTimes = defaultBlockTimes.map((auxTime) => auxTime || 6000) formBlocks.setFieldsValue({ blockTimes, }) } const resetBlockTime = (index: number) => { - const blockTimes = formBlocks.getFieldValue("blockTimes") + const blockTimes = formBlocks.getFieldValue('blockTimes') blockTimes[index] = defaultBlockTimes[index] || 6000 formBlocks.setFieldsValue({ blockTimes, }) } - const checkOptionalFields = ( - changedValues: Record, - values: BlockTimeFormValues - ) => { + const checkOptionalFields = (changedValues: Record, values: BlockTimeFormValues) => { // Validate that start block is less than end block if (changedValues && !values.blockNumber && !values.datetime) { setIsOptionalFieldsValid(false) formBlocks.setFields([ { - name: "blockNumber", + name: 'blockNumber', value: values.blockNumber, - errors: ["Enter block number or datetime"], + errors: ['Enter block number or datetime'], }, { - name: "datetime", + name: 'datetime', value: values.datetime, - errors: ["Enter block number or datetime"], + errors: ['Enter block number or datetime'], }, ]) } else { setIsOptionalFieldsValid(true) formBlocks.setFields([ { - name: "blockNumber", + name: 'blockNumber', value: values.blockNumber, errors: [], }, { - name: "datetime", + name: 'datetime', value: values.datetime, errors: [], }, @@ -148,52 +128,42 @@ function BlockTime(): React.ReactElement { } } catch (err) { console.log(err) - message.error("An error ocurred when loading block data.") + message.error('An error ocurred when loading block data.') setIsLoading(false) } } - const estimateForBlockNumber = async ( - blockNumber: number, - expectedBlockTimes: number[] - ) => { + const estimateForBlockNumber = async (blockNumber: number, expectedBlockTimes: number[]) => { setIsLoading(true) const auxResults: BlockTimeResult[] = [] let index = 0 while (index < selectedNetworks.length) { try { - const api = await connectToApi( - apiConnections, - apiStatus, - selectedNetworks[index] - ) + const api = await connectToApi(apiConnections, apiStatus, selectedNetworks[index]) // Get current block number const latestBlock = await api.rpc.chain.getHeader() const currentBlockNumber = latestBlock.number.toNumber() - let formattedResult = "" - let type = "" + let formattedResult = '' + let type = '' + const blocksDifference = blockNumber - currentBlockNumber // If it is future, estimate the date time if (blockNumber > currentBlockNumber) { - const currentHash = await api.rpc.chain.getBlockHash( - currentBlockNumber - ) + const currentHash = await api.rpc.chain.getBlockHash(currentBlockNumber) const currentTime = await api.query.timestamp.now.at(currentHash) - const estimatedTime = - currentTime.toNumber() + - expectedBlockTimes[index] * (blockNumber - currentBlockNumber) + const estimatedTime = currentTime.toNumber() + expectedBlockTimes[index] * blocksDifference formattedResult = formatDate(estimatedTime, config.utcTime) - type = "Future" + type = 'Future' // If it is past, fetch the blocktime } else { const pastHash = await api.rpc.chain.getBlockHash(blockNumber) const pastTime = await api.query.timestamp.now.at(pastHash) formattedResult = formatDate(pastTime.toNumber(), config.utcTime) - type = "Past" + type = 'Past' } // Add estimate to results @@ -201,6 +171,7 @@ function BlockTime(): React.ReactElement { chainName: selectedNetworks[index].networkName, estimateResult: formattedResult, type, + blocksDifference, }) index += 1 @@ -213,39 +184,28 @@ function BlockTime(): React.ReactElement { setIsLoading(false) } - const estimateForDateTime = async ( - datetime: Moment, - expectedBlockTimes: number[] - ) => { + const estimateForDateTime = async (datetime: Moment, expectedBlockTimes: number[]) => { setIsLoading(true) const inputTimestamp = toUnixTimestamp(datetime, config.utcTime) let index = 0 while (index < selectedNetworks.length) { try { - const api = await connectToApi( - apiConnections, - apiStatus, - selectedNetworks[index] - ) + const api = await connectToApi(apiConnections, apiStatus, selectedNetworks[index]) // Get current block number const latestBlock = await api.rpc.chain.getHeader() const currentBlockNumber = latestBlock.number.toNumber() const currentHash = await api.rpc.chain.getBlockHash(currentBlockNumber) - const currentTime = ( - await api.query.timestamp.now.at(currentHash) - ).toNumber() + const currentTime = (await api.query.timestamp.now.at(currentHash)).toNumber() let result: number - let type = "" + let type = '' // If it is future, estimate the block number if (inputTimestamp > currentTime) { - result = - currentBlockNumber + - Math.ceil((inputTimestamp - currentTime) / expectedBlockTimes[index]) - type = "Future" + result = currentBlockNumber + Math.ceil((inputTimestamp - currentTime) / expectedBlockTimes[index]) + type = 'Future' // If it is past, find the block number } else { @@ -256,24 +216,25 @@ function BlockTime(): React.ReactElement { currentBlockNumber, expectedBlockTimes[index] ) - type = "Past" + type = 'Past' } // Add estimate to results - setResults(oldResults => { + setResults((oldResults) => { return [ ...oldResults, { chainName: selectedNetworks[index].networkName, estimateResult: result, type, + blocksDifference: result - currentBlockNumber, }, ] }) index += 1 } catch (err) { - message.error("An error happened when estimating block times/numbers") + message.error('An error happened when estimating block times/numbers') console.log(err) index += 1 } @@ -295,9 +256,7 @@ function BlockTime(): React.ReactElement { // Get timestamp at first block (block 1) const firstBlockHash = await api.rpc.chain.getBlockHash(1) - const firstBlockTime = ( - await api.query.timestamp.now.at(firstBlockHash) - ).toNumber() + const firstBlockTime = (await api.query.timestamp.now.at(firstBlockHash)).toNumber() // Handle special cases if (targetTime <= firstBlockTime) { @@ -318,40 +277,23 @@ function BlockTime(): React.ReactElement { let searchBlockNumber if (directionLeftToRight) { // Estimate using expectedBlockTime - searchBlockNumber = - leftBlockNumber + - Math.max( - 1, - Math.round((targetTime - leftBlockTime) / expectedBlockTime) - ) + searchBlockNumber = leftBlockNumber + Math.max(1, Math.round((targetTime - leftBlockTime) / expectedBlockTime)) // If estimation goes too high, search block in the middle instead if (searchBlockNumber > rightBlockNumber - 1) { - searchBlockNumber = Math.ceil( - (leftBlockNumber + rightBlockNumber) / 2 - ) + searchBlockNumber = Math.ceil((leftBlockNumber + rightBlockNumber) / 2) } } else { // Estimate using expectedBlockTime searchBlockNumber = - rightBlockNumber - - Math.max( - 1, - Math.round((rightBlockTime - targetTime) / expectedBlockTime) - ) + rightBlockNumber - Math.max(1, Math.round((rightBlockTime - targetTime) / expectedBlockTime)) // If estimation goes too low, search block in the middle instead if (searchBlockNumber < leftBlockNumber + 1) { - searchBlockNumber = Math.floor( - (leftBlockNumber + rightBlockNumber) / 2 - ) + searchBlockNumber = Math.floor((leftBlockNumber + rightBlockNumber) / 2) } } // Load search block time - const searchBlockHash = await api.rpc.chain.getBlockHash( - searchBlockNumber - ) - const searchBlockTime = ( - await api.query.timestamp.now.at(searchBlockHash) - ).toNumber() + const searchBlockHash = await api.rpc.chain.getBlockHash(searchBlockNumber) + const searchBlockTime = (await api.query.timestamp.now.at(searchBlockHash)).toNumber() // If we found the block, return the value if (searchBlockTime === targetTime) return searchBlockNumber @@ -377,7 +319,7 @@ function BlockTime(): React.ReactElement { } } - throw Error("Error estimating the block number") + throw Error('Error estimating the block number') } const renderChain = (row: BlockTimeResult) => { @@ -388,57 +330,68 @@ function BlockTime(): React.ReactElement { return
{row.estimateResult}
} + const renderBlocksDifference = (row: BlockTimeResult) => { + return
{row.blocksDifference} blocks
+ } + const columns = [ { - title: "Chain", - key: "chain", + title: 'Chain', + key: 'chain', render: renderChain, }, { - title: "Type", - key: "type", - dataIndex: "type", + title: 'Type', + key: 'type', + dataIndex: 'type', }, { - title: "Estimated", - key: "action", + title: 'Estimated', + key: 'action', render: renderResult, }, + { + title: 'Blocks Difference', + key: 'action', + render: renderBlocksDifference, + }, ] return ( -
+
undefined), }} - onFinish={handleOnCalculate}> + onFinish={handleOnCalculate} + > - - + + - + - + {(fields, operations, { errors }) => { return (
- -
Expected Block Times (ms):{" "} + + Expected Block Times (ms):{' '} @@ -453,28 +406,30 @@ function BlockTime(): React.ReactElement { rules={[ { required: true, - message: "Please input expected block time", + message: 'Please input expected block time', }, ]} - key={index}> + key={index} + > {isExpectedTimeLoading && ( -
+
)} {defaultBlockTimes[index] !== undefined && ( -
+
{defaultBlockTimes[index] === 0 - ? "No default value" + ? 'No default value' : `Default value: ${defaultBlockTimes[index]} ms`}
)} @@ -515,18 +470,19 @@ function BlockTime(): React.ReactElement { */}

Result:

-
+
) } diff --git a/src/components/Config/AddEndpointModal.tsx b/src/components/Config/AddEndpointModal.tsx index 7aa19ae..c20ab65 100644 --- a/src/components/Config/AddEndpointModal.tsx +++ b/src/components/Config/AddEndpointModal.tsx @@ -1,10 +1,10 @@ -import { ApiPromise, WsProvider } from "@polkadot/api" -import { Button, Form, Input, Modal, Row, Space, message, Spin } from "antd" -import React, { useContext, useEffect, useState } from "react" -import { addEndpoint } from "../../store/actions/configActions" -import { useAppDispatch, useAppSelector } from "../../store/hooks" -import { RPCEndpoint } from "../../types" -import { ApiContext, ApiContextData } from "../utils/ApiProvider" +import { ApiPromise, WsProvider } from '@polkadot/api' +import { Button, Form, Input, Modal, Row, Space, message, Spin } from 'antd' +import React, { useContext, useEffect, useState } from 'react' +import { addEndpoint } from '../../store/actions/configActions' +import { useAppDispatch, useAppSelector } from '../../store/hooks' +import { RPCEndpoint } from '../../types' +import { ApiContext, ApiContextData } from '../utils/ApiProvider' type AddEndpointModalProps = { showModal: boolean @@ -16,7 +16,7 @@ function AddEndpointModal(props: AddEndpointModalProps): React.ReactElement { const { deleteNetworkConnection } = useContext(ApiContext) const [form] = Form.useForm() const dispatch = useAppDispatch() - const networks = useAppSelector(state => state.config.networks) + const networks = useAppSelector((state) => state.config.networks) const [isLoading, setIsLoading] = useState(false) const { showModal, setShowModal, chosenNetwork } = props @@ -29,23 +29,21 @@ function AddEndpointModal(props: AddEndpointModalProps): React.ReactElement { setIsLoading(true) const trimmedValue = rpcEndpoint.value.trim() const checkExisting = networks - .find(auxNetwork => auxNetwork.networkName === chosenNetwork) - ?.endpoints.find(auxEndpoint => auxEndpoint.value === trimmedValue) + .find((auxNetwork) => auxNetwork.networkName === chosenNetwork) + ?.endpoints.find((auxEndpoint) => auxEndpoint.value === trimmedValue) if (checkExisting) { - message.error( - `Endpoint ${checkExisting.value} already exists in network ${chosenNetwork}` - ) + message.error(`Endpoint ${checkExisting.value} already exists in network ${chosenNetwork}`) setIsLoading(false) return } const provider = new WsProvider(trimmedValue) - provider.on("error", () => { + provider.on('error', () => { provider.disconnect() message.error("Error: Couldn't connect to endpoint") setIsLoading(false) }) - await ApiPromise.create({ provider }) + await ApiPromise.create({ provider }) // const chainName = (await api.rpc.system.chain()).toString() provider.disconnect() dispatch( @@ -58,7 +56,7 @@ function AddEndpointModal(props: AddEndpointModalProps): React.ReactElement { deleteNetworkConnection(chosenNetwork) handleClose() } catch (err) { - message.error("Error: Invalid endpoint URL") + message.error('Error: Invalid endpoint URL') setIsLoading(false) } } @@ -70,43 +68,47 @@ function AddEndpointModal(props: AddEndpointModalProps): React.ReactElement { return ( + footer={null} + >
+ onFinish={onFormSubmit} + > - + ]} + > + - - + + - diff --git a/src/components/Config/AddNetworkModal.tsx b/src/components/Config/AddNetworkModal.tsx index 03faa62..e5b8b59 100644 --- a/src/components/Config/AddNetworkModal.tsx +++ b/src/components/Config/AddNetworkModal.tsx @@ -1,8 +1,8 @@ -import { ApiPromise, WsProvider } from "@polkadot/api" -import { Button, Form, Input, Modal, Row, Space, message, Spin } from "antd" -import React, { useEffect, useState } from "react" -import { addNetwork } from "../../store/actions/configActions" -import { useAppDispatch, useAppSelector } from "../../store/hooks" +import { ApiPromise, WsProvider } from '@polkadot/api' +import { Button, Form, Input, Modal, Row, Space, message, Spin } from 'antd' +import React, { useEffect, useState } from 'react' +import { addNetwork } from '../../store/actions/configActions' +import { useAppDispatch, useAppSelector } from '../../store/hooks' type AddNetworkModalProps = { showModal: boolean @@ -12,7 +12,7 @@ type AddNetworkModalProps = { function AddNetworkModal(props: AddNetworkModalProps): React.ReactElement { const [form] = Form.useForm() const dispatch = useAppDispatch() - const networks = useAppSelector(state => state.config.networks) + const networks = useAppSelector((state) => state.config.networks) const [isLoading, setIsLoading] = useState(false) const { showModal, setShowModal } = props useEffect(() => { @@ -23,20 +23,16 @@ function AddNetworkModal(props: AddNetworkModalProps): React.ReactElement { try { setIsLoading(true) const trimmedValue = formValues.networkName.trim() - const checkExisting = networks.find( - auxNetwork => auxNetwork.networkName === trimmedValue - ) + const checkExisting = networks.find((auxNetwork) => auxNetwork.networkName === trimmedValue) if (checkExisting) { - message.error( - `Network with name ${checkExisting.networkName} already exists` - ) + message.error(`Network with name ${checkExisting.networkName} already exists`) setIsLoading(false) return } const trimmedUrl = formValues.urlValue const provider = new WsProvider(trimmedUrl) - provider.on("error", () => { + provider.on('error', () => { provider.disconnect() message.error("Error: Couldn't connect to endpoint") setIsLoading(false) @@ -73,54 +69,59 @@ function AddNetworkModal(props: AddNetworkModalProps): React.ReactElement { return ( + footer={null} + > + onFinish={onFormSubmit} + > - + ]} + > + - + ]} + > + - - + + - diff --git a/src/components/Config/Configuration.less b/src/components/Config/Configuration.less index 60ef6d0..c806a24 100644 --- a/src/components/Config/Configuration.less +++ b/src/components/Config/Configuration.less @@ -7,13 +7,12 @@ font-size: 12px; color: gray; } - .add-network-button{ + .add-network-button { color: @primary-color; } - .networks-table{ - .ant-table-expanded-row.ant-table-expanded-row-level-1>.ant-table-cell{ + .networks-table { + .ant-table-expanded-row.ant-table-expanded-row-level-1 > .ant-table-cell { background-color: lightgray; } - } -} \ No newline at end of file +} diff --git a/src/components/Config/Configuration.tsx b/src/components/Config/Configuration.tsx index e5504f8..a03c372 100644 --- a/src/components/Config/Configuration.tsx +++ b/src/components/Config/Configuration.tsx @@ -1,16 +1,7 @@ -import React, { ReactNode, useContext, useState } from "react" -import { - Button, - Divider, - message, - Row, - Space, - Switch, - Table, - Popconfirm, -} from "antd" -import "./Configuration.less" -import { useAppDispatch, useAppSelector } from "../../store/hooks" +import React, { ReactNode, useContext, useState } from 'react' +import { Button, Divider, message, Row, Space, Switch, Table, Popconfirm } from 'antd' +import './Configuration.less' +import { useAppDispatch, useAppSelector } from '../../store/hooks' import { deleteNetwork, selectNetwork, @@ -19,24 +10,19 @@ import { setUtcTime, toggleEndpoint, resetConfig, -} from "../../store/actions/configActions" -import { PolkadotNetwork, RPCEndpoint } from "../../types" -import { - CheckOutlined, - DeleteOutlined, - PlusOutlined, - UndoOutlined, -} from "@ant-design/icons" -import AddEndpointModal from "./AddEndpointModal" -import { ApiContext, ApiContextData } from "../utils/ApiProvider" -import AddNetworkModal from "./AddNetworkModal" +} from '../../store/actions/configActions' +import { PolkadotNetwork, RPCEndpoint } from '../../types' +import { CheckOutlined, DeleteOutlined, PlusOutlined, UndoOutlined } from '@ant-design/icons' +import AddEndpointModal from './AddEndpointModal' +import { ApiContext, ApiContextData } from '../utils/ApiProvider' +import AddNetworkModal from './AddNetworkModal' function Configuration(): React.ReactElement { const { deleteNetworkConnection } = useContext(ApiContext) const dispatch = useAppDispatch() const [showAddNetworkModal, setShowAddNetworkModal] = useState(false) const [showAddEndpointModal, setShowAddEndpointModal] = useState(false) - const [networkChosenToAdd, setNetworkChosenToAdd] = useState("") + const [networkChosenToAdd, setNetworkChosenToAdd] = useState('') const config = useAppSelector((state) => state.config) const onUtcChange = (checked: boolean) => { @@ -47,11 +33,7 @@ function Configuration(): React.ReactElement { return ( <> {text} - {row.hostedBy ? ( - - {row.hostedBy} - ) : ( - "" - )} + {row.hostedBy ? - {row.hostedBy} : ''} ) } @@ -127,12 +109,7 @@ function Configuration(): React.ReactElement { Default ) : ( - )} @@ -143,19 +120,19 @@ function Configuration(): React.ReactElement { const renderExpandedRow = (row: PolkadotNetwork): ReactNode => { const endpointColumns = [ { - title: "Endpoint Name", - dataIndex: "value", - key: "value", + title: 'Endpoint Name', + dataIndex: 'value', + key: 'value', render: renderEndpointWithHost, }, { - title: "", - key: "toggle", + title: '', + key: 'toggle', render: (endpoint: RPCEndpoint) => renderEndpointToggle(row, endpoint), }, { - title: "Actions", - key: "actions", + title: 'Actions', + key: 'actions', render: (endpoint: RPCEndpoint) => renderEndpointActions(row, endpoint), }, ] @@ -185,24 +162,16 @@ function Configuration(): React.ReactElement { ) } - const renderEndpointToggle = ( - network: PolkadotNetwork, - endpoint: RPCEndpoint - ) => { + const renderEndpointToggle = (network: PolkadotNetwork, endpoint: RPCEndpoint) => { return ( { - const enabledList = network.endpoints.filter( - (auxEndpoint) => auxEndpoint.enabled - ) - if ( - enabledList.length === 1 && - enabledList[0].value === endpoint.value - ) { - message.warning("Needs to have at least one endpoint enabled") + const enabledList = network.endpoints.filter((auxEndpoint) => auxEndpoint.enabled) + if (enabledList.length === 1 && enabledList[0].value === endpoint.value) { + message.warning('Needs to have at least one endpoint enabled') return } handleToggleEndpoint(network.networkName, endpoint) @@ -211,10 +180,7 @@ function Configuration(): React.ReactElement { ) } - const renderEndpointActions = ( - network: PolkadotNetwork, - endpoint: RPCEndpoint - ) => { + const renderEndpointActions = (network: PolkadotNetwork, endpoint: RPCEndpoint) => { return ( - @@ -319,10 +261,7 @@ function Configuration(): React.ReactElement { rowKey="networkName" /> - + + -
- - - Polkadot -
Parachain Utilities
+
+ + + Polkadot +
Parachain Utilities
@@ -21,23 +21,22 @@ function NavbarComponent(): React.ReactElement { */} - - }> - - Address Book + + }> + + Address Book - - Average Block Time + + Average Block Time - - Block Time + + Block Time - - Block Author + + Block Author - - Config + + Config diff --git a/src/components/ParachainUtilities.tsx b/src/components/ParachainUtilities.tsx index 70fc07b..31f2f03 100644 --- a/src/components/ParachainUtilities.tsx +++ b/src/components/ParachainUtilities.tsx @@ -1,19 +1,19 @@ -import React, { useEffect, useState } from "react" -import { Layout, message, Spin } from "antd" -import { BrowserRouter, Switch, Route, Redirect } from "react-router-dom" -import { createWsEndpoints } from "@polkadot/apps-config" -import NavbarComponent from "./Navbar/Navbar" -import CustomSpinner from "./utils/CustomSpinner" -import AddressBook from "./AddressBook/AddressBook" -import Configuration from "./Config/Configuration" -import AverageBlockTime from "./AverageBlockTime/AverageBlockTime" -import BlockTime from "./BlockTime/BlockTime" -import BlockAuthor from "./BlockAuthor/BlockAuthor" -import { useAppDispatch, useAppSelector } from "../store/hooks" -import { replaceText } from "../utils/UtilsFunctions" -import { selectNetwork, setNetworkList } from "../store/actions/configActions" -import { PolkadotNetwork } from "../types" -import "./ParachainUtilities.less" +import React, { useEffect, useState } from 'react' +import { Layout, message, Spin } from 'antd' +import { BrowserRouter, Switch, Route, Redirect } from 'react-router-dom' +import { createWsEndpoints } from '@polkadot/apps-config' +import NavbarComponent from './Navbar/Navbar' +import CustomSpinner from './utils/CustomSpinner' +import AddressBook from './AddressBook/AddressBook' +import Configuration from './Config/Configuration' +import AverageBlockTime from './AverageBlockTime/AverageBlockTime' +import BlockTime from './BlockTime/BlockTime' +import BlockAuthor from './BlockAuthor/BlockAuthor' +import { useAppDispatch, useAppSelector } from '../store/hooks' +import { replaceText } from '../utils/UtilsFunctions' +import { selectNetwork, setNetworkList } from '../store/actions/configActions' +import { PolkadotNetwork } from '../types' +import './ParachainUtilities.less' function ParachainUtilities(): React.ReactElement { const [isLoading, setIsLoading] = useState(false) @@ -37,11 +37,7 @@ function ParachainUtilities(): React.ReactElement { const externalList = createWsEndpoints(replaceText) for (const auxEndpoint of externalList) { const networkName = auxEndpoint.text as string - if ( - auxEndpoint.value && - !auxEndpoint.isLightClient && - !auxEndpoint.isUnreachable - ) { + if (auxEndpoint.value && !auxEndpoint.isLightClient && !auxEndpoint.isUnreachable) { if (networksMap[networkName]) { networksMap[networkName].endpoints.push({ value: auxEndpoint.value, @@ -64,7 +60,7 @@ function ParachainUtilities(): React.ReactElement { } } - const defaultNetworks = ["Polkadot", "Kusama", "Acala", "Karura"] + const defaultNetworks = ['Polkadot', 'Kusama', 'Acala', 'Karura'] // Enable some default networks for (const network of defaultNetworks) { @@ -84,16 +80,11 @@ function ParachainUtilities(): React.ReactElement { } // If no endpoint is selected, set the first enabled endpoint as selected if (!config.selectedNetwork) { - dispatch( - selectNetwork( - config.networks?.find((auxEndpoint) => auxEndpoint.enabled) || - newNetworks[0] - ) - ) + dispatch(selectNetwork(config.networks?.find((auxEndpoint) => auxEndpoint.enabled) || newNetworks[0])) } } catch (err) { console.log(err) - message.error("An error ocurred when trying to load default networks") + message.error('An error ocurred when trying to load default networks') } } @@ -105,11 +96,7 @@ function ParachainUtilities(): React.ReactElement { - + diff --git a/src/components/utils/ApiProvider.tsx b/src/components/utils/ApiProvider.tsx index 25a6838..81f2cbf 100644 --- a/src/components/utils/ApiProvider.tsx +++ b/src/components/utils/ApiProvider.tsx @@ -1,8 +1,8 @@ -import React, { FC, useCallback, useRef } from "react" +import React, { FC, useCallback, useRef } from 'react' -import { ApiPromise, WsProvider } from "@polkadot/api" -import { typesBundle, typesChain } from "@polkadot/apps-config" -import { PolkadotNetwork } from "../../types" +import { ApiPromise, WsProvider } from '@polkadot/api' +import { typesBundle, typesChain } from '@polkadot/apps-config' +import { PolkadotNetwork } from '../../types' export interface ApiContextData { apiConnections: Record @@ -11,9 +11,7 @@ export interface ApiContextData { } // Ensure that ApiContext always exists -export const ApiContext = React.createContext( - {} as ApiContextData -) +export const ApiContext = React.createContext({} as ApiContextData) export const connectToApi = async ( apiConnections: Record, @@ -25,21 +23,17 @@ export const connectToApi = async ( return apiConnections[network.networkName] } - const listOfEndpoints = network.endpoints.filter( - endpoint => endpoint.enabled - ) + const listOfEndpoints = network.endpoints.filter((endpoint) => endpoint.enabled) if (listOfEndpoints.length === 0) listOfEndpoints.push(network.endpoints[0]) - const provider = new WsProvider( - listOfEndpoints.map(endpoint => endpoint.value) - ) + const provider = new WsProvider(listOfEndpoints.map((endpoint) => endpoint.value)) - provider.on("disconnected", () => { + provider.on('disconnected', () => { console.log(`Disconnected from provider of ${network.networkName}`) apiStatus[network.networkName] = false }) - provider.on("error", () => { + provider.on('error', () => { console.log(`Error on provider of ${network.networkName}`) apiStatus[network.networkName] = false }) @@ -50,11 +44,11 @@ export const connectToApi = async ( typesChain, }) - api.on("disconnected", () => { + api.on('disconnected', () => { console.log(`Disconnected from api of ${network.networkName}`) apiStatus[network.networkName] = false }) - api.on("error", () => { + api.on('error', () => { console.log(`Error on api of ${network.networkName}`) apiStatus[network.networkName] = false }) @@ -69,15 +63,11 @@ export const connectToApi = async ( } export const ApiProvider: FC = ({ children }) => { - const apiConnections = useRef>( - {} as Record - ) - const apiStatus = useRef>( - {} as Record - ) + const apiConnections = useRef>({} as Record) + const apiStatus = useRef>({} as Record) const deleteNetworkConnection = useCallback((networkName: string) => { - if (typeof apiConnections.current[networkName]?.disconnect === "function") { + if (typeof apiConnections.current[networkName]?.disconnect === 'function') { apiConnections.current[networkName].disconnect() } }, []) @@ -88,7 +78,8 @@ export const ApiProvider: FC = ({ children }) => { apiConnections: apiConnections.current, apiStatus: apiStatus.current, deleteNetworkConnection, - }}> + }} + > {children} ) diff --git a/src/components/utils/CustomSpinner.tsx b/src/components/utils/CustomSpinner.tsx index 575c0f0..775309c 100644 --- a/src/components/utils/CustomSpinner.tsx +++ b/src/components/utils/CustomSpinner.tsx @@ -1,6 +1,6 @@ -import React from "react"; -import { LoadingOutlined } from "@ant-design/icons"; +import React from 'react' +import { LoadingOutlined } from '@ant-design/icons' -const CustomSpinner = ; +const CustomSpinner = -export default CustomSpinner; +export default CustomSpinner diff --git a/src/index.css b/src/index.css index a426eec..d4bff77 100644 --- a/src/index.css +++ b/src/index.css @@ -1,13 +1,11 @@ body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Work Sans", "Segoe UI", - "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", - "Helvetica Neue", sans-serif; + font-family: -apple-system, BlinkMacSystemFont, 'Work Sans', 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', + 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", - monospace; + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; } diff --git a/src/index.tsx b/src/index.tsx index 4a0f1ed..c0756c4 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,16 +1,13 @@ -import React from "react" -import ReactDOM from "react-dom" -import "./index.css" -import App from "./App" -import reportWebVitals from "./reportWebVitals" -import WebFont from "webfontloader" +import React from 'react' +import ReactDOM from 'react-dom' +import './index.css' +import App from './App' +import reportWebVitals from './reportWebVitals' +import WebFont from 'webfontloader' WebFont.load({ google: { - families: [ - "Work Sans:300,400,700,300italic,400italic,700italic", - "sans-serif", - ], + families: ['Work Sans:300,400,700,300italic,400italic,700italic', 'sans-serif'], }, }) @@ -18,7 +15,7 @@ ReactDOM.render( , - document.getElementById("root") + document.getElementById('root') ) // If you want to start measuring performance in your app, pass a function diff --git a/src/reportWebVitals.ts b/src/reportWebVitals.ts index eb4be08..dfe2a4f 100644 --- a/src/reportWebVitals.ts +++ b/src/reportWebVitals.ts @@ -1,15 +1,15 @@ -import { ReportHandler } from 'web-vitals'; +import { ReportHandler } from 'web-vitals' const reportWebVitals = (onPerfEntry?: ReportHandler): void => { if (onPerfEntry && onPerfEntry instanceof Function) { import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { - getCLS(onPerfEntry); - getFID(onPerfEntry); - getFCP(onPerfEntry); - getLCP(onPerfEntry); - getTTFB(onPerfEntry); - }); + getCLS(onPerfEntry) + getFID(onPerfEntry) + getFCP(onPerfEntry) + getLCP(onPerfEntry) + getTTFB(onPerfEntry) + }) } -}; +} -export default reportWebVitals; +export default reportWebVitals diff --git a/src/setupTests.ts b/src/setupTests.ts index 8f2609b..52aaef1 100644 --- a/src/setupTests.ts +++ b/src/setupTests.ts @@ -2,4 +2,4 @@ // allows you to do things like: // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom'; +import '@testing-library/jest-dom' diff --git a/src/store/actions/addressActions.tsx b/src/store/actions/addressActions.tsx index e3fe11c..6794b22 100644 --- a/src/store/actions/addressActions.tsx +++ b/src/store/actions/addressActions.tsx @@ -1,9 +1,9 @@ -import { AnyAction } from "redux" -import { SubstrateAddress } from "../../types" +import { AnyAction } from 'redux' +import { SubstrateAddress } from '../../types' -export const SET_ADDRESS_LIST = "SET_ADDRESS_LIST" -export const ADD_ADDRESS = "ADD_ADDRESS" -export const DELETE_ADDRESS = "DELETE_ADDRESS" +export const SET_ADDRESS_LIST = 'SET_ADDRESS_LIST' +export const ADD_ADDRESS = 'ADD_ADDRESS' +export const DELETE_ADDRESS = 'DELETE_ADDRESS' export const setAddressList = (addressList: SubstrateAddress[]): AnyAction => { return { diff --git a/src/store/actions/configActions.tsx b/src/store/actions/configActions.tsx index 9a8d8dc..eabdbdc 100644 --- a/src/store/actions/configActions.tsx +++ b/src/store/actions/configActions.tsx @@ -1,17 +1,17 @@ -import { AnyAction } from "redux" -import { ConfigState, PolkadotNetwork, RPCEndpoint } from "../../types" +import { AnyAction } from 'redux' +import { ConfigState, PolkadotNetwork, RPCEndpoint } from '../../types' -export const SET_CONFIG = "SET_CONFIG" -export const SET_NETWORK_LIST = "SET_NETWORK_LIST" -export const SET_UTC_TIME = "SET_UTC_TIME" -export const ADD_NETWORK = "ADD_NETWORK" -export const DELETE_NETWORK = "DELETE_NETWORK" -export const SELECT_NETWORK = "SELECT_NETWORK" -export const TOGGLE_NETWORK = "TOGGLE_NETWORK" -export const ADD_ENDPOINT = "ADD_ENDPOINT" -export const DELETE_ENDPOINT = "DELETE_ENDPOINT" -export const TOGGLE_ENDPOINT = "TOGGLE_ENDPOINT" -export const RESET_CONFIG = "RESET_CONFIG" +export const SET_CONFIG = 'SET_CONFIG' +export const SET_NETWORK_LIST = 'SET_NETWORK_LIST' +export const SET_UTC_TIME = 'SET_UTC_TIME' +export const ADD_NETWORK = 'ADD_NETWORK' +export const DELETE_NETWORK = 'DELETE_NETWORK' +export const SELECT_NETWORK = 'SELECT_NETWORK' +export const TOGGLE_NETWORK = 'TOGGLE_NETWORK' +export const ADD_ENDPOINT = 'ADD_ENDPOINT' +export const DELETE_ENDPOINT = 'DELETE_ENDPOINT' +export const TOGGLE_ENDPOINT = 'TOGGLE_ENDPOINT' +export const RESET_CONFIG = 'RESET_CONFIG' export const setConfig = (config: ConfigState): AnyAction => { return { @@ -62,10 +62,7 @@ export const toggleNetwork = (networkName: string): AnyAction => { } } -export const addEndpoint = ( - networkName: string, - endpoint: RPCEndpoint -): AnyAction => { +export const addEndpoint = (networkName: string, endpoint: RPCEndpoint): AnyAction => { return { type: ADD_ENDPOINT, payload: { @@ -75,10 +72,7 @@ export const addEndpoint = ( } } -export const deleteEndpoint = ( - networkName: string, - endpointValue: string -): AnyAction => { +export const deleteEndpoint = (networkName: string, endpointValue: string): AnyAction => { return { type: DELETE_ENDPOINT, payload: { @@ -88,10 +82,7 @@ export const deleteEndpoint = ( } } -export const toggleEndpoint = ( - networkName: string, - endpointValue: string -): AnyAction => { +export const toggleEndpoint = (networkName: string, endpointValue: string): AnyAction => { return { type: TOGGLE_ENDPOINT, payload: { @@ -105,4 +96,4 @@ export const resetConfig = (): AnyAction => { return { type: RESET_CONFIG, } -} \ No newline at end of file +} diff --git a/src/store/hooks.ts b/src/store/hooks.ts index d209dd6..9e016e0 100644 --- a/src/store/hooks.ts +++ b/src/store/hooks.ts @@ -1,8 +1,7 @@ -import { Dispatch } from "react" -import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux" -import { AnyAction } from "redux" -import type { RootState, AppDispatch } from "./" +import { Dispatch } from 'react' +import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' +import { AnyAction } from 'redux' +import type { RootState, AppDispatch } from './' -export const useAppDispatch = (): Dispatch => - useDispatch() +export const useAppDispatch = (): Dispatch => useDispatch() export const useAppSelector: TypedUseSelectorHook = useSelector diff --git a/src/store/index.ts b/src/store/index.ts index 20cd8b3..33ed8dc 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,23 +1,20 @@ -import { createStore, applyMiddleware, compose, Store } from "redux" -import thunk from "redux-thunk" -import { persistStore, persistReducer } from "redux-persist" -import storage from "redux-persist/lib/storage" // defaults to localStorage for web +import { createStore, applyMiddleware, compose, Store } from 'redux' +import thunk from 'redux-thunk' +import { persistStore, persistReducer } from 'redux-persist' +import storage from 'redux-persist/lib/storage' // defaults to localStorage for web -import rootReducer from "./reducers" -import { Persistor } from "redux-persist/lib/types" +import rootReducer from './reducers' +import { Persistor } from 'redux-persist/lib/types' const middleware = [thunk] const rootPersistConfig = { - key: "root", + key: 'root', storage: storage, - whitelist: ["addresses", "config"], + whitelist: ['addresses', 'config'], } -const store = createStore( - persistReducer(rootPersistConfig, rootReducer), - compose(applyMiddleware(...middleware)) -) +const store = createStore(persistReducer(rootPersistConfig, rootReducer), compose(applyMiddleware(...middleware))) export type RootState = ReturnType export type AppDispatch = typeof store.dispatch diff --git a/src/store/reducers/addressReducer.tsx b/src/store/reducers/addressReducer.tsx index 3f7e407..a8224af 100644 --- a/src/store/reducers/addressReducer.tsx +++ b/src/store/reducers/addressReducer.tsx @@ -1,19 +1,12 @@ -import { AnyAction } from "redux" -import { AddressState } from "../../types" -import { - ADD_ADDRESS, - DELETE_ADDRESS, - SET_ADDRESS_LIST, -} from "../actions/addressActions" +import { AnyAction } from 'redux' +import { AddressState } from '../../types' +import { ADD_ADDRESS, DELETE_ADDRESS, SET_ADDRESS_LIST } from '../actions/addressActions' const initialState: AddressState = { list: [], } -const addressReducer = ( - state = initialState, - action: AnyAction -): AddressState => { +const addressReducer = (state = initialState, action: AnyAction): AddressState => { switch (action.type) { case SET_ADDRESS_LIST: return { @@ -28,9 +21,7 @@ const addressReducer = ( case DELETE_ADDRESS: return { ...state, - list: state.list.filter( - auxAddress => auxAddress.key !== action.payload - ), + list: state.list.filter((auxAddress) => auxAddress.key !== action.payload), } default: return state diff --git a/src/store/reducers/configReducer.tsx b/src/store/reducers/configReducer.tsx index 3e171a9..c88ca9b 100644 --- a/src/store/reducers/configReducer.tsx +++ b/src/store/reducers/configReducer.tsx @@ -1,5 +1,5 @@ -import { AnyAction } from "redux" -import { ConfigState } from "../../types" +import { AnyAction } from 'redux' +import { ConfigState } from '../../types' import { SET_CONFIG, SET_NETWORK_LIST, @@ -12,17 +12,14 @@ import { DELETE_ENDPOINT, TOGGLE_ENDPOINT, RESET_CONFIG, -} from "../actions/configActions" +} from '../actions/configActions' const initialState: ConfigState = { networks: [], utcTime: false, } -const configReducer = ( - state = initialState, - action: AnyAction -): ConfigState => { +const configReducer = (state = initialState, action: AnyAction): ConfigState => { switch (action.type) { case SET_CONFIG: return { @@ -47,9 +44,7 @@ const configReducer = ( case DELETE_NETWORK: return { ...state, - networks: state.networks.filter( - auxNetwork => auxNetwork.networkName !== action.payload - ), + networks: state.networks.filter((auxNetwork) => auxNetwork.networkName !== action.payload), } case SELECT_NETWORK: return { @@ -59,7 +54,7 @@ const configReducer = ( case TOGGLE_NETWORK: return { ...state, - networks: state.networks.map(auxNetwork => { + networks: state.networks.map((auxNetwork) => { if (auxNetwork.networkName === action.payload) { return { ...auxNetwork, @@ -72,7 +67,7 @@ const configReducer = ( case ADD_ENDPOINT: return { ...state, - networks: state.networks.map(auxNetwork => { + networks: state.networks.map((auxNetwork) => { if (auxNetwork.networkName === action.payload.networkName) { return { ...auxNetwork, @@ -85,13 +80,12 @@ const configReducer = ( case DELETE_ENDPOINT: return { ...state, - networks: state.networks.map(auxNetwork => { + networks: state.networks.map((auxNetwork) => { if (auxNetwork.networkName === action.payload.networkName) { return { ...auxNetwork, endpoints: auxNetwork.endpoints.filter( - auxEndpoint => - auxEndpoint.value !== action.payload.endpointValue + (auxEndpoint) => auxEndpoint.value !== action.payload.endpointValue ), } } @@ -101,11 +95,11 @@ const configReducer = ( case TOGGLE_ENDPOINT: return { ...state, - networks: state.networks.map(auxNetwork => { + networks: state.networks.map((auxNetwork) => { if (auxNetwork.networkName === action.payload.networkName) { return { ...auxNetwork, - endpoints: auxNetwork.endpoints.map(auxEndpoint => { + endpoints: auxNetwork.endpoints.map((auxEndpoint) => { if (auxEndpoint.value === action.payload.endpointValue) { return { ...auxEndpoint, @@ -120,10 +114,10 @@ const configReducer = ( }), } case RESET_CONFIG: - return { - ...state, - networks: [], - } + return { + ...state, + networks: [], + } default: return state } diff --git a/src/store/reducers/index.tsx b/src/store/reducers/index.tsx index f9c98ca..ac20950 100644 --- a/src/store/reducers/index.tsx +++ b/src/store/reducers/index.tsx @@ -1,21 +1,21 @@ -import { combineReducers } from "redux" -import addressReducer from "./addressReducer" -import configReducer from "./configReducer" -import { persistReducer } from "redux-persist" -import storage from "redux-persist/lib/storage" -import hardSet from "redux-persist/lib/stateReconciler/hardSet" +import { combineReducers } from 'redux' +import addressReducer from './addressReducer' +import configReducer from './configReducer' +import { persistReducer } from 'redux-persist' +import storage from 'redux-persist/lib/storage' +import hardSet from 'redux-persist/lib/stateReconciler/hardSet' const addressPersistConfig = { - key: "address", + key: 'address', storage: storage, - whitelist: ["list"], + whitelist: ['list'], stateReconciler: hardSet, } const configPersistConfig = { - key: "config", + key: 'config', storage: storage, - whitelist: ["networks", "utcTime", "selectedNetwork"], + whitelist: ['networks', 'utcTime', 'selectedNetwork'], stateReconciler: hardSet, } diff --git a/src/types.ts b/src/types.ts index 75281f3..c4acd71 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,33 +1,33 @@ -import { HTMLProps, ReactNode } from 'react'; +import { HTMLProps, ReactNode } from 'react' export interface SubstrateAddress { - name: string; - key: string; + name: string + key: string transformed: TransformedSubstrateAddress[] } export interface TransformedSubstrateAddress { - prefix: number; - value: string; + prefix: number + value: string } export interface PolkadotNetwork { - networkName: string; + networkName: string endpoints: RPCEndpoint[] - enabled: boolean; - prefix?: number; + enabled: boolean + prefix?: number } export interface RPCEndpoint { - value: string; - hostedBy?: string; - enabled: boolean; + value: string + hostedBy?: string + enabled: boolean } export interface ConfigState { - networks: PolkadotNetwork[], + networks: PolkadotNetwork[] selectedNetwork?: PolkadotNetwork - utcTime: boolean, + utcTime: boolean } export interface AddressState { diff --git a/src/utils/UtilsFunctions.ts b/src/utils/UtilsFunctions.ts index cca07c1..2466056 100644 --- a/src/utils/UtilsFunctions.ts +++ b/src/utils/UtilsFunctions.ts @@ -1,9 +1,9 @@ -import moment, { Moment } from "moment" -import { encodeAddress } from "@polkadot/util-crypto/address" -import { BN, BN_THOUSAND, BN_TWO } from "@polkadot/util" -import { SubstrateAddress, TransformedSubstrateAddress } from "../types" -import * as prefixes from "../utils/ss58-registry.json" -import { ApiPromise } from "@polkadot/api" +import moment, { Moment } from 'moment' +import { encodeAddress } from '@polkadot/util-crypto/address' +import { BN, BN_THOUSAND, BN_TWO } from '@polkadot/util' +import { SubstrateAddress, TransformedSubstrateAddress } from '../types' +import * as prefixes from '../utils/ss58-registry.json' +import { ApiPromise } from '@polkadot/api' export const replaceText = ( key: string, @@ -20,10 +20,7 @@ export const replaceText = ( return value || key } -export const transformDate = ( - unixTimestamp: number, - transformUtc: boolean -): Moment => { +export const transformDate = (unixTimestamp: number, transformUtc: boolean): Moment => { let auxMoment if (transformUtc) { auxMoment = moment.utc(unixTimestamp) @@ -33,19 +30,12 @@ export const transformDate = ( return auxMoment } -export const formatDate = ( - unixTimestamp: number, - transformUtc: boolean, - format = "YYYY-MM-DD HH:mm:ss" -): string => { +export const formatDate = (unixTimestamp: number, transformUtc: boolean, format = 'YYYY-MM-DD HH:mm:ss'): string => { return transformDate(unixTimestamp, transformUtc).format(format) } -export const toUnixTimestamp = ( - dateTime: Moment, - transformUtc: boolean -): number => { - const simpleDateTime = dateTime.format("YYYY-MM-DD HH:mm:ss") +export const toUnixTimestamp = (dateTime: Moment, transformUtc: boolean): number => { + const simpleDateTime = dateTime.format('YYYY-MM-DD HH:mm:ss') let timestamp if (transformUtc) { timestamp = moment.utc(simpleDateTime) @@ -55,10 +45,8 @@ export const toUnixTimestamp = ( return timestamp.valueOf() } -export const transformAddress = ( - key: string -): TransformedSubstrateAddress[] => { - const publicKey = Uint8Array.from(Buffer.from(key.substring(2), "hex")) +export const transformAddress = (key: string): TransformedSubstrateAddress[] => { + const publicKey = Uint8Array.from(Buffer.from(key.substring(2), 'hex')) const newFormats: TransformedSubstrateAddress[] = [] for (const auxPrefix of prefixes.registry) { if (auxPrefix.prefix !== 46 && auxPrefix.prefix !== 47) { @@ -71,10 +59,7 @@ export const transformAddress = ( return newFormats } -export const findAuthorName = ( - savedAddresses: SubstrateAddress[], - address: string -): string | undefined => { +export const findAuthorName = (savedAddresses: SubstrateAddress[], address: string): string | undefined => { for (const auxAddress of savedAddresses) { for (const auxTransformed of auxAddress.transformed) { if (auxTransformed.value === address) { @@ -95,16 +80,13 @@ export const estimateStartBlockNumber = ( ): number => { const auxMoment = moment() const currentUnix = auxMoment.valueOf() - hours && auxMoment.subtract(hours, "hours") - days && auxMoment.subtract(days, "days") - weeks && auxMoment.subtract(weeks, "weeks") - months && auxMoment.subtract(months, "months") + hours && auxMoment.subtract(hours, 'hours') + days && auxMoment.subtract(days, 'days') + weeks && auxMoment.subtract(weeks, 'weeks') + months && auxMoment.subtract(months, 'months') const estimatedUnix = auxMoment.valueOf() - return Math.max( - 1, - endBlockNumber - (currentUnix - estimatedUnix) / estimatedBlockTime - ) + return Math.max(1, endBlockNumber - (currentUnix - estimatedUnix) / estimatedBlockTime) } const EXPECTED_TIME_THRESHOLD = BN_THOUSAND.div(BN_TWO)