package com.bitcointxoko.gudariwallet.api import com.bitcointxoko.gudariwallet.security.SecretStore import com.bitcointxoko.gudariwallet.util.WalletConstants import kotlinx.coroutines.runBlocking import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.Interceptor import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient import retrofit2.Retrofit import retrofit2.converter.kotlinx.serialization.asConverterFactory import java.util.concurrent.TimeUnit object LNbitsClient { // Single shared client — used by both Retrofit and WebSocket val httpClient: OkHttpClient = OkHttpClient.Builder() .connectTimeout(WalletConstants.CONNECT_TIMEOUT_S, TimeUnit.SECONDS) .readTimeout(WalletConstants.READ_TIMEOUT_S, TimeUnit.SECONDS) .writeTimeout(WalletConstants.WRITE_TIMEOUT_S, TimeUnit.SECONDS) .build() fun create(secrets: SecretStore): LNbitsApi { // Dynamic base URL interceptor — rewrites the placeholder host to the // real base URL at request time, not at Retrofit construction time. // This means credentials only need to be in DataStore by the time the // first HTTP request fires, not at app startup. val dynamicBaseUrlInterceptor = Interceptor { chain -> val originalRequest = chain.request() val originalUrl = originalRequest.url // Only rewrite requests targeting the Retrofit placeholder host. // External LNURL/Lightning Address requests must pass through unchanged. if (originalUrl.host != "placeholder.invalid") { return@Interceptor chain.proceed(originalRequest) } val realBaseUrl = runBlocking { secrets.baseUrl() } .ifBlank { "https://placeholder.invalid" } .trimEnd('/') val realHttpUrl = realBaseUrl.toHttpUrl() val newUrl = originalUrl.newBuilder() .scheme(realHttpUrl.scheme) .host(realHttpUrl.host) .port(realHttpUrl.port) .build() chain.proceed( originalRequest.newBuilder() .url(newUrl) .build() ) } val client = httpClient.newBuilder() .addInterceptor(dynamicBaseUrlInterceptor) .build() return Retrofit.Builder() .baseUrl("https://placeholder.invalid/") // structurally required by Retrofit; .client(client) .addConverterFactory( JsonProvider.json.asConverterFactory( "application/json; charset=UTF-8".toMediaType() ) ) .build() .create(LNbitsApi::class.java) } }