package chain import ( "strings" "github.com/tech/sendico/pkg/merrors" chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1" ) func AssetString(asset *chainv1.Asset) string { if asset == nil { return "" } symbol := strings.ToUpper(strings.TrimSpace(asset.GetTokenSymbol())) if symbol == "" { return "" } suffix := assetSuffix(asset.GetChain()) if suffix == "" { return symbol } return symbol + "-" + suffix } func ParseAsset(assetString, network, tokenSymbol, contractAddress string) (*chainv1.Asset, error) { token := strings.TrimSpace(tokenSymbol) net := strings.TrimSpace(network) contract := strings.TrimSpace(contractAddress) if token == "" { token = TokenFromAssetString(assetString) } if net == "" { net = NetworkFromAssetString(assetString) } if token == "" { return nil, merrors.InvalidArgument("asset: token_symbol is required") } chain := NetworkFromString(net) if chain == chainv1.ChainNetwork_CHAIN_NETWORK_UNSPECIFIED { return nil, merrors.InvalidArgument("asset: network is required") } return &chainv1.Asset{ Chain: chain, TokenSymbol: strings.ToUpper(token), ContractAddress: strings.ToLower(contract), }, nil } func TokenFromAssetString(asset string) string { trimmed := strings.TrimSpace(asset) if trimmed == "" { return "" } if idx := strings.Index(trimmed, "-"); idx > 0 { return trimmed[:idx] } return trimmed } func NetworkFromAssetString(asset string) string { trimmed := strings.TrimSpace(asset) if trimmed == "" { return "" } idx := strings.Index(trimmed, "-") if idx < 0 { return "" } return strings.TrimSpace(trimmed[idx+1:]) } func NetworkName(chain chainv1.ChainNetwork) string { if chain == chainv1.ChainNetwork_CHAIN_NETWORK_UNSPECIFIED { return "" } if name, ok := chainv1.ChainNetwork_name[int32(chain)]; ok { return strings.TrimPrefix(name, "CHAIN_NETWORK_") } return "" } func NetworkAlias(chain chainv1.ChainNetwork) string { switch chain { case chainv1.ChainNetwork_CHAIN_NETWORK_ETHEREUM_MAINNET: return "ETH" case chainv1.ChainNetwork_CHAIN_NETWORK_TRON_MAINNET: return "TRON" case chainv1.ChainNetwork_CHAIN_NETWORK_TRON_NILE: return "TRON_NILE" case chainv1.ChainNetwork_CHAIN_NETWORK_ARBITRUM_ONE: return "ARBITRUM" default: name := NetworkName(chain) if name == "" { fallback := strings.TrimPrefix(strings.TrimSpace(chain.String()), "CHAIN_NETWORK_") return strings.ToUpper(fallback) } return strings.ToUpper(name) } } func NetworkFromString(value string) chainv1.ChainNetwork { normalized := normalizeNetworkString(value) if normalized == "" { return chainv1.ChainNetwork_CHAIN_NETWORK_UNSPECIFIED } if val, ok := chainv1.ChainNetwork_value[normalized]; ok { return chainv1.ChainNetwork(val) } switch normalized { case "ETH", "ETHEREUM", "ETH_MAINNET": return chainv1.ChainNetwork_CHAIN_NETWORK_ETHEREUM_MAINNET case "TRON": return chainv1.ChainNetwork_CHAIN_NETWORK_TRON_MAINNET case "TRON_NILE": return chainv1.ChainNetwork_CHAIN_NETWORK_TRON_NILE case "ARB", "ARBITRUM": return chainv1.ChainNetwork_CHAIN_NETWORK_ARBITRUM_ONE } if !strings.HasPrefix(normalized, "CHAIN_NETWORK_") { normalized = "CHAIN_NETWORK_" + normalized } if val, ok := chainv1.ChainNetwork_value[normalized]; ok { return chainv1.ChainNetwork(val) } return chainv1.ChainNetwork_CHAIN_NETWORK_UNSPECIFIED } func normalizeNetworkString(value string) string { trimmed := strings.TrimSpace(value) if trimmed == "" { return "" } normalized := strings.ToUpper(trimmed) normalized = strings.ReplaceAll(normalized, " ", "_") normalized = strings.ReplaceAll(normalized, "-", "_") return normalized } func assetSuffix(chain chainv1.ChainNetwork) string { switch chain { case chainv1.ChainNetwork_CHAIN_NETWORK_ETHEREUM_MAINNET: return "ETH" case chainv1.ChainNetwork_CHAIN_NETWORK_ARBITRUM_ONE: return "ARB" case chainv1.ChainNetwork_CHAIN_NETWORK_TRON_MAINNET: return "TRC20" case chainv1.ChainNetwork_CHAIN_NETWORK_TRON_NILE: return "TRC20" default: return "" } }