fix: validate Cashu token format before placing bets (BUG-S4)

Added getDecodedToken validation that rejects malformed tokens with
400 before any DB lookups. Tests cover empty, non-base64, truncated,
and random base64 tokens.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-12 22:46:24 +00:00
co-authored by Claude Opus 4.6
parent c6a54d63c4
commit e4a7f47e0f
2 changed files with 58 additions and 0 deletions
+50
View File
@@ -0,0 +1,50 @@
import { describe, it, expect } from 'vitest'
import { Hono } from 'hono'
import { betsRouter } from './bets.js'
const app = new Hono()
app.route('/api/bets', betsRouter)
async function placeBet(cashuToken: string) {
return app.request('/api/bets/place', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
fightId: 'test-fight',
pubkey: 'deadbeef',
botId: 'test-bot',
amountSats: 100,
cashuToken,
}),
})
}
describe('bets cashu token validation', () => {
it('rejects empty string token', async () => {
const res = await placeBet('')
// Empty string fails the required fields check first
expect(res.status).toBe(400)
})
it('rejects non-base64 garbage token', async () => {
const res = await placeBet('not-a-valid-cashu-token!!!')
expect(res.status).toBe(400)
const json = await res.json() as { error: string }
expect(json.error).toBe('Invalid Cashu token format.')
})
it('rejects truncated token', async () => {
// A truncated token that starts like cashu but is incomplete
const res = await placeBet('cashuAey')
expect(res.status).toBe(400)
const json = await res.json() as { error: string }
expect(json.error).toBe('Invalid Cashu token format.')
})
it('rejects random base64 that is not cashu format', async () => {
const res = await placeBet('eyJhbGciOiJIUzI1NiJ9')
expect(res.status).toBe(400)
const json = await res.json() as { error: string }
expect(json.error).toBe('Invalid Cashu token format.')
})
})