From 58488a5f30d61ba1b96ad29146c0243b18bf4bf2 Mon Sep 17 00:00:00 2001 From: Essbante Date: Thu, 16 Jun 2022 20:05:24 -0600 Subject: [PATCH] refactor: model, package structure --- .../kotlin/com/rootsid/wal/library/DLT.kt | 72 ------- .../com/rootsid/wal/library/didcom/DIDPeer.kt | 3 +- .../wal/library/didcom/model/UnpackResult.kt | 17 ++ .../didcom/{ => storage}/SecretResolver.kt | 2 +- .../com/rootsid/wal/library/prism/Dlt.kt | 82 +++++++- .../wal/library/wallet/WalletService.kt | 2 +- .../wallet/model/BlockchainTxLogEntry.kt | 28 +++ .../rootsid/wal/library/wallet/model/Claim.kt | 32 ++++ .../wallet/model/ImportedCredential.kt | 17 ++ .../library/wallet/model/IssuedCredential.kt | 33 ++++ .../rootsid/wal/library/wallet/model/Model.kt | 180 ------------------ .../rootsid/wal/library/wallet/model/Proof.kt | 18 ++ .../wallet/model/VerifiedCredential.kt | 16 ++ .../wal/library/wallet/model/Wallet.kt | 38 ++++ .../wal/library/wallet/storage/Storage.kt | 1 + 15 files changed, 284 insertions(+), 257 deletions(-) create mode 100644 src/main/kotlin/com/rootsid/wal/library/didcom/model/UnpackResult.kt rename src/main/kotlin/com/rootsid/wal/library/didcom/{ => storage}/SecretResolver.kt (96%) create mode 100644 src/main/kotlin/com/rootsid/wal/library/wallet/model/BlockchainTxLogEntry.kt create mode 100644 src/main/kotlin/com/rootsid/wal/library/wallet/model/Claim.kt create mode 100644 src/main/kotlin/com/rootsid/wal/library/wallet/model/ImportedCredential.kt create mode 100644 src/main/kotlin/com/rootsid/wal/library/wallet/model/IssuedCredential.kt delete mode 100644 src/main/kotlin/com/rootsid/wal/library/wallet/model/Model.kt create mode 100644 src/main/kotlin/com/rootsid/wal/library/wallet/model/Proof.kt create mode 100644 src/main/kotlin/com/rootsid/wal/library/wallet/model/VerifiedCredential.kt create mode 100644 src/main/kotlin/com/rootsid/wal/library/wallet/model/Wallet.kt diff --git a/src/main/kotlin/com/rootsid/wal/library/DLT.kt b/src/main/kotlin/com/rootsid/wal/library/DLT.kt index f0d675b..e895e6a 100644 --- a/src/main/kotlin/com/rootsid/wal/library/DLT.kt +++ b/src/main/kotlin/com/rootsid/wal/library/DLT.kt @@ -9,75 +9,3 @@ import kotlinx.coroutines.runBlocking import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json -/** - * Verify issued credential - * - * @param wallet Wallet containing the credential - * @param credentialAlias Alias of Credential to verify - * @return Verification result - */ -// TODO: refactor to a single verifyCredential function -fun verifyIssuedCredential(wallet: Wallet, credentialAlias: String): List { - val credentials = wallet.issuedCredentials.filter { it.alias == credentialAlias } - if (credentials.isNotEmpty()) { - val credential = credentials[0] - val nodeAuthApi = NodeAuthApiImpl(GrpcConfig.options()) - val signed = JsonBasedCredential.fromString(credential.verifiedCredential.encodedSignedCredential) - // Use encodeDefaults to generate empty siblings field on proof - val format = Json { encodeDefaults = true } - val proof = MerkleInclusionProof.decode(format.encodeToString(credential.verifiedCredential.proof)) - - return runBlocking { - nodeAuthApi.verify(signed, proof).toMessageArray() - } - } else { - throw Exception("Credential '$credentialAlias' not found.") - } -} - -private fun VerificationResult.toMessageArray(): List { - val messages = mutableListOf() - for (message in this.verificationErrors) { - messages.add(message.errorMessage) - } - return messages -} - -/** - * Verify imported credential - * - * @param wallet Wallet containing the credential - * @param credentialAlias Alias of credential to verify - * @return Verification result - */ -// TODO: refactor to a single verifyCredential function -fun verifyImportedCredential(wallet: Wallet, credentialAlias: String): List { - val credentials = wallet.importedCredentials.filter { it.alias == credentialAlias } - if (credentials.isNotEmpty()) { - val credential = credentials[0] - val nodeAuthApi = NodeAuthApiImpl(GrpcConfig.options()) - val signed = JsonBasedCredential.fromString(credential.verifiedCredential.encodedSignedCredential) - // Use encodeDefaults to generate empty siblings field on proof - val format = Json { encodeDefaults = true } - val proof = MerkleInclusionProof.decode(format.encodeToString(credential.verifiedCredential.proof)) - - return runBlocking { - nodeAuthApi.verify(signed, proof).toMessageArray() - } - } else { - throw Exception("Credential '$credentialAlias' not found.") - } -} - -/** - * Grpc config - * Done this way to allow programmatic override of the grpc config - * @constructor Create empty Grpc config - */ -class GrpcConfig { - companion object { - var host: String = System.getenv("PRISM_NODE_HOST") ?: "" - var port: String = System.getenv("PRISM_NODE_PORT") ?: "50053" - fun options() = GrpcOptions("https", host, port.toInt()) - } -} diff --git a/src/main/kotlin/com/rootsid/wal/library/didcom/DIDPeer.kt b/src/main/kotlin/com/rootsid/wal/library/didcom/DIDPeer.kt index 28b2996..7669758 100644 --- a/src/main/kotlin/com/rootsid/wal/library/didcom/DIDPeer.kt +++ b/src/main/kotlin/com/rootsid/wal/library/didcom/DIDPeer.kt @@ -1,6 +1,7 @@ package com.rootsid.wal.library.didcom -import com.rootsid.wal.library.UnpackResult +import com.rootsid.wal.library.didcom.model.UnpackResult +import com.rootsid.wal.library.didcom.storage.SecretResolver import org.didcommx.didcomm.DIDComm import org.didcommx.didcomm.message.Message import org.didcommx.didcomm.model.PackEncryptedParams diff --git a/src/main/kotlin/com/rootsid/wal/library/didcom/model/UnpackResult.kt b/src/main/kotlin/com/rootsid/wal/library/didcom/model/UnpackResult.kt new file mode 100644 index 0000000..1d05a03 --- /dev/null +++ b/src/main/kotlin/com/rootsid/wal/library/didcom/model/UnpackResult.kt @@ -0,0 +1,17 @@ +package com.rootsid.wal.library.didcom.model + +/** + * Unpack result + * + * @property message + * @property from + * @property to + * @property res + * @constructor Create empty Unpack result + */ +data class UnpackResult( + val message: String, + val from: String?, + val to: String, + val res: org.didcommx.didcomm.model.UnpackResult +) diff --git a/src/main/kotlin/com/rootsid/wal/library/didcom/SecretResolver.kt b/src/main/kotlin/com/rootsid/wal/library/didcom/storage/SecretResolver.kt similarity index 96% rename from src/main/kotlin/com/rootsid/wal/library/didcom/SecretResolver.kt rename to src/main/kotlin/com/rootsid/wal/library/didcom/storage/SecretResolver.kt index 9ec7e96..ef50a5a 100644 --- a/src/main/kotlin/com/rootsid/wal/library/didcom/SecretResolver.kt +++ b/src/main/kotlin/com/rootsid/wal/library/didcom/storage/SecretResolver.kt @@ -1,4 +1,4 @@ -package com.rootsid.wal.library.didcom +package com.rootsid.wal.library.didcom.storage import org.didcommx.didcomm.secret.Secret import org.didcommx.didcomm.secret.SecretResolverEditable diff --git a/src/main/kotlin/com/rootsid/wal/library/prism/Dlt.kt b/src/main/kotlin/com/rootsid/wal/library/prism/Dlt.kt index d7f0a6f..2421254 100644 --- a/src/main/kotlin/com/rootsid/wal/library/prism/Dlt.kt +++ b/src/main/kotlin/com/rootsid/wal/library/prism/Dlt.kt @@ -4,8 +4,10 @@ import com.rootsid.wal.library.* import com.rootsid.wal.library.prism.model.Did import com.rootsid.wal.library.prism.model.DltDidUpdate import com.rootsid.wal.library.prism.model.KeyPath +import com.rootsid.wal.library.wallet.model.* import io.iohk.atala.prism.api.CredentialClaim import io.iohk.atala.prism.api.KeyGenerator +import io.iohk.atala.prism.api.VerificationResult import io.iohk.atala.prism.api.models.AtalaOperationId import io.iohk.atala.prism.api.models.AtalaOperationStatus import io.iohk.atala.prism.api.node.NodeAuthApiImpl @@ -13,7 +15,9 @@ import io.iohk.atala.prism.api.node.NodePayloadGenerator import io.iohk.atala.prism.api.node.NodePublicApi import io.iohk.atala.prism.api.node.PrismDidState import io.iohk.atala.prism.common.PrismSdkInternal +import io.iohk.atala.prism.credentials.json.JsonBasedCredential import io.iohk.atala.prism.crypto.EC +import io.iohk.atala.prism.crypto.MerkleInclusionProof import io.iohk.atala.prism.crypto.Sha256Digest import io.iohk.atala.prism.crypto.keys.ECKeyPair import io.iohk.atala.prism.identity.* @@ -21,9 +25,9 @@ import io.iohk.atala.prism.protos.* import io.ipfs.multibase.Base58 import kotlinx.coroutines.runBlocking import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString import kotlinx.serialization.json.* import pbandk.ByteArr -import pbandk.ExperimentalProtoJson import pbandk.json.encodeToJsonString class Dlt { @@ -457,7 +461,6 @@ class Dlt { return DltDidUpdate(issueCredentialsOperationId.hexValue(), issuerDid) } - /** * Revoke credential * @@ -495,4 +498,79 @@ class Dlt { credential.revoked = true return DltDidUpdate(revokeOperationId.hexValue(), issuerDid) } + + // TODO REFACTOR PENDING ON FUNCTIONS BELOW + + /** + * Verify issued credential + * + * @param wallet Wallet containing the credential + * @param credentialAlias Alias of Credential to verify + * @return Verification result + */ + // TODO: refactor to a single verifyCredential function + fun verifyIssuedCredential(wallet: Wallet, credentialAlias: String): List { + val credentials = wallet.issuedCredentials.filter { it.alias == credentialAlias } + if (credentials.isNotEmpty()) { + val credential = credentials[0] + val nodeAuthApi = NodeAuthApiImpl(GrpcConfig.options()) + val signed = JsonBasedCredential.fromString(credential.verifiedCredential.encodedSignedCredential) + // Use encodeDefaults to generate empty siblings field on proof + val format = Json { encodeDefaults = true } + val proof = MerkleInclusionProof.decode(format.encodeToString(credential.verifiedCredential.proof)) + + return runBlocking { + nodeAuthApi.verify(signed, proof).toMessageArray() + } + } else { + throw Exception("Credential '$credentialAlias' not found.") + } + } + + private fun VerificationResult.toMessageArray(): List { + val messages = mutableListOf() + for (message in this.verificationErrors) { + messages.add(message.errorMessage) + } + return messages + } + + /** + * Verify imported credential + * + * @param wallet Wallet containing the credential + * @param credentialAlias Alias of credential to verify + * @return Verification result + */ + // TODO: refactor to a single verifyCredential function + fun verifyImportedCredential(wallet: Wallet, credentialAlias: String): List { + val credentials = wallet.importedCredentials.filter { it.alias == credentialAlias } + if (credentials.isNotEmpty()) { + val credential = credentials[0] + val nodeAuthApi = NodeAuthApiImpl(GrpcConfig.options()) + val signed = JsonBasedCredential.fromString(credential.verifiedCredential.encodedSignedCredential) + // Use encodeDefaults to generate empty siblings field on proof + val format = Json { encodeDefaults = true } + val proof = MerkleInclusionProof.decode(format.encodeToString(credential.verifiedCredential.proof)) + + return runBlocking { + nodeAuthApi.verify(signed, proof).toMessageArray() + } + } else { + throw Exception("Credential '$credentialAlias' not found.") + } + } + + /** + * Grpc config + * Done this way to allow programmatic override of the grpc config + * @constructor Create empty Grpc config + */ + class GrpcConfig { + companion object { + var host: String = System.getenv("PRISM_NODE_HOST") ?: "" + var port: String = System.getenv("PRISM_NODE_PORT") ?: "50053" + fun options() = GrpcOptions("https", host, port.toInt()) + } + } } diff --git a/src/main/kotlin/com/rootsid/wal/library/wallet/WalletService.kt b/src/main/kotlin/com/rootsid/wal/library/wallet/WalletService.kt index 94196a4..0bf60c8 100644 --- a/src/main/kotlin/com/rootsid/wal/library/wallet/WalletService.kt +++ b/src/main/kotlin/com/rootsid/wal/library/wallet/WalletService.kt @@ -1,7 +1,7 @@ package com.rootsid.wal.library.wallet import com.rootsid.wal.library.Config -import com.rootsid.wal.library.Wallet +import com.rootsid.wal.library.wallet.model.Wallet import io.iohk.atala.prism.crypto.derivation.KeyDerivation import io.iohk.atala.prism.crypto.derivation.MnemonicCode import io.iohk.atala.prism.crypto.util.BytesOps diff --git a/src/main/kotlin/com/rootsid/wal/library/wallet/model/BlockchainTxLogEntry.kt b/src/main/kotlin/com/rootsid/wal/library/wallet/model/BlockchainTxLogEntry.kt new file mode 100644 index 0000000..6770bff --- /dev/null +++ b/src/main/kotlin/com/rootsid/wal/library/wallet/model/BlockchainTxLogEntry.kt @@ -0,0 +1,28 @@ +package com.rootsid.wal.library.wallet.model + +import kotlinx.serialization.Serializable + +/** + * Blockchain tx log + * + * @property txId transaction id + * @property action one of ADD_KEY, REVOKE_KEY, PUBLISH_DID, ISSUE_CREDENTIAL, REVOKE_CREDENTIAL + * @property url to open the transaction on a blockchain explorer + * @constructor Create empty Blockchain tx log + */ +@Serializable +data class BlockchainTxLogEntry( + val txId: String, + val action: BlockchainTxAction, + val url: String, + val description: String? +) + +// Enum for blockchain tx actions +enum class BlockchainTxAction { + ADD_KEY, + REVOKE_KEY, + PUBLISH_DID, + ISSUE_CREDENTIAL, + REVOKE_CREDENTIAL +} diff --git a/src/main/kotlin/com/rootsid/wal/library/wallet/model/Claim.kt b/src/main/kotlin/com/rootsid/wal/library/wallet/model/Claim.kt new file mode 100644 index 0000000..bd7467f --- /dev/null +++ b/src/main/kotlin/com/rootsid/wal/library/wallet/model/Claim.kt @@ -0,0 +1,32 @@ +package com.rootsid.wal.library.wallet.model + +import io.iohk.atala.prism.api.CredentialClaim +import io.iohk.atala.prism.identity.PrismDid +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.Serializable +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json + +/** + * Claim + * + * @property subjectDid + * @property content + * @constructor Create empty Claim + */ +@Serializable +data class Claim( + val subjectDid: String, + val content: String +) + +/** + * To credential claim + * + * Convert a Claim to PRISM CredentialClaim + */ +@OptIn(ExperimentalSerializationApi::class) +fun Claim.toCredentialClaim() = CredentialClaim( + PrismDid.fromString(this.subjectDid), + Json.decodeFromString(this.content) +) diff --git a/src/main/kotlin/com/rootsid/wal/library/wallet/model/ImportedCredential.kt b/src/main/kotlin/com/rootsid/wal/library/wallet/model/ImportedCredential.kt new file mode 100644 index 0000000..20ac70d --- /dev/null +++ b/src/main/kotlin/com/rootsid/wal/library/wallet/model/ImportedCredential.kt @@ -0,0 +1,17 @@ +package com.rootsid.wal.library.wallet.model + +import kotlinx.serialization.Serializable + +/** + * Imported credential + * + * @property alias + * @property verifiedCredential + * @constructor Create empty Imported credential + */ +@Serializable +data class ImportedCredential( + val alias: String, + // Signed VC and proof (This is the real VC) + var verifiedCredential: VerifiedCredential, +) diff --git a/src/main/kotlin/com/rootsid/wal/library/wallet/model/IssuedCredential.kt b/src/main/kotlin/com/rootsid/wal/library/wallet/model/IssuedCredential.kt new file mode 100644 index 0000000..a9ea3fe --- /dev/null +++ b/src/main/kotlin/com/rootsid/wal/library/wallet/model/IssuedCredential.kt @@ -0,0 +1,33 @@ +package com.rootsid.wal.library.wallet.model + +import kotlinx.serialization.Serializable + +/** + * Credential + * + * @property alias + * @property issuingDidAlias + * @property claim + * @property verifiedCredential + * @property batchId + * @property credentialHash + * @property operationHash + * @property revoked + * @constructor Create empty Credential + */ +@Serializable +data class IssuedCredential( + val alias: String, + var issuingDidAlias: String, + // Plain json claim + val claim: Claim, + // Signed VC and proof (This is the real VC) + var verifiedCredential: VerifiedCredential, + // Required for revocation + var batchId: String, + // Required for revocation + var credentialHash: String, + // Required for revocation + var operationHash: String, + var revoked: Boolean +) diff --git a/src/main/kotlin/com/rootsid/wal/library/wallet/model/Model.kt b/src/main/kotlin/com/rootsid/wal/library/wallet/model/Model.kt deleted file mode 100644 index 3fcd04f..0000000 --- a/src/main/kotlin/com/rootsid/wal/library/wallet/model/Model.kt +++ /dev/null @@ -1,180 +0,0 @@ -package com.rootsid.wal.library - -import com.rootsid.wal.library.prism.model.Did -import io.iohk.atala.prism.api.CredentialClaim -import io.iohk.atala.prism.identity.PrismDid -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.Serializable -import kotlinx.serialization.decodeFromString -import kotlinx.serialization.json.Json - -/** - * Wallet - * - * @property _id - * @property mnemonic - * @property passphrase - * @property dids - * @property importedCredentials - * @property issuedCredentials - * @constructor Create empty Wallet - */ -@Serializable -data class Wallet( - var _id: String, // name - val mnemonic: List, - val passphrase: String, - val seed: String, - var dids: MutableList = mutableListOf(), - // List of imported (Issued elsewhere) - var importedCredentials: MutableList = mutableListOf(), - // List of credentials issued by a DID from this wallet - var issuedCredentials: MutableList = mutableListOf(), - var blockchainTxLogEntry: MutableList = mutableListOf() -) - -/** - * Add blockchain tx log - * - * @param entry blockchain transaction log entry - */ -fun Wallet.addBlockchainTxLog(entry: BlockchainTxLogEntry) { - blockchainTxLogEntry.add(entry) -} - -/** - * Blockchain tx log - * - * @property txId transaction id - * @property action one of ADD_KEY, REVOKE_KEY, PUBLISH_DID, ISSUE_CREDENTIAL, REVOKE_CREDENTIAL - * @property url to open the transaction on a blockchain explorer - * @constructor Create empty Blockchain tx log - */ -@Serializable -data class BlockchainTxLogEntry( - val txId: String, - val action: BlockchainTxAction, - val url: String, - val description: String? -) - -// Enum for blockchain tx actions -enum class BlockchainTxAction { - ADD_KEY, - REVOKE_KEY, - PUBLISH_DID, - ISSUE_CREDENTIAL, - REVOKE_CREDENTIAL -} - -/** - * Verified credential - * - * @property encodedSignedCredential - * @property proof - * @constructor Create empty Verified credential - */ -@Serializable -data class VerifiedCredential( - val encodedSignedCredential: String, - val proof: Proof -) - -/** - * Proof - * - * @property hash - * @property index - * @property siblings - * @constructor Create empty Proof - */ -@Serializable -data class Proof( - var hash: String, - var index: Int, - var siblings: MutableList = mutableListOf() -) - -/** - * Claim - * - * @property subjectDid - * @property content - * @constructor Create empty Claim - */ -@Serializable -data class Claim( - val subjectDid: String, - val content: String -) - -/** - * To credential claim - * - * Convert a Claim to PRISM CredentialClaim - */ -@OptIn(ExperimentalSerializationApi::class) -fun Claim.toCredentialClaim() = CredentialClaim( - PrismDid.fromString(this.subjectDid), - Json.decodeFromString(this.content) -) - -/** - * Credential - * - * @property alias - * @property issuingDidAlias - * @property claim - * @property verifiedCredential - * @property batchId - * @property credentialHash - * @property operationHash - * @property revoked - * @constructor Create empty Credential - */ -@Serializable -data class IssuedCredential( - val alias: String, - var issuingDidAlias: String, - // Plain json claim - val claim: Claim, - // Signed VC and proof (This is the real VC) - var verifiedCredential: VerifiedCredential, - // Required for revocation - var batchId: String, - // Required for revocation - var credentialHash: String, - // Required for revocation - var operationHash: String, - var revoked: Boolean -) - -/** - * Imported credential - * - * @property alias - * @property verifiedCredential - * @constructor Create empty Imported credential - */ -@Serializable -data class ImportedCredential( - val alias: String, - // Signed VC and proof (This is the real VC) - var verifiedCredential: VerifiedCredential, -) - -/** - * Unpack result - * - * @property message - * @property from - * @property to - * @property res - * @constructor Create empty Unpack result - */ -data class UnpackResult( - val message: String, - val from: String?, - val to: String, - val res: org.didcommx.didcomm.model.UnpackResult -) diff --git a/src/main/kotlin/com/rootsid/wal/library/wallet/model/Proof.kt b/src/main/kotlin/com/rootsid/wal/library/wallet/model/Proof.kt new file mode 100644 index 0000000..622b8e9 --- /dev/null +++ b/src/main/kotlin/com/rootsid/wal/library/wallet/model/Proof.kt @@ -0,0 +1,18 @@ +package com.rootsid.wal.library.wallet.model + +import kotlinx.serialization.Serializable + +/** + * Proof + * + * @property hash + * @property index + * @property siblings + * @constructor Create empty Proof + */ +@Serializable +data class Proof( + var hash: String, + var index: Int, + var siblings: MutableList = mutableListOf() +) diff --git a/src/main/kotlin/com/rootsid/wal/library/wallet/model/VerifiedCredential.kt b/src/main/kotlin/com/rootsid/wal/library/wallet/model/VerifiedCredential.kt new file mode 100644 index 0000000..2b2d776 --- /dev/null +++ b/src/main/kotlin/com/rootsid/wal/library/wallet/model/VerifiedCredential.kt @@ -0,0 +1,16 @@ +package com.rootsid.wal.library.wallet.model + +import kotlinx.serialization.Serializable + +/** + * Verified credential + * + * @property encodedSignedCredential + * @property proof + * @constructor Create empty Verified credential + */ +@Serializable +data class VerifiedCredential( + val encodedSignedCredential: String, + val proof: Proof +) diff --git a/src/main/kotlin/com/rootsid/wal/library/wallet/model/Wallet.kt b/src/main/kotlin/com/rootsid/wal/library/wallet/model/Wallet.kt new file mode 100644 index 0000000..9882fec --- /dev/null +++ b/src/main/kotlin/com/rootsid/wal/library/wallet/model/Wallet.kt @@ -0,0 +1,38 @@ +package com.rootsid.wal.library.wallet.model + +import com.rootsid.wal.library.prism.model.Did +import kotlinx.serialization.Serializable + +/** + * Wallet + * + * @property _id + * @property mnemonic + * @property passphrase + * @property dids + * @property importedCredentials + * @property issuedCredentials + * @constructor Create empty Wallet + */ +@Serializable +data class Wallet( + var _id: String, // name + val mnemonic: List, + val passphrase: String, + val seed: String, + var dids: MutableList = mutableListOf(), + // List of imported (Issued elsewhere) + var importedCredentials: MutableList = mutableListOf(), + // List of credentials issued by a DID from this wallet + var issuedCredentials: MutableList = mutableListOf(), + var blockchainTxLogEntry: MutableList = mutableListOf() +) + +/** + * Add blockchain tx log + * + * @param entry blockchain transaction log entry + */ +fun Wallet.addBlockchainTxLog(entry: BlockchainTxLogEntry) { + blockchainTxLogEntry.add(entry) +} diff --git a/src/main/kotlin/com/rootsid/wal/library/wallet/storage/Storage.kt b/src/main/kotlin/com/rootsid/wal/library/wallet/storage/Storage.kt index d8c0072..17c37c0 100644 --- a/src/main/kotlin/com/rootsid/wal/library/wallet/storage/Storage.kt +++ b/src/main/kotlin/com/rootsid/wal/library/wallet/storage/Storage.kt @@ -1,6 +1,7 @@ package com.rootsid.wal.library import com.mongodb.client.MongoDatabase +import com.rootsid.wal.library.wallet.model.Wallet import org.litote.kmongo.* /**