diff --git a/bchain/coins/blockchain.go b/bchain/coins/blockchain.go index d004896f..38e98bea 100644 --- a/bchain/coins/blockchain.go +++ b/bchain/coins/blockchain.go @@ -302,9 +302,9 @@ func (c *blockChainWithMetrics) LongTermFeeRate() (v *bchain.LongTermFeeRate, er return c.b.LongTermFeeRate() } -func (c *blockChainWithMetrics) SendRawTransaction(tx string) (v string, err error) { +func (c *blockChainWithMetrics) SendRawTransaction(tx string, disableAlternativeRPC bool) (v string, err error) { defer func(s time.Time) { c.observeRPCLatency("SendRawTransaction", s, err) }(time.Now()) - return c.b.SendRawTransaction(tx) + return c.b.SendRawTransaction(tx, disableAlternativeRPC) } func (c *blockChainWithMetrics) GetMempoolEntry(txid string) (v *bchain.MempoolEntry, err error) { diff --git a/bchain/coins/btc/bitcoinrpc.go b/bchain/coins/btc/bitcoinrpc.go index 91bdee97..f6daead2 100644 --- a/bchain/coins/btc/bitcoinrpc.go +++ b/bchain/coins/btc/bitcoinrpc.go @@ -889,7 +889,7 @@ func (b *BitcoinRPC) LongTermFeeRate() (*bchain.LongTermFeeRate, error) { } // SendRawTransaction sends raw transaction -func (b *BitcoinRPC) SendRawTransaction(tx string) (string, error) { +func (b *BitcoinRPC) SendRawTransaction(tx string, disableAlternativeRPC bool) (string, error) { glog.V(1).Info("rpc: sendrawtransaction") res := ResSendRawTransaction{} diff --git a/bchain/coins/dcr/decredrpc.go b/bchain/coins/dcr/decredrpc.go index 07cc4598..31c5810f 100644 --- a/bchain/coins/dcr/decredrpc.go +++ b/bchain/coins/dcr/decredrpc.go @@ -791,7 +791,7 @@ func (d *DecredRPC) EstimateFee(blocks int) (big.Int, error) { return r, nil } -func (d *DecredRPC) SendRawTransaction(tx string) (string, error) { +func (d *DecredRPC) SendRawTransaction(tx string, disableAlternativeRPC bool) (string, error) { sendRawTxRequest := &GenericCmd{ ID: 1, Method: "sendrawtransaction", diff --git a/bchain/coins/eth/ethrpc.go b/bchain/coins/eth/ethrpc.go index 25cf0ee4..9cbf5707 100644 --- a/bchain/coins/eth/ethrpc.go +++ b/bchain/coins/eth/ethrpc.go @@ -1122,12 +1122,15 @@ func (b *EthereumRPC) EthereumTypeGetEip1559Fees() (*bchain.Eip1559Fees, error) } // SendRawTransaction sends raw transaction -func (b *EthereumRPC) SendRawTransaction(hex string) (string, error) { +func (b *EthereumRPC) SendRawTransaction(hex string, disableAlternativeRPC bool) (string, error) { var txid string var retErr error - if b.alternativeSendTxProvider != nil { + if !disableAlternativeRPC && b.alternativeSendTxProvider != nil { txid, retErr = b.alternativeSendTxProvider.SendRawTransaction(hex) + if retErr == nil { + return txid, nil + } if b.alternativeSendTxProvider.UseOnlyAlternativeProvider() { return txid, retErr } diff --git a/bchain/coins/nuls/nulsrpc.go b/bchain/coins/nuls/nulsrpc.go index 001cb6df..3c73bed8 100644 --- a/bchain/coins/nuls/nulsrpc.go +++ b/bchain/coins/nuls/nulsrpc.go @@ -471,7 +471,7 @@ func (n *NulsRPC) EstimateFee(blocks int) (big.Int, error) { return *big.NewInt(100000), nil } -func (n *NulsRPC) SendRawTransaction(tx string) (string, error) { +func (n *NulsRPC) SendRawTransaction(tx string, alternativeRPC bool) (string, error) { broadcast := CmdTxBroadcast{} req := struct { TxHex string `json:"txHex"` diff --git a/bchain/types.go b/bchain/types.go index e6c2d126..8e214ae1 100644 --- a/bchain/types.go +++ b/bchain/types.go @@ -331,7 +331,7 @@ type BlockChain interface { EstimateSmartFee(blocks int, conservative bool) (big.Int, error) EstimateFee(blocks int) (big.Int, error) LongTermFeeRate() (*LongTermFeeRate, error) - SendRawTransaction(tx string) (string, error) + SendRawTransaction(tx string, disableAlternativeRPC bool) (string, error) GetMempoolEntry(txid string) (*MempoolEntry, error) GetContractInfo(contractDesc AddressDescriptor) (*ContractInfo, error) // parser diff --git a/blockbook-api.ts b/blockbook-api.ts index a327e8d1..56ec8ae7 100644 --- a/blockbook-api.ts +++ b/blockbook-api.ts @@ -754,6 +754,8 @@ export interface WsLongTermFeeRateRes { export interface WsSendTransactionReq { /** Hex-encoded transaction data to broadcast. */ hex: string; + /** Use alternative RPC method to broadcast transaction. */ + disableAlternativeRPC?: boolean; } export interface WsSubscribeAddressesReq { /** List of addresses to subscribe for updates (e.g., new transactions). */ diff --git a/server/public.go b/server/public.go index 84ba710b..82650d9b 100644 --- a/server/public.go +++ b/server/public.go @@ -1059,7 +1059,7 @@ func (s *PublicServer) explorerSendTx(w http.ResponseWriter, r *http.Request) (t } hex := r.FormValue("hex") if len(hex) > 0 { - res, err := s.chain.SendRawTransaction(hex) + res, err := s.chain.SendRawTransaction(hex, false) if err != nil { data.SendTxHex = hex data.Error = &api.APIError{Text: err.Error(), Public: true} @@ -1509,7 +1509,7 @@ func (s *PublicServer) apiSendTx(r *http.Request, apiVersion int) (interface{}, } } if len(hex) > 0 { - res.Result, err = s.chain.SendRawTransaction(hex) + res.Result, err = s.chain.SendRawTransaction(hex, false) if err != nil { return nil, api.NewAPIError(err.Error(), true) } diff --git a/server/public_ethereumtype_test.go b/server/public_ethereumtype_test.go index f16658a6..f63f8558 100644 --- a/server/public_ethereumtype_test.go +++ b/server/public_ethereumtype_test.go @@ -153,6 +153,17 @@ var websocketTestsEthereumType = []websocketTest{ }, want: `{"id":"1","data":{"data":"0x4567abcd"}}`, }, + { + name: "websocket sendTransaction hex format", + req: websocketReq{ + Method: "sendTransaction", + Params: WsSendTransactionReq{ + Hex: "123456", + DisableAlternativeRPC: true, + }, + }, + want: `{"id":"2","data":{"result":"9876"}}`, + }, } func initEthereumTypeDB(d *db.RocksDB) error { diff --git a/server/socketio.go b/server/socketio.go index 9e8dab7f..c606eb1a 100644 --- a/server/socketio.go +++ b/server/socketio.go @@ -641,7 +641,7 @@ func (s *SocketIoServer) getDetailedTransaction(txid string) (res resultGetDetai } func (s *SocketIoServer) sendTransaction(tx string) (res resultSendTransaction, err error) { - txid, err := s.chain.SendRawTransaction(tx) + txid, err := s.chain.SendRawTransaction(tx, false) if err != nil { return res, err } diff --git a/server/websocket.go b/server/websocket.go index cdaa340c..9a6d09cb 100644 --- a/server/websocket.go +++ b/server/websocket.go @@ -376,10 +376,11 @@ var requestHandlers = map[string]func(*WebsocketServer, *websocketChannel, *WsRe r := WsSendTransactionReq{} err = json.Unmarshal(req.Params, &r) if err == nil { - rv, err = s.sendTransaction(r.Hex) + rv, err = s.sendTransaction(r.Hex, r.DisableAlternativeRPC) } return }, + "getMempoolFilters": func(s *WebsocketServer, c *websocketChannel, req *WsReq) (rv interface{}, err error) { r := WsMempoolFiltersReq{} err = json.Unmarshal(req.Params, &r) @@ -751,8 +752,8 @@ func (s *WebsocketServer) longTermFeeRate() (res interface{}, err error) { }, nil } -func (s *WebsocketServer) sendTransaction(tx string) (res resultSendTransaction, err error) { - txid, err := s.chain.SendRawTransaction(tx) +func (s *WebsocketServer) sendTransaction(tx string, disableAlternativeRPC bool) (res resultSendTransaction, err error) { + txid, err := s.chain.SendRawTransaction(tx, disableAlternativeRPC) if err != nil { return res, err } diff --git a/server/ws_types.go b/server/ws_types.go index 5add2356..3f17f6ce 100644 --- a/server/ws_types.go +++ b/server/ws_types.go @@ -141,7 +141,8 @@ type WsLongTermFeeRateRes struct { // WsSendTransactionReq is used to broadcast a transaction to the network. type WsSendTransactionReq struct { - Hex string `json:"hex" ts_doc:"Hex-encoded transaction data to broadcast."` + Hex string `json:"hex,omitempty" ts_doc:"Hex-encoded transaction data to broadcast (string format)."` + DisableAlternativeRPC bool `json:"disableAlternativeRpc" ts_doc:"Use alternative RPC method to broadcast transaction."` } // WsSubscribeAddressesReq is used to subscribe to updates on a list of addresses. diff --git a/tests/dbtestdata/fakechain.go b/tests/dbtestdata/fakechain.go index 044c2683..6f0e22e8 100644 --- a/tests/dbtestdata/fakechain.go +++ b/tests/dbtestdata/fakechain.go @@ -201,7 +201,7 @@ func (c *fakeBlockChain) EstimateFee(blocks int) (v big.Int, err error) { return } -func (c *fakeBlockChain) SendRawTransaction(tx string) (v string, err error) { +func (c *fakeBlockChain) SendRawTransaction(tx string, disableAlternativeRPC bool) (v string, err error) { if tx == "123456" { return "9876", nil }