From 903ebe0c7be4205b538188ac16a52f5c02febf9b Mon Sep 17 00:00:00 2001 From: Dylan Jeffers Date: Thu, 21 May 2026 10:16:10 -0700 Subject: [PATCH] staking: migrate from discovery and fix prod issues Brings the staking service to parity with the version in apps/packages/discovery-provider/plugins/pedalboard/apps/staking and fixes a handful of issues that would have prevented it from running in prod: - Bump @audius/eth 0.1.0 -> 1.0.0. The 1.0.0 export shape changed: ClaimsManager is now a plain `{ abi, address }` object rather than a class, so `new ClaimsManager(viemClient)` was a runtime crash. Rewrite initRound to use viemClient.readContract({ abi, address, functionName }) and parallelize the three on-chain reads. - Replace `npx tsx ./src/index.ts` start script with `tsc` build + `node ./dist/index.js`, matching anti-abuse-oracle. The Dockerfile already runs `npm run build` during install, so tsx at runtime was both slower and dragged the dev toolchain into prod. - Pin the server port to 6000 (matches the nginx /plugins//... upstream) and drop the `process.env.port` fallback that no caller was setting. - /health now returns the standard `{ status: 'ok' }` shape used by the other pedalboard services instead of `{ status: 'up', port }`. The apps/dev-tools/compose/docker-compose.pedalboard.prod.yml entry was also missing the env_file/environment blocks needed to forward solana_rpc_endpoint and eth_rpc_endpoint to the container. That's fixed in a paired PR on the apps repo (AudiusProject/apps#14375) so this service actually has its RPC URLs at runtime. Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/staking/package.json | 10 +++++---- apps/staking/src/index.ts | 4 +++- apps/staking/src/routes/health.ts | 6 +++--- apps/staking/src/routes/initRound.ts | 29 ++++++++++++++++++------- package-lock.json | 32 ++++++++++++++++++++++++++-- 5 files changed, 63 insertions(+), 18 deletions(-) diff --git a/apps/staking/package.json b/apps/staking/package.json index 0330182..44161bb 100644 --- a/apps/staking/package.json +++ b/apps/staking/package.json @@ -3,16 +3,18 @@ "version": "0.0.2", "private": true, "scripts": { - "start": "npx tsx ./src/index.ts", + "build": "tsc", + "clean": "rm -rf dist", "dev": "npx tsx watch ./src/index.ts", - "test": "vitest", - "lint": "tsc --noEmit && eslint \"src/**/*.ts*\"" + "lint": "tsc --noEmit && eslint \"src/**/*.ts*\"", + "start": "node ./dist/index.js", + "test": "vitest" }, "jest": { "preset": "jest-presets/jest/node" }, "dependencies": { - "@audius/eth": "0.1.0", + "@audius/eth": "1.0.0", "@audius/sdk": "10.0.0", "@pedalboard/basekit": "*", "@pedalboard/logger": "*", diff --git a/apps/staking/src/index.ts b/apps/staking/src/index.ts index be569c4..b457781 100644 --- a/apps/staking/src/index.ts +++ b/apps/staking/src/index.ts @@ -10,6 +10,8 @@ import dotenv from 'dotenv' dotenv.config() +const PORT = 6000 + export type SharedData = { ethRpcEndpoint: string viemClient: PublicClient @@ -27,7 +29,7 @@ const main = async () => { chain: mainnet, transport: http(process.env.eth_rpc_endpoint!) }), - port: process.env.port ? parseInt(process.env.port) : 6000 + port: PORT } await new App({ appData: sharedData }) .task(async (app: App) => { diff --git a/apps/staking/src/routes/health.ts b/apps/staking/src/routes/health.ts index 1bedc4c..600a6d4 100644 --- a/apps/staking/src/routes/health.ts +++ b/apps/staking/src/routes/health.ts @@ -2,11 +2,11 @@ import { NextFunction, Request, Response } from 'express' import { App } from '@pedalboard/basekit' import { SharedData } from '..' -export const health = (app: App) => async ( - req: Request, +export const health = (_app: App) => async ( + _req: Request, res: Response, next: NextFunction ) => { - res.send({ status: 'up', port: app.viewAppData().port }) + res.send({ status: 'ok' }) next() } diff --git a/apps/staking/src/routes/initRound.ts b/apps/staking/src/routes/initRound.ts index 19ed5e8..dbf0583 100644 --- a/apps/staking/src/routes/initRound.ts +++ b/apps/staking/src/routes/initRound.ts @@ -2,7 +2,6 @@ import { NextFunction, Request, Response } from 'express' import { App } from '@pedalboard/basekit' import { SharedData } from '..' import { ClaimsManager } from '@audius/eth' -import { PublicClient } from 'viem' export const initRound = (app: App) => async ( req: Request, @@ -10,11 +9,26 @@ export const initRound = (app: App) => async ( next: NextFunction ) => { const { viemClient } = app.viewAppData() - const claimsManager = new ClaimsManager(viemClient as PublicClient) - const latestBlock = Number((await viemClient.getBlock()).number) - const lastFundedBlockNumber = Number(await claimsManager.getLastFundedBlock()) - const fundingRoundBlockDiff = Number(await claimsManager.getFundingRoundBlockDiff()) + const [latestBlock, lastFundedBlockNumber, fundingRoundBlockDiff] = + await Promise.all([ + viemClient.getBlock().then((b) => Number(b.number)), + viemClient + .readContract({ + abi: ClaimsManager.abi, + address: ClaimsManager.address, + functionName: 'getLastFundedBlock' + }) + .then(Number), + viemClient + .readContract({ + abi: ClaimsManager.abi, + address: ClaimsManager.address, + functionName: 'getFundingRoundBlockDiff' + }) + .then(Number) + ]) + const blockDiff = latestBlock - lastFundedBlockNumber if (lastFundedBlockNumber < latestBlock - 1.1 * fundingRoundBlockDiff) { @@ -23,7 +37,7 @@ export const initRound = (app: App) => async ( lastFundedBlockNumber, latestBlock, fundingRoundBlockDiff, - blockDiff, + blockDiff }) next() return @@ -34,8 +48,7 @@ export const initRound = (app: App) => async ( lastFundedBlockNumber, latestBlock, fundingRoundBlockDiff, - blockDiff, + blockDiff }) next() } - diff --git a/package-lock.json b/package-lock.json index bad7977..3a0c610 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3869,7 +3869,7 @@ "name": "@pedalboard/staking", "version": "0.0.2", "dependencies": { - "@audius/eth": "0.1.0", + "@audius/eth": "1.0.0", "@audius/sdk": "10.0.0", "@pedalboard/basekit": "*", "@pedalboard/logger": "*", @@ -3901,6 +3901,12 @@ "vitest": "0.34.6" } }, + "apps/staking/node_modules/@audius/eth": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@audius/eth/-/eth-1.0.0.tgz", + "integrity": "sha512-q7kgA7grolH6j8XV8Q13HY97Pn3kp8C0esaUxlvHoy4zWF2q2gIHhq3S/Su3hZcceY25UQ1N7a6OnJRUh0Lufw==", + "license": "Apache-2.0" + }, "apps/staking/node_modules/@audius/fixed-decimal": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@audius/fixed-decimal/-/fixed-decimal-0.2.0.tgz", @@ -3956,6 +3962,15 @@ "@solana/web3.js": "^1.95.8" } }, + "apps/staking/node_modules/@audius/sdk/node_modules/@audius/eth": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@audius/eth/-/eth-0.1.0.tgz", + "integrity": "sha512-RZ0K0xonhTVle237E2Mb1c+e4TEaqDQYCQPJtoPb6aNjcC3WU6i2i1ufIMz3sq7pGm1OSL7SzMxOE8QTrzU6cQ==", + "license": "Apache-2.0", + "dependencies": { + "viem": "2.21.21" + } + }, "apps/staking/node_modules/@audius/sdk/node_modules/@babel/runtime": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.3.tgz", @@ -51855,7 +51870,7 @@ "@pedalboard/staking": { "version": "file:apps/staking", "requires": { - "@audius/eth": "0.1.0", + "@audius/eth": "1.0.0", "@audius/sdk": "10.0.0", "@pedalboard/basekit": "*", "@pedalboard/logger": "*", @@ -51885,6 +51900,11 @@ "vitest": "0.34.6" }, "dependencies": { + "@audius/eth": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@audius/eth/-/eth-1.0.0.tgz", + "integrity": "sha512-q7kgA7grolH6j8XV8Q13HY97Pn3kp8C0esaUxlvHoy4zWF2q2gIHhq3S/Su3hZcceY25UQ1N7a6OnJRUh0Lufw==" + }, "@audius/fixed-decimal": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@audius/fixed-decimal/-/fixed-decimal-0.2.0.tgz", @@ -51932,6 +51952,14 @@ "zod": "3.21.4" }, "dependencies": { + "@audius/eth": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@audius/eth/-/eth-0.1.0.tgz", + "integrity": "sha512-RZ0K0xonhTVle237E2Mb1c+e4TEaqDQYCQPJtoPb6aNjcC3WU6i2i1ufIMz3sq7pGm1OSL7SzMxOE8QTrzU6cQ==", + "requires": { + "viem": "2.21.21" + } + }, "@babel/runtime": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.3.tgz",