joyApi.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import { WsProvider, ApiPromise } from "@polkadot/api";
  2. import { types } from "@joystream/types";
  3. import { AccountId, Hash } from "@polkadot/types/interfaces";
  4. import { config } from "dotenv";
  5. import BN from "bn.js";
  6. import { Option, Vec } from "@polkadot/types";
  7. import { log } from "./debug"
  8. import { ActiveEra } from "./Types";
  9. config();
  10. export class JoyApi {
  11. endpoint: string;
  12. isReady: Promise<ApiPromise>;
  13. api!: ApiPromise;
  14. constructor(endpoint?: string) {
  15. const wsEndpoint = endpoint || process.env.REACT_APP_WS_PROVIDER || "ws://127.0.0.1:9944";
  16. this.endpoint = wsEndpoint;
  17. this.isReady = (async () => {
  18. const api = await new ApiPromise({ provider: new WsProvider(wsEndpoint), types })
  19. .isReadyOrError;
  20. return api;
  21. })();
  22. }
  23. get init(): Promise<JoyApi> {
  24. return this.isReady.then((instance) => {
  25. this.api = instance;
  26. return this;
  27. });
  28. }
  29. async totalIssuance(blockHash?: Hash) {
  30. const issuance =
  31. blockHash === undefined
  32. ? await this.api.query.balances.totalIssuance()
  33. : await this.api.query.balances.totalIssuance.at(blockHash);
  34. return issuance.toNumber();
  35. }
  36. async systemData() {
  37. const [chain, nodeName, nodeVersion] = await Promise.all([
  38. this.api.rpc.system.chain(),
  39. this.api.rpc.system.name(),
  40. this.api.rpc.system.version(),
  41. // this.api.rpc.system.peers(),
  42. ]);
  43. return {
  44. chain: chain.toString(),
  45. nodeName: nodeName.toString(),
  46. nodeVersion: nodeVersion.toString(),
  47. // peerCount: peers.length,
  48. };
  49. }
  50. async finalizedHash() {
  51. return this.api.rpc.chain.getFinalizedHead();
  52. }
  53. async finalizedBlockHeight() {
  54. const finalizedHash = await this.finalizedHash();
  55. const { number } = await this.api.rpc.chain.getHeader(`${finalizedHash}`);
  56. return number.toNumber();
  57. }
  58. async getActiveErasForBlock(address: string, blockStart: number): Promise<ActiveEra[] | undefined> {
  59. const stash = address;
  60. const startHash = (await this.api.rpc.chain.getBlockHash(blockStart));
  61. const startEra = (await this.api.query.staking.activeEra.at(startHash)).unwrap().index.toNumber();
  62. const startTimestamp = new Date((await this.api.query.timestamp.now.at(startHash)).toNumber()).toISOString();
  63. const eraPoints = await this.api.query.staking.erasRewardPoints.at(startHash, startEra)
  64. let data = undefined
  65. eraPoints.individual.forEach((points, author) => {
  66. log(`Author Points [${author}]`);
  67. log(`Individual Points [${points}]`);
  68. if (author.toString() === stash) {
  69. const pn = Number(points.toBigInt())
  70. const activeEra: ActiveEra = {
  71. id: blockStart,
  72. era: startEra,
  73. hash: startHash.toString(),
  74. block: blockStart,
  75. date: startTimestamp,
  76. points: pn
  77. }
  78. log(`Era [${activeEra.era}], Block [${activeEra.block}], Date [${activeEra.date}], Points [${activeEra.points}], Hash [${activeEra.hash}]`);
  79. data = activeEra
  80. }
  81. });
  82. return data
  83. }
  84. async findActiveValidators(hash: Hash, searchPreviousBlocks: boolean): Promise<AccountId[]> {
  85. const block = await this.api.rpc.chain.getBlock(hash);
  86. let currentBlockNr = block.block.header.number.toNumber();
  87. let activeValidators;
  88. do {
  89. let currentHash = (await this.api.rpc.chain.getBlockHash(currentBlockNr)) as Hash;
  90. let allValidators = await this.api.query.staking.snapshotValidators.at(currentHash) as Option<Vec<AccountId>>;
  91. if (!allValidators.isEmpty) {
  92. let max = (await this.api.query.staking.validatorCount.at(currentHash)).toNumber();
  93. activeValidators = Array.from(allValidators.unwrap()).slice(0, max);
  94. }
  95. if (searchPreviousBlocks) {
  96. --currentBlockNr;
  97. } else {
  98. ++currentBlockNr;
  99. }
  100. } while (activeValidators === undefined);
  101. return activeValidators;
  102. }
  103. async validatorsData() {
  104. const validators = await this.api.query.session.validators();
  105. const era = await this.api.query.staking.currentEra();
  106. const totalStake = era.isSome ?
  107. await this.api.query.staking.erasTotalStake(era.unwrap())
  108. : new BN(0);
  109. return {
  110. count: validators.length,
  111. validators: validators.toJSON(),
  112. total_stake: totalStake.toNumber(),
  113. };
  114. }
  115. }