council.ts 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import { WsProvider, ApiPromise } from "@polkadot/api";
  2. import { types } from "@joystream/types";
  3. import { Announcing, ElectionStage, Revealing, Seats, Voting } from "@joystream/types/council";
  4. import { Null, Option, u32 } from "@polkadot/types";
  5. import { CouncilData, CouncilMemberData, Participant, VoterData } from "./interfaces";
  6. import { getParticipantAt } from "./functions";
  7. import { BalanceOf, BlockNumber, Hash } from "@polkadot/types/interfaces";
  8. import { Mint, MintId } from "@joystream/types/mint";
  9. async function main() {
  10. // Initialise the provider to connect to the local node
  11. const provider = new WsProvider('ws://127.0.0.1:9944');
  12. //If you want to play around on our staging network, go ahead and connect to this staging network instead.
  13. //const provider = new WsProvider('wss://testnet-rpc-2-singapore.joystream.org');
  14. // Create the API and wait until ready
  15. const api = await ApiPromise.create({ provider, types })
  16. // made this example with historical data, so you can check different councils/stages
  17. const blocks :number[] = [259200, 259201]
  18. // discounting this voter
  19. const joystreamVoter = "5CJzTaCp5fuqG7NdJQ6oUCwdmFHKichew8w4RZ3zFHM8qSe6"
  20. const councils: CouncilData[] = []
  21. for (let i=0; i<blocks.length; i++) {
  22. const councilMembers: CouncilMemberData[] = []
  23. const blockHash = await api.rpc.chain.getBlockHash(blocks[i]) as Hash
  24. const electionStatus = await api.query.councilElection.stage.at(blockHash) as Option<ElectionStage>
  25. const electionRound = await api.query.councilElection.round.at(blockHash) as u32
  26. console.log(`
  27. at block: ${blocks[i]},
  28. the election stage was: ${electionStatus.value.toString()},
  29. of election round: ${electionRound.toNumber()},
  30. `)
  31. if (electionStatus.value instanceof ElectionStage) {
  32. const electionStage = electionStatus.unwrap()
  33. if (electionStage.value instanceof Announcing) {
  34. console.log("In 'Announcing' stage - ends at block", electionStage.value.toNumber())
  35. } else if (electionStage.value instanceof Voting) {
  36. console.log("In 'Voting' stage - ends at block", electionStage.value.toNumber())
  37. } else if (electionStage.value instanceof Revealing) {
  38. console.log("In 'Revealing' stage - ends at block", electionStage.value.toNumber())
  39. } else {
  40. }
  41. }
  42. const activeCouncil = await api.query.council.activeCouncil.at(blockHash) as Seats
  43. if (!activeCouncil.isEmpty) {
  44. const elected: Participant[] = []
  45. for (let member of activeCouncil) {
  46. let otherStake = 0
  47. let jsgStake = 0
  48. const councilMemberId = await getParticipantAt(api, member.member, blockHash)
  49. const voters: VoterData[] = []
  50. elected.push(councilMemberId)
  51. for (let backer of member.backers) {
  52. const voterId = await getParticipantAt(api, backer.member, blockHash)
  53. const voter: VoterData = {
  54. voterId,
  55. voterStake: backer.stake.toNumber(),
  56. stakeRatioExJSGvotes: 0,
  57. kpiRewardRatio: 0,
  58. }
  59. otherStake += backer.stake.toNumber()
  60. if (backer.member.toString() === joystreamVoter) {
  61. jsgStake += backer.stake.toNumber()
  62. }
  63. voters.push(voter)
  64. }
  65. const ownStake = member.stake.toNumber()
  66. const totalStakeExJSGvotes = member.stake.toNumber() + otherStake - jsgStake
  67. const totalStake = member.stake.toNumber() + otherStake
  68. const councilMember: CouncilMemberData = {
  69. councilMemberId,
  70. totalStake,
  71. totalStakeExJSGvotes,
  72. ownStake,
  73. otherStake,
  74. otherStakeExJSGvotes: otherStake - jsgStake,
  75. stakeRatioExJSGvotes: ownStake/totalStakeExJSGvotes,
  76. voters,
  77. }
  78. councilMembers.push(councilMember)
  79. }
  80. let totalStakes = 0
  81. let totalStakesExJSGvotes = 0
  82. let ownStakes = 0
  83. let otherStakes = 0
  84. let otherStakesExJSGvotes = 0
  85. for (let councilMember of councilMembers) {
  86. totalStakes += councilMember.totalStake
  87. totalStakesExJSGvotes += councilMember.totalStakeExJSGvotes
  88. ownStakes += councilMember.ownStake
  89. otherStakes += councilMember.otherStake
  90. otherStakesExJSGvotes += councilMember.otherStakeExJSGvotes
  91. }
  92. for (let councilMember of councilMembers) {
  93. councilMember.kpiRewardRatio = councilMember.ownStake/totalStakesExJSGvotes
  94. for (let voter of councilMember.voters) {
  95. if (voter.voterId.accountId != joystreamVoter) {
  96. voter.stakeRatioExJSGvotes = voter.voterStake/councilMember.totalStakeExJSGvotes
  97. voter.kpiRewardRatio = voter.voterStake/totalStakesExJSGvotes
  98. }
  99. }
  100. }
  101. const termEnd = (await api.query.council.termEndsAt.at(blockHash) as BlockNumber).toNumber()
  102. const announcing = (await api.query.councilElection.announcingPeriod.at(blockHash) as BlockNumber).toNumber()
  103. const voting = (await api.query.councilElection.votingPeriod.at(blockHash) as BlockNumber).toNumber()
  104. const revealing = (await api.query.councilElection.votingPeriod.at(blockHash) as BlockNumber).toNumber()
  105. const term = (await api.query.councilElection.newTermDuration.at(blockHash) as BlockNumber).toNumber()
  106. // this will not always be correct...
  107. const electedAtBlock = termEnd-term
  108. const newCouncilStartsAt = termEnd+announcing+voting+revealing
  109. const electedHash = await api.rpc.chain.getBlockHash(electedAtBlock) as Hash
  110. const getRewardInterval = await api.query.council.payoutInterval.at(electedHash) as Option<BlockNumber>
  111. const councilMint = await api.query.council.councilMint.at(electedHash) as MintId
  112. const mintAtStart = await api.query.minting.mints.at(electedHash,councilMint) as Mint
  113. const mintCapacityAtStart = mintAtStart.capacity.toNumber()
  114. let rewardInterval = 3600
  115. if (!(getRewardInterval.value instanceof Null)) {
  116. rewardInterval = getRewardInterval.unwrap().toNumber()
  117. }
  118. const rewardamountPerPayout = (await api.query.council.amountPerPayout.at(electedHash) as BalanceOf).toNumber()
  119. const expectedIndividualRewards = rewardamountPerPayout*term/rewardInterval
  120. const council: CouncilData = {
  121. electionCycle: electionRound.toNumber(),
  122. electedAtBlock,
  123. mintCapacityAtStart,
  124. rewardamountPerPayout,
  125. rewardInterval,
  126. termEnd: termEnd,
  127. expectedIndividualRewards,
  128. newCouncilStartsAt,
  129. totalStakes,
  130. totalStakesExJSGvotes,
  131. ownStakes,
  132. otherStakes,
  133. otherStakesExJSGvotes,
  134. elected,
  135. electionData: councilMembers,
  136. }
  137. const bestHeight = (await api.derive.chain.bestNumber()).toNumber()
  138. if (bestHeight>newCouncilStartsAt) {
  139. const endHash = await api.rpc.chain.getBlockHash(newCouncilStartsAt) as Hash
  140. const mintAtEnd = await api.query.minting.mints.at(endHash,councilMint) as Mint
  141. council.mintCapacityAtEnd = mintAtEnd.capacity.toNumber()
  142. council.councilSpending = mintAtEnd.total_minted.toNumber() - mintAtStart.total_minted.toNumber()
  143. }
  144. councils.push(council)
  145. }
  146. }
  147. console.log("councils",JSON.stringify(councils, null, 4))
  148. api.disconnect()
  149. }
  150. main()