Skip to content

Quickstart

mero-kotlin (com.calimero.mero) is the native Kotlin SDK for a remote Calimero node. This page takes you from adding the dependency to your first authenticated contract call.

  • Kotlin 2.x, coroutines + Flow throughout.
  • Android minSdk 24, compileSdk 34.
  • Dependencies (pulled in transitively): OkHttp (+ okhttp-sse), kotlinx.serialization, AndroidX Security, AndroidX Browser.

Published to GitHub Packages on each v* tag. Add the repository (see PUBLISHING.md for the credentials snippet), then the dependency:

build.gradle.kts
dependencies {
implementation("com.calimero.mero:mero-core:0.1.0")
implementation("com.calimero.mero:mero-compose:0.1.0") // optional Compose UI
}

Coordinates are com.calimero.mero:{mero-core,mero-compose}:<version>.

Every SDK call is a suspend function — call them from a coroutine (a lifecycleScope/viewModelScope launch, or another suspend function).

  1. Create the client. Point it at your node; persist tokens in encrypted storage and give the cross-process refresh lock a file.

    import com.calimero.mero.Mero
    import com.calimero.mero.MeroConfig
    import com.calimero.mero.storage.EncryptedPrefsTokenStore
    import java.io.File
    val mero = Mero(
    MeroConfig(
    baseUrl = "https://your-node.example",
    tokenStore = EncryptedPrefsTokenStore(context), // in-memory otherwise
    refreshLockFile = File(context.filesDir, "mero-refresh.lock"),
    )
    )
  2. Authenticate with a username and password. bootstrapSecret is only needed for the very first login on a fresh node.

    import com.calimero.mero.Credentials
    mero.authenticate(Credentials(username = "alice", password = "s3cr3t"))
    val authed = mero.isAuthenticated // true
  3. Call a contract over JSON-RPC. The result is decoded with kotlinx.serialization into your @Serializable type; arguments are a JsonObject.

    import kotlinx.serialization.Serializable
    import kotlinx.serialization.json.buildJsonObject
    import kotlinx.serialization.json.put
    @Serializable data class Post(val id: String, val title: String)
    val post: Post = mero.rpc.execute(
    contextId = "…",
    method = "get_post",
    argsJson = buildJsonObject { put("id", "42") },
    )
  4. Use the admin & auth APIs for everything else.

    val contexts = mero.admin.getContexts()
    val providers = mero.auth.getProviders()
  5. Log out — clears the token bundle from memory and the store (and, when a clientId is supplied, best-effort revokes it server-side).

    mero.logout()

Failures are thrown as subclasses of MeroException. Catch the ones you care about:

import com.calimero.mero.http.AuthRevokedException
import com.calimero.mero.http.HttpException
import com.calimero.mero.rpc.RpcException
try {
val post: Post = mero.rpc.execute(
contextId = "…", method = "get_post",
argsJson = buildJsonObject { put("id", "42") },
)
} catch (e: AuthRevokedException) {
// refresh token reused/revoked — prompt re-login
} catch (e: RpcException) {
println("contract error ${e.code}: ${e.message}")
} catch (e: HttpException) {
println("HTTP ${e.status}")
}

See the error model for every type.