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.
The shape of a client
Section titled “The shape of a client”import com.calimero.mero.Meroimport com.calimero.mero.MeroConfigimport 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 managementmero.admin // AdminApi — contexts, apps, namespaces, groups, blobs, TEEmero.rpc // RpcClient — execute WASM contract methodsmero.http // the transport in use (advanced callers)For the visual layer map, see The device is a thin client on the home page.
Single-flight refresh
Section titled “Single-flight refresh”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 propertymero.logout() // suspendThe layers
Section titled “The layers”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/authand identity/key endpoints:generateTokens,refreshToken, providers, and root/client key management. See the auth API reference.AdminApi(mero.admin) — the node’s/admin-apisurface: 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.
Token store — TokenStore
Section titled “Token store — TokenStore”Where tokens persist between launches. EncryptedPrefsTokenStore (secure, backed
by AndroidX EncryptedSharedPreferences) or MemoryTokenStore (ephemeral, the
default). Implement the TokenStore interface to use your own.
Optional frontend — mero-compose
Section titled “Optional frontend — mero-compose”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.
Dependencies
Section titled “Dependencies”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.
How it maps to the node
Section titled “How it maps to the node”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) |