bitsy-wallet/app/src/main/java/cy/agorise/bitsybitshareswallet/fragments/BaseAccountFragment.kt

127 lines
5.0 KiB
Kotlin

package cy.agorise.bitsybitshareswallet.fragments
import androidx.core.content.edit
import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.activities.ConnectedActivity
import cy.agorise.bitsybitshareswallet.database.entities.Authority
import cy.agorise.bitsybitshareswallet.repositories.AuthorityRepository
import cy.agorise.bitsybitshareswallet.repositories.UserAccountRepository
import cy.agorise.bitsybitshareswallet.utils.Constants
import cy.agorise.bitsybitshareswallet.utils.CryptoUtils
import cy.agorise.graphenej.AuthorityType
import cy.agorise.graphenej.BrainKey
import cy.agorise.graphenej.PublicKey
import cy.agorise.graphenej.models.AccountProperties
import org.bitcoinj.core.ECKey
abstract class BaseAccountFragment : ConnectedFragment() {
/** Private variable that will hold an instance of the [BrainKey] class */
protected var mBrainKey: BrainKey? = null
/**
* Method called internally once an account has been detected. This method will store internally
* the following details:
*
* - Account name in the database
* - Account authorities in the database
* - The current account id in the shared preferences
*
* @param accountProperties Account properties object
*/
protected fun onAccountSelected(accountProperties: AccountProperties, pin: String) {
val salt = CryptoUtils.generateSalt()
val hashedPIN = CryptoUtils.createSHA256Hash(salt + pin)
// Stores the user selected PIN, hashed
PreferenceManager.getDefaultSharedPreferences(requireContext()).edit {
putString(Constants.KEY_HASHED_PIN_PATTERN, hashedPIN)
putString(Constants.KEY_PIN_PATTERN_SALT, salt)
putInt(Constants.KEY_SECURITY_LOCK_SELECTED, 1) // 1 -> PIN
}
// Stores the accounts this key refers to
val id = accountProperties.id
val name = accountProperties.name
val isLTM =
accountProperties.membership_expiration_date == Constants.LIFETIME_EXPIRATION_DATE
val userAccount =
cy.agorise.bitsybitshareswallet.database.entities.UserAccount(id, name, isLTM)
val userAccountRepository = UserAccountRepository(requireContext().applicationContext)
userAccountRepository.insert(userAccount)
// Stores the id of the currently active user account
PreferenceManager.getDefaultSharedPreferences(requireContext()).edit()
.putString(Constants.KEY_CURRENT_ACCOUNT_ID, accountProperties.id).apply()
// Trying to store all possible authorities (owner, active and memo) into the database
val ownerAuthority = accountProperties.owner
val activeAuthority = accountProperties.active
val options = accountProperties.options
for (i in 0..2) {
mBrainKey!!.sequenceNumber = i
val publicKey = PublicKey(ECKey.fromPublicOnly(mBrainKey!!.privateKey.pubKey))
if (ownerAuthority.keyAuths.keys.contains(publicKey)) {
addAuthorityToDatabase(
accountProperties.id,
AuthorityType.OWNER.ordinal,
mBrainKey!!
)
}
if (activeAuthority.keyAuths.keys.contains(publicKey)) {
addAuthorityToDatabase(
accountProperties.id,
AuthorityType.ACTIVE.ordinal,
mBrainKey!!
)
}
if (options.memoKey == publicKey) {
addAuthorityToDatabase(
accountProperties.id,
AuthorityType.MEMO.ordinal,
mBrainKey!!
)
}
}
// Force [ConnectedActivity] to refresh the userId from the SharedPreferences, so that the app can immediately
// to fetch the account's transactions.
(activity as ConnectedActivity).getUserAccount()
// Send the user back to HomeFragment
findNavController().navigate(R.id.home_action)
}
/**
* Adds the given BrainKey encrypted as AuthorityType of userId.
*/
private fun addAuthorityToDatabase(userId: String, authorityType: Int, brainKey: BrainKey) {
val brainKeyWords = brainKey.brainKey
val wif = brainKey.walletImportFormat
val sequenceNumber = brainKey.sequenceNumber
val encryptedBrainKey = CryptoUtils.encrypt(requireContext(), brainKeyWords)
val encryptedSequenceNumber =
CryptoUtils.encrypt(requireContext(), sequenceNumber.toString())
val encryptedWIF = CryptoUtils.encrypt(requireContext(), wif)
val authority = Authority(
0,
userId,
authorityType,
encryptedWIF,
encryptedBrainKey,
encryptedSequenceNumber
)
val authorityRepository = AuthorityRepository(requireContext())
authorityRepository.insert(authority)
}
}