Quickstart
This sets up a Win32 GUI app. For console tools, see Blocking calls.
1. Start up once
Section titled “1. Start up once”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));});2. React to events in one place
Section titled “2. React to events in one place”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.
3. Sign in from any file
Section titled “3. Sign in from any file”#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)); });}4. Gate features
Section titled “4. Gate features”#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.
- Sign-in flows: passwords, keys, free mode, resume, redeem.
- Errors and messages: what to show when something fails.
- Testing locally.