Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
checksum0 committed Apr 11, 2019
2 parents 41e5dbe + f6d304c commit 6d70e4a
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 146 deletions.
56 changes: 31 additions & 25 deletions electrum/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,42 @@ import "errors"

var (
// ErrCheckpointHeight is thrown if the checkpoint height is smaller than the block height.
ErrCheckpointHeight = errors.New("checkpoint height must be greater or equal than block height")
ErrCheckpointHeight = errors.New("checkpoint height must be greater than or equal to block height")
)

// BlockHeaderResp represents the response to GetBlockHeader().
type BlockHeaderResp struct {
// GetBlockHeaderResp represents the response to GetBlockHeader().
type GetBlockHeaderResp struct {
Result *GetBlockHeaderResult `json:"result"`
}

// GetBlockHeaderResult represents the content of the result field in the response to GetBlockHeader().
type GetBlockHeaderResult struct {
Branch []string `json:"branch"`
Header string `json:"header"`
Root string `json:"root"`
}

// GetBlockHeader returns the block header at a specific height.
// https://electrumx.readthedocs.io/en/latest/protocol-methods.html#blockchain-block-header
func (s *Server) GetBlockHeader(height uint32, checkpointHeight ...uint32) (*BlockHeaderResp, error) {
if checkpointHeight != nil {
func (s *Server) GetBlockHeader(height uint32, checkpointHeight ...uint32) (*GetBlockHeaderResult, error) {
if checkpointHeight != nil && checkpointHeight[0] != 0 {
if height > checkpointHeight[0] {
return nil, ErrCheckpointHeight
}

resp := &struct {
Result *BlockHeaderResp `json:"result"`
}{}
err := s.request("blockchain.block.header", []interface{}{height, checkpointHeight}, resp)
var resp GetBlockHeaderResp
err := s.request("blockchain.block.header", []interface{}{height, checkpointHeight[0]}, &resp)

return resp.Result, err
}

resp := &basicResp{}
err := s.request("blockchain.block.header", []interface{}{height}, resp)
var resp basicResp
err := s.request("blockchain.block.header", []interface{}{height, 0}, &resp)
if err != nil {
return nil, err
}

result := &BlockHeaderResp{
result := &GetBlockHeaderResult{
Branch: nil,
Header: resp.Result,
Root: "",
Expand All @@ -45,8 +48,13 @@ func (s *Server) GetBlockHeader(height uint32, checkpointHeight ...uint32) (*Blo
return result, err
}

// BlockHeadersResp represents the response to GetBlockHeaders().
type BlockHeadersResp struct {
// GetBlockHeadersResp represents the response to GetBlockHeaders().
type GetBlockHeadersResp struct {
Result *GetBlockHeadersResult `json:"result"`
}

// GetBlockHeadersResult represents the content of the result field in the response to GetBlockHeaders().
type GetBlockHeadersResult struct {
Count uint32 `json:"count"`
Headers string `json:"hex"`
Max uint32 `json:"max"`
Expand All @@ -56,24 +64,22 @@ type BlockHeadersResp struct {

// GetBlockHeaders return a concatenated chunk of block headers.
// https://electrumx.readthedocs.io/en/latest/protocol-methods.html#blockchain-block-headers
func (s *Server) GetBlockHeaders(startHeight, count uint32, checkpointHeight ...uint32) (*BlockHeadersResp, error) {
resp := &struct {
Result *BlockHeadersResp `json:"result"`
}{}
func (s *Server) GetBlockHeaders(startHeight, count uint32,
checkpointHeight ...uint32) (*GetBlockHeadersResult, error) {

if checkpointHeight != nil {
var resp GetBlockHeadersResp
var err error

if checkpointHeight != nil && checkpointHeight[0] != 0 {
if (startHeight + (count - 1)) > checkpointHeight[0] {
return nil, ErrCheckpointHeight
}
err := s.request("blockchain.block.headers", []interface{}{startHeight, count, checkpointHeight}, resp)
if err != nil {
return nil, err
}

return resp.Result, err
err = s.request("blockchain.block.headers", []interface{}{startHeight, count, checkpointHeight[0]}, &resp)
} else {
err = s.request("blockchain.block.headers", []interface{}{startHeight, count, 0}, &resp)
}

err := s.request("blockchain.block.headers", []interface{}{startHeight, count, checkpointHeight}, resp)
if err != nil {
return nil, err
}
Expand Down
37 changes: 23 additions & 14 deletions electrum/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ type basicResp struct {
Result string `json:"result"`
}

// GetFeeResp represents the response to GetFee().
type GetFeeResp struct {
Result float32 `json:"result"`
}

// GetFee returns the estimated transaction fee per kilobytes for a transaction
// to be confirmed within a target number of blocks.
// https://electrumx.readthedocs.io/en/latest/protocol-methods.html#blockchain-estimatefee
func (s *Server) GetFee(target uint32) (float32, error) {
resp := &struct {
Result float32 `json:"result"`
}{}
var resp GetFeeResp

err := s.request("blockchain.estimatefee", []interface{}{target}, resp)
err := s.request("blockchain.estimatefee", []interface{}{target}, &resp)
if err != nil {
return -1, err
}
Expand All @@ -24,30 +27,36 @@ func (s *Server) GetFee(target uint32) (float32, error) {
// remote server memory pool.
// https://electrumx.readthedocs.io/en/latest/protocol-methods.html#blockchain-relayfee
func (s *Server) GetRelayFee() (float32, error) {
resp := &struct {
Result float32 `json:"result"`
}{}
var resp GetFeeResp

err := s.request("blockchain.relayfee", []interface{}{}, resp)
err := s.request("blockchain.relayfee", []interface{}{}, &resp)
if err != nil {
return -1, err
}

return resp.Result, err
}

// GetFeeHistogramResp represents the response to GetFee().
type getFeeHistogramResp struct {
Result [][2]uint64 `json:"result"`
}

// GetFeeHistogram returns a histogram of the fee rates paid by transactions in the
// memory pool, weighted by transacation size.
// https://electrumx.readthedocs.io/en/latest/protocol-methods.html#mempool-get-fee-histogram
func (s *Server) GetFeeHistogram() (map[uint32]uint32, error) {
resp := &struct {
Result map[uint32]uint32 `json:"result"`
}{}
func (s *Server) GetFeeHistogram() (map[uint32]uint64, error) {
var resp getFeeHistogramResp

err := s.request("mempool.get_fee_histogram", []interface{}{}, resp)
err := s.request("mempool.get_fee_histogram", []interface{}{}, &resp)
if err != nil {
return nil, err
}

return resp.Result, err
feeMap := make(map[uint32]uint64)
for i := 0; i < len(resp.Result); i++ {
feeMap[uint32(resp.Result[i][0])] = resp.Result[i][1]
}

return feeMap, err
}
66 changes: 39 additions & 27 deletions electrum/scripthash.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,47 @@
package electrum

// BalanceResp represents the response to GetBalance().
type BalanceResp struct {
// GetBalanceResp represents the response to GetBalance().
type GetBalanceResp struct {
Result GetBalanceResult `json:"result"`
}

// GetBalanceResult represents the content of the result field in the response to GetBalance().
type GetBalanceResult struct {
Confirmed float64 `json:"confirmed"`
Unconfirmed float64 `json:"unconfirmed"`
}

// GetBalance returns the confirmed and unconfirmed balance for a scripthash.
// https://electrumx.readthedocs.io/en/latest/protocol-methods.html#blockchain-scripthash-get-balance
func (s *Server) GetBalance(scripthash string) (BalanceResp, error) {
resp := &struct {
Result BalanceResp `json:"result"`
}{}
err := s.request("blockchain.scripthash.get_balance", []interface{}{scripthash}, resp)
func (s *Server) GetBalance(scripthash string) (GetBalanceResult, error) {
var resp GetBalanceResp

err := s.request("blockchain.scripthash.get_balance", []interface{}{scripthash}, &resp)
if err != nil {
return BalanceResp{}, err
return GetBalanceResult{}, err
}

return resp.Result, err
}

// MempoolResp represents the reponse to GetHistory() and GetMempool().
type MempoolResp struct {
// GetMempoolResp represents the response to GetHistory() and GetMempool().
type GetMempoolResp struct {
Result []*GetMempoolResult `json:"result"`
}

// GetMempoolResult represents the content of the result field in the response
// to GetHistory() and GetMempool().
type GetMempoolResult struct {
Hash string `json:"tx_hash"`
Height int32 `json:"height"`
Fee uint32 `json:"fee,omitempty"`
}

// GetHistory returns the confirmed and unconfirmed history for a scripthash.
func (s *Server) GetHistory(scripthash string) ([]*MempoolResp, error) {
resp := &struct {
Result []*MempoolResp `json:"result"`
}{}
err := s.request("blockchain.scripthash.get_history", []interface{}{scripthash}, resp)
func (s *Server) GetHistory(scripthash string) ([]*GetMempoolResult, error) {
var resp GetMempoolResp

err := s.request("blockchain.scripthash.get_history", []interface{}{scripthash}, &resp)
if err != nil {
return nil, err
}
Expand All @@ -41,32 +50,35 @@ func (s *Server) GetHistory(scripthash string) ([]*MempoolResp, error) {
}

// GetMempool returns the unconfirmed transacations of a scripthash.
func (s *Server) GetMempool(scripthash string) ([]*MempoolResp, error) {
resp := &struct {
Result []*MempoolResp `json:"result"`
}{}
err := s.request("blockchain.scripthash.get_mempool", []interface{}{scripthash}, resp)
func (s *Server) GetMempool(scripthash string) ([]*GetMempoolResult, error) {
var resp GetMempoolResp

err := s.request("blockchain.scripthash.get_mempool", []interface{}{scripthash}, &resp)
if err != nil {
return nil, err
}

return resp.Result, err
}

// UnspentResp represents the response to ListUnspent()
type UnspentResp struct {
// ListUnspentResp represents the response to ListUnspent()
type ListUnspentResp struct {
Result []*ListUnspentResult `json:"result"`
}

// ListUnspentResult represents the content of the result field in the response to ListUnspent()
type ListUnspentResult struct {
Height uint32 `json:"height"`
Position uint32 `json:"tx_pos"`
Hash string `json:"tx_hash"`
Value uint64 `json:"value"`
}

// ListUnspent returns an ordered list of UTXOs for a scripthash.
func (s *Server) ListUnspent(scripthash string) ([]*UnspentResp, error) {
resp := &struct {
Result []*UnspentResp `json:"result"`
}{}
err := s.request("blockchain.scripthash.listunspent", []interface{}{scripthash}, resp)
func (s *Server) ListUnspent(scripthash string) ([]*ListUnspentResult, error) {
var resp ListUnspentResp

err := s.request("blockchain.scripthash.listunspent", []interface{}{scripthash}, &resp)
if err != nil {
return nil, err
}
Expand Down
49 changes: 30 additions & 19 deletions electrum/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,30 @@ func (s *Server) Ping() error {
// ServerAddPeer adds your new server into the remote server own peers list.
// This should not be used if you are a client.
// https://electrumx.readthedocs.io/en/latest/protocol-methods.html#server-add-peer
func (s *Server) ServerAddPeer(features *FeaturesResp) error {
resp := &basicResp{}
err := s.request("server.add_peer", []interface{}{features}, resp)
func (s *Server) ServerAddPeer(features *ServerFeaturesResult) error {
var resp basicResp

err := s.request("server.add_peer", []interface{}{features}, &resp)

return err
}

// ServerBanner returns the banner for this remote server.
// https://electrumx.readthedocs.io/en/latest/protocol-methods.html#server-banner
func (s *Server) ServerBanner() (string, error) {
resp := &basicResp{}
err := s.request("server.banner", []interface{}{}, resp)
var resp basicResp

err := s.request("server.banner", []interface{}{}, &resp)

return resp.Result, err
}

// ServerDonation returns the donation address for this remote server
// https://electrumx.readthedocs.io/en/latest/protocol-methods.html#server-donation-address
func (s *Server) ServerDonation() (string, error) {
resp := &basicResp{}
err := s.request("server.donation_address", []interface{}{}, resp)
var resp basicResp

err := s.request("server.donation_address", []interface{}{}, &resp)

return resp.Result, err
}
Expand All @@ -42,9 +45,14 @@ type host struct {
SSLPort uint16 `json:"ssl_port,omitempty"`
}

// FeaturesResp represent the data sent or receive in RPC call "server.features" and
// ServerFeaturesResp represent the response to GetFeatures().
type ServerFeaturesResp struct {
Result *ServerFeaturesResult `json:"result"`
}

// ServerFeaturesResult represent the data sent or receive in RPC call "server.features" and
// "server.add_peer".
type FeaturesResp struct {
type ServerFeaturesResult struct {
GenesisHash string `json:"genesis_hash"`
Hosts map[string]host `json:"hosts"`
ProtocolMax string `json:"protocol_max"`
Expand All @@ -56,11 +64,10 @@ type FeaturesResp struct {

// ServerFeatures returns a list of features and services supported by the remote server.
// https://electrumx.readthedocs.io/en/latest/protocol-methods.html#server-features
func (s *Server) ServerFeatures() (*FeaturesResp, error) {
resp := &struct {
Result *FeaturesResp `json:"result"`
}{}
err := s.request("server.features", []interface{}{}, resp)
func (s *Server) ServerFeatures() (*ServerFeaturesResult, error) {
var resp ServerFeaturesResp

err := s.request("server.features", []interface{}{}, &resp)

return resp.Result, err
}
Expand All @@ -71,19 +78,23 @@ func (s *Server) ServerPeers() (interface{}, error) {
resp := &struct {
Result [][]interface{} `json:"result"`
}{}
err := s.request("server.peers.subscribe", []interface{}{}, resp)
err := s.request("server.peers.subscribe", []interface{}{}, &resp)

return resp.Result, err
}

// ServerVersionResp represent the response to ServerVersion().
type ServerVersionResp struct {
Result [2]string `json:"result"`
}

// ServerVersion identify the client to the server, and negotiate the protocol version.
// This call must be sent first, or the server will default to an older protocol version.
// https://electrumx.readthedocs.io/en/latest/protocol-methods.html#server-version
func (s *Server) ServerVersion() (serverVer, protocolVer string, err error) {
resp := &struct {
Result []string `json:"result"`
}{}
err = s.request("server.version", []interface{}{ClientVersion, ProtocolVersion}, resp)
var resp ServerVersionResp

err = s.request("server.version", []interface{}{ClientVersion, ProtocolVersion}, &resp)
if err != nil {
serverVer = ""
protocolVer = ""
Expand Down
Loading

0 comments on commit 6d70e4a

Please sign in to comment.