github.com/trezor/blockbook@v0.4.1-0.20240328132726-e9a08582ee2c/bchain/coins/flo/florpc.go (about) 1 package flo 2 3 import ( 4 "encoding/json" 5 6 "github.com/golang/glog" 7 "github.com/juju/errors" 8 "github.com/trezor/blockbook/bchain" 9 "github.com/trezor/blockbook/bchain/coins/btc" 10 ) 11 12 // FloRPC is an interface to JSON-RPC bitcoind service. 13 type FloRPC struct { 14 *btc.BitcoinRPC 15 } 16 17 // NewFloRPC returns new FloRPC instance. 18 func NewFloRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) { 19 b, err := btc.NewBitcoinRPC(config, pushHandler) 20 if err != nil { 21 return nil, err 22 } 23 24 s := &FloRPC{ 25 b.(*btc.BitcoinRPC), 26 } 27 s.RPCMarshaler = btc.JSONMarshalerV2{} 28 s.ChainConfig.SupportsEstimateFee = false 29 30 return s, nil 31 } 32 33 // Initialize initializes FloRPC instance. 34 func (f *FloRPC) Initialize() error { 35 ci, err := f.GetChainInfo() 36 if err != nil { 37 return err 38 } 39 chainName := ci.Chain 40 41 glog.Info("Chain name ", chainName) 42 params := GetChainParams(chainName) 43 44 // always create parser 45 f.Parser = NewFloParser(params, f.ChainConfig) 46 47 // parameters for getInfo request 48 if params.Net == MainnetMagic { 49 f.Testnet = false 50 f.Network = "livenet" 51 } else { 52 f.Testnet = true 53 f.Network = "testnet" 54 } 55 56 glog.Info("rpc: block chain ", params.Name) 57 58 return nil 59 } 60 61 // GetBlock returns block with given hash. 62 func (f *FloRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) { 63 var err error 64 if hash == "" { 65 hash, err = f.GetBlockHash(height) 66 if err != nil { 67 return nil, err 68 } 69 } 70 if !f.ParseBlocks { 71 return f.GetBlockFull(hash) 72 } 73 // optimization 74 if height > 0 { 75 return f.GetBlockWithoutHeader(hash, height) 76 } 77 header, err := f.GetBlockHeader(hash) 78 if err != nil { 79 return nil, err 80 } 81 data, err := f.GetBlockBytes(hash) 82 if err != nil { 83 return nil, err 84 } 85 block, err := f.Parser.ParseBlock(data) 86 if err != nil { 87 return nil, errors.Annotatef(err, "hash %v", hash) 88 } 89 block.BlockHeader = *header 90 return block, nil 91 } 92 93 // GetBlockFull returns block with given hash 94 func (f *FloRPC) GetBlockFull(hash string) (*bchain.Block, error) { 95 glog.V(1).Info("rpc: getblock (verbosity=2) ", hash) 96 97 res := btc.ResGetBlockFull{} 98 req := btc.CmdGetBlock{Method: "getblock"} 99 req.Params.BlockHash = hash 100 req.Params.Verbosity = 2 101 err := f.Call(&req, &res) 102 103 if err != nil { 104 return nil, errors.Annotatef(err, "hash %v", hash) 105 } 106 if res.Error != nil { 107 if btc.IsErrBlockNotFound(res.Error) { 108 return nil, bchain.ErrBlockNotFound 109 } 110 return nil, errors.Annotatef(res.Error, "hash %v", hash) 111 } 112 113 for i := range res.Result.Txs { 114 tx := &res.Result.Txs[i] 115 for j := range tx.Vout { 116 vout := &tx.Vout[j] 117 // convert vout.JsonValue to big.Int and clear it, it is only temporary value used for unmarshal 118 vout.ValueSat, err = f.Parser.AmountToBigInt(vout.JsonValue) 119 if err != nil { 120 return nil, err 121 } 122 vout.JsonValue = "" 123 } 124 } 125 126 return &res.Result, nil 127 } 128 129 // GetTransactionForMempool returns a transaction by the transaction ID. 130 // It could be optimized for mempool, i.e. without block time and confirmations 131 func (f *FloRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) { 132 return f.GetTransaction(txid) 133 }