af3895de79
* Calculate quadratic funding match * Tweak copy * More concise quadratic funding calculation Co-authored-by: Sinclair Chen <abc.sinclair@gmail.com> * Fix imports and calculations * Remove unused var for now * Clean up styling Co-authored-by: Sinclair Chen <abc.sinclair@gmail.com>
28 lines
995 B
TypeScript
28 lines
995 B
TypeScript
import { groupBy, mapValues, sum, sumBy } from 'lodash'
|
|
import { Txn } from './txn'
|
|
|
|
// Returns a map of charity ids to the amount of M$ matched
|
|
export function quadraticMatches(
|
|
allCharityTxns: Txn[],
|
|
matchingPool: number
|
|
): Record<string, number> {
|
|
// For each charity, group the donations by each individual donor
|
|
const donationsByCharity = groupBy(allCharityTxns, 'toId')
|
|
const donationsByDonors = mapValues(donationsByCharity, (txns) =>
|
|
groupBy(txns, 'fromId')
|
|
)
|
|
|
|
// Weight for each charity = [sum of sqrt(individual donor)] ^ 2
|
|
const weights = mapValues(donationsByDonors, (byDonor) => {
|
|
const sumByDonor = Object.values(byDonor).map((txns) =>
|
|
sumBy(txns, 'amount')
|
|
)
|
|
const sumOfRoots = sumBy(sumByDonor, Math.sqrt)
|
|
return sumOfRoots ** 2
|
|
})
|
|
|
|
// Then distribute the matching pool based on the individual weights
|
|
const totalWeight = sum(Object.values(weights))
|
|
return mapValues(weights, (weight) => matchingPool * (weight / totalWeight))
|
|
}
|