diff --git a/backend-lib/src/main/java/cash/z/ecc/android/sdk/internal/Backend.kt b/backend-lib/src/main/java/cash/z/ecc/android/sdk/internal/Backend.kt index a008079a7..cbe17c7cf 100644 --- a/backend-lib/src/main/java/cash/z/ecc/android/sdk/internal/Backend.kt +++ b/backend-lib/src/main/java/cash/z/ecc/android/sdk/internal/Backend.kt @@ -85,7 +85,7 @@ interface Backend { */ @Throws(RuntimeException::class) suspend fun createAccount( - accountName: String, + accountName: String?, keySource: String?, seed: ByteArray, treeState: ByteArray, diff --git a/backend-lib/src/main/java/cash/z/ecc/android/sdk/internal/jni/RustBackend.kt b/backend-lib/src/main/java/cash/z/ecc/android/sdk/internal/jni/RustBackend.kt index 76da5f00a..d39ea2cdc 100644 --- a/backend-lib/src/main/java/cash/z/ecc/android/sdk/internal/jni/RustBackend.kt +++ b/backend-lib/src/main/java/cash/z/ecc/android/sdk/internal/jni/RustBackend.kt @@ -90,7 +90,7 @@ class RustBackend private constructor( } override suspend fun createAccount( - accountName: String, + accountName: String?, keySource: String?, seed: ByteArray, treeState: ByteArray, @@ -521,7 +521,7 @@ class RustBackend private constructor( private external fun createAccount( dbDataPath: String, networkId: Int, - accountName: String, + accountName: String?, keySource: String?, seed: ByteArray, treeState: ByteArray, diff --git a/sdk-lib/src/androidTest/java/cash/z/ecc/fixture/FakeRustBackend.kt b/sdk-lib/src/androidTest/java/cash/z/ecc/fixture/FakeRustBackend.kt index a5c25b524..e1a86d5e5 100644 --- a/sdk-lib/src/androidTest/java/cash/z/ecc/fixture/FakeRustBackend.kt +++ b/sdk-lib/src/androidTest/java/cash/z/ecc/fixture/FakeRustBackend.kt @@ -136,6 +136,8 @@ internal class FakeRustBackend( } override suspend fun createAccount( + accountName: String, + keySource: String?, seed: ByteArray, treeState: ByteArray, recoverUntil: Long? diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/SdkSynchronizer.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/SdkSynchronizer.kt index e4cde8496..ac8c7e163 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/SdkSynchronizer.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/SdkSynchronizer.kt @@ -644,12 +644,16 @@ class SdkSynchronizer private constructor( // Not ready to be a public API; internal for testing only internal suspend fun createAccount( + accountName: String, + keySource: String?, + recoverUntil: BlockHeight?, seed: ByteArray, treeState: TreeState, - recoverUntil: BlockHeight? ): UnifiedSpendingKey { return runCatching { backend.createAccountAndGetSpendingKey( + accountName = accountName, + keySource = keySource, seed = seed, treeState = treeState, recoverUntil = recoverUntil @@ -990,6 +994,8 @@ internal object DefaultSynchronizerFactory { @Suppress("LongParameterList") internal suspend fun defaultDerivedDataRepository( + accountName: String?, + keySource: String?, context: Context, rustBackend: TypesafeBackend, databaseFile: File, @@ -1000,13 +1006,15 @@ internal object DefaultSynchronizerFactory { ): DerivedDataRepository = DbDerivedDataRepository( DerivedDataDb.new( + accountName, context, rustBackend, databaseFile, checkpoint, - seed, + keySource, numberOfAccounts, - recoverUntil + recoverUntil, + seed, ) ) diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/Synchronizer.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/Synchronizer.kt index 163e0742d..0186f7c97 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/Synchronizer.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/Synchronizer.kt @@ -549,6 +549,12 @@ interface Synchronizer { /** * Primary method that SDK clients will use to construct a synchronizer. * + * @param accountName Optional account name that will be created as part of the new wallet setup process based + * on the given seed + * + * @param keySource Optional key source that will be persisted alongside the account created in the new + * wallet setup process based on the given seed + * * @param zcashNetwork the network to use. * * @param alias A string used to segregate multiple wallets in the filesystem. This implies the string @@ -585,13 +591,15 @@ interface Synchronizer { */ @Suppress("LongParameterList", "LongMethod") suspend fun new( - context: Context, - zcashNetwork: ZcashNetwork, + accountName: String?, alias: String = ZcashSdk.DEFAULT_ALIAS, + birthday: BlockHeight?, + context: Context, + keySource: String?, lightWalletEndpoint: LightWalletEndpoint, seed: ByteArray?, - birthday: BlockHeight?, - walletInitMode: WalletInitMode + walletInitMode: WalletInitMode, + zcashNetwork: ZcashNetwork, ): CloseableSynchronizer { val applicationContext = context.applicationContext @@ -648,10 +656,12 @@ interface Synchronizer { val repository = DefaultSynchronizerFactory.defaultDerivedDataRepository( + accountName = accountName, context = applicationContext, rustBackend = backend, databaseFile = coordinator.dataDbFile(zcashNetwork, alias), checkpoint = loadedCheckpoint, + keySource = keySource, seed = seed, numberOfAccounts = Derivation.DEFAULT_NUMBER_OF_ACCOUNTS, recoverUntil = chainTip, @@ -696,16 +706,28 @@ interface Synchronizer { @JvmStatic @Suppress("LongParameterList") fun newBlocking( - context: Context, - zcashNetwork: ZcashNetwork, + accountName: String?, alias: String = ZcashSdk.DEFAULT_ALIAS, + birthday: BlockHeight?, + context: Context, + keySource: String?, lightWalletEndpoint: LightWalletEndpoint, seed: ByteArray?, - birthday: BlockHeight?, - walletInitMode: WalletInitMode + walletInitMode: WalletInitMode, + zcashNetwork: ZcashNetwork, ): CloseableSynchronizer = runBlocking { - new(context, zcashNetwork, alias, lightWalletEndpoint, seed, birthday, walletInitMode) + new( + accountName = accountName, + alias = alias, + birthday = birthday, + context = context, + keySource = keySource, + lightWalletEndpoint = lightWalletEndpoint, + seed = seed, + walletInitMode = walletInitMode, + zcashNetwork = zcashNetwork, + ) } /** diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/fixture/AccountFixture.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/fixture/AccountFixture.kt index 6f3799ba0..4dd85e07b 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/fixture/AccountFixture.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/fixture/AccountFixture.kt @@ -15,9 +15,9 @@ object AccountFixture { val ACCOUNT_UUID = UUID.fromString("01234567-89ab-cdef-0123-456789abcdef") const val ZIP_32_ACCOUNT_INDEX = 0 - fun new(accountId: Int = ZIP_32_ACCOUNT_INDEX) = + fun new(accountId: UUID = ACCOUNT_UUID) = Account( - value = accountId + accountUuid = accountId.toByteArray() ) } diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackend.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackend.kt index 23d3bb38c..863cf8b98 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackend.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackend.kt @@ -27,7 +27,7 @@ internal interface TypesafeBackend { suspend fun getAccounts(): List suspend fun createAccountAndGetSpendingKey( - accountName: String, + accountName: String?, keySource: String?, seed: ByteArray, treeState: TreeState, diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackendImpl.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackendImpl.kt index 1a49379a3..34db1b38b 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackendImpl.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/TypesafeBackendImpl.kt @@ -30,7 +30,7 @@ internal class TypesafeBackendImpl(private val backend: Backend) : TypesafeBacke override suspend fun getAccounts(): List = backend.getAccounts().map { Account(it.accountUuid) } override suspend fun createAccountAndGetSpendingKey( - accountName: String, + accountName: String?, keySource: String?, seed: ByteArray, treeState: TreeState, diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/db/derived/DerivedDataDb.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/db/derived/DerivedDataDb.kt index 93fa14ede..d47ca513c 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/db/derived/DerivedDataDb.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/db/derived/DerivedDataDb.kt @@ -38,13 +38,15 @@ internal class DerivedDataDb private constructor( @Suppress("LongParameterList") suspend fun new( + accountName: String?, context: Context, backend: TypesafeBackend, databaseFile: File, checkpoint: Checkpoint, - seed: ByteArray?, + keySource: String?, numberOfAccounts: Int, - recoverUntil: BlockHeight? + recoverUntil: BlockHeight?, + seed: ByteArray?, ): DerivedDataDb { backend.initDataDb(seed) @@ -69,9 +71,11 @@ internal class DerivedDataDb private constructor( repeat(missingAccounts) { runCatching { backend.createAccountAndGetSpendingKey( + accountName = accountName, + keySource = keySource, + recoverUntil = recoverUntil, seed = checkedSeed, treeState = checkpoint.treeState(), - recoverUntil = recoverUntil ) }.onFailure { Twig.error(it) { "Create account failed." } diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/db/derived/TxOutputsView.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/db/derived/TxOutputsView.kt index a116621e6..42d4a1e49 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/db/derived/TxOutputsView.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/internal/db/derived/TxOutputsView.kt @@ -26,7 +26,7 @@ internal class TxOutputsView(private val sqliteDatabase: SupportSQLiteDatabase) private val PROJECTION_RECIPIENT = arrayOf( TxOutputsViewDefinition.COLUMN_STRING_TO_ADDRESS, - TxOutputsViewDefinition.COLUMN_INTEGER_TO_ACCOUNT + TxOutputsViewDefinition.COLUMN_BLOB_TO_ACCOUNT ) private val SELECT_BY_TRANSACTION_ID_AND_NOT_CHANGE = @@ -66,15 +66,13 @@ internal class TxOutputsView(private val sqliteDatabase: SupportSQLiteDatabase) selectionArgs = arrayOf(transactionId.byteArray), orderBy = ORDER_BY, cursorParser = { - val toAccountIndex = it.getColumnIndex(TxOutputsViewDefinition.COLUMN_INTEGER_TO_ACCOUNT) + val toAccountIndex = it.getColumnIndex(TxOutputsViewDefinition.COLUMN_BLOB_TO_ACCOUNT) val toAddressIndex = it.getColumnIndex(TxOutputsViewDefinition.COLUMN_STRING_TO_ADDRESS) if (!it.isNull(toAccountIndex)) { - // TODO [#1644]: Refactor Account ZIP32 index across SDK - // TODO [#1644]: https://github.com/Electric-Coin-Company/zcash-android-wallet-sdk/issues/1644 - TransactionRecipient.RecipientAccount(it.getInt(toAccountIndex)) + TransactionRecipient.RecipientAccount(accountUuid = it.getBlob(toAccountIndex)) } else { - TransactionRecipient.RecipientAddress(it.getString(toAddressIndex)) + TransactionRecipient.RecipientAddress(addressValue = it.getString(toAddressIndex)) } } ) @@ -93,7 +91,7 @@ internal object TxOutputsViewDefinition { const val COLUMN_STRING_TO_ADDRESS = "to_address" // $NON-NLS - const val COLUMN_INTEGER_TO_ACCOUNT = "to_account_id" // $NON-NLS + const val COLUMN_BLOB_TO_ACCOUNT = "to_account_uuid" // $NON-NLS const val COLUMN_INTEGER_VALUE = "value" // $NON-NLS diff --git a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/model/PendingTransaction.kt b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/model/PendingTransaction.kt index 7c159bf2c..19ccf391a 100644 --- a/sdk-lib/src/main/java/cash/z/ecc/android/sdk/model/PendingTransaction.kt +++ b/sdk-lib/src/main/java/cash/z/ecc/android/sdk/model/PendingTransaction.kt @@ -28,11 +28,11 @@ data class PendingTransaction internal constructor( sealed class TransactionRecipient { data class RecipientAddress(val addressValue: String) : TransactionRecipient() { - override fun toString() = "TransactionRecipient.Address" + override fun toString() = "TransactionRecipient.RecipientAddress" } - data class RecipientAccount(val accountValue: cash.z.ecc.android.sdk.model.Account) : TransactionRecipient() { - override fun toString() = "TransactionRecipient.Account" + data class RecipientAccount(val accountUuid: ByteArray) : TransactionRecipient() { + override fun toString() = "TransactionRecipient.RecipientAccount" } companion object