Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ Base URL: http://stats.filspark.com/

http://stats.filspark.com/participants/top-measurements?from=yesterday&to=yesterday

- `GET /participants/summary`

http://stats.filspark.com/participants/summary

- `GET /participant/:address/scheduled-rewards?address=<address>&from=<day>&to=<day>`

http://stats.filspark.com/participant/0x000000000000000000000000000000000000dEaD/scheduled-rewards
Expand Down
11 changes: 10 additions & 1 deletion stats/lib/platform-routes.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { json } from 'http-responders'
import { getStatsWithFilterAndCaching } from './request-helpers.js'
import {
fetchDailyStationCount,
fetchMonthlyStationCount,
fetchDailyRewardTransfers,
fetchTopEarningParticipants,
fetchParticipantsWithTopMeasurements,
fetchDailyStationMeasurementCounts
fetchDailyStationMeasurementCounts,
fetchParticipantsSummary
} from './platform-stats-fetchers.js'

const createRespondWithFetchFn = (pathname, searchParams, res) => (pgPool, fetchFn) => {
Expand Down Expand Up @@ -36,10 +38,17 @@ export const handlePlatformRoutes = async (req, res, pgPools) => {
await respond(pgPools.evaluate, fetchParticipantsWithTopMeasurements)
} else if (req.method === 'GET' && url === '/participants/top-earning') {
await respond(pgPools.stats, fetchTopEarningParticipants)
} else if (req.method === 'GET' && url === '/participants/summary') {
await respondWithParticipantsSummary(res, pgPools)
} else if (req.method === 'GET' && url === '/transfers/daily') {
await respond(pgPools.stats, fetchDailyRewardTransfers)
} else {
return false
}
return true
}

export const respondWithParticipantsSummary = async (res, pgPools) => {
res.setHeader('cache-control', `public, max-age=${24 * 3600 /* one day */}`)
json(res, await fetchParticipantsSummary(pgPools.evaluate))
}
12 changes: 12 additions & 0 deletions stats/lib/platform-stats-fetchers.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,15 @@ export const fetchTopEarningParticipants = async (pgPool, filter) => {
`, [filter.from, filter.to])
return rows
}

/**
* @param {Queryable} pgPool
*/
export const fetchParticipantsSummary = async (pgPool) => {
const { rows } = await pgPool.query(`
SELECT COUNT(DISTINCT participant_id) FROM daily_participants
`)
return {
participant_count: Number(rows[0].count)
}
}
24 changes: 24 additions & 0 deletions stats/test/platform-routes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { getPgPools } from '@filecoin-station/spark-stats-db'
import { assertResponseStatus, getPort } from './test-helpers.js'
import { createHandler } from '../lib/handler.js'
import { getLocalDayAsISOString, today, yesterday } from '../lib/request-helpers.js'
import { givenDailyParticipants } from '@filecoin-station/spark-stats-db/test-helpers.js'

const debug = createDebug('test')

Expand Down Expand Up @@ -338,6 +339,29 @@ describe('Platform Routes HTTP request handler', () => {
await assertResponseStatus(res, 400)
})
})

describe('GET /participants/summary', () => {
it('counts participants', async () => {
await givenDailyParticipants(
pgPools.evaluate,
'2000-01-01',
['0x1', '0x2', '0x3']
)

const res = await fetch(
new URL('/participants/summary', baseUrl), {
redirect: 'manual'
}
)
await assertResponseStatus(res, 200)
const summary = await res.json()
assert.deepStrictEqual(summary, { participant_count: 3 })
assert.strictEqual(
res.headers.get('cache-control'),
'public, max-age=86400'
)
})
})
})

const givenDailyMeasurementsSummary = async (pgPoolEvaluate, summaryData) => {
Expand Down