Documentation
¶
Overview ¶
Callback functions ¶
This library uses callback functions to allow the users to execute the code needed when certain events are triggered.
the ShipClient struct accepts the following callback functions
InitHandler func(*eos.ABI)
Called when the client receives the first message from the SHIP node on connection. This message contains the abi with all the information about the functions/types exposed by the websocket api.
BlockHandler func(*ship.GetBlocksResultV0)
Called when the client reveives a block message from the server.
TraceHandler func([]*ship.TransactionTraceV0)
When the client reveives a block message from the server and the Block has any traces attached to it. these traces are then passed to this callback.
StatusHandler func(*ship.GetStatusResultV0)
Called when the client reveives a status message.
CloseHandler func()
Called when a client has closed the socket connection (in `(*ShipClient) Close()` function)
Example (Basic) ¶
package main
import (
"context"
"log"
"os"
"os/signal"
"time"
eos "github.com/eoscanada/eos-go"
"github.com/eoscanada/eos-go/ship"
shipclient "github.com/eosswedenorg-go/antelope-ship-client"
)
// -----------------------------
// Config variables
// -----------------------------
// IP and port to the ship node.
var shipHost string = "127.0.0.1:8089"
// Url to the antelope api on the same node as ship is running.
// Use this to fetch a sane value for `startBlock`
var APIURL string // = "http://127.0.0.1:8088"
// If `APIURL` is not set, this is the block
// where we request ship to start sending blocks from.
// This should be something other than zero. check a block explorer or /v1/chain/get_info for the latest block number.
// or use APIURL to make the code fetch it itself.
var startBlock uint32 = 0
// True if the client should request a status message from the ship server on startup.
var sendStatus bool = true
// True if traces should be printed (this can get spammy)
var printTraces bool = false
func initHandler(abi *eos.ABI) {
log.Println("Server abi:", abi.Version)
}
func processBlock(block *ship.GetBlocksResultV0) {
if block.ThisBlock.BlockNum%100 == 0 {
log.Printf("Current: %d, Head: %d\n", block.ThisBlock.BlockNum, block.Head.BlockNum)
}
}
func processTraces(traces []*ship.TransactionTraceV0) {
for _, trace := range traces {
log.Println("Trace ID:", trace.ID)
}
}
func processStatus(status *ship.GetStatusResultV0) {
log.Println("-- Status --")
log.Println("Head", status.Head.BlockNum, status.Head.BlockID)
log.Println("ChainStateBeginBlock", status.ChainStateBeginBlock, "ChainStateEndBlock", status.ChainStateEndBlock)
}
func main() {
// Create done and interrupt channels.
done := make(chan bool)
interrupt := make(chan os.Signal, 1)
// Register interrupt channel to receive interrupt messages
signal.Notify(interrupt, os.Interrupt)
// Get start block from chain info
if APIURL != "" {
chainInfo, err := eos.New(APIURL).GetInfo(context.Background())
if err == nil {
startBlock = chainInfo.HeadBlockNum
} else {
log.Println("Failed to get info:", err)
return
}
}
log.Println("Connecting to ship starting at block:", startBlock)
client := shipclient.NewClient(startBlock, shipclient.NULL_BLOCK_NUMBER, false)
client.InitHandler = initHandler
client.BlockHandler = processBlock
client.StatusHandler = processStatus
// Only assign trace handler if printTraces is true.
if printTraces {
client.TraceHandler = processTraces
}
// Connect to SHIP client
err := client.Connect(shipHost)
if err != nil {
log.Println(err)
return
}
// Request streaming of blocks from ship
err = client.SendBlocksRequest()
if err != nil {
log.Println(err)
return
}
// Request status message from ship
if sendStatus {
err = client.SendStatusRequest()
if err != nil {
log.Println(err)
return
}
}
// Spawn message read loop in another thread.
go func() {
for {
err := client.Read()
if err != nil {
log.Print(err)
if e, ok := err.(shipclient.ShipClientError); ok {
if e.Type == shipclient.ErrSockRead {
break
}
}
}
}
client.Close()
// Client exited. signal that we are done.
done <- true
}()
// Enter event loop in main thread
for {
select {
case <-interrupt:
log.Println("Interrupt, closing")
// Cleanly close the connection by sending a close message and then
// waiting (with timeout) for the server to close the connection.
err := client.SendCloseMessage()
if err != nil {
log.Println("Failed to send close message", err)
}
select {
case <-done:
log.Println("Closed")
case <-time.After(time.Second * 4):
log.Println("Timeout")
}
return
case <-done:
log.Println("Closed")
return
}
}
}
Output:
Index ¶
- Constants
- type ShipClient
- func (c *ShipClient) Close() error
- func (c *ShipClient) Connect(host string) error
- func (c *ShipClient) ConnectURL(url url.URL) error
- func (c *ShipClient) IsOpen() bool
- func (c *ShipClient) Read() error
- func (c *ShipClient) ReadRaw() (int, []byte, error)
- func (c *ShipClient) SendACK() error
- func (c *ShipClient) SendBlocksRequest() error
- func (c *ShipClient) SendCloseMessage() error
- func (c *ShipClient) SendStatusRequest() error
- func (c ShipClient) UnconfirmedMessages() uint32
- type ShipClientError
Examples ¶
Constants ¶
const ( ErrNotConnected = iota ErrSockRead ErrSockClosed ErrSendClose ErrACK ErrParse )
const NULL_BLOCK_NUMBER uint32 = 0xffffffff
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ShipClient ¶
type ShipClient struct {
// Block to start receiving notifications on.
StartBlock uint32
// Block to end receiving notifications on.
EndBlock uint32
// if only irreversible blocks should be sent.
IrreversibleOnly bool
// Max number of non-ACKed messages that may be sent.
MaxMessagesInFlight uint32
// Callback functions
InitHandler func(*eos.ABI)
BlockHandler func(*ship.GetBlocksResultV0)
TraceHandler func([]*ship.TransactionTraceV0)
StatusHandler func(*ship.GetStatusResultV0)
CloseHandler func()
// contains filtered or unexported fields
}
func NewClient ¶
func NewClient(startBlock uint32, endBlock uint32, irreversibleOnly bool) *ShipClient
Create a new client
func (*ShipClient) Close ¶
func (c *ShipClient) Close() error
Close the socket on the client side.
NOTE: This method closes the underlying network connection without sending or waiting for a close message.
func (*ShipClient) Connect ¶
func (c *ShipClient) Connect(host string) error
Connect the client to a ship node
Returns an error if the connection fails, nil otherwise.
NOTE: this is equivalent to calling
c.ConnectURL(url.URL{Scheme: "ws", Host: host, Path: "/"})
func (*ShipClient) ConnectURL ¶
func (c *ShipClient) ConnectURL(url url.URL) error
Connect the client to a ship node
Returns an error if the connection fails, nil otherwise.
func (*ShipClient) IsOpen ¶
func (c *ShipClient) IsOpen() bool
Returns true if the websocket connection is open. false otherwise.
func (*ShipClient) Read ¶
func (c *ShipClient) Read() error
Read messages from the client and calls the appropriate callback function.
This function will block until atleast one valid message is processed or an error occured.
func (*ShipClient) SendACK ¶
func (c *ShipClient) SendACK() error
Sends an Acknowledgment message that tells th server that we have received X number of messages where X is the number returned by c.UnconfirmedMessages().
This is normally called internally by Read() So only use this manually if you know that you need to.
func (*ShipClient) SendBlocksRequest ¶
func (c *ShipClient) SendBlocksRequest() error
Send a blocks request to the ship server. This tells the server to start sending block message to the client.
func (*ShipClient) SendCloseMessage ¶
func (c *ShipClient) SendCloseMessage() error
Sends a close message to the server indicating that the client wants to terminate the connection.
func (*ShipClient) SendStatusRequest ¶
func (c *ShipClient) SendStatusRequest() error
Send a status request to the ship server. This tells the server to start sending status message to the client.
func (ShipClient) UnconfirmedMessages ¶
func (c ShipClient) UnconfirmedMessages() uint32
Returns the number of messages the client has received but have not yet been confirmed as having been received by the client
type ShipClientError ¶
func (ShipClientError) Error ¶
func (e ShipClientError) Error() string