Skip to content

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OddSockets Flutter SDK

Official Flutter/Dart SDK for OddSockets real-time messaging platform. Pub/sub, presence, message history. Works on iOS, Android, Web, Desktop.

Install

dependencies:
  oddsockets_flutter: ^1.0.0

Quick Start

import 'package:oddsockets_flutter/oddsockets_flutter.dart';

final client = OddSocketsClient(
  OddSocketsConfig(apiKey: 'YOUR_API_KEY', userId: 'my-agent'),
);
await client.connect();

final channel = client.channel('my-channel');
await channel.subscribe((msg) => print('Received: ${msg.data}'));
await channel.publish({'text': 'Hello from Flutter'});

Token auth for game clients (tokenProvider)

Ship apps with no API key in the binary. Your backend verifies the player (its own login/JWT), calls POST /v1/token on the OddSockets front door, and returns a short-lived realtime token. The SDK asks your tokenProvider for a fresh token before every (re)connect and silently refreshes it before expiry.

final config = OddSocketsConfigBuilder()
    .tokenProvider(() async {
      // Ask YOUR backend for a short-lived OddSockets token.
      final res = await http.post(
        Uri.parse('https://your-game-backend.example/realtime-token'),
        headers: {'Authorization': 'Bearer $playerJwt'},
      );
      // Return the mint response as-is: {token, expiresAt, exp, ...}
      // (a raw JWT string also works).
      return jsonDecode(res.body) as Map<String, dynamic>;
    })
    .userId('player-42')
    .build();

final client = OddSocketsClient(config);
await client.connect();

Notes:

  • tokenProvider is used instead of apiKey — configure one or the other.
  • The refresh fires tokenRefreshLeadMs (default 120000 ms) before expiry and emits a token_refreshed event you can observe via client.on('token_refreshed', (info) => ...) or the eventStream. A failed refresh emits token_refresh_failed instead.
  • Tune the lead with .tokenRefreshLeadMs(120000) on the builder.

Manager URL

The client asks a manager for a worker. Point it at a self-hosted or QA manager with managerUrl:

final client = OddSocketsClient(
  OddSocketsConfig(
    apiKey: 'YOUR_API_KEY',
    managerUrl: 'https://manager.internal.example',
  ),
);

Resolution order, highest first:

  1. managerUrl on OddSocketsConfig
  2. the ODDSOCKETS_MANAGER_URL environment variable (not available on web)
  3. the public endpoint https://connect.oddsockets.tyga.network

Whatever resolves is used verbatim. If it is unreachable the connection fails with that error — the SDK never quietly falls back to another manager, because that would send a QA or self-hosted deployment to production unnoticed. A value that is not an absolute http:// or https:// URL throws an ArgumentError reading Invalid managerUrl: <value>.

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 client.enhanced. The pattern is always the same:

  1. Send an action with a client.enhanced.* method (camelCase).
  2. Receive the paired broadcast with client.on('<event>', handler).
import 'package:oddsockets_flutter/oddsockets_flutter.dart';

final client = OddSocketsClient(
  OddSocketsConfig(apiKey: 'YOUR_API_KEY', userId: 'alice'),
);
await client.connect();

final channel = client.channel('room-42');
await channel.subscribe((msg) {}, const SubscribeOptions(enablePresence: true));

// Receive-path: broadcasts from other users on the channel
client.on('user_typing',    (data) => print('${data['userId']} is typing'));
client.on('reaction_added', (data) => print('${data['userId']} reacted ${data['emoji']}'));
client.on('thread_reply',   (data) => print('new thread reply'));

// Send-path: enhanced actions over the live socket
client.enhanced.startTyping('alice', 'room-42');
client.enhanced.addReaction(
  messageId: 'msg-1', channel: 'room-42', emoji: ':thumbsup:',
  userId: 'alice', userName: 'Alice',
);
await client.enhanced.threadReply(
  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 a Future<Map<String, dynamic>> that completes 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 (future 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 surface.

Get a Free API Key

curl -X POST https://oddsockets.com/api/agent-signup \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "agentName": "my-agent", "platform": "flutter"}'
# Verify with 6-digit code:
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

Free Starter Pro
Price $0/mo $49.99/mo $299/mo
MAU 100 1,000 50,000
Concurrent connections 50 1,000 Unlimited
Messages/day 10,000 4,320,000 Unlimited
Channels 10 Unlimited Unlimited
Storage 100MB (24h) 50GB (6 months) Unlimited

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

Flutter/Dart SDK for OddSockets — real-time WebSocket channels, pub/sub, presence.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages