فهرست منبع

20230223: Integrated polkadot chain api for validation

mkbeefcake 1 سال پیش
والد
کامیت
32628e6cff

+ 33 - 17
src/App.tsx

@@ -19,8 +19,15 @@ import {
   getValidatorStakes,
   getEraRewardPoints,
   getLastReward,
-  getTotalStake,
+  // getTotalStake,
 } from "./lib/validators";
+
+import {
+  getCountForValidators,
+  getTotalMinted,
+  getTotalStake
+} from './lib/validation';
+
 import { apiLocation, wsLocation, historyDepth } from "./config";
 import { initialState } from "./state";
 import axios from "axios";
@@ -252,18 +259,25 @@ class App extends React.Component<IProps, IState> {
   async getStakesForValidators(api: ApiPromise) {
     const era = Number(await api.query.staking.currentEra());
     console.log('Era: ', era);
+
+    // added by mkblockchaindev
+    let validation = {count: 0, minted: 0, stakes: 0}
+    validation.count = await getCountForValidators(api);
+    validation.minted = await getTotalMinted(api);
+    validation.stakes = await getTotalStake(api, era);
+    this.save("validation", validation);
+
     // await this.updateValidatorPoints(api, era);
     // await this.updateValidators(api);
-
     // console.log('LastReward', await getLastReward(api, era));
     // console.log('getTotalStake', await getTotalStake(api, era));
-
   }
 
   // startup from bottom up
   joyApi() {
     console.debug(`Connecting to ${wsLocation}`);
     const provider = new WsProvider(wsLocation);
+
     ApiPromise.create({ provider/*, types*/ }).then(async (api) => {
       await api.isReady;
       console.log(`Connected to ${wsLocation}`);
@@ -280,19 +294,21 @@ class App extends React.Component<IProps, IState> {
 
         // console.log(`api.rpc.chain.subscribeNewHeads: ${id}`)
 
-        // const isEven = id / 50 === Math.floor(id / 50);
-        // if (isEven || status.block?.id + 50 < id) this.updateStatus(api, id);
-
-        // if (blocks.find((b) => b.id === id)) return;
-        // const timestamp = (await api.query.timestamp.now()).toNumber();
-        // const duration = status.block
-        //   ? timestamp - status.block.timestamp
-        //   : 6000;
-        // status.block = { id, timestamp, duration };
-        // this.save("status", status);
-
-        // blocks = blocks.filter((i) => i.id !== id).concat(status.block);
-        // this.setState({ blocks });
+        const isEven = id / 50 === Math.floor(id / 50);
+        if (isEven || status.block?.id + 50 < id) { 
+          this.updateStatus(api, id);
+        }
+
+        if (blocks.find((b) => b.id === id)) return;
+        const timestamp = (await api.query.timestamp.now()).toNumber();
+        const duration = status.block
+          ? timestamp - status.block.timestamp
+          : 6000;
+        status.block = { id, timestamp, duration };
+        this.save("status", status);
+
+        blocks = blocks.filter((i) => i.id !== id).concat(status.block);
+        this.setState({ blocks });
       });
     });
   }
@@ -334,7 +350,7 @@ class App extends React.Component<IProps, IState> {
   }
 
   componentDidMount() {
-    this.loadData(); // local storage + bootstrap
+    // this.loadData(); // local storage + bootstrap
     this.joyApi(); // joystream rpc connection
     //this.initializeSocket() // jsstats socket.io
   }

+ 1 - 1
src/components/Dashboard/Status.tsx

@@ -12,7 +12,7 @@ const Status = (props: {
         Connecting ..
       </div>
     );
-  if (!fetching.length) return <div />;
+  if (!fetching?.length) return <div />;
   return (
     <div className="connecting" onClick={toggleShowStatus}>
       Fetching {fetching}

+ 15 - 7
src/components/Dashboard/Validation.tsx

@@ -1,4 +1,4 @@
-import React from "react";
+import React, { useEffect, useState } from "react";
 import SubBlock from "./ui/SubBlock";
 import Line from "./ui/Line";
 import { ElectedCouncil } from "@/queries";
@@ -6,17 +6,25 @@ import { useValidation } from "@/hooks";
 
 const Validation = (props: { council: ElectedCouncil | undefined }) => {
   const { council } = props;
-  const { validator, stake, mint, loading, error } = useValidation({ council });
+  const [validation, setValidation] = useState({count: 0, minted: 0, stakes: 0});
 
-  console.log("validation", validator, stake, mint, loading)
+  // const { validator, stake, mint, loading, error } = useValidation({ council });
+  // console.log("validation", validator, stake, mint, loading)
+
+  useEffect(() => {
+    const data = localStorage.getItem("validation");
+    if (!data) return;
+
+    setValidation(JSON.parse(data));
+  }, [])
 
   return (
     <SubBlock title="Validation">
-      { !loading && (
+      {(
         <>
-          <Line content={"Count"} value={validator} />
-          <Line content={"Minted"} value={mint} />
-          <Line content={"Staked"} value={stake} />
+          <Line content={"Count"} value={validation.count} />
+          <Line content={"Minted"} value={validation.minted} />
+          <Line content={"Staked"} value={validation.stakes} />
         </>
       )}
     </SubBlock>

+ 12 - 12
src/lib/announcements.ts

@@ -1,7 +1,7 @@
-import { Api, Council, ProposalDetail, Proposals, Summary } from "../types";
+import { Api, Council, ProposalDetail, Proposals, Summary } from "../ptypes";
 import { BlockNumber } from "@polkadot/types/interfaces";
-import { Channel } from "@joystream/types/augment";
-import { Category, Thread, Post } from "@joystream/types/forum";
+import { Channel } from "../ptypes";
+import { Category, Thread, Post } from "../ptypes";
 import { formatTime } from "./util";
 import {
   categoryById,
@@ -38,9 +38,9 @@ export const channels = async (
       api.query.contentWorkingGroup.channelById(id)
     );
 
-    const handle = await memberHandle(api, channel.owner);
+    const handle = await memberHandle(api, channel.ownerId); // channel.owner
     const member: { id: number; url: string; handle: string } = {
-      id: channel.owner.toNumber(),
+      id: channel.ownerId,
       handle,
       url: `${domain}/#/members/${handle}`,
     };
@@ -120,18 +120,18 @@ export const posts = async (
     const post: Post = await query("current_text", () =>
       api.query.forum.postById(id)
     );
-    const replyId: number = post.nr_in_thread.toNumber();
+    const replyId: number = post.nr_in_thread;
     const message: string = post.current_text;
     const excerpt: string = message.substring(0, 100);
-    const threadId: number = post.thread_id.toNumber();
+    const threadId: number = post.threadId; // post.thread_id 
     const thread: Thread = await query("title", () =>
       api.query.forum.threadById(threadId)
     );
     const threadTitle: string = thread.title;
     const category: Category = await query("title", () =>
-      categoryById(api, thread.category_id.toNumber())
+      categoryById(api, thread.categoryId) // thread.category_id
     );
-    const handle = await memberHandleByAccount(api, post.author_id.toJSON());
+    const handle = await memberHandleByAccount(api, post.authorId); //post.author_id
     const msg = `<b><a href="${domain}/#/members/${handle}">${handle}</a> posted <a href="${domain}/#/forum/threads/${threadId}?replyIdx=${replyId}">${threadTitle}</a> in <a href="${domain}/#/forum/categories/${category.id}">${category.title}</a>:</b>\n\r<i>${excerpt}</i> <a href="${domain}/#/forum/threads/${threadId}?replyIdx=${replyId}">more</a>`;
     messages.push(msg);
   }
@@ -153,10 +153,10 @@ export const threads = async (
     const thread: Thread = await query("title", () =>
       api.query.forum.threadById(id)
     );
-    const { title, author_id } = thread;
-    const handle: string = await memberHandleByAccount(api, author_id.toJSON());
+    const { title, authorId } = thread;
+    const handle: string = await memberHandleByAccount(api, authorId);
     const category: Category = await query("title", () =>
-      categoryById(api, thread.category_id.toNumber())
+      categoryById(api, thread.categoryId)
     );
     const msg = `Thread ${id}: <a href="${domain}/#/forum/threads/${id}">"${title}"</a> by <a href="${domain}/#/members/${handle}">${handle}</a> in category "<a href="${domain}/#/forum/categories/${category.id}">${category.title}</a>" `;
     messages.push(msg);

+ 17 - 11
src/lib/election.ts

@@ -1,8 +1,8 @@
 import { ApiPromise } from "@polkadot/api";
 import { AccountId } from "@polkadot/types/interfaces";
-import { MemberId } from "@joystream/types/members";
-import { Member, IApplicant, IVote } from "../types";
-import { IElectionStake, SealedVote } from "@joystream/types/council";
+import { MemberId } from "../ptypes";
+import { Member, IApplicant, IVote } from "../ptypes";
+import { IElectionStake, SealedVote } from "../ptypes";
 
 export const finalizedBlockHeight = async (api: ApiPromise) => {
   const hash = await finalizedHash(api);
@@ -13,19 +13,25 @@ export const finalizedBlockHeight = async (api: ApiPromise) => {
 export const finalizedHash = (api: ApiPromise) =>
   api.rpc.chain.getFinalizedHead();
 
-export const getCouncilSize = async (api: ApiPromise): Promise<Number> =>
-  Number((await api.query.councilElection.councilSize()).toJSON());
+export const getCouncilSize = async (api: ApiPromise): Promise<number> => {
+  const councilSize: any = await api.query.councilElection.councilSize();
+  return councilSize.toJSON() || 0;
+}
 
-export const getCouncilRound = async (api: ApiPromise): Promise<Number> =>
-  Number((await api.query.councilElection.round()).toJSON());
+export const getCouncilRound = async (api: ApiPromise): Promise<number> =>{
+  const councilRound: any = await api.query.councilElection.round();
+  return councilRound.toJSON() || 0;
+}
 
-export const getTermEndsAt = async (api: ApiPromise): Promise<Number> =>
-  Number((await api.query.council.termEndsAt()).toJSON());
+export const getTermEndsAt = async (api: ApiPromise): Promise<number> => {
+  const termsEndsAt: any = await api.query.council.termEndsAt();
+  return termsEndsAt.toJSON() || 0;
+}
 
 export const getElectionStage = async (
   api: ApiPromise
-): Promise<{ [key: string]: Number }> =>
-  (await api.query.councilElection.stage()).toJSON();
+): Promise</*{ [key: string]: Number }*/ any> =>
+  (await api.query.councilElection.stage()).toHuman();
 
 export const updateElection = async (api: ApiPromise) => {
   console.debug(`Updating election status`);

+ 9 - 10
src/lib/getters.ts

@@ -2,24 +2,23 @@ import { formatProposalMessage } from "./announcements";
 import fetch from "node-fetch";
 
 //types
-
-import { Api, ProposalArray, ProposalDetail } from "../types";
+import { Api, ProposalArray, ProposalDetail } from "../ptypes";
 import {
   ChannelId,
   PostId,
   ProposalDetailsOf,
   ThreadId,
-} from "@joystream/types/augment";
-import { Category, CategoryId } from "@joystream/types/forum";
-import { MemberId, Membership } from "@joystream/types/members";
-import { Proposal } from "@joystream/types/proposals";
+} from "../ptypes";
+import { Category, CategoryId } from "../ptypes";
+import { MemberId, Membership } from "../ptypes";
+import { Proposal } from "../ptypes";
 import { AccountId } from "@polkadot/types/interfaces";
 
 // channel
 
 export const currentChannelId = async (api: Api): Promise<number> => {
   const id: ChannelId = await api.query.contentWorkingGroup.nextChannelId();
-  return id.toNumber() - 1;
+  return id - 1;
 };
 
 // members
@@ -64,17 +63,17 @@ export const categoryById = async (api: Api, id: number): Promise<Category> => {
 
 export const currentPostId = async (api: Api): Promise<number> => {
   const postId: PostId = await api.query.forum.nextPostId();
-  return postId.toNumber() - 1;
+  return postId - 1;
 };
 
 export const currentThreadId = async (api: Api): Promise<number> => {
   const threadId: ThreadId = await api.query.forum.nextThreadId();
-  return threadId.toNumber() - 1;
+  return threadId - 1;
 };
 
 export const currentCategoryId = async (api: Api): Promise<number> => {
   const categoryId: CategoryId = await api.query.forum.nextCategoryId();
-  return categoryId.toNumber() - 1;
+  return categoryId - 1;
 };
 
 // proposals

+ 6 - 3
src/lib/groups.ts

@@ -1,6 +1,8 @@
 import moment from "moment";
-import { Openings } from "./types";
-import { Mint } from "@joystream/types/mint";
+import { ApiPromise } from "@polkadot/api";
+import { Openings } from "../ptypes";
+import { Mint, Member, WorkerId, WorkerOf, RewardRelationship, 
+  Membership, Stake, Opening, OpeningId, OpeningOf, ApplicationOf } from "../ptypes";
 
 // mapping: key = pioneer route, value: chain section
 export const groups = {
@@ -12,7 +14,7 @@ export const groups = {
   operationsGroupGamma: "operationsWorkingGroupGamma",
 };
 
-export const getMints = async (api: Api): Promise<Mint[]> => {
+export const getMints = async (api: ApiPromise): Promise<[]> => {
   console.debug(`Fetching mints`);
   const getMint = (id: number) => api.query.minting.mints(id);
   const promises = Object.values(groups).map((group) =>
@@ -37,6 +39,7 @@ export const updateWorkers = async (
     moment() < moment(lastUpdate).add(1, `hour`)
   )
     return workers;
+
   console.log(`Fetching workers of ${Object.keys(groups).length} groups`);
   let updated: { [key: string]: any[] } = {};
   const promises = Object.values(groups).map((group: string) =>

+ 1 - 1
src/lib/queries.ts

@@ -1,5 +1,5 @@
 import { apiLocation } from "../config";
-import { Tokenomics } from "../types";
+import { Tokenomics } from "../ptypes";
 //import { getAssets, getStorageProviders } from "./storage";
 import axios from "axios";
 

+ 1 - 1
src/lib/util.ts

@@ -1,4 +1,4 @@
-import { Options, Proposals, IApplicant, IVote } from "../types";
+import { Options, Proposals, IApplicant, IVote } from "../ptypes";
 import moment from "moment";
 
 export const parseArgs = (args: string[]): Options => {

+ 19 - 0
src/lib/validation.ts

@@ -0,0 +1,19 @@
+import { ApiPromise } from "@polkadot/api";
+
+// get validator count
+export const getCountForValidators = async (api: ApiPromise): Promise<number> =>{
+	const count: any = await api.query.staking.counterForValidators();
+	return count.toJSON() || 0;
+}
+  
+// get minted value
+export const getTotalMinted = async (api: ApiPromise): Promise<number> =>{
+	const minted: any = await api.query.balances.totalIssuance();
+	return minted.toJSON() || 0;
+}
+
+// get total stakes
+export const getTotalStake = async (api: ApiPromise, era: number): Promise<number> => {
+	const total: any = await api.query.staking.erasTotalStake(era);
+	return total.toJSON() || 0;
+}

+ 3 - 1
src/lib/validators.ts

@@ -1,4 +1,6 @@
 import { ApiPromise } from "@polkadot/api";
+import { AccountId, Member } from '../ptypes'
+import { Hash } from '@polkadot/types/interfaces/runtime';
 
 // total reward per era
 export const getLastReward = async (api: ApiPromise, era: number) =>
@@ -47,7 +49,7 @@ export const getValidatorStakes = async (
   return stakes;
 };
 
-export const getEraRewardPoints = async (api: Api, era: EraId | number) =>
+export const getEraRewardPoints = async (api: ApiPromise, era: number) =>
   (await api.query.staking.erasRewardPoints(era)).toJSON();
 
 export const findActiveValidators = async (

+ 34 - 9
src/types_.ts → src/ptypes.ts

@@ -1,8 +1,10 @@
-import { ProposalParameters, VotingResults } from "@joystream/types/proposals";
 import { Nominations } from "@polkadot/types/interfaces";
 import { Option } from "@polkadot/types/codec";
 import { StorageKey } from "@polkadot/types/primitive";
-import { IElectionStake } from "@joystream/types/council";
+
+// import { IElectionStake } from "@joystream/types/council";
+// import { ProposalParameters, VotingResults } from "@joystream/types/proposals";
+
 
 export interface Api {
   query: any;
@@ -38,11 +40,12 @@ export interface Consul {
 
 export interface Council {
   round: number;
-  start: number;
-  end: number;
-  startDate: string;
-  endDate: string;
-  consuls: Consul[];
+  start?: number;
+  end?: number;
+  startDate?: string;
+  endDate?: string;
+  consuls?: Consul[];
+  last: string;
 }
 
 export interface ElectionStage {
@@ -231,7 +234,7 @@ export interface Channel {
   avatar: string;
   banner: string;
   content: string;
-  ownerId: number;
+  ownerId: number;  
   accountId: string;
   publicationStatus: boolean;
   curation: string;
@@ -260,6 +263,9 @@ export interface Post {
   threadId: number;
   authorId: string;
   createdAt: { block: number; time: number };
+  // patches
+  nr_in_thread: number;
+  current_text : string;
 }
 
 export interface Thread {
@@ -310,7 +316,7 @@ export interface DollarPoolChange {
 }
 
 export interface Tokenomics {
-  dollarPool: { size: number; replenishAmount: numer };
+  dollarPool: { size: number; replenishAmount: number };
   dollarPoolChanges: DollarPoolChange[];
   price: string;
   totalIssuance: string;
@@ -437,3 +443,22 @@ export interface Kpi {
   totalPossibleRewardsUsd: 3525;
   councilMembers: CouncilMember[];
 }
+
+// ------ patches ----
+export type ChannelId = number;
+export type PostId = number;
+export type ThreadId = number;
+export type ProposalDetailsOf = any;
+export type CategoryId = number;
+export type MemberId = number;
+export type Membership = any;
+export type Proposal = any;
+export type IElectionStake = any;
+export type ProposalParameters = any;
+export type VotingResults = any;
+export type SealedVote = any;
+export type Openings = any;
+export interface Mint { group: string; mintId: number; content: number }
+export type WorkerId = u64;
+export type WorkerOf = any;
+export type RewardRelationship = any;

+ 1 - 0
src/state.ts

@@ -39,4 +39,5 @@ export const initialState = {
     eraTotals: {},
     validators: {},
   },
+  blocks: []
 };