Skip to content

Commit 6b94cef

Browse files
authored
Merge pull request #813 from synonymdev/fix/unpaid-order-import
fix: settle invalid migration transfers from unpaid orders
2 parents e6dcb4b + 25d776a commit 6b94cef

3 files changed

Lines changed: 58 additions & 3 deletions

File tree

app/src/main/java/to/bitkit/repositories/TransferRepo.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package to.bitkit.repositories
22

33
import com.synonym.bitkitcore.Activity
44
import com.synonym.bitkitcore.ActivityFilter
5+
import com.synonym.bitkitcore.BtOrderState2
56
import com.synonym.bitkitcore.SortDirection
67
import kotlinx.coroutines.CoroutineDispatcher
78
import kotlinx.coroutines.flow.Flow
@@ -111,6 +112,15 @@ class TransferRepo @Inject constructor(
111112
if (channel != null && channel.isChannelReady) {
112113
markSettled(transfer.id)
113114
Logger.debug("Channel $channelId ready, settled transfer: ${transfer.id}", context = TAG)
115+
} else if (channelId == null && transfer.lspOrderId != null) {
116+
val order = blocktankRepo.getOrder(transfer.lspOrderId, refresh = false).getOrNull()
117+
if (order?.state2 == BtOrderState2.EXPIRED) {
118+
markSettled(transfer.id)
119+
Logger.info(
120+
"Order ${transfer.lspOrderId} expired, settled transfer: ${transfer.id}",
121+
context = TAG,
122+
)
123+
}
114124
}
115125
}
116126

app/src/main/java/to/bitkit/services/MigrationService.kt

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import androidx.datastore.preferences.core.stringPreferencesKey
88
import androidx.datastore.preferences.preferencesDataStore
99
import com.synonym.bitkitcore.Activity
1010
import com.synonym.bitkitcore.ActivityTags
11+
import com.synonym.bitkitcore.BtOrderState2
1112
import com.synonym.bitkitcore.ClosedChannelDetails
1213
import com.synonym.bitkitcore.LightningActivity
1314
import com.synonym.bitkitcore.OnchainActivity
@@ -53,7 +54,6 @@ import to.bitkit.models.TransactionSpeed
5354
import to.bitkit.models.TransferType
5455
import to.bitkit.models.WidgetType
5556
import to.bitkit.models.WidgetWithPosition
56-
import to.bitkit.models.safe
5757
import to.bitkit.models.widget.BlocksPreferences
5858
import to.bitkit.models.widget.FactsPreferences
5959
import to.bitkit.models.widget.HeadlinePreferences
@@ -94,6 +94,7 @@ class MigrationService @Inject constructor(
9494
private const val RN_PENDING_BOOSTS_KEY = "rnPendingBoosts"
9595
private const val RN_CHANNEL_RECOVERY_CHECKED_KEY = "rnChannelRecoveryChecked"
9696
private const val RN_DID_ATTEMPT_PEER_RECOVERY_KEY = "rnDidAttemptMigrationPeerRecovery"
97+
private const val RN_DID_CLEANUP_INVALID_TRANSFERS_KEY = "didCleanupInvalidMigrationTransfers"
9798
private const val OPENING_CURLY_BRACE = "{"
9899
private const val MMKV_ROOT = "persist:root"
99100
private const val RN_WALLET_NAME = "wallet0"
@@ -1303,6 +1304,43 @@ class MigrationService @Inject constructor(
13031304
}.getOrDefault(emptyList())
13041305
}
13051306

1307+
suspend fun cleanupInvalidMigrationTransfers() {
1308+
val key = stringPreferencesKey(RN_DID_CLEANUP_INVALID_TRANSFERS_KEY)
1309+
if (rnMigrationStore.data.first()[key] == "true") return
1310+
if (!isRnMigrationCompleted()) return
1311+
1312+
val transfers = transferDao.getActiveTransfers().first()
1313+
.filter { it.type == TransferType.TO_SPENDING && it.lspOrderId != null }
1314+
1315+
if (transfers.isEmpty()) {
1316+
rnMigrationStore.edit { it[key] = "true" }
1317+
return
1318+
}
1319+
1320+
val orderIds = transfers.mapNotNull { it.lspOrderId }
1321+
val orders = runCatching {
1322+
coreService.blocktank.orders(orderIds = orderIds, filter = null, refresh = true)
1323+
}.onFailure {
1324+
Logger.warn("Cannot cleanup migration transfers: Blocktank unreachable", it, context = TAG)
1325+
}.getOrNull() ?: return
1326+
1327+
val now = System.currentTimeMillis() / MS_PER_SEC
1328+
for (transfer in transfers) {
1329+
val order = orders.find { it.id == transfer.lspOrderId } ?: continue
1330+
if (order.state2 != BtOrderState2.PAID) {
1331+
transferDao.markSettled(transfer.id, now)
1332+
Logger.info(
1333+
"Cleanup: settled invalid migration transfer ${transfer.id} " +
1334+
"for order ${transfer.lspOrderId} (state: ${order.state2})",
1335+
context = TAG,
1336+
)
1337+
}
1338+
}
1339+
1340+
rnMigrationStore.edit { it[key] = "true" }
1341+
Logger.info("Migration transfer cleanup completed", context = TAG)
1342+
}
1343+
13061344
suspend fun cleanupAfterMigration() {
13071345
clearPersistedMigrationData()
13081346
setNeedsPostMigrationSync(false)
@@ -1517,11 +1555,17 @@ class MigrationService @Inject constructor(
15171555
null
15181556
}
15191557

1520-
order.state2 == com.synonym.bitkitcore.BtOrderState2.EXECUTED -> null
1558+
order.state2 != BtOrderState2.PAID -> {
1559+
Logger.debug(
1560+
"Skipping order $orderId with state ${order.state2} for transfer creation",
1561+
context = TAG,
1562+
)
1563+
null
1564+
}
15211565
else -> TransferEntity(
15221566
id = txId,
15231567
type = TransferType.TO_SPENDING,
1524-
amountSats = (order.clientBalanceSat.safe() + order.feeSat.safe()).toLong(),
1568+
amountSats = order.clientBalanceSat.toLong(),
15251569
channelId = null,
15261570
fundingTxId = null,
15271571
lspOrderId = orderId,

app/src/main/java/to/bitkit/viewmodels/WalletViewModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ class WalletViewModel @Inject constructor(
294294
}
295295
walletRepo.setWalletExistsState()
296296
connectMigrationPeers()
297+
migrationService.cleanupInvalidMigrationTransfers()
297298
walletRepo.syncBalances()
298299
if (_restoreState.value.isIdle()) {
299300
walletRepo.refreshBip21()

0 commit comments

Comments
 (0)