The Wavedash SDK gives your game access to player accounts, leaderboards, achievements, multiplayer, cloud saves, and more. This page walks you through getting it set up.
How the SDK works
When your game runs on Wavedash, the platform makes Wavedash available in the browser before your code starts. During local development, wavedash dev does the same thing with a sandbox version so you can test everything offline.
Methods that talk to servers are asynchronous and return Promises. Methods that read local state (like the current player) are synchronous.
View the SDK on GitHubTyped access in JavaScript/TypeScript
Optionally install @wvdsh/sdk-js and import Wavedash directly in your game script for editor autocomplete and type safety:
npm install @wvdsh/sdk-js
import Wavedash from "@wvdsh/sdk-js";
Wavedash.init({ debug: true });
Wavedash.on(Wavedash.Events.LOBBY_JOINED, (payload) => {
console.log(`Joined lobby ${payload.lobbyId}`);
});
The import gives you the host's injected SDK instance with full TypeScript types — methods, events, and payloads all autocomplete. Importing from anywhere in your codebase returns the same SDK singleton.
Initialization
Call Wavedash.init(config?) once — before any other SDK method — to apply your settings and mark the game as loaded. init() is synchronous and returns a boolean (true on first call, false if already initialized). You do not need to await it.
init() also calls loadComplete() internally, so a single init() is enough for most games. See Load lifecycle below if you want to report progress and signal load completion separately.
func _ready():
WavedashSDK.backend_connected.connect(_on_connected)
WavedashSDK.init({"debug": true, "deferEvents": true})
WavedashSDK.ready_for_events()
func _on_connected(payload):
print("SDK is ready!")
var username = WavedashSDK.get_username()
print("Playing as: ", username)
using System.Collections.Generic;
void Awake()
{
Wavedash.SDK.Init(new Dictionary<string, object>
{
{ "debug", true },
{ "deferEvents", true }
});
Wavedash.SDK.ReadyForEvents();
}
void Start()
{
var user = Wavedash.SDK.GetUser();
if (user != null)
Debug.Log($"Playing as: {user["username"]}");
}
Wavedash.init({ debug: true, deferEvents: true });
Wavedash.readyForEvents();
const user = Wavedash.getUser();
console.log(`Playing as: ${user.username}`);
Load lifecycle
Wavedash tracks two separate signals while your game boots:
- Load progress — a 0-to-1 value the shell uses to render its loading bar. Call
updateLoadProgressZeroToOne(progress)while your game is downloading assets or initializing. - Load complete — fires once, when the player can actually interact.
init()calls this for you, or you can callloadComplete()directly if you want to signal completion before you're ready to initialize the full SDK (e.g., hand-off from a splash screen).
// Report progress while assets download
Wavedash.updateLoadProgressZeroToOne(0.2);
await downloadAssets();
Wavedash.updateLoadProgressZeroToOne(0.8);
await startRuntime();
// Either of these works — init() calls loadComplete() internally
Wavedash.init({ debug: false });
// Wavedash.loadComplete(); // only needed if you call it before init()
Both methods are idempotent — calling them twice is a no-op.
Ready-state getters
The SDK exposes three boolean getters for defensive code that needs to know where you are in the lifecycle:
| Getter | True when |
|---|---|
initialized | init() has been called at least once |
eventsReady | The deferred event queue has been flushed (either by init() or a manual readyForEvents()) |
gameLoaded | loadComplete() has fired |
if (!Wavedash.initialized) Wavedash.init();
if (Wavedash.eventsReady && Wavedash.gameLoaded) {
// SDK is fully booted and serving events
}
Loading third-party scripts
Wavedash.loadScript(src) is a small helper that appends a <script> tag to the page and resolves once it finishes loading. Useful for lazy-loading analytics, engine runtimes, or any script you don't want to block initial page load.
await Wavedash.loadScript("https://cdn.example.com/analytics.js");
// analytics global is now available
Overlay
Call toggleOverlay() to show or hide the Wavedash in-game overlay (friends list, invites, settings). Wire it to a pause button or a keyboard shortcut so players can reach Wavedash's built-in UI without leaving your game.
WavedashSDK.toggle_overlay()
Wavedash.SDK.ToggleOverlay();
Wavedash.toggleOverlay();
Response format
Most async SDK methods that talk to Wavedash services return a response object. Check success before using data.
const response = await Wavedash.getLeaderboard("high-scores");
if (response.success) {
console.log(`Leaderboard: ${response.data.name}`);
} else {
console.error(`Error: ${response.message}`);
}
When a call fails, message explains what went wrong.
Error handling
Wrap async service calls in try/catch and check success:
func _on_leaderboard(response):
if not response.get("success", false):
push_error(response.get("message", "leaderboard error"))
return
var board = response["data"]
try
{
var board = await Wavedash.SDK.GetLeaderboard("high-scores");
if (board == null)
{
Debug.LogWarning("Leaderboard call failed");
return;
}
}
catch (Exception ex)
{
Debug.LogException(ex);
}
try {
const response = await Wavedash.getLeaderboard("high-scores");
if (!response.success) {
console.error(response.message);
return;
}
useBoard(response.data);
} catch (e) {
console.error(e);
}
Configuration options
Pass these to init() when you need non-default behavior:
| Option | What it does |
|---|---|
debug | Turns on verbose logging in the browser console |
deferEvents | Queues lobby and multiplayer events until you call readyForEvents() |
p2p | Custom P2P networking settings (see Types reference) |
If you set deferEvents: true, make sure you call readyForEvents() once your game is done loading. Otherwise queued events will never reach your handlers.
Launch params
When a player opens your game through a URL with wvdsh_-prefixed query parameters, Wavedash strips the prefix and passes them to your game as key-value pairs. Call getLaunchParams() after init() to read them.
The most common use case is lobby invite links — when a player clicks an invite link, the lobby param contains the lobby ID so your game can join automatically.
WavedashSDK.init({})
var params = WavedashSDK.get_launch_params()
if params.has("lobby"):
WavedashSDK.join_lobby(params["lobby"])
Wavedash.SDK.Init(new Dictionary<string, object>());
var parameters = Wavedash.SDK.GetLaunchParams();
if (parameters.TryGetValue("lobby", out var lobbyId))
await Wavedash.SDK.JoinLobby(lobbyId);
Wavedash.init();
const params = Wavedash.getLaunchParams();
if (params.lobby) {
await Wavedash.joinLobby(params.lobby);
}
How it works
- A player visits a URL like
https://wavedash.com/games/my-game?wvdsh_lobby=abc123 - Wavedash strips the
wvdsh_prefix from matching query parameters - The resulting key-value pairs (
{ lobby: "abc123" }) are passed to your game - Your game reads them with
getLaunchParams()and acts on them
Only query parameters prefixed with wvdsh_ are forwarded to your game. Other query parameters are ignored.
Built-in params
| Param | Description |
|---|---|
lobby | Lobby ID — the player followed an invite link. Join with joinLobby(). See Multiplayer lobbies. |
You can also pass custom data by adding wvdsh_-prefixed query parameters to any game URL. For example, ?wvdsh_mode=ranked would appear as { mode: "ranked" } in getLaunchParams().
Connection events
Listen for connection changes to show online/offline status in your UI:
func _ready():
WavedashSDK.backend_connected.connect(_on_connected)
WavedashSDK.backend_disconnected.connect(_on_disconnected)
WavedashSDK.backend_reconnecting.connect(_on_reconnecting)
func _on_connected(payload):
print("Connected (attempt %d)" % payload["connectionCount"])
func _on_disconnected(payload):
print("Disconnected (was ever connected: %s)" % payload["hasEverConnected"])
func _on_reconnecting(payload):
print("Reconnecting (retry %d)" % payload["connectionRetries"])
void Awake()
{
Wavedash.SDK.OnBackendConnected += data =>
Debug.Log($"Connected (attempt {data["connectionCount"]})");
Wavedash.SDK.OnBackendDisconnected += data =>
Debug.Log($"Disconnected (was ever connected: {data["hasEverConnected"]})");
Wavedash.SDK.OnBackendReconnecting += data =>
Debug.Log($"Reconnecting (retry {data["connectionRetries"]})");
}
Wavedash.on(Wavedash.Events.BACKEND_CONNECTED, (payload) => {
console.log(`Connected (attempt ${payload.connectionCount})`);
});
Wavedash.on(Wavedash.Events.BACKEND_DISCONNECTED, (payload) => {
console.log(`Disconnected (was ever connected: ${payload.hasEverConnected})`);
});
Wavedash.on(Wavedash.Events.BACKEND_RECONNECTING, (payload) => {
console.log(`Reconnecting (retry ${payload.connectionRetries})`);
});
What's next
Accounts, avatars, friends, and presence.
Lobbies, chat, and P2P networking.
Reward players for hitting milestones.
Godot, Unity, Three.js, and more.
See the Events reference for the complete event list.