[econ] add getBalance endpoint

This commit is contained in:
Devin Zuczek
2026-10-15 13:04:39 -04:00
parent e7ee9ed444
commit 2a9ff1337a
3 changed files with 98 additions and 7 deletions
+54
View File
@@ -139,6 +139,7 @@ import {
RemoveInfluencerBody,
RoomConsumableDto,
RoomConsumableEnvelope,
RoomCurrencyBalance,
RoomCurrencyDto,
RoomCurrencyEnvelope,
RoomCurrencyPurchaseOfferDto,
@@ -4586,6 +4587,59 @@ const app = new Hono<App>({ strict: false })
c.json([])
)
// What one player holds of one room currency. Any signed-in caller may read any player's,
// as the query names the player rather than taking the caller.
.get(
'/api/roomcurrencies/v1/getBalance',
describeRoute({
tags: ['Econ'],
summary: 'A player’s balance of one room currency',
description: [
'What the player named by `accountId` holds of the room currency `currencyId`',
'(`room_balance`). A player who has never earned any — and a currency that does not',
'exist — is a `Balance` of 0, not a 404.',
'',
'`ModifiedAt` is the time of the response: `room_balance` keeps no modification time.',
'A missing `currencyId` or a non-integer `accountId` is a 400.',
].join('\n'),
security: AUTHED,
parameters: [
{
name: 'currencyId',
in: 'query',
required: true,
description: 'The room currency',
schema: { type: 'string' },
},
{
name: 'accountId',
in: 'query',
required: true,
description: 'The player whose balance to read',
schema: { type: 'integer' },
},
],
responses: {
200: json(RoomCurrencyBalance, 'The player’s balance'),
400: { description: 'A missing `currencyId` or a non-integer `accountId`' },
401: UNAUTHORIZED_RESPONSE,
},
}),
async (c) => {
if ((await authedId(c)) === null) return unauthorized(c)
const currencyId = c.req.query('currencyId')?.trim() ?? ''
const rawAccountId = c.req.query('accountId')?.trim() ?? ''
if (currencyId === '' || !/^\d+$/.test(rawAccountId)) return c.body(null, 400)
const accountId = Number(rawAccountId)
return c.json({
AccountId: accountId,
CurrencyId: currencyId,
Balance: await getRoomBalance(c.env.DB, currencyId, accountId),
ModifiedAt: new Date().toISOString(),
})
}
)
// Buy room currency with tokens, through one of the currency's purchase offers. The body
// names only the OFFER — which currency it sells is whichever one lists it — and the
// amount and price the client rendered, both of which must still match the offer.