Skip to content

About

Go SDK for OddSockets — real-time WebSocket channels, pub/sub, presence. Goroutine-safe.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

14 Commits

Folders and files

Repository files navigation

OddSockets Go SDK

Go Reference Go Report Card License: MIT

Official Go SDK for OddSockets real-time messaging platform.

Features

  • High Performance: Optimized for Go's concurrency model with goroutines
  • Channels & Context: Native Go patterns with context cancellation
  • Type Safety: Strong typing with Go structs and interfaces
  • Enhanced Surface: Slack-like reactions, threads, typing, presence and more
  • Cost Effective: No per-message pricing — a monthly message allowance
  • Cloud Native: Perfect for microservices and Kubernetes deployments

📦 Installation

go get github.com/jyswee/oddsockets-go-sdk

🏃‍♂️ Quick Start

Basic Usage

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/jyswee/oddsockets-go-sdk/oddsockets"
)

func main() {
    // Create client
    client, err := oddsockets.NewClient(&oddsockets.Config{
        APIKey:     "ak_live_1234567890abcdef",
        ManagerURL: "https://connect.oddsockets.tyga.network",
        UserID:     "go-demo-user",
    })
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    // Connect to OddSockets
    ctx := context.Background()
    if err := client.Connect(ctx); err != nil {
        log.Fatal(err)
    }

    // Create channel
    channel := client.Channel("my-channel")

    // Subscribe to messages
    messages := make(chan *oddsockets.Message, 100)
    if err := channel.Subscribe(ctx, messages, &oddsockets.SubscribeOptions{
        EnablePresence: true,
        RetainHistory:  true,
    }); err != nil {
        log.Fatal(err)
    }

    // Handle messages in goroutine
    go func() {
        for msg := range messages {
            fmt.Printf("Received: %+v\n", msg.Data)
        }
    }()

    // Publish a message
    if err := channel.Publish(ctx, "Hello from Go! 🐹", nil); err != nil {
        log.Fatal(err)
    }

    // Keep alive
    time.Sleep(5 * time.Second)
}

Context and Cancellation

package main

import (
    "context"
    "time"

    "github.com/jyswee/oddsockets-go-sdk/oddsockets"
)

func main() {
    client, _ := oddsockets.NewClient(&oddsockets.Config{
        APIKey: "ak_live_1234567890abcdef",
    })
    defer client.Close()

    // Context with timeout
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()

    // Connect with context
    client.Connect(ctx)

    channel := client.Channel("timed-channel")
    messages := make(chan *oddsockets.Message, 10)

    // Subscribe with context cancellation
    go func() {
        channel.Subscribe(ctx, messages, nil)
    }()

    // Context will automatically cancel subscription after timeout
}

Token auth for game clients (TokenProvider)

Game and app clients should never ship a static API key. Instead, supply a TokenProvider callback that exchanges your player's own JWT for a short-lived, scoped realtime token via the OddSockets /v1/token front door. The SDK calls it before every (re)connect and again shortly before the token expires, so the connection refreshes itself with no restart.

client, _ := oddsockets.NewClient(&oddsockets.Config{
    // No APIKey. The provider supplies a fresh minted token instead.
    TokenProvider: func(ctx context.Context) (oddsockets.Token, error) {
        // Exchange the signed-in player's JWT for a realtime token.
        // POST https://connect.oddsockets.tyga.network/v1/token
        //   Authorization: Bearer <player JWT>
        // -> { token, expiresAt, exp, baseUrl, identity }
        return mintRealtimeToken(ctx, playerJWT())
    },
    // Refresh this many ms before expiry (default 120000).
    TokenRefreshLeadMs: 120000,
})

// token_refreshed fires each time the SDK rotates the token in place.
client.On("token_refreshed", func(_ oddsockets.EventType, data interface{}) {
    log.Printf("realtime token refreshed: %+v", data)
})

client.Connect(context.Background())

The Token returned by your provider only needs Token; ExpiresAt (ISO-8601 or epoch), Exp (epoch seconds), or the JWT's own exp claim are used to schedule the ahead-of-expiry refresh.

Enhanced Features

Beyond core pub/sub, OddSockets ships a Slack-like enhanced surface — reactions, typing indicators, threads, read receipts, presence/status, notifications, DMs, channel management, message editing and search. It lives on the exported client.Enhanced field. The pattern is always the same:

  1. Send an action with a client.Enhanced.* method.
  2. Receive the paired broadcast with client.On("<event>", handler).
package main

import (
    "context"
    "fmt"
    "log"

    "github.com/jyswee/oddsockets-go-sdk/oddsockets"
)

func main() {
    client, err := oddsockets.NewClient(&oddsockets.Config{
        APIKey: "ak_live_1234567890abcdef",
        UserID: "alice",
    })
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    ctx := context.Background()
    if err := client.Connect(ctx); err != nil {
        log.Fatal(err)
    }

    // Receive-path: broadcasts from other users on the channel
    client.On("user_typing", func(_ oddsockets.EventType, data interface{}) {
        m, _ := data.(map[string]interface{})
        fmt.Printf("%v is typing\n", m["userId"])
    })
    client.On("reaction_added", func(_ oddsockets.EventType, data interface{}) {
        m, _ := data.(map[string]interface{})
        fmt.Printf("%v reacted %v\n", m["userId"], m["emoji"])
    })

    channel := client.Channel("room-42")
    msgs := make(chan *oddsockets.Message, 100)
    channel.Subscribe(ctx, msgs, &oddsockets.SubscribeOptions{EnablePresence: true})

    // Send-path: enhanced actions over the live socket
    client.Enhanced.StartTyping("alice", "room-42")
    client.Enhanced.AddReaction(oddsockets.ReactionParams{
        MessageID: "msg-1",
        Channel:   "room-42",
        Emoji:     ":thumbsup:",
        UserID:    "alice",
        UserName:  "Alice",
    })
    client.Enhanced.ThreadReply(oddsockets.ThreadReplyParams{
        Channel:         "room-42",
        ParentMessageID: "msg-1",
        Message:         "Replying in the thread",
        UserID:          "alice",
        UserName:        "Alice",
    })
}

Each area exposes methods on client.Enhanced; the worker broadcasts the paired events which you handle with client.On(...). Query methods (Get*, Search*) return (map[string]interface{}, error) with the worker response.

Area Requests (client.Enhanced.*) Broadcast events (client.On)
Typing StartTyping, StopTyping user_typing, user_stopped_typing
Reactions AddReaction, RemoveReaction, GetReactions reaction_added, reaction_removed
Threads ThreadReply, GetThread, SubscribeThread, FollowThread, MarkThreadRead thread_reply, thread_subscribed, thread_followed, thread_read_updated
Read receipts MarkRead, MarkAllRead, GetUnreadCounts user_read, unread_count_updated, all_marked_read
Messages EditMessage, DeleteMessage, PinMessage, UnpinMessage, GetPinnedMessages, SearchMessages message_edited, message_deleted, message_pinned, message_unpinned
Presence & status SetStatus, SetCustomStatus, SetDND, GetUserPresence user_status_changed, custom_status_updated, dnd_status_changed
Channels CreateChannel, UpdateChannel, ArchiveChannel, InviteToChannel, JoinChannel, LeaveChannel channel_created, channel_updated, user_invited, user_joined_channel, user_left_channel
DMs CreateDM, SendDM, GetDMConversations dm_created, dm_received
Notifications SubscribeNotifications, GetNotifications, MarkNotificationRead, ClearNotifications notification, notification_read, notifications_cleared
Search SearchMessages, SearchInChannel, SearchByUser, FilterMessages (map, error) results

For any worker event not wrapped above, subscribe with the raw client.On("<event>", handler) API — all enhanced broadcasts are forwarded onto the client event stream.

Examples

Explore the runnable examples:

Configuration

Client Options

config := &oddsockets.Config{
    APIKey:             "your-api-key",       // Your OddSockets API key (or use TokenProvider)
    TokenProvider:      provider,             // Optional: mint minted tokens instead of an API key
    TokenRefreshLeadMs: 120000,               // Optional: refresh lead time before token expiry
    ManagerURL:         "manager-url",        // Optional: Manager URL
    UserID:             "user-id",            // Optional: User identifier
    AutoConnect:        true,                 // Optional: Auto-connect on creation
    ReconnectAttempts:  5,                    // Optional: Max reconnection attempts
    HeartbeatInterval:  30 * time.Second,     // Optional: Heartbeat interval
    Timeout:            10 * time.Second,     // Optional: Request timeout
}
// Provide EITHER APIKey OR TokenProvider.

Channel Options

// Subscribe with options
err := channel.Subscribe(ctx, messages, &oddsockets.SubscribeOptions{
    EnablePresence:    true,                  // Enable presence tracking
    RetainHistory:     true,                  // Retain message history
    FilterExpression:  "user.premium == true", // Message filter expression
})

// Publish with options
err := channel.Publish(ctx, message, &oddsockets.PublishOptions{
    TTL:             3600,                    // Time to live (seconds)
    Metadata:        map[string]interface{}{"priority": "high"}, // Additional metadata
    StoreInHistory:  true,                    // Store in message history
})

Go Support

  • Go 1.19+
  • Goroutines and channels
  • Context cancellation
  • Structured concurrency

Testing

# Run tests
go test ./...

# Run tests with coverage
go test -cover ./...

# Run benchmarks
go test -bench=. ./...

# Run integration tests
go test -tags=integration ./...

Building

# Get dependencies
go mod tidy

# Build
go build ./...

# Install
go install ./...

# Cross-compile
GOOS=linux GOARCH=amd64 go build -o oddsockets-linux ./cmd/example

Performance

  • Automatic failover - the cluster reroutes you if a node goes away, and the SDK reconnects and resubscribes on your behalf
  • No per-message pricing - you buy a monthly message allowance, not individual sends
  • 32 KB maximum message size - split anything larger, or publish a reference to it
  • Non-blocking - deliveries are dispatched on goroutines, so publishes never block your caller

Uptime SLA is per plan (Pro 99.9%, Scale 99.95%, Enterprise 99.999%) — see pricing for the current commitment.

Security

  • End-to-end encryption available
  • API key authentication with fine-grained permissions
  • Rate limiting and abuse protection
  • GDPR compliant data handling

Framework Integrations

Gin Web Framework

package main

import (
    "github.com/gin-gonic/gin"
    "github.com/jyswee/oddsockets-go-sdk/oddsockets"
)

func main() {
    client, _ := oddsockets.NewClient(&oddsockets.Config{
        APIKey: "ak_live_1234567890abcdef",
    })
    defer client.Close()

    r := gin.Default()
    
    r.POST("/send-message", func(c *gin.Context) {
        var req struct {
            Channel string      `json:"channel"`
            Message interface{} `json:"message"`
        }
        
        if err := c.ShouldBindJSON(&req); err != nil {
            c.JSON(400, gin.H{"error": err.Error()})
            return
        }
        
        channel := client.Channel(req.Channel)
        if err := channel.Publish(c.Request.Context(), req.Message, nil); err != nil {
            c.JSON(500, gin.H{"error": err.Error()})
            return
        }
        
        c.JSON(200, gin.H{"status": "sent"})
    })
    
    r.Run(":8080")
}

gRPC Service

package main

import (
    "context"
    
    "github.com/jyswee/oddsockets-go-sdk/oddsockets"
    "google.golang.org/grpc"
)

type MessageService struct {
    client *oddsockets.Client
}

func (s *MessageService) SendMessage(ctx context.Context, req *SendMessageRequest) (*SendMessageResponse, error) {
    channel := s.client.Channel(req.Channel)
    
    if err := channel.Publish(ctx, req.Message, nil); err != nil {
        return nil, err
    }
    
    return &SendMessageResponse{Success: true}, nil
}

Kubernetes Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: oddsockets-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: oddsockets-service
  template:
    metadata:
      labels:
        app: oddsockets-service
    spec:
      containers:
      - name: service
        image: your-registry/oddsockets-service:latest
        env:
        - name: ODDSOCKETS_API_KEY
          valueFrom:
            secretKeyRef:
              name: oddsockets-secret
              key: api-key
        - name: ODDSOCKETS_MANAGER_URL
          value: "https://connect.oddsockets.tyga.network"

Other SDKs

OddSockets is available in multiple languages:

  • JavaScript SDK - Browser + Node.js, TypeScript ready
  • Python SDK - AsyncIO support, Django/Flask integrations
  • Java SDK - Enterprise-ready, Spring Boot integration
  • C# SDK - .NET Core/Framework, Azure integrations
  • Swift SDK - iOS native, Combine framework
  • Kotlin SDK - Android native, coroutines support

Get an API Key

AI agents can sign up with a verified email in two steps — no dashboard, no human required.

Step 1: Request a verification code

curl -X POST https://oddsockets.com/api/agent-signup \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "agentName": "my-agent", "platform": "go"}'

Step 2: Verify the 6-digit code from your email and get your API key

curl -X POST https://oddsockets.com/api/agent-signup/verify \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "code": "123456", "agentName": "my-agent"}'

Plans

No free tier — every plan starts with a 7-day free trial.

Starter Pro Scale Enterprise
Price $29/mo $99/mo $299/mo Contact sales
Messages/mo 5M 25M 100M Unlimited
Peak connections 200 1,000 5,000 Unlimited
MAU Unlimited Unlimited Unlimited Unlimited
Extra messages $2.50/M $1.60/M $1.00/M Included

Current pricing: oddsockets.com/#pricing.

All limits are enforced in real time.

Get Accredited

tyga.games accreditation

Prove you can build and operate real-time features on OddSockets — channels, presence, pub/sub, delivery guarantees and production liveops — on the stack itself. Three tiers (TCU / TCA / TCP), certified through tyga.games and delivered on ClassaaS.

Get accredited on tyga.games →

Support

License

MIT License - Copyright (c) 2026 Joe Wee, Tyga.Cloud Ltd. See LICENSE for details.

About

Go SDK for OddSockets — real-time WebSocket channels, pub/sub, presence. Goroutine-safe.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages