diff --git a/.idea/copyright/Erik_s_Copyright_Notice.xml b/.idea/copyright/Erik_s_Copyright_Notice.xml index df1b749..6af75f8 100644 --- a/.idea/copyright/Erik_s_Copyright_Notice.xml +++ b/.idea/copyright/Erik_s_Copyright_Notice.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index e1eea1d..2b8a50f 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index c55072b..323152a 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -4,5 +4,8 @@ - + + + \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt index ab5f3ce..194661d 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,5 +1,4 @@ -Copyright (c) 2021-2022, Erik C. Thauvin (erik@thauvin.net) -All rights reserved. +Copyright 2021-2023 Erik C. Thauvin (erik@thauvin.net) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.md b/README.md index f3297db..4265eb2 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,16 @@ -[![License (3-Clause BSD)](https://img.shields.io/badge/license-BSD%203--Clause-blue.svg?style=flat-square)](https://opensource.org/licenses/BSD-3-Clause) [![Release](https://img.shields.io/github/release/ethauvin/cryptoprice.svg)](https://github.com/ethauvin/cryptoprice/releases/latest) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/net.thauvin.erik/cryptoprice/badge.svg?color=blue)](https://maven-badges.herokuapp.com/maven-central/net.thauvin.erik/cryptoprice) +[![License (3-Clause BSD)](https://img.shields.io/badge/license-BSD%203--Clause-blue.svg?style=flat-square)](https://opensource.org/licenses/BSD-3-Clause) +[![Kotlin](https://img.shields.io/badge/kotlin-1.8.0-blue)](https://kotlinlang.org/) +[![Nexus Snapshot](https://img.shields.io/nexus/s/net.thauvin.erik/cryptoprice?label=snapshot&server=https%3A%2F%2Foss.sonatype.org%2F)](https://oss.sonatype.org/content/repositories/snapshots/net/thauvin/erik/cryptoprice/) +[![Release](https://img.shields.io/github/release/ethauvin/cryptoprice.svg)](https://github.com/ethauvin/cryptoprice/releases/latest) +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/net.thauvin.erik/cryptoprice/badge.svg?color=blue)](https://maven-badges.herokuapp.com/maven-central/net.thauvin.erik/cryptoprice) -[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=ethauvin_cryptoprice&metric=alert_status)](https://sonarcloud.io/dashboard?id=ethauvin_cryptoprice) [![GitHub CI](https://github.com/ethauvin/cryptoprice/actions/workflows/gradle.yml/badge.svg)](https://github.com/ethauvin/cryptoprice/actions/workflows/gradle.yml) [![CircleCI](https://circleci.com/gh/ethauvin/cryptoprice/tree/master.svg?style=shield)](https://circleci.com/gh/ethauvin/cryptoprice/tree/master) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=ethauvin_cryptoprice&metric=alert_status)](https://sonarcloud.io/dashboard?id=ethauvin_cryptoprice) +[![GitHub CI](https://github.com/ethauvin/cryptoprice/actions/workflows/gradle.yml/badge.svg)](https://github.com/ethauvin/cryptoprice/actions/workflows/gradle.yml) +[![CircleCI](https://circleci.com/gh/ethauvin/cryptoprice/tree/master.svg?style=shield)](https://circleci.com/gh/ethauvin/cryptoprice/tree/master) # Retrieve cryptocurrencies current (buy, sell or spot) prices -A simple Kotlin/Java/Android implementation of the prices [Coinbase Public API](https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-prices). +A simple implementation of the prices [Coinbase Public API](https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-prices). ## Examples (TL;DR) @@ -32,6 +38,7 @@ To use with [Gradle](https://gradle.org/), include the following dependency in y ```gradle repositories { mavenCentral() + maven { url = uri("https://oss.sonatype.org/content/repositories/snapshots") } // only needed for SNAPSHOT } dependencies { @@ -85,7 +92,7 @@ val euro = CryptoPrice("BTC", "EUR", 23456.78.toBigDecimal()) println(euro.toCurrency()) // €23,456.78 val krone = CryptoPrice("BTC", "DKK", 123456.78.toBigDecimal()) -println(krone.toCurrency(Locale("da", "DK"))) // 123.456,78 kr. +println(krone.toCurrency(Locale.Builder().setLanguage("da").setRegion("DK").build())) // 123.456,78 kr. ``` ##### JSON diff --git a/build.gradle.kts b/build.gradle.kts index bfb0112..ec7c712 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,22 +7,22 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent plugins { id("application") - id("com.github.ben-manes.versions") version "0.42.0" - id("io.gitlab.arturbosch.detekt") version "1.21.0" + id("com.github.ben-manes.versions") version "0.44.0" + id("io.gitlab.arturbosch.detekt") version "1.22.0" id("java") id("maven-publish") - id("org.jetbrains.dokka") version "1.7.10" + id("org.jetbrains.dokka") version "1.7.20" id("org.jetbrains.kotlinx.kover") version "0.6.1" - id("org.sonarqube") version "3.4.0.2513" + id("org.sonarqube") version "3.5.0.2730" id("signing") - kotlin("jvm") version "1.7.20" + kotlin("jvm") version "1.8.0" } defaultTasks(ApplicationPlugin.TASK_RUN_NAME) -description = "Retrieve cryptocurrencies prices." +description = "Retrieve cryptocurrencies prices" group = "net.thauvin.erik" -version = "1.0.0" +version = "1.0.1-SNAPSHOT" val deployDir = "deploy" val gitHub = "ethauvin/$name" @@ -168,8 +168,8 @@ publishing { } } scm { - connection.set("scm:git:git://github.com/$gitHub.git") - developerConnection.set("scm:git:git@github.com:$gitHub.git") + connection.set("scm:git://github.com/$gitHub.git") + developerConnection.set("scm:git@github.com:$gitHub.git") url.set(mavenUrl) } issueManagement { diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index c9deefb..d61bc18 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -2,8 +2,8 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("application") - id("com.github.ben-manes.versions") version "0.42.0" - kotlin("jvm") version "1.7.20" + id("com.github.ben-manes.versions") version "0.44.0" + kotlin("jvm") version "1.8.0" } // ./gradlew run @@ -20,7 +20,7 @@ repositories { } dependencies { - implementation("net.thauvin.erik:cryptoprice:1.0.0") + implementation("net.thauvin.erik:cryptoprice:1.1.0-SNAPSHOT") implementation("org.json:json:20220924") } diff --git a/examples/gradle/wrapper/gradle-wrapper.properties b/examples/gradle/wrapper/gradle-wrapper.properties index ae04661..070cb70 100644 --- a/examples/gradle/wrapper/gradle-wrapper.properties +++ b/examples/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ae04661..070cb70 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/pom.xml b/pom.xml index e92e855..661ec0f 100644 --- a/pom.xml +++ b/pom.xml @@ -8,9 +8,9 @@ 4.0.0 net.thauvin.erik cryptoprice - 1.0.0 + 1.0.1-SNAPSHOT cryptoprice - Retrieve cryptocurrencies prices. + Retrieve cryptocurrencies prices https://github.com/ethauvin/cryptoprice @@ -27,8 +27,8 @@ - scm:git:git://github.com/ethauvin/cryptoprice.git - scm:git:git@github.com:ethauvin/cryptoprice.git + scm:git://github.com/ethauvin/cryptoprice.git + scm:git@github.com:ethauvin/cryptoprice.git https://github.com/ethauvin/cryptoprice @@ -40,7 +40,7 @@ org.jetbrains.kotlin kotlin-bom - 1.7.10 + 1.8.0 pom import @@ -50,7 +50,7 @@ org.jetbrains.kotlin kotlin-stdlib-jdk8 - 1.7.10 + 1.8.0 runtime @@ -62,7 +62,7 @@ org.json json - 20220320 + 20220924 runtime diff --git a/src/main/kotlin/net/thauvin/erik/crypto/CryptoException.kt b/src/main/kotlin/net/thauvin/erik/crypto/CryptoException.kt index b5303df..38fd2df 100644 --- a/src/main/kotlin/net/thauvin/erik/crypto/CryptoException.kt +++ b/src/main/kotlin/net/thauvin/erik/crypto/CryptoException.kt @@ -1,8 +1,7 @@ /* * CryptoException.kt * - * Copyright (c) 2021-2022, Erik C. Thauvin (erik@thauvin.net) - * All rights reserved. + * Copyright 2021-2023 Erik C. Thauvin (erik@thauvin.net) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -37,6 +36,7 @@ package net.thauvin.erik.crypto */ class CryptoException @JvmOverloads constructor( var statusCode: Int = NO_STATUS, + var id: String, message: String, cause: Throwable? = null ) : Exception(message, cause) { diff --git a/src/main/kotlin/net/thauvin/erik/crypto/CryptoPrice.kt b/src/main/kotlin/net/thauvin/erik/crypto/CryptoPrice.kt index f8c5b4b..23ab627 100644 --- a/src/main/kotlin/net/thauvin/erik/crypto/CryptoPrice.kt +++ b/src/main/kotlin/net/thauvin/erik/crypto/CryptoPrice.kt @@ -1,8 +1,7 @@ /* * CryptoPrice.kt * - * Copyright (c) 2021-2022, Erik C. Thauvin (erik@thauvin.net) - * All rights reserved. + * Copyright 2021-2023 Erik C. Thauvin (erik@thauvin.net) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -73,9 +72,9 @@ open class CryptoPrice(val base: String, val currency: String, val amount: BigDe return CryptoPrice(getString("base"), getString("currency"), getString("amount").toBigDecimal()) } } catch (e: NumberFormatException) { - throw CryptoException(message = "Could not convert amount to number.", cause = e) + throw CryptoException(id = "convert_error", message = "Could not convert amount to number.", cause = e) } catch (e: JSONException) { - throw CryptoException(message = "Could not parse price data.", cause = e) + throw CryptoException(id = "parse_error", message = "Could not parse price data.", cause = e) } } @@ -101,17 +100,24 @@ open class CryptoPrice(val base: String, val currency: String, val amount: BigDe val request = Request.Builder().url(httpUrl).build() val response = client.newCall(request).execute() - val body = response.body?.string() ?: throw CryptoException(response.code, "Empty response.") + val body = response.body?.string() ?: throw CryptoException( + response.code, + id = "empty_response", + message = "Empty response." + ) try { val json = JSONObject(body) if (response.isSuccessful) { return body } else { val data = json.getJSONArray("errors") - throw CryptoException(response.code, data.getJSONObject(0).getString("message")) + throw CryptoException( + response.code, data.getJSONObject(0).getString("id"), + data.getJSONObject(0).getString("message") + ) } } catch (e: JSONException) { - throw CryptoException(response.code, "Could not parse data.", e) + throw CryptoException(response.code, id = "parse_error", "Could not parse data.", e) } } diff --git a/src/test/kotlin/net/thauvin/erik/crypto/CryptoPriceTest.kt b/src/test/kotlin/net/thauvin/erik/crypto/CryptoPriceTest.kt index cb27271..dbb8eba 100644 --- a/src/test/kotlin/net/thauvin/erik/crypto/CryptoPriceTest.kt +++ b/src/test/kotlin/net/thauvin/erik/crypto/CryptoPriceTest.kt @@ -1,8 +1,7 @@ /* * CryptoPriceTest.kt * - * Copyright (c) 2021-2022, Erik C. Thauvin (erik@thauvin.net) - * All rights reserved. + * Copyright 2021-2023 Erik C. Thauvin (erik@thauvin.net) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -134,6 +133,13 @@ class CryptoPriceTest { block = { spotPrice("FOO") } ) + try { + spotPrice("BAR") + } catch (e: CryptoException) { + assertThat(e.id, "spotPrice(bar) error id").isEqualTo("not_found") + assertThat(e.message, "spotPrice(bar) error message").isEqualTo("Invalid base currency") + } + assertFailsWith( message = "buyPrice(BTC,BAR)", exceptionClass = CryptoException::class, @@ -183,7 +189,11 @@ class CryptoPriceTest { assertEquals("A$12,345.60", aud.toCurrency(), "CryptoPrice(LTC,AUD)") val dk = CryptoPrice("BCH", "DKK", d) - assertEquals("12.345,60 kr.", dk.toCurrency(Locale("da", "DK")), "CryptoPrice(BCH,DKK)") + assertEquals( + "12.345,60 kr.", dk.toCurrency( + Locale.Builder().setLanguage("da").setRegion("DK").build() + ), "CryptoPrice(BCH,DKK)" + ) val jp = CryptoPrice("BTC", "JPY", d) assertEquals("¥12,345.60", jp.toCurrency(Locale.JAPAN), "CryptoPrice(BTC,JPY)")