Skip to main content

Android API Reference

Complete reference of the public Android SDK surface (gg.interstellar.wallet). All methods live on InterstellarSdk unless noted otherwise. suspend functions do network work on Dispatchers.IO and are safe to call from the main thread. Cached values are marked [cached]; live network calls are marked [network].

Naming

The API mirrors the underlying Rust calls: getter… functions read state, extrinsic… functions submit on-chain actions, and prepare… functions arm a pinpad/VCA flow.

Observable state​

MemberTypeDescription
balancesStateFlow<WalletBalances>[cached] per-coin balances in base units (BigDecimal). Updated by updateBalances/updateBalance.
totalBalanceUsdStateFlow<String>[cached] total portfolio value in USD, 2 decimals (e.g. "12.34").
vcaCount / nfcCountStateFlow<Int>Number of VCA-token / NFC recovery methods registered by this device.
recoveryThresholdStateFlow<Int>Configured recovery threshold (default 1).
recoveryVouchSubmittedStateFlow<Boolean>true when this device has vouched to recover a lost account and is waiting the ~10-block delay before it can recoveryClaim(). Persisted across restarts. Gate your "Claim" button on this, not on the counts.
pendingCircuitsPackageStateFlow<JniCircuitsPackage?>Non-null while a VCA/pinpad flow is armed and its circuits are ready to render.
pendingCampaignIdStateFlow<String?>Campaign id of the armed airdrop flow (null for other flows).
navigateToPinpadStateFlow<Boolean>true when the SDK wants your app to show the pinpad overlay now (see Pinpad integration).
showTxFailedStateFlow<Boolean>true only when a coin-transfer pinpad input was rejected (wrong code). See the pinpad page — never infer failure from a null pinpad result alone.
toastListenerSdkToastListener?Set this to receive the SDK's toast feedback (always delivered on the main thread).

Value objects​

  • WalletBalances(dot, sol, btc, eth: BigDecimal) — standard base units (planck/lamport/satoshi/wei). Public DTO: what your UI displays.
  • enum class CoinType(id: Int) — Dot(0), Sol(1), Btc(2), Eth(3). Ordinal/id is wire-compatible with the Rust core — do not reorder.
  • enum class VcaFlowType — the flow the SDK is currently armed for: DEMO_TX, RECOVERY_VCA_VOUCH, AIRDROP_REGISTRATION, AIRDROP_CLAIM, COIN_TRANSFER.
  • JniTxAmount — amount spec for extrinsicClientInitializeTransaction: JniTxAmount.fixed(amount) for a fixed amount in display units (e.g. 0.1 ETH), or JniTxAmount.drainAccount() to send the whole balance. (⚠️ iOS takes atomic units — see the differences table.)
  • JniPendingTxResult(status: Int, circuitsPackage: JniCircuitsPackage?, txHash: String?) — result of getterClientGetPendingTx(): status == 0 → RequiresVca (a JniCircuitsPackage needs user confirmation), status == 1 → AutoSent (txHash already broadcast, no VCA required). null → the transaction could not be prepared (e.g. insufficient funds).
  • JniCircuitsPackage — opaque handle for a rendered VCA package (the garbled circuits, the tx id and the number of message digits): pass it to TxPinpadView / importRecoveryToken / the pinpad-consuming calls; never inspect it.
  • CampaignInfo(campaignId, status, chain, amountPerClaim: String, claimLimit: Int, totalFunds: String, registrationCount: Int, claimCount: Int, fundingAddress) — full campaign details. ⚠️ amountPerClaim and totalFunds are strings (they are decimal amounts).
  • UserCampaign(campaignId, state) — this account's registration state in a campaign.
  • SdkInitListener — suspend fun onServerResetDetected(); SdkToastListener — onToast(message: String, duration: Int).
  • InterstellarFileSharer — shareData(data: ByteArray, fileName: String, mimeType: String, shareTitle: String); used to export the recovery token.
  • InterstellarSigningException — thrown when the Android Keystore signing fails.
  • Price constants DOTUSD, SOLUSD, BTCUSD, ETHUSD (BigDecimal; demo-grade values).

Constants​

ConstantValueDescription
DEFAULT_WS_URLwss://127.0.0.1:2090The Interstellar worker (L2) endpoint the SDK talks to by default.
DEFAULT_NODE_URLws://127.0.0.1:9944The Integritee node (L1) endpoint.
DEFAULT_IPFS_ADDR/ip4/127.0.0.1/tcp/5001The IPFS endpoint (the garbled circuits).
TOAST_LENGTH_SHORT / TOAST_LENGTH_LONG0 / 1The duration values for SdkToastListener.onToast.
note

The three DEFAULT_* constants point at the local dev stack: each port needs an adb reverse tcp:PORT tcp:PORT to be reachable from a device or an emulator. Changing the environment is done at integration time by Interstellar — contact us for the other values.

Initialization & lifecycle​

APISignatureDescription
createsuspend fun create(context: Context, fileSharer: InterstellarFileSharer, listener: SdkInitListener? = null): InterstellarSdk[network] The only entry point. Registers the device if needed, handles server-reset via listener, warms the balance cache, returns a ready SDK.
checkServerResetsuspend fun checkServerReset(listener: SdkInitListener?): Boolean[network] Re-run the server-reset detection (call on app resume). Returns true if a reset was detected and handled (your listener was awaited, then re-registration + balance refresh happened).
resetKeyPairAndRegistersuspend fun resetKeyPairAndRegister()[network] Delete the Android-Keystore key, wipe cached state and register a new identity. User-initiated only.
toastListenerpropertySee Overview.

Root & coin accounts​

APISignatureDescription
getterRootAccountsuspend fun getterRootAccount(): ByteArray[cached → network] The 32-byte root account id of this device. Served from the local cache when available.
getterClientGetAccountsuspend fun getterClientGetAccount(coinType: CoinType): String?[cached → network] Deposit address of the coin client (e.g. base58 SOL, hex ETH). Usable as-is as a transfer recipient or faucet target.
getterClientGetAccountWithPrefixsuspend fun getterClientGetAccountWithPrefix(coinType: CoinType): String?[cached → network] Same, prefixed form (e.g. SS58 for DOT) for display.

Balances​

APISignatureDescription
updateBalancessuspend fun updateBalances(context: Context, listener: SdkInitListener? = null)[network] Refresh all coin balances and update balances/totalBalanceUsd. If listener is given, a server-reset check runs first (pull-to-refresh pattern).
updateBalancesuspend fun updateBalance(context: Context, coinType: CoinType, listener: SdkInitListener? = null)[network] Same, for a single coin.
getterClientGetBalanceInCoinfun getterClientGetBalanceInCoin(coinType: CoinType): BigDecimal[cached] Balance in base units — no network call.
getterClientGetBalanceInUsdfun getterClientGetBalanceInUsd(coinType: CoinType): Double[cached] Balance converted to USD (2 decimals, hardcoded price table).
getterClientGetTotalBalanceInUsdfun getterClientGetTotalBalanceInUsd(): Double[cached] Sum over all coins.
convertToUsdfun convertToUsd(coinType: CoinType, amount: Double): DoubleHelper to display a user-entered amount in USD.
convertCoinToAtomicfun convertCoinToAtomic(coinType: CoinType, amount: Double): LongConvert a display amount (e.g. 0.1 ETH) to atomic units (Wei).

Transactions (coin transfer)​

The supported end-to-end flow — all steps are [network]:

// 1. Prepare the transaction on-chain-side.
sdk.extrinsicClientInitializeTransaction(
recipient = "9WzDX…", // recipient address
txAmount = JniTxAmount.fixed(0.5), // or JniTxAmount.drainAccount()
coinType = CoinType.Sol,
)

// 2. Ask the SDK what to do next.
when (val pending = sdk.getterClientGetPendingTx()) {
null -> { /* failed: e.g. insufficient balance */ }
else -> if (pending.status == 1) {
// AutoSent: no VCA required for this policy — tx already broadcast.
val hash = pending.txHash
} else {
// RequiresVca: arm the pinpad (recommended shortcut below),
// or render it yourself from pending.circuitsPackage.
sdk.prepareCoinTransfer(CoinType.Sol) // → navigateToPinpad=true
}
}

Prefer the high-level shortcut in one call — prepareCoinTransfer does steps 1–2 internally:

sdk.prepareCoinTransfer(CoinType.Sol)   // arms pinpad if VCA needed; no-ops if AutoSent
APISignatureDescription
extrinsicClientInitializeTransactionsuspend fun extrinsicClientInitializeTransaction(recipient: String, txAmount: JniTxAmount, coinType: CoinType): StringInitialize a transaction to recipient. Returns a tx hash.
getterClientGetPendingTxsuspend fun getterClientGetPendingTx(): JniPendingTxResult?Inspect the pending transaction: RequiresVca (needs pinpad) or AutoSent (already broadcast). null on failure.
prepareCoinTransferfun prepareCoinTransfer(coinType: CoinType)High-level: initializes the pinpad state for the pending coin transfer only if a VCA is required (navigateToPinpad=true). Toasts on failure.
extrinsicClientTransfersuspend fun extrinsicClientTransfer(jniCircuitsPackage: JniCircuitsPackage, inputDigits: ByteArray, coinType: CoinType, onTxDone: () -> Unit)Low-level: submit the pinpad digits to validate & broadcast. You normally do not call this — TxPinpadView does it for you via processPinpadInputs.
getterLatestBroadcastedTxHashsuspend fun getterLatestBroadcastedTxHash(): String?Latest broadcasted tx hash for this account — call after a transfer to show the receipt.
clearPinpadfun clearPinpad()Reset all pinpad state (navigateToPinpad=false, package/campaign cleared). Call when you hide your pinpad overlay.
Reading the transfer result

Only for a coin transfer a rejected pinpad means failure: the SDK sets showTxFailed=true and processPinpadInputs (invoked internally by TxPinpadView) delivers null. For every other flow (recovery vouch, airdrop) a null result is not a failure — key your "Transaction failed" UI off showTxFailed, never off null.

Keypairs & message signing​

APISignatureDescription
extrinsicClientAddKeypairsuspend fun extrinsicClientAddKeypair(coinType: CoinType)Create a new keypair for the coin client (usually done automatically at registration).
extrinsicClientSignMessagesuspend fun extrinsicClientSignMessage(message: ByteArray, coinType: CoinType)[network] Sign an arbitrary message (e.g. eth_sign) with the coin key. Does NOT use a VCA — no user pinpad.
getterSignMessagesuspend fun getterSignMessage(): ByteArray?Retrieve the signature produced above.

Recovery​

Registration-time APIs (device has its account) and restore-time APIs (device lost its account) both live here.

APISignatureDescription
recoverySetThresholdsuspend fun recoverySetThreshold(threshold: Int): Boolean[network] Set how many methods are required to recover. Returns false if the chain rejected it (e.g. threshold > registered methods); local value unchanged then.
recoveryAddNfcsuspend fun recoveryAddNfc(nfcSerialNumber: ByteArray): Boolean[network] Register an NFC card as recovery method. true on success (increments nfcCount).
recoveryAddVcaTokensuspend fun recoveryAddVcaToken()[network] Generate a VCA token file and hand it to your InterstellarFileSharer (export/save/send). Increments vcaCount on success.
importRecoveryTokensuspend fun importRecoveryToken(encryptedVca: ByteArray): JniCircuitsPackageDecrypt an imported token file into a VCA package (restore flow). Throws on corrupt data.
prepareRecoveryVcaVouchfun prepareRecoveryVcaVouch(fileBytes: ByteArray)High-level restore: import the token file and arm the vouch pinpad in one call (navigateToPinpad=true when ready). A corrupt/undecryptable token only toasts ("Invalid recovery token") and resets pinpad state — it does not crash.
recoveryVouchVcasuspend fun recoveryVouchVca(jniCircuitsPackage: JniCircuitsPackage, inputs: ByteArray, onTxDone: () -> Unit)[network] Complete the VCA-token vouch (pinpad digits via TxPinpadView / processPinpadInputs internally).
recoveryVouchNfcsuspend fun recoveryVouchNfc(nfcSerialNumber: ByteArray): Boolean[network] Vouch with an NFC card. On success sets recoveryVouchSubmitted=true.
recoveryClaimsuspend fun recoveryClaim()[network] Claim the recovered account after the ~10-block delay. Clears cached accounts/root and zeroes balances until refresh.
Vouch → Claim flow

Recovering a lost account: the helping device (with its own or the imported token/NFC) vouches — recoveryVouchVca or recoveryVouchNfc — then the same device waits for the ~10-block delay (watch recoveryVouchSubmitted=true) and finally calls recoveryClaim().

Airdrop campaigns​

APISignatureDescription
getterCampaignssuspend fun getterCampaigns(): List<String>[network] All campaign ids.
getterCampaignInfosuspend fun getterCampaignInfo(campaignId: String): CampaignInfo?[network] Full campaign details (status, funding address, counts…).
getterUserCampaignssuspend fun getterUserCampaigns(): List<UserCampaign>[network] This account's campaign registrations/states.
extrinsicCreateCampaignsuspend fun extrinsicCreateCampaign(coinType: CoinType, amountPerClaim: Long, claimLimit: Int, freezePeriod: Int, registrationPeriod: Int, claimPeriod: Int)[network] Create a campaign (organizer flow). The funding address comes back in getterCampaignInfo.
extrinsicFundCampaignsuspend fun extrinsicFundCampaign(campaignId: String)[network] Fund & activate a campaign (after transferring funds to its funding address).
prepareAirdropRegistrationfun prepareAirdropRegistration(campaignId: String)[network] High-level: arm the registration VCA pinpad for a campaign (navigateToPinpad=true when ready).
prepareAirdropClaimfun prepareAirdropClaim(campaignId: String)[network] High-level: arm the claim VCA pinpad.
extrinsicPrepareRegistration / extrinsicCompleteRegistrationsuspend fun …(campaignId: String, inputIndices: ByteArray)Low-level 2-step registration (VCA #1 created, then validated by pinpad digits). Prefer prepareAirdropRegistration.
extrinsicPrepareClaim / extrinsicClaimAirdropsuspend fun …(campaignId: String, inputIndices: ByteArray, onTxDone: () -> Unit)Low-level 2-step claim (VCA #2 created, then validated). Prefer prepareAirdropClaim.
getterAirdropVcasuspend fun getterAirdropVca(campaignId: String): JniCircuitsPackage?Fetch the campaign's VCA package directly (used by the prepare… helpers).

On/off-ramp (MoonPay)​

APISignatureDescription
signMoonpayUrlsuspend fun signMoonpayUrl(queryString: String): String?[network] Server-signs a MoonPay query string so your app can build a trusted MoonPay URL.

Demo transaction (visual cryptography sandbox) — not part of the public API​

The SDK code still carries a createDemoTx / demoTxCheckInputs pair: it garbles a display circuits package for a free-form message so the VCA renderer can be exercised without a real transaction. These are internal sandbox helpers, not public API — they are not documented as a contract, they may change or disappear, and they are not covered by the parity promise with iOS. Do not build on them; use the real flows (prepareCoinTransfer, prepareAirdropRegistration, prepareAirdropClaim, prepareRecoveryVcaVouch) instead.

Thread-safety & threading guarantees​

  • Suspend functions hop to Dispatchers.IO; SDK-internal toasts are re-posted to the main thread.
  • StateFlows are safe to collect from the UI thread.
  • On iOS the equivalent published-state mutations are serialized on the main thread — see the iOS reference.

What is not public API​

The SDK module contains a few more classes; they are internal and are not part of the contract — do not use them (and do not expect them to exist in a future release):

SymbolWhat it is
processPinpadInputs(inputs)the SDK's internal pinpad entry point (it is called by TxPinpadView for you). ⚠️ it is public on iOS — an asymmetry, not a contract.
RustWrapperthe thin adapter over the uniffi-Kotlin bindings.
CurrencyMaththe internal currency helpers (the public entry points are convertToUsd, convertCoinToAtomic, getterClientGetBalanceInUsd, …).
MobileKeySigner / AndroidKeyStoreSigner / AndroidMobileSignerthe internal signing seam over the Android Keystore (it is injectable in the tests only).
PreferencesManager / KeysManagerthe internal persistence and key-management helpers.
updateWorkerEndpointForTest(wsUrl)test-only endpoint switch.

The public Rust surface is reachable through the same uniffi bindings, but the supported entry point is the InterstellarSdk API documented above.