rewards.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import { ApiPromise, WsProvider } from '@polkadot/api'
  2. import { wsLocation } from '../config.json'
  3. import { memberHandle, memberIdByAccount } from './lib/getters'
  4. // types
  5. import { Api } from '../types'
  6. import { Hash } from '@polkadot/types/interfaces'
  7. import { types } from '@joystream/types'
  8. import {
  9. RewardRelationship,
  10. RewardRelationshipId,
  11. } from '@joystream/types/recurring-rewards'
  12. import { MemberId } from '@joystream/types/members'
  13. import { Stake } from '@joystream/types/stake'
  14. import { WorkerId } from '@joystream/types/working-group'
  15. import { WorkerOf } from '@joystream/types/augment-codec/all'
  16. const PRICE = 30 / 1000000 // TODO
  17. // api calls
  18. const getBlockHash = (api: Api, blockId: number) =>
  19. api.rpc.chain.getBlockHash(blockId).then((array: any) => array.toHuman())
  20. const nextWorker = (api: Api, group: string, hash: Hash) =>
  21. api.query[group].nextWorkerId.at(hash)
  22. const getWorker = (api: Api, group: string, id: number) =>
  23. api.query[group].workerById(id)
  24. const getStake = (api: Api, id: number) => api.query.stake.stakes(id)
  25. const getReward = (api: Api, hash: Hash, id: RewardRelationshipId) =>
  26. api.query.recurringRewards.rewardRelationships.at(hash, id)
  27. const formatTokens = (amount: number) => (amount / 1000000).toFixed(1)
  28. // calculations
  29. const computeReward = async (
  30. api: Api,
  31. blocks: number,
  32. ids: RewardRelationshipId[],
  33. hash: Hash
  34. ): Promise<[number, string]> => {
  35. let recurringRewards: RewardRelationship[] = await Promise.all(
  36. ids.map((id) => getReward(api, hash, id))
  37. )
  38. let report = ``
  39. let rewardPerBlock = 0
  40. for (let recurringReward of recurringRewards) {
  41. const amount = recurringReward.amount_per_payout.toNumber()
  42. const payoutInterval = recurringReward.payout_interval.unwrapOr(null)
  43. if (amount && payoutInterval) {
  44. const amountPerBlock = amount / +payoutInterval
  45. rewardPerBlock += amountPerBlock
  46. const id: MemberId = await memberIdByAccount(api, recurringReward.account)
  47. if (!id) continue
  48. const handle = await memberHandle(api, id)
  49. const earned = amountPerBlock * blocks
  50. const dailyDollar = (14400 * amountPerBlock * PRICE).toFixed(1)
  51. const totalEarned = +recurringReward.total_reward_received
  52. const earnedDollar = (earned * PRICE).toFixed()
  53. const totalEarnedDollar = (totalEarned * PRICE).toFixed()
  54. report += workerRow(
  55. id.toNumber(),
  56. handle,
  57. amountPerBlock.toFixed(),
  58. formatTokens(earned),
  59. dailyDollar,
  60. earnedDollar,
  61. formatTokens(totalEarned),
  62. totalEarnedDollar
  63. )
  64. }
  65. }
  66. return [rewardPerBlock * blocks, report]
  67. }
  68. export const getSalaries = async (
  69. api: any,
  70. group: string,
  71. blocks: number,
  72. startHash: Hash,
  73. endHash: Hash
  74. ) => {
  75. const nextWorkerId = ((await nextWorker(
  76. api,
  77. group,
  78. endHash
  79. )) as WorkerId).toNumber()
  80. let ids: RewardRelationshipId[] = []
  81. let totalStake = 0
  82. for (let i = 0; i < nextWorkerId; ++i) {
  83. let worker = (await getWorker(api, group, i)) as WorkerOf
  84. if (worker.reward_relationship.isSome)
  85. ids.push(worker.reward_relationship.unwrap())
  86. if (worker.role_stake_profile.isSome) {
  87. let roleStakeProfile = worker.role_stake_profile.unwrap()
  88. const id = Number(roleStakeProfile.stake_id)
  89. let stake = (await getStake(api, id)) as Stake
  90. totalStake += stake.value.toNumber()
  91. }
  92. }
  93. let [sum, report] = await computeReward(api, blocks, ids, endHash)
  94. const staked = formatTokens(totalStake)
  95. const rewards = formatTokens(sum)
  96. const stakedDollar = (totalStake * PRICE).toFixed()
  97. const rewardsDollar = (sum * PRICE).toFixed()
  98. report += `- Rewards: ${rewards} M tJOY ($${rewardsDollar})\n- Stake: ${staked} M tJOY ($${stakedDollar})`
  99. return report
  100. }
  101. // output
  102. const tableHead = (group: string, start: number, end: number) =>
  103. `# Salaries ${group} from ${start} to ${end}\n| # | Member | tJOY / Block | Daily $ | M tJOY / term | $ / term | Total M tJOY | Total $ |\n|--|--|--|--|--|--|--|--|\n`
  104. const workerRow = (
  105. id: number,
  106. handle: string,
  107. perBlock: string,
  108. earned: string,
  109. dailyDollar: string,
  110. earnedDollar: string,
  111. totalEarned: string,
  112. totalDollar: string
  113. ) =>
  114. `| ${id} | ${handle} | ${perBlock} | ${earned} | ${dailyDollar} | ${earnedDollar} | ${totalEarned} | ${totalDollar} |\n`
  115. // main
  116. const main = async () => {
  117. const provider = new WsProvider(wsLocation)
  118. const api = await ApiPromise.create({ provider, types })
  119. await api.isReady
  120. const start = 1890000
  121. const end = (await api.derive.chain.bestNumberFinalized()).toNumber()
  122. const startHash = await getBlockHash(api, start)
  123. const endHash = await getBlockHash(api, end)
  124. const group = 'operationsWorkingGroup'
  125. const report = await getSalaries(api, group, end - start, startHash, endHash)
  126. console.log(tableHead(group, start, end) + report)
  127. }
  128. main()