listen to mempool.space websocket
This commit is contained in:
+100
-10
@@ -5,7 +5,11 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
@@ -14,19 +18,27 @@ var (
|
||||
ErrNotWebsocket = errors.New("provided addr was not websocket")
|
||||
)
|
||||
|
||||
const (
|
||||
WSEndpoint = "api/v1/ws"
|
||||
)
|
||||
|
||||
type mempool struct {
|
||||
addr string
|
||||
ws *websocket.Conn
|
||||
baseUrl string
|
||||
httpClient *http.Client
|
||||
ws *websocket.Conn
|
||||
}
|
||||
|
||||
func New(addr string) *mempool {
|
||||
func New(baseUrl string, httpClient *http.Client) *mempool {
|
||||
return &mempool{
|
||||
addr: addr,
|
||||
baseUrl: baseUrl,
|
||||
httpClient: &http.Client{
|
||||
Timeout: 5 * time.Second,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mempool) Init() error {
|
||||
u, err := url.Parse(m.addr)
|
||||
u, err := url.Parse(fmt.Sprintf("wss://%s/%s", m.baseUrl, WSEndpoint))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -40,15 +52,93 @@ func (m *mempool) Init() error {
|
||||
return err
|
||||
}
|
||||
|
||||
b, err := json.Marshal(struct {
|
||||
Action string `json:"action"`
|
||||
Data []string `json:"data"`
|
||||
}{
|
||||
Action: "want",
|
||||
Data: []string{"blocks", "stats"},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = c.WriteMessage(websocket.BinaryMessage, b); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.ws = c
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mempool) Listen(ctx context.Context, blocks chan Block, errs chan error, done chan struct{}) {
|
||||
func (m *mempool) CurrentBlockHeight() (int, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("https://%s/api/blocks/tip/height", m.baseUrl), nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
resp, err := m.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= http.StatusInternalServerError {
|
||||
return 0, errors.New("server error")
|
||||
}
|
||||
|
||||
if resp.StatusCode >= http.StatusBadRequest {
|
||||
return 0, errors.New("client error")
|
||||
}
|
||||
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return strconv.Atoi(string(b))
|
||||
}
|
||||
|
||||
func (m *mempool) CurrentFees() (int, int, int, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("https://%s/api/v1/fees/recommended", m.baseUrl), nil)
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
|
||||
resp, err := m.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= http.StatusInternalServerError {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
|
||||
if resp.StatusCode >= http.StatusBadRequest {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return 0, 0, 0, err
|
||||
}
|
||||
|
||||
var data struct {
|
||||
Fastest int `json:"fastestFee"`
|
||||
HalfHour int `json:"halfHourFee"`
|
||||
Hour int `json:"hourFee"`
|
||||
}
|
||||
|
||||
err = json.Unmarshal(b, &data)
|
||||
return data.Fastest, data.HalfHour, data.Hour, err
|
||||
}
|
||||
|
||||
func (m *mempool) Listen(ctx context.Context, messages chan Message, errs chan error, done chan struct{}) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
close(blocks)
|
||||
close(messages)
|
||||
close(errs)
|
||||
close(done)
|
||||
return
|
||||
@@ -59,14 +149,14 @@ func (m *mempool) Listen(ctx context.Context, blocks chan Block, errs chan error
|
||||
continue
|
||||
}
|
||||
|
||||
var b Block
|
||||
err = json.Unmarshal(message, &b)
|
||||
var m Message
|
||||
err = json.Unmarshal(message, &m)
|
||||
if err != nil {
|
||||
errs <- err
|
||||
continue
|
||||
}
|
||||
|
||||
blocks <- b
|
||||
messages <- m
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
package mempool
|
||||
|
||||
type Message struct {
|
||||
Block *Block `json:"block"`
|
||||
Conversions *Conversions `json:"conversions"`
|
||||
Fees *Fees `json:"fees"`
|
||||
}
|
||||
|
||||
type Block struct {
|
||||
Height int64 `json:"height"`
|
||||
}
|
||||
|
||||
type Conversions struct {
|
||||
USD int `json:"USD"`
|
||||
EUR int `json:"EUR"`
|
||||
GBP int `json:"GBP"`
|
||||
CAD int `json:"CAD"`
|
||||
CHF int `json:"CHF"`
|
||||
AUD int `json:"AUD"`
|
||||
JPY int `json:"JPY"`
|
||||
}
|
||||
|
||||
type Fees struct {
|
||||
FastestFee int `json:"fastestFee"`
|
||||
HalfHourFee int `json:"halfHourFee"`
|
||||
HourFee int `json:"hourFee"`
|
||||
EconomyFee int `json:"economyFee"`
|
||||
MinimumFee int `json:"minimumFee"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user