Skip to content

Commit 7030d57

Browse files
authored
Merge pull request #384 from synonymdev/feat/use-url-for-electrum-server
refactor: use url string for electrum server config
2 parents cb58510 + 5af2f7d commit 7030d57

File tree

12 files changed

+238
-120
lines changed

12 files changed

+238
-120
lines changed

app/detekt-baseline.xml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
<ID>ComposableParamOrder:HomeScreen.kt$Content</ID>
2929
<ID>ComposableParamOrder:InfoScreenContent.kt$InfoScreenContent</ID>
3030
<ID>ComposableParamOrder:Money.kt$MoneyCaptionB</ID>
31-
<ID>ComposableParamOrder:NumberPadTextField.kt$MoneyAmount</ID>
3231
<ID>ComposableParamOrder:OnboardingSlidesScreen.kt$OnboardingSlidesScreen</ID>
3332
<ID>ComposableParamOrder:OnboardingSlidesScreen.kt$OnboardingTab</ID>
3433
<ID>ComposableParamOrder:PriceCard.kt$PriceCard</ID>
@@ -168,13 +167,11 @@
168167
<ID>LongMethod:AppViewModel.kt$AppViewModel$private suspend fun proceedWithPayment()</ID>
169168
<ID>LongMethod:ContentView.kt$private fun NavGraphBuilder.widgets( navController: NavHostController, settingsViewModel: SettingsViewModel, currencyViewModel: CurrencyViewModel, )</ID>
170169
<ID>LongMethod:CoreService.kt$ActivityService$suspend fun generateRandomTestData(count: Int = 100)</ID>
171-
<ID>LongMethod:LightningRepo.kt$LightningRepo$suspend fun start( walletIndex: Int = 0, timeout: Duration? = null, shouldRetry: Boolean = true, eventHandler: NodeEventHandler? = null, customServer: ElectrumServer? = null, customRgsServerUrl: String? = null, ): Result&lt;Unit&gt;</ID>
172170
<ID>LongMethod:LightningService.kt$LightningService$private fun logEvent(event: Event)</ID>
173171
<ID>LongMethod:MainActivity.kt$MainActivity$override fun onCreate(savedInstanceState: Bundle?)</ID>
174172
<ID>LongMethod:WakeNodeWorker.kt$WakeNodeWorker$private suspend fun handleLdkEvent(event: Event)</ID>
175173
<ID>LongParameterList:ActivityRepo.kt$ActivityRepo$( filter: ActivityFilter? = null, txType: PaymentType? = null, tags: List&lt;String&gt;? = null, search: String? = null, minDate: ULong? = null, maxDate: ULong? = null, limit: UInt? = null, sortDirection: SortDirection? = null, )</ID>
176174
<ID>LongParameterList:ActivityRepo.kt$ActivityRepo$( id: String, paymentHash: String? = null, txId: String? = null, address: String, isReceive: Boolean, tags: List&lt;String&gt;, )</ID>
177-
<ID>LongParameterList:AppViewModel.kt$AppViewModel$( @ApplicationContext private val context: Context, @BgDispatcher private val bgDispatcher: CoroutineDispatcher, private val keychain: Keychain, private val lightningRepo: LightningRepo, private val walletRepo: WalletRepo, private val coreService: CoreService, private val ldkNodeEventBus: LdkNodeEventBus, private val settingsStore: SettingsStore, private val currencyRepo: CurrencyRepo, private val activityRepo: ActivityRepo, private val blocktankRepo: BlocktankRepo, connectivityRepo: ConnectivityRepo, healthRepo: HealthRepo, )</ID>
178175
<ID>LongParameterList:BiometricPrompt.kt$( activity: Context, title: String, cancelButtonText: String, onAuthSucceed: () -&gt; Unit, onAuthFailed: (() -&gt; Unit), onAuthError: ((errorCode: Int, errString: CharSequence) -&gt; Unit), )</ID>
179176
<ID>LongParameterList:BiometricPrompt.kt$( activity: Context, title: String, cancelButtonText: String, onAuthSucceeded: () -&gt; Unit, onAuthFailed: (() -&gt; Unit), onAuthError: ((errorCode: Int, errString: CharSequence) -&gt; Unit), onUnsupported: () -&gt; Unit, )</ID>
180177
<ID>LongParameterList:CoreService.kt$ActivityService$( filter: ActivityFilter? = null, txType: PaymentType? = null, tags: List&lt;String&gt;? = null, search: String? = null, minDate: ULong? = null, maxDate: ULong? = null, limit: UInt? = null, sortDirection: SortDirection? = null, )</ID>
@@ -184,7 +181,6 @@
184181
<ID>LongParameterList:LightningConnectionsViewModel.kt$LightningConnectionsViewModel$( @ApplicationContext private val context: Context, @BgDispatcher private val bgDispatcher: CoroutineDispatcher, private val lightningRepo: LightningRepo, internal val blocktankRepo: BlocktankRepo, private val logsRepo: LogsRepo, private val addressChecker: AddressChecker, private val ldkNodeEventBus: LdkNodeEventBus, private val walletRepo: WalletRepo, )</ID>
185182
<ID>LongParameterList:LightningRepo.kt$LightningRepo$( @BgDispatcher private val bgDispatcher: CoroutineDispatcher, private val lightningService: LightningService, private val ldkNodeEventBus: LdkNodeEventBus, private val settingsStore: SettingsStore, private val coreService: CoreService, private val lspNotificationsService: LspNotificationsService, private val firebaseMessaging: FirebaseMessaging, private val keychain: Keychain, private val lnurlService: LnurlService, private val cacheStore: CacheStore, )</ID>
186183
<ID>LongParameterList:LightningRepo.kt$LightningRepo$( address: Address, sats: ULong, speed: TransactionSpeed? = null, utxosToSpend: List&lt;SpendableUtxo&gt;? = null, feeRates: FeeRates? = null, isTransfer: Boolean = false, channelId: String? = null, )</ID>
187-
<ID>LongParameterList:LightningRepo.kt$LightningRepo$( walletIndex: Int = 0, timeout: Duration? = null, shouldRetry: Boolean = true, eventHandler: NodeEventHandler? = null, customServer: ElectrumServer? = null, customRgsServerUrl: String? = null, )</ID>
188184
<ID>LongParameterList:Notifications.kt$( title: String?, text: String?, extras: Bundle? = null, bigText: String? = null, id: Int = Random.nextInt(), context: Context, )</ID>
189185
<ID>LongParameterList:TransferViewModel.kt$TransferViewModel$( @ApplicationContext private val context: Context, private val lightningRepo: LightningRepo, private val blocktankRepo: BlocktankRepo, private val walletRepo: WalletRepo, private val currencyRepo: CurrencyRepo, private val settingsStore: SettingsStore, private val cacheStore: CacheStore, )</ID>
190186
<ID>LongParameterList:WalletRepo.kt$WalletRepo$( @BgDispatcher private val bgDispatcher: CoroutineDispatcher, private val db: AppDb, private val keychain: Keychain, private val coreService: CoreService, private val settingsStore: SettingsStore, private val addressChecker: AddressChecker, private val lightningRepo: LightningRepo, private val cacheStore: CacheStore, )</ID>
@@ -389,7 +385,6 @@
389385
<ID>MaxLineLength:BlocktankRegtestScreen.kt$"Initiating channel close with fundingTxId: $fundingTxId, vout: $vout, forceCloseAfter: $forceCloseAfter"</ID>
390386
<ID>MaxLineLength:BlocktankRepo.kt$BlocktankRepo$"Buying channel with lspBalanceSat: $receivingBalanceSats, channelExpiryWeeks: $channelExpiryWeeks, options: $options"</ID>
391387
<ID>MaxLineLength:ChannelOrdersScreen.kt$lnurl = "LNURL1DP68GURN8GHJ7CTSDYH8XARPVUHXYMR0VD4HGCTWDVH8GME0VFKX7CMTW3SKU6E0V9CXJTMKXGHKCTENVV6NVDP4XUEJ6ETRX33Z6DPEXU6Z6C34XQEZ6DT9XENX2WFNXQ6RXDTXGQAH4MLNURL1DP68GURN8GHJ7CTSDYH8XARPVUHXYMR0VD4HGCTWDVH8GME0VFKX7CMTW3SKU6E0V9CXJTMKXGHKCTENVV6NVDP4XUEJ6ETRX33Z6DPEXU6Z6C34XQEZ6DT9XENX2WFNXQ6RXDTXGQAH4M"</ID>
392-
<ID>MaxLineLength:CoreService.kt$CoreService$// val blocktankPeers = getInfo(refresh = true)?.nodes?.map { LnPeer(nodeId = it.pubkey, address = "TO_DO") }.orEmpty()</ID>
393388
<ID>MaxLineLength:CryptoTest.kt$CryptoTest$val ciphertext = "l2fInfyw64gO12odo8iipISloQJ45Rc4WjFmpe95brdaAMDq+T/L9ZChcmMCXnR0J6BXd8sSIJe/0bmby8uSZZJuVCzwF76XHfY5oq0Y1/hKzyZTn8nG3dqfiLHnAPy1tZFQfm5ALgjwWnViYJLXoGFpXs7kLMA=".fromBase64()</ID>
394389
<ID>MaxLineLength:CryptoTest.kt$CryptoTest$val decryptedPayload = """{"source":"blocktank","type":"incomingHtlc","payload":{"secretMessage":"hello"},"createdAt":"2024-09-18T13:33:52.555Z"}"""</ID>
395390
<ID>MaxLineLength:HeadlineCard.kt$headline = "How Bitcoin changed El Salvador in more ways a big headline to test the text overflooooooow"</ID>
@@ -554,14 +549,6 @@
554549
<ID>PreviewPublic:EmptyWalletView.kt$EmptyStateViewPreview</ID>
555550
<ID>PreviewPublic:HighlightLabel.kt$FlexibleLogoPreview</ID>
556551
<ID>PreviewPublic:HighlightLabel.kt$LongTextLogoPreview</ID>
557-
<ID>PreviewPublic:NumberPadTextField.kt$PreviewMoneyAmountBitcoinClassicEmpty</ID>
558-
<ID>PreviewPublic:NumberPadTextField.kt$PreviewMoneyAmountBitcoinClassicWithValue</ID>
559-
<ID>PreviewPublic:NumberPadTextField.kt$PreviewMoneyAmountBitcoinModernEmpty</ID>
560-
<ID>PreviewPublic:NumberPadTextField.kt$PreviewMoneyAmountBitcoinModernWithValue</ID>
561-
<ID>PreviewPublic:NumberPadTextField.kt$PreviewMoneyAmountBitcoinPartial</ID>
562-
<ID>PreviewPublic:NumberPadTextField.kt$PreviewMoneyAmountFiatEmpty</ID>
563-
<ID>PreviewPublic:NumberPadTextField.kt$PreviewMoneyAmountFiatPartial</ID>
564-
<ID>PreviewPublic:NumberPadTextField.kt$PreviewMoneyAmountFiatWithValue</ID>
565552
<ID>PreviewPublic:RestoreWalletScreen.kt$RestoreWalletViewPreview</ID>
566553
<ID>PreviewPublic:SplashScreen.kt$SplashScreenPreview</ID>
567554
<ID>PrintStackTrace:ShareSheet.kt$e</ID>
@@ -577,7 +564,6 @@
577564
<ID>TooGenericExceptionCaught:ActivityRepo.kt$ActivityRepo$e: Exception</ID>
578565
<ID>TooGenericExceptionCaught:AddressChecker.kt$AddressChecker$e: Exception</ID>
579566
<ID>TooGenericExceptionCaught:AppViewModel.kt$AppViewModel$e: Exception</ID>
580-
<ID>TooGenericExceptionCaught:AppViewModel.kt$AppViewModel$e: Throwable</ID>
581567
<ID>TooGenericExceptionCaught:ArticleModel.kt$e: Exception</ID>
582568
<ID>TooGenericExceptionCaught:BackupNavSheetViewModel.kt$BackupNavSheetViewModel$e: Throwable</ID>
583569
<ID>TooGenericExceptionCaught:BackupRepo.kt$BackupRepo$e: Throwable</ID>

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import to.bitkit.data.serializers.SettingsSerializer
1111
import to.bitkit.env.Env
1212
import to.bitkit.models.BitcoinDisplayUnit
1313
import to.bitkit.models.CoinSelectionPreference
14-
import to.bitkit.models.ElectrumServer
1514
import to.bitkit.models.PrimaryDisplay
1615
import to.bitkit.models.Suggestion
1716
import to.bitkit.models.TransactionSpeed
@@ -105,7 +104,7 @@ data class SettingsData(
105104
val balanceWarningTimes: Int = 0,
106105
val coinSelectAuto: Boolean = true,
107106
val coinSelectPreference: CoinSelectionPreference = CoinSelectionPreference.BranchAndBound,
108-
val electrumServer: ElectrumServer = Env.defaultElectrumServer,
107+
val electrumServer: String = Env.defaultElectrumServer,
109108
val rgsServerUrl: String? = Env.ldkRgsServerUrl,
110109
)
111110

app/src/main/java/to/bitkit/env/Env.kt

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import org.lightningdevkit.ldknode.Network
66
import to.bitkit.BuildConfig
77
import to.bitkit.ext.ensureDir
88
import to.bitkit.models.BlocktankNotificationType
9-
import to.bitkit.models.ElectrumProtocol
10-
import to.bitkit.models.ElectrumServer
119
import to.bitkit.models.LnPeer
1210
import to.bitkit.utils.Logger
1311
import java.io.File
@@ -151,33 +149,13 @@ internal object Env {
151149
}
152150

153151
object ElectrumServers {
154-
val BITCOIN = ElectrumServer(
155-
host = "35.187.18.233",
156-
tcp = 8911,
157-
ssl = 8900,
158-
protocol = ElectrumProtocol.SSL,
159-
)
160-
val TESTNET = ElectrumServer(
161-
host = "electrum.blockstream.info",
162-
tcp = 60001, // or 50001
163-
ssl = 60002, // or 50002
164-
protocol = ElectrumProtocol.SSL,
165-
)
166-
val REGTEST = ElectrumServer(
167-
host = "34.65.252.32",
168-
tcp = 18483,
169-
ssl = 18484,
170-
protocol = ElectrumProtocol.TCP,
171-
)
172-
val E2E = ElectrumServer(
173-
host = "127.0.0.1",
174-
tcp = 60001,
175-
ssl = 60002,
176-
protocol = ElectrumProtocol.TCP,
177-
)
152+
const val BITCOIN = "ssl://35.187.18.233:8900"
153+
const val TESTNET = "ssl://electrum.blockstream.info:60002"
154+
const val REGTEST = "tcp://34.65.252.32:18483"
155+
const val E2E = "tcp://127.0.0.1:60001"
178156
}
179157

180-
val defaultElectrumServer: ElectrumServer
158+
val defaultElectrumServer: String
181159
get() {
182160
if (isE2eTest) return ElectrumServers.E2E
183161
return when (network) {
@@ -211,6 +189,7 @@ internal object Env {
211189
const val BITKIT_GITHUB = "https://github.com/synonymdev"
212190
const val BITKIT_HELP_CENTER = "https://help.bitkit.to"
213191
const val TERMS_OF_USE_URL = "https://bitkit.to/terms-of-use"
192+
const val PRIVACY_POLICY_URL = "https://bitkit.to/privacy-policy"
214193
const val STORING_BITCOINS_URL = "https://en.bitcoin.it/wiki/Storing_bitcoins"
215194
const val SUPPORT_EMAIL = "[email protected]"
216195
}

app/src/main/java/to/bitkit/models/ElectrumServer.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,42 @@ data class ElectrumServer(
2424
}
2525

2626
companion object {
27+
const val MAX_VALID_PORT = 65535
28+
29+
fun parse(url: String): ElectrumServer {
30+
val url = url.trim()
31+
require(url.isNotBlank()) { "URL cannot be blank" }
32+
33+
val parts = url.split("://", limit = 2)
34+
require(parts.size == 2) { "Invalid URL format, expected 'scheme://host:port'" }
35+
36+
val scheme = parts[0].lowercase()
37+
val protocol = when (scheme) {
38+
"tcp" -> ElectrumProtocol.TCP
39+
"ssl" -> ElectrumProtocol.SSL
40+
else -> throw IllegalArgumentException("Invalid scheme: $scheme, expected 'tcp' or 'ssl'")
41+
}
42+
43+
val hostPort = parts[1].split(":", limit = 2)
44+
require(hostPort.size == 2) { "Invalid URL format, expected 'scheme://host:port'" }
45+
46+
val host = hostPort[0].trim()
47+
require(host.isNotBlank()) { "Host cannot be blank" }
48+
49+
val port = hostPort[1].trim().toIntOrNull()
50+
require(port != null && port > 0 && port <= MAX_VALID_PORT) { "Invalid port: ${hostPort[1]}" }
51+
52+
val defaultTcp = ElectrumProtocol.TCP.getDefaultPort()
53+
val defaultSsl = ElectrumProtocol.SSL.getDefaultPort()
54+
55+
return ElectrumServer(
56+
host = host,
57+
tcp = if (protocol == ElectrumProtocol.TCP) port else defaultTcp,
58+
ssl = if (protocol == ElectrumProtocol.SSL) port else defaultSsl,
59+
protocol = protocol,
60+
)
61+
}
62+
2763
fun fromUserInput(
2864
host: String,
2965
port: Int,

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

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ import to.bitkit.di.BgDispatcher
4040
import to.bitkit.env.Env
4141
import to.bitkit.ext.getSatsPerVByteFor
4242
import to.bitkit.models.CoinSelectionPreference
43-
import to.bitkit.models.ElectrumServer
4443
import to.bitkit.models.LnPeer
4544
import to.bitkit.models.NodeLifecycleState
4645
import to.bitkit.models.TransactionSpeed
@@ -148,24 +147,25 @@ class LightningRepo @Inject constructor(
148147

149148
private suspend fun setup(
150149
walletIndex: Int,
151-
customServer: ElectrumServer? = null,
150+
customServerUrl: String? = null,
152151
customRgsServerUrl: String? = null,
153152
) = withContext(bgDispatcher) {
154153
return@withContext try {
155-
lightningService.setup(walletIndex, customServer, customRgsServerUrl)
154+
lightningService.setup(walletIndex, customServerUrl, customRgsServerUrl)
156155
Result.success(Unit)
157156
} catch (e: Throwable) {
158157
Logger.error("Node setup error", e, context = TAG)
159158
Result.failure(e)
160159
}
161160
}
162161

162+
@Suppress("LongMethod", "LongParameterList")
163163
suspend fun start(
164164
walletIndex: Int = 0,
165165
timeout: Duration? = null,
166166
shouldRetry: Boolean = true,
167167
eventHandler: NodeEventHandler? = null,
168-
customServer: ElectrumServer? = null,
168+
customServerUrl: String? = null,
169169
customRgsServerUrl: String? = null,
170170
): Result<Unit> = withContext(bgDispatcher) {
171171
val initialLifecycleState = _lightningState.value.nodeLifecycleState
@@ -179,7 +179,7 @@ class LightningRepo @Inject constructor(
179179

180180
// Setup if not already setup
181181
if (lightningService.node == null) {
182-
val setupResult = setup(walletIndex, customServer, customRgsServerUrl)
182+
val setupResult = setup(walletIndex, customServerUrl, customRgsServerUrl)
183183
if (setupResult.isFailure) {
184184
_lightningState.update {
185185
it.copy(
@@ -232,7 +232,7 @@ class LightningRepo @Inject constructor(
232232
timeout = timeout,
233233
shouldRetry = false,
234234
eventHandler = eventHandler,
235-
customServer = customServer,
235+
customServerUrl = customServerUrl,
236236
customRgsServerUrl = customRgsServerUrl,
237237
)
238238
} else {
@@ -312,43 +312,43 @@ class LightningRepo @Inject constructor(
312312
}
313313
}
314314

315-
suspend fun restartWithElectrumServer(newServer: ElectrumServer): Result<Unit> = withContext(bgDispatcher) {
316-
Logger.info("Changing ldk-node electrum server to: $newServer")
315+
suspend fun restartWithElectrumServer(newServerUrl: String): Result<Unit> = withContext(bgDispatcher) {
316+
Logger.info("Changing ldk-node electrum server to: '$newServerUrl'")
317317

318318
waitForNodeToStop().onFailure { return@withContext Result.failure(it) }
319319
stop().onFailure {
320320
Logger.error("Failed to stop node during electrum server change", it)
321321
return@withContext Result.failure(it)
322322
}
323323

324-
Logger.debug("Starting node with new electrum server: $newServer")
324+
Logger.debug("Starting node with new electrum server: '$newServerUrl'")
325325

326326
start(
327327
eventHandler = cachedEventHandler,
328-
customServer = newServer,
328+
customServerUrl = newServerUrl,
329329
shouldRetry = false,
330330
).onFailure { startError ->
331331
Logger.warn("Failed ldk-node config change, attempting recovery…")
332332
restartWithPreviousConfig()
333333
return@withContext Result.failure(startError)
334334
}.onSuccess {
335-
settingsStore.update { it.copy(electrumServer = newServer) }
335+
settingsStore.update { it.copy(electrumServer = newServerUrl) }
336336

337-
Logger.info("Successfully changed electrum server connection")
337+
Logger.info("Successfully changed electrum server")
338338
return@withContext Result.success(Unit)
339339
}
340340
}
341341

342342
suspend fun restartWithRgsServer(newRgsUrl: String): Result<Unit> = withContext(bgDispatcher) {
343-
Logger.info("Changing ldk-node RGS server to: $newRgsUrl")
343+
Logger.info("Changing ldk-node RGS server to: '$newRgsUrl'")
344344

345345
waitForNodeToStop().onFailure { return@withContext Result.failure(it) }
346346
stop().onFailure {
347347
Logger.error("Failed to stop node during RGS server change", it)
348348
return@withContext Result.failure(it)
349349
}
350350

351-
Logger.debug("Starting node with new RGS server: $newRgsUrl")
351+
Logger.debug("Starting node with new RGS server: '$newRgsUrl'")
352352

353353
start(
354354
eventHandler = cachedEventHandler,

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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ import to.bitkit.env.Env
4444
import to.bitkit.ext.DatePattern
4545
import to.bitkit.ext.totalNextOutboundHtlcLimitSats
4646
import to.bitkit.ext.uByteList
47-
import to.bitkit.models.ElectrumServer
4847
import to.bitkit.models.LnPeer
4948
import to.bitkit.models.LnPeer.Companion.toLnPeer
5049
import to.bitkit.utils.LdkError
@@ -78,7 +77,7 @@ class LightningService @Inject constructor(
7877

7978
suspend fun setup(
8079
walletIndex: Int,
81-
customServer: ElectrumServer? = null,
80+
customServerUrl: String? = null,
8281
customRgsServerUrl: String? = null,
8382
) {
8483
val mnemonic = keychain.loadString(Keychain.Key.BIP39_MNEMONIC.name) ?: throw ServiceError.MnemonicNotFound
@@ -102,7 +101,7 @@ class LightningService @Inject constructor(
102101
val builder = Builder.fromConfig(config).apply {
103102
setFilesystemLogger(generateLogFilePath(), Env.ldkLogLevel)
104103

105-
configureChainSource(customServer)
104+
configureChainSource(customServerUrl)
106105
configureGossipSource(customRgsServerUrl)
107106

108107
setEntropyBip39Mnemonic(mnemonic, passphrase)
@@ -151,10 +150,9 @@ class LightningService @Inject constructor(
151150
}
152151
}
153152

154-
private suspend fun Builder.configureChainSource(customServer: ElectrumServer? = null) {
155-
val electrumServer = customServer ?: settingsStore.data.first().electrumServer
156-
val serverUrl = electrumServer.toString()
157-
Logger.info("Using onchain source Electrum url: $serverUrl")
153+
private suspend fun Builder.configureChainSource(customServerUrl: String? = null) {
154+
val serverUrl = customServerUrl ?: settingsStore.data.first().electrumServer
155+
Logger.info("Using onchain source Electrum Sever url: $serverUrl")
158156
setChainSourceElectrum(
159157
serverUrl = serverUrl,
160158
config = ElectrumSyncConfig(

0 commit comments

Comments
 (0)