-
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
- Loading branch information
49659410+tx0c
committed
Jan 20, 2024
1 parent
e9c911f
commit 0b3bfe3
Showing
8 changed files
with
2,199 additions
and
114 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,19 @@ | ||
#!/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, | ||
}); | ||
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,53 @@ | ||
import { Context, APIGatewayProxyResult, APIGatewayEvent } from "aws-lambda"; | ||
import { calculateQFScore } from "../lib/qf-calculate.js"; | ||
|
||
export const handler = async ( | ||
event: APIGatewayEvent & { | ||
fromTime?: string; | ||
toTime?: string; | ||
amount?: string; | ||
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 = !!("forceRun" in (event?.queryStringParameters as any)); | ||
const { accept, origin }: { accept?: string; origin?: string } = | ||
event?.headers || {}; | ||
if ( | ||
!( | ||
event?.forceRun || | ||
(path === "/qf-calculator" && accept?.includes("application/json")) | ||
) | ||
) { | ||
return { | ||
statusCode: 400, | ||
body: JSON.stringify({ | ||
error: | ||
"input error, call with POST /qf-calculator with accept: application/json", | ||
}), | ||
}; | ||
} | ||
|
||
const { fromTime, toTime, amount } = event?.forceRun | ||
? event | ||
: event?.queryStringParameters || {}; | ||
|
||
const { root, gist_url } = await calculateQFScore({ | ||
fromTime, | ||
toTime, | ||
amount: BigInt(+(amount || 500) * 1e6), | ||
}); | ||
|
||
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.