Skip to content

Commit 9cdc19c

Browse files
authored
WAL-1588 Sponsored delegation (#349)
1 parent 28368c9 commit 9cdc19c

File tree

8 files changed

+177
-9
lines changed

8 files changed

+177
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- Support for sponsored Smart contract updates
13+
- Support for sponsored delegation configuration transaction
1314

1415
### Fixed
1516

app/src/main/java/com/concordium/wallet/data/walletconnect/AccountTransactionPayload.kt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.concordium.wallet.data.walletconnect
22

3+
import com.concordium.sdk.responses.transactionstatus.DelegationTarget
34
import com.concordium.sdk.transactions.tokens.TransferTokenOperation
45
import com.concordium.sdk.types.ContractAddress
56
import com.google.gson.annotations.SerializedName
@@ -22,18 +23,24 @@ sealed interface AccountTransactionPayload {
2223
val maxContractExecutionEnergy: Long?,
2324
val message: String,
2425
val receiveName: String
25-
): AccountTransactionPayload
26+
) : AccountTransactionPayload
2627

2728
data class Transfer(
2829
val amount: BigInteger,
2930
@SerializedName("to", alternate = ["toAddress"])
3031
val toAddress: String
31-
): AccountTransactionPayload
32+
) : AccountTransactionPayload
3233

3334
data class PltTransfer(
3435
val tokenId: String,
3536
val transfer: TransferTokenOperation,
36-
): AccountTransactionPayload
37+
) : AccountTransactionPayload
38+
39+
data class ConfigureDelegation(
40+
val amount: BigInteger,
41+
val restakeEarnings: Boolean,
42+
val delegationTarget: DelegationTarget?
43+
) : AccountTransactionPayload
3744

3845
// InitContract is not needed for now.
3946
}

app/src/main/java/com/concordium/wallet/ui/walletconnect/WalletConnectSignSponsoredTransactionRequestHandler.kt

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.concordium.wallet.ui.walletconnect
22

33
import android.content.Context
44
import com.concordium.sdk.serializing.JsonMapper
5+
import com.concordium.sdk.transactions.ConfigureDelegation
56
import com.concordium.sdk.transactions.PartiallySignedSponsoredTransaction
67
import com.concordium.sdk.transactions.Payload
78
import com.concordium.sdk.transactions.SignerEntry
@@ -121,6 +122,14 @@ class WalletConnectSignSponsoredTransactionRequestHandler(
121122
)
122123
}
123124

125+
is ConfigureDelegation -> {
126+
AccountTransactionPayload.ConfigureDelegation(
127+
amount = BigInteger(1, payload.capital?.value?.bytes),
128+
restakeEarnings = payload.restakeEarnings ?: false,
129+
delegationTarget = payload.delegationTarget
130+
)
131+
}
132+
124133
else ->
125134
error("The wallet only supports CCD and token transfers")
126135
}
@@ -181,7 +190,8 @@ class WalletConnectSignSponsoredTransactionRequestHandler(
181190
token = try {
182191
when (val transactionPayload = this.transactionPayload) {
183192
is AccountTransactionPayload.Transfer,
184-
is AccountTransactionPayload.Update
193+
is AccountTransactionPayload.Update,
194+
is AccountTransactionPayload.ConfigureDelegation
185195
->
186196
CCDToken(
187197
account = account,
@@ -228,6 +238,7 @@ class WalletConnectSignSponsoredTransactionRequestHandler(
228238

229239
val method = getTransactionMethodName(transactionPayload)
230240
val accountAtDisposalBalance = account.balanceAtDisposal
241+
val accountCooldownBalance = account.cooldownAmount
231242
val sponsorAddress = partiallySignedTransaction.header.sponsor.get().toString()
232243

233244
val reviewState = when (val transactionPayload = this.transactionPayload) {
@@ -241,6 +252,7 @@ class WalletConnectSignSponsoredTransactionRequestHandler(
241252
account = account,
242253
canShowDetails = false,
243254
isEnoughFunds = transactionPayload.amount <= accountAtDisposalBalance,
255+
showCooldownWarning = false,
244256
sponsor = sponsorAddress,
245257
appMetadata = appMetadata,
246258
)
@@ -255,6 +267,7 @@ class WalletConnectSignSponsoredTransactionRequestHandler(
255267
account = account,
256268
canShowDetails = true,
257269
isEnoughFunds = transactionPayload.amount <= accountAtDisposalBalance,
270+
showCooldownWarning = false,
258271
sponsor = sponsorAddress,
259272
appMetadata = appMetadata,
260273
)
@@ -272,10 +285,31 @@ class WalletConnectSignSponsoredTransactionRequestHandler(
272285
account = account,
273286
canShowDetails = transactionPayload.transfer.memo.isPresent,
274287
isEnoughFunds = tokenAmount <= token.balance,
288+
showCooldownWarning = false,
275289
sponsor = sponsorAddress,
276290
appMetadata = appMetadata,
277291
)
278292
}
293+
294+
is AccountTransactionPayload.ConfigureDelegation -> {
295+
State.SessionRequestReview.TransactionRequestReview(
296+
method = method,
297+
receiver = transactionPayload.delegationTarget?.type?.name ?: "",
298+
amount = transactionPayload.amount,
299+
token = token,
300+
estimatedFee = BigInteger.ZERO,
301+
account = account,
302+
canShowDetails = true,
303+
isEnoughFunds = transactionPayload.amount <= accountAtDisposalBalance + accountCooldownBalance,
304+
showCooldownWarning = transactionPayload.amount < account.delegatedAmount,
305+
sponsor = sponsorAddress,
306+
delegationRestakeEarnings = transactionPayload.restakeEarnings,
307+
delegationType = transactionPayload.delegationTarget?.bakerId?.id?.toString()
308+
?: context.getString(R.string.delegation_register_delegation_passive_long),
309+
delegationPoolId = transactionPayload.delegationTarget?.bakerId?.id?.toString() ?: "",
310+
appMetadata = appMetadata,
311+
)
312+
}
279313
}
280314

281315
emitState(reviewState)
@@ -390,6 +424,16 @@ class WalletConnectSignSponsoredTransactionRequestHandler(
390424
)
391425
)
392426
}
427+
428+
is AccountTransactionPayload.ConfigureDelegation -> {
429+
430+
emitEvent(
431+
Event.ShowDetailsDialog(
432+
title = getTransactionMethodName(transactionPayload),
433+
prettyPrintDetails = context.getString(R.string.wallet_connect_transaction_request_no_details),
434+
)
435+
)
436+
}
393437
}
394438
}
395439

@@ -409,6 +453,9 @@ class WalletConnectSignSponsoredTransactionRequestHandler(
409453

410454
is AccountTransactionPayload.Update ->
411455
transactionPayload.receiveName
456+
457+
is AccountTransactionPayload.ConfigureDelegation ->
458+
context.getString(R.string.wallet_connect_delegation_configuration)
412459
}
413460

414461
companion object {

app/src/main/java/com/concordium/wallet/ui/walletconnect/WalletConnectSignTransactionRequestHandler.kt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ class WalletConnectSignTransactionRequestHandler(
163163
when (val transactionPayload = this.transactionPayload) {
164164
is AccountTransactionPayload.Transfer,
165165
is AccountTransactionPayload.Update,
166-
->
166+
->
167167
CCDToken(
168168
account = account,
169169
withTotalBalance = true,
@@ -183,6 +183,8 @@ class WalletConnectSignTransactionRequestHandler(
183183
&& it.tokenId == transactionPayload.tokenId
184184
}
185185
?: error("Missing the requested token ${transactionPayload.tokenId}")
186+
187+
else -> error("The wallet only supports CCD and token transfers")
186188
}
187189
} catch (error: Exception) {
188190
Log.e("failed_loading_token", error)
@@ -224,6 +226,7 @@ class WalletConnectSignTransactionRequestHandler(
224226
account = account,
225227
canShowDetails = false,
226228
isEnoughFunds = transactionPayload.amount + transactionCost.cost <= accountAtDisposalBalance,
229+
showCooldownWarning = false,
227230
sponsor = null,
228231
appMetadata = appMetadata,
229232
)
@@ -238,6 +241,7 @@ class WalletConnectSignTransactionRequestHandler(
238241
account = account,
239242
canShowDetails = true,
240243
isEnoughFunds = transactionPayload.amount + transactionCost.cost <= accountAtDisposalBalance,
244+
showCooldownWarning = false,
241245
sponsor = null,
242246
appMetadata = appMetadata,
243247
)
@@ -256,10 +260,13 @@ class WalletConnectSignTransactionRequestHandler(
256260
canShowDetails = transactionPayload.transfer.memo.isPresent,
257261
isEnoughFunds = transactionCost.cost <= accountAtDisposalBalance
258262
&& tokenAmount <= token.balance,
263+
showCooldownWarning = false,
259264
sponsor = null,
260265
appMetadata = appMetadata,
261266
)
262267
}
268+
269+
else -> error("The wallet only supports CCD and token transfers")
263270
}
264271

265272
emitState(reviewState)
@@ -278,6 +285,7 @@ class WalletConnectSignTransactionRequestHandler(
278285
is AccountTransactionPayload.PltTransfer -> getProtocolLevelTokenTransferCost(
279286
pltTransferPayload = transactionPayload,
280287
)
288+
else -> error("The wallet only supports CCD and token transfers")
281289
}
282290

283291
private suspend fun getTransferCost(
@@ -382,6 +390,8 @@ class WalletConnectSignTransactionRequestHandler(
382390
pltTransferPayload = transactionPayload,
383391
signer = accountKeys.getSignerEntry(),
384392
)
393+
394+
else -> error("The wallet only supports CCD and token transfers")
385395
}
386396

387397
respondSuccess(App.appCore.gson.toJson(TransactionSuccess(submissionId)))
@@ -531,6 +541,8 @@ class WalletConnectSignTransactionRequestHandler(
531541
)
532542
)
533543
}
544+
545+
else -> error("The wallet only supports CCD and token transfers")
534546
}
535547
}
536548

@@ -546,11 +558,13 @@ class WalletConnectSignTransactionRequestHandler(
546558
when (transactionPayload) {
547559
is AccountTransactionPayload.Transfer,
548560
is AccountTransactionPayload.PltTransfer,
549-
->
561+
->
550562
context.getString(R.string.transaction_type_transfer)
551563

552564
is AccountTransactionPayload.Update ->
553565
transactionPayload.receiveName
566+
567+
else -> error("The wallet only supports CCD and token transfers")
554568
}
555569

556570
companion object {

app/src/main/java/com/concordium/wallet/ui/walletconnect/WalletConnectView.kt

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class WalletConnectView(
7272
when (state) {
7373
is WalletConnectViewModel.State.SessionProposalReview,
7474
is WalletConnectViewModel.State.SessionRequestReview,
75-
-> {
75+
-> {
7676
val lifecycleState = lifecycle.currentState
7777
if (lifecycleState >= Lifecycle.State.CREATED
7878
&& lifecycleState < Lifecycle.State.STARTED
@@ -137,8 +137,12 @@ class WalletConnectView(
137137
estimatedFee = state.estimatedFee,
138138
canShowDetails = state.canShowDetails,
139139
isEnoughFunds = state.isEnoughFunds,
140+
showCooldownWarning = state.showCooldownWarning,
140141
sponsor = state.sponsor,
141142
account = state.account,
143+
delegationRestakeEarnings = state.delegationRestakeEarnings,
144+
delegationType = state.delegationType,
145+
delegationPoolId = state.delegationPoolId,
142146
appMetadata = state.appMetadata,
143147
)
144148
}
@@ -223,7 +227,7 @@ class WalletConnectView(
223227
val duration = when (event.error) {
224228
WalletConnectViewModel.Error.ConnectionFailed,
225229
WalletConnectViewModel.Error.AccountNotFound,
226-
->
230+
->
227231
Toast.LENGTH_LONG
228232

229233
else ->
@@ -355,8 +359,12 @@ class WalletConnectView(
355359
estimatedFee: BigInteger,
356360
canShowDetails: Boolean,
357361
isEnoughFunds: Boolean,
362+
showCooldownWarning: Boolean,
358363
sponsor: String?,
359364
account: Account,
365+
delegationRestakeEarnings: Boolean,
366+
delegationType: String,
367+
delegationPoolId: String,
360368
appMetadata: WalletConnectViewModel.AppMetadata,
361369
) {
362370
getShownBottomSheet().showTransactionRequestReview { (view, lifecycleOwner) ->
@@ -370,8 +378,12 @@ class WalletConnectView(
370378
estimatedFee = estimatedFee,
371379
canShowDetails = canShowDetails,
372380
isEnoughFunds = isEnoughFunds,
381+
showCooldownWarning = showCooldownWarning,
373382
sponsor = sponsor,
374383
account = account,
384+
delegationRestakeEarnings = delegationRestakeEarnings,
385+
delegationType = delegationType,
386+
delegationPoolId = delegationPoolId,
375387
appMetadata = appMetadata,
376388
)
377389
}
@@ -388,8 +400,12 @@ class WalletConnectView(
388400
estimatedFee: BigInteger,
389401
canShowDetails: Boolean,
390402
isEnoughFunds: Boolean,
403+
showCooldownWarning: Boolean,
391404
sponsor: String?,
392405
account: Account,
406+
delegationRestakeEarnings: Boolean,
407+
delegationType: String,
408+
delegationPoolId: String,
393409
appMetadata: WalletConnectViewModel.AppMetadata,
394410
) = with(view) {
395411
Glide.with(appIconImageView.context)
@@ -462,6 +478,17 @@ class WalletConnectView(
462478
sponsoredLabel.isVisible = false
463479
}
464480

481+
if (delegationType.isNotEmpty()) {
482+
transactionDataLayout.isVisible = false
483+
delegationDataLayout.isVisible = true
484+
delegationTarget.text = delegationPoolId.ifEmpty { delegationType }
485+
delegationRewards.text =
486+
if (delegationRestakeEarnings) root.context.getString(R.string.delegation_status_added_to_delegation_amount)
487+
else root.context.getString(R.string.delegation_status_at_disposal)
488+
} else {
489+
delegationDataLayout.isVisible = false
490+
}
491+
465492
errorTextView.isVisible = !isEnoughFunds
466493
errorTextView.text =
467494
when {
@@ -481,6 +508,8 @@ class WalletConnectView(
481508
}
482509
}
483510

511+
delegationWarning.isVisible = showCooldownWarning
512+
484513
declineButton.setOnClickListener {
485514
viewModel.rejectSessionRequest()
486515
}

app/src/main/java/com/concordium/wallet/ui/walletconnect/WalletConnectViewModel.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,7 +1259,11 @@ private constructor(
12591259
val estimatedFee: BigInteger,
12601260
val canShowDetails: Boolean,
12611261
val isEnoughFunds: Boolean,
1262+
val showCooldownWarning: Boolean,
12621263
val sponsor: String?,
1264+
val delegationRestakeEarnings: Boolean = false,
1265+
val delegationType: String = "",
1266+
val delegationPoolId: String = "",
12631267
account: Account,
12641268
appMetadata: AppMetadata,
12651269
) : SessionRequestReview(

0 commit comments

Comments
 (0)