Skip to content

System Overview

mero-kotlin is a thin composition of small clients over one OkHttp transport, fronted by the Mero class. The device never runs a node — every capability is a suspend HTTP(S) call to a remote one. It’s a faithful Kotlin port of the Mero.js wire contract.

import com.calimero.mero.Mero
import com.calimero.mero.MeroConfig
import com.calimero.mero.storage.EncryptedPrefsTokenStore
val mero = Mero(
MeroConfig(
baseUrl = "https://your-node.example",
tokenStore = EncryptedPrefsTokenStore(context),
)
)
mero.authenticate(Credentials(username = "alice", password = "s3cr3t"))
mero.auth // AuthApi — login, tokens, key management
mero.admin // AdminApi — contexts, apps, namespaces, groups, blobs, TEE
mero.rpc // RpcClient — execute WASM contract methods
mero.http // the transport in use (advanced callers)

For the visual layer map, see The device is a thin client on the home page.

Mero holds a RefreshCoordinator that makes token refresh race-free. When several concurrent requests all get a 401, it serialises them so exactly one refresh runs; the rest await its result and retry with the rotated token. Refresh tokens are single-use, so this is what keeps concurrent traffic from revoking the token family. A refreshLockFile extends the guarantee across processes (a background worker and the UI won’t both replay a token). See the token lifecycle.

Every call is a suspend function — invoke them from a coroutine:

val authed = mero.isAuthenticated // a plain Boolean property
mero.logout() // suspend

Transport — HttpClient / OkHttpTransport

Section titled “Transport — HttpClient / OkHttpTransport”

An OkHttp-based client (OkHttpTransport) implementing the HttpClient interface. It attaches Authorization: Bearer, runs the reactive 401 → refresh → retry cycle (via an OkHttp Authenticator), handles the terminal x-auth-error cases, and retries transient network/5xx failures with backoff. Mero builds it from your MeroConfig. Advanced callers reach it as mero.http — see the error model.

API clients — AuthApi, AdminApi, RpcClient

Section titled “API clients — AuthApi, AdminApi, RpcClient”

All three are lightweight classes built over the shared HttpClient; none manages tokens itself — the transport does.

  • AuthApi (mero.auth) — the node’s /auth and identity/key endpoints: generateTokens, refreshToken, providers, and root/client key management. See the auth API reference.
  • AdminApi (mero.admin) — the node’s /admin-api surface: contexts, applications, packages, namespaces, groups, blobs, aliases, capabilities, metadata, upgrades/migration, and TEE. See the admin API reference.
  • RpcClient (mero.rpc) — JSON-RPC to /jsonrpc; executes WASM contract methods and decodes the result into your type. See executing methods.

Where tokens persist between launches. EncryptedPrefsTokenStore (secure, backed by AndroidX EncryptedSharedPreferences) or MemoryTokenStore (ephemeral, the default). Implement the TokenStore interface to use your own.

A separate module with a MeroClient view-model (exposing a StateFlow<MeroAuthState>) plus a MeroProvider/useMero pair and drop-in LoginSheet / ConnectButton composables — the analog of mero-react’s MeroProvider/useMero + LoginModal. See the Compose frontend guide.

Small and coroutine-native:

Library Used for
OkHttp (+ okhttp-sse) all HTTP requests and the SSE stream
kotlinx.serialization JSON coding of wire types
kotlinx.coroutines suspend calls and the Flow event stream
AndroidX Security the EncryptedPrefsTokenStore
AndroidX Browser the SSO Custom Tab (SsoLauncher)
Jetpack Compose the optional mero-compose layer

Kotlin 2.x, Android minSdk 24 / compileSdk 34.

Every call is HTTP to a single remote merod node:

Client Node surface
mero.auth GET/POST /auth/*, /admin/keys*
mero.admin /admin-api/* (REST)
mero.rpc POST /jsonrpc (JSON-RPC)
mero.events(contextIds) GET /sse + POST /sse/subscription (SSE stream)