package market import ( "sort" "strings" "me.thuanle/bbot/internal/configs/binance" "me.thuanle/bbot/internal/utils/stringx" ) var futureSymbolPrefixPriority = append(append([]string{}, binance.SymbolPrefixList...), "") func tokenKeyFromSymbol(symbol string) string { token := strings.ToUpper(symbol) for _, prefix := range binance.SymbolPrefixList { token, _ = strings.CutPrefix(token, strings.ToUpper(prefix)) } for _, suffix := range binance.SymbolSuffixList { replaced, ok := stringx.ReplaceSuffix(token, strings.ToUpper(suffix), strings.ToUpper(binance.SymbolSuffixMap[suffix])) if ok { return replaced } } return "" } func selectCanonicalSpotSymbol(token string, candidates []string) string { return selectCanonicalSymbolByTokenOrder(token, candidates, []string{""}) } func selectCanonicalFutureSymbol(token string, candidates []string) string { return selectCanonicalSymbolByTokenOrder(token, candidates, futureSymbolPrefixPriority) } func selectCanonicalSymbolByTokenOrder(token string, candidates []string, prefixes []string) string { if len(candidates) == 0 { return "" } if len(candidates) == 1 { return strings.ToUpper(candidates[0]) } token = strings.ToUpper(token) normalized := make([]string, 0, len(candidates)) candidateSet := make(map[string]struct{}, len(candidates)) for _, candidate := range candidates { candidate = strings.ToUpper(candidate) normalized = append(normalized, candidate) candidateSet[candidate] = struct{}{} } for _, prefix := range prefixes { base := strings.ToUpper(prefix) + token if _, ok := candidateSet[base]; ok { return base } for _, suffix := range binance.SymbolSuffixList { target := base + strings.ToUpper(suffix) if _, ok := candidateSet[target]; ok { return target } replaced, ok := stringx.ReplaceSuffix(base, strings.ToUpper(binance.SymbolSuffixMap[suffix]), strings.ToUpper(suffix)) if ok { if _, exists := candidateSet[replaced]; exists { return replaced } } } } sort.Strings(normalized) return normalized[0] }