|
@@ -1,24 +1,77 @@
|
|
|
-const { Block } = require('../db/models')
|
|
|
+import {
|
|
|
+ Block,
|
|
|
+ Channel,
|
|
|
+ Council,
|
|
|
+ Proposal,
|
|
|
+ Category,
|
|
|
+ Post,
|
|
|
+ Thread,
|
|
|
+ Member,
|
|
|
+} from '../db/models'
|
|
|
+const models: { [key: string]: any } = {
|
|
|
+ channel: Channel,
|
|
|
+ proposal: Proposal,
|
|
|
+ category: Category,
|
|
|
+ thread: Thread,
|
|
|
+ post: Post,
|
|
|
+ block: Block,
|
|
|
+ council: Council,
|
|
|
+ member: Member,
|
|
|
+}
|
|
|
|
|
|
-const get = require('./lib/getters')
|
|
|
-const axios = require('axios')
|
|
|
-const moment = require('moment')
|
|
|
+import * as get from './lib/getters'
|
|
|
+import axios from 'axios'
|
|
|
+import moment from 'moment'
|
|
|
|
|
|
import { VoteKind } from '@joystream/types/proposals'
|
|
|
import {
|
|
|
Api,
|
|
|
Handles,
|
|
|
IState,
|
|
|
- Member,
|
|
|
- Category,
|
|
|
- Channel,
|
|
|
- Post,
|
|
|
+ MemberType,
|
|
|
+ CategoryType,
|
|
|
+ ChannelType,
|
|
|
+ PostType,
|
|
|
Seat,
|
|
|
- Thread,
|
|
|
+ ThreadType,
|
|
|
+ CouncilType,
|
|
|
ProposalDetail,
|
|
|
Status,
|
|
|
} from '../types'
|
|
|
|
|
|
+// queuing
|
|
|
+let lastUpdate = 0
|
|
|
+const queue: any[] = []
|
|
|
+let inProgress = false
|
|
|
+const enqueue = (fn: any) => {
|
|
|
+ queue.push(fn)
|
|
|
+ processNext()
|
|
|
+}
|
|
|
+const processNext = async () => {
|
|
|
+ if (inProgress) return
|
|
|
+ inProgress = true
|
|
|
+ const task = queue.pop()
|
|
|
+ if (task) await task()
|
|
|
+
|
|
|
+ inProgress = false
|
|
|
+ //processNext()
|
|
|
+ //return queue.length
|
|
|
+}
|
|
|
+
|
|
|
+const save = async (model: any, data: any) => {
|
|
|
+ const Model = models[model]
|
|
|
+ try {
|
|
|
+ const exists = await Model.findByPk(data.id)
|
|
|
+ if (exists) return exists.update(data)
|
|
|
+ } catch (e) {}
|
|
|
+ //console.debug(`saving ${data.id}`, `queued tasks: ${queue.length}`)
|
|
|
+ try {
|
|
|
+ return Model.create(data)
|
|
|
+ } catch (e) {
|
|
|
+ console.warn(`Failed to save ${Model}`, e.message)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
const addBlock = async (
|
|
|
api: Api,
|
|
|
io: any,
|
|
@@ -26,69 +79,58 @@ const addBlock = async (
|
|
|
status: Status
|
|
|
): Promise<Status> => {
|
|
|
const id = +header.number
|
|
|
- const exists = await Block.findByPk(id)
|
|
|
- if (exists) return status
|
|
|
-
|
|
|
- const timestamp = (await api.query.timestamp.now()).toNumber()
|
|
|
-
|
|
|
const last = await Block.findByPk(id - 1)
|
|
|
-
|
|
|
- const blocktime = last ? timestamp - last.timestamp : 6000
|
|
|
const author = header.author?.toString()
|
|
|
-
|
|
|
- const block = await Block.create({ id, timestamp, blocktime, author })
|
|
|
- console.log('[Joystream] block', block.id, block.blocktime, block.author)
|
|
|
+ const member = await fetchMemberByAccount(api, author)
|
|
|
+ const timestamp = moment.utc(await api.query.timestamp.now()).valueOf()
|
|
|
+ const blocktime = last ? timestamp - last.timestamp : 6000
|
|
|
+ const block = await save('block', { id, timestamp, blocktime })
|
|
|
+ if (member && member.id) block.setAuthor(member)
|
|
|
io.emit('block', block)
|
|
|
- updateAll(api, io, status)
|
|
|
- return status
|
|
|
+
|
|
|
+ const handle = member ? member.handle : author
|
|
|
+ const queued = `(queued: ${queue.length})`
|
|
|
+ console.log(`[Joystream] block ${block.id} ${handle} ${queued}`)
|
|
|
+ return updateStatus(api, io, status)
|
|
|
}
|
|
|
|
|
|
-const processEvents = (api: Api, blockHash) => {
|
|
|
+const processEvents = (api: Api, blockHash: string) => {
|
|
|
const blockEvents = api.query.system.events.at(blockHash)
|
|
|
// TODO as Vec<EventRecord>
|
|
|
- let transfers = blockEvents.filter((event) => {
|
|
|
+ let transfers = blockEvents.filter((event: any) => {
|
|
|
return event.section == 'balances' && event.method == 'Transfer'
|
|
|
})
|
|
|
- let validatorRewards = blockEvents.filter((event) => {
|
|
|
+ let validatorRewards = blockEvents.filter((event: any) => {
|
|
|
return event.section == 'staking' && event.method == 'Reward'
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-// from frontend
|
|
|
-const updateAll = async (api: Api, io: any, status: any) => {
|
|
|
- const proposalCount = await get.proposalCount(api)
|
|
|
- if (proposalCount > status.proposalCount) {
|
|
|
- fetchProposal(api, proposalCount)
|
|
|
- status.proposalCount = proposalCount
|
|
|
- }
|
|
|
-
|
|
|
- const currentChannel = await get.currentChannelId(api)
|
|
|
- if (currentChannel > status.lastChannel)
|
|
|
- status.lastChannel = await fetchChannels(api, currentChannel)
|
|
|
-
|
|
|
- const currentCategory = await get.currentCategoryId(api)
|
|
|
- if (currentCategory > status.lastCategory)
|
|
|
- status.lastCategory = await fetchCategories(api, currentCategory)
|
|
|
-
|
|
|
- const currentPost = await get.currentPostId(api)
|
|
|
- if (currentPost > status.lastPost)
|
|
|
- status.lastPost = await fetchPosts(api, currentPost)
|
|
|
-
|
|
|
- const currentThread = await get.currentThreadId(api)
|
|
|
- if (currentThread > status.lastThread)
|
|
|
- status.lastThread = await fetchThreads(api, currentThread)
|
|
|
-
|
|
|
- const postCount = await api.query.proposalsDiscussion.postCount()
|
|
|
- // TODO save proposalComments: Number(postCount)
|
|
|
-
|
|
|
- const currentEra = Number(await api.query.staking.currentEra())
|
|
|
- if (currentEra > status.era) {
|
|
|
- status.era = currentEra
|
|
|
+const updateStatus = async (api: Api, io: any, status: any) => {
|
|
|
+ const era = Number(await api.query.staking.currentEra())
|
|
|
+ if (era > status.era) {
|
|
|
fetchStakes(api, status.era, status.validators)
|
|
|
fetchLastReward(api, status.era - 1)
|
|
|
- } else if (status.lastReward === 0) fetchLastReward(api, currentEra)
|
|
|
+ } else if (status.lastReward === 0) fetchLastReward(api, era)
|
|
|
+ fetchEraRewardPoints(api, Number(era))
|
|
|
|
|
|
- fetchEraRewardPoints(api, Number(status.era))
|
|
|
+ //const postCount = await api.query.proposalsDiscussion.postCount()
|
|
|
+ // TODO save proposalComments: Number(postCount)
|
|
|
+
|
|
|
+ const now: number = moment().valueOf()
|
|
|
+ if (lastUpdate + 60000 > now) return status
|
|
|
+ //console.log(`updating status`, lastUpdate)
|
|
|
+ lastUpdate = now
|
|
|
+ processNext()
|
|
|
+ return {
|
|
|
+ members: await fetchMembers(api),
|
|
|
+ categories: await fetchCategories(api),
|
|
|
+ threads: await fetchThreads(api),
|
|
|
+ proposals: await fetchProposals(api),
|
|
|
+ channels: await fetchChannels(api),
|
|
|
+ posts: await fetchPosts(api),
|
|
|
+ queued: queue.length,
|
|
|
+ era,
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
const fetchLastReward = async (api: Api, era: number) => {
|
|
@@ -106,192 +148,226 @@ const fetchTokenomics = async () => {
|
|
|
// TODO save 'tokenomics', data
|
|
|
}
|
|
|
|
|
|
-const fetchChannels = async (api: Api, lastId: number) => {
|
|
|
- const channels = [] // TOOD await Channel.findAll()
|
|
|
- for (let id = lastId; id > 0; id--) {
|
|
|
- if (channels.find((c) => c.id === id)) continue
|
|
|
- console.debug(`Fetching channel ${id}`)
|
|
|
- const data = await api.query.contentWorkingGroup.channelById(id)
|
|
|
-
|
|
|
- const handle = String(data.handle)
|
|
|
- const title = String(data.title)
|
|
|
- const description = String(data.description)
|
|
|
- const avatar = String(data.avatar)
|
|
|
- const banner = String(data.banner)
|
|
|
- const content = String(data.content)
|
|
|
- const ownerId = Number(data.owner)
|
|
|
- const accountId = String(data.role_account)
|
|
|
- const publicationStatus =
|
|
|
- data.publication_status === 'Public' ? true : false
|
|
|
- const curation = String(data.curation_status)
|
|
|
- const createdAt = data.created
|
|
|
- const principal = Number(data.principal_id)
|
|
|
-
|
|
|
- const channel = {
|
|
|
- id,
|
|
|
- handle,
|
|
|
- title,
|
|
|
- description,
|
|
|
- avatar,
|
|
|
- banner,
|
|
|
- content,
|
|
|
- ownerId,
|
|
|
- accountId,
|
|
|
- publicationStatus,
|
|
|
- curation,
|
|
|
- createdAt,
|
|
|
- principal,
|
|
|
- }
|
|
|
- // TODO Channel.create(channel)
|
|
|
- }
|
|
|
+const fetchChannels = async (api: Api) => {
|
|
|
+ const lastId = await get.currentChannelId(api)
|
|
|
+ for (let id = lastId; id > 0; id--) enqueue(() => fetchChannel(api, id))
|
|
|
return lastId
|
|
|
}
|
|
|
+const fetchChannel = async (api: Api, id: number) => {
|
|
|
+ const exists = await Channel.findByPk(id)
|
|
|
+ if (exists) return exists
|
|
|
|
|
|
-const fetchCategories = async (api: Api, lastId: number) => {
|
|
|
- const categories = [] // TODO await Category.findAll()
|
|
|
- for (let id = lastId; id > 0; id--) {
|
|
|
- if (categories.find((c) => c.id === id)) continue
|
|
|
- console.debug(`fetching category ${id}`)
|
|
|
- const data = await api.query.forum.categoryById(id)
|
|
|
-
|
|
|
- const threadId = Number(data.thread_id)
|
|
|
- const title = String(data.title)
|
|
|
- const description = String(data.description)
|
|
|
- const createdAt = Number(data.created_at.block)
|
|
|
- const deleted = data.deleted
|
|
|
- const archived = data.archived
|
|
|
- const subcategories = Number(data.num_direct_subcategories)
|
|
|
- const moderatedThreads = Number(data.num_direct_moderated_threads)
|
|
|
- const unmoderatedThreads = Number(data.num_direct_unmoderated_threads)
|
|
|
- const position = Number(data.position_in_parent_category)
|
|
|
- const moderatorId = String(data.moderator_id)
|
|
|
-
|
|
|
- const category = {
|
|
|
- id,
|
|
|
- threadId,
|
|
|
- title,
|
|
|
- description,
|
|
|
- createdAt,
|
|
|
- deleted,
|
|
|
- archived,
|
|
|
- subcategories,
|
|
|
- moderatedThreads,
|
|
|
- unmoderatedThreads,
|
|
|
- position,
|
|
|
- moderatorId,
|
|
|
- }
|
|
|
- //TODO Category.create(
|
|
|
+ console.debug(`Fetching channel ${id}`)
|
|
|
+ const data = await api.query.contentWorkingGroup.channelById(id)
|
|
|
+
|
|
|
+ const handle = String(data.handle)
|
|
|
+ const title = String(data.title)
|
|
|
+ const description = String(data.description)
|
|
|
+ const avatar = String(data.avatar)
|
|
|
+ const banner = String(data.banner)
|
|
|
+ const content = String(data.content)
|
|
|
+ const ownerId = Number(data.owner)
|
|
|
+ const accountId = String(data.role_account)
|
|
|
+ const publicationStatus = data.publication_status === 'Public' ? true : false
|
|
|
+ const curation = String(data.curation_status)
|
|
|
+ const createdAt = +data.created
|
|
|
+ const principal = Number(data.principal_id)
|
|
|
+
|
|
|
+ const channel = {
|
|
|
+ id,
|
|
|
+ handle,
|
|
|
+ title,
|
|
|
+ description,
|
|
|
+ avatar,
|
|
|
+ banner,
|
|
|
+ content,
|
|
|
+ publicationStatus,
|
|
|
+ curation,
|
|
|
+ createdAt,
|
|
|
+ principal,
|
|
|
}
|
|
|
+ const chan = await save('channel', channel)
|
|
|
+ const owner = await fetchMember(api, ownerId)
|
|
|
+ chan.setOwner(owner)
|
|
|
+}
|
|
|
+
|
|
|
+const fetchCategories = async (api: Api) => {
|
|
|
+ const lastId = await get.currentCategoryId(api)
|
|
|
+ for (let id = lastId; id > 0; id--) enqueue(() => fetchCategory(api, id))
|
|
|
return lastId
|
|
|
}
|
|
|
+const fetchCategory = async (api: Api, id: number) => {
|
|
|
+ const exists = await Category.findByPk(id)
|
|
|
+ if (exists) return exists
|
|
|
|
|
|
-const fetchPosts = async (api: Api, lastId: number) => {
|
|
|
- const posts = [] // TODO Post.findAll()
|
|
|
- for (let id = lastId; id > 0; id--) {
|
|
|
- if (posts.find((p) => p.id === id)) continue
|
|
|
- console.debug(`fetching post ${id}`)
|
|
|
- const data = await api.query.forum.postById(id)
|
|
|
+ console.debug(`fetching category ${id}`)
|
|
|
+ const data = await api.query.forum.categoryById(id)
|
|
|
+
|
|
|
+ const threadId = +data.thread_id
|
|
|
+ const title = String(data.title)
|
|
|
+ const description = String(data.description)
|
|
|
+ const createdAt = +data.created_at.block
|
|
|
+ const deleted = data.deleted
|
|
|
+ const archived = data.archived
|
|
|
+ const subcategories = Number(data.num_direct_subcategories)
|
|
|
+ const moderatedThreads = Number(data.num_direct_moderated_threads)
|
|
|
+ const unmoderatedThreads = Number(data.num_direct_unmoderated_threads)
|
|
|
+ const position = +data.position_in_parent_category // TODO sometimes NaN
|
|
|
+ const moderator: string = String(data.moderator_id) // account
|
|
|
+
|
|
|
+ const cat = {
|
|
|
+ id,
|
|
|
+ title,
|
|
|
+ description,
|
|
|
+ createdAt,
|
|
|
+ deleted,
|
|
|
+ archived,
|
|
|
+ subcategories,
|
|
|
+ moderatedThreads,
|
|
|
+ unmoderatedThreads,
|
|
|
+ //position,
|
|
|
+ }
|
|
|
+ const category = await save('category', cat)
|
|
|
+ const mod = await fetchMemberByAccount(api, moderator)
|
|
|
+ if (mod) category.setModerator(mod)
|
|
|
+ return category
|
|
|
+}
|
|
|
|
|
|
- const threadId = Number(data.thread_id)
|
|
|
- const text = data.current_text
|
|
|
- //const moderation = data.moderation;
|
|
|
- //const history = data.text_change_history;
|
|
|
- //const createdAt = moment(data.created_at);
|
|
|
- const createdAt = data.created_at
|
|
|
- const authorId = String(data.author_id)
|
|
|
+const fetchPosts = async (api: Api) => {
|
|
|
+ const lastId = await get.currentPostId(api)
|
|
|
+ for (let id = lastId; id > 0; id--) enqueue(() => fetchPost(api, id))
|
|
|
+ return lastId
|
|
|
+}
|
|
|
+const fetchPost = async (api: Api, id: number) => {
|
|
|
+ const exists = await Post.findByPk(id)
|
|
|
+ if (exists) return exists
|
|
|
|
|
|
- // TODO Post.create({ id, threadId, text, authorId, createdAt })
|
|
|
- }
|
|
|
+ console.debug(`fetching post ${id}`)
|
|
|
+ const data = await api.query.forum.postById(id)
|
|
|
+
|
|
|
+ const threadId = Number(data.thread_id)
|
|
|
+ const text = data.current_text
|
|
|
+ const moderation = data.moderation
|
|
|
+ //const history = data.text_change_history;
|
|
|
+ const createdAt = data.created_at.block
|
|
|
+ const author: string = String(data.author_id)
|
|
|
+
|
|
|
+ const post = await save('post', { id, text, createdAt })
|
|
|
+ const thread = await fetchThread(api, threadId)
|
|
|
+ if (thread) post.setThread(thread)
|
|
|
+ const member = await fetchMemberByAccount(api, author)
|
|
|
+ if (member) post.setAuthor(member)
|
|
|
+ const mod = await fetchMemberByAccount(api, moderation)
|
|
|
+ return post
|
|
|
+}
|
|
|
+
|
|
|
+const fetchThreads = async (api: Api) => {
|
|
|
+ const lastId = await get.currentThreadId(api)
|
|
|
+ for (let id = lastId; id > 0; id--) enqueue(() => fetchThread(api, id))
|
|
|
return lastId
|
|
|
}
|
|
|
+const fetchThread = async (api: Api, id: number) => {
|
|
|
+ const exists = await Thread.findByPk(id)
|
|
|
+ if (exists) return exists
|
|
|
|
|
|
-const fetchThreads = async (api: Api, lastId: number) => {
|
|
|
- const threads = [] //TODO Thread.findAll()
|
|
|
- for (let id = lastId; id > 0; id--) {
|
|
|
- if (threads.find((t) => t.id === id)) continue
|
|
|
- console.debug(`fetching thread ${id}`)
|
|
|
- const data = await api.query.forum.threadById(id)
|
|
|
-
|
|
|
- const title = String(data.title)
|
|
|
- const categoryId = Number(data.category_id)
|
|
|
- const nrInCategory = Number(data.nr_in_category)
|
|
|
- const moderation = data.moderation
|
|
|
- const createdAt = String(data.created_at.block)
|
|
|
- const authorId = String(data.author_id)
|
|
|
-
|
|
|
- const thread = {
|
|
|
- id,
|
|
|
- title,
|
|
|
- categoryId,
|
|
|
- nrInCategory,
|
|
|
- moderation,
|
|
|
- createdAt,
|
|
|
- authorId,
|
|
|
- }
|
|
|
- // TODO Thread.create(
|
|
|
+ console.debug(`fetching thread ${id}`)
|
|
|
+ const data = await api.query.forum.threadById(id)
|
|
|
+
|
|
|
+ const title = String(data.title)
|
|
|
+ const categoryId = Number(data.category_id)
|
|
|
+ const nrInCategory = Number(data.nr_in_category)
|
|
|
+ const moderation = data.moderation
|
|
|
+ const createdAt = +data.created_at.block
|
|
|
+ const account = String(data.author_id)
|
|
|
+
|
|
|
+ const thread = await save('thread', { id, title, nrInCategory, createdAt })
|
|
|
+ const category = await fetchCategory(api, categoryId)
|
|
|
+ if (category) thread.setCategory(category)
|
|
|
+ const author = await fetchMemberByAccount(api, account)
|
|
|
+ if (author) thread.setAuthor(author)
|
|
|
+ if (moderation) {
|
|
|
+ /* TODO
|
|
|
+ Error: Invalid value ModerationAction(3) [Map] {
|
|
|
+[1] 'moderated_at' => BlockAndTime(2) [Map] {
|
|
|
+[1] 'block' => <BN: 4f4ff>,
|
|
|
+[1] 'time' => <BN: 17526e65a40>,
|
|
|
+[1] registry: TypeRegistry {},
|
|
|
+[1] block: [Getter],
|
|
|
+[1] time: [Getter],
|
|
|
+[1] typeDefs: { block: [Function: U32], time: [Function: U64] }
|
|
|
+[1] },
|
|
|
+[1] 'moderator_id'
|
|
|
+[1] 'rationale' => [String (Text): 'Irrelevant as posted in another thread.'] {
|
|
|
+*/
|
|
|
+ //const mod = await fetchMemberByAccount(api, moderation)
|
|
|
+ //if (mod) thread.setModeration(mod)
|
|
|
}
|
|
|
- return lastId
|
|
|
+ return thread
|
|
|
}
|
|
|
|
|
|
-const fetchCouncils = async (api: Api, status: any) => {
|
|
|
- let councils = [] // await Council.findAll()
|
|
|
+const fetchCouncils = async (api: Api, lastBlock: number) => {
|
|
|
+ const round = await api.query.councilElection.round()
|
|
|
+ let councils: CouncilType[] = await Council.findAll()
|
|
|
const cycle = 201600
|
|
|
|
|
|
- for (let round = 0; round < status.round; round++) {
|
|
|
+ for (let round = 0; round < round; round++) {
|
|
|
const block = 57601 + round * cycle
|
|
|
- if (councils[round] || block > status.block) continue
|
|
|
-
|
|
|
- console.debug(`Fetching council at block ${block}`)
|
|
|
- const blockHash = await api.rpc.chain.getBlockHash(block)
|
|
|
- if (!blockHash) continue
|
|
|
-
|
|
|
- // TODO Council.create(await api.query.council.activeCouncil.at(blockHash))
|
|
|
+ if (councils.find((c) => c.round === round) || block > lastBlock) continue
|
|
|
+ //enqueue(() => fetchCouncil(api, block))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-const fetchProposals = async (api: Api) => {
|
|
|
- const proposalCount = await get.proposalCount(api)
|
|
|
- for (let i = proposalCount; i > 0; i--) fetchProposal(api, i)
|
|
|
+const fetchCouncil = async (api: Api, block: number) => {
|
|
|
+ console.debug(`Fetching council at block ${block}`)
|
|
|
+ const blockHash = await api.rpc.chain.getBlockHash(block)
|
|
|
+ if (!blockHash)
|
|
|
+ return console.error(`Error: empty blockHash fetchCouncil ${block}`)
|
|
|
+ const council = await api.query.council.activeCouncil.at(blockHash)
|
|
|
+ return save('council', council)
|
|
|
}
|
|
|
|
|
|
+const fetchProposals = async (api: Api) => {
|
|
|
+ const lastId = await get.proposalCount(api)
|
|
|
+ for (let i = lastId; i > 0; i--) enqueue(() => fetchProposal(api, i))
|
|
|
+}
|
|
|
const fetchProposal = async (api: Api, id: number) => {
|
|
|
- const exists = null // TODO await Proposa.findByPk(id)
|
|
|
+ const exists = await Proposal.findByPk(id)
|
|
|
+ if (exists) return exists
|
|
|
|
|
|
- if (exists && exists.stage === 'Finalized')
|
|
|
- if (exists.votesByAccount && exists.votesByAccount.length) return
|
|
|
- else return fetchVotesPerProposal(api, exists)
|
|
|
+ //if (exists && exists.stage === 'Finalized')
|
|
|
+ //if (exists.votesByAccount && exists.votesByAccount.length) return
|
|
|
+ //else return //TODO fetchVotesPerProposal(api, exists)
|
|
|
|
|
|
console.debug(`Fetching proposal ${id}`)
|
|
|
const proposal = await get.proposalDetail(api, id)
|
|
|
- //TODO Proposal.create(proposal)
|
|
|
- fetchVotesPerProposal(api, proposal)
|
|
|
+ save('proposal', proposal)
|
|
|
+ //TODO fetchVotesPerProposal(api, proposal)
|
|
|
}
|
|
|
|
|
|
const fetchVotesPerProposal = async (api: Api, proposal: ProposalDetail) => {
|
|
|
- const { votesByAccount } = proposal
|
|
|
- const proposals = [] // TODO await Proposal.findAll()
|
|
|
- const councils = [] // TODO await Council.findAll()
|
|
|
+ if (proposal.votesByAccount && proposal.votesByAccount.length) return
|
|
|
|
|
|
- if (votesByAccount && votesByAccount.length) return
|
|
|
+ const proposals = await Proposal.findAll()
|
|
|
+ const councils = await Council.findAll()
|
|
|
|
|
|
console.debug(`Fetching proposal votes (${proposal.id})`)
|
|
|
- let members = []
|
|
|
- councils.map((seats) =>
|
|
|
+ let members: MemberType[] = []
|
|
|
+ councils.map((seats: Seat[]) =>
|
|
|
seats.forEach(async (seat: Seat) => {
|
|
|
if (members.find((member) => member.account === seat.member)) return
|
|
|
- const member = null // TODO await Member.findOne({ account: seat.member })
|
|
|
+ const member = await Member.findOne({ where: { account: seat.member } })
|
|
|
member && members.push(member)
|
|
|
})
|
|
|
)
|
|
|
|
|
|
const { id } = proposal
|
|
|
- proposal.votesByAccount = await Promise.all(
|
|
|
+ const votesByAccount = await Promise.all(
|
|
|
members.map(async (member) => {
|
|
|
const vote = await fetchVoteByProposalByVoter(api, id, member.id)
|
|
|
return { vote, handle: member.handle }
|
|
|
})
|
|
|
)
|
|
|
- // TODO save proposal.votesByAccount
|
|
|
+ Proposal.findByPk(id).then((p: any) => p.update({ votesByAccount }))
|
|
|
}
|
|
|
|
|
|
const fetchVoteByProposalByVoter = async (
|
|
@@ -338,7 +414,7 @@ const fetchValidators = async (api: Api) => {
|
|
|
const fetchStakes = async (api: Api, era: number, validators: string[]) => {
|
|
|
// TODO staking.bondedEras: Vec<(EraIndex,SessionIndex)>
|
|
|
console.debug(`fetching stakes`)
|
|
|
- const stashes = [] // TODO Stash.findAll()
|
|
|
+ const stashes: any[] = [] // TODO await Stash.findAll()
|
|
|
if (!stashes) return
|
|
|
stashes.forEach(async (validator: string) => {
|
|
|
try {
|
|
@@ -362,38 +438,36 @@ const fetchEraRewardPoints = async (api: Api, era: number) => {
|
|
|
}
|
|
|
|
|
|
// accounts
|
|
|
-const fetchMembers = async (api: Api, lastId: number) => {
|
|
|
- for (let id = lastId; id > 0; id--) {
|
|
|
- fetchMember(api, id)
|
|
|
- }
|
|
|
+const fetchMembers = async (api: Api) => {
|
|
|
+ const lastId = await api.query.members.nextMemberId()
|
|
|
+ for (let id = lastId - 1; id > 0; id--) enqueue(() => fetchMember(api, id))
|
|
|
+ return lastId
|
|
|
}
|
|
|
|
|
|
const fetchMemberByAccount = async (
|
|
|
api: Api,
|
|
|
account: string
|
|
|
-): Promise<Member> => {
|
|
|
- const exists = null // TODO await Member.findOne({account}
|
|
|
+): Promise<MemberType | undefined> => {
|
|
|
+ const exists = await Member.findOne({ where: { account } })
|
|
|
if (exists) return exists
|
|
|
|
|
|
- const id = await get.memberIdByAccount(api, account)
|
|
|
- if (!id)
|
|
|
- return { id: -1, handle: `unknown`, account, about: ``, registeredAt: 0 }
|
|
|
- // TODO return member
|
|
|
+ const id: number = Number(await get.memberIdByAccount(api, account))
|
|
|
+ return id ? fetchMember(api, id) : undefined
|
|
|
}
|
|
|
|
|
|
-const fetchMember = async (api: Api, id: number): Promise<Member> => {
|
|
|
- const exists = null // TODO await Member.findOne({id}
|
|
|
- if (exists) return exists
|
|
|
-
|
|
|
- console.debug(`Fetching member ${id}`)
|
|
|
+const fetchMember = async (api: Api, id: number): Promise<MemberType> => {
|
|
|
+ try {
|
|
|
+ const exists = await Member.findByPk(id)
|
|
|
+ if (exists) return exists
|
|
|
+ } catch (e) {
|
|
|
+ console.debug(`Fetching member ${id}`)
|
|
|
+ }
|
|
|
const membership = await get.membership(api, id)
|
|
|
-
|
|
|
const handle = String(membership.handle)
|
|
|
const account = String(membership.root_account)
|
|
|
const about = String(membership.about)
|
|
|
- const registeredAt = Number(membership.registered_at_block)
|
|
|
- const member = null // TODO await Member.create({ id, handle, account, registeredAt, about })
|
|
|
- return member
|
|
|
+ const createdAt = +membership.registered_at_block
|
|
|
+ return save('member', { id, handle, createdAt, about })
|
|
|
}
|
|
|
|
|
|
const fetchReports = () => {
|
|
@@ -428,7 +502,8 @@ const fetchGithubDir = async (url: string) => {
|
|
|
const match = o.name.match(/^(.+)\.md$/)
|
|
|
const name = match ? match[1] : o.name
|
|
|
if (o.type === 'file') {
|
|
|
- // TODO save await fetchGithubFile(o.download_url)
|
|
|
+ const file = await fetchGithubFile(o.download_url)
|
|
|
+ // TODO save file
|
|
|
} else fetchGithubDir(o.url)
|
|
|
}
|
|
|
)
|