Skip to content

Commit

Permalink
Merge pull request #73 from ergoplatform/develop
Browse files Browse the repository at this point in the history
Build 2201
  • Loading branch information
MrStahlfelge authored Jan 6, 2022
2 parents d94e5ce + 22834f2 commit a1f09c3
Show file tree
Hide file tree
Showing 81 changed files with 3,069 additions and 462 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ jobs:
run: chmod +x gradlew
- name: Setup Android build environment
uses: android-actions/[email protected]
- name: Generate debug keystore
run: keytool -genkey -v -keystore debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000 -dname "C=US, O=Android, CN=Android Debug"
- name: Move debug keystore
run: mkdir ~/.android
- name: Move debug keystore
run: mv debug.keystore ~/.android/debug.keystore
- name: Build Android debug apks
run: ./gradlew clean android:assembleDebug
- name: Release mainnet artifact
Expand Down
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 2120
versionName "1.4.2120"
versionCode 2201
versionName "1.4.2201"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down
25 changes: 23 additions & 2 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,33 @@
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<nav-graph android:value="@navigation/mobile_navigation" />
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- URI schemes not supported by nav component at the moment (2.3.5) -->
<!-- PaymentRequest.PAYMENT_URI_SCHEME -->
<data android:scheme="ergoplatform" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<!-- PaymentRequest.explorerPaymentUrlPrefix -->
<data android:scheme="http" />
<data android:scheme="https" />
<data android:path="/payment-request" />
<data android:host="explorer.ergoplatform.com" />
</intent-filter>
</activity>

<activity
Expand Down
25 changes: 25 additions & 0 deletions android/src/main/java/org/ergoplatform/android/AppDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.room.withTransaction
import androidx.sqlite.db.SupportSQLiteDatabase
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import org.ergoplatform.android.wallet.*
import org.ergoplatform.persistance.*

Expand Down Expand Up @@ -97,15 +99,38 @@ class RoomWalletDbProvider(val database: AppDatabase) : WalletDbProvider {
return database.walletDao().loadWalletWithStateById(id)?.toModel()
}

override suspend fun walletWithStateByIdAsFlow(id: Int): Flow<Wallet?> {
return database.walletDao().walletWithStateByIdAsFlow(id).map { it?.toModel() }
}

override suspend fun insertWalletStates(walletStates: List<WalletState>) {
database.walletDao()
.insertWalletStates(*(walletStates.map { it.toDbEntity() }.toTypedArray()))
}

override suspend fun deleteAddressState(publicAddress: String) {
database.walletDao().deleteAddressState(publicAddress)
}

override suspend fun loadWalletAddresses(firstAddress: String): List<WalletAddress> {
return database.walletDao().loadWalletAddresses(firstAddress).map { it.toModel() }
}

override suspend fun loadWalletAddress(id: Long): WalletAddress? {
return database.walletDao().loadWalletAddress(id.toInt())?.toModel()
}

override suspend fun insertWalletAddress(walletAddress: WalletAddress) {
database.walletDao().insertWalletAddress(walletAddress.toDbEntity())
}

override suspend fun updateWalletAddressLabel(addrId: Long, newLabel: String?) {
database.walletDao().updateWalletAddressLabel(addrId.toInt(), newLabel)
}

override suspend fun deleteWalletAddress(addrId: Long) {
database.walletDao().deleteWalletAddress(addrId.toInt())
}

override suspend fun deleteTokensByAddress(publicAddress: String) {
database.walletDao().deleteTokensByAddress(publicAddress)
Expand Down
16 changes: 15 additions & 1 deletion android/src/main/java/org/ergoplatform/android/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import android.content.Intent
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.NavController
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.google.android.material.bottomnavigation.BottomNavigationView
import net.yslibrary.android.keyboardvisibilityevent.KeyboardVisibilityEvent
import org.ergoplatform.isPaymentRequestUrl

class MainActivity : AppCompatActivity() {

Expand All @@ -33,6 +35,18 @@ class MainActivity : AppCompatActivity() {
KeyboardVisibilityEvent.registerEventListener(this, { isOpen ->
navView.visibility = if (isOpen) View.GONE else View.VISIBLE
})

if (savedInstanceState == null) {
handleIntent(navController)
}
}

private fun handleIntent(navController: NavController) {
intent.dataString?.let {
if (isPaymentRequestUrl(it)) {
navController.navigate(R.id.chooseSpendingWalletFragmentDialog)
}
}
}

override fun onSupportNavigateUp(): Boolean {
Expand All @@ -41,6 +55,6 @@ class MainActivity : AppCompatActivity() {

override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
findNavController(R.id.nav_host_fragment).handleDeepLink(intent)
handleIntent(findNavController(R.id.nav_host_fragment))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class DisplayCurrencyListDialogFragment : BottomSheetDialogFragment() {

private fun onChooseCurrency(currency: String) {
Preferences(requireContext()).prefDisplayCurrency = currency
NodeConnector.getInstance().invalidateCache()
NodeConnector.getInstance().invalidateCache(resetFiatValue = true)
(parentFragment as? SettingsFragment)?.showDisplayCurrency()
dismiss()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import org.ergoplatform.android.ui.AndroidStringProvider
import org.ergoplatform.android.ui.enableLinks
import org.ergoplatform.android.ui.navigateSafe
import org.ergoplatform.android.ui.showDialogWithCopyOption
import org.ergoplatform.settings.SettingsUiLogic
import org.ergoplatform.uilogic.settings.SettingsUiLogic

class SettingsFragment : Fragment() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import org.ergoplatform.android.databinding.FragmentSendFundsWalletChooserBindin
import org.ergoplatform.android.databinding.FragmentSendFundsWalletChooserItemBinding
import org.ergoplatform.android.ui.FullScreenFragmentDialog
import org.ergoplatform.android.ui.navigateSafe
import org.ergoplatform.parsePaymentRequestFromQuery
import org.ergoplatform.parsePaymentRequest
import org.ergoplatform.wallet.getBalanceForAllAddresses


Expand All @@ -39,14 +39,14 @@ class ChooseSpendingWalletFragmentDialog : FullScreenFragmentDialog() {

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val query = requireActivity().intent.data?.encodedQuery
val query = requireActivity().intent.dataString

if (query == null) {
dismiss()
return
}

val content = parsePaymentRequestFromQuery(query)
val content = parsePaymentRequest(query)
binding.receiverAddress.text = content?.address
val amount = content?.amount ?: ErgoAmount.ZERO
binding.grossAmount.amount = amount.toDouble()
Expand All @@ -59,7 +59,7 @@ class ChooseSpendingWalletFragmentDialog : FullScreenFragmentDialog() {

if (wallets.size == 1) {
// immediately switch to send funds screen
navigateToSendFundsScreen(wallets.first().walletConfig.id)
navigateToSendFundsScreen(wallets.first().walletConfig.id, query)
}
wallets.sortedBy { it.walletConfig.displayName }.forEach { wallet ->
val itemBinding = FragmentSendFundsWalletChooserItemBinding.inflate(
Expand All @@ -71,21 +71,21 @@ class ChooseSpendingWalletFragmentDialog : FullScreenFragmentDialog() {
itemBinding.walletName.text = wallet.walletConfig.displayName

itemBinding.root.setOnClickListener {
navigateToSendFundsScreen(wallet.walletConfig.id)
navigateToSendFundsScreen(wallet.walletConfig.id, query)
}
}
})
}

private fun navigateToSendFundsScreen(walletId: Int) {
private fun navigateToSendFundsScreen(walletId: Int, paymentRequest: String) {
val navBuilder = NavOptions.Builder()
val navOptions =
navBuilder.setPopUpTo(R.id.chooseSpendingWalletFragmentDialog, true).build()

NavHostFragment.findNavController(requireParentFragment())
.navigateSafe(
ChooseSpendingWalletFragmentDialogDirections.actionChooseSpendingWalletFragmentDialogToSendFundsFragment(
requireActivity().intent.data?.encodedQuery!!, walletId
paymentRequest, walletId
), navOptions
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ import org.ergoplatform.android.R
import org.ergoplatform.android.databinding.EntryTransactionBoxBinding
import org.ergoplatform.android.databinding.EntryWalletTokenBinding
import org.ergoplatform.android.databinding.FragmentColdWalletSigningBinding
import org.ergoplatform.android.ui.AbstractAuthenticationFragment
import org.ergoplatform.android.ui.ProgressBottomSheetDialogFragment
import org.ergoplatform.android.ui.QrPagerAdapter
import org.ergoplatform.android.ui.showDialogWithCopyOption
import org.ergoplatform.android.ui.*
import org.ergoplatform.explorer.client.model.AssetInstanceInfo
import org.ergoplatform.transactions.reduceBoxes

Expand Down Expand Up @@ -202,11 +199,11 @@ class ColdWalletSigningFragment : AbstractAuthenticationFragment() {
}

override fun proceedAuthFlowWithPassword(password: String): Boolean {
return viewModel.signTxWithPassword(password)
return viewModel.signTxWithPassword(password, AndroidStringProvider(requireContext()))
}

override fun proceedAuthFlowFromBiometrics() {
viewModel.signTxUserAuth()
viewModel.signTxUserAuth(AndroidStringProvider(requireContext()))
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import org.ergoplatform.explorer.client.model.TransactionInfo
import org.ergoplatform.persistance.Wallet
import org.ergoplatform.transactions.PromptSigningResult
import org.ergoplatform.transactions.SigningResult
import org.ergoplatform.uilogic.StringProvider
import org.ergoplatform.wallet.getSortedDerivedAddressesList

class ColdWalletSigningViewModel : ViewModel() {
Expand Down Expand Up @@ -82,7 +83,7 @@ class ColdWalletSigningViewModel : ViewModel() {
}
}

fun signTxWithPassword(password: String): Boolean {
fun signTxWithPassword(password: String, texts: StringProvider): Boolean {
wallet?.walletConfig?.secretStorage?.let {
val mnemonic: String?
try {
Expand All @@ -98,15 +99,15 @@ class ColdWalletSigningViewModel : ViewModel() {
return false
}

signTxWithMnemonicAsync(mnemonic)
signTxWithMnemonicAsync(mnemonic, texts)

return true
}

return false
}

fun signTxUserAuth() {
fun signTxUserAuth(texts: StringProvider) {
// we don't handle exceptions here by intention: we throw them back to the caller which
// will show a snackbar to give the user a hint what went wrong
wallet?.walletConfig?.secretStorage?.let {
Expand All @@ -115,12 +116,12 @@ class ColdWalletSigningViewModel : ViewModel() {
val decryptData = AndroidEncryptionManager.decryptDataWithDeviceKey(it)
mnemonic = deserializeSecrets(String(decryptData!!))

signTxWithMnemonicAsync(mnemonic!!)
signTxWithMnemonicAsync(mnemonic!!, texts)

}
}

private fun signTxWithMnemonicAsync(mnemonic: String) {
private fun signTxWithMnemonicAsync(mnemonic: String, texts: StringProvider) {
signingRequest?.let { signingRequest ->
val derivedAddresses =
wallet!!.getSortedDerivedAddressesList().map { it.derivationIndex }
Expand All @@ -130,7 +131,7 @@ class ColdWalletSigningViewModel : ViewModel() {
withContext(Dispatchers.IO) {
ergoTxResult = signSerializedErgoTx(
signingRequest.serializedTx!!, mnemonic, "",
derivedAddresses
derivedAddresses, texts
)
signedQrCode = buildColdSigningResponse(ergoTxResult)?.let {
coldSigningResponseToQrChunks(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.core.view.descendants
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.textfield.TextInputLayout
import com.google.zxing.integration.android.IntentIntegrator
Expand Down Expand Up @@ -301,6 +302,8 @@ class SendFundsFragment : AbstractAuthenticationFragment(), PasswordDialogCallba

setFocusToEmptyTokenAmountInput()
}

showPaymentRequestWarnings()
}

private fun setFocusToEmptyTokenAmountInput() {
Expand Down Expand Up @@ -337,7 +340,11 @@ class SendFundsFragment : AbstractAuthenticationFragment(), PasswordDialogCallba
override fun startAuthFlow(walletConfig: WalletConfig) {
if (walletConfig.secretStorage == null) {
// we have a read only wallet here, let's go to cold wallet support mode
viewModel.uiLogic.startColdWalletPayment(Preferences(requireContext()))
val context = requireContext()
viewModel.uiLogic.startColdWalletPayment(
Preferences(context),
AndroidStringProvider(context)
)
} else {
super.startAuthFlow(walletConfig)
}
Expand Down Expand Up @@ -383,15 +390,15 @@ class SendFundsFragment : AbstractAuthenticationFragment(), PasswordDialogCallba
)
)
} else {
val content = parsePaymentRequestFromQrCode(it)
val content = parsePaymentRequest(it)
content?.let {
binding.tvReceiver.editText?.setText(content.address)
content.amount.let { amount ->
if (amount.nanoErgs > 0) setAmountEdittext(
amount
)
}
viewModel.uiLogic.addTokensFromQr(content.tokens)
viewModel.uiLogic.addTokensFromPaymentRequest(content.tokens)
}
}
}
Expand All @@ -400,6 +407,15 @@ class SendFundsFragment : AbstractAuthenticationFragment(), PasswordDialogCallba
}
}

private fun showPaymentRequestWarnings() {
viewModel.uiLogic.getPaymentRequestWarnings(AndroidStringProvider(requireContext()))?.let {
MaterialAlertDialogBuilder(requireContext())
.setMessage(it)
.setPositiveButton(R.string.zxing_button_ok, null)
.show()
}
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
Expand Down
Loading

0 comments on commit a1f09c3

Please sign in to comment.