Skip to content

Commit

Permalink
WA-430: Fix safe name reset after deploy (#200)
Browse files Browse the repository at this point in the history
• Fix safe name reset after deploy
• Add shortcut to send asset
  • Loading branch information
rmeissner authored and fmrsabino committed Jul 9, 2018
1 parent 1c0d24c commit 194c70d
Show file tree
Hide file tree
Showing 16 changed files with 122 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class HeimdallApplication : MultiDexApplication() {
// Init crash tracker to track unhandled exceptions
component.crashTracker().init()
RxJavaPlugins.setErrorHandler(Timber::e)
component.shortcutRepository().init()

try {
LinuxSecureRandom()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ interface GnosisSafeDao {
@Query("SELECT * FROM ${PendingGnosisSafeDb.TABLE_NAME} WHERE ${PendingGnosisSafeDb.COL_TX_HASH} = :hash")
fun loadPendingSafe(hash: BigInteger): Single<PendingGnosisSafeDb>

@Query("SELECT * FROM ${PendingGnosisSafeDb.TABLE_NAME} WHERE ${PendingGnosisSafeDb.COL_TX_HASH} = :hash")
fun queryPendingSafe(hash: BigInteger): PendingGnosisSafeDb

@Query("DELETE FROM ${PendingGnosisSafeDb.TABLE_NAME} WHERE ${PendingGnosisSafeDb.COL_TX_HASH} = :hash")
fun removePendingSafe(hash: BigInteger)

Expand All @@ -48,8 +51,9 @@ interface GnosisSafeDao {
fun updatePendingSafe(pendingSafe: PendingGnosisSafeDb)

@Transaction
fun pendingSafeToDeployedSafe(pendingSafe: PendingSafe) {
removePendingSafe(pendingSafe.hash)
insertSafe(GnosisSafeDb(pendingSafe.address, pendingSafe.name))
fun pendingSafeToDeployedSafe(pendingSafeHash: BigInteger) {
val safe = queryPendingSafe(pendingSafeHash)
removePendingSafe(safe.transactionHash)
insertSafe(GnosisSafeDb(safe.address, safe.name))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ interface GnosisSafeRepository {
fun observeSafes(): Flowable<List<AbstractSafe>>
fun observeDeployedSafes(): Flowable<List<Safe>>

fun addSafe(address: Solidity.Address, name: String): Completable
fun removeSafe(address: Solidity.Address): Completable
fun updateSafe(safe: Safe): Completable
fun loadSafe(address: Solidity.Address): Single<Safe>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package pm.gnosis.heimdall.data.repositories

interface ShortcutRepository {

fun init()
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,6 @@ class DefaultGnosisSafeRepository @Inject constructor(
override fun observePendingSafe(transactionHash: BigInteger): Flowable<PendingSafe> =
safeDao.observePendingSafe(transactionHash).map { it.fromDb() }

override fun addSafe(address: Solidity.Address, name: String) =
Completable.fromCallable {
safeDao.insertSafe(GnosisSafeDb(address, name))
}.subscribeOn(Schedulers.io())!!

override fun savePendingSafe(transactionHash: BigInteger, name: String?, safeAddress: Solidity.Address, payment: Wei): Completable =
Completable.fromAction {
safeDao.insertPendingSafe(PendingGnosisSafeDb(transactionHash, name, safeAddress, ERC20Token.ETHER_TOKEN.address, payment.value))
Expand All @@ -87,7 +82,7 @@ class DefaultGnosisSafeRepository @Inject constructor(
}.subscribeOn(Schedulers.io())!!

override fun pendingSafeToDeployedSafe(pendingSafe: PendingSafe): Completable =
Completable.fromCallable { safeDao.pendingSafeToDeployedSafe(pendingSafe) }
Completable.fromCallable { safeDao.pendingSafeToDeployedSafe(pendingSafe.hash) }
.andThen(sendSafeCreationPush(pendingSafe.address).onErrorComplete())
.subscribeOn(Schedulers.io())

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package pm.gnosis.heimdall.data.repositories.impls

import android.annotation.TargetApi
import android.content.Context
import android.content.Intent
import android.content.pm.ShortcutInfo
import android.content.pm.ShortcutManager
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.Icon
import android.os.Build
import io.reactivex.rxkotlin.subscribeBy
import io.reactivex.schedulers.Schedulers
import pm.gnosis.blockies.Blockies
import pm.gnosis.blockies.BlockiesPainter
import pm.gnosis.heimdall.R
import pm.gnosis.heimdall.data.repositories.GnosisSafeRepository
import pm.gnosis.heimdall.data.repositories.ShortcutRepository
import pm.gnosis.heimdall.data.repositories.models.Safe
import pm.gnosis.heimdall.di.ApplicationContext
import pm.gnosis.heimdall.ui.tokens.select.SelectTokenActivity
import pm.gnosis.model.Solidity
import pm.gnosis.utils.asEthereumAddressString
import pm.gnosis.utils.nullOnThrow
import timber.log.Timber
import javax.inject.Inject

class DefaultShortcutRepository @Inject constructor(
@ApplicationContext private val context: Context,
private val safeRepository: GnosisSafeRepository
) : ShortcutRepository {


private val iconDimension = context.resources.getDimension(R.dimen.shortcut_icon)

private val blockiesPainter = BlockiesPainter().apply {
setDimensions(iconDimension, iconDimension)
}

override fun init() {
shortcutManager()?.let {
safeRepository.observeDeployedSafes()
.subscribeOn(Schedulers.io())
.map(::createShortcutInfo)
.subscribeBy(onNext = ::setupSafeShortcuts, onError = Timber::e)
}
}

@TargetApi(Build.VERSION_CODES.N_MR1)
private fun createShortcutInfo(safes: List<Safe>): List<ShortcutInfo> =
// This should only be done if we can use the shortcut manager
shortcutManager()?.let {
safes.map {
ShortcutInfo.Builder(context, it.address.asEthereumAddressString())
.setShortLabel(context.getString(R.string.send_from_x, it.displayName(context)))
.setLongLabel(context.getString(R.string.send_from_x, it.displayName(context)))
.setIcon(Icon.createWithBitmap(blockiesBitmap(it.address)))
.setIntent(SelectTokenActivity.createIntent(context, it.address).prepare())
.build()
}
} ?: emptyList()

private fun blockiesBitmap(address: Solidity.Address) =
Bitmap.createBitmap(iconDimension.toInt(), iconDimension.toInt(), Bitmap.Config.ARGB_8888).apply {
blockiesPainter.draw(Canvas(this), Blockies.fromAddress(address)!!)
}

private fun Intent.prepare(): Intent = apply {
action = Intent.ACTION_VIEW
flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
}

@TargetApi(Build.VERSION_CODES.N_MR1)
private fun setupSafeShortcuts(shortcuts: List<ShortcutInfo>) {
// This should only be done if we can use the shortcut manager
shortcutManager()?.let {
it.removeAllDynamicShortcuts()
it.dynamicShortcuts = shortcuts
}
}

private fun shortcutManager(): ShortcutManager? =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1)
nullOnThrow { context.getSystemService(ShortcutManager::class.java) }
else null
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ import android.arch.lifecycle.ViewModelProvider
import android.content.Context
import com.squareup.picasso.Picasso
import dagger.Component
import pm.gnosis.heimdall.data.repositories.AddressBookRepository
import pm.gnosis.heimdall.data.repositories.GnosisSafeRepository
import pm.gnosis.heimdall.data.repositories.TokenRepository
import pm.gnosis.heimdall.data.repositories.TransactionInfoRepository
import pm.gnosis.heimdall.data.repositories.*
import pm.gnosis.heimdall.di.ApplicationContext
import pm.gnosis.heimdall.di.modules.ApplicationBindingsModule
import pm.gnosis.heimdall.di.modules.ApplicationModule
Expand Down Expand Up @@ -47,6 +44,7 @@ interface ApplicationComponent {
fun accountsRepository(): AccountsRepository
fun addressBookRepository(): AddressBookRepository
fun safeRepository(): GnosisSafeRepository
fun shortcutRepository(): ShortcutRepository
fun tokenRepository(): TokenRepository
fun transactionInfoRepository(): TransactionInfoRepository

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ abstract class ApplicationBindingsModule {
@Singleton
abstract fun bindsSafeRepository(repository: DefaultGnosisSafeRepository): GnosisSafeRepository

@Binds
@Singleton
abstract fun bindsShortcutRepository(repository: DefaultShortcutRepository): ShortcutRepository

@Binds
@Singleton
abstract fun bindsTokenRepository(repository: DefaultTokenRepository): TokenRepository
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ class ConfirmSafeRecoveryPhraseViewModel @Inject constructor(
this.mnemonic = mnemonic
this.chromeExtensionAddress = chromeExtensionAddress
}
.andThen(loadShuffledWords())
.andThen(loadWordsToDisplay())
.subscribeOn(Schedulers.io())

private fun loadShuffledWords(): Single<List<String>> =
private fun loadWordsToDisplay(): Single<List<String>> =
Single.fromCallable {
mnemonic.words().shuffled()
mnemonic.words().sorted()
}.subscribeOn(Schedulers.computation())

override fun isCorrectSequence(words: List<String>): Single<Result<Boolean>> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,14 @@ class CreateAssetTransferActivity : ViewModelActivity<CreateAssetTransferContrac

disposables += Single.fromCallable {
var address: Solidity.Address? = null
@Suppress("MoveLambdaOutsideParentheses")
handleQrCodeActivityResult(requestCode, resultCode, data, {
address = parseEthereumAddress(it) ?: throw IllegalArgumentException()
})

// We couldn't parse an address yet
if (address == null) {
@Suppress("MoveLambdaOutsideParentheses")
handleAddressBookResult(requestCode, resultCode, data, {
address = it.address
})
Expand Down Expand Up @@ -155,11 +157,9 @@ class CreateAssetTransferActivity : ViewModelActivity<CreateAssetTransferContrac
}
CreateAssetTransferContract.ViewUpdate.EstimateError -> disableContinue()
is CreateAssetTransferContract.ViewUpdate.TokenInfo -> {
update.value.token.name?.let {
layout_create_asset_transfer_title.text = getString(R.string.transfer_x, it)
}
layout_create_asset_transfer_title.text = getString(R.string.send_x, update.value.token.name)
layout_create_asset_transfer_safe_balance.text = update.value.displayString()
layout_create_asset_transfer_input_label.text = update.value.token.symbol ?: "???"
layout_create_asset_transfer_input_label.text = update.value.token.symbol
}
is CreateAssetTransferContract.ViewUpdate.InvalidInput -> {
layout_create_asset_transfer_input_value.setTextColor(
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/layout/layout_create_asset_transfer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
android:gravity="center_vertical"
android:minHeight="@dimen/toolbar_height"
android:paddingEnd="16dp"
android:text="@string/transfer"
android:text="@string/send"
android:textColor="@color/dark_slate_blue"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/layout/layout_create_safe_intro.xml
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_shadow_size"
android:background="@drawable/toolbar_dropshadow"
app:layout_constraintTop_toBottomOf="@id/layout_manage_tokens"
app:layout_constraintTop_toBottomOf="@id/layout_create_safe_intro_title"
tools:visibility="visible" />

</android.support.constraint.ConstraintLayout>
2 changes: 2 additions & 0 deletions app/src/main/res/values/dimens.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

<dimen name="action_circle">40dp</dimen>

<dimen name="shortcut_icon">48dp</dimen>

<dimen name="divider_width">1dp</dimen>

<dimen name="info_blockies">32dp</dimen>
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
<string name="submit_transaction">Submit Transaction</string>
<string name="cancel">Cancel</string>
<string name="invalid_ethereum_address">Invalid ethereum address</string>
<string name="transfer">Transfer</string>
<string name="transaction_details_error">Error fetching transaction details</string>
<string name="safe_remove_success">Removed %1s from this device</string>
<string name="change_name">Edit Safe name</string>
Expand Down Expand Up @@ -124,7 +123,7 @@
<string name="confirmations_ready">confirmed by extension</string>
<string name="submitting_transaction">Submitting transaction</string>
<string name="rejecting_transaction">Rejecting transaction</string>
<string name="transfer_x">Transfer %s</string>
<string name="send_x">Send %s</string>
<string name="enter_password">Enter password</string>
<string name="use_password">Use password</string>
<string name="place_your_finger_to_unlock">Place your finger to unlock</string>
Expand Down Expand Up @@ -193,4 +192,5 @@
<string name="debug_settings">Debug Settings</string>
<string name="confirm_recovery_phrase">Confirm recovery phrase</string>
<string name="recovery_phrase">Recovery phrase</string>
<string name="send_from_x">Send from %s</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class ConfirmSafeRecoveryPhraseViewModelTest {

viewModel.setup(encryptedMnemonic, Solidity.Address(1.toBigInteger())).subscribe(testObserver)

testObserver.assertTerminated().assertNoErrors()
testObserver.assertResult(mnemonic.words().sorted())
then(encryptionManagerMock).should().decrypt(capture(cryptoDataCaptor))
then(encryptionManagerMock).shouldHaveNoMoreInteractions()
assertTrue(cryptoDataCaptor.value.data.contentEquals("ffffff".hexStringToByteArray()))
Expand Down
2 changes: 1 addition & 1 deletion buildsystem/dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ ext {
rxjava : '2.1.12',
rxkotlin : '2.2.0',
spongycastle : '1.58.0.0',
svalinn : 'v0.5.3',
svalinn : 'v0.5.4',
timber : '4.7.0',
zxing : '3.3.1',

Expand Down

0 comments on commit 194c70d

Please sign in to comment.