diff --git a/api/resolvers/rewards.js b/api/resolvers/rewards.js index 19450237..8d701010 100644 --- a/api/resolvers/rewards.js +++ b/api/resolvers/rewards.js @@ -27,7 +27,7 @@ async function getActiveRewards (models) { return await models.$queryRaw` SELECT (sum(total) / 1000)::INT as total, - date_trunc('month', (now() AT TIME ZONE 'America/Chicago') + interval '1 month') AT TIME ZONE 'America/Chicago' as time, + date_trunc('day', (now() AT TIME ZONE 'America/Chicago') + interval '1 day') AT TIME ZONE 'America/Chicago' as time, json_build_array( json_build_object('name', 'donations', 'value', (sum(donations) / 1000)::INT), json_build_object('name', 'fees', 'value', (sum(fees) / 1000)::INT), @@ -36,10 +36,6 @@ async function getActiveRewards (models) { json_build_object('name', 'anon''s stack', 'value', (sum(anons_stack) / 1000)::INT) ) AS sources FROM ( - (SELECT * - FROM rewards_days - WHERE rewards_days.t >= date_trunc('month', now() AT TIME ZONE 'America/Chicago')) - UNION ALL (SELECT * FROM rewards_today) UNION ALL (SELECT * FROM @@ -79,8 +75,8 @@ async function getRewards (when, models) { throw new GraphQLError('bad date range', { extensions: { code: 'BAD_USER_INPUT' } }) } - if (new Date(when[0]).getTime() > new Date('2024-03-01').getTime()) { - // after 3/1/2024, we reward monthly on the 1st + if (new Date(when[0]).getTime() > new Date('2024-03-01').getTime() && new Date(when[0]).getTime() < new Date('2024-05-02').getTime()) { + // after 3/1/2024 and until 5/1/2024, we reward monthly on the 1st if (new Date(when[0]).getUTCDate() !== 1) { throw new GraphQLError('invalid reward date', { extensions: { code: 'BAD_USER_INPUT' } }) } @@ -159,8 +155,8 @@ export default { leaderboard: async (parent, args, { models, ...context }) => { // get to and from using postgres because it's easier to do there const [{ to, from }] = await models.$queryRaw` - SELECT date_trunc('month', (now() AT TIME ZONE 'America/Chicago')) AT TIME ZONE 'America/Chicago' as from, - (date_trunc('month', (now() AT TIME ZONE 'America/Chicago')) AT TIME ZONE 'America/Chicago') + interval '1 month - 1 second' as to` + SELECT date_trunc('day', (now() AT TIME ZONE 'America/Chicago')) AT TIME ZONE 'America/Chicago' as from, + (date_trunc('day', (now() AT TIME ZONE 'America/Chicago')) AT TIME ZONE 'America/Chicago') + interval '1 day - 1 second' as to` return await topUsers(parent, { when: 'custom', to: new Date(to).getTime().toString(), from: new Date(from).getTime().toString(), limit: 100 }, { models, ...context }) } }, diff --git a/components/countdown.js b/components/countdown.js index cd4c48f5..3fa328ba 100644 --- a/components/countdown.js +++ b/components/countdown.js @@ -37,7 +37,7 @@ export function CompactLongCountdown (props) { {...props} formatter={props => { return ( <> - {props.formatted.days + {Number(props.formatted.days) > 0 ? ` ${props.formatted.days}d ${props.formatted.hours}h ${props.formatted.minutes}m ${props.formatted.seconds}s` : ` ${props.formatted.hours}:${props.formatted.minutes}:${props.formatted.seconds}`} diff --git a/lib/madness.js b/lib/madness.js index e5451d9b..185c2ee3 100644 --- a/lib/madness.js +++ b/lib/madness.js @@ -1,101 +1,22 @@ export const proportions = [ - 0.08122, - 0.07, - 0.06, - 0.05, - 0.045, - 0.04, - 0.035, - 0.03, - 0.029, - 0.028, - 0.027, - 0.026, - 0.025, - 0.024, - 0.023, - 0.022, - 0.021, - 0.02, - 0.019, - 0.018, - 0.017, - 0.016, - 0.015, - 0.014, - 0.013, - 0.012, - 0.011, - 0.01, - 0.009, - 0.0083, - 0.0077, - 0.0074, - 0.0071, - 0.0068, - 0.0065, - 0.0063, - 0.0061, - 0.0059, - 0.0057, - 0.0055, - 0.0053, - 0.0051, - 0.0049, - 0.0047, - 0.0045, - 0.0043, - 0.0041, - 0.0039, - 0.0037, - 0.0036, - 0.0035, - 0.0034, - 0.0033, - 0.0032, - 0.0031, - 0.003, - 0.0029, - 0.0028, - 0.0027, - 0.0026, - 0.0025, - 0.0024, - 0.0023, - 0.0022, - 0.0021, - 0.002, - 0.0019, - 0.0018, - 0.0017, - 0.0016, - 0.0015, - 0.0014, - 0.0013, - 0.0012, - 0.0011, - 0.001, - 0.0009, - 0.0008, - 0.00078, - 0.00076, - 0.00074, - 0.00072, - 0.0007, - 0.00068, - 0.00066, - 0.00064, - 0.00062, - 0.0006, - 0.00058, - 0.00056, - 0.00054, - 0.00052, - 0.0005, - 0.00048, - 0.00046, - 0.00044, - 0.00042, - 0.0004, - 0.00038 + 0.07575508, 0.06619601, 0.05835029, 0.05183037, 0.0463526, + 0.04170543, 0.0377285, 0.03429843, 0.03131904, 0.02871442, + 0.02642405, 0.02439916, 0.0226001, 0.0209944, 0.01955519, + 0.01826016, 0.0170906, 0.01603075, 0.01506725, 0.01418874, + 0.01338546, 0.01264904, 0.01197222, 0.01134872, 0.01077306, + 0.01024046, 0.0097467, 0.00928808, 0.00886135, 0.00846359, + 0.00809223, 0.00774497, 0.00741977, 0.0071148, 0.00682839, + 0.00655908, 0.00630551, 0.00606648, 0.0058409, 0.00562778, + 0.0054262, 0.00523534, 0.00505446, 0.00488287, 0.00471994, + 0.0045651, 0.00441782, 0.0042776, 0.00414401, 0.00401663, + 0.00389509, 0.00377902, 0.00366811, 0.00356204, 0.00346055, + 0.00336337, 0.00327026, 0.003181, 0.00309537, 0.00301318, + 0.00293424, 0.0028584, 0.00278548, 0.00271534, 0.00264783, + 0.00258284, 0.00252022, 0.00245988, 0.00240169, 0.00234556, + 0.00229139, 0.0022391, 0.00218858, 0.00213978, 0.00209259, + 0.00204697, 0.00200283, 0.00196012, 0.00191877, 0.00187873, + 0.00183994, 0.00180234, 0.0017659, 0.00173056, 0.00169628, + 0.00166301, 0.00163072, 0.00159937, 0.00156893, 0.00153935, + 0.00151061, 0.00148267, 0.00145551, 0.00142909, 0.00140339, + 0.00137839, 0.00135405, 0.00133035, 0.00130728, 0.00128481 ] diff --git a/pages/rewards/index.js b/pages/rewards/index.js index 021f397f..92a2b965 100644 --- a/pages/rewards/index.js +++ b/pages/rewards/index.js @@ -108,11 +108,10 @@ export default function Rewards ({ ssrData }) { if (!dat) return function EstimatedReward ({ rank }) { - const totalRest = total - 1000000 return (
- estimated reward: {numWithUnits(rank === 1 ? 1000000 : Math.floor(totalRest * proportions[rank - 2]))} + estimated reward: {numWithUnits(Math.floor(total * proportions[rank - 1]))}
) @@ -120,10 +119,9 @@ export default function Rewards ({ ssrData }) { return ( - +

- bitcoin++ is a developer-focused conference series. -
Join us in Austin May 1-4 for a deep dive into bitcoin script.
+ rewards are sponsored by ... we are hiring

diff --git a/pages/~/index.js b/pages/~/index.js index dcd9c913..b2b5162b 100644 --- a/pages/~/index.js +++ b/pages/~/index.js @@ -7,7 +7,6 @@ import Snl from '@/components/snl' import { useQuery } from '@apollo/client' import PageLoading from '@/components/page-loading' import TerritoryHeader from '@/components/territory-header' -import Link from 'next/link' export const getServerSideProps = getGetServerSideProps({ query: SUB_ITEMS, @@ -30,14 +29,6 @@ export default function Sub ({ ssrData }) { <> )} - - - Million Sat Madness - is sponsored by{' '} - - the Bitcoin++ Conference in Austin May 1-4 - -
) diff --git a/prisma/migrations/20240501141206_daily_earn_job/migration.sql b/prisma/migrations/20240501141206_daily_earn_job/migration.sql new file mode 100644 index 00000000..d80ec3f0 --- /dev/null +++ b/prisma/migrations/20240501141206_daily_earn_job/migration.sql @@ -0,0 +1,15 @@ +CREATE OR REPLACE FUNCTION reschedule_earn_job() +RETURNS INTEGER +LANGUAGE plpgsql +AS $$ +DECLARE +BEGIN + UPDATE pgboss.schedule set cron = '0 0 * * *' WHERE name = 'earn'; + return 0; +EXCEPTION WHEN OTHERS THEN + return 0; +END; +$$; + +SELECT reschedule_earn_job(); +DROP FUNCTION IF EXISTS reschedule_earn_job; \ No newline at end of file diff --git a/worker/earn.js b/worker/earn.js index 1ac27b4b..85c73333 100644 --- a/worker/earn.js +++ b/worker/earn.js @@ -4,18 +4,17 @@ import { PrismaClient } from '@prisma/client' import { proportions } from '@/lib/madness.js' import { SN_NO_REWARDS_IDS } from '@/lib/constants.js' -const TOTAL_UPPER_BOUND_MSATS = 10000000000 +const TOTAL_UPPER_BOUND_MSATS = 1_000_000_000 export async function earn ({ name }) { // grab a greedy connection const models = new PrismaClient() try { - // compute how much sn earned got the month + // compute how much sn earned yesterday const [{ sum: sumDecimal }] = await models.$queryRaw` - SELECT coalesce(sum(total), 0) as sum - FROM rewards_days - WHERE date_trunc('month', rewards_days.t) = date_trunc('month', (now() AT TIME ZONE 'America/Chicago' - interval '1 month'))` + SELECT total as sum + FROM rewards(now() AT TIME ZONE 'America/Chicago' - interval '1 day', now() AT TIME ZONE 'America/Chicago' - interval '1 day', '1 day'::INTERVAL, 'day')` // XXX primsa will return a Decimal (https://mikemcl.github.io/decimal.js) // because sum of a BIGINT returns a NUMERIC type (https://www.postgresql.org/docs/13/functions-aggregate.html) @@ -52,11 +51,9 @@ export async function earn ({ name }) { // get earners { userId, id, type, rank, proportion } const earners = await models.$queryRaw` - SELECT id AS "userId", sum(proportion) as proportion, ROW_NUMBER() OVER (ORDER BY sum(proportion) DESC) as rank - FROM user_values_days - WHERE date_trunc('month', user_values_days.t) = date_trunc('month', (now() AT TIME ZONE 'America/Chicago' - interval '1 month')) - AND NOT (id = ANY (${SN_NO_REWARDS_IDS})) - GROUP BY id + SELECT id AS "userId", proportion, ROW_NUMBER() OVER (ORDER BY proportion DESC) as rank + FROM user_values_days(now() AT TIME ZONE 'America/Chicago' - interval '1 day', now() AT TIME ZONE 'America/Chicago' - interval '1 day', '1 day'::INTERVAL, 'day') + WHERE NOT (id = ANY (${SN_NO_REWARDS_IDS})) ORDER BY proportion DESC LIMIT 100` @@ -69,14 +66,7 @@ export async function earn ({ name }) { const notifications = {} for (const [i, earner] of earners.entries()) { - let earnings = 0 - if (i === 0) { - // top earner gets 1m sats - earnings = 1_000_000_000 - } else { - // everyone else gets a proportion of the total - earnings = Math.floor(parseFloat(proportions[i - 1] * (sum - 1_000_000_000))) - } + const earnings = Math.floor(parseFloat(proportions[i] * sum)) total += earnings if (total > sum) { console.log(name, 'total exceeds sum', total, '>', sum)