@@ -13,13 +13,16 @@ import com.flowfoundation.wallet.manager.walletdata.COAWallet
1313import com.flowfoundation.wallet.manager.walletdata.ChildWallet
1414import com.flowfoundation.wallet.manager.walletdata.EOAWallet
1515import com.flowfoundation.wallet.manager.walletdata.FlowWallet
16+ import com.flowfoundation.wallet.network.ApiService
17+ import com.flowfoundation.wallet.network.retrofitApi
1618import com.flowfoundation.wallet.page.main.model.WalletAccountData
1719import com.flowfoundation.wallet.page.main.model.LinkedAccountData
1820import com.flowfoundation.wallet.utils.formatLargeBalanceNumber
1921import com.flowfoundation.wallet.utils.ioScope
2022import kotlinx.coroutines.flow.MutableStateFlow
2123import kotlinx.coroutines.flow.StateFlow
2224import kotlinx.coroutines.flow.asStateFlow
25+ import java.math.BigDecimal
2326
2427class AccountListViewModel : ViewModel (), OnEmojiUpdate {
2528
@@ -32,6 +35,11 @@ class AccountListViewModel : ViewModel(), OnEmojiUpdate {
3235 private val _hiddenAccounts = MutableStateFlow <Set <String >>(emptySet())
3336 val hiddenAccounts: StateFlow <Set <String >> = _hiddenAccounts .asStateFlow()
3437
38+ private val service by lazy { retrofitApi().create(ApiService ::class .java) }
39+
40+ // Cache for verified EVM addresses that should be included in linkedAccounts
41+ private val verifiedEvmAddresses = mutableSetOf<String >()
42+
3543 init {
3644 AccountEmojiManager .addListener(this )
3745 }
@@ -47,6 +55,7 @@ class AccountListViewModel : ViewModel(), OnEmojiUpdate {
4755
4856 val addressList = mutableListOf<String >()
4957 val accounts = mutableListOf<WalletAccountData >()
58+ val pendingEvmAddresses = mutableListOf<Pair <String , String >>() // EVM address to wallet address mapping
5059
5160 walletNodes.forEach { mainNode ->
5261 when (mainNode) {
@@ -86,17 +95,22 @@ class AccountListViewModel : ViewModel(), OnEmojiUpdate {
8695 is COAWallet -> {
8796 val evmAddress = linkedWallet.address
8897 addressList.add(evmAddress)
89- val linkedEmojiInfo = AccountEmojiManager .getEmojiByAddress(evmAddress)
90- linkedAccounts.add(
91- LinkedAccountData (
92- address = evmAddress,
93- name = linkedEmojiInfo.emojiName,
94- icon = null ,
95- emojiId = linkedEmojiInfo.emojiId,
96- isSelected = WalletManager .selectedWalletAddress().equals(evmAddress, ignoreCase = true ),
97- isCOAAccount = true
98+ // Restore logic: Only add if verified, otherwise add to pending
99+ if (evmAddress !in verifiedEvmAddresses) {
100+ pendingEvmAddresses.add(Pair (evmAddress, mainNode.address))
101+ } else {
102+ val linkedEmojiInfo = AccountEmojiManager .getEmojiByAddress(evmAddress)
103+ linkedAccounts.add(
104+ LinkedAccountData (
105+ address = evmAddress,
106+ name = linkedEmojiInfo.emojiName,
107+ icon = null ,
108+ emojiId = linkedEmojiInfo.emojiId,
109+ isSelected = WalletManager .selectedWalletAddress().equals(evmAddress, ignoreCase = true ),
110+ isCOAAccount = true
111+ )
98112 )
99- )
113+ }
100114 }
101115 }
102116 }
@@ -131,18 +145,88 @@ class AccountListViewModel : ViewModel(), OnEmojiUpdate {
131145 }
132146
133147 if (refreshBalance) {
134- fetchAllBalances(addressList)
148+ fetchAllBalances(addressList, pendingEvmAddresses )
135149 }
136150 }
137151 }
138152
139- private fun fetchAllBalances (addressList : List <String >) {
153+ private fun fetchAllBalances (addressList : List <String >, pendingEvmAddresses : List < Pair < String , String >> = emptyList() ) {
140154 ioScope {
141155 val balanceMap = cadenceGetAllFlowBalance(addressList) ? : return @ioScope
142156 val formattedBalanceMap = balanceMap.mapValues { (_, balance) ->
143157 " ${balance.formatLargeBalanceNumber(isAbbreviation = true )} FLOW"
144158 }
145159 _balanceMap .value = formattedBalanceMap
160+
161+ // Check each pending EVM address
162+ pendingEvmAddresses.forEach { (evmAddress, walletAddress) ->
163+ val evmBalance = balanceMap[evmAddress]
164+ val hasBalance = evmBalance != null && evmBalance > BigDecimal .ZERO
165+ var hasNFTs = false
166+
167+ if (! hasBalance) {
168+ try {
169+ val nftResponse = service.getEVMNFTCollections(evmAddress)
170+ val totalNftCount = nftResponse.data?.sumOf { it.count ? : 0 } ? : 0
171+ hasNFTs = nftResponse.data?.isNotEmpty() == true && totalNftCount > 0
172+ } catch (e: Exception ) {
173+ // Ignore NFT API errors
174+ }
175+ }
176+
177+ if (hasBalance || hasNFTs) {
178+ // Add EVM address to linked accounts
179+ val currentAccounts = _accounts .value.toMutableList()
180+ val walletAccount = currentAccounts.find { it.address == walletAddress }
181+ walletAccount?.let { account ->
182+ // Check if EVM address already exists in linked accounts
183+ val alreadyExists = account.linkedAccounts.any { it.address == evmAddress }
184+ if (! alreadyExists) {
185+ val emojiInfo = AccountEmojiManager .getEmojiByAddress(evmAddress)
186+ val updatedLinkedAccounts = account.linkedAccounts.toMutableList()
187+ updatedLinkedAccounts.add(
188+ LinkedAccountData (
189+ address = evmAddress,
190+ name = emojiInfo.emojiName,
191+ icon = null ,
192+ emojiId = emojiInfo.emojiId,
193+ isSelected = WalletManager .selectedWalletAddress().equals(evmAddress, ignoreCase = true ),
194+ isCOAAccount = true
195+ )
196+ )
197+ val updatedAccount = account.copy(linkedAccounts = updatedLinkedAccounts)
198+ val accountIndex = currentAccounts.indexOfFirst { it.address == walletAddress }
199+ if (accountIndex >= 0 ) {
200+ currentAccounts[accountIndex] = updatedAccount
201+ _accounts .value = currentAccounts
202+ }
203+ }
204+ // Add to verified cache for future refreshWalletList calls
205+ verifiedEvmAddresses.add(evmAddress)
206+ }
207+ } else {
208+ // Remove EVM address from linked accounts if it no longer has assets
209+ // (Though typically it wouldn't be there yet if it was pending,
210+ // this handles the case where it might have been removed or balance drained)
211+ val currentAccounts = _accounts .value.toMutableList()
212+ val walletAccount = currentAccounts.find { it.address == walletAddress }
213+ walletAccount?.let { account ->
214+ val existingLinkedAccount = account.linkedAccounts.find { it.address == evmAddress }
215+ if (existingLinkedAccount != null ) {
216+ val updatedLinkedAccounts = account.linkedAccounts.toMutableList()
217+ updatedLinkedAccounts.removeAll { it.address == evmAddress }
218+ val updatedAccount = account.copy(linkedAccounts = updatedLinkedAccounts)
219+ val accountIndex = currentAccounts.indexOfFirst { it.address == walletAddress }
220+ if (accountIndex >= 0 ) {
221+ currentAccounts[accountIndex] = updatedAccount
222+ _accounts .value = currentAccounts
223+ }
224+ }
225+ }
226+ // Remove from verified cache
227+ verifiedEvmAddresses.remove(evmAddress)
228+ }
229+ }
146230 }
147231 }
148232
0 commit comments