### Get TransactionFee gRPC Request Example in Go Source: https://blockrazor.gitbook.io/blockrazor/solana/get-transactionfee This Go code demonstrates how to connect to the Blockrazor gRPC service, construct a TransactionFee request, and send it to the server. It includes examples for querying with and without specific accounts. Requires the generated Go protobuf client code. ```go package main import ( "context" "crypto/tls" "log" // directory of the generated code using the provided proto file pb "fee-test/feepb" "google.golang.org/grpc" "google.golang.org/grpc/credentials" ) const ( gRPCEndpoint = "grpc.solana-fee.blockrazor.xyz:443" // endpoint address auth = "your auth" // auth to be verified testAccount1 = "DH4xmaWDnTzKXehVaPSNy9tMKJxnYL5Mo5U3oTHFtNYJ" // query priority fee and tip of transactions involving a specified account testAccount2 = "CAPhoEse9xEH95XmdnJjYrZdNCA8xfUWdy3aWymHa1Vj" ) func main() { // open gRPC connection to endpoint conn, err := grpc.Dial( gRPCEndpoint, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})), grpc.WithPerRPCCredentials(&Authentication{auth}), ) if err != nil { panic(err) } defer conn.Close() // use the gRPC client client := pb.NewServerClient(conn) req := &pb.TransactionFee{ Accounts: []string{}, //do not set accounts Percentile: 75, SlotRange: 150, } // send gRPC request1 resp, err := client.GetTransactionFee(context.Background(), req) if err != nil { panic(err) } log.Printf("Response PriorityFee Percentile: %+v", resp.PriorityFee.Percentile) log.Printf("Response PriorityFee Value: %+v", resp.PriorityFee.Value) log.Printf("Response Tip Percentile: %+v", resp.Tip.Percentile) log.Printf("Response Tip Value: %+v", resp.Tip.Value) req2 := &pb.TransactionFee{ Accounts: []string{testAccount1, testAccount2}, //set specified accounts Percentile: 75, SlotRange: 150, } // send gRPC request2 resp2, err := client.GetTransactionFee(context.Background(), req2) if err != nil { panic(err) } log.Printf("Response2 PriorityFee Percentile: %+v", resp2.PriorityFee.Percentile) log.Printf("Response2 PriorityFee Value: %+v", resp2.PriorityFee.Value) log.Printf("Response2 Tip Percentile: %+v", resp2.Tip.Percentile) log.Printf("Response2 Tip Value: %+v", resp2.Tip.Value) } type Authentication struct { auth string } func (a *Authentication) GetRequestMetadata(context.Context, ...string) (map[string]string, error) { return map[string]string{"apiKey": a.auth}, nil } func (a *Authentication) RequireTransportSecurity() bool { return false } ``` -------------------------------- ### Send Solana Transaction via HTTP (Go) Source: https://blockrazor.gitbook.io/blockrazor/solana/send-transaction/go This Go code snippet demonstrates how to construct and send a Solana transaction using the Blockrazor HTTP API. It includes steps for account setup, transaction building, signing, and sending the transaction with specified mode and protection settings. Dependencies include the 'solana-go' library. ```Go package main import ( "bytes" "context" "encoding/json" "fmt" "io" "math/rand" "net/http" "time" "github.com/gagliardetto/solana-go" "github.com/gagliardetto/solana-go/programs/system" "github.com/gagliardetto/solana-go/rpc" ) const ( httpEndpoint = "http://frankfurt.solana.blockrazor.xyz:443/sendTransaction" healthEndpoint = "http://frankfurt.solana.blockrazor.xyz:443/health" mainNetRPC = "" authKey = "" privateKey = "" publicKey = "" amount = 200_000 tipAmount = 1_000_000 mode = "fast" safeWindow = 5 revertProtection = false ) var tipAccounts = []string{ "Gywj98ophM7GmkDdaWs4isqZnDdFCW7B46TXmKfvyqSm", "FjmZZrFvhnqqb9ThCuMVnENaM3JGVuGWNyCAxRJcFpg9", "6No2i3aawzHsjtThw81iq1EXPJN6rh8eSJCLaYZfKDTG", "A9cWowVAiHe9pJfKAj3TJiN9VpbzMUq6E4kEvf5mUT22", "68Pwb4jS7eZATjDfhmTXgRJjCiZmw1L7Huy4HNpnxJ3o", "4ABhJh5rZPjv63RBJBuyWzBK3g9gWMUQdTZP2kiW31V9", "B2M4NG5eyZp5SBQrSdtemzk5TqVuaWGQnowGaCBt8GyM", "5jA59cXMKQqZAVdtopv8q3yyw9SYfiE3vUCbt7p8MfVf", "5YktoWygr1Bp9wiS1xtMtUki1PeYuuzuCF98tqwYxf61", "295Avbam4qGShBYK7E9H5Ldew4B3WyJGmgmXfiWdeeyV", "EDi4rSy2LZgKJ74mbLTFk4mxoTgT6F7HxxzG2HBAFyK", "BnGKHAC386n4Qmv9xtpBVbRaUTKixjBe3oagkPFKtoy6", "Dd7K2Fp7AtoN8xCghKDRmyqr5U169t48Tw5fEd3wT9mq", "AP6qExwrbRgBAVaehg4b5xHENX815sMabtBzUzVB4v8S", } var httpClient = &http.Client{ Timeout: 10 * time.Second, } type SendRequest struct { Transaction string `json:"transaction"` Mode string `json:"mode"` SafeWindow int `json:"safeWindow"` RevertProtection bool `json:"revertProtection"` } type SendResponse struct { Signature string `json:"signature"` } type HealthResponse struct { Result string `json:"result"` } func main() { // Pre-warm: perform an initial health check to establish the HTTP connection err := pingHealth() if err != nil { fmt.Printf("health check failed: %v\n", err) } // Start a background goroutine to periodically send /health requests // For low-frequency users, this keeps the HTTP connection alive (warm) go func() { for { err := pingHealth() if err != nil { fmt.Printf("health check failed: %v\n", err) } time.Sleep(30 * time.Second) } }() // send transactions if err := sendTx(); err != nil { fmt.Printf("send tx failed: %v\n", err) } } func pingHealth() error { req, err := http.NewRequest("GET", healthEndpoint, nil) if err != nil { return err } req.Header.Set("Content-Type", "application/json") req.Header.Set("apikey", authKey) resp, err := httpClient.Do(req) if err != nil { return err } defer resp.Body.Close() // ⚠️ Important Note: // According to the Go net/http documentation, in order for the underlying TCP connection // to be reused (i.e. kept alive), the response body must be fully read and closed. // Otherwise, the Transport may not reuse the connection for future requests. // Reference: https://pkg.go.dev/net/http#Response // > "The default HTTP client's Transport may not reuse HTTP/1.x 'keep-alive' TCP connections // if the Body is not read to completion and closed." // Read the full response body to enable connection reuse bodyBytes, _ := io.ReadAll(resp.Body) var healthRes HealthResponse if err := json.Unmarshal(bodyBytes, &healthRes); err != nil { return fmt.Errorf("decode error: %v", err) } return nil } func sendTx() error { account, err := solana.WalletFromPrivateKeyBase58(privateKey) if err != nil { return err } receivePub := solana.MustPublicKeyFromBase58(publicKey) tipPub := solana.MustPublicKeyFromBase58(tipAccounts[rand.Intn(len(tipAccounts))]) rpcClient := rpc.New(mainNetRPC) blockhash, err := rpcClient.GetLatestBlockhash(context.TODO(), rpc.CommitmentFinalized) if err != nil { return fmt.Errorf("[get blockhash] %v", err) } transferIx := system.NewTransferInstruction(amount, account.PublicKey(), receivePub).Build() tipIx := system.NewTransferInstruction(tipAmount, account.PublicKey(), tipPub).Build() tx, err := solana.NewTransaction( []solana.Instruction{tipIx, transferIx}, blockhash.Value.Blockhash, solana.TransactionPayer(account.PublicKey()), ) if err != nil { return fmt.Errorf("build tx error: %v", err) } _, err = tx.Sign(func(key solana.PublicKey) *solana.PrivateKey { if account.PublicKey().Equals(key) { return &account.PrivateKey } return nil }) if err != nil { return fmt.Errorf("sign tx error: %v", err) } txBase64, err := tx.ToBase64() if err != nil { return err } reqBody := SendRequest{ Transaction: txBase64, Mode: mode, SafeWindow: safeWindow, RevertProtection: revertProtection, } jsonBody, _ := json.Marshal(reqBody) httpReq, err := http.NewRequest("POST", httpEndpoint, bytes.NewBuffer(jsonBody)) if err != nil { return err } ``` -------------------------------- ### Untitled No description -------------------------------- ### Untitled No description -------------------------------- ### Untitled No description -------------------------------- ### Connect to BlockRazor WebSocket with Authentication Source: https://blockrazor.gitbook.io/blockrazor/base/authentication This example shows how to connect to BlockRazor's WebSocket endpoint using `wscat` and includes the necessary Authorization header. It also sends a sample JSON-RPC request to subscribe to FlashBlock. ```bash wscat -H "Authorization: " \ -c wss://frankfurt.base.blockrazor.xyz/ws \ --wait 1000 \ --execute '{"jsonrpc": "2.0", "id": 1, "method": "subscribe_FlashBlock", "params": []}' ``` -------------------------------- ### Untitled No description -------------------------------- ### Go gRPC BlockStream Request Example Source: https://blockrazor.gitbook.io/blockrazor/base/get-blockstream This Go function demonstrates how to connect to the gRPC server and subscribe to the block stream. It requires an authentication token for authorization and handles basic connection and stream reception. For production use, implement reconnection logic and more robust error handling. ```go // GetBlockStream provides a simplified example of subscribing to and processing the regular block stream. // Note: This function attempts to connect and subscribe only once. For production use, implement your own reconnection logic. func GetBlockStream(authToken string) { log.Printf("[BlockStream] Attempting to connect to gRPC server at %s...", grpcAddr) // Establish a connection to the gRPC server with a timeout. ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() conn, err := grpc.DialContext(ctx, grpcAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Printf("[BlockStream] Failed to connect to gRPC server: %v", err) return } defer conn.Close() log.Println("[BlockStream] Successfully connected to gRPC server.") client := basepb.NewBaseApiClient(conn) // Create a new context with authentication metadata for the stream subscription. streamCtx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs("authorization", authToken)) stream, err := client.GetBlockStream(streamCtx, &basepb.GetBlockStreamRequest{}) if err != nil { log.Printf("[BlockStream] Failed to subscribe to stream: %v", err) return } log.Println("[BlockStream] Subscription successful. Waiting for new blocks...") // Loop indefinitely to receive messages from the stream. for { block, err := stream.Recv() if err != nil { if err == io.EOF { log.Println("[BlockStream] Stream closed by the server (EOF).") } else { log.Printf("[BlockStream] An error occurred while receiving data: %v", err) } break // Exit the loop on error or stream closure. } // Process the received block data. log.Printf("=> [BlockStream] Received new block: Number=%d, Hash=%s, TransactionCount=%d", block.GetBlockNumber(), block.GetBlockHash(), len(block.GetTransactions()), ) // To decode transactions, you can call DecodeTransactions(block.Transactions). } } ``` -------------------------------- ### Untitled No description -------------------------------- ### Perform HTTP Health Check (Go) Source: https://blockrazor.gitbook.io/blockrazor/solana/send-transaction/go This Go code snippet demonstrates how to perform an HTTP GET request to check the health of the Blockrazor service. It includes setting the necessary headers and reading the response body to ensure connection reuse. Dependencies include the standard Go 'net/http' package. ```Go func pingHealth() error { req, err := http.NewRequest("GET", healthEndpoint, nil) if err != nil { return err } req.Header.Set("Content-Type", "application/json") req.Header.Set("apikey", authKey) resp, err := httpClient.Do(req) if err != nil { return err } defer resp.Body.Close() // ⚠️ Important Note: // According to the Go net/http documentation, in order for the underlying TCP connection // to be reused (i.e. kept alive), the response body must be fully read and closed. // Otherwise, the Transport may not reuse the connection for future requests. // Reference: https://pkg.go.dev/net/http#Response // > "The default HTTP client's Transport may not reuse HTTP/1.x 'keep-alive' TCP connections // if the Body is not read to completion and closed." // Read the full response body to enable connection reuse bodyBytes, _ := io.ReadAll(resp.Body) var healthRes HealthResponse if err := json.Unmarshal(bodyBytes, &healthRes); err != nil { return fmt.Errorf("decode error: %v", err) } return nil } ``` -------------------------------- ### Untitled No description -------------------------------- ### Untitled No description -------------------------------- ### Untitled No description -------------------------------- ### Example BlockRazor Transaction Response Payloads Source: https://blockrazor.gitbook.io/blockrazor/tc/solana/send-transaction/go Illustrates example responses for the SendTransaction RPC. The 'normal' example shows a successful transaction with a signature, while the 'abnormal' example indicates an error, such as insufficient tip. ```go signature:"2PCgCdD5gm4852ooyT2LQqiTgcau28hRNWCqBHCJ33EhhBsuAzAxYGLbS8kAmAMu7DW8JSrrKtaCGMZqQbtbGpgx" ``` ```go error: rpc error: code = Unknown desc = Insufficient tip, please increase the tip amount and try again, at least 1000000 lamports ``` -------------------------------- ### Blockrazor Server Transaction Success Response Example Source: https://blockrazor.gitbook.io/blockrazor/solana/send-transaction/go An example of a successful response from the SendTransaction RPC, containing a transaction signature. ```go signature:"2PCgCdD5gm4852ooyT2LQqiTgcau28hRNWCqBHCJ33EhhBsuAzAxYGLbS8kAmAMu7DW8JSrrKtaCGMZqQbtbGpgx" ``` -------------------------------- ### Untitled No description -------------------------------- ### Untitled No description -------------------------------- ### GetRawFlashBlockStream Response Example Source: https://blockrazor.gitbook.io/blockrazor/base/get-flashblockstream Example responses for the GetRawFlashBlockStream RPC. ```APIDOC ## GetRawFlashBlockStream Response Example ### Success Response (200) #### Response Example ```json { "message": "185329……7e04b7" } ``` ### Error Response #### Response Example ``` rpc error: code = Unknown desc = Authentication information is missing. Please provide a valid auth token ``` ``` -------------------------------- ### Untitled No description -------------------------------- ### Blockrazor Server Transaction Error Response Example Source: https://blockrazor.gitbook.io/blockrazor/solana/send-transaction/go An example of an error response from the SendTransaction RPC, indicating an 'Insufficient tip' error with a description of the required action. ```go error: rpc error: code = Unknown desc = Insufficient tip, please increase the tip amount and try again, at least 1000000 lamports ```