From c318827e059c88956b203f521ff0f1051fd01e14 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Wed, 12 Apr 2023 17:55:05 +0200 Subject: [PATCH 1/8] initial calculator implementation --- package.json | 1 + src/calculator.ts | 39 +++++++++++++++++++++++++++++++++++++++ src/server.ts | 11 +++++++++++ 3 files changed, 51 insertions(+) create mode 100644 src/calculator.ts diff --git a/package.json b/package.json index ad462912..fae799d3 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "express": "^4.18.2", "memory-cache": "^0.2.0", "npm-run-all": "^4.1.5", + "pluralistic": "github:gitcoinco/pluralistic.js#431f4fe2d429f65f2de03bdfcc66bba451da2ba7", "serve-index": "^1.9.1", "statuses-bitmap": "github:gitcoinco/statuses-bitmap#3d8fd370f209ccbaffd3781cf2b6d2895237c21c", "typescript": "^4.9.5", diff --git a/src/calculator.ts b/src/calculator.ts new file mode 100644 index 00000000..2edb822a --- /dev/null +++ b/src/calculator.ts @@ -0,0 +1,39 @@ +import fs from "fs"; +import { linearQF, Contribution } from "pluralistic"; + +export default class Calculator { + private baseDataPath: string; + private chainID: string; + private roundID: string; + + constructor(baseDataPath: string, chainID: string, roundID: string) { + this.baseDataPath = baseDataPath; + this.chainID = chainID; + this.roundID = roundID; + } + + calculate() { + const votesPath = `${this.baseDataPath}/${this.chainID}/rounds/${this.roundID}/votes.json`; + const votesData = fs.readFileSync(votesPath, { + encoding: "utf8", + flag: "r", + }); + + const rawContributions = JSON.parse(votesData); + + const contributions: Array = rawContributions.map( + (raw: any) => ({ + contributor: raw.voter, + recipient: raw.projectId, + amount: raw.amountUSD, + }) + ); + + const results = linearQF(contributions, 333000, { + minimumAmount: 1, + ignoreSaturation: true, + }); + + return results; + } +} diff --git a/src/server.ts b/src/server.ts index 17202ba7..5d9c3eb8 100644 --- a/src/server.ts +++ b/src/server.ts @@ -3,6 +3,7 @@ import cors from "cors"; import serveIndex from "serve-index"; import config from "./config.js"; +import Calculator from "./calculator.js"; const app = express(); @@ -23,6 +24,16 @@ app.get("/", (_req, res) => { res.redirect("/data"); }); +app.get("/chains/:chainID/rounds/:roundID/matches", (req, res) => { + const chainID = req.params.chainID; + const roundID = req.params.roundID; + + const c = new Calculator("./data", chainID, roundID); + const matches = c.calculate(); + + res.send(matches); +}); + app.listen(config.port, () => { console.log(`Server listening on port ${config.port}`); }); From 24c3ecd5af58650f028f7d9b5922d94ea4e0c4c8 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Wed, 12 Apr 2023 18:18:49 +0200 Subject: [PATCH 2/8] augment matching results with project data --- src/calculator.ts | 49 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/src/calculator.ts b/src/calculator.ts index 2edb822a..20558999 100644 --- a/src/calculator.ts +++ b/src/calculator.ts @@ -1,6 +1,14 @@ import fs from "fs"; import { linearQF, Contribution } from "pluralistic"; +type AugmentedResult = { + totalReceived: number; + sumOfSqrt: number; + matched: number; + projectName: string; + payoutAddress: string; +}; + export default class Calculator { private baseDataPath: string; private chainID: string; @@ -13,13 +21,13 @@ export default class Calculator { } calculate() { - const votesPath = `${this.baseDataPath}/${this.chainID}/rounds/${this.roundID}/votes.json`; - const votesData = fs.readFileSync(votesPath, { - encoding: "utf8", - flag: "r", - }); - - const rawContributions = JSON.parse(votesData); + const rawContributions = this.parseJSONFile( + `${this.chainID}/rounds/${this.roundID}/votes.json` + ); + const projects = this.parseJSONFile(`${this.chainID}/projects.json`); + const applications = this.parseJSONFile( + `${this.chainID}/rounds/${this.roundID}/projects.json` + ); const contributions: Array = rawContributions.map( (raw: any) => ({ @@ -34,6 +42,31 @@ export default class Calculator { ignoreSaturation: true, }); - return results; + const augmented: Array = []; + for (const id in results) { + const calc = results[id]; + const project = projects.find((p: any) => p.id === id); + const application = applications.find((a: any) => a.id === id); + + augmented.push({ + totalReceived: calc.totalReceived, + sumOfSqrt: calc.sumOfSqrt, + matched: calc.matched, + projectName: project?.metadata?.title, + payoutAddress: application?.payoutAddress, + }); + } + + return augmented; + } + + parseJSONFile(path: string) { + const fullPath = `${this.baseDataPath}/${path}`; + const data = fs.readFileSync(fullPath, { + encoding: "utf8", + flag: "r", + }); + + return JSON.parse(data); } } From fb5c976cb4c3e2276baa8778f633a38e67a0b2cf Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Wed, 12 Apr 2023 18:27:16 +0200 Subject: [PATCH 3/8] augment Calculation --- src/calculator.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/calculator.ts b/src/calculator.ts index 20558999..92ba0063 100644 --- a/src/calculator.ts +++ b/src/calculator.ts @@ -1,10 +1,7 @@ import fs from "fs"; -import { linearQF, Contribution } from "pluralistic"; +import { linearQF, Contribution, Calculation } from "pluralistic"; -type AugmentedResult = { - totalReceived: number; - sumOfSqrt: number; - matched: number; +type AugmentedResult = Calculation & { projectName: string; payoutAddress: string; }; From 43a818087d501794099e7b1f552370da6292fd5b Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Wed, 12 Apr 2023 18:55:23 +0200 Subject: [PATCH 4/8] rename ID to Id in variable names --- src/server.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/server.ts b/src/server.ts index 5d9c3eb8..e9671db0 100644 --- a/src/server.ts +++ b/src/server.ts @@ -24,11 +24,11 @@ app.get("/", (_req, res) => { res.redirect("/data"); }); -app.get("/chains/:chainID/rounds/:roundID/matches", (req, res) => { - const chainID = req.params.chainID; - const roundID = req.params.roundID; +app.get("/chains/:chainId/rounds/:roundId/matches", (req, res) => { + const chainId = req.params.chainId; + const roundId = req.params.roundId; - const c = new Calculator("./data", chainID, roundID); + const c = new Calculator("./data", chainId, roundId); const matches = c.calculate(); res.send(matches); From 562932dfa0fdc2c5f91275eb56c00bdb0d3a24f7 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Wed, 12 Apr 2023 18:57:37 +0200 Subject: [PATCH 5/8] rename ID to Id in Calculator vars --- src/calculator.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/calculator.ts b/src/calculator.ts index 92ba0063..e873f98c 100644 --- a/src/calculator.ts +++ b/src/calculator.ts @@ -8,22 +8,22 @@ type AugmentedResult = Calculation & { export default class Calculator { private baseDataPath: string; - private chainID: string; - private roundID: string; + private chainId: string; + private roundId: string; - constructor(baseDataPath: string, chainID: string, roundID: string) { + constructor(baseDataPath: string, chainId: string, roundId: string) { this.baseDataPath = baseDataPath; - this.chainID = chainID; - this.roundID = roundID; + this.chainId = chainId; + this.roundId = roundId; } calculate() { const rawContributions = this.parseJSONFile( - `${this.chainID}/rounds/${this.roundID}/votes.json` + `${this.chainId}/rounds/${this.roundId}/votes.json` ); - const projects = this.parseJSONFile(`${this.chainID}/projects.json`); + const projects = this.parseJSONFile(`${this.chainId}/projects.json`); const applications = this.parseJSONFile( - `${this.chainID}/rounds/${this.roundID}/projects.json` + `${this.chainId}/rounds/${this.roundId}/projects.json` ); const contributions: Array = rawContributions.map( From 6c11906f3939d332e438abd17ee2123531d38694 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Wed, 12 Apr 2023 19:31:02 +0200 Subject: [PATCH 6/8] update lock file with pluralistic dep --- package-lock.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/package-lock.json b/package-lock.json index c34246ce..26106043 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "express": "^4.18.2", "memory-cache": "^0.2.0", "npm-run-all": "^4.1.5", + "pluralistic": "github:gitcoinco/pluralistic.js#431f4fe2d429f65f2de03bdfcc66bba451da2ba7", "serve-index": "^1.9.1", "statuses-bitmap": "github:gitcoinco/statuses-bitmap#3d8fd370f209ccbaffd3781cf2b6d2895237c21c", "typescript": "^4.9.5", @@ -3570,6 +3571,13 @@ "node": ">=4" } }, + "node_modules/pluralistic": { + "version": "0.1.0", + "resolved": "git+ssh://git@github.com/gitcoinco/pluralistic.js.git#431f4fe2d429f65f2de03bdfcc66bba451da2ba7", + "integrity": "sha512-42ieZn9bIoWVmbYtLKF81Ilv9y+eKJhIfMZX3uNi4tc+gZP22oLAM5LOjd5vRhM9XcIkjbLJr0Pn3ox4iFXE7g==", + "hasInstallScript": true, + "license": "ISC" + }, "node_modules/prebuild-install": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", @@ -6711,6 +6719,11 @@ "pify": { "version": "3.0.0" }, + "pluralistic": { + "version": "git+ssh://git@github.com/gitcoinco/pluralistic.js.git#431f4fe2d429f65f2de03bdfcc66bba451da2ba7", + "integrity": "sha512-42ieZn9bIoWVmbYtLKF81Ilv9y+eKJhIfMZX3uNi4tc+gZP22oLAM5LOjd5vRhM9XcIkjbLJr0Pn3ox4iFXE7g==", + "from": "pluralistic@github:gitcoinco/pluralistic.js#431f4fe2d429f65f2de03bdfcc66bba451da2ba7" + }, "prebuild-install": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", From c9bbc0ad5076d7f4ad3fec587dfe7c3a60f00659 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Thu, 13 Apr 2023 18:39:52 +0200 Subject: [PATCH 7/8] add matchAmount to Calculator --- src/calculator.ts | 11 +++++++++-- src/server.ts | 4 +++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/calculator.ts b/src/calculator.ts index e873f98c..39179518 100644 --- a/src/calculator.ts +++ b/src/calculator.ts @@ -10,11 +10,18 @@ export default class Calculator { private baseDataPath: string; private chainId: string; private roundId: string; + private matchAmount: number; - constructor(baseDataPath: string, chainId: string, roundId: string) { + constructor( + baseDataPath: string, + chainId: string, + roundId: string, + matchAmount: number + ) { this.baseDataPath = baseDataPath; this.chainId = chainId; this.roundId = roundId; + this.matchAmount = matchAmount; } calculate() { @@ -34,7 +41,7 @@ export default class Calculator { }) ); - const results = linearQF(contributions, 333000, { + const results = linearQF(contributions, this.matchAmount, { minimumAmount: 1, ignoreSaturation: true, }); diff --git a/src/server.ts b/src/server.ts index e9671db0..6ba0b265 100644 --- a/src/server.ts +++ b/src/server.ts @@ -28,7 +28,9 @@ app.get("/chains/:chainId/rounds/:roundId/matches", (req, res) => { const chainId = req.params.chainId; const roundId = req.params.roundId; - const c = new Calculator("./data", chainId, roundId); + // temporarily hardcoded amount waiting to take this data from the round indexed data + const matchAmount = 333000; + const c = new Calculator("./data", chainId, roundId, matchAmount); const matches = c.calculate(); res.send(matches); From b13d3ca26c0ca82bde00adacd7a00c80698f5115 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Thu, 13 Apr 2023 18:43:09 +0200 Subject: [PATCH 8/8] add RawContribution interface --- src/calculator.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/calculator.ts b/src/calculator.ts index 39179518..99bd54b7 100644 --- a/src/calculator.ts +++ b/src/calculator.ts @@ -6,6 +6,12 @@ type AugmentedResult = Calculation & { payoutAddress: string; }; +interface RawContribution { + voter: string; + projectId: string; + amountUSD: number; +} + export default class Calculator { private baseDataPath: string; private chainId: string; @@ -34,7 +40,7 @@ export default class Calculator { ); const contributions: Array = rawContributions.map( - (raw: any) => ({ + (raw: RawContribution) => ({ contributor: raw.voter, recipient: raw.projectId, amount: raw.amountUSD,