antelope_ship_client

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 30, 2022 License: MIT Imports: 6 Imported by: 2

README

Antelope SHIP Client

Test Go Reference

Client Implementation of Antelope state-history websocket.

Install package
go get -u github.com/eosswedenorg-go/antelope-ship-client@latest
Documentation

Documentation can be found over at pkg.go.dev

Examples
Author

Henrik Hautakoski - Sw/eden - henrik@eossweden.org

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
		}
	}
}

Index

Examples

Constants

View Source
const (
	ErrNotConnected = iota
	ErrSockRead
	ErrSockClosed
	ErrSendClose
	ErrACK
	ErrParse
)
View Source
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) ReadRaw

func (c *ShipClient) ReadRaw() (int, []byte, error)

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

type ShipClientError struct {
	Type int
	Text string
}

func (ShipClientError) Error

func (e ShipClientError) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL