Skip to content

Commit

Permalink
Add Block time page functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
eliasmpw committed Sep 19, 2021
1 parent 399ebff commit 9df3064
Show file tree
Hide file tree
Showing 11 changed files with 557 additions and 68 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Getting Started with Create React App
# Parachain utilities

This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).

Expand Down
3 changes: 0 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ import BlockTime from "./components/BlockTime/BlockTime"
import BlockAuthor from "./components/BlockAuthor/BlockAuthor"
import { useAppDispatch, useAppSelector } from "./store/hooks"
import { replaceText } from "./utils/UtilsFunctions"
import { setAddressList } from "./store/actions/addressActions"
import {
selectEndpoint,
setConfig,
setEndpointList,
} from "./store/actions/configActions"
import { RPCEndpoint } from "./types"
Expand All @@ -25,7 +23,6 @@ function App(): React.ReactElement {
const config = useAppSelector(state => {
return state.config
})
const addressList = useAppSelector(state => state.address.list)
const dispatch = useAppDispatch()

useEffect(() => {
Expand Down
8 changes: 2 additions & 6 deletions src/components/AddressBook/ViewFormatsModal.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { Button, Form, Input, message, Modal, Row, Space, Table } from "antd"
import React, { useEffect, useState } from "react"
import { addAddress } from "../../store/actions/addressActions"
import { useAppDispatch } from "../../store/hooks"
import { Button, message, Modal, Row, Space, Table } from "antd"
import React from "react"
import { SubstrateAddress, TransformedSubstrateAddress } from "../../types"
import * as prefixes from "../../utils/ss58-registry.json"
import { encodeAddress, decodeAddress } from "@polkadot/util-crypto/address"
import CopyToClipboard from "react-copy-to-clipboard"
import { CopyOutlined } from "@ant-design/icons"

Expand Down
4 changes: 2 additions & 2 deletions src/components/AverageBlockTime/AverageBlockTime.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BarChartOutlined, LineChartOutlined } from "@ant-design/icons"
import { BarChartOutlined } from "@ant-design/icons"
import { ApiPromise, WsProvider } from "@polkadot/api"
import {
Button,
Expand Down Expand Up @@ -200,7 +200,7 @@ function AverageBlockTime(): React.ReactElement {
disabled={!isBlockRangeValid || isLoading}
loading={isLoading}
htmlType='submit'>
Calculate
Calculate Average Block Time
</Button>
</Form.Item>
</Form>
Expand Down
12 changes: 12 additions & 0 deletions src/components/BlockAuthor/BlockAuthor.less
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
.block-author-container {
padding: 25px;

.collapse-blocks .ant-collapse-content-box {
padding: 0;
}

.address-name {
font-weight: bold;
}

.block-number {
font-weight: bold;
}
}
106 changes: 64 additions & 42 deletions src/components/BlockAuthor/BlockAuthor.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { BarChartOutlined } from "@ant-design/icons"
import { BarChartOutlined, CaretRightOutlined } from "@ant-design/icons"
import { ApiPromise, WsProvider } from "@polkadot/api"
import { BlockHash, Header } from "@polkadot/types/interfaces"
import {
Button,
Collapse,
Form,
InputNumber,
List,
message,
Row,
Select,
Expand All @@ -13,6 +14,7 @@ import {
} from "antd"
import React, { useState } from "react"
import { useAppSelector } from "../../store/hooks"
import { findAuthorName } from "../../utils/UtilsFunctions"
import "./BlockAuthor.less"

interface BlockAuthorFormValues {
Expand All @@ -34,6 +36,7 @@ interface BlockInfo {

function BlockAuthor(): React.ReactElement {
const [formBlocks] = Form.useForm()
const addresses = useAppSelector(state => state.address.list)
const config = useAppSelector(state => state.config)
const [results, setResults] = useState<Array<BlockAuthorResult>>([])
const [isBlockRangeValid, setIsBlockRangeValid] = useState(false)
Expand Down Expand Up @@ -65,6 +68,7 @@ function BlockAuthor(): React.ReactElement {
}

const handleOnCalculate = (values: BlockAuthorFormValues) => {
setResults([])
countBlockAuthors(values)
}

Expand All @@ -86,58 +90,49 @@ function BlockAuthor(): React.ReactElement {
const api = await ApiPromise.create({ provider })

// Load hashes
const groupedBlocks: Record<string, BlockInfo[]> = {}
let loadedUntil = startBlock
let allHashes: BlockHash[] = []
while (loadedUntil <= endBlock) {
let promiseCount = 0
const allowedParallel = 5
const promises = []
while (loadedUntil <= endBlock && promiseCount < allowedParallel) {
promises.push(api.rpc.chain.getBlockHash(loadedUntil))
loadedUntil += 1
let promises = []
while (
promiseCount < allowedParallel &&
loadedUntil + promiseCount <= endBlock
) {
promises.push(api.rpc.chain.getBlockHash(loadedUntil + promiseCount))
promiseCount += 1
}
const newHashes = await Promise.all(promises)
allHashes = allHashes.concat(newHashes)
}

// Load headers/authors
loadedUntil = startBlock
let allHeaders: any[] = []
while (loadedUntil <= endBlock) {
let promiseCount = 0
const allowedParallel = 5
const promises = []
while (loadedUntil <= endBlock && promiseCount < allowedParallel) {
promises.push(
api.derive.chain.getHeader(allHashes[loadedUntil - startBlock])
)
loadedUntil += 1
promiseCount += 1
promises = []
for (const hash of newHashes) {
promises.push(api.derive.chain.getHeader(hash))
}
const newHeaders = await Promise.all(promises)
allHeaders = allHeaders.concat(newHeaders)
newHeaders.forEach((header, index) => {
const author = header?.author?.toString()
if (author) {
groupedBlocks[author] = [
...(groupedBlocks[author] || []),
{
number: loadedUntil + index,
hash: newHashes[index].toString(),
},
]
}
})
loadedUntil += newHashes.length
}

const groupBlocks: Record<string, BlockInfo[]> = {}
for (const header of allHeaders) {
const author = header?.author?.toString()
if (author) {
groupBlocks[author] = [
...(groupBlocks[author] || []),
{
number: 1,
hash: "",
},
]
}
}
provider.disconnect()

const finalResults: BlockAuthorResult[] = []

for (const author in groupBlocks) {
for (const author in groupedBlocks) {
finalResults.push({
authorAddress: author,
blocks: groupBlocks[author],
authorName: findAuthorName(addresses, author),
blocks: groupedBlocks[author],
})
}

Expand All @@ -152,11 +147,38 @@ function BlockAuthor(): React.ReactElement {
}

const renderAuthor = (row: BlockAuthorResult) => {
return <div>{row.authorAddress}</div>
return (
<>
{row.authorName && <Row className='address-name'>{row.authorName}</Row>}
<Row>{row.authorAddress}</Row>
</>
)
}

const renderBlocks = (row: BlockAuthorResult) => {
return <div>{row.blocks.length} blocks</div>
return (
<Collapse
accordion={true}
expandIcon={({ isActive }) => (
<CaretRightOutlined rotate={isActive ? 90 : 0} />
)}>
<Collapse.Panel
className='collapse-blocks'
header={`${row.blocks.length} blocks`}
key={row.authorAddress}>
<List
size='small'
dataSource={row.blocks}
renderItem={item => (
<List.Item>
<span className='block-number'>{item.number}</span> -{" "}
{item.hash}
</List.Item>
)}
/>
</Collapse.Panel>
</Collapse>
)
}

const columns = [
Expand Down Expand Up @@ -234,7 +256,7 @@ function BlockAuthor(): React.ReactElement {
disabled={!isBlockRangeValid || isLoading}
loading={isLoading}
htmlType='submit'>
Calculate
Load Block Authors
</Button>
</Form.Item>
</Form>
Expand Down
4 changes: 4 additions & 0 deletions src/components/BlockTime/BlockTime.less
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.block-time-container {
padding: 25px;
.default-block-time {
font-size: 12px;
color: gray;
}
}
Loading

0 comments on commit 9df3064

Please sign in to comment.