Skip to content

Commit 652ea86

Browse files
authored
Merge pull request #414 from synonymdev/feat/pending-balance
feat: pending transfer balance & force transfer
2 parents df71c2a + c7f3127 commit 652ea86

File tree

73 files changed

+3548
-635
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+3548
-635
lines changed

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ See also:
4141

4242
- For LNURL dev testing see [bitkit-docker](https://github.com/ovitrif/bitkit-docker)
4343

44-
### Linting
44+
### Lint
4545

4646
This project uses detekt with default ktlint and compose-rules for android code linting.
4747

@@ -56,6 +56,17 @@ Recommended Android Studio plugins:
5656
```
5757
Reports are generated in: `app/build/reports/detekt/`.
5858

59+
## Test
60+
61+
**Commands**
62+
```sh
63+
./gradlew testDevDebugUnitTest # run unit tests
64+
65+
# run android tests:
66+
./gradlew installDevDebug # install
67+
./gradlew connectedDevDebugAndroidTest # run
68+
```
69+
5970
## Localization
6071
See repo: https://github.com/synonymdev/bitkit-transifex-sync
6172

app/build.gradle.kts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
2+
import org.gradle.api.tasks.testing.logging.TestLogEvent
13
import org.jetbrains.kotlin.compose.compiler.gradle.ComposeFeatureFlag
24
import java.io.FileInputStream
35
import java.util.Properties
@@ -281,7 +283,17 @@ room {
281283

282284
tasks.withType<Test> {
283285
testLogging {
284-
events("passed", "skipped", "failed")
285-
// showStandardStreams = true
286+
events(
287+
TestLogEvent.FAILED,
288+
TestLogEvent.PASSED,
289+
TestLogEvent.SKIPPED,
290+
TestLogEvent.STANDARD_OUT,
291+
TestLogEvent.STANDARD_ERROR,
292+
)
293+
294+
exceptionFormat = TestExceptionFormat.FULL
295+
showExceptions = true
296+
showCauses = true
297+
showStackTraces = true
286298
}
287299
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
{
2+
"formatVersion": 1,
3+
"database": {
4+
"version": 4,
5+
"identityHash": "0cc3eca5ea6819dee0ddd3bfa503e961",
6+
"entities": [
7+
{
8+
"tableName": "config",
9+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`walletIndex` INTEGER NOT NULL, PRIMARY KEY(`walletIndex`))",
10+
"fields": [
11+
{
12+
"fieldPath": "walletIndex",
13+
"columnName": "walletIndex",
14+
"affinity": "INTEGER",
15+
"notNull": true
16+
}
17+
],
18+
"primaryKey": {
19+
"autoGenerate": false,
20+
"columnNames": [
21+
"walletIndex"
22+
]
23+
},
24+
"indices": [],
25+
"foreignKeys": []
26+
},
27+
{
28+
"tableName": "tag_metadata",
29+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `paymentHash` TEXT, `txId` TEXT, `address` TEXT NOT NULL, `isReceive` INTEGER NOT NULL, `tags` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, PRIMARY KEY(`id`))",
30+
"fields": [
31+
{
32+
"fieldPath": "id",
33+
"columnName": "id",
34+
"affinity": "TEXT",
35+
"notNull": true
36+
},
37+
{
38+
"fieldPath": "paymentHash",
39+
"columnName": "paymentHash",
40+
"affinity": "TEXT",
41+
"notNull": false
42+
},
43+
{
44+
"fieldPath": "txId",
45+
"columnName": "txId",
46+
"affinity": "TEXT",
47+
"notNull": false
48+
},
49+
{
50+
"fieldPath": "address",
51+
"columnName": "address",
52+
"affinity": "TEXT",
53+
"notNull": true
54+
},
55+
{
56+
"fieldPath": "isReceive",
57+
"columnName": "isReceive",
58+
"affinity": "INTEGER",
59+
"notNull": true
60+
},
61+
{
62+
"fieldPath": "tags",
63+
"columnName": "tags",
64+
"affinity": "TEXT",
65+
"notNull": true
66+
},
67+
{
68+
"fieldPath": "createdAt",
69+
"columnName": "createdAt",
70+
"affinity": "INTEGER",
71+
"notNull": true
72+
}
73+
],
74+
"primaryKey": {
75+
"autoGenerate": false,
76+
"columnNames": [
77+
"id"
78+
]
79+
},
80+
"indices": [],
81+
"foreignKeys": []
82+
},
83+
{
84+
"tableName": "transfers",
85+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `type` TEXT NOT NULL, `amountSats` INTEGER NOT NULL, `channelId` TEXT, `fundingTxId` TEXT, `lspOrderId` TEXT, `isSettled` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, `settledAt` INTEGER, PRIMARY KEY(`id`))",
86+
"fields": [
87+
{
88+
"fieldPath": "id",
89+
"columnName": "id",
90+
"affinity": "TEXT",
91+
"notNull": true
92+
},
93+
{
94+
"fieldPath": "type",
95+
"columnName": "type",
96+
"affinity": "TEXT",
97+
"notNull": true
98+
},
99+
{
100+
"fieldPath": "amountSats",
101+
"columnName": "amountSats",
102+
"affinity": "INTEGER",
103+
"notNull": true
104+
},
105+
{
106+
"fieldPath": "channelId",
107+
"columnName": "channelId",
108+
"affinity": "TEXT",
109+
"notNull": false
110+
},
111+
{
112+
"fieldPath": "fundingTxId",
113+
"columnName": "fundingTxId",
114+
"affinity": "TEXT",
115+
"notNull": false
116+
},
117+
{
118+
"fieldPath": "lspOrderId",
119+
"columnName": "lspOrderId",
120+
"affinity": "TEXT",
121+
"notNull": false
122+
},
123+
{
124+
"fieldPath": "isSettled",
125+
"columnName": "isSettled",
126+
"affinity": "INTEGER",
127+
"notNull": true
128+
},
129+
{
130+
"fieldPath": "createdAt",
131+
"columnName": "createdAt",
132+
"affinity": "INTEGER",
133+
"notNull": true
134+
},
135+
{
136+
"fieldPath": "settledAt",
137+
"columnName": "settledAt",
138+
"affinity": "INTEGER",
139+
"notNull": false
140+
}
141+
],
142+
"primaryKey": {
143+
"autoGenerate": false,
144+
"columnNames": [
145+
"id"
146+
]
147+
},
148+
"indices": [],
149+
"foreignKeys": []
150+
}
151+
],
152+
"views": [],
153+
"setupQueries": [
154+
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
155+
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '0cc3eca5ea6819dee0ddd3bfa503e961')"
156+
]
157+
}
158+
}

app/src/main/java/to/bitkit/data/AppDb.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,25 @@ import kotlinx.coroutines.coroutineScope
2020
import kotlinx.coroutines.flow.Flow
2121
import to.bitkit.BuildConfig
2222
import to.bitkit.data.dao.TagMetadataDao
23+
import to.bitkit.data.dao.TransferDao
2324
import to.bitkit.data.entities.ConfigEntity
2425
import to.bitkit.data.entities.TagMetadataEntity
26+
import to.bitkit.data.entities.TransferEntity
2527
import to.bitkit.data.typeConverters.StringListConverter
2628

2729
@Database(
2830
entities = [
2931
ConfigEntity::class,
3032
TagMetadataEntity::class,
33+
TransferEntity::class,
3134
],
32-
version = 3,
35+
version = 4,
3336
)
3437
@TypeConverters(StringListConverter::class)
3538
abstract class AppDb : RoomDatabase() {
3639
abstract fun configDao(): ConfigDao
3740
abstract fun tagMetadataDao(): TagMetadataDao
41+
abstract fun transferDao(): TransferDao
3842

3943
companion object {
4044
private const val DB_NAME = "${BuildConfig.APPLICATION_ID}.sqlite"

app/src/main/java/to/bitkit/data/CacheStore.kt

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@ import kotlinx.coroutines.flow.Flow
88
import kotlinx.coroutines.flow.first
99
import kotlinx.coroutines.flow.map
1010
import kotlinx.serialization.Serializable
11-
import to.bitkit.data.dto.InProgressTransfer
1211
import to.bitkit.data.dto.PendingBoostActivity
13-
import to.bitkit.data.dto.TransactionMetadata
1412
import to.bitkit.data.serializers.AppCacheSerializer
1513
import to.bitkit.models.BackupCategory
1614
import to.bitkit.models.BackupItemStatus
1715
import to.bitkit.models.BalanceState
1816
import to.bitkit.models.FxRate
17+
import to.bitkit.models.TransactionMetadata
1918
import to.bitkit.utils.Logger
2019
import javax.inject.Inject
2120
import javax.inject.Singleton
@@ -132,22 +131,6 @@ class CacheStore @Inject constructor(
132131
}
133132
}
134133

135-
suspend fun addInProgressTransfer(item: InProgressTransfer) {
136-
if (item in store.data.first().inProgressTransfers) return
137-
138-
store.updateData {
139-
it.copy(inProgressTransfers = it.inProgressTransfers + item)
140-
}
141-
}
142-
143-
suspend fun removeInProgressTransfer(item: InProgressTransfer) {
144-
if (item !in store.data.first().inProgressTransfers) return
145-
146-
store.updateData {
147-
it.copy(inProgressTransfers = it.inProgressTransfers - item)
148-
}
149-
}
150-
151134
suspend fun reset() {
152135
store.updateData { AppCacheData() }
153136
Logger.info("Deleted all app cached data.")
@@ -171,5 +154,4 @@ data class AppCacheData(
171154
val activitiesPendingDelete: List<String> = listOf(),
172155
val pendingBoostActivities: List<PendingBoostActivity> = listOf(),
173156
val transactionsMetadata: List<TransactionMetadata> = listOf(),
174-
val inProgressTransfers: List<InProgressTransfer> = listOf(),
175157
)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package to.bitkit.data.dao
2+
3+
import androidx.room.Dao
4+
import androidx.room.Insert
5+
import androidx.room.OnConflictStrategy
6+
import androidx.room.Query
7+
import androidx.room.Update
8+
import kotlinx.coroutines.flow.Flow
9+
import to.bitkit.data.entities.TransferEntity
10+
11+
@Dao
12+
interface TransferDao {
13+
@Insert(onConflict = OnConflictStrategy.REPLACE)
14+
suspend fun insert(transfer: TransferEntity)
15+
16+
@Update
17+
suspend fun update(transfer: TransferEntity)
18+
19+
@Query("SELECT * FROM transfers WHERE isSettled = 0")
20+
fun getActiveTransfers(): Flow<List<TransferEntity>>
21+
22+
@Query("SELECT * FROM transfers WHERE id = :id LIMIT 1")
23+
suspend fun getById(id: String): TransferEntity?
24+
25+
@Query("UPDATE transfers SET isSettled = 1, settledAt = :settledAt WHERE id = :id")
26+
suspend fun markSettled(id: String, settledAt: Long)
27+
28+
@Query("DELETE FROM transfers WHERE isSettled = 1 AND settledAt < :expirationTimestamp")
29+
suspend fun deleteOldSettled(expirationTimestamp: Long)
30+
}

app/src/main/java/to/bitkit/data/dto/InProgressTransfer.kt

Lines changed: 0 additions & 9 deletions
This file was deleted.

app/src/main/java/to/bitkit/data/dto/TransferType.kt

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package to.bitkit.data.entities
2+
3+
import androidx.room.Entity
4+
import androidx.room.PrimaryKey
5+
import kotlinx.serialization.Serializable
6+
import to.bitkit.models.TransferType
7+
8+
@Serializable
9+
@Entity(tableName = "transfers")
10+
data class TransferEntity(
11+
@PrimaryKey val id: String,
12+
val type: TransferType,
13+
val amountSats: Long,
14+
val channelId: String? = null,
15+
val fundingTxId: String? = null,
16+
val lspOrderId: String? = null,
17+
val isSettled: Boolean = false,
18+
val createdAt: Long,
19+
val settledAt: Long? = null,
20+
)

app/src/main/java/to/bitkit/di/DbModule.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import dagger.hilt.InstallIn
77
import dagger.hilt.android.qualifiers.ApplicationContext
88
import dagger.hilt.components.SingletonComponent
99
import to.bitkit.data.AppDb
10+
import to.bitkit.data.dao.TransferDao
1011
import javax.inject.Singleton
1112

1213
@Module
@@ -20,4 +21,10 @@ object DbModule {
2021
): AppDb {
2122
return AppDb.getInstance(applicationContext)
2223
}
24+
25+
@Provides
26+
@Singleton
27+
fun provideTransferDao(db: AppDb): TransferDao {
28+
return db.transferDao()
29+
}
2330
}

0 commit comments

Comments
 (0)