Documentation
¶
Overview ¶
Package rpc provides the RPC API types for the Nitrolite Node service.
This file implements the API request and response definitions specified in api.yaml with versioned types organized by functional groups. All types follow the naming convention: {Group}{Version}{Name}{Request|Response}.
Package rpc provides a high-level client for interacting with the Nitrolite Node RPC server.
This file implements the V1 API client with versioned request/response types following the api.yaml specification.
Package rpc provides the core data structures and utilities for the Nitrolite Node RPC protocol.
This package implements a secure RPC communication protocol designed for blockchain and distributed systems. It provides strong typing, efficient encoding, and clear error handling with versioned API endpoints.
Protocol Overview ¶
The protocol uses a request-response pattern with compact JSON encoding:
- Messages use typed communication (request, response, event, error response)
- All messages include timestamps for replay protection
- Methods follow versioned naming: {group}.v{version}.{action}
- Responses preserve the request method for easy correlation
Core Types ¶
Messages are the fundamental unit of communication:
type Message struct {
Type MsgType // Message type: Req, Resp, Event, or RespErr
RequestID uint64 // Unique request identifier
Method string // RPC method name (e.g., "node.v1.ping")
Payload Payload // Method parameters or response data
Timestamp uint64 // Unix milliseconds timestamp
}
Message types:
MsgTypeReq = 1 // Request message MsgTypeResp = 2 // Success response message MsgTypeEvent = 3 // Server-initiated event notification MsgTypeRespErr = 4 // Error response message
JSON Encoding ¶
Messages use a compact array encoding for efficiency. A message like:
Message{
Type: MsgTypeReq,
RequestID: 12345,
Method: "node.v1.get_config",
Payload: {},
Timestamp: 1634567890123,
}
Encodes to:
[1, 12345, "node.v1.get_config", {}, 1634567890123]
This format reduces message size while maintaining readability and compatibility.
API Versioning ¶
All RPC methods follow a versioned naming convention:
{group}.v{version}.{action}
Examples:
node.v1.ping // Node group, version 1, ping action channels.v1.get_channels // Channels group, version 1, get channels action user.v1.get_balances // User group, version 1, get balances action
API groups:
- node: Node configuration and connectivity
- channels: Payment channel management and state
- app_sessions: Application session operations
- session_keys: Session key management
- user: User balances and transactions
Error Handling ¶
Error responses use MsgTypeRespErr and preserve the original request method:
// Success response
Message{Type: MsgTypeResp, Method: "node.v1.ping", ...}
// Error response
Message{Type: MsgTypeRespErr, Method: "node.v1.ping", Payload: {"error": "..."}}
Creating error responses:
// In a handler
if err := validate(request); err != nil {
return NewErrorResponse(request.RequestID, request.Method, err.Error())
}
Checking for errors in responses:
response, err := client.Call(ctx, &request)
if err != nil {
return err
}
if err := response.Error(); err != nil {
// Handle RPC error
return fmt.Errorf("RPC error: %w", err)
}
The package provides explicit error types for client communication:
// Client-facing error - will be sent in response
if amount < 0 {
return rpc.Errorf("invalid amount: cannot be negative")
}
// Internal error - generic message sent to client
if err := db.Save(); err != nil {
return fmt.Errorf("database error: %w", err)
}
Parameter Handling ¶
The Payload type provides flexible parameter handling with type safety:
// Creating payload from a struct
payload, err := rpc.NewPayload(NodeV1GetAssetsRequest{
ChainID: &chainID,
})
// Extracting payload into a struct
var resp NodeV1GetConfigResponse
err := response.Payload.Translate(&resp)
Client Communication ¶
The Client type provides convenient methods for all V1 RPC operations:
// Create client with WebSocket dialer
dialer := rpc.NewWebsocketDialer(rpc.DefaultWebsocketDialerConfig)
client := rpc.NewClient(dialer)
// Connect to server
err := client.Start(ctx, "wss://clearnode-sandbox.yellow.org/v1/ws", func(err error) {
if err != nil {
log.Error("Connection closed", "error", err)
}
})
if err != nil {
log.Fatal("Failed to start client", "error", err)
}
// Make RPC calls - Node methods
err = client.NodeV1Ping(ctx)
if err != nil {
log.Error("Ping failed", "error", err)
}
config, err := client.NodeV1GetConfig(ctx)
if err != nil {
log.Fatal(err)
}
log.Info("Connected to node", "address", config.NodeAddress)
// User methods
balances, err := client.UserV1GetBalances(ctx, rpc.UserV1GetBalancesRequest{
Wallet: walletAddress,
})
if err != nil {
log.Fatal(err)
}
for _, balance := range balances.Balances {
log.Info("Balance", "asset", balance.Asset, "amount", balance.Amount)
}
// Channel methods
channels, err := client.ChannelsV1GetChannels(ctx, rpc.ChannelsV1GetChannelsRequest{
Wallet: walletAddress,
})
if err != nil {
log.Fatal(err)
}
## Low-Level Dialer
For direct RPC communication without the convenience methods:
params, _ := rpc.NewPayload(map[string]string{"key": "value"})
request := rpc.NewRequest(12345, "node.v1.ping", params)
response, err := dialer.Call(ctx, &request)
if err != nil {
log.Error("RPC call failed", "error", err)
}
// Handle events manually
go func() {
for event := range dialer.EventCh() {
if event == nil {
break
}
log.Info("Received event", "method", event.Method)
}
}()
API Types ¶
The package includes comprehensive type definitions for the Nitrolite Node V1 RPC API:
Request/Response Types (organized by group):
- Node: NodeV1PingRequest/Response, NodeV1GetConfigRequest/Response, etc.
- Channels: ChannelsV1GetHomeChannelRequest/Response, etc.
- AppSessions: AppSessionsV1CreateAppSessionRequest/Response, etc.
- SessionKeys: SessionKeysV1RegisterRequest/Response, etc.
- User: UserV1GetBalancesRequest/Response, etc.
Common Types:
- ChannelV1: On-chain channel information
- StateV1: Channel state with transitions and ledgers
- TransactionV1: Transaction records
- AssetV1: Supported asset information
- BlockchainInfoV1: Supported network information
All types follow the naming convention: {Group}V{Version}{Name}{Request|Response}
Server Implementation ¶
The package provides a complete RPC server implementation through the WebsocketNode:
// Create and configure the server
config := rpc.WebsocketNodeConfig{
Logger: logger,
}
node, err := rpc.NewWebsocketNode(config)
if err != nil {
log.Fatal(err)
}
// Register handlers (built-in handlers are registered automatically)
// The node.v1.ping handler is registered by default
node.Handle("user.v1.get_balances", handleGetBalances)
node.Handle("channels.v1.get_channels", handleGetChannels)
// Add middleware
node.Use(loggingMiddleware)
node.Use(authMiddleware)
// Create handler groups
privateGroup := node.NewGroup("private")
privateGroup.Use(requireAuthMiddleware)
privateGroup.Handle("channels.v1.request_creation", handleCreateChannel)
// Start the server
http.Handle("/ws", node)
http.ListenAndServe(":8080", nil)
Writing handlers:
func handleGetBalances(c *rpc.Context) {
// Extract parameters
var req UserV1GetBalancesRequest
if err := c.Request.Payload.Translate(&req); err != nil {
c.Fail(nil, "invalid parameters")
return
}
// Process request
balances := getBalancesForWallet(req.Wallet)
// Create response
resp := UserV1GetBalancesResponse{
Balances: balances,
}
respPayload, _ := rpc.NewPayload(resp)
// Send response
c.Succeed("user.v1.get_balances", respPayload)
}
Writing middleware:
func authMiddleware(c *rpc.Context) {
// Check if connection is authenticated
if c.UserID == "" {
// Try to authenticate from request
token := extractToken(c.Request)
userID, err := validateToken(token)
if err != nil {
c.Fail(nil, "authentication required")
return
}
c.UserID = userID
}
// Continue to next handler
c.Next()
}
Security Considerations ¶
When using this protocol:
- Always validate timestamps to prevent replay attacks
- Use rpc.Errorf() for safe client-facing errors
- Thoroughly validate all parameters
- Use unique request IDs to prevent duplicate processing
- Implement proper authentication middleware
- Rate limit requests to prevent abuse
Example Usage ¶
Creating and sending a request:
// Create request
params, _ := rpc.NewPayload(NodeV1GetAssetsRequest{})
request := rpc.NewRequest(12345, "node.v1.get_assets", params)
// Marshal and send
data, _ := json.Marshal(request)
// ... send data over WebSocket ...
Processing a request:
// Unmarshal request
var request rpc.Message
err := json.Unmarshal(data, &request)
// Check message type
if request.Type != rpc.MsgTypeReq {
return rpc.NewErrorResponse(request.RequestID, request.Method, "invalid message type")
}
// Process based on method
switch request.Method {
case "node.v1.ping":
return rpc.NewResponse(request.RequestID, "node.v1.ping", rpc.Payload{})
case "user.v1.get_balances":
var params UserV1GetBalancesRequest
if err := request.Payload.Translate(¶ms); err != nil {
return rpc.NewErrorResponse(request.RequestID, request.Method, "invalid parameters")
}
// ... handle get balances ...
}
Testing ¶
The package includes a comprehensive test suite:
- client_test.go: Unit tests for all V1 client methods
- dialer_test.go: Tests for WebSocket dialer functionality
- message_test.go: Tests for message encoding/decoding
- payload_test.go: Tests for payload handling
Run tests with:
go test github.com/layer-3/nitrolite/pkg/rpc
Package rpc provides common method and event type definitions.
Package rpc provides the RPC API types for the Nitrolite Node service.
This file contains common types and structs shared across V1 API groups.
Index ¶
- Constants
- Variables
- type ActionAllowanceV1
- type AppAllocationV1
- type AppDefinitionV1
- type AppInfoV1
- type AppParticipantV1
- type AppSessionInfoV1
- type AppSessionKeyStateV1
- type AppSessionsV1CreateAppSessionRequest
- type AppSessionsV1CreateAppSessionResponse
- type AppSessionsV1GetAppDefinitionRequest
- type AppSessionsV1GetAppDefinitionResponse
- type AppSessionsV1GetAppSessionsRequest
- type AppSessionsV1GetAppSessionsResponse
- type AppSessionsV1GetLastKeyStatesRequest
- type AppSessionsV1GetLastKeyStatesResponse
- type AppSessionsV1RebalanceAppSessionsRequest
- type AppSessionsV1RebalanceAppSessionsResponse
- type AppSessionsV1SubmitAppStateRequest
- type AppSessionsV1SubmitAppStateResponse
- type AppSessionsV1SubmitDepositStateRequest
- type AppSessionsV1SubmitDepositStateResponse
- type AppSessionsV1SubmitSessionKeyStateRequest
- type AppSessionsV1SubmitSessionKeyStateResponse
- type AppStateUpdateV1
- type AppV1
- type AppsV1GetAppsRequest
- type AppsV1GetAppsResponse
- type AppsV1SubmitAppVersionRequest
- type AppsV1SubmitAppVersionResponse
- type AssetV1
- type BalanceEntryV1
- type BlockchainInfoV1
- type ChannelDefinitionV1
- type ChannelSessionKeyStateV1
- type ChannelV1
- type ChannelsV1GetChannelsRequest
- type ChannelsV1GetChannelsResponse
- type ChannelsV1GetEscrowChannelRequest
- type ChannelsV1GetEscrowChannelResponse
- type ChannelsV1GetHomeChannelRequest
- type ChannelsV1GetHomeChannelResponse
- type ChannelsV1GetLastKeyStatesRequest
- type ChannelsV1GetLastKeyStatesResponse
- type ChannelsV1GetLatestStateRequest
- type ChannelsV1GetLatestStateResponse
- type ChannelsV1GetStatesRequest
- type ChannelsV1GetStatesResponse
- type ChannelsV1HomeChannelCreatedEvent
- type ChannelsV1RequestCreationRequest
- type ChannelsV1RequestCreationResponse
- type ChannelsV1SubmitSessionKeyStateRequest
- type ChannelsV1SubmitSessionKeyStateResponse
- type ChannelsV1SubmitStateRequest
- type ChannelsV1SubmitStateResponse
- type Client
- func (c *Client) AppSessionsV1CreateAppSession(ctx context.Context, req AppSessionsV1CreateAppSessionRequest) (AppSessionsV1CreateAppSessionResponse, error)
- func (c *Client) AppSessionsV1GetAppDefinition(ctx context.Context, req AppSessionsV1GetAppDefinitionRequest) (AppSessionsV1GetAppDefinitionResponse, error)
- func (c *Client) AppSessionsV1GetAppSessions(ctx context.Context, req AppSessionsV1GetAppSessionsRequest) (AppSessionsV1GetAppSessionsResponse, error)
- func (c *Client) AppSessionsV1GetLastKeyStates(ctx context.Context, req AppSessionsV1GetLastKeyStatesRequest) (AppSessionsV1GetLastKeyStatesResponse, error)
- func (c *Client) AppSessionsV1RebalanceAppSessions(ctx context.Context, req AppSessionsV1RebalanceAppSessionsRequest) (AppSessionsV1RebalanceAppSessionsResponse, error)
- func (c *Client) AppSessionsV1SubmitAppState(ctx context.Context, req AppSessionsV1SubmitAppStateRequest) (AppSessionsV1SubmitAppStateResponse, error)
- func (c *Client) AppSessionsV1SubmitDepositState(ctx context.Context, req AppSessionsV1SubmitDepositStateRequest) (AppSessionsV1SubmitDepositStateResponse, error)
- func (c *Client) AppSessionsV1SubmitSessionKeyState(ctx context.Context, req AppSessionsV1SubmitSessionKeyStateRequest) (AppSessionsV1SubmitSessionKeyStateRequest, error)
- func (c *Client) AppsV1GetApps(ctx context.Context, req AppsV1GetAppsRequest) (AppsV1GetAppsResponse, error)
- func (c *Client) AppsV1SubmitAppVersion(ctx context.Context, req AppsV1SubmitAppVersionRequest) (AppsV1SubmitAppVersionResponse, error)
- func (c *Client) ChannelsV1GetChannels(ctx context.Context, req ChannelsV1GetChannelsRequest) (ChannelsV1GetChannelsResponse, error)
- func (c *Client) ChannelsV1GetEscrowChannel(ctx context.Context, req ChannelsV1GetEscrowChannelRequest) (ChannelsV1GetEscrowChannelResponse, error)
- func (c *Client) ChannelsV1GetHomeChannel(ctx context.Context, req ChannelsV1GetHomeChannelRequest) (ChannelsV1GetHomeChannelResponse, error)
- func (c *Client) ChannelsV1GetLastKeyStates(ctx context.Context, req ChannelsV1GetLastKeyStatesRequest) (ChannelsV1GetLastKeyStatesResponse, error)
- func (c *Client) ChannelsV1GetLatestState(ctx context.Context, req ChannelsV1GetLatestStateRequest) (ChannelsV1GetLatestStateResponse, error)
- func (c *Client) ChannelsV1GetStates(ctx context.Context, req ChannelsV1GetStatesRequest) (ChannelsV1GetStatesResponse, error)
- func (c *Client) ChannelsV1RequestCreation(ctx context.Context, req ChannelsV1RequestCreationRequest) (ChannelsV1RequestCreationResponse, error)
- func (c *Client) ChannelsV1SubmitSessionKeyState(ctx context.Context, req ChannelsV1SubmitSessionKeyStateRequest) (ChannelsV1SubmitSessionKeyStateResponse, error)
- func (c *Client) ChannelsV1SubmitState(ctx context.Context, req ChannelsV1SubmitStateRequest) (ChannelsV1SubmitStateResponse, error)
- func (c *Client) NodeV1GetAssets(ctx context.Context, req NodeV1GetAssetsRequest) (NodeV1GetAssetsResponse, error)
- func (c *Client) NodeV1GetConfig(ctx context.Context) (NodeV1GetConfigResponse, error)
- func (c *Client) NodeV1Ping(ctx context.Context) error
- func (c *Client) Start(ctx context.Context, url string, handleClosure func(err error)) error
- func (c *Client) UserV1GetActionAllowances(ctx context.Context, req UserV1GetActionAllowancesRequest) (UserV1GetActionAllowancesResponse, error)
- func (c *Client) UserV1GetBalances(ctx context.Context, req UserV1GetBalancesRequest) (UserV1GetBalancesResponse, error)
- func (c *Client) UserV1GetTransactions(ctx context.Context, req UserV1GetTransactionsRequest) (UserV1GetTransactionsResponse, error)
- type Connection
- type ConnectionHub
- type Context
- type Dialer
- type Error
- type Event
- type GorillaWsConnectionAdapter
- type Group
- type Handler
- type HandlerGroup
- type LedgerV1
- type Message
- func NewErrorResponse(requestID uint64, method string, errMsg string) Message
- func NewEvent(requestID uint64, method string, params Payload) Message
- func NewMessage(typ MsgType, id uint64, method string, params Payload) Message
- func NewRequest(requestID uint64, method string, params Payload) Message
- func NewResponse(requestID uint64, method string, params Payload) Message
- type Method
- type MsgType
- type Node
- type NodeV1GetAssetsRequest
- type NodeV1GetAssetsResponse
- type NodeV1GetConfigRequest
- type NodeV1GetConfigResponse
- type NodeV1PingRequest
- type NodeV1PingResponse
- type ObserveConnectionsFn
- type PaginationMetadataV1
- type PaginationParamsV1
- type Payload
- type SafeStorage
- type SendResponseFunc
- type SignedAppStateUpdateV1
- type StateV1
- type TokenV1
- type TransactionV1
- type TransitionV1
- type UserV1GetActionAllowancesRequest
- type UserV1GetActionAllowancesResponse
- type UserV1GetBalancesRequest
- type UserV1GetBalancesResponse
- type UserV1GetTransactionsRequest
- type UserV1GetTransactionsResponse
- type WebsocketConnection
- func (conn *WebsocketConnection) ConnectionID() string
- func (conn *WebsocketConnection) Origin() string
- func (conn *WebsocketConnection) RawRequests() <-chan []byte
- func (conn *WebsocketConnection) Serve(parentCtx context.Context, handleClosure func(error))
- func (conn *WebsocketConnection) WriteRawResponse(message []byte) bool
- type WebsocketConnectionConfig
- type WebsocketDialer
- type WebsocketDialerConfig
- type WebsocketHandlerGroup
- type WebsocketNode
- func (wn *WebsocketNode) Handle(method string, handler Handler)
- func (wn *WebsocketNode) NewGroup(name string) HandlerGroup
- func (wn *WebsocketNode) Notify(userID, method string, params Payload)
- func (wn *WebsocketNode) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (wn *WebsocketNode) Use(middleware Handler)
- type WebsocketNodeConfig
Constants ¶
const ( // Channels Group - V1 Methods ChannelV1Group Group = "channels.v1" ChannelsV1GetHomeChannelMethod Method = "channels.v1.get_home_channel" ChannelsV1GetEscrowChannelMethod Method = "channels.v1.get_escrow_channel" ChannelsV1GetChannelsMethod Method = "channels.v1.get_channels" ChannelsV1GetLatestStateMethod Method = "channels.v1.get_latest_state" ChannelsV1GetStatesMethod Method = "channels.v1.get_states" ChannelsV1RequestCreationMethod Method = "channels.v1.request_creation" ChannelsV1SubmitStateMethod Method = "channels.v1.submit_state" ChannelsV1SubmitSessionKeyStateMethod Method = "channels.v1.submit_session_key_state" ChannelsV1GetLastKeyStatesMethod Method = "channels.v1.get_last_key_states" // App Sessions Group - V1 Methods AppSessionsV1Group Group = "app_sessions.v1" AppSessionsV1SubmitDepositStateMethod Method = "app_sessions.v1.submit_deposit_state" AppSessionsV1SubmitAppStateMethod Method = "app_sessions.v1.submit_app_state" AppSessionsV1RebalanceAppSessionsMethod Method = "app_sessions.v1.rebalance_app_sessions" AppSessionsV1GetAppDefinitionMethod Method = "app_sessions.v1.get_app_definition" AppSessionsV1GetAppSessionsMethod Method = "app_sessions.v1.get_app_sessions" AppSessionsV1CreateAppSessionMethod Method = "app_sessions.v1.create_app_session" AppSessionsV1SubmitSessionKeyStateMethod Method = "app_sessions.v1.submit_session_key_state" AppSessionsV1GetLastKeyStatesMethod Method = "app_sessions.v1.get_last_key_states" // Apps Group - V1 Methods AppsV1Group Group = "apps.v1" AppsV1GetAppsMethod Method = "apps.v1.get_apps" AppsV1SubmitAppVersionMethod Method = "apps.v1.submit_app_version" // User Group - V1 Methods UserV1Group Group = "user.v1" UserV1GetBalancesMethod Method = "user.v1.get_balances" UserV1GetTransactionsMethod Method = "user.v1.get_transactions" UserV1GetActionAllowancesMethod Method = "user.v1.get_action_allowances" // Node Group - V1 Methods NodeV1Group Group = "node.v1" NodeV1PingMethod Method = "node.v1.ping" NodeV1GetConfigMethod Method = "node.v1.get_config" NodeV1GetAssetsMethod Method = "node.v1.get_assets" )
Variables ¶
var ( // Connection errors ErrAlreadyConnected = fmt.Errorf("already connected") ErrNotConnected = fmt.Errorf("not connected to server") ErrConnectionTimeout = fmt.Errorf("websocket connection timeout") ErrReadingMessage = fmt.Errorf("error reading message") // Request/Response errors ErrNilRequest = fmt.Errorf("nil request") ErrInvalidRequestMethod = fmt.Errorf("invalid request method") ErrMarshalingRequest = fmt.Errorf("error marshaling request") ErrSendingRequest = fmt.Errorf("error sending request") ErrNoResponse = fmt.Errorf("no response received") ErrSendingPing = fmt.Errorf("error sending ping") // WebSocket-specific errors ErrDialingWebsocket = fmt.Errorf("error dialing websocket server") )
Dialer error messages
var DefaultWebsocketDialerConfig = WebsocketDialerConfig{ HandshakeTimeout: 5 * time.Second, PingTimeout: 15 * time.Second, EventChanSize: 100, }
DefaultWebsocketDialerConfig provides sensible defaults for WebSocket connections
Functions ¶
This section is empty.
Types ¶
type ActionAllowanceV1 ¶
type ActionAllowanceV1 struct {
// GatedAction is the specific action being gated (e.g. transfer, app_operation)
GatedAction core.GatedAction `json:"gated_action"`
// TimeWindow is the time window for which the allowance is valid (e.g. "1h", "24h")
TimeWindow string `json:"time_window"`
// Allowance is the total allowance for the gated action within the time window
Allowance string `json:"allowance"`
// Used is the amount of the allowance that has already been used within the time window
Used string `json:"used"`
}
ActionAllowanceV1 represents the allowance information for a specific gated action.
type AppAllocationV1 ¶
type AppAllocationV1 struct {
// Participant is the participant's wallet address
Participant string `json:"participant"`
// Asset is the asset symbol
Asset string `json:"asset"`
// Amount is the amount allocated to the participant
Amount string `json:"amount"`
}
AppAllocationV1 represents the allocation of assets to a participant in an app session.
type AppDefinitionV1 ¶
type AppDefinitionV1 struct {
// Application is the application identifier from an app registry
Application string `json:"application_id"`
// Participants is the list of participants in the app session
Participants []AppParticipantV1 `json:"participants"`
// Quorum is the quorum required for the app session
Quorum uint8 `json:"quorum"`
// Nonce is a unique number to prevent replay attacks
Nonce string `json:"nonce"`
}
AppDefinitionV1 represents the definition for an app session.
type AppInfoV1 ¶
type AppInfoV1 struct {
AppV1
// CreatedAt is the creation timestamp (unix seconds)
CreatedAt string `json:"created_at"`
// UpdatedAt is the last update timestamp (unix seconds)
UpdatedAt string `json:"updated_at"`
}
AppInfoV1 represents full application info including timestamps.
type AppParticipantV1 ¶
type AppParticipantV1 struct {
// WalletAddress is the participant's wallet address
WalletAddress string `json:"wallet_address"`
// SignatureWeight is the signature weight for the participant
SignatureWeight uint8 `json:"signature_weight"`
}
AppParticipantV1 represents the definition for an app participant.
type AppSessionInfoV1 ¶
type AppSessionInfoV1 struct {
// AppSessionID is the unique application session identifier
AppSessionID string `json:"app_session_id"`
// Status is the session status (open/closed)
Status string `json:"status"`
// AppDefinitionV1 contains immutable application fields
AppDefinitionV1 AppDefinitionV1 `json:"app_definition"`
// SessionData is the JSON stringified session data
SessionData *string `json:"session_data,omitempty"`
// Version is the current version of the session state
Version string `json:"version"`
// Nonce is the nonce for the session
Allocations []AppAllocationV1 `json:"allocations"`
}
AppSessionInfoV1 represents information about an application session.
type AppSessionKeyStateV1 ¶
type AppSessionKeyStateV1 struct {
// ID Hash(user_address + session_key + version)
// UserAddress is the user wallet address
UserAddress string `json:"user_address"`
// SessionKey is the session key address for delegation
SessionKey string `json:"session_key"`
// Version is the version of the session key format
Version string `json:"version"`
// ApplicationID is the application IDs associated with this session key
ApplicationIDs []string `json:"application_ids"`
// AppSessionID is the application session IDs associated with this session key
AppSessionIDs []string `json:"app_session_ids"`
// ExpiresAt is Unix timestamp in seconds indicating when the session key expires
ExpiresAt string `json:"expires_at"`
// UserSig is the user's signature over the session key metadata to authorize the registration/update of the session key
UserSig string `json:"user_sig"`
}
AppSessionKeyStateV1 represents the state of a session key.
type AppSessionsV1CreateAppSessionRequest ¶
type AppSessionsV1CreateAppSessionRequest struct {
// Definition is the application definition including participants and quorum
Definition AppDefinitionV1 `json:"definition"`
// SessionData is the optional JSON stringified session data
SessionData string `json:"session_data"`
// QuorumSigs is the list of participant signatures for the app session creation
QuorumSigs []string `json:"quorum_sigs,omitempty"`
// OwnerSig is the optional owner signature for app session creation if approval required by the app registry
OwnerSig string `json:"owner_sig,omitempty"`
}
AppSessionsV1CreateAppSessionRequest creates a new application session between participants.
type AppSessionsV1CreateAppSessionResponse ¶
type AppSessionsV1CreateAppSessionResponse struct {
// AppSessionID is the created application session ID
AppSessionID string `json:"app_session_id"`
// Version is the initial version of the session
Version string `json:"version"`
// Status is the status of the session (closed)
Status string `json:"status"`
}
AppSessionsV1CreateAppSessionResponse returns the created application session information.
type AppSessionsV1GetAppDefinitionRequest ¶
type AppSessionsV1GetAppDefinitionRequest struct {
// AppSessionID is the application session ID
AppSessionID string `json:"app_session_id"`
}
AppSessionsV1GetAppDefinitionRequest retrieves the application definition for a specific app session.
type AppSessionsV1GetAppDefinitionResponse ¶
type AppSessionsV1GetAppDefinitionResponse struct {
// Definition is the application definition
Definition AppDefinitionV1 `json:"definition"`
}
AppSessionsV1GetAppDefinitionResponse returns the application definition.
type AppSessionsV1GetAppSessionsRequest ¶
type AppSessionsV1GetAppSessionsRequest struct {
// AppSessionID filters by application session ID
AppSessionID *string `json:"app_session_id,omitempty"`
// Participant filters by participant wallet address
Participant *string `json:"participant,omitempty"`
// Status filters by status (open/closed)
Status *string `json:"status,omitempty"`
// Pagination contains pagination parameters (offset, limit, sort)
Pagination *PaginationParamsV1 `json:"pagination,omitempty"`
}
AppSessionsV1GetAppSessionsRequest lists all application sessions for a participant with optional filtering.
type AppSessionsV1GetAppSessionsResponse ¶
type AppSessionsV1GetAppSessionsResponse struct {
// AppSessions is the list of application sessions
AppSessions []AppSessionInfoV1 `json:"app_sessions"`
// Metadata contains pagination information
Metadata PaginationMetadataV1 `json:"metadata"`
}
AppSessionsV1GetAppSessionsResponse returns the list of application sessions.
type AppSessionsV1GetLastKeyStatesRequest ¶
type AppSessionsV1GetLastKeyStatesRequest struct {
// UserAddress is the user's wallet address
UserAddress string `json:"user_address"`
SessionKey *string `json:"session_key,omitempty"` // Optionally filter by SessionKey
}
AppSessionsV1GetLastKeyStatesRequest retrieves the latest session key states for a user with optional filtering by session key.
type AppSessionsV1GetLastKeyStatesResponse ¶
type AppSessionsV1GetLastKeyStatesResponse struct {
// States is the list of active session key states for the user
States []AppSessionKeyStateV1 `json:"states"`
}
SessionKeysV1GetSessionKeysResponse returns the list of active session keys.
type AppSessionsV1RebalanceAppSessionsRequest ¶
type AppSessionsV1RebalanceAppSessionsRequest struct {
// SignedUpdates is the list of signed application session state updates
SignedUpdates []SignedAppStateUpdateV1 `json:"signed_updates"`
}
AppSessionsV1RebalanceAppSessionsRequest rebalances multiple application sessions atomically.
type AppSessionsV1RebalanceAppSessionsResponse ¶
type AppSessionsV1RebalanceAppSessionsResponse struct {
// BatchID is the unique identifier for this rebalancing operation
BatchID string `json:"batch_id"`
}
AppSessionsV1RebalanceAppSessionsResponse returns the batch ID for the rebalancing operation.
type AppSessionsV1SubmitAppStateRequest ¶
type AppSessionsV1SubmitAppStateRequest struct {
// AppStateUpdate is the application session state update to be submitted
AppStateUpdate AppStateUpdateV1 `json:"app_state_update"`
// QuorumSigs is the signature quorum for the application session
QuorumSigs []string `json:"quorum_sigs"`
}
AppSessionsV1SubmitAppStateRequest submits an application session state update.
type AppSessionsV1SubmitAppStateResponse ¶
type AppSessionsV1SubmitAppStateResponse struct{}
AppSessionsV1SubmitAppStateResponse returns the Node's signature for the new User state.
type AppSessionsV1SubmitDepositStateRequest ¶
type AppSessionsV1SubmitDepositStateRequest struct {
// AppStateUpdate is the application session state update to be submitted
AppStateUpdate AppStateUpdateV1 `json:"app_state_update"`
// QuorumSigs is the list of participant signatures for the app state update
QuorumSigs []string `json:"quorum_sigs"`
// SigQuorum is the signature quorum for the application session
UserState StateV1 `json:"user_state"`
}
AppSessionsV1SubmitDepositStateRequest submits an application session state update.
type AppSessionsV1SubmitDepositStateResponse ¶
type AppSessionsV1SubmitDepositStateResponse struct {
// StateNodeSig is the Node's signature for the deposit state
StateNodeSig string `json:"signature"`
}
AppSessionsV1SubmitDepositStateResponse returns the Node's signature for the deposit state.
type AppSessionsV1SubmitSessionKeyStateRequest ¶
type AppSessionsV1SubmitSessionKeyStateRequest struct {
// State contains the session key metadata and delegation information
State AppSessionKeyStateV1 `json:"state"`
}
AppSessionsV1SubmitSessionKeyStateRequest submits the session key state for registration and updates.
type AppSessionsV1SubmitSessionKeyStateResponse ¶
type AppSessionsV1SubmitSessionKeyStateResponse struct {
}
AppSessionsV1SubmitSessionKeyStateResponse returns the result of session key state submission.
type AppStateUpdateV1 ¶
type AppStateUpdateV1 struct {
// AppSessionID is the unique application session identifier
AppSessionID string `json:"app_session_id"`
// Intent is the intent of the app session update (operate, deposit, withdraw, close)
Intent app.AppStateUpdateIntent `json:"intent"`
// Version is the version of the app state
Version string `json:"version"`
// Allocations is the list of allocations in the app state
Allocations []AppAllocationV1 `json:"allocations"`
// SessionData is the JSON stringified session data
SessionData string `json:"session_data"`
}
AppStateUpdateV1 represents the current state of an application session.
type AppV1 ¶
type AppV1 struct {
// ID is the application identifier
ID string `json:"id"`
// OwnerWallet is the owner's wallet address
OwnerWallet string `json:"owner_wallet"`
// Metadata is the application metadata
Metadata string `json:"metadata"`
// Version is the current version
Version string `json:"version"`
// CreationApprovalNotRequired indicates if sessions can be created without approval
CreationApprovalNotRequired bool `json:"creation_approval_not_required"`
}
AppV1 represents a registered application definition (without timestamps).
type AppsV1GetAppsRequest ¶
type AppsV1GetAppsRequest struct {
// AppID filters by application ID
AppID *string `json:"app_id,omitempty"`
// OwnerWallet filters by owner wallet address
OwnerWallet *string `json:"owner_wallet,omitempty"`
// Pagination contains pagination parameters (offset, limit, sort)
Pagination *PaginationParamsV1 `json:"pagination,omitempty"`
}
AppsV1GetAppsRequest retrieves registered applications with optional filtering.
type AppsV1GetAppsResponse ¶
type AppsV1GetAppsResponse struct {
// Apps is the list of registered applications
Apps []AppInfoV1 `json:"apps"`
// Metadata contains pagination information
Metadata PaginationMetadataV1 `json:"metadata"`
}
AppsV1GetAppsResponse returns the list of registered applications.
type AppsV1SubmitAppVersionRequest ¶
type AppsV1SubmitAppVersionRequest struct {
// App contains the application definition
App AppV1 `json:"app"`
// OwnerSig is the owner's signature over the packed app data
OwnerSig string `json:"owner_sig"`
}
AppsV1SubmitAppVersionRequest submits a new application version (currently only creation is supported).
type AppsV1SubmitAppVersionResponse ¶
type AppsV1SubmitAppVersionResponse struct {
}
AppsV1SubmitAppVersionResponse returns the result of the application version submission.
type AssetV1 ¶
type AssetV1 struct {
// Name is the asset name
Name string `json:"name"`
// Symbol is the asset symbol
Symbol string `json:"symbol"`
// Decimals is the number of decimal places for the asset
Decimals uint8 `json:"decimals"`
// SuggestedBlockchainID is the suggested blockchain network ID for this asset
SuggestedBlockchainID string `json:"suggested_blockchain_id"`
// Tokens is the list of supported tokens for the asset
Tokens []TokenV1 `json:"tokens"`
}
AssetV1 represents information about a supported asset.
type BalanceEntryV1 ¶
type BalanceEntryV1 struct {
// Asset is the asset symbol
Asset string `json:"asset"`
// Amount is the balance amount
Amount string `json:"amount"`
}
BalanceEntryV1 represents a balance for a specific asset.
type BlockchainInfoV1 ¶
type BlockchainInfoV1 struct {
// Name is the blockchain name
Name string `json:"name"`
// BlockchainID is the blockchain network ID
BlockchainID string `json:"blockchain_id"`
// ChannelHubAddress is the contract address on this network
ChannelHubAddress string `json:"channel_hub_address"`
// LockingContractAddress is the contract address for the locking contract on this network
LockingContractAddress string `json:"locking_contract_address"`
}
BlockchainInfoV1 represents information about a supported network.
type ChannelDefinitionV1 ¶
type ChannelDefinitionV1 struct {
// Nonce is a unique number to prevent replay attacks
Nonce string `json:"nonce"`
// Challenge is the challenge period for the channel in seconds
Challenge uint32 `json:"challenge"`
// ApprovedSigValidators is a hex string bitmap representing the approved signature validators for the channel
ApprovedSigValidators string `json:"approved_sig_validators"`
}
ChannelDefinitionV1 represents the configuration for creating a channel.
type ChannelSessionKeyStateV1 ¶
type ChannelSessionKeyStateV1 struct {
// ID Hash(user_address + session_key + version)
// UserAddress is the user wallet address
UserAddress string `json:"user_address"`
// SessionKey is the session key address for delegation
SessionKey string `json:"session_key"`
// Version is the version of the session key format
Version string `json:"version"`
// Assets associated with this session key
Assets []string `json:"assets"`
// Expiration time as unix timestamp of this session key
ExpiresAt string `json:"expires_at"`
// UserSig is the user's signature over the session key metadata to authorize the registration/update of the session key
UserSig string `json:"user_sig"`
}
ChannelSessionKeyStateV1 represents the state of a session key.
type ChannelV1 ¶
type ChannelV1 struct {
// ChannelID is the unique identifier for the channel
ChannelID string `json:"channel_id"`
// UserWallet is the user wallet address
UserWallet string `json:"user_wallet"`
// Asset is the asset symbol (e.g. USDC, ETH)
Asset string `json:"asset"`
// Type is the type of the channel (home, escrow)
Type string `json:"type"`
// BlockchainID is the unique identifier for the blockchain
BlockchainID string `json:"blockchain_id"`
// TokenAddress is the address of the token used in the channel
TokenAddress string `json:"token_address"`
// ChallengeDuration is the challenge period for the channel in seconds
ChallengeDuration uint32 `json:"challenge_duration"`
// ChallegeExpiresAt
ChallengeExpiresAt *time.Time `json:"challenge_expires_at"`
// Nonce is the nonce for the channel
Nonce string `json:"nonce"`
// ApprovedSigValidators is a hex string bitmap of approved signature validators
ApprovedSigValidators string `json:"approved_sig_validators"`
// Status is the current status of the channel (void, open, challenged, closed)
Status string `json:"status"`
// StateVersion is the on-chain state version of the channel
StateVersion string `json:"state_version"`
}
ChannelV1 represents an on-chain channel.
type ChannelsV1GetChannelsRequest ¶
type ChannelsV1GetChannelsRequest struct {
// Wallet filters by user's wallet address
Wallet string `json:"wallet"`
// Status filters by status
Status *string `json:"status,omitempty"`
// Asset filters by asset
Asset *string `json:"asset,omitempty"`
// ChannelType filters by channel type ("home" or "escrow")
ChannelType *string `json:"channel_type,omitempty"`
// Pagination contains pagination parameters (offset, limit, sort)
Pagination *PaginationParamsV1 `json:"pagination,omitempty"`
}
ChannelsV1GetChannelsRequest retrieves all channels for a user with optional filtering.
type ChannelsV1GetChannelsResponse ¶
type ChannelsV1GetChannelsResponse struct {
// Channels is the list of channels
Channels []ChannelV1 `json:"channels"`
// Metadata contains pagination information
Metadata PaginationMetadataV1 `json:"metadata"`
}
ChannelsV1GetChannelsResponse returns the list of channels.
type ChannelsV1GetEscrowChannelRequest ¶
type ChannelsV1GetEscrowChannelRequest struct {
// EscrowChannelID is the escrow channel ID
EscrowChannelID string `json:"escrow_channel_id"`
}
ChannelsV1GetEscrowChannelRequest retrieves current on-chain escrow channel information.
type ChannelsV1GetEscrowChannelResponse ¶
type ChannelsV1GetEscrowChannelResponse struct {
// Channel is the on-chain channel information
Channel ChannelV1 `json:"channel"`
}
ChannelsV1GetEscrowChannelResponse returns the on-chain channel information.
type ChannelsV1GetHomeChannelRequest ¶
type ChannelsV1GetHomeChannelRequest struct {
// UserWallet is the user's wallet address
Wallet string `json:"wallet"`
// Asset is the asset symbol
Asset string `json:"asset"`
}
ChannelsV1GetHomeChannelRequest retrieves current on-chain home channel information.
type ChannelsV1GetHomeChannelResponse ¶
type ChannelsV1GetHomeChannelResponse struct {
// Channel is the on-chain channel information
Channel ChannelV1 `json:"channel"`
}
ChannelsV1GetHomeChannelResponse returns the on-chain channel information.
type ChannelsV1GetLastKeyStatesRequest ¶
type ChannelsV1GetLastKeyStatesRequest struct {
// UserAddress is the user's wallet address
UserAddress string `json:"user_address"`
SessionKey *string `json:"session_key,omitempty"` // Optionally filter by SessionKey
}
ChannelsV1GetLastKeyStatesRequest retrieves the latest session key states for a user with optional filtering by session key.
type ChannelsV1GetLastKeyStatesResponse ¶
type ChannelsV1GetLastKeyStatesResponse struct {
// States is the list of active session key states for the user
States []ChannelSessionKeyStateV1 `json:"states"`
}
ChannelsV1GetSessionKeysResponse returns the list of active session keys.
type ChannelsV1GetLatestStateRequest ¶
type ChannelsV1GetLatestStateRequest struct {
// UserWallet is the user's wallet address
Wallet string `json:"wallet"`
// Asset is the asset symbol
Asset string `json:"asset"`
// OnlySigned can be enabled to get the latest signed state to know what is the current pending transition
OnlySigned bool `json:"only_signed"`
}
ChannelsV1GetLatestStateRequest retrieves the current state of the user stored on the Node.
type ChannelsV1GetLatestStateResponse ¶
type ChannelsV1GetLatestStateResponse struct {
// State is the current state of the user
State StateV1 `json:"state"`
}
ChannelsV1GetLatestStateResponse returns the current state of the user.
type ChannelsV1GetStatesRequest ¶
type ChannelsV1GetStatesRequest struct {
// Wallet is the user's wallet address
Wallet string `json:"wallet"`
// Asset filters by asset symbol
Asset string `json:"asset"`
// Epoch filters by user epoch index
Epoch *string `json:"epoch,omitempty"`
// ChannelID filters by Home/Escrow Channel ID
ChannelID *string `json:"channel_id,omitempty"`
// OnlySigned returns only signed states
OnlySigned bool `json:"only_signed"`
// Pagination contains pagination parameters (offset, limit, sort)
Pagination *PaginationParamsV1 `json:"pagination,omitempty"`
}
ChannelsV1GetStatesRequest retrieves state history for a user with optional filtering.
type ChannelsV1GetStatesResponse ¶
type ChannelsV1GetStatesResponse struct {
// States is the list of states
States []StateV1 `json:"states"`
// Metadata contains pagination information
Metadata PaginationMetadataV1 `json:"metadata"`
}
ChannelsV1GetStatesResponse returns the list of states.
type ChannelsV1HomeChannelCreatedEvent ¶
type ChannelsV1HomeChannelCreatedEvent struct {
// Channel is the created home channel information
Channel ChannelV1 `json:"channel"`
// InitialState is the initial state of the home channel
InitialState StateV1 `json:"initial_state"`
}
ChannelsV1HomeChannelCreatedEvent is emitted when a home channel is created.
type ChannelsV1RequestCreationRequest ¶
type ChannelsV1RequestCreationRequest struct {
// State is the state to be submitted
State StateV1 `json:"state"`
// ChannelDefinition is the definition of the channel to be created
ChannelDefinition ChannelDefinitionV1 `json:"channel_definition"`
}
ChannelsV1RequestCreationRequest requests the creation of a channel from Node.
type ChannelsV1RequestCreationResponse ¶
type ChannelsV1RequestCreationResponse struct {
// Signature is the Node's signature for the state
Signature string `json:"signature"`
}
ChannelsV1RequestCreationResponse returns the Node's signature for the state.
type ChannelsV1SubmitSessionKeyStateRequest ¶
type ChannelsV1SubmitSessionKeyStateRequest struct {
// State contains the session key metadata and delegation information
State ChannelSessionKeyStateV1 `json:"state"`
}
ChannelsV1SubmitSessionKeyStateRequest submits the session key state for registration and updates.
type ChannelsV1SubmitSessionKeyStateResponse ¶
type ChannelsV1SubmitSessionKeyStateResponse struct {
}
ChannelsV1SubmitSessionKeyStateResponse returns the result of session key state submission.
type ChannelsV1SubmitStateRequest ¶
type ChannelsV1SubmitStateRequest struct {
// State is the state to be submitted
State StateV1 `json:"state"`
}
ChannelsV1SubmitStateRequest submits a cross-chain state.
type ChannelsV1SubmitStateResponse ¶
type ChannelsV1SubmitStateResponse struct {
// Signature is the Node's signature for the state
Signature string `json:"signature"`
}
ChannelsV1SubmitStateResponse returns the Node's signature for the state.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client provides a high-level interface for interacting with the Nitrolite Node V1 RPC API. It wraps a Dialer to provide convenient methods for all V1 RPC operations.
The Client supports:
- Channel management (home and escrow channels)
- State queries and submissions
- Application session operations
- Session key management
- User balance and transaction queries
- Node configuration and asset queries
Example usage:
dialer := rpc.NewWebsocketDialer(rpc.DefaultWebsocketDialerConfig)
client := rpc.NewClient(dialer)
// Connect to the server
err := client.Start(ctx, "wss://clearnode-sandbox.yellow.org/v1/ws", handleError)
if err != nil {
log.Fatal(err)
}
// Make RPC calls
config, err := client.NodeV1GetConfig(ctx)
if err != nil {
log.Fatal(err)
}
func NewClient ¶
NewClient creates a new V1 RPC client using the provided dialer. The dialer must be connected before making RPC calls.
func (*Client) AppSessionsV1CreateAppSession ¶
func (c *Client) AppSessionsV1CreateAppSession(ctx context.Context, req AppSessionsV1CreateAppSessionRequest) (AppSessionsV1CreateAppSessionResponse, error)
AppSessionsV1CreateAppSession creates a new application session between participants.
func (*Client) AppSessionsV1GetAppDefinition ¶
func (c *Client) AppSessionsV1GetAppDefinition(ctx context.Context, req AppSessionsV1GetAppDefinitionRequest) (AppSessionsV1GetAppDefinitionResponse, error)
AppSessionsV1GetAppDefinition retrieves the application definition for a specific app session.
func (*Client) AppSessionsV1GetAppSessions ¶
func (c *Client) AppSessionsV1GetAppSessions(ctx context.Context, req AppSessionsV1GetAppSessionsRequest) (AppSessionsV1GetAppSessionsResponse, error)
AppSessionsV1GetAppSessions lists all application sessions for a participant with optional filtering.
func (*Client) AppSessionsV1GetLastKeyStates ¶
func (c *Client) AppSessionsV1GetLastKeyStates(ctx context.Context, req AppSessionsV1GetLastKeyStatesRequest) (AppSessionsV1GetLastKeyStatesResponse, error)
AppSessionsV1GetSessionKeys retrieves all active session keys for the authenticated user.
func (*Client) AppSessionsV1RebalanceAppSessions ¶
func (c *Client) AppSessionsV1RebalanceAppSessions(ctx context.Context, req AppSessionsV1RebalanceAppSessionsRequest) (AppSessionsV1RebalanceAppSessionsResponse, error)
AppSessionsV1RebalanceAppSessions rebalances multiple application sessions atomically.
func (*Client) AppSessionsV1SubmitAppState ¶
func (c *Client) AppSessionsV1SubmitAppState(ctx context.Context, req AppSessionsV1SubmitAppStateRequest) (AppSessionsV1SubmitAppStateResponse, error)
AppSessionsV1SubmitAppState submits an application session state update.
func (*Client) AppSessionsV1SubmitDepositState ¶
func (c *Client) AppSessionsV1SubmitDepositState(ctx context.Context, req AppSessionsV1SubmitDepositStateRequest) (AppSessionsV1SubmitDepositStateResponse, error)
AppSessionsV1SubmitDepositState submits an application session state update.
func (*Client) AppSessionsV1SubmitSessionKeyState ¶
func (c *Client) AppSessionsV1SubmitSessionKeyState(ctx context.Context, req AppSessionsV1SubmitSessionKeyStateRequest) (AppSessionsV1SubmitSessionKeyStateRequest, error)
AppSessionsV1Register initiates session key registration.
func (*Client) AppsV1GetApps ¶
func (c *Client) AppsV1GetApps(ctx context.Context, req AppsV1GetAppsRequest) (AppsV1GetAppsResponse, error)
AppsV1GetApps retrieves registered applications with optional filtering.
func (*Client) AppsV1SubmitAppVersion ¶
func (c *Client) AppsV1SubmitAppVersion(ctx context.Context, req AppsV1SubmitAppVersionRequest) (AppsV1SubmitAppVersionResponse, error)
AppsV1SubmitAppVersion submits a new application version (currently only creation is supported).
func (*Client) ChannelsV1GetChannels ¶
func (c *Client) ChannelsV1GetChannels(ctx context.Context, req ChannelsV1GetChannelsRequest) (ChannelsV1GetChannelsResponse, error)
ChannelsV1GetChannels retrieves all channels for a user with optional filtering.
func (*Client) ChannelsV1GetEscrowChannel ¶
func (c *Client) ChannelsV1GetEscrowChannel(ctx context.Context, req ChannelsV1GetEscrowChannelRequest) (ChannelsV1GetEscrowChannelResponse, error)
ChannelsV1GetEscrowChannel retrieves current on-chain escrow channel information.
func (*Client) ChannelsV1GetHomeChannel ¶
func (c *Client) ChannelsV1GetHomeChannel(ctx context.Context, req ChannelsV1GetHomeChannelRequest) (ChannelsV1GetHomeChannelResponse, error)
ChannelsV1GetHomeChannel retrieves current on-chain home channel information.
func (*Client) ChannelsV1GetLastKeyStates ¶
func (c *Client) ChannelsV1GetLastKeyStates(ctx context.Context, req ChannelsV1GetLastKeyStatesRequest) (ChannelsV1GetLastKeyStatesResponse, error)
ChannelsV1GetLastKeyStates retrieves the latest channel session key states for a user.
func (*Client) ChannelsV1GetLatestState ¶
func (c *Client) ChannelsV1GetLatestState(ctx context.Context, req ChannelsV1GetLatestStateRequest) (ChannelsV1GetLatestStateResponse, error)
ChannelsV1GetLatestState retrieves the current state of the user stored on the Node.
func (*Client) ChannelsV1GetStates ¶
func (c *Client) ChannelsV1GetStates(ctx context.Context, req ChannelsV1GetStatesRequest) (ChannelsV1GetStatesResponse, error)
ChannelsV1GetStates retrieves state history for a user with optional filtering.
func (*Client) ChannelsV1RequestCreation ¶
func (c *Client) ChannelsV1RequestCreation(ctx context.Context, req ChannelsV1RequestCreationRequest) (ChannelsV1RequestCreationResponse, error)
ChannelsV1RequestCreation requests the creation of a channel from Node.
func (*Client) ChannelsV1SubmitSessionKeyState ¶
func (c *Client) ChannelsV1SubmitSessionKeyState(ctx context.Context, req ChannelsV1SubmitSessionKeyStateRequest) (ChannelsV1SubmitSessionKeyStateResponse, error)
ChannelsV1SubmitSessionKeyState submits a channel session key state for registration or update.
func (*Client) ChannelsV1SubmitState ¶
func (c *Client) ChannelsV1SubmitState(ctx context.Context, req ChannelsV1SubmitStateRequest) (ChannelsV1SubmitStateResponse, error)
ChannelsV1SubmitState submits a cross-chain state.
func (*Client) NodeV1GetAssets ¶
func (c *Client) NodeV1GetAssets(ctx context.Context, req NodeV1GetAssetsRequest) (NodeV1GetAssetsResponse, error)
NodeV1GetAssets retrieves all supported assets with optional chain filter.
func (*Client) NodeV1GetConfig ¶
func (c *Client) NodeV1GetConfig(ctx context.Context) (NodeV1GetConfigResponse, error)
NodeV1GetConfig retrieves broker configuration and supported networks.
func (*Client) NodeV1Ping ¶
NodeV1Ping sends a ping request to the server to check connectivity.
func (*Client) Start ¶
Start establishes a connection to the RPC server. This is a convenience method that wraps the dialer's Dial method.
func (*Client) UserV1GetActionAllowances ¶
func (c *Client) UserV1GetActionAllowances(ctx context.Context, req UserV1GetActionAllowancesRequest) (UserV1GetActionAllowancesResponse, error)
UserV1GetActionAllowances retrieves the user's current action allowances for channels and app sessions.
func (*Client) UserV1GetBalances ¶
func (c *Client) UserV1GetBalances(ctx context.Context, req UserV1GetBalancesRequest) (UserV1GetBalancesResponse, error)
UserV1GetBalances retrieves the balances of the user in YN.
func (*Client) UserV1GetTransactions ¶
func (c *Client) UserV1GetTransactions(ctx context.Context, req UserV1GetTransactionsRequest) (UserV1GetTransactionsResponse, error)
UserV1GetTransactions retrieves ledger transaction history with optional filtering.
type Connection ¶
type Connection interface {
// ConnectionID returns the unique identifier for this connection.
// This ID is generated when the connection is established and remains
// constant throughout the connection's lifetime.
ConnectionID() string
// Origin returns the origin of the connection, such as the client's IP address or other identifying information.
Origin() string
// RawRequests returns a read-only channel for receiving incoming raw request messages.
// Messages received on this channel are raw bytes that need to be unmarshaled
// into Request objects for processing. The channel is closed when the
// connection is terminated.
RawRequests() <-chan []byte
// WriteRawResponse attempts to send a raw response message to the client.
// The method returns true if the message was successfully queued for sending,
// or false if the operation timed out (indicating a potentially unresponsive client).
// Messages that fail to send may trigger connection closure.
WriteRawResponse(message []byte) bool
// Serve starts the connection's lifecycle by spawning goroutines for reading and writing.
// This method returns immediately after starting the goroutines. The handleClosure
// callback will be invoked asynchronously when the connection terminates (with an
// error if abnormal termination occurred). The parentCtx parameter enables
// graceful shutdown of the connection.
Serve(parentCtx context.Context, handleClosure func(error))
}
Connection represents an active RPC connection that handles bidirectional communication. Implementations of this interface manage the connection lifecycle and message routing. The interface is designed to be transport-agnostic, though the primary implementation uses WebSocket.
type ConnectionHub ¶
type ConnectionHub struct {
// contains filtered or unexported fields
}
ConnectionHub provides centralized management of all active RPC connections. It maintains thread-safe mappings between connection IDs and Connection instances, as well as user IDs and their associated connections. This enables efficient message routing and connection lifecycle management.
Key features:
- Thread-safe connection storage and retrieval
- User-to-connection mapping for authenticated sessions
- Automatic cleanup of auth mappings when connections close
- Support for re-authentication (updating user associations)
- Broadcast capabilities to all connections for a specific user
func NewConnectionHub ¶
func NewConnectionHub(observeConnections ObserveConnectionsFn) *ConnectionHub
NewConnectionHub creates a new ConnectionHub instance with initialized maps. The hub is typically used internally by Node implementations to manage the lifecycle of all active connections.
func (*ConnectionHub) Add ¶
func (hub *ConnectionHub) Add(conn Connection) error
Add registers a new connection with the hub. The connection is indexed by its ConnectionID for fast retrieval.
Returns an error if:
- The connection is nil
- A connection with the same ID already exists
func (*ConnectionHub) Get ¶
func (hub *ConnectionHub) Get(connID string) Connection
Get retrieves a connection by its unique connection ID. Returns the Connection instance if found, or nil if no connection with the specified ID exists in the hub.
This method is safe for concurrent access.
func (*ConnectionHub) Publish ¶
func (hub *ConnectionHub) Publish(userID string, response []byte)
Publish broadcasts a message to all active connections for a specific user. This enables server-initiated notifications to be sent to all of a user's connected clients (e.g., multiple browser tabs or devices).
The method:
- Looks up all connections associated with the user
- Attempts to send the message to each connection
- Silently skips any connections that fail to accept the message
If the user has no active connections, the message is silently dropped. This method is safe for concurrent access. TODO: refine with subscription topics capability
func (*ConnectionHub) Remove ¶
func (hub *ConnectionHub) Remove(connID string)
Remove unregisters a connection from the hub. This method:
- Removes the connection from the main connection map
- Cleans up any user-to-connection mappings
- Removes empty user entries to prevent memory leaks
If the connection doesn't exist, this method does nothing (no-op). This method is safe for concurrent access.
type Context ¶
type Context struct {
// Context is the standard Go context for the request
Context context.Context
// Request is the original RPC request message
Request Message
// Response is the response message to be sent back to the client
Response Message
// Storage provides per-connection storage for session data
Storage *SafeStorage
// contains filtered or unexported fields
}
Context encapsulates all information related to an RPC request and provides methods for handlers to process and respond. It implements a middleware pattern where handlers can be chained together, each having the ability to process the request, modify the context, or delegate to the next handler.
The Context serves multiple purposes:
- Request/response container: Holds the incoming request and outgoing response
- Middleware chain management: Tracks and executes the handler chain
- Session state: Provides per-connection storage for maintaining state
- Response helpers: Convenient methods for success and error responses
func (*Context) Fail ¶
Fail sets an error response for the RPC request. This method should be called by handlers when an error occurs during request processing.
Error handling behavior:
- If err is an RPCError: The exact error message is sent to the client
- If err is any other error type: The fallbackMessage is sent to the client
- If both err is nil/non-RPCError AND fallbackMessage is empty: A generic error message is sent
This design allows handlers to control what error information is exposed to clients:
- Use RPCError for client-safe, descriptive error messages
- Use regular errors with a fallbackMessage to hide internal error details
Usage examples:
// Hide internal error details from client
balance, err := ledger.GetBalance(account)
if err != nil {
c.Fail(err, "failed to retrieve balance")
return
}
// Validation error with no internal error
if len(params) < 3 {
c.Fail(nil, "invalid parameters: expected at least 3")
return
}
The response will have Method="error" and Params containing the error message.
func (*Context) Next ¶
func (c *Context) Next()
Next advances the middleware chain by executing the next handler. This enables handlers to perform pre-processing, call Next() to delegate to subsequent handlers, then perform post-processing. If there are no more handlers in the chain, Next() returns immediately without error.
Example middleware pattern:
func invalidRequest(c *Context) {
// Pre-processing: check request message type
if c.Request.Type != MsgTypeReq {
c.Fail(nil, "invalid request")
return
}
c.Next() // Continue to next handler
}
func (*Context) Succeed ¶
Succeed sets a successful response for the RPC request. This method should be called by handlers when the request has been processed successfully. The method parameter typically matches the request method, and params contains the result data.
Example:
func handleGetBalance(c *Context) {
balance := getBalanceForUser(c.Request.Payload{"userWallet"})
c.Succeed("get_balance", Payload{"balance": balance})
}
type Dialer ¶
type Dialer interface {
// Dial establishes a connection to the specified URL.
// This method is designed to be called in a goroutine as it blocks until the connection is closed.
// The handleClosure callback is invoked when the connection is closed, with an error if any.
Dial(ctx context.Context, url string, handleClosure func(err error)) error
// IsConnected returns true if the dialer has an active connection.
IsConnected() bool
// Call sends an RPC request and waits for a response.
// It returns an error if the request cannot be sent or no response is received.
// The context can be used to cancel the request.
Call(ctx context.Context, req *Message) (*Message, error)
// EventCh returns a read-only channel for receiving unsolicited events from the server.
// Events are responses that don't match any pending request ID.
EventCh() <-chan *Message
}
Dialer is the interface for RPC client connections. It provides methods to establish connections, send requests, and receive responses.
type Error ¶
type Error struct {
// contains filtered or unexported fields
}
Error represents an error in the RPC protocol that should be sent back to the client in the RPC response. Unlike generic errors, Error messages are guaranteed to be included in the error response sent to the client.
Use Error when you want to provide specific, user-facing error messages in RPC responses. For internal errors that should not be exposed to clients, use regular errors instead.
Example:
// Client will receive this exact error message
return rpc.Errorf("invalid wallet address: %s", addr)
// Client will receive a generic error message
return fmt.Errorf("database connection failed")
func Errorf ¶
Errorf creates a new Error with a formatted error message that will be sent to the client in the RPC response. This is the preferred way to create client-facing errors in RPC handlers.
The error message should be clear, actionable, and safe to expose to external clients. Avoid including sensitive information like internal system details, file paths, or database specifics.
Usage in RPC handlers:
// In a handler function that returns an error
if amount.IsNegative() {
return Errorf("invalid amount: cannot be negative")
}
// With formatting for specific details
if balance.LessThan(amount) {
return Errorf("insufficient balance: need %s but have %s", amount, balance)
}
func NewError ¶
NewError creates a new Error from an existing error. The message from the provided error will be included in the RPC response sent to the client.
Use this function when you have an existing error that contains a user-friendly message that you want to send back to the client. If the original error message is not suitable for client consumption, consider using Errorf to create a new Error with a custom message.
Example:
// Creating an Error from an existing error
if err := validateAddress(addr); err != nil {
return rpc.NewError(err)
}
// This will send the original error message to the client, so ensure it's appropriate for exposure.
func (Error) Error ¶
Error implements the error interface for Error. It returns the underlying error message that will be sent to clients.
This method allows Error to be used anywhere a standard Go error is expected, while maintaining the distinction that this error's message is safe for external client consumption.
type Event ¶
type Event string
Event represents a notification event type sent by the server. Events are unsolicited notifications sent to connected clients.
type GorillaWsConnectionAdapter ¶
type GorillaWsConnectionAdapter interface {
// ReadMessage reads a message from the WebSocket connection.
ReadMessage() (messageType int, p []byte, err error)
// NextWriter returns a writer for the next message to be sent on the WebSocket connection.
NextWriter(messageType int) (io.WriteCloser, error)
// Close closes the WebSocket connection.
Close() error
// WriteControl writes a control message (ping, pong, close) to the connection.
WriteControl(messageType int, data []byte, deadline time.Time) error
// SetPongHandler sets the handler for pong messages received from the peer.
SetPongHandler(h func(appData string) error)
// SetReadDeadline sets the deadline for future Read calls.
// A zero value means reads will not time out.
SetReadDeadline(t time.Time) error
}
GorillaWsConnectionAdapter abstracts the methods of a WebSocket connection needed by WebsocketConnection.
type Group ¶
type Group string
Method represents an RPC method name that can be called on the server.
type Handler ¶
type Handler func(c *Context)
Handler defines the function signature for RPC request processors. Handlers receive a Context containing the request and all necessary information to process it. They can call c.Next() to delegate to the next handler in the middleware chain, enabling composable request processing pipelines.
type HandlerGroup ¶
type HandlerGroup interface {
Handle(method string, handler Handler)
Use(middleware Handler)
NewGroup(name string) HandlerGroup
}
type LedgerV1 ¶
type LedgerV1 struct {
// TokenAddress is the address of the token used in this channel
TokenAddress string `json:"token_address"`
// BlockchainID is the unique identifier for the blockchain
BlockchainID string `json:"blockchain_id"`
// UserBalance is the user balance in the channel
UserBalance string `json:"user_balance"`
// UserNetFlow is the user net flow in the channel
UserNetFlow string `json:"user_net_flow"`
// NodeBalance is the node balance in the channel
NodeBalance string `json:"node_balance"`
// NodeNetFlow is the node net flow in the channel
NodeNetFlow string `json:"node_net_flow"`
}
LedgerV1 represents ledger balances for a channel.
type Message ¶
type Message struct {
Type MsgType `json:"type"`
// RequestID is a unique identifier for tracking requests and matching responses.
// Clients should generate unique IDs to prevent collisions and enable proper
// request-response correlation.
RequestID uint64 `json:"request_id"`
// Method specifies the RPC method to be invoked (e.g., "wallet_transfer").
// Method names should follow a consistent naming convention, typically
// using lowercase with underscores (e.g., "module_action").
Method string `json:"method"`
// Payload contains the method-specific parameters as a flexible map.
// This allows different methods to have different parameter structures
// while maintaining type safety through the Translate method.
Payload Payload `json:"payload"`
// Timestamp is the Unix timestamp in milliseconds when the payload was created.
// This is used for replay protection and request expiration checks.
// Servers should validate that timestamps are within an acceptable time window.
Timestamp uint64 `json:"ts"`
}
Message represents the core data structure for RPC communication. It contains all the information needed to process an RPC call, response, or event.
Messages are encoded as JSON arrays for compact transmission: [Type, RequestID, Method, Params, Timestamp]
This encoding reduces message size while maintaining human readability and allows for efficient parsing. The array format is automatically handled by the custom JSON marshaling methods.
func NewErrorResponse ¶
NewErrorResponse creates an error Response message containing an error message. This is a convenience function that combines error parameter creation and response construction in a single call.
The message type is set to MsgTypeRespErr and the method is preserved from the request.
Parameters:
- requestID: The ID from the original request
- method: The method from the original request
- errMsg: The error message to send to the client
Example usage:
// In an RPC handler when an error occurs
if err := validateRequest(request); err != nil {
return NewErrorResponse(request.RequestID, request.Method, err.Error())
}
// Creating an error response
errorResponse := NewErrorResponse(12345, "node.v1.ping", "insufficient balance")
The resulting response will have type MsgTypeRespErr, the same method as the request, and params in the format: {"error": "<errMsg>"}
func NewMessage ¶
NewMessage creates a new Message with the given request ID, type, method, and parameters. The timestamp is automatically set to the current time in Unix milliseconds.
Example:
params, _ := NewParams(map[string]string{"address": "0x123"})
message := NewMessage(MsgTypeReq, 12345, "wallet_getBalance", params)
The resulting message will have the current timestamp and can be used for requests, responses, or events depending on the type specified.
func NewRequest ¶
NewRequest creates a new Request message with the given request ID, method, and parameters. The message type is automatically set to MsgTypeReq and the timestamp is set to the current time.
Example usage:
// Create a request message
params, _ := NewParams(map[string]string{"address": "0x123"})
request := NewRequest(12345, "wallet_getBalance", params)
// Create a request with complex parameters
type TransferParams struct {
To string `json:"to"`
Amount string `json:"amount"`
}
params, _ := NewParams(TransferParams{To: "0xabc", Amount: "100"})
request := NewRequest(67890, "wallet_transfer", params)
func NewResponse ¶
NewResponse creates a new Response message with the given request ID, method, and parameters. The message type is automatically set to MsgTypeResp and the timestamp is set to the current time.
Example usage:
// Create a success response
params, _ := NewParams(map[string]string{"balance": "1000"})
response := NewResponse(12345, "wallet_getBalance", params)
func (Message) Error ¶
Error checks if the Message contains an error and returns it. This method extracts any error stored in the message's payload under the standard "error" key by checking if the message type is MsgTypeRespErr.
Returns:
- An error if the message type is MsgTypeRespErr
- nil if the message represents a successful operation
This is typically used by clients to check if an RPC call failed:
// After receiving and unmarshaling a response message
var message Message
if err := json.Unmarshal(data, &message); err != nil {
return fmt.Errorf("failed to unmarshal message: %w", err)
}
// Check if the message contains an error
if err := message.Error(); err != nil {
return fmt.Errorf("RPC call failed: %w", err)
}
// Process successful response
var result TransferResult
message.Payload.Translate(&result)
This method is designed to work with error responses created by NewErrorResponse or any response where errors are stored using NewErrorParams.
func (Message) MarshalJSON ¶
MarshalJSON implements the json.Marshaler interface for Message. It always emits the compact array format: [Type, RequestID, Method, Params, Timestamp]
This ensures consistent wire format regardless of how the Message struct is modified in the future, maintaining protocol compatibility.
Example output:
[1, 12345, "wallet_transfer", {"to": "0xabc", "amount": "100"}, 1634567890123]
func (*Message) UnmarshalJSON ¶
UnmarshalJSON implements the json.Unmarshaler interface for Message. It expects data in the compact array format: [Type, RequestID, Method, Params, Timestamp]
This custom unmarshaling ensures backward compatibility with the array-based protocol format while providing a clean struct-based API for Go code.
The method validates that: - The input is a valid JSON array - The array contains exactly 5 elements - Each element has the correct type
Returns an error if the JSON format is invalid or any element has the wrong type.
type Node ¶
type Node interface {
// ServeHTTP handles incoming HTTP requests and upgrades them to
// the appropriate transport protocol (e.g., WebSocket). It manages
// connection lifecycle, including reading requests, routing to
// handlers, and sending responses.
ServeHTTP(w http.ResponseWriter, r *http.Request)
// Handle registers a handler function for a specific RPC method.
// When a request with the matching method name is received,
// the handler will be invoked with the request context.
Handle(method string, handler Handler)
// Notify sends a server-initiated notification to a specific user.
// All active connections for the user will receive the notification.
// If the user has no active connections, the notification is dropped.
Notify(userID string, method string, params Payload)
// Use adds global middleware that will be executed for all requests.
// Middleware is executed in the order it was added, before any
// method-specific handlers.
Use(middleware Handler)
// NewGroup creates a new handler group for organizing related endpoints.
// Groups can have their own middleware and can be nested to create
// hierarchical handler structures.
NewGroup(name string) HandlerGroup
}
Node represents an RPC server that manages client connections and routes messages to appropriate handlers. It provides a foundation for building RPC-based services with support for middleware, authentication, and server-initiated notifications. The interface is transport-agnostic, allowing for different implementations (WebSocket, HTTP/2, etc.).
type NodeV1GetAssetsRequest ¶
type NodeV1GetAssetsRequest struct {
// BlockchainID filters by blockchain network ID
BlockchainID *string `json:"blockchain_id,omitempty"`
}
NodeV1GetAssetsRequest retrieves all supported assets with optional chain filter.
type NodeV1GetAssetsResponse ¶
type NodeV1GetAssetsResponse struct {
// Assets is the list of supported assets
Assets []AssetV1 `json:"assets"`
}
NodeV1GetAssetsResponse returns the list of supported assets.
type NodeV1GetConfigRequest ¶
type NodeV1GetConfigRequest struct{}
NodeV1GetConfigRequest retrieves broker configuration and supported networks.
type NodeV1GetConfigResponse ¶
type NodeV1GetConfigResponse struct {
// NodeAddress is the node wallet address
NodeAddress string `json:"node_address"`
// NodeVersion is the node software version
NodeVersion string `json:"node_version"`
// SupportedSigValidators is the list of supported signature validators identifiers for state sig verification
SupportedSigValidators []core.ChannelSignerType `json:"supported_sig_validators"`
// Blockchains is the list of supported networks
Blockchains []BlockchainInfoV1 `json:"blockchains"`
}
NodeV1GetConfigResponse returns the broker configuration.
type NodeV1PingRequest ¶
type NodeV1PingRequest struct{}
NodeV1PingRequest is a simple connectivity check.
type NodeV1PingResponse ¶
type NodeV1PingResponse struct{}
NodeV1PingResponse is the response to a ping request.
type ObserveConnectionsFn ¶
type PaginationMetadataV1 ¶
type PaginationMetadataV1 struct {
// Page is the current page number
Page uint32 `json:"page"`
// PerPage is the number of items per page
PerPage uint32 `json:"per_page"`
// TotalCount is the total number of items
TotalCount uint32 `json:"total_count"`
// PageCount is the total number of pages
PageCount uint32 `json:"page_count"`
}
PaginationMetadataV1 represents pagination information.
type PaginationParamsV1 ¶
type PaginationParamsV1 struct {
// Offset is the pagination offset (number of items to skip)
Offset *uint32 `json:"offset,omitempty"`
// Limit is the number of items to return
Limit *uint32 `json:"limit,omitempty"`
// Sort is the sort order (asc/desc)
Sort *string `json:"sort,omitempty"`
}
PaginationParamsV1 represents pagination request parameters.
type Payload ¶
type Payload map[string]json.RawMessage
Payload represents method-specific parameters as a map of JSON raw messages. This design allows maximum flexibility while maintaining type safety: - Parameters are stored as raw JSON until needed - The Translate method provides type-safe extraction into Go structs - Supports optional parameters and forward compatibility
Example usage:
// Creating params from a struct
params, _ := NewParams(TransferRequest{To: "0x123", Amount: "100"})
// Accessing individual parameters
var amount string
json.Unmarshal(params["amount"], &amount)
// Translating to a struct
var req TransferRequest
params.Translate(&req)
func NewErrorPayload ¶
NewErrorPayload creates a Params map containing an error message. This is a convenience function for creating standardized error parameters that follow the protocol's error response convention.
The error message is stored under the "error" key and properly JSON-encoded.
Example usage:
// Creating error params for a validation failure
errParams := NewErrorPayload("invalid address format")
payload := NewPayload(requestID, method, errParams)
// Creating error params from an existing error
if err := validateAmount(amount); err != nil {
errParams := NewErrorPayload(err.Error())
response := NewResponse(NewPayload(id, method, errParams))
}
The resulting Params will contain: {"error": "invalid address format"}
func NewPayload ¶
NewPayload creates a Payload map from any JSON-serializable value. This is typically used with structs or maps to create method parameters.
The function works by: 1. Marshaling the input value to JSON 2. Unmarshaling it into a Params map 3. Each field becomes a key with its JSON representation as the value
Example:
type TransferRequest struct {
From string `json:"from"`
To string `json:"to"`
Amount string `json:"amount"`
}
req := TransferRequest{
From: "0x111...",
To: "0x222...",
Amount: "1000000000000000000",
}
payload, err := NewPayload(req)
// payload now contains: {"from": "0x111...", "to": "0x222...", "amount": "1000000000000000000"}
Returns an error if the value cannot be marshaled to JSON or is not a valid object.
func (Payload) Error ¶
Error extracts and returns an error from the Payload if one exists. This method checks for the standard "error" key in the payload and attempts to unmarshal its value as a string error message.
Returns:
- An error with the message if the "error" key exists and contains a valid string
- nil if no error key exists or if the value cannot be unmarshaled
This is typically used when processing response payloads to check for errors:
// In a client processing a response message
if err := message.Payload.Error(); err != nil {
// The server returned an error
return fmt.Errorf("RPC error: %w", err)
}
// Process successful response
var result TransferResult
message.Payload.Translate(&result)
This method is designed to work with error params created by NewErrorParams.
func (Payload) Translate ¶
Translate extracts the parameters into the provided value (typically a struct). This provides type-safe parameter extraction with automatic JSON unmarshaling.
The method works by: 1. Marshaling the Payload map back to JSON 2. Unmarshaling that JSON into the target value 3. Go's JSON unmarshaling handles type conversion and validation
Example:
type BalanceRequest struct {
Address string `json:"address"`
Block string `json:"block,omitempty"`
}
// In an RPC handler:
var req BalanceRequest
if err := message.Payload.Translate(&req); err != nil {
return rpc.Errorf("invalid parameters: %v", err)
}
// req.Address and req.Block are now populated
The target value should be a pointer to the desired type. Returns an error if the parameters don't match the expected structure.
type SafeStorage ¶
type SafeStorage struct {
// contains filtered or unexported fields
}
SafeStorage provides thread-safe key-value storage for connection-specific data. Each connection gets its own SafeStorage instance that persists for the connection's lifetime. This enables handlers to store and retrieve session state, authentication tokens, rate limiting counters, or any other per-connection data across multiple requests.
Common use cases:
- Storing authentication state and policies
- Caching frequently accessed data
- Maintaining request counters for rate limiting
- Storing connection-specific configuration
func NewSafeStorage ¶
func NewSafeStorage() *SafeStorage
NewSafeStorage creates a new thread-safe storage instance. The storage starts empty and can be used immediately for storing connection-specific data.
func (*SafeStorage) Get ¶
func (s *SafeStorage) Get(key string) (any, bool)
Get retrieves a value by key from the storage. Returns the value and true if the key exists, or nil and false if the key is not found. The caller must type-assert the returned value to the expected type.
Example:
if val, ok := storage.Get("auth_token"); ok {
token := val.(string)
// Use token...
}
func (*SafeStorage) Set ¶
func (s *SafeStorage) Set(key string, value any)
Set stores a value with the given key in the storage. If the key already exists, its value is overwritten. The value can be of any type. This method is thread-safe and can be called concurrently from multiple goroutines.
Example:
storage.Set("auth_token", "bearer-xyz123")
storage.Set("rate_limit_count", 42)
storage.Set("user_preferences", userPrefs)
type SendResponseFunc ¶
SendResponseFunc is a function type for sending server-initiated RPC notifications. Unlike regular responses that reply to client requests, these functions enable the server to push unsolicited messages to clients (e.g., balance updates, connection events). The method parameter specifies the notification type, and params contains the notification data.
type SignedAppStateUpdateV1 ¶
type SignedAppStateUpdateV1 struct {
// AppStateUpdate is the application session state update
AppStateUpdate AppStateUpdateV1 `json:"app_state_update"`
// QuorumSigs is the signature quorum for the application session
QuorumSigs []string `json:"quorum_sigs"`
}
SignedAppStateUpdateV1 represents a signed application session state update.
type StateV1 ¶
type StateV1 struct {
// ID is the deterministic ID (hash) of the state
ID string `json:"id"`
// Transition is the state transition that led to this state
Transition TransitionV1 `json:"transition"`
// Asset is the asset type of the state
Asset string `json:"asset"`
// UserWallet is the user wallet address
UserWallet string `json:"user_wallet"`
// Epoch is the user Epoch Index
Epoch string `json:"epoch"`
// Version is the version of the state
Version string `json:"version"`
// HomeChannelID is the identifier for the home Channel blockchain network
HomeChannelID *string `json:"home_channel_id,omitempty"`
// EscrowChannelID is the identifier for the escrow Channel blockchain network
EscrowChannelID *string `json:"escrow_channel_id,omitempty"`
// HomeLedger contains user and node balances for the home channel
HomeLedger LedgerV1 `json:"home_ledger"`
// EscrowLedger contains user and node balances for the escrow channel
EscrowLedger *LedgerV1 `json:"escrow_ledger,omitempty"`
// UserSig is the user signature for the state
UserSig *string `json:"user_sig,omitempty"`
// NodeSig is the node signature for the state
NodeSig *string `json:"node_sig,omitempty"`
}
StateV1 represents the current state of the user stored on Node.
type TokenV1 ¶
type TokenV1 struct {
// Name is the token name
Name string `json:"name"`
// Symbol is the token symbol
Symbol string `json:"symbol"`
// Address is the token contract address
Address string `json:"address"`
// BlockchainID is the blockchain network ID
BlockchainID string `json:"blockchain_id"`
// Decimals is the number of decimal places
Decimals uint8 `json:"decimals"`
}
TokenV1 represents information about a supported token.
type TransactionV1 ¶
type TransactionV1 struct {
// ID is the unique transaction reference
ID string `json:"id"`
// Asset is the asset symbol
Asset string `json:"asset"`
// TxType is the transaction type
TxType core.TransactionType `json:"tx_type"`
// FromAccount is the account that sent the funds
FromAccount string `json:"from_account"`
// ToAccount is the account that received the funds
ToAccount string `json:"to_account"`
// SenderNewStateID is the ID of the new sender's channel state
SenderNewStateID *string `json:"sender_new_state_id,omitempty"`
// ReceiverNewStateID is the ID of the new receiver's channel state
ReceiverNewStateID *string `json:"receiver_new_state_id,omitempty"`
// Amount is the transaction amount
Amount string `json:"amount"`
// CreatedAt is when the transaction was created
CreatedAt string `json:"created_at"`
}
TransactionV1 represents a transaction record.
type TransitionV1 ¶
type TransitionV1 struct {
// Type is the type of state transition
Type core.TransitionType `json:"type"`
// TxID is the transaction ID associated with the transition
TxID string `json:"tx_id"`
// AccountID is the account identifier (varies based on transition type)
AccountID string `json:"account_id"`
// Amount is the amount involved in the transition
Amount string `json:"amount"`
}
TransitionV1 represents a state transition.
type UserV1GetActionAllowancesRequest ¶
type UserV1GetActionAllowancesRequest struct {
// Wallet is the user's wallet address
Wallet string `json:"wallet"`
}
UserV1GetActionAllowancesRequest retrieves the current action allowances for a user.
type UserV1GetActionAllowancesResponse ¶
type UserV1GetActionAllowancesResponse struct {
// Allowances is the list of action allowances for the user
Allowances []ActionAllowanceV1 `json:"allowances"`
}
UserV1GetActionAllowancesResponse returns the list of action allowances for the user.
type UserV1GetBalancesRequest ¶
type UserV1GetBalancesRequest struct {
// Wallet is the user's wallet address
Wallet string `json:"wallet"`
}
UserV1GetBalancesRequest retrieves the balances of the user in YN.
type UserV1GetBalancesResponse ¶
type UserV1GetBalancesResponse struct {
// Balances is the list of asset balances
Balances []BalanceEntryV1 `json:"balances"`
}
UserV1GetBalancesResponse returns the list of asset balances.
type UserV1GetTransactionsRequest ¶
type UserV1GetTransactionsRequest struct {
// Wallet filters by user's wallet address
Wallet string `json:"wallet"`
// Asset filters by asset symbol
Asset *string `json:"asset,omitempty"`
// TxType filters by transaction type
TxType *core.TransactionType `json:"tx_type,omitempty"`
// Pagination contains pagination parameters (offset, limit, sort)
Pagination *PaginationParamsV1 `json:"pagination,omitempty"`
// FromTime is the start time filter (Unix timestamp)
FromTime *uint64 `json:"from_time,omitempty"`
// ToTime is the end time filter (Unix timestamp)
ToTime *uint64 `json:"to_time,omitempty"`
}
UserV1GetTransactionsRequest retrieves ledger transaction history with optional filtering.
type UserV1GetTransactionsResponse ¶
type UserV1GetTransactionsResponse struct {
// Transactions is the list of transactions
Transactions []TransactionV1 `json:"transactions"`
// Metadata contains pagination information
Metadata PaginationMetadataV1 `json:"metadata"`
}
UserV1GetTransactionsResponse returns the list of transactions.
type WebsocketConnection ¶
type WebsocketConnection struct {
// contains filtered or unexported fields
}
WebsocketConnection implements the Connection interface using WebSocket transport. It manages bidirectional communication, and provides thread-safe operations for concurrent message processing. The connection supports graceful shutdown and automatic cleanup of resources.
Key features:
- Concurrent read/write operations with separate goroutines
- Configurable timeouts for write operations
- Buffered channels for message processing
- Thread-safe user authentication state management
- Graceful connection closure with proper resource cleanup
- Native WebSocket ping/pong keepalive detection
func NewWebsocketConnection ¶
func NewWebsocketConnection(config WebsocketConnectionConfig) (*WebsocketConnection, error)
NewWebsocketConnection creates a new WebsocketConnection instance with the provided configuration. Returns an error if required fields (ConnectionID, WebsocketConn) are missing. Optional fields are set to sensible defaults if not provided.
func (*WebsocketConnection) ConnectionID ¶
func (conn *WebsocketConnection) ConnectionID() string
ConnectionID returns the unique identifier for this connection.
func (*WebsocketConnection) Origin ¶
func (conn *WebsocketConnection) Origin() string
Origin returns the origin of the connection, such as the client's IP address or other identifying information.
func (*WebsocketConnection) RawRequests ¶
func (conn *WebsocketConnection) RawRequests() <-chan []byte
RawRequests returns the channel for processing incoming requests.
func (*WebsocketConnection) Serve ¶
func (conn *WebsocketConnection) Serve(parentCtx context.Context, handleClosure func(error))
Serve starts the connection's lifecycle by spawning concurrent goroutines. This method:
- Spawns three goroutines: one for reading messages, one for writing messages, and one for monitoring connection closure signals
- Returns immediately after starting the goroutines
- Spawns an additional goroutine that waits for all operations to complete and then invokes handleClosure with any error that occurred
The handleClosure callback is guaranteed to be called exactly once when the connection terminates. The method is idempotent - calling it multiple times will immediately invoke handleClosure without starting duplicate goroutines.
func (*WebsocketConnection) WriteRawResponse ¶
func (conn *WebsocketConnection) WriteRawResponse(message []byte) bool
WriteRawResponse attempts to queue a message for sending to the client. The method uses a timeout to prevent blocking on unresponsive clients. If the message cannot be queued within the timeout duration:
- The method returns false
- A close signal is sent to trigger connection shutdown
- This prevents resource exhaustion from slow or disconnected clients
Returns true if the message was successfully queued for sending.
type WebsocketConnectionConfig ¶
type WebsocketConnectionConfig struct {
// ConnectionID is the unique identifier for this connection (required)
ConnectionID string
// Origin is the origin of the connection, such as the client's IP address (optional)
Origin string
// WebsocketConn is the underlying WebSocket connection (required)
WebsocketConn GorillaWsConnectionAdapter
// WriteTimeout is the maximum duration to wait for a write operation (default: 5s)
WriteTimeout time.Duration
// WriteBufferSize is the capacity of the outgoing message buffer (default: 10)
WriteBufferSize int
// ProcessBufferSize is the capacity of the incoming message buffer (default: 10)
ProcessBufferSize int
// PingInterval is how often to send ping frames to clients (default: 5s).
PingInterval time.Duration
// PongTimeout is the maximum duration to wait for a pong response from the client (default: 10s).
// If no pong is received within this duration, the connection is considered dead.
PongTimeout time.Duration
// Logger for connection events (default: no-op logger)
Logger log.Logger
// OnMessageSentHandler is called after a message is successfully sent (optional)
OnMessageSentHandler func([]byte)
}
WebsocketConnectionConfig contains configuration options for creating a new WebsocketConnection. All fields except ConnectionID and WebsocketConn have sensible defaults.
type WebsocketDialer ¶
type WebsocketDialer struct {
// contains filtered or unexported fields
}
WebsocketDialer implements the Dialer interface using WebSocket connections. It provides thread-safe RPC communication with automatic ping handling.
func NewWebsocketDialer ¶
func NewWebsocketDialer(cfg WebsocketDialerConfig) *WebsocketDialer
NewWebsocketDialer creates a new WebSocket dialer with the given configuration
func (*WebsocketDialer) Call ¶
Call sends an RPC request and waits for a response. The request must have a unique RequestID that identifies this call. The method is thread-safe and can be called concurrently.
The context can be used to set a timeout for the request:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() resp, err := dialer.Call(ctx, request)
func (*WebsocketDialer) Dial ¶
func (d *WebsocketDialer) Dial(parentCtx context.Context, url string, handleClosure func(err error)) error
Dial establishes a WebSocket connection to the specified URL. This method blocks until the connection is closed, so it should typically be called in a goroutine. It starts three background goroutines: - One to handle context cancellation - One to read and route incoming messages - One to send periodic ping messages
Example:
dialer := NewWebsocketDialer(DefaultWebsocketDialerConfig)
go dialer.Dial(ctx, "ws://localhost:8080/ws", func(err error) {
if err != nil {
log.Error("Connection closed", "error", err)
}
})
func (*WebsocketDialer) EventCh ¶
func (d *WebsocketDialer) EventCh() <-chan *Message
EventCh returns a read-only channel for receiving unsolicited events. Events are responses that don't match any pending request ID. The channel will receive nil when the connection is closed.
Example:
for event := range dialer.EventCh() {
if event == nil {
// Connection closed
break
}
// Handle event
log.Info("Received event", "method", event.Method)
}
func (*WebsocketDialer) IsConnected ¶
func (d *WebsocketDialer) IsConnected() bool
IsConnected returns true if the dialer has an active connection
type WebsocketDialerConfig ¶
type WebsocketDialerConfig struct {
// HandshakeTimeout is the duration to wait for the WebSocket handshake to complete
HandshakeTimeout time.Duration
// PingTimeout is how long to wait for a ping from the server before considering the connection dead.
// The server sends periodic pings to keep connections alive and detect dead clients.
PingTimeout time.Duration
// EventChanSize is the buffer size for the event channel
// A larger buffer prevents blocking when processing many unsolicited events
EventChanSize int
}
WebsocketDialerConfig contains configuration options for the WebSocket dialer
type WebsocketHandlerGroup ¶
type WebsocketHandlerGroup struct {
// contains filtered or unexported fields
}
WebsocketHandlerGroup implements the HandlerGroup interface for organizing related handlers with shared middleware. Groups support nesting, allowing for hierarchical organization of endpoints with inherited middleware chains.
When a request matches a handler in a group, the middleware chain is:
- Global middleware (from Node.Use)
- Parent group middleware (if nested)
- This group's middleware
- The method handler
This enables fine-grained control over request processing pipelines.
func (*WebsocketHandlerGroup) Handle ¶
func (hg *WebsocketHandlerGroup) Handle(method string, handler Handler)
Handle registers a handler for the specified RPC method within this group. The handler will execute after all applicable middleware:
- Global middleware
- Parent group middleware (for nested groups)
- This group's middleware
The method parameter must be unique across the entire node.
func (*WebsocketHandlerGroup) NewGroup ¶
func (hg *WebsocketHandlerGroup) NewGroup(name string) HandlerGroup
NewGroup creates a nested handler group within this group. The nested group inherits the middleware chain from all parent groups, allowing for progressive middleware application.
Example:
api := node.NewGroup("api")
api.Use(apiVersionMiddleware)
v1 := api.NewGroup("v1")
v1.Use(v1AuthMiddleware)
// Handlers in v1 group will execute: global → api → v1 middleware
func (*WebsocketHandlerGroup) Use ¶
func (hg *WebsocketHandlerGroup) Use(middleware Handler)
Use adds middleware to this handler group. The middleware will execute for all handlers in this group and any nested groups. Middleware is executed in the order it was added.
Panics if middleware is nil.
type WebsocketNode ¶
type WebsocketNode struct {
// contains filtered or unexported fields
}
WebsocketNode implements the Node interface using WebSocket as the transport layer. It provides a complete RPC server implementation with the following features:
- WebSocket connection management with automatic cleanup
- Request routing based on method names
- Middleware support at global and group levels
- Cryptographic signing of all responses
- Connection authentication and re-authentication
- Server-initiated notifications to specific users
- Configurable timeouts and buffer sizes
- Structured logging for debugging and monitoring
The node automatically handles connection lifecycle, including:
- WebSocket protocol upgrade
- Concurrent message processing
- Graceful connection shutdown
- Resource cleanup on disconnection
func NewWebsocketNode ¶
func NewWebsocketNode(config WebsocketNodeConfig) (*WebsocketNode, error)
NewWebsocketNode creates a new WebsocketNode instance with the provided configuration. The node is ready to accept WebSocket connections after creation.
Required configuration:
- Logger: Used for structured logging
Returns an error if required configuration is missing.
func (*WebsocketNode) Handle ¶
func (wn *WebsocketNode) Handle(method string, handler Handler)
Handle registers a handler function for the specified RPC method. When a request with a matching method name is received, the handler will be invoked with a Context containing the request information.
The handler executes after all global middleware registered with Use().
Panics if:
- method is empty
- handler is nil
func (*WebsocketNode) NewGroup ¶
func (wn *WebsocketNode) NewGroup(name string) HandlerGroup
NewGroup creates a new handler group with the specified name. Groups provide a way to organize related handlers and apply common middleware. Groups can be nested to create hierarchical structures.
Example:
// Create a group for authenticated endpoints
privateGroup := node.NewGroup("private")
privateGroup.Use(authMiddleware)
privateGroup.Handle("get_balance", handleGetBalance)
// Create a nested group with additional middleware
adminGroup := privateGroup.NewGroup("admin")
adminGroup.Use(adminAuthMiddleware)
adminGroup.Handle("manage_users", handleManageUsers)
func (*WebsocketNode) Notify ¶
func (wn *WebsocketNode) Notify(userID, method string, params Payload)
Notify sends a server-initiated notification to all connections of a specific user. This enables the server to push updates to clients without a prior request. Common use cases include:
- Balance updates after transactions
- Status changes in long-running operations
- Real-time notifications for user events
The notification is sent to all active connections for the user. If the user has no active connections, the notification is silently dropped.
Notifications have RequestID=0 to distinguish them from responses.
func (*WebsocketNode) ServeHTTP ¶
func (wn *WebsocketNode) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler, making the node compatible with standard HTTP servers. This method:
- Upgrades incoming HTTP requests to WebSocket connections
- Creates a unique connection ID and manages connection state
- Spawns goroutines for concurrent message processing
- Invokes lifecycle callbacks (OnConnect, OnDisconnect, etc.)
- Blocks until the connection is closed
Each connection runs independently with its own goroutines for:
- Reading incoming messages
- Processing requests and routing to handlers
- Writing outgoing responses
- Monitoring connection health
The method ensures proper cleanup when connections close, including removing the connection from the hub and invoking disconnect callbacks.
func (*WebsocketNode) Use ¶
func (wn *WebsocketNode) Use(middleware Handler)
Use adds global middleware that executes for all requests. Middleware is executed in the order it was registered, before any method-specific handlers. Common middleware includes:
- Authentication checks
- Request logging
- Rate limiting
- Request validation
Example:
node.Use(loggingMiddleware) node.Use(rateLimitMiddleware) node.Use(authMiddleware)
type WebsocketNodeConfig ¶
type WebsocketNodeConfig struct {
// Logger is used for structured logging throughout the node (required).
Logger log.Logger
// Connection lifecycle callbacks:
// ObserveConnections is called with the current number of active connections whenever a connection is established or closed.
ObserveConnections ObserveConnectionsFn
// WsUpgraderReadBufferSize sets the read buffer size for the WebSocket upgrader (default: 1024).
WsUpgraderReadBufferSize int
// WsUpgraderWriteBufferSize sets the write buffer size for the WebSocket upgrader (default: 1024).
WsUpgraderWriteBufferSize int
// WsUpgraderCheckOrigin validates the origin of incoming WebSocket requests.
// Default allows all origins; implement this for CORS protection.
WsUpgraderCheckOrigin func(r *http.Request) bool
// WsConnWriteTimeout is the maximum time to wait for a write operation (default: 5s).
// Connections that exceed this timeout are considered unresponsive and closed.
WsConnWriteTimeout time.Duration
// WsConnWriteBufferSize is the capacity of each connection's outgoing message queue (default: 10).
WsConnWriteBufferSize int
// WsConnProcessBufferSize is the capacity of each connection's incoming message queue (default: 10).
WsConnProcessBufferSize int
}
WebsocketNodeConfig contains all configuration options for creating a WebsocketNode. The only required field is Logger; all others have sensible defaults.