package track1 import ( "context" _ "embed" "encoding/json" "math/big" "net/http" "os" "strconv" "strings" "time" ) //go:embed bridge_lanes_default.json var defaultBridgeLanesJSON []byte type bridgeLaneDefinition struct { Key string `json:"key"` ChainName string `json:"chain_name"` ChainID int64 `json:"chain_id"` ConfigReady bool `json:"config_ready"` RPCEnvs []string `json:"rpc_envs"` RPCDefault string `json:"rpc_default"` LinkToken string `json:"link_token"` WETH9Bridge string `json:"weth9_bridge"` WETH10Bridge string `json:"weth10_bridge"` } type bridgeLanesConfig struct { Updated string `json:"updated"` MinLinkWei string `json:"min_link_wei"` Lanes []bridgeLaneDefinition `json:"lanes"` } func loadBridgeLanesConfig() bridgeLanesConfig { path := strings.TrimSpace(os.Getenv("MISSION_CONTROL_BRIDGE_LANES_JSON")) if path != "" { if b, err := os.ReadFile(path); err == nil && len(b) > 0 { var cfg bridgeLanesConfig if json.Unmarshal(b, &cfg) == nil && len(cfg.Lanes) > 0 { return cfg } } } var cfg bridgeLanesConfig _ = json.Unmarshal(defaultBridgeLanesJSON, &cfg) return cfg } func resolveLaneRPC(def bridgeLaneDefinition) string { for _, key := range def.RPCEnvs { if value := strings.TrimSpace(os.Getenv(key)); value != "" { return value } } for _, row := range ParseExtraRPCProbes() { chainKey := row[2] if chainKey == strconv.FormatInt(def.ChainID, 10) { return row[1] } } return strings.TrimSpace(def.RPCDefault) } func erc20BalanceOf(ctx context.Context, rpcURL, tokenAddress, holderAddress string) (string, error) { tokenAddress = strings.ToLower(strings.TrimSpace(tokenAddress)) holderAddress = strings.ToLower(strings.TrimPrefix(strings.TrimSpace(holderAddress), "0x")) if len(holderAddress) != 40 { return "0", nil } data := "0x70a08231" + strings.Repeat("0", 24) + holderAddress raw, _, err := postJSONRPC(ctx, bridgeLaneHTTPClient(), rpcURL, "eth_call", []interface{}{ map[string]interface{}{ "to": tokenAddress, "data": data, }, "latest", }) if err != nil { return "", err } var hex string if err := json.Unmarshal(raw, &hex); err != nil { return "", err } hex = strings.TrimSpace(hex) if hex == "" || hex == "0x" { return "0", nil } value := new(big.Int) if _, ok := value.SetString(strings.TrimPrefix(hex, "0x"), 16); !ok { return "0", nil } return value.String(), nil } func bridgeLaneHTTPClient() *http.Client { return &http.Client{Timeout: 6 * time.Second} } func bridgeFundingStatus(linkBalanceWei, minLinkWei string) string { balance, okBalance := new(big.Int).SetString(strings.TrimSpace(linkBalanceWei), 10) minimum, okMin := new(big.Int).SetString(strings.TrimSpace(minLinkWei), 10) if !okBalance || !okMin { return "unknown" } if balance.Cmp(minimum) >= 0 { return "funded" } if balance.Sign() > 0 { return "degraded" } return "unfunded" } func proofStatusForLane(key string, proofs map[string]interface{}) string { if proofs == nil { return "proof-pending" } laneProofs, ok := proofs[key].([]interface{}) if !ok || len(laneProofs) == 0 { return "proof-pending" } for _, item := range laneProofs { row, ok := item.(map[string]interface{}) if !ok { continue } if tx, ok := row["tx_hash"].(string); ok && strings.TrimSpace(tx) != "" { return "proof-recorded" } } return "proof-pending" } func readProofTransfersJSON() map[string]interface{} { path := strings.TrimSpace(os.Getenv("MISSION_CONTROL_PROOF_TRANSFERS_JSON")) if path == "" { return nil } b, err := os.ReadFile(path) if err != nil || len(b) == 0 { return map[string]interface{}{"error": "unreadable or empty", "path": path} } if len(b) > 512*1024 { return map[string]interface{}{"error": "file too large", "path": path} } var payload map[string]interface{} if err := json.Unmarshal(b, &payload); err != nil { return map[string]interface{}{"error": err.Error(), "path": path} } return payload } func probeBridgeContract(ctx context.Context, rpcURL, linkToken, bridgeAddress, minLinkWei string) map[string]interface{} { result := map[string]interface{}{ "bridge": strings.TrimSpace(bridgeAddress), } if rpcURL == "" { result["status"] = "unknown" result["error"] = "rpc unavailable" return result } if linkToken == "" || bridgeAddress == "" { result["status"] = "unknown" result["error"] = "missing link token or bridge address" return result } balance, err := erc20BalanceOf(ctx, rpcURL, linkToken, bridgeAddress) if err != nil { result["status"] = "unknown" result["error"] = err.Error() return result } result["link_balance_wei"] = balance result["status"] = bridgeFundingStatus(balance, minLinkWei) return result } func aggregateLaneStatus(weth9Status, weth10Status, proofStatus string) string { statuses := []string{weth9Status, weth10Status} hasUnfunded := false hasDegraded := false hasUnknown := false for _, status := range statuses { switch status { case "unfunded": hasUnfunded = true case "degraded": hasDegraded = true case "unknown": hasUnknown = true } } if hasUnfunded { return "unfunded" } if hasDegraded { return "degraded" } if hasUnknown { return "unknown" } if proofStatus == "proof-pending" { return "proof-pending" } return "funded" } func BuildBridgeLaneHealth(ctx context.Context) (map[string]interface{}, map[string]interface{}) { cfg := loadBridgeLanesConfig() minLinkWei := strings.TrimSpace(cfg.MinLinkWei) if minLinkWei == "" { minLinkWei = "1000000000000000000" } proofPayload := readProofTransfersJSON() proofByLane := map[string]interface{}{} if proofPayload != nil { if lanes, ok := proofPayload["lanes"].(map[string]interface{}); ok { proofByLane = lanes } } lanes := make([]map[string]interface{}, 0, len(cfg.Lanes)) for _, def := range cfg.Lanes { rpcURL := resolveLaneRPC(def) weth9 := probeBridgeContract(ctx, rpcURL, def.LinkToken, def.WETH9Bridge, minLinkWei) weth10 := probeBridgeContract(ctx, rpcURL, def.LinkToken, def.WETH10Bridge, minLinkWei) weth9Status, _ := weth9["status"].(string) weth10Status, _ := weth10["status"].(string) proofStatus := proofStatusForLane(def.Key, proofByLane) lanes = append(lanes, map[string]interface{}{ "key": def.Key, "chain_name": def.ChainName, "chain_id": def.ChainID, "config_ready": def.ConfigReady, "link_token": def.LinkToken, "status": aggregateLaneStatus(weth9Status, weth10Status, proofStatus), "proof_status": proofStatus, "weth9": weth9, "weth10": weth10, "rpc_endpoint": redactRPCOrigin(rpcURL), }) } laneHealth := map[string]interface{}{ "updated_at": time.Now().UTC().Format(time.RFC3339), "min_link_wei": minLinkWei, "lanes": lanes, } return laneHealth, proofPayload }