Skip to content

Commit

Permalink
Merge 49ff609 into 57312d8
Browse files Browse the repository at this point in the history
  • Loading branch information
Agupane committed Jul 15, 2019
2 parents 57312d8 + 49ff609 commit 164c8b4
Show file tree
Hide file tree
Showing 9 changed files with 534 additions and 13 deletions.
10 changes: 6 additions & 4 deletions server/delegator/delegator.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const DelegatorSchema = new mongoose.Schema({
required: true
},
delegate: {
type: mongoose.Schema.Types.ObjectId,
type: String,
ref: 'Delegate',
required: true
},
Expand All @@ -19,13 +19,15 @@ const DelegatorSchema = new mongoose.Schema({
},
totalStake: {
type: String,
required: false
required: false,
default: '0'
},
shares: [
{
type: mongoose.Schema.Types.ObjectId,
type: String,
ref: 'Share',
required: false
required: false,
default: []
}
]
})
Expand Down
105 changes: 105 additions & 0 deletions server/helpers/delegatorUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
const Delegator = require('../delegator/delegator.model')
const Share = require('../share/share.model')
const mongoose = require('../../config/mongoose')
const { MathBN } = require('./utils')

// Fetch the round-id delegator total stake from the last share and make a sub with the current total stake
const getDelegatorCurrentRewardTokens = async (
currentRoundId,
delegatorAddress,
currentDelegatorTotalStake
) => {
if (!currentRoundId) {
console.error(
'[Delegator utils] - no round id was provided on getDelegateCurrentRewardTokens()'
)
throw new Error(
'[Delegator utils] - no round id was provided on getDelegateCurrentRewardTokens()'
)
}
if (!delegatorAddress) {
console.error(
'[Delegator utils] - no delegatorAddress was provided on getDelegateCurrentRewardTokens()'
)
throw new Error(
'[Delegator utils] - no delegatorAddress was provided on getDelegateCurrentRewardTokens()'
)
}
if (!currentDelegatorTotalStake) {
console.error(
'[Delegator utils] - no currentDelegatorTotalStake was provided on getDelegateCurrentRewardTokens()'
)
throw new Error(
'[Delegator utils] - no currentDelegatorTotalStake was provided on getDelegateCurrentRewardTokens()'
)
}
const lastRoundId = currentRoundId - 1
const lastDelegatorShareId = `${delegatorAddress}-${lastRoundId}`
const lastDelegatorShare = await Share.findById(lastDelegatorShareId)
// The first time we register the delegator on the db, he won't have any shares, we save 0
if (!lastDelegatorShare) {
console.error('[Delegator utils] - last share not found')
return 0
}
const newShare = MathBN.sub(currentDelegatorTotalStake, lastDelegatorShare.totalStakeOnRound)
console.log(`[Delegator utils] - returning new share: ${newShare}`)
return newShare
}

// Receives all the delegates that are stored locally and the delegates from the graph
// If there are delegates who are not stored locally, save them on the db
const checkAndUpdateMissingLocalDelegators = async fetchedDelegators => {
console.error(`[Delegator utils] - checkAndUpdateMissingLocalDelegators Start`)
if (!fetchedDelegators || fetchedDelegators.length === 0) {
console.error(
'[Delegator utils] - there were no remote delegators received on checkAndUpdateMissingLocalDelegators()'
)
return
}
const updateDelegatorPromises = []
for (let remoteDelegatorIterator of fetchedDelegators) {
const remoteId = remoteDelegatorIterator.address
const delegateAddress = remoteDelegatorIterator.delegateAddress
? remoteDelegatorIterator.delegateAddress
: remoteDelegatorIterator.delegate
if (!remoteId) {
console.error(`[Delegator utils] - delegator ${remoteDelegatorIterator} has not id, skipped`)
continue
}
if (!delegateAddress) {
console.error(`[Delegator utils] - delegator ${remoteId} has not delegate address, skipped`)
continue
}
const localFound = await Delegator.findById(remoteId)
if (!localFound) {
console.log(`[Delegator utils] - remote delegator ${remoteId} not found locally, adding it`)
const { startRound, totalStake } = remoteDelegatorIterator
const newDelegator = new Delegator({
_id: remoteId,
delegate: delegateAddress,
startRound,
totalStake
})
updateDelegatorPromises.push(newDelegator.save())
} else {
// If found, just update it
const updatedDelegator = new Delegator({
_id: remoteId,
delegate: delegateAddress,
startRound: remoteDelegatorIterator.startRound,
totalStake: remoteDelegatorIterator.totalStake,
shares: localFound.shares
})
updateDelegatorPromises.push(updatedDelegator.save())
}
}
await Promise.all(updateDelegatorPromises)
console.error(`[Delegator utils] - checkAndUpdateMissingLocalDelegators Finished`)
}

const delegatorUtils = {
checkAndUpdateMissingLocalDelegators,
getDelegatorCurrentRewardTokens
}

module.exports = delegatorUtils
8 changes: 6 additions & 2 deletions server/helpers/updateRoundPools.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,14 @@ const updateDelegatePoolsOfRound = async (round, roundPools) => {
newSavedPool = await newSavedPool.save()
// Also updates the round with the pool
round.pools.push(newSavedPool)
console.log('[Update Delegates Pools] - Updating round with pool')
console.log(
`[Update Delegates Pools] - Updating round ${roundId} with pool ${poolIterator.id}`
)
round = await round.save()
// Finally Updates the delegate with the new pool
console.log('[Update Delegates Pools] - Updating delegate with pool')
console.log(
`[Update Delegates Pools] - Updating delegate ${delegateId} with pool ${poolIterator.id}`
)
delegate.pools.push(newSavedPool)
delegate = await delegate.save()
} catch (err) {
Expand Down
124 changes: 124 additions & 0 deletions server/helpers/updateRoundShares.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
const mongoose = require('../../config/mongoose')
const delegatorUtils = require('./delegatorUtils')
const Share = require('../share/share.model')
const Round = require('../round/round.model')
const Delegator = require('../delegator/delegator.model')
const Subscriber = require('../subscriber/subscriber.model')

const updateDelegatorSharesOfRound = async (round, delegator) => {
console.log('[Update Delegators Shares] - Starts updating delegator shares')
if (!round) {
console.error('[Update Delegators Shares] - No round shares were provided')
throw new Error('[Update Delegators Shares] - No round shares were provided')
}
if (!delegator) {
console.error('[Update Delegators Shares] - No delegator was provided')
throw new Error('[Update Delegators Shares] - No delegator was provided')
}
const delegatorAddress = delegator.address
if (!delegatorAddress) {
console.error(`[Update Delegators Shares] - delegator ${delegator} has not address`)
throw new Error(`[Update Delegators Shares] - delegator ${delegator} has not address`)
}
// Checks that the delegator exists before continue
delegator = await Delegator.findById(delegatorAddress)
if (!delegator) {
console.error(
`[Update Delegators Shares] - Delegator ${delegatorAddress} not found, did you called checkAndUpdateMissingLocalDelegators() before?`
)
throw new Error(
'[Update Delegators Shares] - Delegator ${delegatorAddress} not found, did you called checkAndUpdateMissingLocalDelegators() before?'
)
}
// Checks that the round exists before continue
const { roundId } = round
round = await Round.findById(roundId)
if (!round) {
console.error('[Update Delegators Shares] - The round provided does not exists')
throw new Error('[Update Delegators Shares] - The round provided does not exists')
}

// Creates the share object
const { totalStake } = delegator
const shareId = `${delegatorAddress}-${roundId}`
const rewardTokens = await delegatorUtils.getDelegatorCurrentRewardTokens(
roundId,
delegatorAddress,
totalStake
)

let newSavedShared = new Share({
_id: shareId,
rewardTokens,
totalStakeOnRound: totalStake,
delegator: delegatorAddress,
delegate: delegatorAddress,
round: roundId
})

try {
// Saves the share
console.log(`[Update Delegators Shares] - Saving new share for delegator ${delegatorAddress}`)
newSavedShared = await newSavedShared.save()
// Updates the pool with the share
round.shares.push(newSavedShared)
console.log('[Update Delegators Shares] - Updating round with share')
round = await round.save()
// Finally updates the delegator with the new share
delegator.shares.push(newSavedShared)
delegator = await delegator.save()
} catch (err) {
console.error(
`[Update Delegators Shares] - Error Updating share on delegator ${delegatorAddress}`
)
console.error(err)
throw err
}
}

// Executed on round changed, only executes for the delegators which are subscribed
const updateDelegatorsShares = async newRound => {
console.log('[Update Delegator shares] - Start')
if (!newRound) {
throw new Error('[Update Delegator shares] - No round was provided')
}

// Fetch all the delegators that are subscribed
const delegatorsAndSubscribersList = await Subscriber.getDelegatorSubscribers()
if (!delegatorsAndSubscribersList || delegatorsAndSubscribersList.length === 0) {
console.log('[Update Delegator shares] - No delegators subscribers found')
return
}
const delegators = []
delegatorsAndSubscribersList.forEach(element => {
if (element.delegator) {
delegators.push(element.delegator)
}
})
if (!delegators || delegators.length === 0) {
console.log('[Update Delegator shares] - No delegators subscribers found')
return
}

try {
// Then checks if all the fetched delegators exists locally, otherwise, add the ones that are missing
await delegatorUtils.checkAndUpdateMissingLocalDelegators(delegators)

// Then updates the delegators shares on the current round
for (let delegatorIterator of delegators) {
await service.updateDelegatorSharesOfRound(newRound, delegatorIterator)
}

console.log('[Update Delegators Share] - Finish')
} catch (err) {
console.error(`[Update Delegators Share] - Error when updating delegators shares: ${err}`)
throw new Error(`[Update Delegators Share] - Error when updating delegators shares: ${err}`)
}
}

const service = {
updateDelegatorsShares,
updateDelegatorSharesOfRound
}

module.exports = service
5 changes: 3 additions & 2 deletions server/jobs/check-round-change.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const config = require('../../config/config')

const { getProtocolService } = require('../helpers/services/protocolService')
const roundPoolsUtils = require('../helpers/updateRoundPools')
const roundSharesUtils = require('../helpers/updateRoundShares')

const Round = require('../round/round.model')

Expand Down Expand Up @@ -61,7 +62,6 @@ const workerCheckRoundChange = async () => {
sendTelegramRewardCallNotificationToDelegators(),
sendTelegramRewardCallNotificationToDelegates()
])

// Once the notifications are sent, update round and lock
const data = {
_id: id,
Expand All @@ -75,8 +75,9 @@ const workerCheckRoundChange = async () => {
let roundCreated = new Round(data)
await roundCreated.save()

// Dispatch updates of round pools
// Originally this was dispatched in promise all, but I'm not sure how the update of the round could impact on a race condition
await roundPoolsUtils.updateDelegatesPools(roundCreated)
await roundSharesUtils.updateDelegatorsShares(roundCreated)
} else {
console.log(
`[Check-Round-Change] - The round progress is bellow the threshold or the notifications were already sent, actions will be not dispatched`
Expand Down
6 changes: 5 additions & 1 deletion server/jobs/clear-documents.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
const mongoose = require('../../config/mongoose')
const Delegator = require('../delegator/delegator.model')
const Subscriber = require('../subscriber/subscriber.model')
const Telegram = require('../telegram/telegram.model')
const Round = require('../round/round.model')
const Delegate = require('../delegate/delegate.model')
const Pool = require('../pool/pool.model')
const Share = require('../share/share.model')
const config = require('../../config/config')

if (!['test', 'development'].includes(config.env)) {
console.log('You cant use this script in this enviroment')
console.log('You cant use this script in this environment')
process.exit(1)
}

Expand All @@ -17,7 +19,9 @@ Promise.all([
Subscriber.deleteMany({}),
Telegram.deleteMany({}),
Round.deleteMany({}),
Share.deleteMany({}),
Delegate.deleteMany({}),
Delegator.deleteMany({}),
Pool.deleteMany({})
])
.then(() => {
Expand Down
2 changes: 1 addition & 1 deletion server/jobs/notificate-delegates-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const sendEmailRewardCallNotificationToDelegates = async () => {
activated: 1,
email: { $ne: null }
}).exec()
console.log(`[Notificate-Delegates] - Start sending email notification to delegates}`)
console.log(`[Notificate-Delegates] - Start sending email notification to delegates`)
const subscribersToNofity = await getSubscribers(subscribers)

const subscribersToSendEmails = []
Expand Down
6 changes: 3 additions & 3 deletions server/share/share.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ const ShareSchema = new mongoose.Schema({
required: true
},
delegator: {
type: mongoose.Schema.Types.ObjectId,
type: String,
required: true,
ref: 'Delegator'
},
// The address of the delegate that provided the share on that round
delegate: {
type: mongoose.Schema.Types.ObjectId,
type: String,
ref: 'Delegate',
required: true
},
round: {
type: mongoose.Schema.Types.ObjectId,
type: String,
ref: 'Round',
required: true
}
Expand Down
Loading

0 comments on commit 164c8b4

Please sign in to comment.