Skip to content

Send RawTxBatch

Introduction

{% hint style="info" %} This method does not provide MEV protection. Transactions sent through this method will be broadcast to the public mempool. {% endhint %}

SendTxsis used to broadcast raw transaction batch on the high-performance network of BSC.

Endpoint

RegionAvailability Zone(AWS)Relay Address
Frankfurteuc1-az235.157.64.49:50051
Tokyoapne1-az454.249.93.63:50051
Irelandeuw1-az13.248.65.151:50051
Virginiause1-az452.205.173.134:50051

Rate Limit

Tier 4Tier 3Tier 2Tier 1Tier 0
BPS--2 batches / 1s4 batches / 1s12 batches / 1s
Transactions per batch--10 Txs / batch10 Txs / batch20 Txs / batch

Request Parameter

ParametersMandatoryFormatExampleDescription
TransactionsMandatoryArray[String]["0xf8……8219", "0xcb……2ac0"]signed raw txs

Request Example

https://github.com/BlockRazorinc/relay_example

package main

import (
    "context"
    "encoding/hex"
    "fmt"
    "math/big"

    // directory of the generated code using the provided relay.proto file
    pb "github.com/BlockRazorinc/relay_example/protobuf"
    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/core/types"
    "github.com/ethereum/go-ethereum/crypto"
    "github.com/ethereum/go-ethereum/rlp"
    "google.golang.org/grpc"
)

// auth will be used to verify the credential
type Authentication struct {
    apiKey string
}

func (a *Authentication) GetRequestMetadata(context.Context, ...string) (map[string]string, error) {
    return map[string]string{"apiKey": a.apiKey}, nil
}

func (a *Authentication) RequireTransportSecurity() bool {
    return false
}

func main() {

    // BlockRazor relay endpoint address
    blzrelayEndPoint := "ip:port"

    // auth will be used to verify the credential
    auth := Authentication{
        "your auth token",
    }

    // open gRPC connection to BlockRazor relay
    var err error
    conn, err := grpc.Dial(blzrelayEndPoint, grpc.WithInsecure(), grpc.WithPerRPCCredentials(&auth), grpc.WithWriteBufferSize(0), grpc.WithInitialConnWindowSize(128*1024))
    if err != nil {
        fmt.Println("error: ", err)
        return
    }

    // use the Gateway client connection interface
    client := pb.NewGatewayClient(conn)

    // create context
    ctx := context.Background()

    // replace with your address
    from_private_address1 := "6c0456……8b8003"
    from_private_address2 := "42b565……44d05c"
    to_public_address := "0x4321……3f1c66"

    // replace with your transaction data
    nonce1 := uint64(1)
    nonce2 := uint64(1)
    toAddress := common.HexToAddress(to_public_address)
    var data []byte
    gasPrice := big.NewInt(1e9)
    gasLimit := uint64(22000)
    value := big.NewInt(0)
    chainid := types.NewEIP155Signer(big.NewInt(56))

    // create new transaction
    tx1 := types.NewTransaction(nonce1, toAddress, value, gasLimit, gasPrice, data)
    tx2 := types.NewTransaction(nonce2, toAddress, value, gasLimit, gasPrice, data)

    privateKey1, err := crypto.HexToECDSA(from_private_address1)
    if err != nil {
        fmt.Println("fail to casting private key to ECDSA")
        return
    }

    privateKey2, err := crypto.HexToECDSA(from_private_address2)
    if err != nil {
        fmt.Println("fail to casting private key to ECDSA")
        return
    }

    // sign transaction by private key
    signedTx1, err := types.SignTx(tx1, chainid, privateKey1)
    if err != nil {
        fmt.Println("fail to sign transaction")
        return
    }

    signedTx2, err := types.SignTx(tx2, chainid, privateKey2)
    if err != nil {
        fmt.Println("fail to sign transaction")
        return
    }

    // use rlp to encode your transaction
    body, _ := rlp.EncodeToBytes([]types.Transaction{*signedTx1, *signedTx2})

    // encode []byte to string
    encode_txs := hex.EncodeToString(body)

    // send raw tx batch by BlockRazor
    res, err := client.SendTxs(ctx, &pb.SendTxsRequest{Transactions: encode_txs})

    if err != nil {
        fmt.Println("failed to send raw tx batch: ", err)
        return
    } else {
        fmt.Println("raw tx batch sent by BlockRazor, tx hashes are ", res.TxHashs)
    }

}

Proto

The code of relay.proto is as follows:

syntax = "proto3";

package blockchain;

option go_package = "/Users/code/relay/grpcServer"; 
service Gateway {
  rpc SendTx (SendTxRequest) returns (SendTxReply) {}
  rpc SendTxs (SendTxsRequest) returns (SendTxsReply) {}
  rpc NewTxs (TxsRequest) returns (stream TxsReply){}
  rpc NewBlocks (BlocksRequest) returns (stream BlocksReply){}
}

message TxsRequest{
  bool node_validation = 1;
}

message Tx{
  bytes from = 1;
  int64 timestamp = 2;
  bytes raw_tx = 3;
}

message TxsReply{
   Tx tx = 1;
}

message BlocksRequest{
  bool node_validation = 1;
}

message BlockHeader{
  string parent_hash = 1;
  string sha3_uncles = 2;
  string miner = 3;
  string state_root = 4;
  string transactions_root = 5;
  string receipts_root = 6;
  string logs_bloom = 7;
  string difficulty = 8;
  string number = 9;
  uint64 gas_limit = 10;
  uint64 gas_used = 11;
  uint64 timestamp = 12;
  bytes extra_data = 13;
  string mix_hash = 14;
  uint64 nonce = 15;
  uint64 base_fee_per_gas = 16;
  string withdrawals_root = 17;
  uint64 blob_gas_used = 18;
  uint64 excess_blob_gas = 19;
  string parent_beacon_block_root = 20;
}

message NextValidator{
  string block_height = 1;
  string coinbase = 2;
}

message BlocksReply{
  string hash = 1;
  BlockHeader header = 2;
  repeated NextValidator nextValidator = 3;
  repeated Tx txs = 4;
}

message Transaction {
  string content = 1;
}

message Transactions {
  repeated Transaction transactions = 1;
}

message SendTxRequest {
  string transaction = 1;
}

message SendTxsRequest {
  string transactions = 1;
}

message SendTxReply {
  string tx_hash = 1;
}

message SendTxsReply {
  repeated string tx_hashs = 1;
}

Response Example

Success

{
 "tx_hash":["0xdb95……584813", "0x887d……7aba19"]
}

Error

rpc error: code = Unknown desc = invalid transaction format