Skip to content
Windows only · Invite only. To get the SDK, DM @snailyt on Telegram.

Quickstart

This sets up a Win32 GUI app. For console tools, see Blocking calls.

Do this in one .cpp file, for example where you create the main window.

#include "eonauth.h"
#include "config.h" // generated by the panel
#define WM_APP_EONAUTH (WM_APP + 1)
bool StartLicensing(HWND mainWindow) {
eonauth::Config cfg;
cfg.host = demo_config::kApiHost;
cfg.appId = demo_config::kAppId;
cfg.keyVersion = demo_config::kKeyVersion;
cfg.hmacSecret = eonauth::UnmaskSecret(demo_config::kHmacSecretMasked, demo_config::kHmacSecretPad, 32);
cfg.encKey = eonauth::UnmaskSecret(demo_config::kEncKeyMasked, demo_config::kEncKeyPad, 32);
cfg.responseSigningKey = EONAUTH_RESPONSE_SIGNING_KEY;
cfg.appVersion = "1.0.0";
if (const eonauth::Result r = eonauth::Init(cfg); !r) {
MessageBoxW(mainWindow, eonauth::ToWide(r.message).c_str(), L"Licensing", MB_ICONERROR);
return false;
}
eonauth::WipeSecrets(cfg);
// Deliver every callback and event on the UI thread:
eonauth::SetDispatcher(eonauth::win32::WindowDispatcher(mainWindow, WM_APP_EONAUTH));
eonauth::AddEventHandler(OnLicensingEvent);
eonauth::ResumeSessionAsync(); // signs in automatically if a saved session is still valid
return true;
}

In that window’s procedure:

case WM_APP_EONAUTH:
eonauth::win32::RunDispatched(lParam);
return 0;
case WM_DESTROY:
eonauth::Shutdown(); // stops the background thread; Shutdown(true) also signs out
PostQuitMessage(0);
return 0;

Using Qt, wxWidgets or Dear ImGui? Pass your own dispatcher:

eonauth::SetDispatcher([](std::function<void()> work) {
QMetaObject::invokeMethod(qApp, std::move(work));
});
void OnLicensingEvent(const eonauth::EventInfo& e) {
switch (e.event) {
case eonauth::Event::LoggedIn: ShowMainUi(); break;
case eonauth::Event::LoggedOut: ShowLoginUi(); break;
case eonauth::Event::SessionLost: ShowLoginUi(); ShowMessage(eonauth::UserMessage(e.result)); break;
case eonauth::Event::SubscriptionsChanged: RefreshTierUi(); break;
case eonauth::Event::ConnectionProblem: ShowBanner("Reconnecting…"); break; // still signed in
case eonauth::Event::ConnectionRestored: HideBanner(); break;
}
}

SessionLost covers everything the server can end a session for: a ban, a revoked key, expiry, a PC mismatch, a blacklist entry, a forced update, or being offline longer than the idle timeout.

login_dialog.cpp
#include "eonauth.h"
void LoginDialog::OnSignIn() {
eonauth::LoginAsync(eonauth::ToUtf8(user), eonauth::ToUtf8(pass), [this](const eonauth::Result& r) {
if (!r) ShowError(eonauth::UserMessage(r), eonauth::UserHint(r)); // success raises LoggedIn
});
}
void LoginDialog::OnSignInWithKey() {
const std::string key = eonauth::NormalizeLicenseKey(eonauth::ToUtf8(keyText));
eonauth::LoginWithKeyAsync(key, eonauth::ToUtf8(user), [this](const eonauth::Result& r) {
if (r.status == eonauth::Status::UsernameRequired) AskForUsername(); // first use of this key
else if (!r) ShowError(eonauth::UserMessage(r), eonauth::UserHint(r));
});
}
editor.cpp
#include "eonauth.h"
void Editor::UpdateToolbar() {
exportButton.SetEnabled(eonauth::HasTier("Pro")); // a snapshot read: never blocks
}
void Editor::OnExport() {
// The real feature data comes from the server, only for Pro:
eonauth::FetchVariableAsync("var_0123456789abcdef0123456789abcdef",
[this](const eonauth::Result& r, const std::string& value) {
if (r) RunExport(value);
else if (r.status == eonauth::Status::VariableNotFound) ShowUpgradePrompt();
else ShowError(eonauth::UserMessage(r), eonauth::UserHint(r));
});
}

The local HasTier check is for the UI. The variable is the part a cracked copy can’t fake. See Tiers and variables.