Skip to content

Commit

Permalink
Merge pull request #78 from ergoplatform/develop
Browse files Browse the repository at this point in the history
Version 1.5.2203
  • Loading branch information
MrStahlfelge authored Jan 15, 2022
2 parents a1f09c3 + aba4294 commit 77162af
Show file tree
Hide file tree
Showing 48 changed files with 1,257 additions and 417 deletions.
4 changes: 2 additions & 2 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ android {
applicationId "org.ergoplatform.android"
minSdkVersion 24
targetSdkVersion 30
versionCode 2201
versionName "1.4.2201"
versionCode 2203
versionName "1.5.2203"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class SettingsFragment : Fragment() {
_binding = FragmentSettingsBinding.inflate(inflater, container, false)

binding.labelVersion.text = BuildConfig.VERSION_NAME
binding.labelBuildBy.text = getString(R.string.desc_about, getString(R.string.about_year))

return binding.root
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import org.ergoplatform.android.databinding.EntryWalletTokenBinding
import org.ergoplatform.android.databinding.FragmentColdWalletSigningBinding
import org.ergoplatform.android.ui.*
import org.ergoplatform.explorer.client.model.AssetInstanceInfo
import org.ergoplatform.transactions.QR_DATA_LENGTH_LIMIT
import org.ergoplatform.transactions.QR_DATA_LENGTH_LOW_RES
import org.ergoplatform.transactions.coldSigningResponseToQrChunks
import org.ergoplatform.transactions.reduceBoxes

/**
Expand All @@ -30,6 +33,8 @@ class ColdWalletSigningFragment : AbstractAuthenticationFragment() {

private val args: ColdWalletSigningFragmentArgs by navArgs()

private var scaleDown = false

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
Expand All @@ -40,54 +45,16 @@ class ColdWalletSigningFragment : AbstractAuthenticationFragment() {

private val viewModel: ColdWalletSigningViewModel
get() {
val viewModel = ViewModelProvider(this).get(ColdWalletSigningViewModel::class.java)
return viewModel
return ViewModelProvider(this).get(ColdWalletSigningViewModel::class.java)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val viewModel = viewModel

args.qrCode?.let { viewModel.addQrCodeChunk(it) }
addQrCodeChunk(args.qrCode)
viewModel.setWalletId(args.walletId, requireContext())

viewModel.transactionInfo.observe(viewLifecycleOwner, {
// don't show transaction info when we already have a signing result
if (viewModel.signedQrCode != null)
return@observe

if (it == null) {
// refresh information on scanned codes
binding.labelScannedPages.text = getString(
R.string.label_qr_pages_info,
viewModel.pagesAdded.toString(),
viewModel.pagesQrCode.toString()
)
binding.cardScanMore.visibility = View.VISIBLE
}

it?.reduceBoxes()?.let {
binding.transactionInfo.visibility = View.VISIBLE
binding.cardScanMore.visibility = View.GONE

binding.layoutInboxes.apply {
removeAllViews()

it.inputs.forEach { input ->
bindBoxView(this, input.value, input.address ?: input.boxId, input.assets)
}
}

binding.layoutOutboxes.apply {
removeAllViews()

it.outputs.forEach { output ->
bindBoxView(this, output.value, output.address, output.assets)
}
}
}
})

viewModel.lockInterface.observe(viewLifecycleOwner, {
if (it)
ProgressBottomSheetDialogFragment.showProgressDialog(childFragmentManager)
Expand All @@ -101,8 +68,9 @@ class ColdWalletSigningFragment : AbstractAuthenticationFragment() {
binding.cardSigningResult.visibility = View.VISIBLE
binding.cardScanMore.visibility = View.GONE

binding.qrCodePager.adapter = QrPagerAdapter(viewModel.signedQrCode!!)
refreshButtonState()
binding.switchResolution.visibility =
if (viewModel.signedQrCode!!.length > QR_DATA_LENGTH_LOW_RES) View.VISIBLE else View.GONE
setQrData()

} else {
binding.cardSigningResult.visibility = View.GONE
Expand Down Expand Up @@ -136,6 +104,11 @@ class ColdWalletSigningFragment : AbstractAuthenticationFragment() {
binding.qrCodePager.currentItem = binding.qrCodePager.currentItem + 1
}

binding.switchResolution.setOnClickListener {
scaleDown = !scaleDown
setQrData()
}

binding.buttonDismiss.setOnClickListener {
findNavController().popBackStack()
}
Expand All @@ -153,6 +126,63 @@ class ColdWalletSigningFragment : AbstractAuthenticationFragment() {
})
}

private fun setQrData() {
viewModel.signedQrCode?.let {
binding.qrCodePager.adapter = QrPagerAdapter(
coldSigningResponseToQrChunks(
it,
if (scaleDown) QR_DATA_LENGTH_LOW_RES else QR_DATA_LENGTH_LIMIT
)
)
refreshButtonState()
}
}

private fun addQrCodeChunk(qrCode: String?) {
qrCode?.let { viewModel.uiLogic.addQrCodeChunk(qrCode) }

val transactionInfo = viewModel.uiLogic.transactionInfo

// don't show transaction info when we already have a signing result
if (viewModel.signedQrCode != null)
return

if (transactionInfo == null) {
// refresh information on scanned codes
binding.labelScannedPages.text = getString(
R.string.label_qr_pages_info,
viewModel.uiLogic.qrPagesCollector.pagesAdded.toString(),
viewModel.uiLogic.qrPagesCollector.pagesCount.toString()
)
binding.cardScanMore.visibility = View.VISIBLE
val errorMessage = viewModel.uiLogic.lastErrorMessage
binding.labelErrorMessage.visibility =
if (errorMessage.isNullOrBlank()) View.GONE else View.VISIBLE
binding.labelErrorMessage.text = errorMessage
}

transactionInfo?.reduceBoxes()?.let {
binding.transactionInfo.visibility = View.VISIBLE
binding.cardScanMore.visibility = View.GONE

binding.layoutInboxes.apply {
removeAllViews()

it.inputs.forEach { input ->
bindBoxView(this, input.value, input.address ?: input.boxId, input.assets)
}
}

binding.layoutOutboxes.apply {
removeAllViews()

it.outputs.forEach { output ->
bindBoxView(this, output.value, output.address, output.assets)
}
}
}
}

private fun refreshButtonState() {
val lastPage =
binding.qrCodePager.currentItem + 1 == binding.qrCodePager.adapter!!.itemCount
Expand Down Expand Up @@ -210,7 +240,7 @@ class ColdWalletSigningFragment : AbstractAuthenticationFragment() {
val result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data)
if (result != null) {
result.contents?.let {
viewModel.addQrCodeChunk(it)
addQrCodeChunk(it)
}
} else {
super.onActivityResult(requestCode, resultCode, data)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,82 +5,29 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.CoroutineScope
import org.ergoplatform.android.AppDatabase
import org.ergoplatform.deserializeSecrets
import org.ergoplatform.signSerializedErgoTx
import org.ergoplatform.android.RoomWalletDbProvider
import org.ergoplatform.api.AesEncryptionManager
import org.ergoplatform.api.AndroidEncryptionManager
import org.ergoplatform.explorer.client.model.TransactionInfo
import org.ergoplatform.persistance.Wallet
import org.ergoplatform.transactions.PromptSigningResult
import org.ergoplatform.deserializeSecrets
import org.ergoplatform.transactions.SigningResult
import org.ergoplatform.uilogic.StringProvider
import org.ergoplatform.wallet.getSortedDerivedAddressesList
import org.ergoplatform.uilogic.transactions.ColdWalletSigningUiLogic

class ColdWalletSigningViewModel : ViewModel() {

var pagesQrCode = 0
val pagesAdded get() = qrCodeChunks.size
val qrCodeChunks = HashMap<Int, String>()
var signedQrCode: List<String>? = null
private set
private var signingRequest: PromptSigningResult? = null
private val _transactionInfo = MutableLiveData<TransactionInfo?>()
val transactionInfo: LiveData<TransactionInfo?> = _transactionInfo
private val _lockInterface = MutableLiveData<Boolean>()
val lockInterface: LiveData<Boolean> = _lockInterface
private val _signingResult = MutableLiveData<SigningResult?>()
val signingResult: LiveData<SigningResult?> = _signingResult
var wallet: Wallet? = null

fun addQrCodeChunk(qrCodeChunk: String): Boolean {

// qr code not fitting, no qr code chunk, or we are already done? => don't add
if (transactionInfo.value != null || !isColdSigningRequestChunk(qrCodeChunk)) {
return false
}

val page = getQrChunkIndex(qrCodeChunk)
val count = getQrChunkPagesCount(qrCodeChunk)

if (pagesQrCode != 0 && count != pagesQrCode) {
return false
}

qrCodeChunks.put(page, qrCodeChunk)
pagesQrCode = count

val ti = buildRequestWhenApplicable()
_transactionInfo.postValue(ti)

return true
}

private fun buildRequestWhenApplicable(): TransactionInfo? {
if (pagesAdded == pagesQrCode) {
try {
val sr = coldSigningRequestFromQrChunks(qrCodeChunks.values)
signingRequest = sr
return buildTransactionInfoFromReduced(
sr.serializedTx!!,
sr.serializedInputs
)
} catch (t: Throwable) {

}
}

return null
}
val uiLogic = AndroidColdWalletSigningUiLogic()
val wallet get() = uiLogic.wallet
val signedQrCode get() = uiLogic.signedQrCode

fun setWalletId(walletId: Int, ctx: Context) {
viewModelScope.launch {
wallet =
AppDatabase.getInstance(ctx).walletDao().loadWalletWithStateById(walletId)?.toModel()
}
uiLogic.setWalletId(walletId, RoomWalletDbProvider(AppDatabase.getInstance(ctx)))
}

fun signTxWithPassword(password: String, texts: StringProvider): Boolean {
Expand All @@ -99,7 +46,7 @@ class ColdWalletSigningViewModel : ViewModel() {
return false
}

signTxWithMnemonicAsync(mnemonic, texts)
uiLogic.signTxWithMnemonicAsync(mnemonic, texts)

return true
}
Expand All @@ -116,36 +63,22 @@ class ColdWalletSigningViewModel : ViewModel() {
val decryptData = AndroidEncryptionManager.decryptDataWithDeviceKey(it)
mnemonic = deserializeSecrets(String(decryptData!!))

signTxWithMnemonicAsync(mnemonic!!, texts)
uiLogic.signTxWithMnemonicAsync(mnemonic!!, texts)

}
}

private fun signTxWithMnemonicAsync(mnemonic: String, texts: StringProvider) {
signingRequest?.let { signingRequest ->
val derivedAddresses =
wallet!!.getSortedDerivedAddressesList().map { it.derivationIndex }

viewModelScope.launch {
val ergoTxResult: SigningResult
withContext(Dispatchers.IO) {
ergoTxResult = signSerializedErgoTx(
signingRequest.serializedTx!!, mnemonic, "",
derivedAddresses, texts
)
signedQrCode = buildColdSigningResponse(ergoTxResult)?.let {
coldSigningResponseToQrChunks(
it,
QR_SIZE_LIMIT
)
}
}
_lockInterface.postValue(false)

_signingResult.postValue(ergoTxResult)
}
inner class AndroidColdWalletSigningUiLogic : ColdWalletSigningUiLogic() {
override val coroutineScope: CoroutineScope
get() = viewModelScope

_lockInterface.postValue(true)
override fun notifyUiLocked(locked: Boolean) {
_lockInterface.postValue(locked)
}

override fun notifySigningResult(ergoTxResult: SigningResult) {
_signingResult.postValue(ergoTxResult)
}

}
}
Loading

0 comments on commit 77162af

Please sign in to comment.