Skip to content

Commit 0a4114d

Browse files
authored
fix: validate WFAIR reserves response (#14)
1 parent 564618e commit 0a4114d

1 file changed

Lines changed: 46 additions & 1 deletion

File tree

src/hooks/use-wfair-reserves.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,47 @@ export type ReservesResult =
1919
| { status: 'ok'; data: ReservesSnapshot }
2020
| { status: 'unavailable' }
2121

22+
const INTEGER_STRING_PATTERN = /^-?\d+$/
23+
24+
function isRecord(value: unknown): value is Record<string, unknown> {
25+
return typeof value === 'object' && value !== null && !Array.isArray(value)
26+
}
27+
28+
function isIntegerString(value: unknown): value is string {
29+
return typeof value === 'string' && INTEGER_STRING_PATTERN.test(value)
30+
}
31+
32+
function isValidDateString(value: unknown): value is string {
33+
return typeof value === 'string' && !Number.isNaN(Date.parse(value))
34+
}
35+
36+
function parseReservesSnapshot(value: unknown): ReservesSnapshot | null {
37+
if (!isRecord(value)) {
38+
return null
39+
}
40+
41+
const { at, fairCustodySats, wfairSupplyWei, deltaSats, pegHealthy } = value
42+
if (
43+
!isValidDateString(at) ||
44+
!isIntegerString(fairCustodySats) ||
45+
!isIntegerString(wfairSupplyWei) ||
46+
!isIntegerString(deltaSats) ||
47+
typeof pegHealthy !== 'boolean'
48+
) {
49+
return null
50+
}
51+
52+
try {
53+
BigInt(fairCustodySats)
54+
BigInt(wfairSupplyWei)
55+
BigInt(deltaSats)
56+
} catch {
57+
return null
58+
}
59+
60+
return { at, fairCustodySats, wfairSupplyWei, deltaSats, pegHealthy }
61+
}
62+
2263
export function useWfairReserves() {
2364
return useQuery<ReservesResult>({
2465
queryKey: ['wfair', 'reserves', RESERVES_ENDPOINT],
@@ -31,7 +72,11 @@ export function useWfairReserves() {
3172
if (!response.ok) {
3273
return { status: 'unavailable' }
3374
}
34-
const data = (await response.json()) as ReservesSnapshot
75+
const data = parseReservesSnapshot(await response.json())
76+
if (!data) {
77+
console.warn('[wfair-reserves] reserves API returned invalid data')
78+
return { status: 'unavailable' }
79+
}
3580
return { status: 'ok', data }
3681
} catch (error) {
3782
console.error('[wfair-reserves] reserves API unreachable:', error)

0 commit comments

Comments
 (0)