-
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.
Merge pull request #1 from opensource-observer/jabolol/sdk-scaffold
add: `weight` update functionality
- Loading branch information
Showing
19 changed files
with
3,685 additions
and
0 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,43 @@ | ||
name: Update Split Weights | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
pull_request: | ||
branches: | ||
- main | ||
schedule: | ||
- cron: "0 19 * * 0" | ||
|
||
jobs: | ||
update-weights: | ||
runs-on: ubuntu-latest | ||
env: | ||
SUPABASE_URL: ${{ secrets.SUPABASE_URL }} | ||
SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
INFURA_KEY: ${{ secrets.INFURA_KEY }} | ||
INFURA_API_URL: ${{ secrets.INFURA_API_URL }} | ||
HOT_WALLET_ADDRESS: ${{ secrets.HOT_WALLET_ADDRESS }} | ||
HOT_WALLET_PRIVATE_KEY: ${{ secrets.HOT_WALLET_PRIVATE_KEY }} | ||
SPLITS_API_KEY: ${{ secrets.SPLITS_API_KEY }} | ||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
- name: Setup pnpm | ||
uses: pnpm/action-setup@v4 | ||
with: | ||
version: 9 | ||
run_install: | | ||
- recursive: true | ||
args: [--frozen-lockfile, --strict-peer-dependencies] | ||
- name: Setup node | ||
uses: actions/setup-node@v4 | ||
with: | ||
cache: "pnpm" | ||
node-version: "20.x" | ||
- name: Build sdk | ||
run: pnpm build:sdk | ||
- name: Update Weights | ||
run: cd packages/sdk && pnpm update:weights |
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,38 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# Dependencies | ||
node_modules | ||
.pnp | ||
.pnp.js | ||
|
||
# Local env files | ||
.env | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
# Testing | ||
coverage | ||
|
||
# Turbo | ||
.turbo | ||
|
||
# Vercel | ||
.vercel | ||
|
||
# Build Outputs | ||
.next/ | ||
out/ | ||
build | ||
dist | ||
|
||
|
||
# Debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# Misc | ||
.DS_Store | ||
*.pem |
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,35 @@ | ||
{ | ||
"name": "ethglobal-sf-2024", | ||
"description": "Funding public goods.", | ||
"version": "0.0.0", | ||
"author": "Kariba Labs", | ||
"license": "Apache-2.0", | ||
"private": true, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/opensource-observer/ethglobal-sf-2024.git" | ||
}, | ||
"scripts": { | ||
"build": "turbo run build --concurrency=100%", | ||
"build:sdk": "turbo run build --filter=@ethglobal-sf-2024/sdk", | ||
"lint": "turbo run lint --concurrency=100%", | ||
"test": "turbo run test --concurrency=1" | ||
}, | ||
"devDependencies": { | ||
"@typescript-eslint/eslint-plugin": "^8.10.0", | ||
"@typescript-eslint/parser": "^8.10.0", | ||
"eslint": "^9.13.0", | ||
"eslint-config-prettier": "^9.1.0", | ||
"eslint-plugin-react": "^7.37.1", | ||
"prettier": "^3.3.3", | ||
"turbo": "^2.2.1" | ||
}, | ||
"engines": { | ||
"node": ">=18.x", | ||
"pnpm": ">=8" | ||
}, | ||
"packageManager": "pnpm@9.6.0", | ||
"dependencies": { | ||
"pyright": "^1.1.385" | ||
} | ||
} |
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,9 @@ | ||
SUPABASE_URL= | ||
SUPABASE_KEY= | ||
GITHUB_TOKEN= | ||
INFURA_KEY= | ||
INFURA_API_URL= | ||
HOT_WALLET_ADDRESS= | ||
HOT_WALLET_PRIVATE_KEY= | ||
SPLITS_API_KEY= | ||
POPULATE_USER_ID= |
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,38 @@ | ||
{ | ||
"name": "@ethglobal-sf-2024/sdk", | ||
"version": "0.0.0", | ||
"private": true, | ||
"type": "module", | ||
"scripts": { | ||
"build": "tsc", | ||
"format": "prettier --write .", | ||
"populate:db": "node dist/index.js populate:db", | ||
"update:weights": "node dist/index.js update:weights", | ||
"dispatch:email": "node dist/index.js dispatch:email" | ||
}, | ||
"keywords": [], | ||
"authors": [ | ||
{ | ||
"name": "Javier Ríos", | ||
"email": "javi@karibalabs.co" | ||
} | ||
], | ||
"license": "ISC", | ||
"devDependencies": { | ||
"@types/node": "^22.7.7", | ||
"@types/yargs": "^17.0.33", | ||
"prettier": "^3.3.3", | ||
"typescript": "~5.6.3" | ||
}, | ||
"dependencies": { | ||
"@0xsplits/splits-sdk": "^4.1.0", | ||
"@actions/core": "^1.11.1", | ||
"@faker-js/faker": "^9.0.3", | ||
"@octokit/rest": "^21.0.2", | ||
"@supabase/supabase-js": "^2.45.6", | ||
"dotenv": "^16.4.5", | ||
"typescript-monads": "^9.0.0", | ||
"viem": "^2.21.29", | ||
"yargs": "^17.7.2" | ||
} | ||
} |
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,32 @@ | ||
import yargs from "yargs"; | ||
import { updateWeights } from "./metrics/index.js"; | ||
import { populateDb } from "./utils/misc.js"; | ||
|
||
const args = await yargs(process.argv.slice(2)) | ||
.command("populate:db", "Populate the database with initial data") | ||
.command("update:weights", "Update weights in the Split") | ||
.command("dispatch:email", "Dispatch email with the new weights") | ||
.demandCommand(1) | ||
.help().argv; | ||
|
||
const [command] = args._; | ||
|
||
const commandMap: { | ||
[key: string]: () => unknown; | ||
} = { | ||
"populate:db": async () => { | ||
const result = await populateDb(); | ||
if (result.isFail()) { | ||
throw result.unwrapFail(); | ||
} | ||
}, | ||
"update:weights": async () => { | ||
const result = await updateWeights(); | ||
if (result.isFail()) { | ||
throw result.unwrapFail(); | ||
} | ||
}, | ||
"dispatch:email": () => void 0, | ||
}; | ||
|
||
await commandMap[command](); |
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,108 @@ | ||
import { supabase } from "../utils/client.js"; | ||
import { FailResult, OkResult, Result } from "typescript-monads"; | ||
import { fetchMetricsForPool } from "./fetchMetricsForPool.js"; | ||
import core from "@actions/core"; | ||
|
||
type FundingWeight = { | ||
contributor: { | ||
id: string; | ||
wallet: string; | ||
artifact_namespace: string; | ||
artifact_name: string; | ||
}; | ||
allocatedFunding: number; | ||
}; | ||
|
||
export const computeWeights = async (): Promise< | ||
Result<Record<string, FundingWeight[]>, Error> | ||
> => { | ||
core.info("Computing weights for funding pools"); | ||
const { data: poolData, error } = await supabase | ||
.from("funding_pools") | ||
.select("*"); | ||
|
||
if (error) { | ||
return new FailResult(new Error(error.message)); | ||
} | ||
|
||
const fundingWeights: { | ||
[key: string]: FundingWeight[]; | ||
} = {}; | ||
|
||
for (const pool of poolData) { | ||
const metricsResult = await fetchMetricsForPool(pool.id); | ||
|
||
if (metricsResult.isFail()) { | ||
return new FailResult(metricsResult.unwrapFail()); | ||
} | ||
const metrics = metricsResult.unwrap(); | ||
|
||
const prWeight = 0.3; | ||
const issueWeight = 0.2; | ||
const linesWeight = 0.4; | ||
const commitWeight = 0.1; | ||
|
||
const fundingPool = 100; | ||
|
||
let totalPRs = 0; | ||
let totalIssues = 0; | ||
let totalLinesAdded = 0; | ||
let totalLinesDeleted = 0; | ||
let totalCommits = 0; | ||
|
||
metrics.forEach(({ metrics }) => { | ||
totalPRs += metrics.prCount; | ||
totalIssues += metrics.issueCount; | ||
totalLinesAdded += metrics.linesAdded; | ||
totalLinesDeleted += metrics.linesDeleted; | ||
totalCommits += metrics.commitCount; | ||
}); | ||
|
||
const contributorsShares = metrics.map(({ metrics, info }) => { | ||
const normalizedPRs = metrics.prCount / totalPRs; | ||
const normalizedIssues = metrics.issueCount / totalIssues; | ||
const normalizedLinesAdded = metrics.linesAdded / totalLinesAdded; | ||
const normalizedLinesDeleted = metrics.linesDeleted / totalLinesDeleted; | ||
const normalizedCommits = metrics.commitCount / totalCommits; | ||
|
||
const normalizedLines = (normalizedLinesAdded + normalizedLinesDeleted) / | ||
2; | ||
|
||
const share = prWeight * normalizedPRs + | ||
issueWeight * normalizedIssues + | ||
linesWeight * normalizedLines + | ||
commitWeight * normalizedCommits; | ||
|
||
return { | ||
contributor: { | ||
id: info.user_id, | ||
wallet: info.wallet_address, | ||
artifact_namespace: info.artifact_namespace, | ||
artifact_name: info.artifact_name, | ||
}, | ||
sharePercentage: share * 100, | ||
}; | ||
}); | ||
|
||
const fundingDistribution = contributorsShares.map((contributorShare) => { | ||
return { | ||
contributor: contributorShare.contributor, | ||
allocatedFunding: +((contributorShare.sharePercentage / 100) * | ||
fundingPool).toFixed(4), | ||
}; | ||
}); | ||
|
||
fundingWeights[pool.id] = fundingDistribution; | ||
|
||
core.info(`Computed weights for pool ${pool.id}`); | ||
core.startGroup("Weights"); | ||
fundingDistribution.forEach((fundingWeight) => { | ||
core.info( | ||
`${fundingWeight.contributor.artifact_namespace}/${fundingWeight.contributor.artifact_name}: ${fundingWeight.allocatedFunding}`, | ||
); | ||
}); | ||
core.endGroup(); | ||
} | ||
|
||
return new OkResult(fundingWeights); | ||
}; |
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,58 @@ | ||
import { supabase } from "../utils/client.js"; | ||
import { Tables } from "types.js"; | ||
import { FailResult, OkResult, Result } from "typescript-monads"; | ||
import { metricsForProject, type PoolEntryMetrics } from "../utils/metrics.js"; | ||
import core from "@actions/core"; | ||
|
||
type ExtendedMetrics = { | ||
info: Tables<"pool_registrations">; | ||
metrics: PoolEntryMetrics; | ||
}; | ||
|
||
export const fetchMetricsForPool = async ( | ||
poolUuid: string, | ||
): Promise<Result<ExtendedMetrics[], Error>> => { | ||
core.info(`Fetching metrics for pool ${poolUuid}`); | ||
const { data, error } = await supabase | ||
.from("funding_pools") | ||
.select("*") | ||
.eq("id", poolUuid); | ||
if (error) { | ||
return new FailResult(error); | ||
} | ||
|
||
const [pool] = data; | ||
const metrics: ExtendedMetrics[] = []; | ||
|
||
const { data: poolData, error: poolError } = await supabase | ||
.from("pool_registrations") | ||
.select("*") | ||
.eq("pool_id", pool.id); | ||
|
||
if (poolError) { | ||
return new FailResult(poolError); | ||
} | ||
|
||
for (const project of poolData) { | ||
const projectMetric = await metricsForProject( | ||
project.artifact_namespace, | ||
project.artifact_name, | ||
); | ||
|
||
const flatMappedMetric = projectMetric.flatMap( | ||
(metric) => | ||
new OkResult({ | ||
info: project, | ||
metrics: metric, | ||
}), | ||
); | ||
|
||
if (flatMappedMetric.isFail()) { | ||
return new FailResult(flatMappedMetric.unwrapFail()); | ||
} | ||
|
||
metrics.push(flatMappedMetric.unwrap()); | ||
} | ||
|
||
return new OkResult(metrics); | ||
}; |
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 @@ | ||
export * from "./updateWeights.js"; |
Oops, something went wrong.