Skip to content

Commit a55bb86

Browse files
author
Alex Oakley
authored
Merge pull request #591 from soramitsu/master_2.0.7_from_staging
Master 2.0.7 from staging
2 parents a858d91 + 7c5240f commit a55bb86

File tree

22 files changed

+229
-24
lines changed

22 files changed

+229
-24
lines changed

build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
buildscript {
22
ext {
33
// App version
4-
versionName = '2.0.6'
5-
versionCode = 67
4+
versionName = '2.0.7'
5+
versionCode = 68
66

77
// SDK and tools
88
compileSdkVersion = 31
@@ -43,7 +43,7 @@ buildscript {
4343

4444
bouncyCastleVersion = '1.60'
4545

46-
fearlessLibVersion = '1.0.104'
46+
fearlessLibVersion = '1.0.108'
4747

4848
gifVersion = '1.2.19'
4949

common/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ operations will appear here</string>
115115
<string name="choose_amount_asset">Asset</string>
116116
<string name="choose_amount_to">To</string>
117117
<string name="choose_amount_fee">Transfer fee</string>
118+
<string name="choose_amount_tip">Tip</string>
118119
<string name="common_continue">Continue</string>
119120
<string name="common_amount">Amount</string>
120121
<string name="wallet_send_confirm_transfer">Confirm transfer</string>

feature-account-api/src/main/java/jp/co/soramitsu/feature_account_api/data/extrinsic/ExtrinsicService.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,13 @@ class ExtrinsicService(
3636
chain: Chain,
3737
accountId: ByteArray,
3838
useBatchAll: Boolean = false,
39+
tip: BigInteger? = null,
3940
formExtrinsic: suspend ExtrinsicBuilder.() -> Unit,
4041
): Result<String> = runCatching {
4142
val metaAccount = accountRepository.findMetaAccount(accountId) ?: error("No meta account found accessing ${accountId.toHexString()}")
4243
val keypair = secretStoreV2.getKeypairFor(metaAccount, chain, accountId)
4344

44-
val extrinsicBuilder = extrinsicBuilderFactory.create(chain, keypair, metaAccount.cryptoType(chain))
45+
val extrinsicBuilder = extrinsicBuilderFactory.create(chain, keypair, metaAccount.cryptoType(chain), tip)
4546

4647
extrinsicBuilder.formExtrinsic()
4748

feature-crowdloan-impl/src/main/java/jp/co/soramitsu/feature_crowdloan_impl/domain/contribute/CrowdloanContributeInteractor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ class CrowdloanContributeInteractor(
137137
}
138138

139139
return runCatching {
140-
walletRepository.performTransfer(accountId, chain, transfer, fee, additional, batchAll)
140+
walletRepository.performTransfer(accountId, chain, transfer, fee, null, additional, batchAll)
141141
}
142142
}
143143

feature-wallet-api/src/main/java/jp/co/soramitsu/feature_wallet_api/domain/interfaces/WalletConstants.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ import java.math.BigInteger
66
interface WalletConstants {
77

88
suspend fun existentialDeposit(chainId: ChainId): BigInteger
9+
10+
suspend fun tip(chainId: ChainId): BigInteger?
911
}

feature-wallet-api/src/main/java/jp/co/soramitsu/feature_wallet_api/domain/interfaces/WalletInteractor.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import jp.co.soramitsu.runtime.multiNetwork.chain.model.ChainId
2020
import kotlinx.coroutines.flow.Flow
2121
import java.io.File
2222
import java.math.BigDecimal
23+
import java.math.BigInteger
2324

2425
class NotValidTransferStatus(val status: TransferValidityStatus) : Exception()
2526

@@ -63,7 +64,8 @@ interface WalletInteractor {
6364
suspend fun performTransfer(
6465
transfer: Transfer,
6566
fee: BigDecimal,
66-
maxAllowedLevel: TransferValidityLevel = TransferValidityLevel.Ok
67+
maxAllowedLevel: TransferValidityLevel = TransferValidityLevel.Ok,
68+
tipInPlanks: BigInteger?
6769
): Result<Unit>
6870

6971
suspend fun getSenderAddress(chainId: ChainId): String?

feature-wallet-api/src/main/java/jp/co/soramitsu/feature_wallet_api/domain/interfaces/WalletRepository.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ interface WalletRepository {
7171
chain: Chain,
7272
transfer: Transfer,
7373
fee: BigDecimal,
74+
tip: BigInteger?,
7475
additional: (suspend ExtrinsicBuilder.() -> Unit)? = null,
7576
batchAll: Boolean = false
7677
)

feature-wallet-api/src/main/java/jp/co/soramitsu/feature_wallet_api/domain/model/Transfer.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package jp.co.soramitsu.feature_wallet_api.domain.model
22

3+
import jp.co.soramitsu.common.utils.orZero
34
import jp.co.soramitsu.runtime.multiNetwork.chain.model.Chain
45
import java.math.BigDecimal
56
import java.math.BigInteger
@@ -17,9 +18,10 @@ class Transfer(
1718
senderTotal: BigDecimal,
1819
fee: BigDecimal,
1920
recipientBalance: BigDecimal,
20-
existentialDeposit: BigDecimal
21+
existentialDeposit: BigDecimal,
22+
tip: BigDecimal? = null,
2123
): TransferValidityStatus {
22-
val transactionTotal = fee + amount
24+
val transactionTotal = fee + amount + tip.orZero()
2325

2426
return when {
2527
transactionTotal > senderTransferable -> TransferValidityLevel.Error.Status.NotEnoughFunds

feature-wallet-impl/src/main/java/jp/co/soramitsu/feature_wallet_impl/data/network/blockchain/SubstrateRemoteSource.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ interface SubstrateRemoteSource {
3939
accountId: ByteArray,
4040
chain: Chain,
4141
transfer: Transfer,
42+
tip: BigInteger?,
4243
additional: (suspend ExtrinsicBuilder.() -> Unit)?,
4344
batchAll: Boolean
4445
): String

feature-wallet-impl/src/main/java/jp/co/soramitsu/feature_wallet_impl/data/network/blockchain/WssSubstrateSource.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,15 @@ class WssSubstrateSource(
8888
accountId: AccountId,
8989
chain: Chain,
9090
transfer: Transfer,
91+
tip: BigInteger?,
9192
additional: (suspend ExtrinsicBuilder.() -> Unit)?,
9293
batchAll: Boolean
9394
): String {
9495
return extrinsicService.submitExtrinsic(
9596
chain = chain,
9697
accountId = accountId,
9798
useBatchAll = batchAll,
99+
tip = tip,
98100
formExtrinsic = {
99101
transfer(chain, transfer, this.runtime.typeRegistry)
100102
additional?.invoke(this)

feature-wallet-impl/src/main/java/jp/co/soramitsu/feature_wallet_impl/data/repository/RuntimeWalletConstants.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package jp.co.soramitsu.feature_wallet_impl.data.repository
22

3+
import jp.co.soramitsu.common.utils.Modules
34
import jp.co.soramitsu.common.utils.balances
45
import jp.co.soramitsu.common.utils.numberConstant
56
import jp.co.soramitsu.feature_wallet_api.domain.interfaces.WalletConstants
@@ -17,4 +18,14 @@ class RuntimeWalletConstants(
1718

1819
return runtime.metadata.balances().numberConstant("ExistentialDeposit", runtime)
1920
}
21+
22+
override suspend fun tip(chainId: ChainId): BigInteger? {
23+
val runtime = chainRegistry.getRuntime(chainId)
24+
25+
val constantName = "DefaultTip"
26+
27+
return kotlin.runCatching {
28+
runtime.metadata.balances().numberConstant(constantName, runtime)
29+
}.getOrNull() ?: runtime.overrides?.get(Modules.BALANCES)?.get(constantName)?.toBigInteger()
30+
}
2031
}

feature-wallet-impl/src/main/java/jp/co/soramitsu/feature_wallet_impl/data/repository/WalletRepositoryImpl.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,11 @@ class WalletRepositoryImpl(
294294
chain: Chain,
295295
transfer: Transfer,
296296
fee: BigDecimal,
297+
tip: BigInteger?,
297298
additional: (suspend ExtrinsicBuilder.() -> Unit)?,
298299
batchAll: Boolean
299300
) {
300-
val operationHash = substrateSource.performTransfer(accountId, chain, transfer, additional, batchAll)
301+
val operationHash = substrateSource.performTransfer(accountId, chain, transfer, tip, additional, batchAll)
301302
val accountAddress = chain.addressOf(accountId)
302303

303304
val operation = createOperation(
@@ -343,7 +344,10 @@ class WalletRepositoryImpl(
343344
val existentialDepositInPlanks = kotlin.runCatching { walletConstants.existentialDeposit(chain.id) }.getOrDefault(BigInteger.ZERO)
344345
val existentialDeposit = chainAsset.amountFromPlanks(existentialDepositInPlanks)
345346

346-
return transfer.validityStatus(asset.transferable, asset.total.orZero(), feeResponse.feeAmount, totalRecipientBalance, existentialDeposit)
347+
val tipInPlanks = kotlin.runCatching { walletConstants.tip(chain.id) }.getOrNull()
348+
val tip = tipInPlanks?.let { chainAsset.amountFromPlanks(it) }
349+
350+
return transfer.validityStatus(asset.transferable, asset.total.orZero(), feeResponse.feeAmount, totalRecipientBalance, existentialDeposit, tip)
347351
}
348352

349353
// TODO adapt for ethereum chains

feature-wallet-impl/src/main/java/jp/co/soramitsu/feature_wallet_impl/domain/WalletInteractorImpl.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import kotlinx.coroutines.flow.onStart
4545
import kotlinx.coroutines.flow.withIndex
4646
import kotlinx.coroutines.withContext
4747
import java.math.BigDecimal
48+
import java.math.BigInteger
4849

4950
private const val CUSTOM_ASSET_SORTING_PREFS_KEY = "customAssetSorting-"
5051

@@ -240,6 +241,7 @@ class WalletInteractorImpl(
240241
transfer: Transfer,
241242
fee: BigDecimal,
242243
maxAllowedLevel: TransferValidityLevel,
244+
tipInPlanks: BigInteger?,
243245
): Result<Unit> {
244246
val metaAccount = accountRepository.getSelectedMetaAccount()
245247
val chain = chainRegistry.getChain(transfer.chainAsset.chainId)
@@ -252,7 +254,7 @@ class WalletInteractorImpl(
252254
}
253255

254256
return runCatching {
255-
walletRepository.performTransfer(accountId, chain, transfer, fee)
257+
walletRepository.performTransfer(accountId, chain, transfer, fee, tipInPlanks)
256258
}
257259
}
258260

feature-wallet-impl/src/main/java/jp/co/soramitsu/feature_wallet_impl/presentation/send/TransferDraft.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package jp.co.soramitsu.feature_wallet_impl.presentation.send
22

33
import android.os.Parcelable
4+
import jp.co.soramitsu.common.utils.orZero
45
import jp.co.soramitsu.feature_wallet_impl.presentation.AssetPayload
56
import kotlinx.android.parcel.IgnoredOnParcel
67
import kotlinx.android.parcel.Parcelize
@@ -11,10 +12,11 @@ class TransferDraft(
1112
val amount: BigDecimal,
1213
val fee: BigDecimal,
1314
val assetPayload: AssetPayload,
14-
val recipientAddress: String
15+
val recipientAddress: String,
16+
val tip: BigDecimal?,
1517
) : Parcelable {
1618
@IgnoredOnParcel
17-
val totalTransaction = amount + fee
19+
val totalTransaction = amount + fee + tip.orZero()
1820

1921
fun totalAfterTransfer(currentTotal: BigDecimal) = currentTotal - totalTransaction
2022
}

feature-wallet-impl/src/main/java/jp/co/soramitsu/feature_wallet_impl/presentation/send/amount/ChooseAmountFragment.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import androidx.core.os.bundleOf
1111
import coil.ImageLoader
1212
import jp.co.soramitsu.common.base.BaseFragment
1313
import jp.co.soramitsu.common.di.FeatureUtils
14+
import jp.co.soramitsu.common.utils.makeVisible
1415
import jp.co.soramitsu.common.utils.onTextChanged
1516
import jp.co.soramitsu.common.utils.orZero
1617
import jp.co.soramitsu.common.utils.setTextColorRes
@@ -33,6 +34,9 @@ import kotlinx.android.synthetic.main.fragment_choose_amount.chooseAmountField
3334
import kotlinx.android.synthetic.main.fragment_choose_amount.chooseAmountMax
3435
import kotlinx.android.synthetic.main.fragment_choose_amount.chooseAmountNext
3536
import kotlinx.android.synthetic.main.fragment_choose_amount.chooseAmountRecipientView
37+
import kotlinx.android.synthetic.main.fragment_choose_amount.chooseAmountTip
38+
import kotlinx.android.synthetic.main.fragment_choose_amount.chooseAmountTipFiat
39+
import kotlinx.android.synthetic.main.fragment_choose_amount.chooseAmountTipGroup
3640
import kotlinx.android.synthetic.main.fragment_choose_amount.chooseAmountToolbar
3741
import javax.inject.Inject
3842

@@ -108,6 +112,13 @@ class ChooseAmountFragment : BaseFragment<ChooseAmountViewModel>() {
108112
viewModel.feeLiveData.observe {
109113
chooseAmountFee.text = it?.feeAmount?.formatTokenAmount(it.type) ?: getString(R.string.common_error_general_title)
110114
}
115+
viewModel.tipAmountTextLiveData.observe {
116+
chooseAmountTipGroup.makeVisible()
117+
chooseAmountTip.text = it
118+
}
119+
viewModel.tipFiatAmountLiveData.observe {
120+
chooseAmountTipFiat.text = it
121+
}
111122
viewModel.feeFiatLiveData.observe {
112123
chooseAmountFeeFiat.text = it ?: ""
113124
}

feature-wallet-impl/src/main/java/jp/co/soramitsu/feature_wallet_impl/presentation/send/amount/ChooseAmountViewModel.kt

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import jp.co.soramitsu.common.utils.combine
1414
import jp.co.soramitsu.common.utils.format
1515
import jp.co.soramitsu.common.utils.formatAsCurrency
1616
import jp.co.soramitsu.common.utils.map
17+
import jp.co.soramitsu.common.utils.mediateWith
1718
import jp.co.soramitsu.common.utils.requireValue
1819
import jp.co.soramitsu.common.view.ButtonState
1920
import jp.co.soramitsu.feature_account_api.presentation.actions.ExternalAccountActions
@@ -27,6 +28,7 @@ import jp.co.soramitsu.feature_wallet_api.domain.model.TransferValidityLevel.Ok
2728
import jp.co.soramitsu.feature_wallet_api.domain.model.TransferValidityLevel.Warning
2829
import jp.co.soramitsu.feature_wallet_api.domain.model.TransferValidityStatus
2930
import jp.co.soramitsu.feature_wallet_api.domain.model.amountFromPlanks
31+
import jp.co.soramitsu.feature_wallet_api.presentation.formatters.formatTokenAmount
3032
import jp.co.soramitsu.feature_wallet_api.presentation.mixin.TransferValidityChecks
3133
import jp.co.soramitsu.feature_wallet_impl.R
3234
import jp.co.soramitsu.feature_wallet_impl.data.mappers.mapAssetToAssetModel
@@ -101,6 +103,24 @@ class ChooseAmountViewModel(
101103
updateExistentialDeposit(asset.token.configuration)
102104
}
103105

106+
private val tipLiveData = liveData { walletConstants.tip(assetPayload.chainId)?.let { emit(it) } }
107+
private val tipAmountLiveData = mediateWith(tipLiveData, assetLiveData) { (tip: BigInteger?, asset: Asset?) ->
108+
tip?.let {
109+
asset?.token?.amountFromPlanks(it)
110+
}
111+
}
112+
113+
val tipAmountTextLiveData = mediateWith(tipAmountLiveData, assetLiveData) { (tip: BigDecimal?, asset: Asset?) ->
114+
asset?.token?.configuration?.symbol?.let {
115+
tip?.formatTokenAmount(it)
116+
}
117+
}
118+
val tipFiatAmountLiveData = mediateWith(tipAmountLiveData, assetLiveData) { (tip: BigDecimal?, asset: Asset?) ->
119+
tip?.let {
120+
asset?.token?.fiatAmount(it)?.formatAsCurrency(asset.token.fiatSymbol)
121+
}
122+
}
123+
104124
val feeLiveData = feeFlow().asLiveData()
105125
val feeFiatLiveData = combine(assetLiveData, feeLiveData) { (asset: Asset, fee: Fee?) ->
106126
fee?.feeAmount?.let {
@@ -265,8 +285,9 @@ class ChooseAmountViewModel(
265285

266286
private fun buildTransferDraft(): TransferDraft? {
267287
val fee = feeLiveData.value ?: return null
288+
val tip = tipAmountLiveData.value
268289

269-
return TransferDraft(fee.transferAmount, fee.feeAmount, assetPayload, recipientAddress)
290+
return TransferDraft(fee.transferAmount, fee.feeAmount, assetPayload, recipientAddress, tip)
270291
}
271292

272293
private fun retryLoadFee() {
@@ -276,15 +297,16 @@ class ChooseAmountViewModel(
276297
fun quickInputSelected(value: Double) {
277298
val amount = assetModelLiveData.value?.available ?: return
278299
val fee = feeLiveData.value?.feeAmount ?: return
300+
val tip = tipAmountLiveData.value ?: BigDecimal.ZERO
279301

280302
val quickAmountRaw = amount * value.toBigDecimal()
281-
val quickAmountWithoutFee = quickAmountRaw - fee
303+
val quickAmountWithoutExtraPays = quickAmountRaw - fee - tip
282304

283-
if (quickAmountWithoutFee < BigDecimal.ZERO) {
305+
if (quickAmountWithoutExtraPays < BigDecimal.ZERO) {
284306
return
285307
}
286308

287-
val newAmount = quickAmountWithoutFee.format()
309+
val newAmount = quickAmountWithoutExtraPays.format()
288310
amountChanged(newAmount)
289311
}
290312
}

feature-wallet-impl/src/main/java/jp/co/soramitsu/feature_wallet_impl/presentation/send/confirm/ConfirmTransferFragment.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import coil.ImageLoader
88
import jp.co.soramitsu.common.base.BaseFragment
99
import jp.co.soramitsu.common.di.FeatureUtils
1010
import jp.co.soramitsu.common.utils.formatAsCurrency
11+
import jp.co.soramitsu.common.utils.makeVisible
1112
import jp.co.soramitsu.common.utils.orZero
1213
import jp.co.soramitsu.feature_account_api.presentation.actions.setupExternalActions
1314
import jp.co.soramitsu.feature_wallet_api.di.WalletFeatureApi
@@ -18,8 +19,11 @@ import jp.co.soramitsu.feature_wallet_impl.di.WalletFeatureComponent
1819
import jp.co.soramitsu.feature_wallet_impl.presentation.send.BalanceDetailsBottomSheet
1920
import jp.co.soramitsu.feature_wallet_impl.presentation.send.TransferDraft
2021
import kotlinx.android.synthetic.main.fragment_confirm_transfer.confirmAmountField
22+
import kotlinx.android.synthetic.main.fragment_confirm_transfer.confirmAmountTipGroup
2123
import kotlinx.android.synthetic.main.fragment_confirm_transfer.confirmFee
2224
import kotlinx.android.synthetic.main.fragment_confirm_transfer.confirmFeeFiat
25+
import kotlinx.android.synthetic.main.fragment_confirm_transfer.confirmTip
26+
import kotlinx.android.synthetic.main.fragment_confirm_transfer.confirmTipFiat
2327
import kotlinx.android.synthetic.main.fragment_confirm_transfer.confirmTransferRecipientView
2428
import kotlinx.android.synthetic.main.fragment_confirm_transfer.confirmTransferSenderView
2529
import kotlinx.android.synthetic.main.fragment_confirm_transfer.confirmTransferSubmit
@@ -96,6 +100,12 @@ class ConfirmTransferFragment : BaseFragment<ConfirmTransferViewModel>() {
96100

97101
confirmAmountField.amountInput.setText(totalTransaction.formatTokenAmount(chainAsset))
98102
confirmAmountField.setAssetBalanceFiatAmount(it.token.fiatAmount(totalTransaction)?.formatAsCurrency(it.token.fiatSymbol))
103+
104+
tip?.let { tip ->
105+
confirmAmountTipGroup.makeVisible()
106+
confirmTip.text = tip.formatTokenAmount(chainAsset)
107+
confirmTipFiat.text = it.token.fiatAmount(tip)?.formatAsCurrency(it.token.fiatSymbol)
108+
}
99109
}
100110
}
101111

feature-wallet-impl/src/main/java/jp/co/soramitsu/feature_wallet_impl/presentation/send/confirm/ConfirmTransferViewModel.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import jp.co.soramitsu.feature_wallet_api.domain.interfaces.WalletInteractor
2020
import jp.co.soramitsu.feature_wallet_api.domain.model.Transfer
2121
import jp.co.soramitsu.feature_wallet_api.domain.model.TransferValidityLevel
2222
import jp.co.soramitsu.feature_wallet_api.domain.model.TransferValidityStatus
23+
import jp.co.soramitsu.feature_wallet_api.domain.model.planksFromAmount
2324
import jp.co.soramitsu.feature_wallet_api.presentation.mixin.TransferValidityChecks
2425
import jp.co.soramitsu.feature_wallet_impl.data.mappers.mapAssetToAssetModel
2526
import jp.co.soramitsu.feature_wallet_impl.presentation.WalletRouter
@@ -109,8 +110,9 @@ class ConfirmTransferViewModel(
109110
_transferSubmittingLiveData.value = true
110111

111112
viewModelScope.launch {
113+
val tipInPlanks = transferDraft.tip?.let { chainAsset.planksFromAmount(it) }
112114
val result = withContext(Dispatchers.Default) {
113-
interactor.performTransfer(createTransfer(chainAsset), transferDraft.fee, maxAllowedStatusLevel)
115+
interactor.performTransfer(createTransfer(chainAsset), transferDraft.fee, maxAllowedStatusLevel, tipInPlanks)
114116
}
115117
if (result.isSuccess) {
116118
router.finishSendFlow()

0 commit comments

Comments
 (0)