-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(qf-funding-score): to calculate score for each project from past…
… donations for thematters/developer-resource#350 & #103 1. add trust points details for each sender, in tsv format good for export/import spreadsheet for human review; 2. saved to s3 bucket `s3://matters-billboard/pre-rounds/` for automation later;
- Loading branch information
49659410+tx0c
committed
Feb 3, 2024
1 parent
e9c911f
commit 511386a
Showing
9 changed files
with
13,196 additions
and
10,361 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#!/usr/bin/env -S node --trace-warnings --loader ts-node/esm | ||
|
||
import { calculateQFScore } from "../lib/qf-calculate.js"; | ||
|
||
async function main() { | ||
const args = process.argv.slice(2); | ||
const amount = BigInt(+(args?.[0] || 500) * 1e6); | ||
const fromTime = args?.[1] || "2023-12-31"; | ||
const toTime = args?.[2] || "2024-12-31T23:59:59.999Z"; | ||
|
||
const res = await calculateQFScore({ | ||
fromTime, // : "2023-12-31", | ||
toTime, // : "2024-12-31T23:59:59.999Z", | ||
amount, | ||
write_gist: true, | ||
}); | ||
console.log(new Date(), "res:", res); | ||
} | ||
|
||
main().catch((err) => console.error(new Date(), "ERROR:", err)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import { Context, APIGatewayProxyResult, APIGatewayEvent } from "aws-lambda"; | ||
import { calculateQFScore } from "../lib/qf-calculate.js"; | ||
import { s3GetFile } from "../lib/utils/aws.js"; | ||
|
||
export const handler = async ( | ||
event: APIGatewayEvent & { | ||
fromTime?: string; | ||
toTime?: string; | ||
fromBlock?: string; | ||
toBlock?: string; | ||
amount?: string; | ||
appendToRounds?: boolean; | ||
forceRun?: boolean; | ||
}, | ||
context: Context | ||
): Promise<APIGatewayProxyResult> => { | ||
console.log(`Event: ${JSON.stringify(event, null, 2)}`); | ||
console.log(`Context: ${JSON.stringify(context, null, 2)}`); | ||
|
||
const { method, path } = ((event?.requestContext as any)?.http as any) || {}; | ||
// const forceRun = !!(event?.queryStringParameters as any).forceRun; | ||
const queryStringParameters = (event?.queryStringParameters as any) || {}; | ||
const forceRun = !!("forceRun" in queryStringParameters); | ||
const { accept, origin }: { accept?: string; origin?: string } = | ||
event?.headers || {}; | ||
if ( | ||
!( | ||
event?.forceRun || | ||
(path === "/qf-calculator" && accept?.startsWith("application/json")) || | ||
(path === "/get-rounds" && accept) | ||
) | ||
) { | ||
return { | ||
statusCode: 400, | ||
body: JSON.stringify({ | ||
error: | ||
"input error, call with POST /qf-calculator with accept: application/json", | ||
}), | ||
}; | ||
} | ||
|
||
if (path === "/get-rounds") { | ||
const { key } = queryStringParameters; | ||
const res = await s3GetFile({ | ||
bucket: "matters-billboard", | ||
key: key?.endsWith(".json") ? key : `pre-rounds/rounds.json`, | ||
}); // .then((res) => console.log(new Date(), `s3 get pre-rounds:`, res)); | ||
console.log(new Date(), `s3 get pre-rounds:`, res.ContentLength, res); | ||
if (!res.Body) { | ||
return { statusCode: 404, body: "file not found" }; | ||
} | ||
const body = await res.Body.transformToString(); | ||
return { | ||
statusCode: 200, | ||
body: body, | ||
}; | ||
} | ||
|
||
const { fromTime, toTime, fromBlock, toBlock, amount, appendToRounds } = | ||
event?.forceRun ? event : queryStringParameters; | ||
|
||
const { root, gist_url } = await calculateQFScore({ | ||
fromTime, | ||
toTime, | ||
fromBlock: fromBlock ? BigInt(fromBlock) : undefined, | ||
toBlock: toBlock ? BigInt(toBlock) : undefined, | ||
amount: BigInt(+(amount || 500) * 1e6), | ||
appendToRounds: !!appendToRounds, | ||
}); | ||
|
||
return { | ||
statusCode: 200, | ||
body: JSON.stringify({ | ||
message: "done.", | ||
root, // tree | ||
gist_url, | ||
}), | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// https://golb.hplar.ch/2018/09/javascript-bigint.html | ||
export class BigIntMath { | ||
static max(...values: Array<bigint | number>) { | ||
if (values.length === 0) { | ||
return null; | ||
} | ||
|
||
if (values.length === 1) { | ||
return values[0]; | ||
} | ||
|
||
let max = values[0]; | ||
for (let i = 1; i < values.length; i++) { | ||
if (values[i] > max) { | ||
max = values[i]; | ||
} | ||
} | ||
return max; | ||
} | ||
|
||
static min(...values: Array<bigint | number>) { | ||
if (values.length === 0) { | ||
return null; | ||
} | ||
|
||
if (values.length === 1) { | ||
return values[0]; | ||
} | ||
|
||
let min = values[0]; | ||
for (let i = 1; i < values.length; i++) { | ||
if (values[i] < min) { | ||
min = values[i]; | ||
} | ||
} | ||
return min; | ||
} | ||
|
||
static sign(value: bigint | number) { | ||
if (value > 0n) { | ||
return 1n; | ||
} | ||
if (value < 0n) { | ||
return -1n; | ||
} | ||
return 0n; | ||
} | ||
|
||
static abs(value: bigint | number) { | ||
if (this.sign(value) === -1n) { | ||
return -value; | ||
} | ||
return value; | ||
} | ||
|
||
// https://stackoverflow.com/questions/53683995/javascript-big-integer-square-root/58863398#58863398 | ||
static rootNth(value: bigint, k: bigint = 2n) { | ||
if (value < 0n) { | ||
throw "negative number is not supported"; | ||
} | ||
|
||
let o = 0n; | ||
let x = value; | ||
let limit = 100; | ||
|
||
while (x ** k !== k && x !== o && --limit) { | ||
o = x; | ||
x = ((k - 1n) * x + value / x ** (k - 1n)) / k; | ||
} | ||
|
||
return x; | ||
} | ||
|
||
static sqrt(value: bigint) { | ||
return BigIntMath.rootNth(value); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
const PolygonScanAPIKEY = process.env.MATTERS_POLYGONSCANAPIKEY || ""; | ||
// https://api.polygonscan.com/api?module=block&action=getblocknobytime×tamp=1704184772&closest=before&apikey={key} | ||
|
||
export class PolygonScanAPI { | ||
static async getBlockFromTimestamp({ | ||
timestamp, | ||
closest, | ||
}: { | ||
timestamp: number; // Date | string | number; | ||
closest: "before" | "after"; | ||
}) { | ||
const nowTs = Math.floor(+Date.now() / 1e3); | ||
const params = new URLSearchParams({ | ||
module: "block", | ||
action: "getblocknobytime", | ||
timestamp: Math.min(nowTs, timestamp).toString(), | ||
closest: timestamp >= nowTs ? "before" : closest, // override to before if pass now or future timestamp | ||
apikey: PolygonScanAPIKEY, | ||
}); | ||
const u = new URL(`https://api.polygonscan.com/api?${params}`); | ||
console.log(new Date(), `get with:`, { params, u }); | ||
const res = await fetch(u).then((res) => res.json()); | ||
|
||
// {"status":"1","message":"OK","result":"51846093"} | ||
if (!(res?.status === "1" && res?.message === "OK")) | ||
console.error(new Date(), `non-ok result:`, res); | ||
|
||
return BigInt(res?.result); | ||
} | ||
} |
Oops, something went wrong.