Fix ~60 compile errors - build now succeeds

- Fixed DI imports: javax.inject -> dev.zacsweers.metro
- Fixed cardano-client-lib API: KoiosBackendService constructor, Amount.quantity type
- Added kotlin-parcelize plugin
- Workaround for Timeline.sendRaw(): use message prefix approach
- Fixed MnemonicCode wordlist access
- Fixed Compose lifecycle/context handling
- Updated test fakes

BUILD SUCCESSFUL - unit tests still need updating for new APIs
This commit is contained in:
Kayos 2026-03-27 13:30:14 -07:00
parent b12b1e4770
commit bd883e9c3a
19 changed files with 279 additions and 706 deletions

View file

@ -11,22 +11,22 @@ import com.bumble.appyx.core.node.Node
import io.element.android.features.wallet.api.WalletEntryPoint
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.tests.testutils.lambda.lambdaError
class FakeWalletEntryPoint : WalletEntryPoint {
class Builder : WalletEntryPoint.Builder {
override fun setRoomId(roomId: RoomId): Builder = this
override fun setRecipientUserId(userId: UserId?): Builder = this
override fun setRecipientAddress(address: String?): Builder = this
override fun setAmount(amount: String?): Builder = this
override fun build(): Node = lambdaError()
override fun setRoomId(roomId: RoomId): WalletEntryPoint.Builder = this
override fun setRecipientUserId(userId: UserId?): WalletEntryPoint.Builder = this
override fun setRecipientAddress(address: String?): WalletEntryPoint.Builder = this
override fun setAmount(amount: String?): WalletEntryPoint.Builder = this
override fun build(): Node {
throw NotImplementedError("FakeWalletEntryPoint cannot build a real node")
}
}
override fun paymentFlowBuilder(
parentNode: Node,
buildContext: BuildContext,
callback: WalletEntryPoint.Callback,
): WalletEntryPoint.Builder {
return Builder()
}
): WalletEntryPoint.Builder = Builder()
}

View file

@ -12,132 +12,99 @@ import io.element.android.libraries.matrix.api.core.SessionId
/**
* Fake implementation of [CardanoKeyStorage] for testing.
*
* Stores wallets in memory without encryption. NOT for production use.
*/
class FakeCardanoKeyStorage : CardanoKeyStorage {
private val wallets = mutableMapOf<String, WalletData>()
private val wallets = mutableMapOf<String, FakeWallet>()
var generateWalletError: Throwable? = null
var importWalletError: Throwable? = null
var getMnemonicError: Throwable? = null
var getAddressError: Throwable? = null
/**
* Test data for generated wallets.
*/
var testMnemonic: List<String> = listOf(
"abandon", "abandon", "abandon", "abandon", "abandon", "abandon",
"abandon", "abandon", "abandon", "abandon", "abandon", "abandon",
"abandon", "abandon", "abandon", "abandon", "abandon", "abandon",
"abandon", "abandon", "abandon", "abandon", "abandon", "art"
var generateWalletResult: Result<WalletCreationResult> = Result.success(
WalletCreationResult(
mnemonic = List(24) { "word$it" },
baseAddress = "addr_test1qpfake",
stakeAddress = "stake_test1upfake",
)
)
var importWalletResult: Result<String> = Result.success("addr_test1qpimported")
var getMnemonicResult: Result<List<String>>? = null
var getBaseAddressResult: Result<String>? = null
var getStakeAddressResult: Result<String>? = null
var deleteWalletResult: Result<Unit> = Result.success(Unit)
private data class WalletData(
val mnemonic: List<String>,
val baseAddress: String,
val stakeAddress: String,
)
var testBaseAddress: String = "addr_test1qp2fg770ddmqxxduasjsas8rgimrhknmqjn43mj74g7ta2tjt0n5nh4t5xqf6lp5mwfpksj9csjg9s4kgfhvwj7m7dcq9qf7zj"
var testStakeAddress: String = "stake_test1upehh7l0vv6ep8vr4n30pjdv6t2vpexs2h7xtpk8erzk06s25g8y3"
override suspend fun hasWallet(sessionId: SessionId): Boolean {
return wallets.containsKey(sessionId.value)
}
override suspend fun generateWallet(sessionId: SessionId): Result<WalletCreationResult> {
generateWalletError?.let { return Result.failure(it) }
if (wallets.containsKey(sessionId.value)) {
return Result.failure(IllegalStateException("Wallet already exists for session"))
}
val wallet = FakeWallet(
mnemonic = testMnemonic,
baseAddress = testBaseAddress,
stakeAddress = testStakeAddress,
)
wallets[sessionId.value] = wallet
return Result.success(
WalletCreationResult(
mnemonic = testMnemonic,
baseAddress = testBaseAddress,
stakeAddress = testStakeAddress,
return generateWalletResult.onSuccess { result ->
if (wallets.containsKey(sessionId.value)) {
return Result.failure(IllegalStateException("Wallet already exists"))
}
wallets[sessionId.value] = WalletData(
mnemonic = result.mnemonic,
baseAddress = result.baseAddress,
stakeAddress = result.stakeAddress,
)
)
}
}
override suspend fun importWallet(sessionId: SessionId, mnemonic: List<String>): Result<String> {
importWalletError?.let { return Result.failure(it) }
if (wallets.containsKey(sessionId.value)) {
return Result.failure(IllegalStateException("Wallet already exists for session"))
return importWalletResult.onSuccess { address ->
if (wallets.containsKey(sessionId.value)) {
return Result.failure(IllegalStateException("Wallet already exists"))
}
wallets[sessionId.value] = WalletData(
mnemonic = mnemonic,
baseAddress = address,
stakeAddress = "stake_test1upimported",
)
}
val wallet = FakeWallet(
mnemonic = mnemonic,
baseAddress = testBaseAddress,
stakeAddress = testStakeAddress,
)
wallets[sessionId.value] = wallet
return Result.success(testBaseAddress)
}
override suspend fun getMnemonic(sessionId: SessionId): Result<List<String>> {
getMnemonicError?.let { return Result.failure(it) }
getMnemonicResult?.let { return it }
val wallet = wallets[sessionId.value]
?: return Result.failure(IllegalStateException("No wallet found for session"))
?: return Result.failure(IllegalStateException("No wallet"))
return Result.success(wallet.mnemonic)
}
override suspend fun getBaseAddress(sessionId: SessionId, addressIndex: Int): Result<String> {
getAddressError?.let { return Result.failure(it) }
getBaseAddressResult?.let { return it }
val wallet = wallets[sessionId.value]
?: return Result.failure(IllegalStateException("No wallet found for session"))
// For testing, just append the index to the address if non-zero
val address = if (addressIndex == 0) {
wallet.baseAddress
} else {
"${wallet.baseAddress}_$addressIndex"
}
return Result.success(address)
?: return Result.failure(IllegalStateException("No wallet"))
return Result.success(wallet.baseAddress)
}
override suspend fun getStakeAddress(sessionId: SessionId): Result<String> {
getAddressError?.let { return Result.failure(it) }
getStakeAddressResult?.let { return it }
val wallet = wallets[sessionId.value]
?: return Result.failure(IllegalStateException("No wallet found for session"))
?: return Result.failure(IllegalStateException("No wallet"))
return Result.success(wallet.stakeAddress)
}
override suspend fun deleteWallet(sessionId: SessionId): Result<Unit> {
wallets.remove(sessionId.value)
return Result.success(Unit)
return deleteWalletResult
}
/**
* Clears all stored wallets. Use in test teardown.
*/
fun clear() {
fun reset() {
wallets.clear()
generateWalletError = null
importWalletError = null
getMnemonicError = null
getAddressError = null
generateWalletResult = Result.success(
WalletCreationResult(
mnemonic = List(24) { "word$it" },
baseAddress = "addr_test1qpfake",
stakeAddress = "stake_test1upfake",
)
)
importWalletResult = Result.success("addr_test1qpimported")
getMnemonicResult = null
getBaseAddressResult = null
getStakeAddressResult = null
deleteWalletResult = Result.success(Unit)
}
/**
* Returns the number of stored wallets.
*/
fun walletCount(): Int = wallets.size
private data class FakeWallet(
val mnemonic: List<String>,
val baseAddress: String,
val stakeAddress: String,
)
}