docs: update BLOCKERS.md with Task 3 completion status

This commit is contained in:
Kayos 2026-03-27 10:39:53 -07:00
parent db4c262b27
commit 19637833a6
8 changed files with 1230 additions and 75 deletions

View file

@ -0,0 +1,94 @@
/*
* Copyright (c) 2026 Sulkta Coop.
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
package io.element.android.features.wallet.api.storage
import io.element.android.libraries.matrix.api.core.SessionId
/**
* Result of wallet creation containing the generated seed phrase and derived addresses.
*/
data class WalletCreationResult(
val mnemonic: List<String>,
val baseAddress: String,
val stakeAddress: String,
)
/**
* Interface for secure storage and retrieval of Cardano wallet keys.
*
* Wallets are scoped PER SESSION (per Matrix account). Each [SessionId] can have
* exactly one wallet associated with it.
*
* ## Security Properties
* - Keys are stored encrypted using Android Keystore
* - Biometric/PIN authentication required for every signing operation
* - Keys are INVALIDATED if biometric enrollment changes
* - Mnemonic is stored encrypted, never in plaintext
*
* ## Implementation Notes
* - Use `setInvalidatedByBiometricEnrollment(true)` for Keystore keys
* - Use `setUserAuthenticationRequired(true)` with duration -1 (every time)
* - Key alias format: "cardano_wallet_{sessionId}"
*/
interface CardanoKeyStorage {
/**
* Checks if a wallet exists for the given session.
*/
suspend fun hasWallet(sessionId: SessionId): Boolean
/**
* Generates a new wallet with a 24-word BIP-39 mnemonic.
*
* @param sessionId The Matrix session to create the wallet for
* @return [WalletCreationResult] containing the mnemonic and derived addresses
* @throws IllegalStateException if a wallet already exists for this session
*/
suspend fun generateWallet(sessionId: SessionId): Result<WalletCreationResult>
/**
* Imports an existing wallet from a mnemonic phrase.
*
* @param sessionId The Matrix session to import the wallet for
* @param mnemonic The BIP-39 mnemonic phrase (12, 15, 18, 21, or 24 words)
* @return The derived base address on success
* @throws IllegalArgumentException if the mnemonic is invalid
* @throws IllegalStateException if a wallet already exists for this session
*/
suspend fun importWallet(sessionId: SessionId, mnemonic: List<String>): Result<String>
/**
* Retrieves the encrypted mnemonic for backup display.
*
* WARNING: This returns sensitive data. UI must use FLAG_SECURE.
*
* @param sessionId The Matrix session
* @return The mnemonic word list
*/
suspend fun getMnemonic(sessionId: SessionId): Result<List<String>>
/**
* Gets the base address (payment + staking key hash) for the wallet.
*
* @param sessionId The Matrix session
* @param addressIndex The address index (default 0)
*/
suspend fun getBaseAddress(sessionId: SessionId, addressIndex: Int = 0): Result<String>
/**
* Gets the staking/reward address for the wallet.
*
* @param sessionId The Matrix session
*/
suspend fun getStakeAddress(sessionId: SessionId): Result<String>
/**
* Permanently deletes the wallet and all associated key material.
*
* @param sessionId The Matrix session
*/
suspend fun deleteWallet(sessionId: SessionId): Result<Unit>
}