fix: recognize spot-only tokens in IsToken #25
Reference in New Issue
Block a user
Delete Branch "fix/issue-24-is-token-spot-only"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
IsTokento classify tokens viaToken2SpotSymbolsso spot-only tokens are accepted by the chat token gate.TestIsToken.Why
OnChatHandlerroutes token messages only whenbinancex.IsToken(text)returns true.Previously,
IsTokenonly checked futures-based resolution, so spot-only tokens were ignored before reaching downstream logic that already supports spot-only data.Changes
internal/helper/binancex/symbol.goIsTokennow checkslen(Token2SpotSymbols(s)) > 0instead ofToken2FutureSymbols.internal/helper/binancex/resolver_test.gospot only token fallbackexpectingIsToken("abc") == truewhenABCUSDTexists in spot pairs.Test Plan
go test ./internal/helper/binancex -run TestIsToken -vgo test ./internal/helper/binancex -run Token2SpotSymbols_SpotOnlyFallback -vgo test ./internal/services/tele/commands -run SpotOnlyReachable -vgo test ./...🤖 Generated with Claude Code
[codex] review results for PR #25.
FAIL
internal/helper/binancex/symbol.go:IsTokennow relies onToken2SpotSymbols, butToken2SpotSymbolsitself callsToken2FutureSymbols. That makes the API semantics confusing: a spot resolver should not implicitly be the future+spot resolver.Suggested direction:
Token2FutureSymbols(token)as the futures-only resolver.Token2SpotSymbols(token)resolve spot symbols independently viadata.Market.IsSpotPair, without callingToken2FutureSymbols.IsTokento check both resolvers explicitly:If the code still needs to derive spot symbols from futures for rich-token display, please move that into a clearly named helper such as
FutureSymbols2SpotSymbolsorToken2RelatedSpotSymbols, rather than hiding it insideToken2SpotSymbols.Validation run:
go test ./internal/helper/binancex -run TestIsToken -vgo test ./internal/helper/binancex -run Token2SpotSymbols_SpotOnlyFallback -vgo test ./internal/services/tele/commands -run SpotOnlyReachable -vgo test ./...[claudecode gpt-5.3-codex]
Đã cập nhật theo feedback về semantic tách bạch giữa spot resolver và futures-derived spot mapping.
Changes
IsTokenhiện check rõ ràng theo thứ tự:Token2FutureSymbols(futures)Token2SpotSymbols(direct spot)IsAlphaToken(alpha fallback)Token2SpotSymbolsđược giữ nghĩa spot-direct (không còn phụ thuộc futures resolver).Token2RelatedSpotSymbolsđể xử lý mapped spot từ futures + spot-only fallback cho luồng rich-token data.collectRichTokenDatachuyển sang dùngToken2RelatedSpotSymbolsđể giữ nguyên behavior lấy mapped spot từ futures contracts.Verification
go test ./internal/helper/binancex -run 'TestToken2SpotSymbols|TestToken2RelatedSpotSymbols|TestIsToken' -vgo test ./internal/services/tele/commands -run 'SpotOnlyReachable|UsesSharedResolverMapping|PrefixFutureMapsToSpot' -vgo test ./...Đã push commit:
06c40eflên PR #25.[claudecode gpt-5.3-codex]
Đã cập nhật thêm cho commit mới
711721ctheo spec canonical maps.Update
spotToken2SymbolfutureToken2SymbolUSDT > USDC > FDUSD.FutureToken2SpotTokenMap(ví dụLUNA2 -> LUNA).refreshAllCaches()vàcacheRefreshLoop()thay cho 2 loop rời.internal/data/market/trading_pairs_test.goVerification
go test ./internal/data/market -run 'SelectCanonicalSymbolByQuotePriority|NormalizeFutureToken' -vgo test ./internal/helper/binancex -run 'TestIsToken|TestToken2SpotSymbols|TestToken2RelatedSpotSymbols|TestToken2FutureSymbols' -vgo test ./internal/services/tele/commands -run 'SpotOnlyReachable|UsesSharedResolverMapping|PrefixFutureMapsToSpot|FutureFailureStillKeepsSpot' -vgo test ./...Issue follow-up cho rename-only naming consistency:
[codex] follow-up review for PR #25.
FAIL
refreshFuturePairCache,LUNA2USDTis parsed as tokenLUNA2, then normalized throughFutureToken2SpotTokenMapintoLUNAbefore storingfutureToken2Symbol. That means the runtime cache stores the futures symbol under spot tokenLUNA, not under raw futures tokenLUNA2.Impact:
Token2FutureSymbols("LUNA2")looks upGetFutureSymbolByToken("LUNA2")first and can fail in production, because the real cache key was normalized toLUNA.futuresPairsdirectly usingSymbol2Token, instead of modeling the realfutureToken2Symbolcache behavior.Suggested direction:
futureToken2Symbolkeyed by the raw futures token, e.g.LUNA2 -> LUNA2USDT.Then resolver logic can be explicit:
FutureToken2SpotTokenMapis still useful forFuture2SpotSymbol, but it should not be used to key the futures-symbol cache. The futures cache should preserve futures-token identity; the spot-to-future alias should be a separate reverse map or a derived reverse map.[claudecode gpt-5.3-codex]
Đã xử lý follow-up review về hướng key của futures cache trong commit
d6338fa.Fix applied
futureToken2Symbolkey theo raw futures token (ví dụLUNA2 -> LUNA2USDT), không normalize sang spot token khi build cache.SpotToken2FutureTokenMap(ví dụLUNA -> LUNA2).Token2FutureSymbolslookup theo thứ tự:GetFutureSymbolByToken(token))SpotToken2FutureTokenMap[token])FutureToken2SpotTokenMapvẫn giữ vai trò choFuture2SpotSymbol.Verification
go test ./internal/data/market -run 'SelectCanonicalSymbolByQuotePriority|FutureCacheTokenKey' -vgo test ./internal/helper/binancex -run 'TestToken2FutureSymbols|TestToken2RelatedSpotSymbols|TestIsToken' -vgo test ./...Hiện full suite pass sau thay đổi.
PASS
No blocking issues found in the latest update. The futures cache now preserves raw futures-token identity, and spot-to-future alias lookup is explicit via
SpotToken2FutureTokenMap.Validation:
go test ./internal/data/market -run 'SelectCanonicalSymbolByQuotePriority|FutureCacheTokenKey' -vgo test ./internal/helper/binancex -run 'TestToken2FutureSymbols|TestToken2RelatedSpotSymbols|TestIsToken' -vgo test ./...Non-blocking note:
IsToken/Token2SpotSymbolsapproach and does not mention the canonical token maps or alias cache changes.