globalrpc

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Feb 19, 2026 License: MIT Imports: 15 Imported by: 0

README

globalrpc

EVM RPC and WSS manager with nonce tracking.

Usage

Setup

  • define a configuration file as provided in the example below
  • Redis needs to be present and accessed via redisAddr and redisPw (password can be an empty string)
  • create an instance:
grpc, err := globalrpc.NewGlobalRpc(chainId, "rpc_config.json", redisAddr, redisPw)

RpcQuery (for read operations)

Retries across different RPC nodes. Return a NonRetryableError if retrying won't help.

result, err := globalrpc.RpcQuery(ctx, grpc, 4, 10*time.Second,
    func(ctx context.Context, rpc *ethclient.Client) ([]string, error) {
        return myFunction(poolId, rpc)
    },
)

RpcDial (for write operations)

Pins all calls to the same RPC node. Lock is automatically renewed until cleanup is called.

client, cleanup, err := globalrpc.RpcDial(ctx, grpc, globalrpc.TypeHTTPS)
if err != nil { return err }
defer cleanup()

Nonce Tracking

Redis-backed nonce counter. Seed on startup (always syncs from chain), then call Next() for each transaction:

tracker := grpc.NewNonceTracker(address)
tracker.Seed(ctx, client)
nonce, err := tracker.Next()

// on nonce error, resync from chain:
tracker.Seed(ctx, client)

RPC Config File Example

[
    {
        "chainId": 999,
        "https": [
            "https://rpc.hyperliquid.xyz/evm",
            "https://rpc.hypurrscan.io",
            "https://hyperliquid.drpc.org",
            "https://rpc.hyperlend.finance"
        ],
        "wss": [
            "wss://hyperliquid.drpc.org",
            "wss://api.hyperliquid.xyz/ws"
        ]
    },
    {
        "chainId": 989,
        "https": [
            "https://spectrum-01.simplystaking.xyz/hyperliquid-tn-rpc/evm",
            "https://rpc.hyperliquid-testnet.xyz/evm"
        ],
        "wss": []
    }
]

Documentation

Index

Constants

View Source
const (
	EXPIRY_SEC         = "10" // rpc locks expire after this amount of time
	REDIS_KEY_CURR_IDX = "glbl_rpc:idx"
	REDIS_KEY_URLS     = "glbl_rpc:urls"
	REDIS_KEY_LOCK     = "glbl_rpc:lock"
	REDIS_SET_URL_LOCK = "glbl_rpc:urls_lock"
)
View Source
const LUA_ACQUIRE = `` /* 370-byte string literal not displayed */
View Source
const LUA_NONCE_NEXT = `` /* 144-byte string literal not displayed */
View Source
const LUA_RELEASE = `
	if redis.call("GET", KEYS[1]) == ARGV[1] then
		return redis.call("DEL", KEYS[1])
	end
	return 0
`
View Source
const LUA_RENEW = `
	if redis.call("GET", KEYS[1]) == ARGV[1] then
		return redis.call("EXPIRE", KEYS[1], ARGV[2])
	end
	return 0
`
View Source
const REDIS_KEY_NONCE = "glbl_rpc:nonce:"

Variables

This section is empty.

Functions

func IsNonRetryable

func IsNonRetryable(err error) bool

IsNonRetryable reports whether err (or any error in its chain) is a NonRetryableError.

func NewNonRetryableError

func NewNonRetryableError(err error) error

NewNonRetryableError wraps err so that RpcQuery will not retry.

func RpcDial added in v0.1.1

func RpcDial(ctx context.Context, rpcH *GlobalRpc, rpcType RPCKind) (*ethclient.Client, func(), error)

func RpcQuery

func RpcQuery[T any](
	ctx context.Context,
	rpcH *GlobalRpc,
	attempts int,
	wait time.Duration,
	call func(ctx context.Context, rpc *ethclient.Client) (T, error),
) (T, error)

Types

type GlobalRpc

type GlobalRpc struct {
	Config RpcConfig
	// contains filtered or unexported fields
}

func NewGlobalRpc

func NewGlobalRpc(chainId int, configname, redisAddr, redisPw string) (*GlobalRpc, error)

func (*GlobalRpc) GetAndLockRpc

func (gr *GlobalRpc) GetAndLockRpc(ctx context.Context, rpcType RPCKind, maxWaitSec int) (Receipt, error)

func (*GlobalRpc) NewNonceTracker added in v0.1.1

func (gr *GlobalRpc) NewNonceTracker(address common.Address) NonceProvider

func (*GlobalRpc) ReturnLock

func (gr *GlobalRpc) ReturnLock(rec Receipt)

type NonRetryableError

type NonRetryableError struct {
	Err error
}

NonRetryableError wraps an error to signal that RpcQuery should not retry. Use NewNonRetryableError to wrap errors that indicate a previous attempt already had a side effect (e.g. a transaction was submitted).

func (*NonRetryableError) Error

func (e *NonRetryableError) Error() string

func (*NonRetryableError) Unwrap

func (e *NonRetryableError) Unwrap() error

type NonceProvider added in v0.1.1

type NonceProvider interface {
	Seed(ctx context.Context, client *ethclient.Client) error
	Next() (uint64, error)
}

type RPCKind

type RPCKind int
const (
	TypeHTTPS RPCKind = iota // Starts at 0
	TypeWSS                  // 1
)

func (RPCKind) String

func (t RPCKind) String() string

type Receipt

type Receipt struct {
	Url     string
	RpcType RPCKind
	// contains filtered or unexported fields
}

type RpcConfig

type RpcConfig struct {
	ChainId int      `json:"chainId"`
	Wss     []string `json:"wss"`
	Https   []string `json:"https"`
}

Jump to

Keyboard shortcuts

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