|
@@ -1,169 +0,0 @@
|
|
|
-import React from "react";
|
|
|
-import { Form, Table, Button, Spinner} from "react-bootstrap";
|
|
|
-import axios from "axios";
|
|
|
-import Pagination from 'react-bootstrap/Pagination'
|
|
|
-import moment from 'moment'
|
|
|
-
|
|
|
-import { alternativeBackendApis } from "../../config"
|
|
|
-
|
|
|
-import { ValidatorApiResponse } from "../../types";
|
|
|
-
|
|
|
-const reportDateFormat = 'DD-MM-yyyy';
|
|
|
-
|
|
|
-interface IProps {
|
|
|
-}
|
|
|
-
|
|
|
-interface IState {
|
|
|
- address: string
|
|
|
- blockStart: number
|
|
|
- blockEnd: number
|
|
|
- page: number,
|
|
|
- search: boolean,
|
|
|
- loading: boolean,
|
|
|
- apiResponse?: ValidatorApiResponse;
|
|
|
-}
|
|
|
-
|
|
|
-class ValidatorReport extends React.Component<IProps, IState> {
|
|
|
-
|
|
|
- constructor(props: IProps) {
|
|
|
- super(props);
|
|
|
- this.state = {
|
|
|
- address: '',
|
|
|
- blockStart: 0,
|
|
|
- blockEnd: 0,
|
|
|
- page: 1,
|
|
|
- search: false,
|
|
|
- loading: false
|
|
|
- };
|
|
|
- this.accountTxFilterChanged = this.accountTxFilterChanged.bind(this);
|
|
|
- this.searchClicked = this.searchClicked.bind(this);
|
|
|
- }
|
|
|
-
|
|
|
- componentDidUpdate = (prevProps: IProps, prevState: IState) => {
|
|
|
- const { address, blockStart, blockEnd, page, search } = this.state;
|
|
|
-
|
|
|
- if(search) {
|
|
|
- console.log(`Fetching transactions`);
|
|
|
- const backend = `${alternativeBackendApis}/validator-report?addr=${address}&start_block=${blockStart}&end_block=${blockEnd}&page=${page}`;
|
|
|
-
|
|
|
- axios.get(backend).then((response) => {this.setState({...this.state, apiResponse: response.data, search: false, loading: false})});
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- accountTxFilterChanged = (address: string) => {
|
|
|
- if(this.state.address !== address) {
|
|
|
- this.setState({...this.state, address: address });
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- startBlockFilterChanged = (blockStart: number) => {
|
|
|
- if(this.state.blockStart !== blockStart) {
|
|
|
- this.setState({...this.state, blockStart: blockStart });
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- endBlockFilterChanged = (blockEnd: number) => {
|
|
|
- if(this.state.blockEnd !== blockEnd) {
|
|
|
- this.setState({...this.state, blockEnd: blockEnd });
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- totalPages = (): number => {
|
|
|
- const pageSize = this.state.apiResponse?.pageSize ?? 50
|
|
|
- const result = 1 + (this.state.apiResponse?.totalCount ?? 1) / pageSize
|
|
|
- return Math.floor(result)
|
|
|
- }
|
|
|
-
|
|
|
- changePage = (page: number) => {
|
|
|
- if(this.state.page !== page) {
|
|
|
- this.setState({...this.state, page: page, search: true, loading: true });
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- searchClicked = () => {
|
|
|
- if(!this.state.search) {
|
|
|
- this.setState({...this.state, page: 1, search: true, loading: true });
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- render() {
|
|
|
-
|
|
|
- const { address, blockStart, blockEnd, apiResponse, page, loading } = this.state;
|
|
|
-
|
|
|
- return (
|
|
|
- <div className="box" style={{textAlign: "left"}}>
|
|
|
- <h3>Validator Report</h3>
|
|
|
- <Form>
|
|
|
- <Form.Group className="mb-3">
|
|
|
- <Form.Label>Wallet address</Form.Label>
|
|
|
- <Form.Control type="address" placeholder="Wallet account" onChange={(e) => this.accountTxFilterChanged(e.target.value)} value={address}/>
|
|
|
- <Form.Text className="text-muted">
|
|
|
- 48 character string starting with 5
|
|
|
- </Form.Text>
|
|
|
- </Form.Group>
|
|
|
- <Form.Group className="mb-3">
|
|
|
- <Form.Label>Start Block</Form.Label>
|
|
|
- <Form.Control type="blockStart" placeholder="Start Block" onChange={(e) => this.startBlockFilterChanged(+e.target.value)} value={blockStart}/>
|
|
|
- </Form.Group>
|
|
|
- <Form.Group className="mb-3">
|
|
|
- <Form.Label>End Block</Form.Label>
|
|
|
- <Form.Control type="blockEnd" placeholder="End Block" onChange={(e) => this.endBlockFilterChanged(+e.target.value)} value={blockEnd}/>
|
|
|
- </Form.Group>
|
|
|
- <Button variant="outline-light" onClick={this.searchClicked}>Search</Button>
|
|
|
- </Form>
|
|
|
- <>
|
|
|
- { !apiResponse ? (loading ? <Spinner animation="border" /> : <div/>) :
|
|
|
- (apiResponse.report && apiResponse.report.length == 0) ? <h4>No records found</h4> :
|
|
|
- <>
|
|
|
- <div className="box" style={{textAlign: "left", fontSize: "1rem", fontFamily: "courier"}}>
|
|
|
- {
|
|
|
- `Validator Date: ${moment(apiResponse?.startTime).format(reportDateFormat)} - ${moment(apiResponse?.endTime).format(reportDateFormat)}\n
|
|
|
- Description: I was an active validator from era/block ${apiResponse?.startEra}/${apiResponse?.startBlock}
|
|
|
- to era/block ${apiResponse?.endEra}/${apiResponse?.endBlock}\n
|
|
|
- with stash account ${address}.
|
|
|
- (I was active in all the eras in this range and found a total of ${this.state.apiResponse?.totalBlocks} blocks)`
|
|
|
- }
|
|
|
- </div>
|
|
|
- <Pagination>
|
|
|
- {[...Array(this.totalPages()).keys()].map(i =>
|
|
|
- <Pagination.Item key={i+1} active={i+1 === page} onClick={() => this.changePage(i+1)}>
|
|
|
- {i + 1}
|
|
|
- </Pagination.Item>
|
|
|
- )
|
|
|
- }
|
|
|
- </Pagination>
|
|
|
-
|
|
|
- <Table striped bordered hover size="sm" variant="dark">
|
|
|
- <thead>
|
|
|
- <tr>
|
|
|
- <th>Era</th>
|
|
|
- <th>Total Stake</th>
|
|
|
- <th>Own Stake</th>
|
|
|
- <th>Points</th>
|
|
|
- <th>Rewards</th>
|
|
|
- <th>Commission</th>
|
|
|
- <th>Blocks Produced</th>
|
|
|
- </tr>
|
|
|
- </thead>
|
|
|
- <tbody>
|
|
|
- {apiResponse.report.map(tx => (
|
|
|
- <tr key={tx.id}>
|
|
|
- <td>{tx.id}</td>
|
|
|
- <td>{tx.stakeTotal}</td>
|
|
|
- <td>{tx.stakeOwn}</td>
|
|
|
- <td>{tx.points}</td>
|
|
|
- <td>{tx.rewards}</td>
|
|
|
- <td>{tx.commission}</td>
|
|
|
- <td>{tx.blocksCount}</td>
|
|
|
- </tr>
|
|
|
- ))}
|
|
|
- </tbody>
|
|
|
- </Table>
|
|
|
- </>
|
|
|
- } </>
|
|
|
- </div>
|
|
|
- );
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-export default ValidatorReport;
|