feat(multi-account): extract SignerType, AccountInfo, AccountStorage to commons
Phase 1 of multi-account support. Move account types to commons/commonMain so both Android and Desktop share the same data model: - SignerType sealed class (Internal, Remote, ViewOnly) - AccountInfo data class (npub, signerType, isTransient) - AccountStorage interface (loadAccounts, saveAccount, etc.) Desktop AccountManager now imports SignerType from commons instead of defining its own. All existing tests updated with new import path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.commons.model.account
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
/**
|
||||
* Lightweight account metadata for account listing and switching.
|
||||
* Does NOT contain private keys — those are stored in SecureKeyStorage.
|
||||
*/
|
||||
@Immutable
|
||||
data class AccountInfo(
|
||||
val npub: String,
|
||||
val signerType: SignerType,
|
||||
val isTransient: Boolean = false,
|
||||
)
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.commons.model.account
|
||||
|
||||
/**
|
||||
* Platform-agnostic interface for persisting account metadata.
|
||||
* Implementations:
|
||||
* - Android: LocalPreferences (EncryptedSharedPreferences)
|
||||
* - Desktop: DesktopAccountStorage (encrypted JSON file)
|
||||
*
|
||||
* Does NOT handle private key storage — that's SecureKeyStorage's job.
|
||||
* Constructor-injected, not expect/actual.
|
||||
*/
|
||||
interface AccountStorage {
|
||||
/** Load all saved account metadata */
|
||||
suspend fun loadAccounts(): List<AccountInfo>
|
||||
|
||||
/** Save or update account metadata */
|
||||
suspend fun saveAccount(info: AccountInfo)
|
||||
|
||||
/** Delete account metadata by npub */
|
||||
suspend fun deleteAccount(npub: String)
|
||||
|
||||
/** Get the npub of the currently active account, or null if none */
|
||||
suspend fun currentAccount(): String?
|
||||
|
||||
/** Set which account is currently active */
|
||||
suspend fun setCurrentAccount(npub: String)
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.commons.model.account
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
/**
|
||||
* Represents how an account's signing is handled.
|
||||
* Sealed class (not enum) because Remote carries additional data.
|
||||
*/
|
||||
@Immutable
|
||||
sealed class SignerType {
|
||||
/** Account has a local private key (nsec) */
|
||||
data object Internal : SignerType()
|
||||
|
||||
/** Account uses a NIP-46 remote signer (bunker) */
|
||||
@Immutable
|
||||
data class Remote(
|
||||
val bunkerUri: String,
|
||||
) : SignerType()
|
||||
|
||||
/** Account is view-only (npub only, no signing capability) */
|
||||
data object ViewOnly : SignerType()
|
||||
}
|
||||
Reference in New Issue
Block a user