Skip to content

Commit 176da36

Browse files
committed
feat: compute proposal's scores_total_value
1 parent a4ad096 commit 176da36

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed

src/helpers/entityValue.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,50 @@ export function getVoteValue(vp_value_by_strategy: number[], vp_by_strategy: num
3838

3939
return vp_value_by_strategy.reduce((sum, value, index) => sum + value * vp_by_strategy[index], 0);
4040
}
41+
42+
/**
43+
* Calculates the proposal total value based on all votes' total voting power and the proposal's value per strategy.
44+
* @returns The total value of the given proposal's votes, in the currency unit specified by the proposal's vp_value_by_strategy values
45+
*/
46+
export function getProposalValue(
47+
scores_by_strategy: number[][],
48+
vp_value_by_strategy: number[]
49+
): number {
50+
if (
51+
!scores_by_strategy.length ||
52+
!scores_by_strategy[0]?.length ||
53+
!vp_value_by_strategy.length
54+
) {
55+
return 0;
56+
}
57+
58+
// Validate that all voteScores arrays have the same length as vp_value_by_strategy
59+
for (const voteScores of scores_by_strategy) {
60+
if (voteScores.length !== vp_value_by_strategy.length) {
61+
throw new Error(
62+
'Array size mismatch: voteScores length does not match vp_value_by_strategy length'
63+
);
64+
}
65+
}
66+
67+
let totalValue = 0;
68+
for (let strategyIndex = 0; strategyIndex < vp_value_by_strategy.length; strategyIndex++) {
69+
const strategyTotal = scores_by_strategy.reduce((sum, voteScores) => {
70+
const score = voteScores[strategyIndex];
71+
if (typeof score !== 'number') {
72+
throw new Error(`Invalid score value: expected number, got ${typeof score}`);
73+
}
74+
return sum + score;
75+
}, 0);
76+
77+
if (typeof vp_value_by_strategy[strategyIndex] !== 'number') {
78+
throw new Error(
79+
`Invalid vp_value: expected number, got ${typeof vp_value_by_strategy[strategyIndex]}`
80+
);
81+
}
82+
83+
totalValue += strategyTotal * vp_value_by_strategy[strategyIndex];
84+
}
85+
86+
return totalValue;
87+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { capture } from '@snapshot-labs/snapshot-sentry';
2+
import snapshot from '@snapshot-labs/snapshot.js';
3+
import { getProposalValue } from './entityValue';
4+
import db from './mysql';
5+
import { CB } from '../constants';
6+
7+
type Proposal = {
8+
id: string;
9+
vp_value_by_strategy: number[];
10+
scores_by_strategy: number[][];
11+
};
12+
13+
const REFRESH_INTERVAL = 10 * 1000;
14+
const BATCH_SIZE = 25;
15+
16+
async function getProposals(): Promise<Proposal[]> {
17+
const query = `
18+
SELECT id, vp_value_by_strategy, scores_by_strategy
19+
FROM proposals
20+
WHERE cb = ? AND end < UNIX_TIMESTAMP() AND scores_state = ?
21+
ORDER BY created ASC
22+
LIMIT ?
23+
`;
24+
const proposals = await db.queryAsync(query, [CB.PENDING_CLOSE, 'final', BATCH_SIZE]);
25+
26+
return proposals.map((p: any) => {
27+
p.vp_value_by_strategy = JSON.parse(p.vp_value_by_strategy);
28+
p.scores_by_strategy = JSON.parse(p.scores_by_strategy);
29+
return p;
30+
});
31+
}
32+
33+
async function refreshScoresTotal(proposals: Proposal[]) {
34+
const query: string[] = [];
35+
const params: any[] = [];
36+
37+
proposals.map(proposal => {
38+
query.push('UPDATE proposals SET scores_total_value = ?, cb = ? WHERE id = ? LIMIT 1');
39+
40+
try {
41+
const scores_total_value = getProposalValue(
42+
proposal.scores_by_strategy,
43+
proposal.vp_value_by_strategy
44+
);
45+
params.push(scores_total_value, CB.FINAL, proposal.id);
46+
} catch (e) {
47+
capture(e);
48+
params.push(0, CB.INELIGIBLE, proposal.id);
49+
}
50+
});
51+
52+
if (query.length) {
53+
await db.queryAsync(query.join(';'), params);
54+
}
55+
}
56+
57+
export default async function run() {
58+
while (true) {
59+
const proposals = await getProposals();
60+
61+
if (proposals.length) {
62+
await refreshScoresTotal(proposals);
63+
}
64+
65+
if (proposals.length < BATCH_SIZE) {
66+
await snapshot.utils.sleep(REFRESH_INTERVAL);
67+
}
68+
}
69+
}

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import api from './api';
66
import log from './helpers/log';
77
import initMetrics from './helpers/metrics';
88
import refreshModeration from './helpers/moderation';
9+
import refreshProposalsScoresValue from './helpers/proposalsScoresValue';
910
import refreshProposalsVpValue from './helpers/proposalStrategiesValue';
1011
import rateLimit from './helpers/rateLimit';
1112
import shutter from './helpers/shutter';
@@ -23,6 +24,7 @@ async function startServer() {
2324
initLogger(app);
2425
refreshModeration();
2526
refreshProposalsVpValue();
27+
refreshProposalsScoresValue();
2628
refreshVotesVpValue();
2729

2830
await initializeStrategies();

0 commit comments

Comments
 (0)