Browse Source

backend: fetchBalances

Joystream Stats 4 years ago
parent
commit
7e48186f8b
4 changed files with 122 additions and 34 deletions
  1. 10 0
      server/db/models/account.ts
  2. 11 0
      server/db/models/balance.ts
  3. 11 0
      server/db/models/index.ts
  4. 90 34
      server/joystream/index.ts

+ 10 - 0
server/db/models/account.ts

@@ -0,0 +1,10 @@
+import db from '../db'
+import { DataTypes } from 'sequelize'
+
+const Account = db.define('account', {
+  address: DataTypes.STRING,
+  format: DataTypes.STRING,
+  about: DataTypes.TEXT,
+})
+
+export default Account

+ 11 - 0
server/db/models/balance.ts

@@ -0,0 +1,11 @@
+import db from '../db'
+import { DataTypes } from 'sequelize'
+
+const Balance = db.define('balance', {
+  available: DataTypes.INTEGER,  
+  locked: DataTypes.INTEGER,
+  frozen: DataTypes.INTEGER,
+  //fee: DataTypes.INTEGER,
+})
+
+export default Balance

+ 11 - 0
server/db/models/index.ts

@@ -1,3 +1,5 @@
+import Account from './account'
+import Balance from './balance'
 import Block from './block'
 import Channel from './channel'
 import Council from './council'
@@ -9,6 +11,13 @@ import Category from './category'
 import Thread from './thread'
 import Post from './post'
 
+Account.belongsTo(Member)
+Account.hasMany(Balance)
+
+Balance.belongsTo(Account)
+Balance.belongsTo(Era)
+
+Era.hasMany(Balance)
 Era.hasMany(Block)
 
 Block.belongsTo(Era)
@@ -31,6 +40,8 @@ Post.belongsTo(Thread)
 Post.belongsTo(Member, { as: 'author' })
 
 export {
+  Account,
+  Balance,
   Block,
   Channel,
   Council,

+ 90 - 34
server/joystream/index.ts

@@ -1,4 +1,6 @@
 import {
+  Account,
+  Balance,
   Block,
   Category,
   Channel,
@@ -28,6 +30,7 @@ import moment from 'moment'
 
 import { VoteKind } from '@joystream/types/proposals'
 import { EventRecord } from '@polkadot/types/interfaces'
+import { AccountInfo } from '@polkadot/types/interfaces/system'
 import {
   Api,
   Handles,
@@ -43,9 +46,9 @@ import {
   Status,
 } from '../types'
 
-import {AccountId, Moment, ActiveEraInfo} from "@polkadot/types/interfaces";
-import Option from "@polkadot/types/codec/Option";
-import {Vec} from "@polkadot/types";
+import { AccountId, Moment, ActiveEraInfo } from '@polkadot/types/interfaces'
+import Option from '@polkadot/types/codec/Option'
+import { Vec } from '@polkadot/types'
 
 // queuing
 let lastUpdate = 0
@@ -95,11 +98,12 @@ const addBlock = async (
 
   const author = header.author?.toString()
   const member = await fetchMemberByAccount(api, author)
-  if (member && member.id) block.setAuthor(member)
+  if (member && member.id) block.setAuthor(member.id)
+  updateBalances(api, id)
 
   const currentEra = Number(await api.query.staking.currentEra())
   const era = await save('era', { id: currentEra })
-  await era.addBlock(block)
+  era.addBlock(block.id)
 
   const handle = member ? member.handle : author
   const queued = `(queued: ${queue.length})`
@@ -109,36 +113,56 @@ const addBlock = async (
   return updateEra(api, io, status, currentEra)
 }
 
-const addBlockRange = async (api: Api, startBlock: number, endBlock: number) => {
-
-  const previousHash = await api.rpc.chain.getBlockHash(startBlock - 1);
-  let previousEra = await api.query.staking.activeEra.at(previousHash) as Option<ActiveEraInfo>;
+const addBlockRange = async (
+  api: Api,
+  startBlock: number,
+  endBlock: number
+) => {
+  const previousHash = await api.rpc.chain.getBlockHash(startBlock - 1)
+  let previousEra = (await api.query.staking.activeEra.at(
+    previousHash
+  )) as Option<ActiveEraInfo>
 
   for (let i = startBlock; i < endBlock; i++) {
-    const hash = await api.rpc.chain.getBlockHash(i);
-    const blockEra = await api.query.staking.activeEra.at(hash) as Option<ActiveEraInfo>;
-    if (blockEra.unwrap().index.toNumber() === previousEra.unwrap().index.toNumber()){
-      continue;
+    const hash = await api.rpc.chain.getBlockHash(i)
+    const blockEra = (await api.query.staking.activeEra.at(
+      hash
+    )) as Option<ActiveEraInfo>
+    if (
+      blockEra.unwrap().index.toNumber() ===
+      previousEra.unwrap().index.toNumber()
+    ) {
+      continue
     }
 
-    let totalValidators = await api.query.staking.snapshotValidators.at(hash) as Option<Vec<AccountId>>;
+    let totalValidators = (await api.query.staking.snapshotValidators.at(
+      hash
+    )) as Option<Vec<AccountId>>
     if (totalValidators.isEmpty) {
-      continue;
+      continue
     }
     console.log(`found validators: ${totalValidators.unwrap().length}`)
 
-    const totalNrValidators = totalValidators.unwrap().length;
-    const maxSlots = Number((await api.query.staking.validatorCount.at(hash)).toString());
-    const actives = Math.min(maxSlots, totalNrValidators);
-    const waiting = totalNrValidators > maxSlots ? totalNrValidators - maxSlots : 0;
-
-    const timestamp = (await api.query.timestamp.now.at(hash)) as Moment;
-    const date = new Date(timestamp.toNumber());
-    await save('era', { id: blockEra.unwrap().index.toNumber(),  waiting: waiting, actives: actives, maxSlots: maxSlots, timestamp: date})
+    const totalNrValidators = totalValidators.unwrap().length
+    const maxSlots = Number(
+      (await api.query.staking.validatorCount.at(hash)).toString()
+    )
+    const actives = Math.min(maxSlots, totalNrValidators)
+    const waiting =
+      totalNrValidators > maxSlots ? totalNrValidators - maxSlots : 0
+
+    const timestamp = (await api.query.timestamp.now.at(hash)) as Moment
+    const date = new Date(timestamp.toNumber())
+    await save('era', {
+      id: blockEra.unwrap().index.toNumber(),
+      waiting: waiting,
+      actives: actives,
+      maxSlots: maxSlots,
+      timestamp: date,
+    })
 
-    previousEra = blockEra;
+    previousEra = blockEra
   }
-
 }
 
 const getBlockHash = (api: Api, blockId: number) =>
@@ -153,8 +177,6 @@ const processEvents = async (api: Api, blockId: number) => {
   })
 }
 
-const updateAccount = async (api: Api, account: string) => {}
-
 const updateEra = async (api: Api, io: any, status: any, era: number) => {
   const now: number = moment().valueOf()
   if (lastUpdate + 60000 > now) return status
@@ -184,7 +206,7 @@ const updateEra = async (api: Api, io: any, status: any, era: number) => {
 
   if (!stashes) return
 
-  for (let validator of stashes){
+  for (let validator of stashes) {
     try {
       const prefs = await api.query.staking.erasValidatorPrefs(era, validator)
       const commission = Number(prefs.commission) / 10000000
@@ -224,6 +246,40 @@ const validatorStatus = async (api: Api, blockId: number) => {
   return { blockId, actives, waiting, maxSlots, date }
 }
 
+const getAccountAtBlock = (
+  api: Api,
+  hash: string,
+  account: string
+): Promise<AccountInfo> => api.query.system.account.at(hash, account)
+
+const fetchAccounts = async (api: Api, blockId: number) => {
+  api.query.system.account.entries().then((account: any) => {
+    const address = account[0].toHuman()[0]
+    Account.create({ address })
+  })
+}
+
+const updateBalances = async (api: Api, blockId: number) => {
+  const blockHash = await getBlockHash(api, blockId)
+  const currentEra: number = await api.query.staking.currentEra.at(blockHash)
+  const era = await Era.findOrCreate({ where: { id: currentEra } })
+
+  Account.findAll().then(async (account: any) => {
+    const { id, address } = account
+    if (!address) return
+    console.log(`updating balance of`, id, address)
+
+    const { data } = await getAccountAtBlock(api, blockHash, address)
+    const { free, reserved, miscFrozen, feeFrozen } = data
+    const balance = { available: free, reserved, frozen: miscFrozen }
+    Balance.create(balance).then((balance: any) => {
+      balance.setAccount(id)
+      balance.setEra(era.id)
+      console.log(`balance`, era.id, address, balance.available)
+    })
+  })
+}
+
 const fetchTokenomics = async () => {
   console.debug(`Updating tokenomics`)
   const { data } = await axios.get('https://status.joystream.org/status')
@@ -304,7 +360,7 @@ const fetchCategory = async (api: Api, id: number) => {
   }
   const category = await save('category', cat)
   const mod = await fetchMemberByAccount(api, moderator)
-  if (mod) category.setModerator(mod)
+  if (mod) category.setModerator(mod.id)
   if (id > 1) fetchCategory(api, id - 1)
   return category
 }
@@ -325,9 +381,9 @@ const fetchPost = async (api: Api, id: number) => {
 
   const post = await save('post', { id, text, createdAt })
   const thread = await fetchThread(api, threadId)
-  if (thread) post.setThread(thread)
+  if (thread) post.setThread(thread.id)
   const member = await fetchMemberByAccount(api, author)
-  if (member) post.setAuthor(member)
+  if (member) post.setAuthor(member.id)
   const mod = await fetchMemberByAccount(api, moderation)
   if (id > 1) fetchPost(api, id - 1)
   return post
@@ -349,9 +405,9 @@ const fetchThread = async (api: Api, id: number) => {
 
   const thread = await save('thread', { id, title, nrInCategory, createdAt })
   const category = await fetchCategory(api, categoryId)
-  if (category) thread.setCategory(category)
+  if (category) thread.setCategory(category.id)
   const author = await fetchMemberByAccount(api, account)
-  if (author) thread.setAuthor(author)
+  if (author) thread.setAuthor(author.id)
   if (moderation) {
     /* TODO
   Error: Invalid value ModerationAction(3) [Map] {
@@ -367,7 +423,7 @@ const fetchThread = async (api: Api, id: number) => {
 [1]   'rationale' => [String (Text): 'Irrelevant as posted in another thread.'] {
 */
     //const mod = await fetchMemberByAccount(api, moderation)
-    //if (mod) thread.setModeration(mod)
+    //if (mod) thread.setModeration(mod.id)
   }
   if (id > 1) fetchThread(api, id - 1)
   return thread