Skip to content

Commit

Permalink
burn
Browse files Browse the repository at this point in the history
  • Loading branch information
polstianka committed Oct 5, 2024
1 parent aec5035 commit 2c1f974
Show file tree
Hide file tree
Showing 18 changed files with 284 additions and 8 deletions.
4 changes: 4 additions & 0 deletions apps/wallet/api/src/main/java/com/tonapps/wallet/api/API.kt
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,10 @@ class API(
return defaultHttpClient.get(url, headers)
}

fun getBurnAddress() = config.burnZeroDomain.ifBlank {
"UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ"
}

fun getEvents(
accountId: String,
testnet: Boolean,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ data class ConfigEntity(
val tonapiSSEEndpoint: String,
val tonapiSSETestnetEndpoint: String,
val iapPackages: List<IAPPackageEntity>,
val burnZeroDomain: String,
): Parcelable {

val swapUri: Uri
Expand Down Expand Up @@ -97,7 +98,8 @@ data class ConfigEntity(
tonapiSSETestnetEndpoint = json.optString("tonapi_sse_testnet_endpoint", "https://rt-testnet.tonapi.io"),
iapPackages = json.optJSONArray("iap_packages")?.let { array ->
(0 until array.length()).map { IAPPackageEntity(array.getJSONObject(it)) }
} ?: emptyList()
} ?: emptyList(),
burnZeroDomain = json.optString("burnZeroDomain", "tonkeeper-zero.ton")
)

constructor() : this(
Expand Down Expand Up @@ -138,7 +140,8 @@ data class ConfigEntity(
stakingInfoUrl = "https://ton.org/stake",
tonapiSSEEndpoint = "https://rt.tonapi.io",
tonapiSSETestnetEndpoint = "https://rt-testnet.tonapi.io",
iapPackages = emptyList()
iapPackages = emptyList(),
burnZeroDomain = "tonkeeper-zero.ton"
)

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package com.tonapps.tonkeeper.core.history
import android.content.Context
import android.util.Log
import androidx.collection.arrayMapOf
import com.tonapps.blockchain.ton.extensions.equalsAddress
import com.tonapps.blockchain.ton.extensions.toRawAddress
import com.tonapps.icu.Coins
import com.tonapps.blockchain.ton.extensions.toUserFriendly
import com.tonapps.extensions.max24
Expand Down Expand Up @@ -35,6 +37,7 @@ import com.tonapps.tonkeeper.helper.DateHelper
import com.tonapps.tonkeeper.ui.screen.dialog.encrypted.EncryptedCommentScreen
import com.tonapps.tonkeeper.usecase.emulation.Emulated
import com.tonapps.uikit.list.ListCell
import com.tonapps.wallet.api.API
import com.tonapps.wallet.api.entity.TokenEntity
import com.tonapps.wallet.data.account.AccountRepository
import com.tonapps.wallet.data.account.entities.WalletEntity
Expand All @@ -47,6 +50,7 @@ import com.tonapps.wallet.data.rates.RatesRepository
import com.tonapps.wallet.data.rates.entity.RatesEntity
import com.tonapps.wallet.data.settings.SettingsRepository
import com.tonapps.wallet.localization.Localization
import io.tonapi.models.Account
import io.tonapi.models.JettonVerificationType
import io.tonapi.models.MessageConsequences
import kotlinx.coroutines.flow.Flow
Expand Down Expand Up @@ -75,6 +79,7 @@ class HistoryHelper(
private val settingsRepository: SettingsRepository,
private val eventsRepository: EventsRepository,
private val passcodeManager: PasscodeManager,
private val api: API,
) {

private val currency: WalletCurrency
Expand Down Expand Up @@ -119,6 +124,14 @@ class HistoryHelper(
}
}

private fun isBurnAccount(account: AccountAddress): Boolean {
val burnAddress = api.getBurnAddress()
if (burnAddress.equalsAddress(account.address) || (account.name != null && burnAddress == account.name)) {
return true
}
return "UQCNzZIsoe75gjl8KIwUJW1Fawt-7IbsFwd0ubGIFkig159E".equalsAddress(account.address)
}

private fun sort(list: List<HistoryItem>): List<HistoryItem.Event> {
return list
.filterIsInstance<HistoryItem.Event>()
Expand Down Expand Up @@ -471,13 +484,21 @@ class HistoryHelper(
val symbol = jettonTransfer.jetton.symbol
val isOut = !wallet.isMyAddress(jettonTransfer.recipient?.address ?: "")

val isBurn = jettonTransfer.recipient?.let {
isBurnAccount(it)
} ?: false

val amount = Coins.ofNano(jettonTransfer.amount, jettonTransfer.jetton.decimals)
var value = CurrencyFormatter.format(symbol, amount, 2)

val itemAction: ActionType
val accountAddress: AccountAddress?

if (isOut) {
if (isBurn) {
itemAction = ActionType.JettonBurn
accountAddress = jettonTransfer.recipient
value = value.withMinus
} else if (isOut) {
itemAction = ActionType.Send
accountAddress = jettonTransfer.recipient
value = value.withMinus
Expand All @@ -502,7 +523,11 @@ class HistoryHelper(
iconURL = accountAddress?.iconURL ?: "",
action = itemAction,
title = simplePreview.name,
subtitle = accountAddress?.getNameOrAddress(wallet.testnet, true) ?: "",
subtitle = if (!isBurn) {
accountAddress?.getNameOrAddress(wallet.testnet, true) ?: ""
} else {
api.getBurnAddress()
},
comment = comment,
value = value,
tokenCode = "",
Expand Down Expand Up @@ -602,12 +627,19 @@ class HistoryHelper(

val isOut = !wallet.isMyAddress(nftItemTransfer.recipient?.address ?: "-")
val sender = nftItemTransfer.sender ?: action.simplePreview.accounts.firstOrNull()
val isBurn = nftItemTransfer.recipient?.let {
isBurnAccount(it)
} ?: false

val itemAction: ActionType
val iconURL: String?
val subtitle: String

if (isOut) {
if (isBurn) {
itemAction = ActionType.JettonBurn
iconURL = nftItemTransfer.recipient?.iconURL
subtitle = api.getBurnAddress()
} else if (isOut) {
itemAction = ActionType.NftSend
iconURL = nftItemTransfer.recipient?.iconURL
subtitle = sender?.getNameOrAddress(wallet.testnet, true) ?: ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ import android.widget.Button
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.net.toUri
import androidx.core.widget.NestedScrollView
import androidx.lifecycle.lifecycleScope
import com.tonapps.blockchain.ton.extensions.toWalletAddress
import com.tonapps.extensions.getParcelableCompat
import com.tonapps.extensions.short4
import com.tonapps.tonkeeper.extensions.copyWithToast
import com.tonapps.tonkeeper.extensions.showToast
import com.tonapps.tonkeeper.extensions.toastLoading
import com.tonapps.tonkeeper.koin.remoteConfig
import com.tonapps.tonkeeper.koin.walletViewModel
import com.tonapps.tonkeeper.popup.ActionSheet
Expand All @@ -29,6 +33,11 @@ import com.tonapps.wallet.data.account.entities.WalletEntity
import com.tonapps.wallet.data.collectibles.entities.NftEntity
import com.tonapps.wallet.data.core.Trust
import com.tonapps.wallet.localization.Localization
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.koin.core.parameter.parametersOf
import uikit.base.BaseFragment
import uikit.dialog.alert.AlertDialog
Expand Down Expand Up @@ -190,6 +199,15 @@ class NftScreen(wallet: WalletEntity): WalletContextScreen(R.layout.fragment_nft
}
}

private fun burn() {
navigation?.add(SendScreen.newInstance(
wallet = wallet,
targetAddress = viewModel.burnAddress,
nftAddress = nftEntity.address
))
finish()
}

private fun mustOpenButtonDApp(url: String) {
navigation?.add(DAppScreen.newInstance(wallet, url = url.toUri()))
finish()
Expand All @@ -215,11 +233,15 @@ class NftScreen(wallet: WalletEntity): WalletContextScreen(R.layout.fragment_nft
actionSheet.addItem(HIDE_NFT_ID, Localization.hide_collection, UIKitIcon.ic_eye_disable_16)
actionSheet.addItem(HIDE_AND_REPORT_ID, Localization.hide_and_report_collection, UIKitIcon.ic_block_16)
actionSheet.addItem(VIEWER_ID, Localization.open_tonviewer, UIKitIcon.ic_globe_16)
if (!nftEntity.inSale && !nftEntity.isTrusted) {
actionSheet.addItem(BURN_ID, Localization.burn, UIKitIcon.ic_fire_badge_16)
}
actionSheet.doOnItemClick = { item ->
when (item.id) {
HIDE_NFT_ID -> hideCollection()
HIDE_AND_REPORT_ID -> reportSpam(true)
VIEWER_ID -> openTonViewer()
BURN_ID -> burn()
}
}
actionSheet.show(view)
Expand All @@ -229,10 +251,14 @@ class NftScreen(wallet: WalletEntity): WalletContextScreen(R.layout.fragment_nft
val actionSheet = ActionSheet(requireContext())
actionSheet.addItem(HIDE_NFT_ID, Localization.hide_collection, UIKitIcon.ic_eye_disable_16)
actionSheet.addItem(VIEWER_ID, Localization.open_tonviewer, UIKitIcon.ic_globe_16)
if (!nftEntity.inSale && !nftEntity.isTrusted) {
actionSheet.addItem(BURN_ID, Localization.burn, UIKitIcon.ic_fire_badge_16)
}
actionSheet.doOnItemClick = { item ->
when (item.id) {
HIDE_NFT_ID -> hideCollection()
VIEWER_ID -> openTonViewer()
BURN_ID -> burn()
}
}
actionSheet.show(view)
Expand Down Expand Up @@ -306,6 +332,7 @@ class NftScreen(wallet: WalletEntity): WalletContextScreen(R.layout.fragment_nft
private const val HIDE_NFT_ID = 1L
private const val HIDE_AND_REPORT_ID = 2L
private const val VIEWER_ID = 3L
private const val BURN_ID = 4L

private const val ARG_ENTITY = "entity"

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,42 @@
package com.tonapps.tonkeeper.ui.screen.nft

import android.app.Application
import android.content.Context
import androidx.lifecycle.viewModelScope
import com.tonapps.blockchain.ton.TonNetwork
import com.tonapps.blockchain.ton.TonTransferHelper
import com.tonapps.blockchain.ton.extensions.EmptyPrivateKeyEd25519
import com.tonapps.blockchain.ton.extensions.base64
import com.tonapps.blockchain.ton.extensions.toAccountId
import com.tonapps.icu.Coins
import com.tonapps.tonkeeper.core.entities.SendMetadataEntity
import com.tonapps.tonkeeper.core.entities.TransferEntity
import com.tonapps.tonkeeper.extensions.toGrams
import com.tonapps.tonkeeper.ui.base.BaseWalletVM
import com.tonapps.tonkeeper.ui.screen.send.main.helper.SendNftHelper
import com.tonapps.tonkeeper.ui.screen.send.transaction.SendTransactionScreen
import com.tonapps.wallet.api.API
import com.tonapps.wallet.api.entity.TokenEntity
import com.tonapps.wallet.data.account.AccountRepository
import com.tonapps.wallet.data.account.entities.WalletEntity
import com.tonapps.wallet.data.collectibles.entities.NftEntity
import com.tonapps.wallet.data.core.entity.RawMessageEntity
import com.tonapps.wallet.data.core.entity.SignRequestEntity
import com.tonapps.wallet.data.settings.SettingsRepository
import com.tonapps.wallet.data.settings.entities.TokenPrefsEntity
import com.tonapps.wallet.data.token.TokenRepository
import com.tonapps.wallet.data.token.entities.AccountTokenEntity
import io.tonapi.models.Account
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.ton.block.AddrStd
import java.math.BigInteger

class NftViewModel(
app: Application,
Expand All @@ -24,6 +46,10 @@ class NftViewModel(
private val api: API,
): BaseWalletVM(app) {

val burnAddress: String by lazy {
api.getBurnAddress()
}

fun reportSpam(spam: Boolean, callback: () -> Unit) {
viewModelScope.launch(Dispatchers.IO) {
val state = if (spam) TokenPrefsEntity.State.SPAM else TokenPrefsEntity.State.TRUST
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import com.tonapps.tonkeeper.koin.walletViewModel
import com.tonapps.tonkeeper.popup.ActionSheet
import com.tonapps.tonkeeper.ui.base.BaseListWalletScreen
import com.tonapps.tonkeeper.ui.base.ScreenContext
import com.tonapps.tonkeeper.ui.screen.send.main.SendScreen
import com.tonapps.tonkeeper.ui.screen.token.unverified.TokenUnverifiedScreen
import com.tonapps.tonkeeper.ui.screen.token.viewer.list.TokenAdapter
import com.tonapps.tonkeeperx.R
Expand Down Expand Up @@ -115,12 +116,35 @@ class TokenScreen(wallet: WalletEntity): BaseListWalletScreen<ScreenContext.Wall
}

val actionSheet = ActionSheet(requireContext())
actionSheet.addItem(0, Localization.view_details, R.drawable.ic_globe_16)
actionSheet.doOnItemClick = { navigation?.openURL(detailsUrl.toString()) }
actionSheet.addItem(VIEWER_ID, Localization.view_details, R.drawable.ic_globe_16)
if (!token.verified) {
actionSheet.addItem(BURN_ID, Localization.burn, UIKitIcon.ic_fire_badge_16)
}
actionSheet.doOnItemClick = {
if (it.id == VIEWER_ID) {
navigation?.openURL(detailsUrl.toString())
} else if (it.id == BURN_ID) {
burn(token)
}
}
actionSheet.show(view)
}

private fun burn(token: AccountTokenEntity) {
navigation?.add(SendScreen.newInstance(
wallet = screenContext.wallet,
targetAddress = viewModel.burnAddress,
tokenAddress = token.address,
amountNano = token.balance.value.toLong()
))
finish()
}

companion object {

private const val VIEWER_ID = 1L
private const val BURN_ID = 2L

fun newInstance(
wallet: WalletEntity,
address: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ class TokenViewModel(
private val historyHelper: HistoryHelper,
): BaseWalletVM(app) {

val burnAddress: String by lazy {
api.getBurnAddress()
}

private val _tokenFlow = MutableStateFlow<AccountTokenEntity?>(null)
val tokenFlow = _tokenFlow.asStateFlow().filterNotNull()

Expand Down
18 changes: 18 additions & 0 deletions apps/wallet/localization/src/main/res/values-bg/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,23 @@
<string name="all_assets">Всички активи</string>
<string name="sorted_by_price">Сортирано по цена</string>
<string name="spam">Спам</string>
<string name="burn">Изгори</string>
<string name="staking_get_withdraw">Вземете теглене</string>
<string name="staking_withdrawal_amount">Сума за теглене</string>
<string name="staking_pending_withdraw_liquid">%1$s не е заложен след края на цикъла</string>
<string name="expired_link">Изтекла връзка</string>
<string name="payment_method_not_found">Методът на плащане не е наличен</string>
<string name="app_not_found">Приложението не е намерено</string>
<string name="insufficient_balance_in_wallet">Недостатъчно средства в портфейла</string>
<string name="insufficient_balance_fees">Изисква се за такси за блокчейн: %1$s.\\nВашето салдо: %2$s.</string>
<string name="insufficient_balance_default">За плащане: %1$s.\\nВашето салдо: %2$s.</string>
<string name="staking_max_apy" translatable="false">MAX APY</string>
<string name="staking_minimum_deposit">Минимален депозит %1$s.</string>
<string name="staking_options">Опции</string>
<string name="gasless_switch_label">Докоснете, за да платите в %1$s</string>
<string name="battery_disclaimer">Едно таксуване покрива средната такса за транзакция. Някои транзакции може да струват повече.</string>
<string name="restore_purchases">Възстановяване на покупките</string>
<string name="battery_refilled">Заредена батерия</string>
<string name="staking_apy" translatable="false">APY</string>
<string name="staking_minimal_deposit">Минимален депозит</string>
<string name="staking_details_description">Стейкингът е базиран на умни договори от трети страни. Tonkeeper не носи отговорност за изживяването по време на стейкинг.</string>
Expand Down Expand Up @@ -141,6 +154,9 @@
<string name="wallet_initialized">Портфейлът е инициализиран</string>
<string name="bid">Залог</string>
<string name="theme">Тема</string>
<string name="battery_large_pack">Голям</string>
<string name="battery_medium_pack">Среден</string>
<string name="battery_small_pack">Малък</string>
<string name="backup_alert_message">Вашият баланс е %1$s и е защитен само от фраза за възстановяване, която още не сте записали. Архивирайте фразата, за да избегнете загуба на средства в случай на проблеми с устройството.</string>
<string name="testnet" translatable="false">Testnet</string>
<string name="unstake_request">Искане за изтегляне на стейк</string>
Expand Down Expand Up @@ -390,6 +406,7 @@
<string name="signer_about">Относно Signer</string>
<string name="signer_open">Отворете Signer на това устройство</string>
<string name="later">По-късно</string>
<string name="buy_ton">Купете TON</string>
<string name="signer" translatable="false">Signer</string>
<string name="choose_wallet_title">Изберете портфейл</string>
<string name="choose_wallet_subtitle">Изберете портфейли, които искате да добавите.</string>
Expand Down Expand Up @@ -479,4 +496,5 @@
<item quantity="other">≈ %1$s трансфера на токен</item>
</plurals>
<string name="or">или</string>
<string name="recharge_battery">Презареждане на батерията</string>
</resources>
Loading

0 comments on commit 2c1f974

Please sign in to comment.