<commit_before>package com.gulden.unity_wallet

import com.squareup.moshi.Moshi
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
import kotlin.random.Random
import com.itkacher.okhttpprofiler.OkHttpProfilerInterceptor
import com.squareup.moshi.JsonAdapter
import okhttp3.*
import se.ansman.kotshi.JsonSerializable
import se.ansman.kotshi.KotshiJsonAdapterFactory
import java.util.*

data class NocksQuoteResult(val amountNLG: Double)

data class NocksOrderResult(val depositAddress: String, val depositAmountNLG: Double)

private const val NOCKS_HOST = "www.nocks.com"

// TODO: Use host sandbox.nocks.com for testnet build
private const val FAKE_NOCKS_SERVICE = false

@JsonSerializable
data class SuccessValueNocksQuote (
    var amount: Double = -1.0
)

@JsonSerializable
data class NocksQuoteApiResult (
    var success: SuccessValueNocksQuote? = null,
    var error: List<String>? = null,
    var errorMessage: String? = null
)

@JsonSerializable
data class SuccessValueNocksOrder (
    var depositAmount: Double = -1.0,
    var deposit: String? = null,
    var expirationTimestamp: String? = null,
    var withdrawalAmount: String? = null,
    var withdrawalOriginal: String? = null
)

@JsonSerializable
data class NocksOrderApiResult (
    var error: String? = null,
    var success: SuccessValueNocksOrder? = null
)

@KotshiJsonAdapterFactory
abstract class ApplicationJsonAdapterFactory : JsonAdapter.Factory {
    companion object {
        val INSTANCE: ApplicationJsonAdapterFactory = KotshiApplicationJsonAdapterFactory()
    }
}

var client : OkHttpClient? = null
var moshi : Moshi? = null

// Only create one client per session so that we avoid unnecessary extra SSL handshakes and can take advantage of connection pooling etc.
fun initNocks()
{
    // Clean up any previously failed nocks sessions
    terminateNocks()

    // Force okhttp to include specific SSL certificates that are required, otherwise these calls simply fail unexpectedly on various devices.
    // See: https://github.com/square/okhttp/issues/3894
    val spec = ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS)
            .tlsVersions(TlsVersion.TLS_1_2, TlsVersion.TLS_1_1, TlsVersion.TLS_1_0)
            .cipherSuites(
                    CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                    CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
                    CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
                    CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA)
            .build()

    val builder = OkHttpClient.Builder()
    if (BuildConfig.DEBUG) {
        builder.addInterceptor(OkHttpProfilerInterceptor() )
    }
    client = builder.connectionSpecs(Collections.singletonList(spec)).build()
    moshi = Moshi.Builder().add(ApplicationJsonAdapterFactory.INSTANCE).build()
}

// Release client when we are done with current session
fun terminateNocks()
{
    //TODO: Cancel all unpaid payment requests here.
    client = null
    moshi = null
}

private suspend inline fun <reified ResultType> nocksRequest(endpoint: String, jsonParams: String): ResultType?
{
    val request = Request.Builder()
            .url("https://$NOCKS_HOST/api/$endpoint")
            .header("User-Agent", Config.USER_AGENT)
            .post(RequestBody.create(MediaType.get("application/json; charset=utf-8"), jsonParams))
            .build()

    // execute on IO thread pool
    val result = withContext(IO) {
        val response = client?.newCall(request)?.execute()
        val body = response?.body()
        if (body != null)
            body.string()
        else
            throw RuntimeException("Null body in Nocks response.")
    }

    val adapter = moshi?.adapter(ResultType::class.java)
    return adapter?.fromJson(result)
}

suspend fun nocksQuote(amountEuro: Double): NocksQuoteResult
{
    return if (FAKE_NOCKS_SERVICE) {
        delay(500)
        val amount = Random.nextDouble(300.0, 400.0)
        NocksQuoteResult(amountNLG = amount)
    }
    else {<commit_msg>ANDROID: Force "Accept" and "Content-type" headers in nocks requests to avoid possible strange caching issues that may have been occuring<commit_after>package com.gulden.unity_wallet

import com.squareup.moshi.Moshi
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
import kotlin.random.Random
import com.itkacher.okhttpprofiler.OkHttpProfilerInterceptor
import com.squareup.moshi.JsonAdapter
import okhttp3.*
import se.ansman.kotshi.JsonSerializable
import se.ansman.kotshi.KotshiJsonAdapterFactory
import java.util.*

data class NocksQuoteResult(val amountNLG: Double)

data class NocksOrderResult(val depositAddress: String, val depositAmountNLG: Double)

private const val NOCKS_HOST = "www.nocks.com"

// TODO: Use host sandbox.nocks.com for testnet build
private const val FAKE_NOCKS_SERVICE = false

@JsonSerializable
data class SuccessValueNocksQuote (
    var amount: Double = -1.0
)

@JsonSerializable
data class NocksQuoteApiResult (
    var success: SuccessValueNocksQuote? = null,
    var error: List<String>? = null,
    var errorMessage: String? = null
)

@JsonSerializable
data class SuccessValueNocksOrder (
    var depositAmount: Double = -1.0,
    var deposit: String? = null,
    var expirationTimestamp: String? = null,
    var withdrawalAmount: String? = null,
    var withdrawalOriginal: String? = null
)

@JsonSerializable
data class NocksOrderApiResult (
    var error: String? = null,
    var success: SuccessValueNocksOrder? = null
)

@KotshiJsonAdapterFactory
abstract class ApplicationJsonAdapterFactory : JsonAdapter.Factory {
    companion object {
        val INSTANCE: ApplicationJsonAdapterFactory = KotshiApplicationJsonAdapterFactory()
    }
}

var client : OkHttpClient? = null
var moshi : Moshi? = null

// Only create one client per session so that we avoid unnecessary extra SSL handshakes and can take advantage of connection pooling etc.
fun initNocks()
{
    // Clean up any previously failed nocks sessions
    terminateNocks()

    // Force okhttp to include specific SSL certificates that are required, otherwise these calls simply fail unexpectedly on various devices.
    // See: https://github.com/square/okhttp/issues/3894
    val spec = ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS)
            .tlsVersions(TlsVersion.TLS_1_2, TlsVersion.TLS_1_1, TlsVersion.TLS_1_0)
            .cipherSuites(
                    CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                    CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
                    CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
                    CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA)
            .build()

    val builder = OkHttpClient.Builder()
    if (BuildConfig.DEBUG) {
        builder.addInterceptor(OkHttpProfilerInterceptor() )
    }
    client = builder.connectionSpecs(Collections.singletonList(spec)).build()
    moshi = Moshi.Builder().add(ApplicationJsonAdapterFactory.INSTANCE).build()
}

// Release client when we are done with current session
fun terminateNocks()
{
    //TODO: Cancel all unpaid payment requests here.
    client = null
    moshi = null
}

private suspend inline fun <reified ResultType> nocksRequest(endpoint: String, jsonParams: String): ResultType?
{
    val request = Request.Builder()
            .url("https://$NOCKS_HOST/api/$endpoint")
            .header("User-Agent", Config.USER_AGENT)
            .header("Content-Type", "application/json")
            .header("Accept", "application/json")
            .post(RequestBody.create(MediaType.get("application/json; charset=utf-8"), jsonParams))
            .build()

    // execute on IO thread pool
    val result = withContext(IO) {
        val response = client?.newCall(request)?.execute()
        val body = response?.body()
        if (body != null)
            body.string()
        else
            throw RuntimeException("Null body in Nocks response.")
    }

    val adapter = moshi?.adapter(ResultType::class.java)
    return adapter?.fromJson(result)
}

suspend fun nocksQuote(amountEuro: Double): NocksQuoteResult
{
    return if (FAKE_NOCKS_SERVICE) {
        delay(500)
        val amount = Random.nextDouble(300.0, 400.0)
        NocksQuoteResult(amountNLG = amount)
    }
    else {
{'fraction_non_alphanumeric': 0.08537747082638723, 'fraction_numerical': 0.011431293165039295, 'mean_word_length': 3.5597176981541803, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6038457', 'n_tokens_mistral': 2586, 'n_tokens_neox': 2474, 'n_words': 617}