From 69cdf31417b0a9b12f166fa2228db49301cf8f62 Mon Sep 17 00:00:00 2001 From: Chris Gianelloni Date: Wed, 29 Jan 2025 14:48:21 -0500 Subject: [PATCH] feat: maestro backend w/ turbo tx support Signed-off-by: Chris Gianelloni --- go.mod | 1 + go.sum | 2 ++ internal/api/api.go | 68 ++++++++++++++++++++++++++++++++++++++- internal/config/config.go | 27 +++++++++++----- 4 files changed, 89 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 0f60ba7..82242a5 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/gin-contrib/zap v1.1.4 github.com/gin-gonic/gin v1.10.0 github.com/kelseyhightower/envconfig v1.4.0 + github.com/maestro-org/go-sdk v1.2.0 go.uber.org/automaxprocs v1.6.0 go.uber.org/zap v1.27.0 gopkg.in/yaml.v2 v2.4.0 diff --git a/go.sum b/go.sum index da1f8d8..8f7897f 100644 --- a/go.sum +++ b/go.sum @@ -59,6 +59,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/maestro-org/go-sdk v1.2.0 h1:0YbC5bwRWklV25L1Z4p2pg2VQYasZGDaC9Epfxwd3a0= +github.com/maestro-org/go-sdk v1.2.0/go.mod h1:EYaRwFT8nkwFzZsN6xK256j+r7ASUUn9p44RlaqYjE8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= diff --git a/internal/api/api.go b/internal/api/api.go index d742cc4..06c7cd8 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -17,6 +17,7 @@ package api import ( "bytes" "context" + "encoding/hex" "fmt" "io" "net/http" @@ -30,6 +31,7 @@ import ( cors "github.com/gin-contrib/cors" ginzap "github.com/gin-contrib/zap" "github.com/gin-gonic/gin" + maestro "github.com/maestro-org/go-sdk/client" "github.com/blinklabs-io/tx-submit-api-mirror/internal/config" "github.com/blinklabs-io/tx-submit-api-mirror/internal/logging" @@ -196,10 +198,74 @@ func handleSubmitTx(c *gin.Context) { connReused, ) } else { - logger.Errorw(fmt.Sprintf("failed to send request to backend %s: got response %d, %s", backend, resp.StatusCode, string(respBody)), "latency", elapsedTime.Seconds(), "connReused", connReused) + logger.Errorw( + fmt.Sprintf( + "failed to send request to backend %s: got response %d, %s", + backend, + resp.StatusCode, + string(respBody), + ), + "latency", + elapsedTime.Seconds(), + "connReused", + connReused, + ) } }(backend) } + // Optional Maestro + if cfg.Maestro.ApiKey != "" { + go func(cfg *config.Config, rawTx []byte) { + txHex := hex.EncodeToString(rawTx) + maestroClient := maestro.NewClient(cfg.Maestro.ApiKey, cfg.Maestro.Network) + startTime := time.Now() + if cfg.Maestro.TurboTx { + _, err := maestroClient.TxManagerSubmitTurbo(txHex) + elapsedTime := time.Since(startTime) + if err != nil { + logger.Errorw( + fmt.Sprintf( + "failed to send request to Maestro: got response %v", + err, + ), + "latency", + elapsedTime.Seconds(), + ) + return + } + logger.Infow( + fmt.Sprintf( + "successfully submitted transaction %s to Maestro TurboTx", + tx.Hash(), + ), + "latency", + elapsedTime.Seconds(), + ) + return + } + _, err := maestroClient.TxManagerSubmit(txHex) + elapsedTime := time.Since(startTime) + if err != nil { + logger.Errorw( + fmt.Sprintf( + "failed to send request to Maestro: got response %v", + err, + ), + "latency", + elapsedTime.Seconds(), + ) + return + } + logger.Infow( + fmt.Sprintf( + "successfully submitted transaction %s to Maestro", + tx.Hash(), + ), + "latency", + elapsedTime.Seconds(), + ) + }(cfg, rawTx) + } // Return transaction ID c.String(202, tx.Hash()) } diff --git a/internal/config/config.go b/internal/config/config.go index af62305..3993a65 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -23,22 +23,29 @@ import ( ) type Config struct { - Logging LoggingConfig `yaml:"logging"` Api ApiConfig `yaml:"api"` + Logging LoggingConfig `yaml:"logging"` + Maestro MaestroConfig `yaml:"maestro"` Tls TlsConfig `yaml:"tls"` Backends []string `yaml:"backends" envconfig:"BACKENDS"` } -type LoggingConfig struct { - Level string `yaml:"level" envconfig:"LOGGING_LEVEL"` -} - type ApiConfig struct { ListenAddress string `yaml:"address" envconfig:"API_LISTEN_ADDRESS"` ListenPort uint `yaml:"port" envconfig:"API_LISTEN_PORT"` ClientTimeout uint `yaml:"client_timeout" envconfig:"CLIENT_TIMEOUT"` } +type LoggingConfig struct { + Level string `yaml:"level" envconfig:"LOGGING_LEVEL"` +} + +type MaestroConfig struct { + ApiKey string `yaml:"apiKey" envconfig:"MAESTRO_API_KEY"` + Network string `yaml:"network" envconfig:"MAESTRO_NETWORK"` + TurboTx bool `yaml:"turboTx" envconfig:"MAESTRO_TURBO_TX"` +} + type TlsConfig struct { CertFilePath string `yaml:"certFilePath" envconfig:"TLS_CERT_FILE_PATH"` KeyFilePath string `yaml:"keyFilePath" envconfig:"TLS_KEY_FILE_PATH"` @@ -46,14 +53,18 @@ type TlsConfig struct { // Singleton config instance with default values var globalConfig = &Config{ - Logging: LoggingConfig{ - Level: "info", - }, Api: ApiConfig{ ListenAddress: "", ListenPort: 8090, ClientTimeout: 60000, // [ms] }, + Logging: LoggingConfig{ + Level: "info", + }, + Maestro: MaestroConfig{ + Network: "mainnet", + TurboTx: false, + }, } func Load(configFile string) (*Config, error) {