Files
zeekayandHanzo Dev d8b8f8fa23 explorer: fold address case at the lookup boundary, and emit the token contract the SPA reads
Two defects that both fail silently, which is worse than erroring.

Every wallet emits EIP-55 checksummed addresses. The hex pattern accepts
mixed case, so a checksummed address passed validation and then matched no
row — the route answered 404, and the page rendered WLUX, a contract holding
149M LUX, as an empty EOA. The stored hash is lowercase, so the two spellings
have to fold to one key. That fold now happens once, in j()/csvHandler(),
which every route already passes through; handlers keep doing lookups and
stay in their lane. Only {hash} and {addr} fold — {id}, {pair}, {prefix} and
{item} are not hex and are case-significant.

formatToken emitted address/holders/trust_score while the SPA's TokenInfo
(luxfi/explore types/api/token.ts) reads address_hash/holders_count, so
TokensTable keyed every row on undefined and the page crashed. Renamed to
the contract rather than shimming the client, and fixed the second producer
of the same object in formatTokenTransfer, which had drifted to its own
spelling. trust_score had no consumer anywhere: TokenReputation is
'ok' | 'scam', a fraud flag, not the 0-100 completeness heuristic that
computed it — deriving one from the other would have called any token
lacking an icon a scam. reputation is null until there is a real oracle, and
the dead scorer is gone. Its toBool/toInt helpers were generic coercion
braided into a scoring file; they move to convert.go with their tests.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-07 09:00:19 -07:00

40 lines
587 B
Go

package explorer
import (
"strconv"
)
// Coercion for values scanned out of SQLite, whose driver returns int64,
// float64 or string for the same column depending on declared affinity.
func toBool(v any) bool {
switch b := v.(type) {
case bool:
return b
case int64:
return b != 0
case float64:
return b != 0
case int:
return b != 0
default:
return false
}
}
func toInt(v any) int {
switch n := v.(type) {
case int:
return n
case int64:
return int(n)
case float64:
return int(n)
case string:
i, _ := strconv.Atoi(n)
return i
default:
return 0
}
}