Skip to content

Commit

Permalink
Revert "PERA-1046 :: Revert KMP Module PR causing CI error (#16)"
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeltchuang committed Oct 30, 2024
1 parent 3d21427 commit fa56836
Show file tree
Hide file tree
Showing 31 changed files with 1,158 additions and 5 deletions.
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ android {
}

dependencies {

implementation project(':wallet-sdk')
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation libs.kotlinx.coroutines.core
implementation libs.kotlinx.coroutines.android
Expand Down
4 changes: 3 additions & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
include(":app")
rootProject.name = "algorand-android"
include(":app")
include(":wallet-sdk")
include(":test-utils")
1 change: 1 addition & 0 deletions test-utils/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
14 changes: 14 additions & 0 deletions test-utils/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
plugins {
id("java-library")
id("org.jetbrains.kotlin.jvm")
}

java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

dependencies {
implementation(libs.kotlin.test)
implementation(libs.kotlinx.coroutines.test)
}
82 changes: 82 additions & 0 deletions test-utils/src/main/kotlin/com/algorand/test/TestObserver.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright 2022 Pera Wallet, LDA
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

package com.algorand.test

import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.test.UnconfinedTestDispatcher

class TestObserver<T>(private val flow: Flow<T>, coroutineScope: CoroutineScope) {
private val emittedValues = mutableListOf<T>()
private var flowError: Throwable? = null
private val job: Job = flow.onEach {
emittedValues.add(it)
}.catch {
flowError = it
}.launchIn(coroutineScope)

fun assertError() {
assertNotNull(flowError)
}

fun assertError(throwable: Throwable) {
assertEquals(flowError, throwable)
}

fun assertNoValue() {
assertTrue(emittedValues.isEmpty())
}

fun assertValue(value: T) {
assertTrue(emittedValues.isNotEmpty())
assertEquals(value, emittedValues.last())
}

fun assertValueHistory(vararg values: T) {
assertSize(values.size)
assertSequence(values.toList())
}

fun assertSize(size: Int) {
assertEquals(size, emittedValues.size)
}

fun getValues() = emittedValues

fun stopObserving() {
job.cancel()
}

fun getFlow() = flow

fun value(): T = getValues().last()

private fun assertSequence(values: List<T>) {
for ((index, v) in values.withIndex()) {
assertEquals(v, emittedValues[index])
}
}
}

@OptIn(ExperimentalCoroutinesApi::class)
fun <T> Flow<T>.test(coroutineScope: CoroutineScope = CoroutineScope(UnconfinedTestDispatcher())): TestObserver<T> {
return TestObserver(this, coroutineScope)
}
8 changes: 4 additions & 4 deletions wallet-sdk/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion

/*
* Copyright 2022 Pera Wallet, LDA
* Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -14,6 +10,10 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
* limitations under the License
*/

import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion

plugins {
alias(libs.plugins.multiplatform)
id("com.android.library")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2022 Pera Wallet, LDA
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

package com.algorand.common.testing

import com.appmattus.kotlinfixture.kotlinFixture

class PeraFixture(private val listItemSize: Int) {

val fixture = kotlinFixture {
repeatCount { listItemSize }
}

inline operator fun <reified T : Any?> invoke(): T {
return fixture()
}
}

actual inline fun <reified T : Any?> peraFixture(listItemSize: Int): T = PeraFixture(listItemSize).fixture()
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2022 Pera Wallet, LDA
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

package com.algorand.common.account.local.model

sealed interface LocalAccount {

val address: String

data class Algo25(
override val address: String,
val secretKey: ByteArray
) : LocalAccount {

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false

other as Algo25

if (address != other.address) return false
if (!secretKey.contentEquals(other.secretKey)) return false

return true
}

override fun hashCode(): Int {
var result = address.hashCode()
result = 31 * result + secretKey.contentHashCode()
return result
}
}

data class LedgerBle(
override val address: String,
val deviceMacAddress: String,
val indexInLedger: Int
) : LocalAccount

data class NoAuth(
override val address: String
) : LocalAccount
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2022 Pera Wallet, LDA
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

package com.algorand.common.account.local.repository

import com.algorand.common.account.local.model.LocalAccount
import kotlinx.coroutines.flow.Flow

internal interface Algo25AccountRepository {

fun getAllAsFlow(): Flow<List<LocalAccount.Algo25>>

fun getAccountCountAsFlow(): Flow<Int>

suspend fun getAll(): List<LocalAccount.Algo25>

suspend fun getAccount(address: String): LocalAccount.Algo25?

suspend fun addAccount(account: LocalAccount.Algo25)

suspend fun deleteAccount(address: String)

suspend fun deleteAllAccounts()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2022 Pera Wallet, LDA
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

package com.algorand.common.account.local.repository

import com.algorand.common.account.local.model.LocalAccount
import kotlinx.coroutines.flow.Flow

internal interface LedgerBleAccountRepository {

fun getAllAsFlow(): Flow<List<LocalAccount.LedgerBle>>

fun getAccountCountAsFlow(): Flow<Int>

suspend fun getAll(): List<LocalAccount.LedgerBle>

suspend fun getAccount(address: String): LocalAccount.LedgerBle?

suspend fun addAccount(account: LocalAccount.LedgerBle)

suspend fun deleteAccount(address: String)

suspend fun deleteAllAccounts()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2022 Pera Wallet, LDA
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

package com.algorand.common.account.local.repository

import com.algorand.common.account.local.model.LocalAccount
import kotlinx.coroutines.flow.Flow

internal interface NoAuthAccountRepository {

fun getAllAsFlow(): Flow<List<LocalAccount.NoAuth>>

fun getAccountCountAsFlow(): Flow<Int>

suspend fun getAll(): List<LocalAccount.NoAuth>

suspend fun getAccount(address: String): LocalAccount.NoAuth?

suspend fun addAccount(account: LocalAccount.NoAuth)

suspend fun deleteAccount(address: String)

suspend fun deleteAllAccounts()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2022 Pera Wallet, LDA
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

package com.algorand.common.account.local.usecase

import com.algorand.common.account.local.repository.Algo25AccountRepository
import com.algorand.common.account.local.repository.LedgerBleAccountRepository
import com.algorand.common.account.local.repository.NoAuthAccountRepository

internal class DeleteLocalAccountUseCase(
private val algo25AccountRepository: Algo25AccountRepository,
private val noAuthAccountRepository: NoAuthAccountRepository,
private val ledgerBleAccountRepository: LedgerBleAccountRepository
) : DeleteLocalAccount {

override suspend fun invoke(address: String) {
algo25AccountRepository.deleteAccount(address)
noAuthAccountRepository.deleteAccount(address)
ledgerBleAccountRepository.deleteAccount(address)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2022 Pera Wallet, LDA
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

package com.algorand.common.account.local.usecase

import com.algorand.common.account.local.repository.Algo25AccountRepository
import com.algorand.common.account.local.repository.LedgerBleAccountRepository
import com.algorand.common.account.local.repository.NoAuthAccountRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine

internal class GetAllLocalAccountAddressesAsFlowUseCase(
private val algo25AccountRepository: Algo25AccountRepository,
private val ledgerBleAccountRepository: LedgerBleAccountRepository,
private val noAuthAccountRepository: NoAuthAccountRepository
) : GetAllLocalAccountAddressesAsFlow {

override fun invoke(): Flow<List<String>> {
return combine(
algo25AccountRepository.getAllAsFlow(),
ledgerBleAccountRepository.getAllAsFlow(),
noAuthAccountRepository.getAllAsFlow()
) { algo25Accounts, ledgerBleAccounts, noAuthAccounts ->
buildList {
addAll(algo25Accounts.map { it.address })
addAll(ledgerBleAccounts.map { it.address })
addAll(noAuthAccounts.map { it.address })
}
}
}
}
Loading

0 comments on commit fa56836

Please sign in to comment.