Skip to content

Commit

Permalink
PERA-1015 :: Create common module and move local account domain layer (
Browse files Browse the repository at this point in the history
  • Loading branch information
mitsinsar authored Oct 25, 2024
1 parent 993f0b2 commit 121e520
Show file tree
Hide file tree
Showing 32 changed files with 1,235 additions and 1 deletion.
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ android {
}

dependencies {

implementation project(':wallet-sdk')
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${libVersions.coroutines}"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${libVersions.coroutines}"
Expand Down
13 changes: 13 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
[versions]
algosdk = "2.5.0"
coreKtx = "1.13.1"
junit = "4.13.2"
kotlinfixture = "1.2.0"
mockk = "1.13.13"
coroutines = "1.9.0"
kotlinTest = "1.5.31"

[libraries]
algosdk = { module = "com.algorand:algosdk", version.ref = "algosdk" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" }
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
junit = { module = "junit:junit", version.ref = "junit" }
kotlinfixture = { module = "com.appmattus.fixture:fixture", version.ref = "kotlinfixture" }
mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlinTest" }

[bundles]

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)
}
68 changes: 68 additions & 0 deletions wallet-sdk/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* 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
*/

plugins {
id("org.jetbrains.kotlin.multiplatform")
id("com.android.library")
}

apply(from = "../versions.gradle")

val targets = extra["targets"] as Map<*, *>

kotlin {
androidTarget {
compilations.all {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
}
}
}

// listOf(
// iosX64(),
// iosArm64(),
// iosSimulatorArm64()
// ).forEach {
// it.binaries.framework {
// baseName = "common"
// isStatic = true
// }
// }

sourceSets {
androidMain.dependencies {
implementation(libs.kotlinfixture)
}
commonMain.dependencies {
implementation(libs.kotlinx.coroutines.core)
}
commonTest.dependencies {
implementation(project(":test-utils"))
implementation(libs.kotlin.test)
implementation(libs.kotlinx.coroutines.test)
implementation(libs.mockk)
}
}
}

android {
namespace = "com.algorand.common"
compileSdk = targets["compileSdkVersion"] as Int
defaultConfig {
minSdk = targets["minSdkVersion"] as Int
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}
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()
}
Loading

0 comments on commit 121e520

Please sign in to comment.