Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions contracts/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ ignition/deployments/chain-31337
broadcast
contracts/coverage_report
coverage_report
config-local

2 changes: 1 addition & 1 deletion services/bridge/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build stage
FROM golang:1.24-alpine AS builder
FROM golang:1.25-alpine AS builder

# Install dependencies
RUN apk add --no-cache git
Expand Down
1 change: 1 addition & 0 deletions services/bridge/config/event_definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ type LegacyRouterDestination struct {
Method DestinationMethodConfig `json:"method"`
Condition string `json:"condition"`
TimeThreshold Duration `json:"time_threshold,omitempty"` // Minimum time between updates for this destination
Cron bool `json:"cron,omitempty"` // Enable cron-based updates for this destination
}

// DestinationMethodConfig defines a contract method call for generic routing
Expand Down
2 changes: 2 additions & 0 deletions services/bridge/config/modular_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type InfrastructureConfig struct {
Metrics MetricsConfig `yaml:"metrics" json:"metrics"`
Replica *ReplicaConfig `yaml:"replica,omitempty" json:"replica,omitempty"`
DryRun bool `yaml:"dry_run,omitempty" json:"dry_run,omitempty"`
CronService CronServiceConfig `yaml:"cron_service" json:"cron_service"`
}

type ChainConfig struct {
Expand Down Expand Up @@ -91,6 +92,7 @@ type RouterDestination struct {
Condition string `yaml:"condition,omitempty" json:"condition,omitempty"`
TimeThreshold Duration `yaml:"time_threshold,omitempty" json:"time_threshold,omitempty"`
PriceDeviation string `yaml:"price_deviation,omitempty" json:"price_deviation,omitempty"` // e.g., "0.5%" or "1.0%"
Cron bool `yaml:"cron,omitempty" json:"cron,omitempty"` // Enable cron-based updates for this destination

// Gas configuration (from modular version)
GasLimit uint64 `yaml:"gas_limit,omitempty" json:"gas_limit,omitempty"`
Expand Down
8 changes: 8 additions & 0 deletions services/bridge/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Config struct {
API APIConfig `json:"api"`
Metrics MetricsConfig `json:"metrics"`
DryRun bool `json:"dry_run"`
CronService CronServiceConfig `json:"cron_service"`
}

// DatabaseConfig represents database configuration
Expand Down Expand Up @@ -197,3 +198,10 @@ func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error {
func (d Duration) MarshalYAML() (interface{}, error) {
return time.Duration(d).String(), nil
}

// CronServiceConfig represents cron-based update service configuration
type CronServiceConfig struct {
Enabled bool `yaml:"enabled" json:"enabled"`
Schedule string `yaml:"schedule" json:"schedule"` // Default cron expression, used if router doesn't have time_threshold
PriceDeviation float64 `yaml:"price_deviation" json:"price_deviation"` // Default minimum price deviation to trigger update (as percentage)
}
1 change: 1 addition & 0 deletions services/bridge/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ require (
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
Expand Down
2 changes: 2 additions & 0 deletions services/bridge/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
Expand Down
89 changes: 89 additions & 0 deletions services/bridge/internal/api/prices.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package api

import (
"encoding/json"
"net/http"

"github.com/diadata.org/Spectra-interoperability/pkg/logger"
"github.com/diadata.org/Spectra-interoperability/services/bridge/internal/processor"
"github.com/gorilla/mux"
)

// handleGetPrices returns all prices from the in-memory cache
func (s *Server) handleGetPrices(w http.ResponseWriter, r *http.Request) {
priceCache, ok := s.priceCache.(*processor.PriceCache)
if !ok || priceCache == nil {
logger.Warn("Price cache not available")
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusServiceUnavailable)
json.NewEncoder(w).Encode(map[string]string{
"error": "Price cache not available",
})
return
}

prices := priceCache.GetAllPrices()

response := make(map[string]interface{})
for symbol, entry := range prices {
response[symbol] = map[string]interface{}{
"price": entry.Price,
"timestamp": entry.Timestamp,
"intent_hash": entry.IntentHash,
}
}

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]interface{}{
"count": len(prices),
"prices": response,
})
}

// handleGetPrice returns the price for a specific symbol
func (s *Server) handleGetPrice(w http.ResponseWriter, r *http.Request) {
priceCache, ok := s.priceCache.(*processor.PriceCache)
if !ok || priceCache == nil {
logger.Warn("Price cache not available")
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusServiceUnavailable)
json.NewEncoder(w).Encode(map[string]string{
"error": "Price cache not available",
})
return
}

vars := mux.Vars(r)
symbol := vars["symbol"]

if symbol == "" {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{
"error": "Symbol is required",
})
return
}

priceEntry, exists := priceCache.GetPrice(symbol)
if !exists {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusNotFound)
json.NewEncoder(w).Encode(map[string]string{
"error": "Price not found for symbol: " + symbol,
})
return
}

response := map[string]interface{}{
"symbol": symbol,
"price": priceEntry.Price,
"timestamp": priceEntry.Timestamp,
"intent_hash": priceEntry.IntentHash,
}

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(response)
}
7 changes: 7 additions & 0 deletions services/bridge/internal/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type Server struct {
db *database.DB
metrics *metrics.Collector
routerRegistry interface{} // Will be *router.Registry when available
priceCache interface{} // Will be *processor.PriceCache when available

router *mux.Router
httpServer *http.Server
Expand All @@ -39,13 +40,15 @@ func NewServer(
db *database.DB,
metricsCollector *metrics.Collector,
routerRegistry interface{}, // Pass as interface{} to avoid import cycle
priceCache interface{}, // Pass as interface{} to avoid import cycle
) *Server {
s := &Server{
config: &cfgService.GetInfrastructure().API,
configService: cfgService,
db: db,
metrics: metricsCollector,
routerRegistry: routerRegistry,
priceCache: priceCache,
router: mux.NewRouter(),
}

Expand Down Expand Up @@ -155,6 +158,10 @@ func (s *Server) setupRoutes() {
v1.HandleFunc("/symbols", s.handleGetSymbols).Methods("GET")
v1.HandleFunc("/symbols/{symbol}/updates", s.handleGetSymbolUpdates).Methods("GET")

// Price cache endpoints
v1.HandleFunc("/prices", s.handleGetPrices).Methods("GET")
v1.HandleFunc("/prices/{symbol}", s.handleGetPrice).Methods("GET")

// Failover endpoints (if available)
if s.failoverHandler != nil {
logger.Info("Registering failover routes - handler is NOT nil")
Expand Down
Loading
Loading