Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Production Release #1427

Merged
merged 11 commits into from
Jul 31, 2024
Merged
2 changes: 1 addition & 1 deletion .github/workflows/deploy-fio-testnet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ jobs:
POSTGRES_DB: ${{ secrets.POSTGRES_DB }}
POSTGRES_DATA: ${{ secrets.POSTGRES_DATA }}
# hapi
HAPI_EOS_API_NETWORK_NAME: fio-testnet
Torresmorah marked this conversation as resolved.
Show resolved Hide resolved
HAPI_EOS_API_NETWORK_NAME: fio
HAPI_EOS_API_ENDPOINTS: '["https://testnet.fioprotocol.io","https://fio-testnet.eosphere.io"]'
HAPI_EOS_STATE_HISTORY_PLUGIN_ENDPOINT: ''
HAPI_EOS_MISSED_BLOCKS_ENABLED: 'false'
Expand Down
131 changes: 121 additions & 10 deletions hapi/src/services/fio.service.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
const { StatusCodes } = require('http-status-codes')

const { axiosUtil, eosUtil, sequelizeUtil, producerUtil } = require('../utils')
const { axiosUtil, hasuraUtil, eosUtil, sequelizeUtil, producerUtil } = require('../utils')
const { eosConfig } = require('../config')

const MAX_PAID_PRODUCERS = 42

const updateRewards = async (producers = []) => {
const upsertMutation = `
mutation ($producers: [producer_insert_input!]!) {
insert_producer(objects: $producers, on_conflict: {constraint: producer_owner_key, update_columns: [ vote_rewards, block_rewards, total_rewards ]}) {
affected_rows,
}
}
`

await hasuraUtil.request(upsertMutation, { producers })
}

const getProducers = async () => {
let producers = []
let totalVoteWeight
Expand Down Expand Up @@ -60,16 +74,9 @@ const getProducers = async () => {
return 0
})

const rewards = await producerUtil.getExpectedRewards(
producers,
totalVoteWeight
)
const nonPaidStandby = { vote_rewards: 0, block_rewards: 0, total_rewards: 0 }

producers = producers.map((producer, index) => {
return {
owner: producer.owner,
...(rewards[producer.owner] || nonPaidStandby),
total_votes: producer.total_votes,
total_votes_percent: producer.total_votes / totalVoteWeight,
total_votes_eos: producerUtil.getVotes(producer.total_votes),
Expand Down Expand Up @@ -187,7 +194,7 @@ const getChains = async producerUrl => {
}

Torresmorah marked this conversation as resolved.
Show resolved Hide resolved
const isNonCompliant = producer => {
return !Object.keys(producer.bpJson).length && producer.total_rewards >= 100
return !Object.keys(producer.bpJson).length && producer.total_rewards > 0
}

const getProducerHealthStatus = async producer => {
Expand Down Expand Up @@ -251,6 +258,110 @@ const getProducersFromDB = async () => {
return producers
}

const getVoteShares = async () => {
try {
const { rows } = await eosUtil.getTableRows({
code: 'fio.treasury',
scope: 'fio.treasury',
table: 'voteshares',
reverse: false,
limit: MAX_PAID_PRODUCERS,
json: true,
lower_bound: null
})

if (!Array.isArray(rows)) return []

return rows
} catch (error) {
console.warn('SYNC FIO REWARDS', error.message || error)

return []
}
}

const getFioRewards = async (producers, voteShares) => {
const activeProducers = producers.slice(0, MAX_PAID_PRODUCERS)

return voteShares.flatMap(producer => {
if (activeProducers.find(bp => bp.owner === producer.owner)) {
const expectedVoteReward = producer.abpayshare / 10 ** 9
const expectedBlockReward = producer.sbpayshare / 10 ** 9

return ({
owner: producer.owner,
vote_rewards: expectedVoteReward,
block_rewards: expectedBlockReward,
total_rewards: expectedVoteReward + expectedBlockReward
})
}

return []
})
}

const getProducersWithRewards = async (voteShares) => {
const producers = await getProducersFromDB()
const paidProducers = await getFioRewards(producers.slice(0, MAX_PAID_PRODUCERS), voteShares)
const nonPaidStandby =
producers.slice(MAX_PAID_PRODUCERS).map(producer => ({
owner: producer.owner,
vote_rewards: 0,
block_rewards: 0,
total_rewards: 0
}))

return paidProducers.concat(nonPaidStandby)
}

const getLastPaidScheduleTime = async () => {
try {
const { rows } = await eosUtil.getTableRows({
code: 'fio.treasury',
scope: 'fio.treasury',
table: 'clockstate',
reverse: false,
limit: 1,
json: true,
lower_bound: null
})

if (!rows?.at(0)?.payschedtimer) return

return new Date(rows?.at(0)?.payschedtimer * 1000)
} catch (error) {
console.warn('SYNC FIO REWARDS', error.message || error)
}
}

// Every day the `voteshare` table is populated with the rewards the BP can claim that day.
const syncRewards = async () => {
console.log('SYNCING FIO REWARDS')

const voteShares = await getVoteShares()
const producers = await getProducersWithRewards(voteShares)

if (!producers?.length) {
setTimeout(syncRewards, 2 * 60 * 1000)
} else {
await updateRewards(producers)
xavier506 marked this conversation as resolved.
Show resolved Hide resolved

const scheduleTime = await getLastPaidScheduleTime()

scheduleTime.setSeconds(scheduleTime.getSeconds() + 86400)

const nextScheduleUpdate = Math.ceil((scheduleTime.getTime() - (new Date()).getTime()))

if (nextScheduleUpdate > 0) {
console.log(`SYNCING FIO REWARDS - sync completed, next sync on ${scheduleTime.toISOString()}`)
setTimeout(syncRewards, nextScheduleUpdate)
} else {
setTimeout(syncRewards, 5 * 60 * 1000)
}
}
}

module.exports = {
getProducers
getProducers,
syncRewards
}
2 changes: 2 additions & 0 deletions hapi/src/services/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const cpuService = require('./cpu.service')
const missedBlocksService = require('./missed-blocks.service')
const producerService = require('./producer.service')
const fioService = require('./fio.service')
const nodeService = require('./node.service')
const healthCheckHistoryService = require('./health-check-history.service')
const settingService = require('./setting.service')
Expand All @@ -14,6 +15,7 @@ module.exports = {
cpuService,
missedBlocksService,
producerService,
fioService,
nodeService,
healthCheckHistoryService,
settingService,
Expand Down
4 changes: 3 additions & 1 deletion hapi/src/services/producer.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ const updateBPJSONs = async (producers = []) => {
}

const updateProducers = async (producers = []) => {
const includeRewards = eosConfig.networkName !== eosConfig.knownNetworks.fio
const additionalFields = includeRewards ? 'vote_rewards, block_rewards, total_rewards' : ''
const upsertMutation = `
mutation ($producers: [producer_insert_input!]!) {
insert_producer(objects: $producers, on_conflict: {constraint: producer_owner_key, update_columns: [ producer_key, unpaid_blocks,last_claim_time, url, location, producer_authority, is_active, total_votes, total_votes_percent, total_votes_eos, vote_rewards,block_rewards, total_rewards, endpoints, rank, bp_json_url, fio_address, addresshash, last_bpclaim]}) {
insert_producer(objects: $producers, on_conflict: {constraint: producer_owner_key, update_columns: [ producer_key, unpaid_blocks,last_claim_time, url, location, producer_authority, is_active, total_votes, total_votes_percent, total_votes_eos, endpoints, rank, bp_json_url, fio_address, addresshash, last_bpclaim, ${additionalFields}]}) {
affected_rows,
returning {
id,
Expand Down
7 changes: 0 additions & 7 deletions hapi/src/utils/producer.util.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ const getExpectedRewards = async (producers, totalVotes) => {
rewards = await getTelosRewards(producers)
break
case eosConfig.knownNetworks.fio:
Torresmorah marked this conversation as resolved.
Show resolved Hide resolved
rewards = await getFioRewards(producers)
break
default:
rewards = await getEOSIORewards(producers, totalVotes)
Expand Down Expand Up @@ -281,12 +280,6 @@ const getEOSIORewards = async (producers, totalVotes) => {
return producersRewards
}

const getFioRewards = async (producers) => {
const producersRewards = []
// ToDo : Calculate producer Rewards Based on FIO System Contracts
return producersRewards
}

const getVotes = (votes) => {
switch (eosConfig.networkName) {
case eosConfig.knownNetworks.telos:
Expand Down
10 changes: 9 additions & 1 deletion hapi/src/workers/producers.worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ const {
producerService,
settingService,
stateHistoryPluginService,
statsService
statsService,
fioService,
} = require('../services')
const { workersConfig, hasuraConfig, eosConfig } = require('../config')
const { axiosUtil, sleepFor } = require('../utils')
Expand Down Expand Up @@ -59,6 +60,13 @@ const start = async () => {
workersConfig.syncExchangeRate
)

if (eosConfig.networkName === eosConfig.knownNetworks.fio) {
run(
'SYNC FIO REWARDS',
fioService.syncRewards
)
}

if (eosConfig.eosmechanics.account && eosConfig.eosmechanics.password) {
run('CPU WORKER', cpuService.worker, workersConfig.cpuWorkerInterval)
run('CPU WORKER CLEANUP', cpuService.cleanOldBenchmarks, 86400)
Expand Down
4 changes: 3 additions & 1 deletion webapp/src/hooks/customHooks/useBlockProducerState.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import { eosConfig } from '../../config'

import useSearchState from './useBPSearchState'

const isFIO = eosConfig.networkName.replace('-testnet', '') === 'fio'
const minimumRewards = isFIO ? 1 : 100
const CHIPS_FILTERS = [
{ where: { owner: { _like: '%%' }, bp_json: { _is_null: false } } },
{
where: { total_rewards: { _neq: 0 }, rank: { _lte: 21 } },
},
{
where: { total_rewards: { _gte: 100 }, rank: { _gte: 22 } },
where: { total_rewards: { _gte: minimumRewards }, rank: { _gte: 22 } },
},
{
where: { total_rewards: { _eq: 0 } },
Expand Down
8 changes: 6 additions & 2 deletions webapp/src/hooks/customHooks/useNonCompliantState.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,27 @@ import { useLazyQuery } from '@apollo/client'

import { PRODUCERS_QUERY, SETTING_QUERY } from '../../gql'

import { eosConfig } from 'config'

const useNonCompliantState = () => {
const [loadProducers, { loading = true, data: { producers } = {} }] =
useLazyQuery(PRODUCERS_QUERY)
const [loadSettings, { data: { setting } = {} }] = useLazyQuery(SETTING_QUERY)
const [items, setItems] = useState([])
const [stats, setStats] = useState()
const isFIO = eosConfig.networkName.replace('-testnet', '') === 'fio'
const minimumRewards = isFIO ? 1 : 100

useEffect(() => {
loadSettings({})
loadProducers({
variables: {
where: { total_rewards: { _gte: 100 } },
where: { total_rewards: { _gte: minimumRewards } },
offset: 0,
limit: 150,
},
})
}, [loadSettings, loadProducers])
}, [loadSettings, loadProducers, minimumRewards])

useEffect(() => {
if (!producers) return
Expand Down
10 changes: 7 additions & 3 deletions webapp/src/hooks/customHooks/useRewardsDistributionState.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
import { useState, useEffect } from 'react'
import { useLazyQuery } from '@apollo/client'

import { countries } from 'utils/countries'
import { PRODUCERS_QUERY, SETTING_QUERY } from '../../gql'

import { countries } from 'utils/countries'
import { eosConfig } from 'config'

const useRewardsDistributionState = () => {
const [loadSettings, { data: { setting } = {} }] = useLazyQuery(SETTING_QUERY)
const [loadProducers, { loading = true, data: { producers } = {} }] =
useLazyQuery(PRODUCERS_QUERY)
const [summary, setSummary] = useState()
const [items, setItems] = useState([])
const isFIO = eosConfig.networkName.replace('-testnet', '') === 'fio'
const minimumRewards = isFIO ? 1 : 100

useEffect(() => {
loadSettings({})
loadProducers({
variables: {
where: { total_rewards: { _gte: 100 } },
where: { total_rewards: { _gte: minimumRewards } },
offset: 0,
limit: 2100,
},
})
}, [loadSettings, loadProducers])
}, [loadSettings, loadProducers, minimumRewards])

useEffect(() => {
if (!producers) return
Expand Down
Loading