Submitting Transaction
This endpoint is used to broadcast a signed transaction
How OFR Handles Transaction Propagation
When you submit a transaction to the OFR endpoint, bloXroute’s infrastructure determines the current Solana leader and forwards the transaction to the Trader API instance that is geographically closest to that leader. This dynamic routing reduces latency and increases the probability of successful inclusion on-chain.
This behavior is fully abstracted away from the user. You do not need to manually manage or track leader locations—OFR handles that for you.
Recommended Submission Strategy
To maximize reliability and minimize latency, we recommend submitting each transaction to:
Your nearest Trader API endpoint, and
The OFR
/submit
endpoint.
This dual submission approach ensures both localized propagation from your own infrastructure and optimized propagation through OFR’s leader-aware routing.
Gateway setup
The two flags required at gateway startup for transaction submission are: -run-http-server
and -http-port
:
docker run --name bxgateway-solana -d \
--network=host bloxroute/solana-gateway:latest \
-auth-header=[AuthHeader] \
-run-http-server \
-http-port=8080 \
-ofr-host=ny.solana-v2.blxrbdn.com \
-port=18888
Additionally, gateway can be started with the -tx-submission-only
flag. This will launch the gateway in a dormant mode in which no shreds are sent nor received from OFR, effectively turning it into a local transaction submission API only.
Request
Method:
POST ./submit
Example
The Solana Gateway, connecting to the bloXroute Optimized Feed Relay (OFR), should run with http server flags, and more details about flags can be found here.
package main
import (
"bytes"
"encoding/base64"
"fmt"
"github.com/gagliardetto/solana-go"
"github.com/gagliardetto/solana-go/rpc"
"io"
"net/http"
)
func createJsonReq(solanaTx *solana.Transaction, frp, fbe, useStakedRPCs bool) ([]byte, error) {
txBase64, err := solanaTx.ToBase64()
if err != nil {
return nil, err
}
txBytes, err := rpc.DataBytesOrJSONFromBase64(txBase64)
if err != nil {
return nil, err
}
twm := rpc.TransactionWithMeta{
Transaction: txBytes,
}
txWithMeta, err := twm.GetTransaction()
if err != nil {
return nil, err
}
txData, err := txWithMeta.MarshalBinary()
if err != nil {
return nil, err
}
var jsonStr = []byte(fmt.Sprintf(`{"transaction": {"content": "%v"}, "frontRunningProtection": %v, "useStakedRPCs": %v, "fastBestEffort": %v}`,
base64.StdEncoding.EncodeToString(txData), frp, useStakedRPCs, fbe))
return jsonStr, nil
}
func main() {
// create your solana tx
solanaTx := &solana.Transaction{
Signatures: nil,
Message: solana.Message{},
}
//endpoint for solana gw to submit tx
url := "http://127.0.0.1:8080/submit"
jsonStr, err := createJsonReq(solanaTx, false, false, false)
if err != nil {
fmt.Println(err)
return
}
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
if err != nil {
fmt.Println(err)
return
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "<AUTH_HEADER>")
httpClient := http.DefaultClient
resp, err := httpClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(fmt.Sprintf("read response body: %s", err))
}
fmt.Println(string(body))
}
Last updated