@@ -2,38 +2,26 @@ package to.bitkit.ui.sheets
22
33import androidx.lifecycle.ViewModel
44import androidx.lifecycle.viewModelScope
5- import com.synonym.bitkitcore.Activity
6- import com.synonym.bitkitcore.PaymentType
7- import com.synonym.bitkitcore.giftOrder
8- import com.synonym.bitkitcore.giftPay
95import dagger.hilt.android.lifecycle.HiltViewModel
106import kotlinx.coroutines.CoroutineDispatcher
11- import kotlinx.coroutines.delay
127import kotlinx.coroutines.flow.MutableSharedFlow
138import kotlinx.coroutines.flow.asSharedFlow
149import kotlinx.coroutines.launch
1510import kotlinx.coroutines.withContext
16- import to.bitkit.async.ServiceQueue
1711import to.bitkit.di.BgDispatcher
18- import to.bitkit.ext.calculateRemoteBalance
1912import to.bitkit.models.NewTransactionSheetDetails
2013import to.bitkit.models.NewTransactionSheetDirection
2114import to.bitkit.models.NewTransactionSheetType
22- import to.bitkit.repositories.ActivityRepo
2315import to.bitkit.repositories.BlocktankRepo
24- import to.bitkit.repositories.LightningRepo
25- import to.bitkit.services.LightningService
16+ import to.bitkit.repositories.GiftClaimResult
2617import to.bitkit.utils.Logger
2718import javax.inject.Inject
2819import kotlin.time.Duration.Companion.milliseconds
2920
3021@HiltViewModel
3122class GiftViewModel @Inject constructor(
3223 @BgDispatcher private val bgDispatcher : CoroutineDispatcher ,
33- private val lightningRepo : LightningRepo ,
34- private val lightningService : LightningService ,
3524 private val blocktankRepo : BlocktankRepo ,
36- private val activityRepo : ActivityRepo ,
3725) : ViewModel() {
3826
3927 private val _navigationEvent = MutableSharedFlow <GiftRoute >(extraBufferCapacity = 1 )
@@ -65,98 +53,39 @@ class GiftViewModel @Inject constructor(
6553 }
6654 }
6755
68- @Suppress(" TooGenericExceptionCaught" )
6956 private suspend fun claimGift () = withContext(bgDispatcher) {
7057 if (isClaiming) return @withContext
7158 isClaiming = true
7259
73- try {
74- lightningRepo.executeWhenNodeRunning(
75- operationName = " waitForNodeRunning" ,
76- waitTimeout = NODE_STARTUP_TIMEOUT_MS .milliseconds,
77- ) {
78- Result .success(Unit )
79- }.getOrThrow()
80-
81- delay(PEER_CONNECTION_DELAY_MS )
82-
83- val channels = lightningRepo.lightningState.value.channels
84- val maxInboundCapacity = channels.calculateRemoteBalance()
85-
86- if (maxInboundCapacity >= amount) {
87- claimWithLiquidity()
88- } else {
89- claimWithoutLiquidity()
90- }
91- } catch (e: Exception ) {
92- handleGiftClaimError(e)
93- } finally {
94- isClaiming = false
95- }
96- }
97-
98- private suspend fun claimWithLiquidity () {
99- runCatching {
100- val invoice = lightningService.receive(
101- sat = null ,
102- description = " blocktank-gift-code:$code " ,
103- expirySecs = 3600u ,
104- )
105-
106- ServiceQueue .CORE .background {
107- giftPay(invoice = invoice)
60+ blocktankRepo.claimGiftCode(
61+ code = code,
62+ amount = amount,
63+ waitTimeout = NODE_STARTUP_TIMEOUT_MS .milliseconds,
64+ ).fold(
65+ onSuccess = { result ->
66+ when (result) {
67+ is GiftClaimResult .SuccessWithLiquidity -> {
68+ _navigationEvent .emit(GiftRoute .Success )
69+ }
70+ is GiftClaimResult .SuccessWithoutLiquidity -> {
71+ _successEvent .emit(
72+ NewTransactionSheetDetails (
73+ type = NewTransactionSheetType .LIGHTNING ,
74+ direction = NewTransactionSheetDirection .RECEIVED ,
75+ paymentHashOrTxId = result.paymentHashOrTxId,
76+ sats = result.sats,
77+ )
78+ )
79+ _navigationEvent .emit(GiftRoute .Success )
80+ }
81+ }
82+ },
83+ onFailure = { error ->
84+ handleGiftClaimError(error)
10885 }
86+ )
10987
110- _navigationEvent .emit(GiftRoute .Success )
111- }.onFailure { e ->
112- handleGiftClaimError(e)
113- }
114- }
115-
116- private suspend fun claimWithoutLiquidity () {
117- runCatching {
118- check(lightningService.nodeId != null ) { " Node not started" }
119- val nodeId = lightningService.nodeId!!
120-
121- val order = ServiceQueue .CORE .background {
122- giftOrder(clientNodeId = nodeId, code = " blocktank-gift-code:$code " )
123- }
124-
125- check(order.orderId != null ) { " Order ID is nil" }
126- val orderId = order.orderId!!
127-
128- val openedOrder = blocktankRepo.openChannel(orderId).getOrThrow()
129-
130- val nowTimestamp = (System .currentTimeMillis() / 1000 ).toULong()
131-
132- val lightningActivity = com.synonym.bitkitcore.LightningActivity (
133- id = openedOrder.channel?.fundingTx?.id ? : orderId,
134- txType = PaymentType .RECEIVED ,
135- status = com.synonym.bitkitcore.PaymentState .SUCCEEDED ,
136- value = amount,
137- fee = 0u ,
138- invoice = openedOrder.payment?.bolt11Invoice?.request ? : " " ,
139- message = code,
140- timestamp = nowTimestamp,
141- preimage = null ,
142- createdAt = nowTimestamp,
143- updatedAt = null ,
144- )
145-
146- activityRepo.insertActivity(Activity .Lightning (lightningActivity)).getOrThrow()
147-
148- _successEvent .emit(
149- NewTransactionSheetDetails (
150- type = NewTransactionSheetType .LIGHTNING ,
151- direction = NewTransactionSheetDirection .RECEIVED ,
152- paymentHashOrTxId = openedOrder.channel?.fundingTx?.id ? : orderId,
153- sats = amount.toLong(),
154- )
155- )
156- _navigationEvent .emit(GiftRoute .Success )
157- }.onFailure { e ->
158- handleGiftClaimError(e)
159- }
88+ isClaiming = false
16089 }
16190
16291 private suspend fun handleGiftClaimError (error : Throwable ) {
@@ -186,6 +115,5 @@ class GiftViewModel @Inject constructor(
186115 companion object {
187116 private const val TAG = " GiftViewModel"
188117 private const val NODE_STARTUP_TIMEOUT_MS = 30_000L
189- private const val PEER_CONNECTION_DELAY_MS = 2_000L
190118 }
191119}
0 commit comments