diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..0f64ec15d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,6 @@ +root = true + +[*.{kt,kts}] +ktlint_standard_no_semi = disabled +ktlint_standard_trailing-comma-on-call-site = disabled +ktlint_standard_trailing-comma-on-declaration-site = disabled diff --git a/.mega-linter.yml b/.mega-linter.yml index 38ccdafab..df9d97879 100644 --- a/.mega-linter.yml +++ b/.mega-linter.yml @@ -2,6 +2,7 @@ APPLY_FIXES: none FILTER_REGEX_EXCLUDE: (karma.config.js|polyfill.js|timeout.js) VALIDATE_ALL_CODEBASE: true REPOSITORY_DEVSKIM_DISABLE_ERRORS: true +REPOSITORY_CHECKOV_DISABLE_ERRORS: true DISABLE_LINTERS: - MARKDOWN_MARKDOWN_LINK_CHECK @@ -9,3 +10,7 @@ DISABLE_LINTERS: - CPP_CPPLINT - BASH_SHELLCHECK - BASH_EXEC + - REPOSITORY_CHECKOV + +DISABLE_ERRORS_LINTERS: + - REPOSITORY_CHECKOV diff --git a/domain/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.domain/buildingBlocks/Pluto.kt b/domain/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.domain/buildingBlocks/Pluto.kt index e0e9747ef..1aa6db125 100644 --- a/domain/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.domain/buildingBlocks/Pluto.kt +++ b/domain/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.domain/buildingBlocks/Pluto.kt @@ -8,27 +8,27 @@ import io.iohk.atala.prism.walletsdk.domain.models.PeerDID import io.iohk.atala.prism.walletsdk.domain.models.PrismDIDInfo import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.VerifiableCredential +import kotlinx.coroutines.flow.Flow import kotlin.js.ExperimentalJsExport -import kotlin.js.JsExport import kotlin.js.JsName @OptIn(ExperimentalJsExport::class) -@JsExport interface Pluto { - fun storePrismDID( + fun storePrismDIDAndPrivateKeys( did: DID, keyPathIndex: Int, alias: String?, + privateKeys: List, ) - fun storePeerDID(did: DID, privateKeys: Array) + fun storePeerDIDAndPrivateKeys(did: DID, privateKeys: List) fun storeDIDPair(host: DID, receiver: DID, name: String) fun storeMessage(message: Message) - fun storeMessages(messages: Array) + fun storeMessages(messages: List) fun storePrivateKeys(privateKey: PrivateKey, did: DID, keyPathIndex: Int, metaId: String? = null) @@ -36,50 +36,50 @@ interface Pluto { fun storeCredential(credential: VerifiableCredential) - fun getAllPrismDIDs(): Array + fun getAllPrismDIDs(): Flow> - fun getDIDInfoByDID(did: DID): PrismDIDInfo? + fun getDIDInfoByDID(did: DID): Flow - fun getDIDInfoByAlias(alias: String): Array + fun getDIDInfoByAlias(alias: String): Flow> - fun getPrismDIDKeyPathIndex(did: DID): Int? + fun getPrismDIDKeyPathIndex(did: DID): Flow - fun getPrismLastKeyPathIndex(): Int + fun getPrismLastKeyPathIndex(): Flow - fun getAllPeerDIDs(): Array + fun getAllPeerDIDs(): Flow> - fun getDIDPrivateKeysByDID(did: DID): Array? + fun getDIDPrivateKeysByDID(did: DID): Flow> - fun getDIDPrivateKeyByID(id: String): PrivateKey? + fun getDIDPrivateKeyByID(id: String): Flow - fun getAllDidPairs(): Array + fun getAllDidPairs(): Flow> - fun getPairByDID(did: DID): DIDPair? + fun getPairByDID(did: DID): Flow - fun getPairByName(name: String): DIDPair? + fun getPairByName(name: String): Flow @JsName("getAllMessages") - fun getAllMessages(): Array + fun getAllMessages(): Flow> @JsName("getAllMessagesByDID") - fun getAllMessages(did: DID): Array + fun getAllMessages(did: DID): Flow> - fun getAllMessagesSent(): Array + fun getAllMessagesSent(): Flow> - fun getAllMessagesReceived(): Array + fun getAllMessagesReceived(): Flow> - fun getAllMessagesSentTo(did: DID): Array + fun getAllMessagesSentTo(did: DID): Flow> - fun getAllMessagesReceivedFrom(did: DID): Array + fun getAllMessagesReceivedFrom(did: DID): Flow> - fun getAllMessagesOfType(type: String, relatedWithDID: DID?): Array + fun getAllMessagesOfType(type: String, relatedWithDID: DID?): Flow> @JsName("getAllMessagesByFromToDID") - fun getAllMessages(from: DID, to: DID): Array + fun getAllMessages(from: DID, to: DID): Flow> - fun getMessage(id: String): Message? + fun getMessage(id: String): Flow - fun getAllMediators(): Array + fun getAllMediators(): Flow> - fun getAllCredentials(): Array + fun getAllCredentials(): Flow> } diff --git a/mercury/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.mercury/resolvers/DefaultSecretsResolverImpl.kt b/mercury/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.mercury/resolvers/DefaultSecretsResolverImpl.kt index 339ef925a..b255dfb58 100644 --- a/mercury/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.mercury/resolvers/DefaultSecretsResolverImpl.kt +++ b/mercury/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.mercury/resolvers/DefaultSecretsResolverImpl.kt @@ -5,12 +5,11 @@ import io.iohk.atala.prism.walletsdk.domain.buildingBlocks.Pluto import io.iohk.atala.prism.walletsdk.domain.models.Secret import io.iohk.atala.prism.walletsdk.domain.models.SecretMaterialJWK import io.iohk.atala.prism.walletsdk.domain.models.SecretType +import kotlinx.coroutines.flow.firstOrNull import kotlinx.serialization.Serializable import kotlin.js.ExperimentalJsExport -import kotlin.js.JsExport @OptIn(ExperimentalJsExport::class) -@JsExport class DefaultSecretsResolverImpl(val pluto: Pluto) : SecretsResolver { @Serializable @@ -21,25 +20,28 @@ class DefaultSecretsResolverImpl(val pluto: Pluto) : SecretsResolver { val d: String? = null, ) - override fun findSecrets(secretIds: Array): Array { + override suspend fun findSecrets(secretIds: Array): Array { return secretIds.filter { - pluto.getDIDPrivateKeyByID(it) != null + pluto.getDIDPrivateKeyByID(it) + .firstOrNull() != null }.toTypedArray() } - override fun getSecret(secretid: String): Secret? { - return pluto.getDIDPrivateKeyByID(secretid)?.let { - Secret( - secretid, - SecretType.JsonWebKey2020, - SecretMaterialJWK( - PrivateJWK( - secretid, - it.keyCurve.curve.toString(), - it.value.base64UrlEncoded, - ).toString(), - ), - ) - } + override suspend fun getSecret(secretid: String): Secret? { + return pluto.getDIDPrivateKeyByID(secretid) + .firstOrNull() + ?.let { privateKey -> + return Secret( + secretid, + SecretType.JsonWebKey2020, + SecretMaterialJWK( + PrivateJWK( + secretid, + privateKey.keyCurve.curve.toString(), + privateKey.value.base64UrlEncoded, + ).toString(), + ), + ) + } } } diff --git a/mercury/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.mercury/resolvers/SecretsResolver.kt b/mercury/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.mercury/resolvers/SecretsResolver.kt index f5425ed4a..fc6ca6e95 100644 --- a/mercury/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.mercury/resolvers/SecretsResolver.kt +++ b/mercury/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.mercury/resolvers/SecretsResolver.kt @@ -2,11 +2,9 @@ package io.iohk.atala.prism.walletsdk.mercury.resolvers import io.iohk.atala.prism.walletsdk.domain.models.Secret import kotlin.js.ExperimentalJsExport -import kotlin.js.JsExport @OptIn(ExperimentalJsExport::class) -@JsExport interface SecretsResolver { - fun findSecrets(secretIds: Array): Array - fun getSecret(secretId: String): Secret? + suspend fun findSecrets(secretIds: Array): Array + suspend fun getSecret(secretId: String): Secret? } diff --git a/pluto/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.pluto/PlutoImpl.kt b/pluto/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.pluto/PlutoImpl.kt index 865e341dd..dd0801bb4 100644 --- a/pluto/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.pluto/PlutoImpl.kt +++ b/pluto/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.pluto/PlutoImpl.kt @@ -1,5 +1,7 @@ package io.iohk.atala.prism.walletsdk.pluto +import com.squareup.sqldelight.runtime.coroutines.asFlow +import com.squareup.sqldelight.runtime.coroutines.mapToList import io.iohk.atala.prism.apollo.uuid.UUID import io.iohk.atala.prism.walletsdk.domain.buildingBlocks.Pluto import io.iohk.atala.prism.walletsdk.domain.models.CredentialType @@ -17,6 +19,10 @@ import io.iohk.atala.prism.walletsdk.domain.models.W3CVerifiableCredential import io.iohk.atala.prism.walletsdk.domain.models.getKeyCurveByNameAndIndex import io.iohk.atala.prism.walletsdk.pluto.data.DbConnection import io.iohk.atala.prism.walletsdk.pluto.data.isConnected +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.mapLatest import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import ioiohkatalaprismwalletsdkpluto.data.DID as DIDDB @@ -51,22 +57,22 @@ class PlutoImpl(private val connection: DbConnection) : Pluto { return this.db ?: throw PlutoError.DatabaseConnectionError() } - override fun storePrismDID(did: DID, keyPathIndex: Int, alias: String?) { - getInstance().dIDQueries.insert(DIDDB(did.toString(), did.method, did.methodId, did.schema, alias)) + override fun storePrismDIDAndPrivateKeys( + did: DID, + keyPathIndex: Int, + alias: String?, + privateKeys: List, + ) { + getInstance().dIDQueries.insert(DIDDB(did.methodId, did.method, did.methodId, did.schema, alias)) + privateKeys.map { privateKey -> + storePrivateKeys(privateKey, did, keyPathIndex) + } } - override fun storePeerDID(did: DID, privateKeys: Array) { - getInstance().dIDQueries.insert(DIDDB(did.toString(), did.method, did.methodId, did.schema, null)) + override fun storePeerDIDAndPrivateKeys(did: DID, privateKeys: List) { + getInstance().dIDQueries.insert(DIDDB(did.methodId, did.method, did.methodId, did.schema, null)) privateKeys.map { privateKey -> - getInstance().privateKeyQueries.insert( - PrivateKeyDB( - UUID.randomUUID4().toString(), - privateKey.keyCurve.curve.value, - privateKey.value.toString(), - privateKey.keyCurve.index, - did.methodId, - ), - ) + storePrivateKeys(privateKey, did, privateKey.keyCurve.index ?: 0) } } @@ -96,12 +102,12 @@ class PlutoImpl(private val connection: DbConnection) : Pluto { privateKey.keyCurve.curve.value, privateKey.value.toString(), keyPathIndex, - did.methodId, + did.toString(), ), ) } - override fun storeMessages(messages: Array) { + override fun storeMessages(messages: List) { messages.map { message -> storeMessage(message) } @@ -131,418 +137,466 @@ class PlutoImpl(private val connection: DbConnection) : Pluto { ) } - override fun getAllPrismDIDs(): Array { + override fun getAllPrismDIDs(): Flow> { return getInstance().dIDQueries .fetchAllPrismDID() - .executeAsList() - .map { - PrismDIDInfo(DID(it.did), it.keyPathIndex, it.alias) - }.toTypedArray() + .asFlow() + .mapToList() + .map { list -> + list.map { + PrismDIDInfo(DID(it.did), it.keyPathIndex, it.alias) + } + } } - override fun getDIDInfoByDID(did: DID): PrismDIDInfo? { - val didInfo = try { - getInstance().dIDQueries - .fetchDIDInfoByDID(did.toString()) - .executeAsOne() - } catch (e: NullPointerException) { - null - } ?: return null - - return PrismDIDInfo(DID(didInfo.did), didInfo.keyPathIndex, didInfo.alias) + @OptIn(ExperimentalCoroutinesApi::class) + override fun getDIDInfoByDID(did: DID): Flow { + return getInstance().dIDQueries + .fetchDIDInfoByDID(did.methodId) + .asFlow() + .mapLatest { + try { + val didInfo = it.executeAsOne() + PrismDIDInfo(DID(didInfo.did), didInfo.keyPathIndex, didInfo.alias) + } catch (e: NullPointerException) { + null + } + } } - override fun getDIDInfoByAlias(alias: String): Array { + override fun getDIDInfoByAlias(alias: String): Flow> { return getInstance().dIDQueries .fetchDIDInfoByAlias(alias) - .executeAsList() - .map { PrismDIDInfo(DID(it.did), it.keyPathIndex, it.alias) } - .toTypedArray() - } - - override fun getDIDPrivateKeysByDID(did: DID): Array? { - val privateKeys = try { - getInstance().privateKeyQueries - .fetchPrivateKeyByDID(did.toString()) - .executeAsList() - } catch (e: IllegalStateException) { - null - } ?: return null - - return privateKeys.map { - PrivateKey( - getKeyCurveByNameAndIndex( - it.curve, - it.keyPathIndex, - ), - byteArrayOf(), - ) - } - .toTypedArray() - } - - override fun getDIDPrivateKeyByID(id: String): PrivateKey? { - val privateKeys = try { - getInstance().privateKeyQueries - .fetchPrivateKeyByID(id) - .executeAsList() - } catch (e: IllegalStateException) { - null - } ?: return null - - return privateKeys.firstOrNull()?.let { - PrivateKey( - getKeyCurveByNameAndIndex( - it.curve, - it.keyPathIndex, - ), - byteArrayOf(), - ) - } + .asFlow() + .map { + it.executeAsList() + .map { didInfo -> + PrismDIDInfo(DID(didInfo.did), didInfo.keyPathIndex, didInfo.alias) + } + } } - override fun getPrismDIDKeyPathIndex(did: DID): Int? { - val did = try { - getInstance().privateKeyQueries.fetchKeyPathIndexByDID(did.methodId) - .executeAsOne() - } catch (e: NullPointerException) { - null - } ?: return null + override fun getDIDPrivateKeysByDID(did: DID): Flow> { + return getInstance().privateKeyQueries + .fetchPrivateKeyByDID(did.toString()) + .asFlow() + .map { + it.executeAsList() + .map { didInfo -> + try { + PrivateKey( + getKeyCurveByNameAndIndex( + didInfo.curve, + didInfo.keyPathIndex, + ), + byteArrayOf(), + ) + } catch (e: IllegalStateException) { + null + } + } + } + } - return did.keyPathIndex + override fun getDIDPrivateKeyByID(id: String): Flow { + return getInstance().privateKeyQueries + .fetchPrivateKeyByID(id) + .asFlow() + .map { + it.executeAsList().firstOrNull()?.let { + try { + PrivateKey( + getKeyCurveByNameAndIndex( + it.curve, + it.keyPathIndex, + ), + byteArrayOf(), + ) + } catch (e: IllegalStateException) { + null + } + } + } } - override fun getPrismLastKeyPathIndex(): Int { + override fun getPrismDIDKeyPathIndex(did: DID): Flow { + return getInstance().privateKeyQueries.fetchKeyPathIndexByDID(did.methodId) + .asFlow() + .map { + try { + it.executeAsOne().keyPathIndex + } catch (e: NullPointerException) { + null + } + } + } + + override fun getPrismLastKeyPathIndex(): Flow { return getInstance().privateKeyQueries.fetchLastkeyPathIndex() - .executeAsOne() - .keyPathIndex ?: 0 + .asFlow() + .map { + it.executeAsOne().keyPathIndex ?: 0 + } } - override fun getAllPeerDIDs(): Array { + override fun getAllPeerDIDs(): Flow> { return getInstance().dIDQueries.fetchAllPeerDID() - .executeAsList() - .groupBy { it.did } - .map { - val privateKeyList = it.value.map { data -> - PrivateKey( - getKeyCurveByNameAndIndex(data.curve, data.keyPathIndex), - byteArrayOf(), - ) - }.toTypedArray() - PeerDID(DID(it.key), privateKeyList) - }.toTypedArray() + .asFlow() + .map { allDIDs -> + allDIDs.executeAsList() + .groupBy { allPeerDid -> allPeerDid.did } + .map { + val privateKeyList = it.value.map { data -> + PrivateKey( + getKeyCurveByNameAndIndex(data.curve, data.keyPathIndex), + byteArrayOf(), + ) + }.toTypedArray() + PeerDID(DID(it.key), privateKeyList) + } + } } - override fun getAllDidPairs(): Array { + override fun getAllDidPairs(): Flow> { return getInstance().dIDPairQueries.fetchAllDIDPairs() - .executeAsList() - .map { DIDPair(DID(it.hostDID), DID(it.receiverDID), it.name) } - .toTypedArray() + .asFlow() + .map { didPair -> + didPair.executeAsList() + .map { DIDPair(DID(it.hostDID), DID(it.receiverDID), it.name) } + } } - override fun getPairByDID(did: DID): DIDPair? { - val didPair = try { - getInstance().dIDPairQueries.fetchDIDPairByDID(did.toString()) - .executeAsOne() - } catch (e: NullPointerException) { - null - } ?: return null - - return DIDPair(DID(didPair.hostDID), DID(didPair.receiverDID), didPair.name) + override fun getPairByDID(did: DID): Flow { + return getInstance().dIDPairQueries.fetchDIDPairByDID(did.toString()) + .asFlow() + .map { + try { + val didPair = it.executeAsOne() + DIDPair(DID(didPair.hostDID), DID(didPair.receiverDID), didPair.name) + } catch (e: NullPointerException) { + null + } + } } - override fun getPairByName(name: String): DIDPair? { - val didPair = try { - getInstance().dIDPairQueries.fetchDIDPairByName(name) - .executeAsOne() - } catch (e: NullPointerException) { - null - } ?: return null - - return DIDPair(DID(didPair.hostDID), DID(didPair.receiverDID), didPair.name) + override fun getPairByName(name: String): Flow { + return getInstance().dIDPairQueries.fetchDIDPairByName(name) + .asFlow() + .map { + try { + val didPair = it.executeAsOne() + DIDPair(DID(didPair.hostDID), DID(didPair.receiverDID), didPair.name) + } catch (e: NullPointerException) { + null + } + } } - override fun getAllMessages(): Array { + override fun getAllMessages(): Flow> { return getInstance().messageQueries.fetchAllMessages() - .executeAsList() + .asFlow() .map { - val messageDb = Json.decodeFromString(it.dataJson) - Message( - messageDb.id, - messageDb.piuri, - messageDb.from, - messageDb.to, - messageDb.fromPrior, - messageDb.body, - messageDb.extraHeaders, - messageDb.createdTime, - messageDb.expiresTimePlus, - messageDb.attachments, - messageDb.thid, - messageDb.pthid, - messageDb.ack, - messageDb.direction, - ) - }.toTypedArray() - } - - override fun getAllMessages(did: DID): Array { + it.executeAsList().map { message -> + val messageDb = Json.decodeFromString(message.dataJson) + Message( + messageDb.id, + messageDb.piuri, + messageDb.from, + messageDb.to, + messageDb.fromPrior, + messageDb.body, + messageDb.extraHeaders, + messageDb.createdTime, + messageDb.expiresTimePlus, + messageDb.attachments, + messageDb.thid, + messageDb.pthid, + messageDb.ack, + messageDb.direction, + ) + } + } + } + + override fun getAllMessages(did: DID): Flow> { return getAllMessages(did, did) } - override fun getAllMessages(from: DID, to: DID): Array { + override fun getAllMessages(from: DID, to: DID): Flow> { return getInstance().messageQueries.fetchAllMessagesFromTo(from.toString(), to.toString()) - .executeAsList() + .asFlow() .map { - val messageDb = Json.decodeFromString(it.dataJson) - Message( - messageDb.id, - messageDb.piuri, - messageDb.from, - messageDb.to, - messageDb.fromPrior, - messageDb.body, - messageDb.extraHeaders, - messageDb.createdTime, - messageDb.expiresTimePlus, - messageDb.attachments, - messageDb.thid, - messageDb.pthid, - messageDb.ack, - messageDb.direction, - ) - }.toTypedArray() - } - - override fun getAllMessagesSent(): Array { + it.executeAsList().map { message -> + val messageDb = Json.decodeFromString(message.dataJson) + Message( + messageDb.id, + messageDb.piuri, + messageDb.from, + messageDb.to, + messageDb.fromPrior, + messageDb.body, + messageDb.extraHeaders, + messageDb.createdTime, + messageDb.expiresTimePlus, + messageDb.attachments, + messageDb.thid, + messageDb.pthid, + messageDb.ack, + messageDb.direction, + ) + } + } + } + + override fun getAllMessagesSent(): Flow> { return getInstance().messageQueries.fetchAllSentMessages() - .executeAsList() + .asFlow() .map { - val messageDb = Json.decodeFromString(it.dataJson) - Message( - messageDb.id, - messageDb.piuri, - messageDb.from, - messageDb.to, - messageDb.fromPrior, - messageDb.body, - messageDb.extraHeaders, - messageDb.createdTime, - messageDb.expiresTimePlus, - messageDb.attachments, - messageDb.thid, - messageDb.pthid, - messageDb.ack, - messageDb.direction, - ) - }.toTypedArray() - } - - override fun getAllMessagesReceived(): Array { + it.executeAsList().map { message -> + val messageDb = Json.decodeFromString(message.dataJson) + Message( + messageDb.id, + messageDb.piuri, + messageDb.from, + messageDb.to, + messageDb.fromPrior, + messageDb.body, + messageDb.extraHeaders, + messageDb.createdTime, + messageDb.expiresTimePlus, + messageDb.attachments, + messageDb.thid, + messageDb.pthid, + messageDb.ack, + messageDb.direction, + ) + } + } + } + + override fun getAllMessagesReceived(): Flow> { return getInstance().messageQueries.fetchAllReceivedMessages() - .executeAsList() + .asFlow() .map { - val messageDb = Json.decodeFromString(it.dataJson) - Message( - messageDb.id, - messageDb.piuri, - messageDb.from, - messageDb.to, - messageDb.fromPrior, - messageDb.body, - messageDb.extraHeaders, - messageDb.createdTime, - messageDb.expiresTimePlus, - messageDb.attachments, - messageDb.thid, - messageDb.pthid, - messageDb.ack, - messageDb.direction, - ) - }.toTypedArray() - } - - override fun getAllMessagesSentTo(did: DID): Array { + it.executeAsList().map { message -> + val messageDb = Json.decodeFromString(message.dataJson) + Message( + messageDb.id, + messageDb.piuri, + messageDb.from, + messageDb.to, + messageDb.fromPrior, + messageDb.body, + messageDb.extraHeaders, + messageDb.createdTime, + messageDb.expiresTimePlus, + messageDb.attachments, + messageDb.thid, + messageDb.pthid, + messageDb.ack, + messageDb.direction, + ) + } + } + } + + override fun getAllMessagesSentTo(did: DID): Flow> { return getInstance().messageQueries.fetchAllMessagesSentTo(did.toString()) - .executeAsList() + .asFlow() .map { - val messageDb = Json.decodeFromString(it.dataJson) - Message( - messageDb.id, - messageDb.piuri, - messageDb.from, - messageDb.to, - messageDb.fromPrior, - messageDb.body, - messageDb.extraHeaders, - messageDb.createdTime, - messageDb.expiresTimePlus, - messageDb.attachments, - messageDb.thid, - messageDb.pthid, - messageDb.ack, - messageDb.direction, - ) - }.toTypedArray() - } - - override fun getAllMessagesReceivedFrom(did: DID): Array { + it.executeAsList().map { message -> + val messageDb = Json.decodeFromString(message.dataJson) + Message( + messageDb.id, + messageDb.piuri, + messageDb.from, + messageDb.to, + messageDb.fromPrior, + messageDb.body, + messageDb.extraHeaders, + messageDb.createdTime, + messageDb.expiresTimePlus, + messageDb.attachments, + messageDb.thid, + messageDb.pthid, + messageDb.ack, + messageDb.direction, + ) + } + } + } + + override fun getAllMessagesReceivedFrom(did: DID): Flow> { return getInstance().messageQueries.fetchAllMessagesReceivedFrom(did.toString()) - .executeAsList() - .map { - val messageDb = Json.decodeFromString(it.dataJson) - Message( - messageDb.id, - messageDb.piuri, - messageDb.from, - messageDb.to, - messageDb.fromPrior, - messageDb.body, - messageDb.extraHeaders, - messageDb.createdTime, - messageDb.expiresTimePlus, - messageDb.attachments, - messageDb.thid, - messageDb.pthid, - messageDb.ack, - messageDb.direction, - ) - }.toTypedArray() - } - - override fun getAllMessagesOfType(type: String, relatedWithDID: DID?): Array { - return getInstance().messageQueries.fetchAllMessagesOfType(type, relatedWithDID.toString(), relatedWithDID.toString()) - .executeAsList() + .asFlow() .map { - val messageDb = Json.decodeFromString(it.dataJson) - Message( - messageDb.id, - messageDb.piuri, - messageDb.from, - messageDb.to, - messageDb.fromPrior, - messageDb.body, - messageDb.extraHeaders, - messageDb.createdTime, - messageDb.expiresTimePlus, - messageDb.attachments, - messageDb.thid, - messageDb.pthid, - messageDb.ack, - messageDb.direction, - ) - }.toTypedArray() - } - - override fun getMessage(id: String): Message? { - val message = try { - getInstance().messageQueries.fetchMessageById(id) - .executeAsOne() - } catch (e: NullPointerException) { - null - } ?: return null - - val messageDb = Json.decodeFromString(message.dataJson) - - return Message( - messageDb.id, - messageDb.piuri, - messageDb.from, - messageDb.to, - messageDb.fromPrior, - messageDb.body, - messageDb.extraHeaders, - messageDb.createdTime, - messageDb.expiresTimePlus, - messageDb.attachments, - messageDb.thid, - messageDb.pthid, - messageDb.ack, - messageDb.direction, + it.executeAsList().map { message -> + val messageDb = Json.decodeFromString(message.dataJson) + Message( + messageDb.id, + messageDb.piuri, + messageDb.from, + messageDb.to, + messageDb.fromPrior, + messageDb.body, + messageDb.extraHeaders, + messageDb.createdTime, + messageDb.expiresTimePlus, + messageDb.attachments, + messageDb.thid, + messageDb.pthid, + messageDb.ack, + messageDb.direction, + ) + } + } + } + + override fun getAllMessagesOfType(type: String, relatedWithDID: DID?): Flow> { + return getInstance().messageQueries.fetchAllMessagesOfType( + type, + relatedWithDID.toString(), ) + .asFlow() + .map { + it.executeAsList().map { message -> + val messageDb = Json.decodeFromString(message.dataJson) + Message( + messageDb.id, + messageDb.piuri, + messageDb.from, + messageDb.to, + messageDb.fromPrior, + messageDb.body, + messageDb.extraHeaders, + messageDb.createdTime, + messageDb.expiresTimePlus, + messageDb.attachments, + messageDb.thid, + messageDb.pthid, + messageDb.ack, + messageDb.direction, + ) + } + } } - override fun getAllMediators(): Array { + override fun getMessage(id: String): Flow { + return getInstance().messageQueries.fetchMessageById(id) + .asFlow() + .map { + try { + val messageDb = Json.decodeFromString(it.executeAsOne().dataJson) + Message( + messageDb.id, + messageDb.piuri, + messageDb.from, + messageDb.to, + messageDb.fromPrior, + messageDb.body, + messageDb.extraHeaders, + messageDb.createdTime, + messageDb.expiresTimePlus, + messageDb.attachments, + messageDb.thid, + messageDb.pthid, + messageDb.ack, + messageDb.direction, + ) + } catch (e: NullPointerException) { + null + } + } + } + + override fun getAllMediators(): Flow> { return getInstance().mediatorQueries.fetchAllMediators() - .executeAsList() + .asFlow() .map { - Mediator( - it.id, - DID(it.MediatorDID), - DID(it.HostDID), - DID(it.RoutingDID), - ) - }.toTypedArray() + it.executeAsList().map { mediator -> + Mediator( + mediator.id, + DID(mediator.MediatorDID), + DID(mediator.HostDID), + DID(mediator.RoutingDID), + ) + } + } } - override fun getAllCredentials(): Array { + override fun getAllCredentials(): Flow> { return getInstance().verifiableCredentialQueries.fetchAllCredentials() - .executeAsList() + .asFlow() .map { - val verifiableCredential = Json.decodeFromString(it.verifiableCredentialJson) - when (it.credentialType) { - CredentialType.JWT.type -> { - JWTCredentialPayload.JWTVerifiableCredential( - id = verifiableCredential.id, - credentialType = CredentialType.JWT, - context = verifiableCredential.context, - type = verifiableCredential.type, - credentialSchema = verifiableCredential.credentialSchema, - credentialSubject = verifiableCredential.credentialSubject, - credentialStatus = verifiableCredential.credentialStatus, - refreshService = verifiableCredential.refreshService, - evidence = verifiableCredential.evidence, - termsOfUse = verifiableCredential.termsOfUse, - issuer = verifiableCredential.issuer, - issuanceDate = verifiableCredential.issuanceDate, - expirationDate = verifiableCredential.expirationDate, - validFrom = verifiableCredential.validFrom, - validUntil = verifiableCredential.validUntil, - proof = verifiableCredential.proof, - aud = verifiableCredential.aud, - ) + it.executeAsList().map { verifiableCredential -> + val verifiableCredential = + Json.decodeFromString(verifiableCredential.verifiableCredentialJson) + when (verifiableCredential.credentialType) { + CredentialType.JWT -> { + JWTCredentialPayload.JWTVerifiableCredential( + id = verifiableCredential.id, + credentialType = CredentialType.JWT, + context = verifiableCredential.context, + type = verifiableCredential.type, + credentialSchema = verifiableCredential.credentialSchema, + credentialSubject = verifiableCredential.credentialSubject, + credentialStatus = verifiableCredential.credentialStatus, + refreshService = verifiableCredential.refreshService, + evidence = verifiableCredential.evidence, + termsOfUse = verifiableCredential.termsOfUse, + issuer = verifiableCredential.issuer, + issuanceDate = verifiableCredential.issuanceDate, + expirationDate = verifiableCredential.expirationDate, + validFrom = verifiableCredential.validFrom, + validUntil = verifiableCredential.validUntil, + proof = verifiableCredential.proof, + aud = verifiableCredential.aud, + ) + } + + CredentialType.W3C -> + W3CVerifiableCredential( + id = verifiableCredential.id, + credentialType = CredentialType.JWT, + context = verifiableCredential.context, + type = verifiableCredential.type, + credentialSchema = verifiableCredential.credentialSchema, + credentialSubject = verifiableCredential.credentialSubject, + credentialStatus = verifiableCredential.credentialStatus, + refreshService = verifiableCredential.refreshService, + evidence = verifiableCredential.evidence, + termsOfUse = verifiableCredential.termsOfUse, + issuer = verifiableCredential.issuer, + issuanceDate = verifiableCredential.issuanceDate, + expirationDate = verifiableCredential.expirationDate, + validFrom = verifiableCredential.validFrom, + validUntil = verifiableCredential.validUntil, + proof = verifiableCredential.proof, + aud = verifiableCredential.aud, + ) + + else -> + JWTCredentialPayload.JWTVerifiableCredential( + id = verifiableCredential.id, + credentialType = CredentialType.JWT, + context = verifiableCredential.context, + type = verifiableCredential.type, + credentialSchema = verifiableCredential.credentialSchema, + credentialSubject = verifiableCredential.credentialSubject, + credentialStatus = verifiableCredential.credentialStatus, + refreshService = verifiableCredential.refreshService, + evidence = verifiableCredential.evidence, + termsOfUse = verifiableCredential.termsOfUse, + issuer = verifiableCredential.issuer, + issuanceDate = verifiableCredential.issuanceDate, + expirationDate = verifiableCredential.expirationDate, + validFrom = verifiableCredential.validFrom, + validUntil = verifiableCredential.validUntil, + proof = verifiableCredential.proof, + aud = verifiableCredential.aud, + ) } - CredentialType.W3C.type -> - W3CVerifiableCredential( - id = verifiableCredential.id, - credentialType = CredentialType.JWT, - context = verifiableCredential.context, - type = verifiableCredential.type, - credentialSchema = verifiableCredential.credentialSchema, - credentialSubject = verifiableCredential.credentialSubject, - credentialStatus = verifiableCredential.credentialStatus, - refreshService = verifiableCredential.refreshService, - evidence = verifiableCredential.evidence, - termsOfUse = verifiableCredential.termsOfUse, - issuer = verifiableCredential.issuer, - issuanceDate = verifiableCredential.issuanceDate, - expirationDate = verifiableCredential.expirationDate, - validFrom = verifiableCredential.validFrom, - validUntil = verifiableCredential.validUntil, - proof = verifiableCredential.proof, - aud = verifiableCredential.aud, - ) - else -> - JWTCredentialPayload.JWTVerifiableCredential( - id = verifiableCredential.id, - credentialType = CredentialType.JWT, - context = verifiableCredential.context, - type = verifiableCredential.type, - credentialSchema = verifiableCredential.credentialSchema, - credentialSubject = verifiableCredential.credentialSubject, - credentialStatus = verifiableCredential.credentialStatus, - refreshService = verifiableCredential.refreshService, - evidence = verifiableCredential.evidence, - termsOfUse = verifiableCredential.termsOfUse, - issuer = verifiableCredential.issuer, - issuanceDate = verifiableCredential.issuanceDate, - expirationDate = verifiableCredential.expirationDate, - validFrom = verifiableCredential.validFrom, - validUntil = verifiableCredential.validUntil, - proof = verifiableCredential.proof, - aud = verifiableCredential.aud, - ) } - }.toTypedArray() + } } } diff --git a/pluto/src/commonMain/sqldelight/io.iohk.atala.prism.walletsdk.pluto/data/DID.sq b/pluto/src/commonMain/sqldelight/io.iohk.atala.prism.walletsdk.pluto/data/DID.sq index 295c1d7e8..7c69a1b7c 100644 --- a/pluto/src/commonMain/sqldelight/io.iohk.atala.prism.walletsdk.pluto/data/DID.sq +++ b/pluto/src/commonMain/sqldelight/io.iohk.atala.prism.walletsdk.pluto/data/DID.sq @@ -14,25 +14,25 @@ VALUES ?; fetchAllPrismDID: SELECT DID.*, PrivateKey.keyPathIndex FROM DID -JOIN PrivateKey ON DID.methodId = PrivateKey.didId +JOIN PrivateKey ON DID.did = PrivateKey.didId WHERE method = 'prism'; fetchDIDInfoByDID: SELECT DID.*, PrivateKey.keyPathIndex FROM DID -JOIN PrivateKey ON DID.methodId = PrivateKey.didId -WHERE did = ?; +JOIN PrivateKey ON DID.did = PrivateKey.didId +WHERE DID.did = ?; fetchDIDInfoByAlias: SELECT DID.*, PrivateKey.keyPathIndex FROM DID -JOIN PrivateKey ON DID.methodId = PrivateKey.didId +JOIN PrivateKey ON DID.did = PrivateKey.didId WHERE alias = ?; fetchAllPeerDID: SELECT DID.did, DID.alias, PrivateKey.* FROM DID -JOIN PrivateKey ON DID.methodId = PrivateKey.didId +JOIN PrivateKey ON DID.did = PrivateKey.didId WHERE DID.method = 'peer'; fetchDIDByMethodId: diff --git a/pluto/src/commonMain/sqldelight/io.iohk.atala.prism.walletsdk.pluto/data/Message.sq b/pluto/src/commonMain/sqldelight/io.iohk.atala.prism.walletsdk.pluto/data/Message.sq index 47c0b048b..93c78cb90 100644 --- a/pluto/src/commonMain/sqldelight/io.iohk.atala.prism.walletsdk.pluto/data/Message.sq +++ b/pluto/src/commonMain/sqldelight/io.iohk.atala.prism.walletsdk.pluto/data/Message.sq @@ -48,8 +48,7 @@ fetchAllMessagesOfType: SELECT * FROM Message WHERE type = :type -AND `from` = :from -AND `to` = :to; +AND (:relatedWithDID IS NULL OR `from` = :relatedWithDID OR `to` = :relatedWithDID); fetchMessageById: SELECT * diff --git a/pluto/src/commonMain/sqldelight/io.iohk.atala.prism.walletsdk.pluto/data/PrivateKey.sq b/pluto/src/commonMain/sqldelight/io.iohk.atala.prism.walletsdk.pluto/data/PrivateKey.sq index 22438fd02..693678691 100644 --- a/pluto/src/commonMain/sqldelight/io.iohk.atala.prism.walletsdk.pluto/data/PrivateKey.sq +++ b/pluto/src/commonMain/sqldelight/io.iohk.atala.prism.walletsdk.pluto/data/PrivateKey.sq @@ -26,6 +26,6 @@ WHERE didId = ?; fetchLastkeyPathIndex: SELECT keyPathIndex FROM PrivateKey -WHERE didId IN (SELECT methodId FROM DID WHERE method = 'Prism') +WHERE didId IN (SELECT methodId FROM DID WHERE method = 'prism') ORDER BY keyPathIndex DESC LIMIT 1; diff --git a/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/ConnectionManager.kt b/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/ConnectionManager.kt index bc056ae2e..41bc09326 100644 --- a/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/ConnectionManager.kt +++ b/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/ConnectionManager.kt @@ -62,9 +62,9 @@ actual class ConnectionManager : ConnectionsManager { mediationHandler.registerMessagesAsRead(messagesIds) it.map { it.second }.toTypedArray() } - .map { - pluto.storeMessages(it) - it + .map { messages -> + pluto.storeMessages(messages.toList()) + messages } } diff --git a/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PrismAgent.kt b/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PrismAgent.kt index 78d7d0e28..aab95f49b 100644 --- a/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PrismAgent.kt +++ b/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PrismAgent.kt @@ -23,6 +23,8 @@ import io.iohk.atala.prism.walletsdk.prismagent.protocols.findProtocolTypeByValu import io.ktor.client.plugins.contentnegotiation.ContentNegotiation import io.ktor.http.HttpMethod import io.ktor.serialization.kotlinx.json.json +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.firstOrNull import kotlinx.serialization.Serializable import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json @@ -106,7 +108,9 @@ class PrismAgent { @Throws() suspend fun start() { - if (state != State.STOPED) { return } + if (state != State.STOPED) { + return + } state = State.STARTING try { connectionManager.startMediator() @@ -135,11 +139,10 @@ class PrismAgent { alias: String? = null, services: Array = emptyArray(), ): DID { - val index = keyPathIndex ?: pluto.getPrismLastKeyPathIndex() + val index = keyPathIndex ?: pluto.getPrismLastKeyPathIndex().first() val keyPair = apollo.createKeyPair(seed = seed, curve = KeyCurve(Curve.SECP256K1, index)) val did = castor.createPrismDID(masterPublicKey = keyPair.publicKey, services = services) - pluto.storePrivateKeys(keyPair.privateKey, did, index) - pluto.storePrismDID(did = did, keyPathIndex = index, alias = alias) + pluto.storePrismDIDAndPrivateKeys(did = did, keyPathIndex = index, alias = alias, listOf(keyPair.privateKey)) return did } @@ -159,9 +162,9 @@ class PrismAgent { // TODO: This still needs to be done update the key List } - pluto.storePeerDID( + pluto.storePeerDIDAndPrivateKeys( did = did, - privateKeys = arrayOf(keyAgreementKeyPair.privateKey, authenticationKeyPair.privateKey), + privateKeys = listOf(keyAgreementKeyPair.privateKey, authenticationKeyPair.privateKey), ) // The next logic is a bit tricky, so it's not forgotten this is a reminder. @@ -225,7 +228,8 @@ class PrismAgent { } suspend fun signWith(did: DID, message: ByteArray): Signature { - val privateKey = pluto.getDIDPrivateKeysByDID(did)?.firstOrNull() ?: throw PrismAgentError.cannotFindDIDPrivateKey() + val privateKey = + pluto.getDIDPrivateKeysByDID(did).first().first() ?: throw PrismAgentError.cannotFindDIDPrivateKey() return apollo.signMessage(privateKey, message) } diff --git a/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/DefaultMediationHandler.kt b/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/DefaultMediationHandler.kt index 9eb40b000..57f193b9b 100644 --- a/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/DefaultMediationHandler.kt +++ b/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/DefaultMediationHandler.kt @@ -17,8 +17,10 @@ import io.iohk.atala.prism.walletsdk.prismagent.protocols.pickup.PickupDelivery import io.iohk.atala.prism.walletsdk.prismagent.protocols.pickup.PickupReceived import io.iohk.atala.prism.walletsdk.prismagent.protocols.pickup.PickupRequest import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.mapNotNull final class DefaultMediationHandler( override val mediatorDID: DID, @@ -26,8 +28,8 @@ final class DefaultMediationHandler( private val store: MediatorRepository, ) : MediationHandler { final class PlutoMediatorRepositoryImpl(private val pluto: Pluto) : MediatorRepository { - override fun getAllMediators(): Array { - return pluto.getAllMediators() + override suspend fun getAllMediators(): List { + return pluto.getAllMediators().first() } override fun storeMediator(mediator: Mediator) { @@ -42,7 +44,7 @@ final class DefaultMediationHandler( this.mediator = null } - override fun bootRegisteredMediator(): Mediator? { + override suspend fun bootRegisteredMediator(): Mediator? { if (mediator == null) { mediator = store.getAllMediators().first() } diff --git a/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/MediationHandler.kt b/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/MediationHandler.kt index a66fc6240..d68fb9ba5 100644 --- a/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/MediationHandler.kt +++ b/prism-agent/src/allButJSMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/MediationHandler.kt @@ -10,7 +10,7 @@ actual interface MediationHandler { actual val mediatorDID: DID @Throws() - fun bootRegisteredMediator(): Mediator? + suspend fun bootRegisteredMediator(): Mediator? @Throws() fun achieveMediation(host: DID): Flow diff --git a/prism-agent/src/allButJSTest/kotlin/io.iohk.atala.prism.walletsdk.prismagent/MediationHandlerMock.kt b/prism-agent/src/allButJSTest/kotlin/io.iohk.atala.prism.walletsdk.prismagent/MediationHandlerMock.kt index 839e9ac57..d3de09dd0 100644 --- a/prism-agent/src/allButJSTest/kotlin/io.iohk.atala.prism.walletsdk.prismagent/MediationHandlerMock.kt +++ b/prism-agent/src/allButJSTest/kotlin/io.iohk.atala.prism.walletsdk.prismagent/MediationHandlerMock.kt @@ -18,7 +18,7 @@ class MediationHandlerMock( var pickupUnreadMessagesResponse: Array> = emptyArray() @Throws() - override fun bootRegisteredMediator(): Mediator? { + override suspend fun bootRegisteredMediator(): Mediator? { mediator = bootMediatorResponse return bootMediatorResponse } diff --git a/prism-agent/src/allButJSTest/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PlutoMock.kt b/prism-agent/src/allButJSTest/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PlutoMock.kt index bed564d33..cbc5cf72f 100644 --- a/prism-agent/src/allButJSTest/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PlutoMock.kt +++ b/prism-agent/src/allButJSTest/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PlutoMock.kt @@ -9,10 +9,11 @@ import io.iohk.atala.prism.walletsdk.domain.models.PeerDID import io.iohk.atala.prism.walletsdk.domain.models.PrismDIDInfo import io.iohk.atala.prism.walletsdk.domain.models.PrivateKey import io.iohk.atala.prism.walletsdk.domain.models.VerifiableCredential +import kotlinx.coroutines.flow.Flow class PlutoMock : Pluto { - var wasStorePrismDIDCalled: Boolean = false - var wasStorePeerDIDCalled: Boolean = false + var wasStorePrismDIDAndPrivateKeysCalled: Boolean = false + var wasStorePeerDIDAndPrivateKeysCalled: Boolean = false var wasStoreDIDPairCalled: Boolean = false var wasStoreMessageCalled: Boolean = false var wasStoreMessagesCalled: Boolean = false @@ -38,40 +39,41 @@ class PlutoMock : Pluto { var wasGetAllMediatorsCalled: Boolean = false var wasGetAllCredentialsCalled: Boolean = false - var storedPrismDID: Array = emptyArray() - var storedPeerDID: Array = emptyArray() - var getAllPrismDIDsReturn: Array = emptyArray() - var getDIDInfoByDIDReturn: PrismDIDInfo? = null - var getPrismDIDKeyPathIndexReturn: Int? = null - var getPrismLastKeyPathIndexReturn: Int = 0 - var getAllPeerDIDsReturn: Array = emptyArray() - var getDIDPrivateKeysReturn: Array? = emptyArray() - var getDIDPrivateKeysByIDReturn: PrivateKey? = null - var getAllDidPairsReturn: Array = emptyArray() - var getPairByDIDReturn: DIDPair? = null - var getPairByNameReturn: DIDPair? = null - var getAllMessagesReturn: Array = emptyArray() - var getAllMessagesSentReturn: Array = emptyArray() - var getAllMessagesSentToReturn: Array = emptyArray() - var getAllMessagesReceivedReturn: Array = emptyArray() - var getAllMessagesReceivedFromReturn: Array = emptyArray() - var getAllMessagesOfTypeReturn: Array = emptyArray() - var getMessageReturn: Message? = null - var getAllMediatorsReturn: Array = emptyArray() - var getAllCredentialsReturn: Array = emptyArray() - - override fun storePrismDID( + var storedPrismDID: List = listOf() + var storedPeerDID: List = listOf() + lateinit var getAllPrismDIDsReturn: Flow> + lateinit var getDIDInfoByDIDReturn: Flow + lateinit var getPrismDIDKeyPathIndexReturn: Flow + lateinit var getPrismLastKeyPathIndexReturn: Flow + lateinit var getAllPeerDIDsReturn: Flow> + lateinit var getDIDPrivateKeysReturn: Flow> + lateinit var getDIDPrivateKeysByIDReturn: Flow + lateinit var getAllDidPairsReturn: Flow> + lateinit var getPairByDIDReturn: Flow + lateinit var getPairByNameReturn: Flow + lateinit var getAllMessagesReturn: Flow> + lateinit var getAllMessagesSentReturn: Flow> + lateinit var getAllMessagesSentToReturn: Flow> + lateinit var getAllMessagesReceivedReturn: Flow> + lateinit var getAllMessagesReceivedFromReturn: Flow> + lateinit var getAllMessagesOfTypeReturn: Flow> + lateinit var getMessageReturn: Flow + lateinit var getAllMediatorsReturn: Flow> + lateinit var getAllCredentialsReturn: Flow> + + override fun storePrismDIDAndPrivateKeys( did: DID, keyPathIndex: Int, alias: String?, + privateKeys: List, ) { storedPrismDID += did - wasStorePrismDIDCalled = true + wasStorePrismDIDAndPrivateKeysCalled = true } - override fun storePeerDID(did: DID, privateKeys: Array) { + override fun storePeerDIDAndPrivateKeys(did: DID, privateKeys: List) { storedPeerDID += did - wasStorePeerDIDCalled = true + wasStorePeerDIDAndPrivateKeysCalled = true } override fun storeDIDPair(host: DID, receiver: DID, name: String) { @@ -82,7 +84,7 @@ class PlutoMock : Pluto { wasStoreMessageCalled = true } - override fun storeMessages(messages: Array) { + override fun storeMessages(messages: List) { wasStoreMessagesCalled = true } @@ -98,106 +100,106 @@ class PlutoMock : Pluto { wasStoreCredentialCalled = true } - override fun getAllPrismDIDs(): Array { + override fun getAllPrismDIDs(): Flow> { wasGetAllPrismDIDsCalled = true return getAllPrismDIDsReturn } - override fun getDIDInfoByDID(did: DID): PrismDIDInfo? { + override fun getDIDInfoByDID(did: DID): Flow { wasGetDIDInfoByDIDCalled = true return getDIDInfoByDIDReturn } - override fun getDIDInfoByAlias(alias: String): Array = getAllPrismDIDsReturn + override fun getDIDInfoByAlias(alias: String): Flow> = getAllPrismDIDsReturn - override fun getPrismDIDKeyPathIndex(did: DID): Int? = getPrismDIDKeyPathIndexReturn + override fun getPrismDIDKeyPathIndex(did: DID): Flow = getPrismDIDKeyPathIndexReturn - override fun getPrismLastKeyPathIndex(): Int { + override fun getPrismLastKeyPathIndex(): Flow { wasGetPrismLastKeyPathIndexCalled = true return getPrismLastKeyPathIndexReturn } - override fun getAllPeerDIDs(): Array { + override fun getAllPeerDIDs(): Flow> { wasGetAllPeerDIDsCalled = true return getAllPeerDIDsReturn } - override fun getDIDPrivateKeysByDID(did: DID): Array? { + override fun getDIDPrivateKeysByDID(did: DID): Flow> { wasGetDIDPrivateKeysByDIDCalled = true return getDIDPrivateKeysReturn } - override fun getDIDPrivateKeyByID(id: String): PrivateKey? { + override fun getDIDPrivateKeyByID(id: String): Flow { wasGetDIDPrivateKeysByIDCalled = true return getDIDPrivateKeysByIDReturn } - override fun getAllDidPairs(): Array { + override fun getAllDidPairs(): Flow> { wasGetAllDidPairsCalled = true return getAllDidPairsReturn } - override fun getPairByDID(did: DID): DIDPair? { + override fun getPairByDID(did: DID): Flow { wasGetPairByDIDCalled = true return getPairByDIDReturn } - override fun getPairByName(name: String): DIDPair? { + override fun getPairByName(name: String): Flow { wasGetPairByNameCalled = true return getPairByNameReturn } - override fun getAllMessages(): Array { + override fun getAllMessages(): Flow> { wasGetAllMessagesCalled = true return getAllMessagesReturn } - override fun getAllMessages(did: DID): Array { + override fun getAllMessages(did: DID): Flow> { wasGetAllMessagesCalled = true return getAllMessagesReturn } - override fun getAllMessagesSent(): Array { + override fun getAllMessagesSent(): Flow> { wasGetAllMessagesSentCalled = true return getAllMessagesSentReturn } - override fun getAllMessagesReceived(): Array { + override fun getAllMessagesReceived(): Flow> { wasGetAllMessagesReceivedCalled = true return getAllMessagesReceivedReturn } - override fun getAllMessagesSentTo(did: DID): Array { + override fun getAllMessagesSentTo(did: DID): Flow> { wasGetAllMessagesSentToCalled = true return getAllMessagesSentToReturn } - override fun getAllMessagesReceivedFrom(did: DID): Array { + override fun getAllMessagesReceivedFrom(did: DID): Flow> { wasGetAllMessagesReceivedFromCalled = true return getAllMessagesReceivedFromReturn } - override fun getAllMessagesOfType(type: String, relatedWithDID: DID?): Array { + override fun getAllMessagesOfType(type: String, relatedWithDID: DID?): Flow> { wasGetAllMessagesOfTypeCalled = true return getAllMessagesOfTypeReturn } - override fun getAllMessages(from: DID, to: DID): Array { + override fun getAllMessages(from: DID, to: DID): Flow> { wasGetAllMessagesCalled = true return getAllMessagesReturn } - override fun getMessage(id: String): Message? { + override fun getMessage(id: String): Flow { wasGetMessageCalled = true return getMessageReturn } - override fun getAllMediators(): Array { + override fun getAllMediators(): Flow> { wasGetAllMediatorsCalled = true return getAllMediatorsReturn } - override fun getAllCredentials(): Array { + override fun getAllCredentials(): Flow> { wasGetAllCredentialsCalled = true return getAllCredentialsReturn } diff --git a/prism-agent/src/allButJSTest/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PrismAgentTests.kt b/prism-agent/src/allButJSTest/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PrismAgentTests.kt index 4fc7ce622..664507a6c 100644 --- a/prism-agent/src/allButJSTest/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PrismAgentTests.kt +++ b/prism-agent/src/allButJSTest/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PrismAgentTests.kt @@ -12,6 +12,7 @@ import io.iohk.atala.prism.walletsdk.prismagent.models.PrismOnboardingInvitation import io.iohk.atala.prism.walletsdk.prismagent.protocols.ProtocolType import io.ktor.http.HttpStatusCode import io.ktor.utils.io.core.toByteArray +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.test.runTest import kotlin.test.BeforeTest import kotlin.test.Test @@ -54,12 +55,12 @@ class PrismAgentTests { seed = seed, api = null, ) + plutoMock.getPrismLastKeyPathIndexReturn = flow { emit(0) } val newDID = agent.createNewPrismDID() assertEquals(newDID, validDID) assertEquals(newDID, plutoMock.storedPrismDID.first()) assertTrue { plutoMock.wasGetPrismLastKeyPathIndexCalled } - assertTrue { plutoMock.wasStorePrivateKeysCalled } - assertTrue { plutoMock.wasStorePrismDIDCalled } + assertTrue { plutoMock.wasStorePrismDIDAndPrivateKeysCalled } } @Test @@ -79,7 +80,7 @@ class PrismAgentTests { assertEquals(newDID, validDID) assertEquals(newDID, plutoMock.storedPeerDID.first()) - assertTrue { plutoMock.wasStorePeerDIDCalled } + assertTrue { plutoMock.wasStorePeerDIDAndPrivateKeysCalled } } @Test @@ -164,7 +165,7 @@ class PrismAgentTests { api = null, ) - plutoMock.getDIDPrivateKeysReturn = null + plutoMock.getDIDPrivateKeysReturn = flow { emit(listOf(null)) } val did = DID("did", "peer", "asdf1234asdf1234") val messageString = "This is a message" @@ -186,8 +187,8 @@ class PrismAgentTests { api = null, ) - val privateKeys = arrayOf(PrivateKey(KeyCurve(Curve.SECP256K1), byteArrayOf())) - plutoMock.getDIDPrivateKeysReturn = privateKeys + val privateKeys = listOf(PrivateKey(KeyCurve(Curve.SECP256K1), byteArrayOf())) + plutoMock.getDIDPrivateKeysReturn = flow { emit(privateKeys) } val did = DID("did", "peer", "asdf1234asdf1234") val messageString = "This is a message" diff --git a/prism-agent/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/MediatorRepository.kt b/prism-agent/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/MediatorRepository.kt index 2fba1f2c0..14ef93190 100644 --- a/prism-agent/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/MediatorRepository.kt +++ b/prism-agent/src/commonMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/MediatorRepository.kt @@ -4,5 +4,5 @@ import io.iohk.atala.prism.walletsdk.domain.models.Mediator interface MediatorRepository { fun storeMediator(mediator: Mediator) - fun getAllMediators(): Array + suspend fun getAllMediators(): List } diff --git a/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/ConnectionManager.kt b/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/ConnectionManager.kt index 5093af261..d611af0e4 100644 --- a/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/ConnectionManager.kt +++ b/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/ConnectionManager.kt @@ -9,6 +9,8 @@ import io.iohk.atala.prism.walletsdk.domain.models.Mediator import io.iohk.atala.prism.walletsdk.domain.models.Message import io.iohk.atala.prism.walletsdk.domain.models.PrismAgentError import io.iohk.atala.prism.walletsdk.prismagent.mediation.MediationHandler +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import kotlin.js.Promise actual class ConnectionManager { @@ -31,7 +33,9 @@ actual class ConnectionManager { } fun startMediator() { - mediationHandler.bootRegisteredMediator() + GlobalScope.launch { + mediationHandler.bootRegisteredMediator() + } } fun registerMediator(host: DID): Promise { @@ -49,12 +53,12 @@ actual class ConnectionManager { fun awaitMessages(): Promise> { return mediationHandler.pickupUnreadMessages(NUMBER_OF_MESSAGES) .then { - val messagesIds = it.map { it.first }.toTypedArray() + val messagesIds = it.map { pair -> pair.first }.toTypedArray() mediationHandler.registerMessagesAsRead(messagesIds) - it.map { it.second }.toTypedArray() + it.map { pair -> pair.second }.toTypedArray() } .then { - pluto.storeMessages(it) + pluto.storeMessages(it.asList()) it } } diff --git a/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PrismAgent.kt b/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PrismAgent.kt index ffe9bf20a..71d6daf4c 100644 --- a/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PrismAgent.kt +++ b/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/PrismAgent.kt @@ -10,7 +10,6 @@ import io.iohk.atala.prism.walletsdk.domain.models.DIDDocument import io.iohk.atala.prism.walletsdk.domain.models.KeyCurve import io.iohk.atala.prism.walletsdk.domain.models.PrismAgentError import io.iohk.atala.prism.walletsdk.domain.models.Seed -import io.iohk.atala.prism.walletsdk.domain.models.Signature import io.iohk.atala.prism.walletsdk.prismagent.helpers.Api import io.iohk.atala.prism.walletsdk.prismagent.helpers.ApiImpl import io.iohk.atala.prism.walletsdk.prismagent.helpers.HttpClient @@ -137,18 +136,18 @@ final class PrismAgent { } } - fun createNewPrismDID( - keyPathIndex: Int? = null, - alias: String? = null, - services: Array = emptyArray(), - ): DID { - val index = keyPathIndex ?: pluto.getPrismLastKeyPathIndex() - val keyPair = apollo.createKeyPair(seed = seed, curve = KeyCurve(Curve.SECP256K1, index)) - val did = castor.createPrismDID(masterPublicKey = keyPair.publicKey, services = services) - pluto.storePrivateKeys(keyPair.privateKey, did, index) - pluto.storePrismDID(did = did, keyPathIndex = index, alias = alias) - return did - } +// fun createNewPrismDID( +// keyPathIndex: Int? = null, +// alias: String? = null, +// services: Array = emptyArray(), +// ): DID { +// val index = keyPathIndex ?: pluto.getPrismLastKeyPathIndex() +// val keyPair = apollo.createKeyPair(seed = seed, curve = KeyCurve(Curve.SECP256K1, index)) +// val did = castor.createPrismDID(masterPublicKey = keyPair.publicKey, services = services) +// pluto.storePrivateKeys(keyPair.privateKey, did, index) +// pluto.storePrismDID(did = did, keyPathIndex = index, alias = alias) +// return did +// } fun createNewPeerDID( services: Array = emptyArray(), @@ -167,16 +166,16 @@ final class PrismAgent { .mediationHandler .updateKeyListWithDIDs(arrayOf(did)) .then { - pluto.storePeerDID( + pluto.storePeerDIDAndPrivateKeys( did = did, - privateKeys = arrayOf(keyAgreementKeyPair.privateKey, authenticationKeyPair.privateKey), + privateKeys = listOf(keyAgreementKeyPair.privateKey, authenticationKeyPair.privateKey), ) } .then { did } } else { - pluto.storePeerDID( + pluto.storePeerDIDAndPrivateKeys( did = did, - privateKeys = arrayOf(keyAgreementKeyPair.privateKey, authenticationKeyPair.privateKey), + privateKeys = listOf(keyAgreementKeyPair.privateKey, authenticationKeyPair.privateKey), ) return Promise.resolve(did) } @@ -214,10 +213,10 @@ final class PrismAgent { } } - fun signWith(did: DID, message: ByteArray): Signature { - val privateKey = pluto.getDIDPrivateKeysByDID(did)?.firstOrNull() ?: throw PrismAgentError.cannotFindDIDPrivateKey() - return apollo.signMessage(privateKey, message) - } +// fun signWith(did: DID, message: ByteArray): Signature { +// val privateKey = pluto.getDIDPrivateKeysByDID(did).first() ?: throw PrismAgentError.cannotFindDIDPrivateKey() +// return apollo.signMessage(privateKey, message) +// } fun parsePrismInvitation(str: String): Promise { try { diff --git a/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/DefaultMediationHandler.kt b/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/DefaultMediationHandler.kt index 227c8f537..f9fa52337 100644 --- a/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/DefaultMediationHandler.kt +++ b/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/DefaultMediationHandler.kt @@ -17,18 +17,18 @@ import io.iohk.atala.prism.walletsdk.prismagent.protocols.mediation.MediationReq import io.iohk.atala.prism.walletsdk.prismagent.protocols.pickup.PickupDelivery import io.iohk.atala.prism.walletsdk.prismagent.protocols.pickup.PickupReceived import io.iohk.atala.prism.walletsdk.prismagent.protocols.pickup.PickupRequest +import kotlinx.coroutines.flow.first import kotlin.js.Promise @OptIn(ExperimentalJsExport::class) -@JsExport final class DefaultMediationHandler( override val mediatorDID: DID, private val mercury: Mercury, private val store: MediatorRepository, ) : MediationHandler { final class PlutoMediatorRepositoryImpl(private val pluto: Pluto) : MediatorRepository { - override fun getAllMediators(): Array { - return pluto.getAllMediators() + override suspend fun getAllMediators(): List { + return pluto.getAllMediators().first() } override fun storeMediator(mediator: Mediator) { @@ -43,7 +43,7 @@ final class DefaultMediationHandler( this.mediator = null } - override fun bootRegisteredMediator(): Mediator? { + override suspend fun bootRegisteredMediator(): Mediator? { if (mediator == null) { mediator = store.getAllMediators().first() } diff --git a/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/MediationHandler.kt b/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/MediationHandler.kt index 6b4d44f4b..49127f440 100644 --- a/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/MediationHandler.kt +++ b/prism-agent/src/jsMain/kotlin/io.iohk.atala.prism.walletsdk.prismagent/mediation/MediationHandler.kt @@ -7,12 +7,11 @@ import io.iohk.atala.prism.walletsdk.prismagent.helpers.KMMPair import kotlin.js.Promise @OptIn(ExperimentalJsExport::class) -@JsExport actual interface MediationHandler { actual val mediator: Mediator? actual val mediatorDID: DID - fun bootRegisteredMediator(): Mediator? + suspend fun bootRegisteredMediator(): Mediator? fun achieveMediation(host: DID): Promise