summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTorsten Grote <t@grobox.de>2020-08-14 10:05:51 -0300
committerTorsten Grote <t@grobox.de>2020-08-14 10:12:53 -0300
commit2ac13b19a5c7fc3531447333fe1772a78ca35795 (patch)
treed5579d87392a6a36d88deec4ceac777e68d6e8b8
parenta35337b991f8b3d38c3480fb76acd9fc6df47885 (diff)
downloadwallet-kotlin-2ac13b19a5c7fc3531447333fe1772a78ca35795.tar.gz
wallet-kotlin-2ac13b19a5c7fc3531447333fe1772a78ca35795.tar.bz2
wallet-kotlin-2ac13b19a5c7fc3531447333fe1772a78ca35795.zip
Add Taler common multiplatform library to project
-rw-r--r--.idea/.gitignore8
-rw-r--r--.idea/codeStyles/Project.xml5
-rw-r--r--.idea/compiler.xml4
-rw-r--r--.idea/modules.xml16
-rw-r--r--.idea/wallet-kotlin.iml19
-rw-r--r--build.gradle178
-rw-r--r--common/.gitignore1
-rw-r--r--common/.gradle/5.5.1/fileChanges/last-build.binbin0 -> 1 bytes
-rw-r--r--common/.gradle/5.5.1/fileHashes/fileHashes.lockbin0 -> 17 bytes
-rw-r--r--common/.gradle/5.5.1/gc.properties0
-rw-r--r--common/.gradle/buildOutputCleanup/buildOutputCleanup.lockbin0 -> 17 bytes
-rw-r--r--common/.gradle/buildOutputCleanup/cache.properties2
-rw-r--r--common/.gradle/vcs-1/gc.properties0
-rw-r--r--common/build.gradle99
-rw-r--r--common/src/commonMain/kotlin/net/taler/common/Amount.kt198
-rw-r--r--common/src/commonMain/kotlin/net/taler/common/TalerUri.kt60
-rw-r--r--common/src/commonMain/kotlin/net/taler/common/Time.kt106
-rw-r--r--common/src/commonMain/kotlin/net/taler/common/Version.kt70
-rw-r--r--common/src/commonTest/kotlin/net/taler/common/AmountTest.kt234
-rw-r--r--common/src/commonTest/kotlin/net/taler/common/TalerUriTest.kt66
-rw-r--r--common/src/commonTest/kotlin/net/taler/common/TestUtils.kt26
-rw-r--r--common/src/commonTest/kotlin/net/taler/common/TimeTest.kt49
-rw-r--r--common/src/commonTest/kotlin/net/taler/common/VersionTest.kt65
-rw-r--r--common/src/jsMain/kotlin/net/taler/common/Time.kt23
-rw-r--r--common/src/jvmMain/kotlin/net/taler/common/Time.kt21
-rw-r--r--common/src/nativeMain/kotlin/net/taler/common/Time.kt23
-rw-r--r--gradle.properties5
-rw-r--r--settings.gradle7
-rw-r--r--wallet/.gitignore1
-rw-r--r--wallet/build.gradle193
-rw-r--r--wallet/src/androidMain/AndroidManifest.xml (renamed from src/androidMain/AndroidManifest.xml)0
-rw-r--r--wallet/src/androidMain/kotlin/net/taler/wallet/kotlin/Db.kt (renamed from src/androidMain/kotlin/net/taler/wallet/kotlin/Db.kt)0
-rw-r--r--wallet/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt (renamed from src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt)0
-rw-r--r--wallet/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/RsaBlinding.kt (renamed from src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/RsaBlinding.kt)0
-rw-r--r--wallet/src/androidTest/kotlin/net/taler/wallet/kotlin/TestUtilsAndroid.kt (renamed from src/androidTest/kotlin/net/taler/wallet/kotlin/TestUtilsAndroid.kt)0
-rw-r--r--wallet/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/PlanchetTest.kt (renamed from src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/PlanchetTest.kt)0
-rw-r--r--wallet/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/RefreshTest.kt (renamed from src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/RefreshTest.kt)0
-rw-r--r--wallet/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/RsaBlindingTest.kt (renamed from src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/RsaBlindingTest.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Amount.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/Amount.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Base32Crockford.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/Base32Crockford.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Db.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/Db.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/PaytoUri.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/PaytoUri.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/TalerUri.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/TalerUri.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Time.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/Time.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Types.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/Types.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Utils.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/Utils.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Version.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/Version.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/WalletApi.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/WalletApi.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Crypto.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Crypto.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoImpl.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoImpl.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Deposit.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Deposit.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Kdf.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Kdf.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Planchet.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Planchet.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Recoup.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Recoup.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Refresh.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Refresh.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Signature.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Signature.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Auditor.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Auditor.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Denomination.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Denomination.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Exchange.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Exchange.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/ExchangeRecord.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/ExchangeRecord.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Keys.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Keys.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Wire.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Wire.kt)0
-rw-r--r--wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/operations/Withdraw.kt (renamed from src/commonMain/kotlin/net/taler/wallet/kotlin/operations/Withdraw.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/AmountTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/AmountTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/Base32CrockfordTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/Base32CrockfordTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/DbTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/DbTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/PaytoUriTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/PaytoUriTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/TalerUriTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/TalerUriTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/TimestampTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/TimestampTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/VersionTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/VersionTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/WalletApiTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/WalletApiTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/DepositTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/DepositTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/EllipticCurveTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/EllipticCurveTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/KdfTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/KdfTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/RecoupTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/RecoupTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/RefreshPlanchetTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/RefreshPlanchetTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha256Test.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha256Test.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha512Test.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha512Test.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/SignatureTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/SignatureTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/DenominationTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/DenominationTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/Denominations.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/Denominations.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/KeysTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/KeysTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/UpdateTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/UpdateTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/WireTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/WireTest.kt)0
-rw-r--r--wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/operations/WithdrawTest.kt (renamed from src/commonTest/kotlin/net/taler/wallet/kotlin/operations/WithdrawTest.kt)0
-rw-r--r--wallet/src/jsMain/kotlin/net/taler/wallet/kotlin/Db.kt (renamed from src/jsMain/kotlin/net/taler/wallet/kotlin/Db.kt)0
-rw-r--r--wallet/src/jsMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt (renamed from src/jsMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt)0
-rw-r--r--wallet/src/jsTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt (renamed from src/jsTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt)0
-rw-r--r--wallet/src/nativeInterop/cinterop/sodium-static.def (renamed from src/nativeInterop/cinterop/sodium-static.def)0
-rw-r--r--wallet/src/nativeInterop/cinterop/sodium.def (renamed from src/nativeInterop/cinterop/sodium.def)0
-rw-r--r--wallet/src/nativeMain/kotlin/net/taler/wallet/kotlin/Db.kt (renamed from src/nativeMain/kotlin/net/taler/wallet/kotlin/Db.kt)0
-rw-r--r--wallet/src/nativeMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt (renamed from src/nativeMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt)0
-rw-r--r--wallet/src/nativeTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt (renamed from src/nativeTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt)0
94 files changed, 1286 insertions, 193 deletions
diff --git a/.idea/.gitignore b/.idea/.gitignore
index 3127cf3..8eae92b 100644
--- a/.idea/.gitignore
+++ b/.idea/.gitignore
@@ -1,10 +1,14 @@
# Default ignored files
/shelf/
/artifacts
-/modules
+/modules*
/workspace.xml
/gradle.xml
/libraries
/caches
/runConfigurations.xml
-/encodings.xml \ No newline at end of file
+/encodings.xml
+/vcs.xml
+/compiler.xml
+/jarRepositories.xml
+/misc.xml \ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 61a2480..69cf9a7 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -1,6 +1,11 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JetCodeStyleSettings>
+ <option name="PACKAGES_TO_USE_STAR_IMPORTS">
+ <value>
+ <package name="kotlinx.android.synthetic" withSubpackages="true" static="false" />
+ </value>
+ </option>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
<option name="IMPORT_NESTED_CLASSES" value="true" />
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index ad4fc3c..72e41ea 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -12,6 +12,10 @@
<entry name="!?*.clj" />
</wildcardResourcePatterns>
<bytecodeTargetLevel target="1.8">
+ <module name="wallet-kotlin.common.jvmMain" target="1.6" />
+ <module name="wallet-kotlin.common.jvmMain~1" target="1.6" />
+ <module name="wallet-kotlin.common.jvmTest" target="1.6" />
+ <module name="wallet-kotlin.common.jvmTest~1" target="1.6" />
<module name="wallet-kotlin_androidMain" target="1.6" />
<module name="wallet-kotlin_androidTest" target="1.6" />
</bytecodeTargetLevel>
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index d8c63dd..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="ProjectModuleManager">
- <modules>
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/wallet-kotlin.iml" filepath="$PROJECT_DIR$/.idea/modules/wallet-kotlin.iml" group="wallet-kotlin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/wallet-kotlin_androidMain.iml" filepath="$PROJECT_DIR$/.idea/modules/wallet-kotlin_androidMain.iml" group="wallet-kotlin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/wallet-kotlin_androidTest.iml" filepath="$PROJECT_DIR$/.idea/modules/wallet-kotlin_androidTest.iml" group="wallet-kotlin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/wallet-kotlin_commonMain.iml" filepath="$PROJECT_DIR$/.idea/modules/wallet-kotlin_commonMain.iml" group="wallet-kotlin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/wallet-kotlin_commonTest.iml" filepath="$PROJECT_DIR$/.idea/modules/wallet-kotlin_commonTest.iml" group="wallet-kotlin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/wallet-kotlin_jsMain.iml" filepath="$PROJECT_DIR$/.idea/modules/wallet-kotlin_jsMain.iml" group="wallet-kotlin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/wallet-kotlin_jsTest.iml" filepath="$PROJECT_DIR$/.idea/modules/wallet-kotlin_jsTest.iml" group="wallet-kotlin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/wallet-kotlin_linuxMain.iml" filepath="$PROJECT_DIR$/.idea/modules/wallet-kotlin_linuxMain.iml" group="wallet-kotlin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/wallet-kotlin_linuxTest.iml" filepath="$PROJECT_DIR$/.idea/modules/wallet-kotlin_linuxTest.iml" group="wallet-kotlin" />
- </modules>
- </component>
-</project> \ No newline at end of file
diff --git a/.idea/wallet-kotlin.iml b/.idea/wallet-kotlin.iml
new file mode 100644
index 0000000..57eb384
--- /dev/null
+++ b/.idea/wallet-kotlin.iml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id="wallet-kotlin" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+ <component name="FacetManager">
+ <facet type="java-gradle" name="Java-Gradle">
+ <configuration>
+ <option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
+ <option name="BUILDABLE" value="false" />
+ </configuration>
+ </facet>
+ </component>
+ <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <excludeFolder url="file://$MODULE_DIR$/.gradle" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module> \ No newline at end of file
diff --git a/build.gradle b/build.gradle
index e0b1a1b..c6c9e9f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -21,181 +21,15 @@ buildscript {
jcenter()
}
dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath 'com.android.tools.build:gradle:4.0.1'
}
}
-plugins {
- id 'org.jetbrains.kotlin.multiplatform' version "$kotlin_version"
- id 'org.jetbrains.kotlin.plugin.serialization' version "$kotlin_version"
-}
-
-repositories {
- mavenCentral()
- jcenter()
- google()
- maven { url "https://dl.bintray.com/terl/lazysodium-maven" }
-}
-group 'net.taler'
-version '0.0.1'
-
-apply plugin: 'com.android.library'
-apply plugin: 'maven-publish'
-
-
-kotlin {
- android {}
- js {
- browser {
- }
- nodejs {
- }
- }
- // For ARM, should be changed to iosArm32 or iosArm64
- ios {
- compilations.main.cinterops {
- sodium {
- packageName 'org.libsodium'
- defFile project.file("src/nativeInterop/cinterop/sodium-static.def")
- }
- }
- binaries {
- framework {
- baseName = "TalerWallet"
- }
- }
- }
- // For Linux, should be changed to e.g. linuxX64
- // For MacOS, should be changed to e.g. macosX64
- // For Windows, should be changed to e.g. mingwX64
- linuxX64("linux") {
- compilations.main.cinterops {
- sodium {
- packageName 'org.libsodium'
- }
- }
- }
- sourceSets {
- def coroutines_version = "1.3.8"
- def ktor_version = "1.3.2"
- all {
- languageSettings {
- useExperimentalAnnotation('kotlin.ExperimentalStdlibApi')
- }
- }
- commonMain {
- dependencies {
- implementation kotlin('stdlib-common')
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutines_version"
- implementation "io.ktor:ktor-client-core:$ktor_version"
- implementation "io.ktor:ktor-client-logging:$ktor_version"
- implementation "io.ktor:ktor-client-serialization:$ktor_version"
- implementation "com.soywiz.korlibs.klock:klock:1.11.12"
- }
- }
- commonTest {
- dependencies {
- implementation kotlin('test-common')
- implementation kotlin('test-annotations-common')
- implementation "io.ktor:ktor-client-mock:$ktor_version"
- }
- }
- androidMain {
- dependencies {
- implementation kotlin('stdlib-jdk8')
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
- implementation "io.ktor:ktor-client-android:$ktor_version"
- implementation "io.ktor:ktor-client-logging-jvm:$ktor_version"
- implementation "io.ktor:ktor-client-serialization-jvm:$ktor_version"
- // TODO Android
-// implementation("com.goterl.lazycode:lazysodium-android:4.2.0@aar") {
- implementation("com.goterl.lazycode:lazysodium-java:4.3.0") {
- exclude group: "org.slf4j"
- }
- implementation 'net.java.dev.jna:jna:5.6.0@aar'
- }
- }
- androidTest {
- dependencies {
- implementation kotlin('test')
- implementation kotlin('test-junit')
- implementation "io.ktor:ktor-client-mock-jvm:$ktor_version"
- implementation "org.slf4j:slf4j-simple:1.7.30"
- }
- }
- jsMain {
- dependencies {
- implementation kotlin('stdlib-js')
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:$coroutines_version"
- implementation "io.ktor:ktor-client-js:$ktor_version"
- implementation "io.ktor:ktor-client-logging-js:$ktor_version"
- implementation "io.ktor:ktor-client-serialization-js:$ktor_version"
- // bug: https://github.com/ktorio/ktor/issues/1822
- api npm("text-encoding", '0.7.0') // work-around for above bug
- api npm("bufferutil", '4.0.1') // work-around for above bug
- api npm("utf-8-validate", '5.0.2') // work-around for above bug
- api npm("abort-controller", '3.0.0') // work-around for above bug
- api npm("node-fetch", '2.6.0') // work-around for above bug
- api npm("fs", '*') // work-around for above bug
-
- implementation npm('tweetnacl', '1.0.3')
- implementation npm('ed2curve', '0.3.0')
- implementation npm('hash.js', '1.1.7')
- }
- }
- jsTest {
- dependencies {
- implementation kotlin('test-js')
- implementation "io.ktor:ktor-client-mock-js:$ktor_version"
- }
- }
- nativeMain {
- dependsOn commonMain
- dependencies {
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version"
- implementation "io.ktor:ktor-client-logging-native:$ktor_version"
- implementation "io.ktor:ktor-client-serialization-native:$ktor_version"
- }
- }
- nativeTest {
- dependsOn commonTest
- dependencies {
- implementation "io.ktor:ktor-client-mock-native:$ktor_version"
- }
- }
- linuxMain {
- dependsOn nativeMain
- dependencies {
- implementation "io.ktor:ktor-client-curl:$ktor_version"
- }
- }
- iosMain {
- dependsOn nativeMain
- dependencies {
- implementation "io.ktor:ktor-client-ios:$ktor_version"
- }
- }
- configure([targets.linux, targets.iosArm64, targets.iosX64]) {
- compilations.main.source(sourceSets.nativeMain)
- compilations.test.source(sourceSets.nativeTest)
- }
- }
-}
-
-android {
- compileSdkVersion 29
- //noinspection GradleDependency
- buildToolsVersion "29.0.2"
-
- defaultConfig {
- minSdkVersion 21
- targetSdkVersion 29
- versionCode 1
- versionName "0.1"
- }
- sourceSets {
- main {
- manifest.srcFile 'src/androidMain/AndroidManifest.xml'
- }
+allprojects {
+ repositories {
+ mavenCentral()
+ jcenter()
}
}
diff --git a/common/.gitignore b/common/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/common/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/common/.gradle/5.5.1/fileChanges/last-build.bin b/common/.gradle/5.5.1/fileChanges/last-build.bin
new file mode 100644
index 0000000..f76dd23
--- /dev/null
+++ b/common/.gradle/5.5.1/fileChanges/last-build.bin
Binary files differ
diff --git a/common/.gradle/5.5.1/fileHashes/fileHashes.lock b/common/.gradle/5.5.1/fileHashes/fileHashes.lock
new file mode 100644
index 0000000..34525bf
--- /dev/null
+++ b/common/.gradle/5.5.1/fileHashes/fileHashes.lock
Binary files differ
diff --git a/common/.gradle/5.5.1/gc.properties b/common/.gradle/5.5.1/gc.properties
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/common/.gradle/5.5.1/gc.properties
diff --git a/common/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/common/.gradle/buildOutputCleanup/buildOutputCleanup.lock
new file mode 100644
index 0000000..04431dd
--- /dev/null
+++ b/common/.gradle/buildOutputCleanup/buildOutputCleanup.lock
Binary files differ
diff --git a/common/.gradle/buildOutputCleanup/cache.properties b/common/.gradle/buildOutputCleanup/cache.properties
new file mode 100644
index 0000000..df9e847
--- /dev/null
+++ b/common/.gradle/buildOutputCleanup/cache.properties
@@ -0,0 +1,2 @@
+#Thu Jul 30 09:16:47 BRT 2020
+gradle.version=5.5.1
diff --git a/common/.gradle/vcs-1/gc.properties b/common/.gradle/vcs-1/gc.properties
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/common/.gradle/vcs-1/gc.properties
diff --git a/common/build.gradle b/common/build.gradle
new file mode 100644
index 0000000..efc1fe0
--- /dev/null
+++ b/common/build.gradle
@@ -0,0 +1,99 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+plugins {
+ id 'org.jetbrains.kotlin.multiplatform'
+ id 'org.jetbrains.kotlin.plugin.serialization'
+}
+
+group 'net.taler'
+version '0.0.1'
+
+apply plugin: 'maven-publish'
+
+kotlin {
+ jvm()
+ js {
+ browser {
+ }
+ nodejs {
+ }
+ }
+ // This is for iPhone simulator
+ // Switch here to iosArm64 (or iosArm32) to build library for iPhone device
+ ios {
+ binaries {
+ framework()
+ }
+ }
+ linuxX64("linux")
+
+ sourceSets {
+ def serialization_version = "0.20.0"
+ commonMain {
+ dependencies {
+ implementation kotlin('stdlib-common')
+ implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version"
+ }
+ }
+ commonTest {
+ dependencies {
+ implementation kotlin('test-common')
+ implementation kotlin('test-annotations-common')
+ }
+ }
+ jvmMain {
+ dependencies {
+ implementation kotlin('stdlib-jdk8')
+ implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version"
+ }
+ }
+ jvmTest {
+ dependencies {
+ implementation kotlin('test')
+ implementation kotlin('test-junit')
+ }
+ }
+ jsMain {
+ dependencies {
+ implementation kotlin('stdlib-js')
+ implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$serialization_version"
+ }
+ }
+ jsTest {
+ dependencies {
+ implementation kotlin('test-js')
+ }
+ }
+ nativeMain {
+ dependsOn commonMain
+ dependencies {
+ implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version"
+ }
+ }
+ nativeTest {
+ dependsOn commonTest
+ }
+ configure([targets.linux, targets.iosArm64, targets.iosX64]) {
+ compilations.main.source(sourceSets.nativeMain)
+ compilations.test.source(sourceSets.nativeTest)
+ }
+ }
+}
+
+configurations {
+ compileClasspath
+}
diff --git a/common/src/commonMain/kotlin/net/taler/common/Amount.kt b/common/src/commonMain/kotlin/net/taler/common/Amount.kt
new file mode 100644
index 0000000..84d10c5
--- /dev/null
+++ b/common/src/commonMain/kotlin/net/taler/common/Amount.kt
@@ -0,0 +1,198 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+import kotlinx.serialization.Decoder
+import kotlinx.serialization.Encoder
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.Serializer
+import kotlin.math.floor
+import kotlin.math.pow
+import kotlin.math.roundToInt
+
+class AmountParserException(msg: String? = null, cause: Throwable? = null) : Exception(msg, cause)
+class AmountOverflowException(msg: String? = null, cause: Throwable? = null) : Exception(msg, cause)
+
+@Serializable(with = KotlinXAmountSerializer::class)
+data class Amount(
+ /**
+ * name of the currency using either a three-character ISO 4217 currency code,
+ * or a regional currency identifier starting with a "*" followed by at most 10 characters.
+ * ISO 4217 exponents in the name are not supported,
+ * although the "fraction" is corresponds to an ISO 4217 exponent of 6.
+ */
+ val currency: String,
+
+ /**
+ * The integer part may be at most 2^52.
+ * Note that "1" here would correspond to 1 EUR or 1 USD, depending on currency, not 1 cent.
+ */
+ val value: Long,
+
+ /**
+ * Unsigned 32 bit fractional value to be added to value representing
+ * an additional currency fraction, in units of one hundred millionth (1e-8)
+ * of the base currency value. For example, a fraction
+ * of 50_000_000 would correspond to 50 cents.
+ */
+ val fraction: Int
+) : Comparable<Amount> {
+
+ companion object {
+
+ private const val FRACTIONAL_BASE: Int = 100000000 // 1e8
+
+ private val REGEX_CURRENCY = Regex("""^[-_*A-Za-z0-9]{1,12}$""")
+ val MAX_VALUE = 2.0.pow(52).toLong()
+ private const val MAX_FRACTION_LENGTH = 8
+ const val MAX_FRACTION = 99_999_999
+
+ fun zero(currency: String): Amount {
+ return Amount(checkCurrency(currency), 0, 0)
+ }
+
+ fun fromJSONString(str: String): Amount {
+ val split = str.split(":")
+ if (split.size != 2) throw AmountParserException("Invalid Amount Format")
+ return fromString(split[0], split[1])
+ }
+
+ fun fromString(currency: String, str: String): Amount {
+ // value
+ val valueSplit = str.split(".")
+ val value = checkValue(valueSplit[0].toLongOrNull())
+ // fraction
+ val fraction: Int = if (valueSplit.size > 1) {
+ val fractionStr = valueSplit[1]
+ if (fractionStr.length > MAX_FRACTION_LENGTH)
+ throw AmountParserException("Fraction $fractionStr too long")
+ val fraction = "0.$fractionStr".toDoubleOrNull()
+ ?.times(FRACTIONAL_BASE)
+ ?.roundToInt()
+ checkFraction(fraction)
+ } else 0
+ return Amount(checkCurrency(currency), value, fraction)
+ }
+
+ fun min(currency: String): Amount = Amount(currency, 0, 1)
+ fun max(currency: String): Amount = Amount(currency, MAX_VALUE, MAX_FRACTION)
+
+
+ internal fun checkCurrency(currency: String): String {
+ if (!REGEX_CURRENCY.matches(currency))
+ throw AmountParserException("Invalid currency: $currency")
+ return currency
+ }
+
+ internal fun checkValue(value: Long?): Long {
+ if (value == null || value > MAX_VALUE)
+ throw AmountParserException("Value $value greater than $MAX_VALUE")
+ return value
+ }
+
+ internal fun checkFraction(fraction: Int?): Int {
+ if (fraction == null || fraction > MAX_FRACTION)
+ throw AmountParserException("Fraction $fraction greater than $MAX_FRACTION")
+ return fraction
+ }
+
+ }
+
+ val amountStr: String
+ get() = if (fraction == 0) "$value" else {
+ var f = fraction
+ var fractionStr = ""
+ while (f > 0) {
+ fractionStr += f / (FRACTIONAL_BASE / 10)
+ f = (f * 10) % FRACTIONAL_BASE
+ }
+ "$value.$fractionStr"
+ }
+
+ operator fun plus(other: Amount): Amount {
+ check(currency == other.currency) { "Can only subtract from same currency" }
+ val resultValue = value + other.value + floor((fraction + other.fraction).toDouble() / FRACTIONAL_BASE).toLong()
+ if (resultValue > MAX_VALUE)
+ throw AmountOverflowException()
+ val resultFraction = (fraction + other.fraction) % FRACTIONAL_BASE
+ return Amount(currency, resultValue, resultFraction)
+ }
+
+ operator fun times(factor: Int): Amount {
+ // TODO consider replacing with a faster implementation
+ if (factor == 0) return zero(currency)
+ var result = this
+ for (i in 1 until factor) result += this
+ return result
+ }
+
+ operator fun minus(other: Amount): Amount {
+ check(currency == other.currency) { "Can only subtract from same currency" }
+ var resultValue = value
+ var resultFraction = fraction
+ if (resultFraction < other.fraction) {
+ if (resultValue < 1L)
+ throw AmountOverflowException()
+ resultValue--
+ resultFraction += FRACTIONAL_BASE
+ }
+ check(resultFraction >= other.fraction)
+ resultFraction -= other.fraction
+ if (resultValue < other.value)
+ throw AmountOverflowException()
+ resultValue -= other.value
+ return Amount(currency, resultValue, resultFraction)
+ }
+
+ fun isZero(): Boolean {
+ return value == 0L && fraction == 0
+ }
+
+ fun toJSONString(): String {
+ return "$currency:$amountStr"
+ }
+
+ override fun toString(): String {
+ return "$amountStr $currency"
+ }
+
+ override fun compareTo(other: Amount): Int {
+ check(currency == other.currency) { "Can only compare amounts with the same currency" }
+ when {
+ value == other.value -> {
+ if (fraction < other.fraction) return -1
+ if (fraction > other.fraction) return 1
+ return 0
+ }
+ value < other.value -> return -1
+ else -> return 1
+ }
+ }
+
+}
+
+@Serializer(forClass = Amount::class)
+object KotlinXAmountSerializer: KSerializer<Amount> {
+ override fun serialize(encoder: Encoder, value: Amount) {
+ encoder.encodeString(value.toJSONString())
+ }
+
+ override fun deserialize(decoder: Decoder): Amount {
+ return Amount.fromJSONString(decoder.decodeString())
+ }
+}
diff --git a/common/src/commonMain/kotlin/net/taler/common/TalerUri.kt b/common/src/commonMain/kotlin/net/taler/common/TalerUri.kt
new file mode 100644
index 0000000..9f121d3
--- /dev/null
+++ b/common/src/commonMain/kotlin/net/taler/common/TalerUri.kt
@@ -0,0 +1,60 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+internal object TalerUri {
+
+ private const val SCHEME = "taler://"
+ private const val SCHEME_INSECURE = "taler+http://"
+ private const val AUTHORITY_PAY = "pay"
+ private const val AUTHORITY_WITHDRAW = "withdraw"
+ private const val AUTHORITY_REFUND = "refund"
+ private const val AUTHORITY_TIP = "tip"
+
+ data class WithdrawUriResult(
+ val bankIntegrationApiBaseUrl: String,
+ val withdrawalOperationId: String
+ )
+
+ /**
+ * Parses a withdraw URI and returns a bank status URL or null if the URI was invalid.
+ */
+ fun parseWithdrawUri(uri: String): WithdrawUriResult? {
+ val (resultScheme, prefix) = when {
+ uri.startsWith(SCHEME, ignoreCase = true) -> {
+ Pair("https://", "${SCHEME}${AUTHORITY_WITHDRAW}/")
+ }
+ uri.startsWith(SCHEME_INSECURE, ignoreCase = true) -> {
+ Pair("http://", "${SCHEME_INSECURE}${AUTHORITY_WITHDRAW}/")
+ }
+ else -> return null
+ }
+ if (!uri.startsWith(prefix)) return null
+ val parts = uri.let {
+ (if (it.endsWith("/")) it.dropLast(1) else it).substring(prefix.length).split('/')
+ }
+ if (parts.size < 2) return null
+ val host = parts[0].toLowerCase()
+ val pathSegments = parts.slice(1 until parts.size - 1).joinToString("/")
+ val withdrawId = parts.last()
+ if (withdrawId.isBlank()) return null
+ val url = "${resultScheme}${host}/${pathSegments}"
+
+ return WithdrawUriResult(url, withdrawId)
+ }
+
+}
diff --git a/common/src/commonMain/kotlin/net/taler/common/Time.kt b/common/src/commonMain/kotlin/net/taler/common/Time.kt
new file mode 100644
index 0000000..37b6606
--- /dev/null
+++ b/common/src/commonMain/kotlin/net/taler/common/Time.kt
@@ -0,0 +1,106 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.builtins.serializer
+import kotlinx.serialization.json.JsonElement
+import kotlinx.serialization.json.JsonPrimitive
+import kotlinx.serialization.json.JsonTransformingSerializer
+import kotlinx.serialization.json.contentOrNull
+import kotlinx.serialization.json.longOrNull
+import net.taler.common.Duration.Companion.FOREVER
+import kotlin.math.max
+
+expect fun nowMillis(): Long
+
+@Serializable
+data class Timestamp(
+ @SerialName("t_ms")
+ @Serializable(NeverSerializer::class)
+ val ms: Long
+) : Comparable<Timestamp> {
+
+ companion object {
+ const val NEVER: Long = -1
+ fun now(): Timestamp = Timestamp(nowMillis())
+ }
+
+ /**
+ * Returns a copy of this [Timestamp] rounded to seconds.
+ */
+ fun truncateSeconds(): Timestamp {
+ if (ms == NEVER) return Timestamp(ms)
+ return Timestamp((ms / 1000L) * 1000L)
+ }
+
+ operator fun minus(other: Timestamp): Duration = when {
+ ms == NEVER -> Duration(FOREVER)
+ other.ms == NEVER -> throw Error("Invalid argument for timestamp comparision")
+ ms < other.ms -> Duration(0)
+ else -> Duration(ms - other.ms)
+ }
+
+ operator fun minus(other: Duration): Timestamp = when {
+ ms == NEVER -> this
+ other.ms == FOREVER -> Timestamp(0)
+ else -> Timestamp(max(0, ms - other.ms))
+ }
+
+ override fun compareTo(other: Timestamp): Int {
+ return if (ms == NEVER) {
+ if (other.ms == NEVER) 0
+ else 1
+ } else {
+ if (other.ms == NEVER) -1
+ else ms.compareTo(other.ms)
+ }
+ }
+
+}
+
+@Serializable
+data class Duration(
+ /**
+ * Duration in milliseconds.
+ */
+ @SerialName("d_ms")
+ @Serializable(ForeverSerializer::class)
+ val ms: Long
+) {
+ companion object {
+ const val FOREVER: Long = -1
+ }
+}
+
+abstract class MinusOneSerializer(private val keyword: String) :
+ JsonTransformingSerializer<Long>(Long.serializer(), keyword) {
+
+ override fun readTransform(element: JsonElement): JsonElement {
+ return if (element.contentOrNull == keyword) return JsonPrimitive(-1)
+ else super.readTransform(element)
+ }
+
+ override fun writeTransform(element: JsonElement): JsonElement {
+ return if (element.longOrNull == -1L) return JsonPrimitive(keyword)
+ else element
+ }
+}
+
+object NeverSerializer : MinusOneSerializer("never")
+object ForeverSerializer : MinusOneSerializer("forever")
diff --git a/common/src/commonMain/kotlin/net/taler/common/Version.kt b/common/src/commonMain/kotlin/net/taler/common/Version.kt
new file mode 100644
index 0000000..8774115
--- /dev/null
+++ b/common/src/commonMain/kotlin/net/taler/common/Version.kt
@@ -0,0 +1,70 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+import kotlin.math.sign
+
+/**
+ * Semantic versioning, but libtool-style.
+ * See https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
+ */
+data class Version(
+ val current: Int,
+ val revision: Int,
+ val age: Int
+) {
+ companion object {
+ fun parse(v: String): Version? {
+ val elements = v.split(":")
+ if (elements.size != 3) return null
+ val (currentStr, revisionStr, ageStr) = elements
+ val current = currentStr.toIntOrNull()
+ val revision = revisionStr.toIntOrNull()
+ val age = ageStr.toIntOrNull()
+ if (current == null || revision == null || age == null) return null
+ return Version(current, revision, age)
+ }
+ }
+
+ /**
+ * Compare two libtool-style versions.
+ *
+ * Returns a [VersionMatchResult] or null if the given version was null.
+ */
+ fun compare(other: Version?): VersionMatchResult? {
+ if (other == null) return null
+ val compatible = current - age <= other.current &&
+ current >= other.current - other.age
+ val currentCmp = sign((current - other.current).toDouble()).toInt()
+ return VersionMatchResult(compatible, currentCmp)
+ }
+
+ /**
+ * Result of comparing two libtool versions.
+ */
+ data class VersionMatchResult(
+ /**
+ * Is the first version compatible with the second?
+ */
+ val compatible: Boolean,
+ /**
+ * Is the first version older (-1), newer (+1) or identical (0)?
+ */
+ val currentCmp: Int
+ )
+
+}
diff --git a/common/src/commonTest/kotlin/net/taler/common/AmountTest.kt b/common/src/commonTest/kotlin/net/taler/common/AmountTest.kt
new file mode 100644
index 0000000..e184307
--- /dev/null
+++ b/common/src/commonTest/kotlin/net/taler/common/AmountTest.kt
@@ -0,0 +1,234 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+import kotlin.random.Random
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertFalse
+import kotlin.test.assertTrue
+import kotlin.test.fail
+
+class AmountTest {
+
+ companion object {
+ fun getRandomAmount() = getRandomAmount(getRandomString(1, Random.nextInt(1, 12)))
+ fun getRandomAmount(currency: String): Amount {
+ val value = Random.nextLong(0, Amount.MAX_VALUE)
+ val fraction = Random.nextInt(0, Amount.MAX_FRACTION)
+ return Amount(currency, value, fraction)
+ }
+ }
+
+ @Test
+ fun testFromJSONString() {
+ var str = "TESTKUDOS:23.42"
+ var amount = Amount.fromJSONString(str)
+ assertEquals(str, amount.toJSONString())
+ assertEquals("TESTKUDOS", amount.currency)
+ assertEquals(23, amount.value)
+ assertEquals((0.42 * 1e8).toInt(), amount.fraction)
+ assertEquals("23.42 TESTKUDOS", amount.toString())
+
+ str = "EUR:500000000.00000001"
+ amount = Amount.fromJSONString(str)
+ assertEquals(str, amount.toJSONString())
+ assertEquals("EUR", amount.currency)
+ assertEquals(500000000, amount.value)
+ assertEquals(1, amount.fraction)
+ assertEquals("500000000.00000001 EUR", amount.toString())
+
+ str = "EUR:1500000000.00000003"
+ amount = Amount.fromJSONString(str)
+ assertEquals(str, amount.toJSONString())
+ assertEquals("EUR", amount.currency)
+ assertEquals(1500000000, amount.value)
+ assertEquals(3, amount.fraction)
+ assertEquals("1500000000.00000003 EUR", amount.toString())
+ }
+
+ @Test
+ fun testFromJSONStringAcceptsMaxValuesRejectsAbove() {
+ val maxValue = 4503599627370496
+ val str = "TESTKUDOS123:$maxValue.99999999"
+ val amount = Amount.fromJSONString(str)
+ assertEquals(str, amount.toJSONString())
+ assertEquals("TESTKUDOS123", amount.currency)
+ assertEquals(maxValue, amount.value)
+ assertEquals("$maxValue.99999999 TESTKUDOS123", amount.toString())
+
+ // longer currency not accepted
+ assertThrows<AmountParserException>("longer currency was accepted") {
+ Amount.fromJSONString("TESTKUDOS1234:$maxValue.99999999")
+ }
+
+ // max value + 1 not accepted
+ assertThrows<AmountParserException>("max value + 1 was accepted") {
+ Amount.fromJSONString("TESTKUDOS123:${maxValue + 1}.99999999")
+ }
+
+ // max fraction + 1 not accepted
+ assertThrows<AmountParserException>("max fraction + 1 was accepted") {
+ Amount.fromJSONString("TESTKUDOS123:$maxValue.999999990")
+ }
+ }
+
+ @Test
+ fun testFromJSONStringRejections() {
+ assertThrows<AmountParserException> {
+ Amount.fromJSONString("TESTKUDOS:0,5")
+ }
+ assertThrows<AmountParserException> {
+ Amount.fromJSONString("+TESTKUDOS:0.5")
+ }
+ assertThrows<AmountParserException> {
+ Amount.fromJSONString("0.5")
+ }
+ assertThrows<AmountParserException> {
+ Amount.fromJSONString(":0.5")
+ }
+ assertThrows<AmountParserException> {
+ Amount.fromJSONString("EUR::0.5")
+ }
+ assertThrows<AmountParserException> {
+ Amount.fromJSONString("EUR:.5")
+ }
+ }
+
+ @Test
+ fun testAddition() {
+ assertEquals(
+ Amount.fromJSONString("EUR:2"),
+ Amount.fromJSONString("EUR:1") + Amount.fromJSONString("EUR:1")
+ )
+ assertEquals(
+ Amount.fromJSONString("EUR:3"),
+ Amount.fromJSONString("EUR:1.5") + Amount.fromJSONString("EUR:1.5")
+ )
+ assertEquals(
+ Amount.fromJSONString("EUR:500000000.00000002"),
+ Amount.fromJSONString("EUR:500000000.00000001") + Amount.fromJSONString("EUR:0.00000001")
+ )
+ assertThrows<AmountOverflowException>("addition didn't overflow") {
+ Amount.fromJSONString("EUR:4503599627370496.99999999") + Amount.fromJSONString("EUR:0.00000001")
+ }
+ assertThrows<AmountOverflowException>("addition didn't overflow") {
+ Amount.fromJSONString("EUR:4000000000000000") + Amount.fromJSONString("EUR:4000000000000000")
+ }
+ }
+
+ @Test
+ fun testTimes() {
+ assertEquals(
+ Amount.fromJSONString("EUR:2"),
+ Amount.fromJSONString("EUR:2") * 1
+ )
+ assertEquals(
+ Amount.fromJSONString("EUR:2"),
+ Amount.fromJSONString("EUR:1") * 2
+ )
+ assertEquals(
+ Amount.fromJSONString("EUR:4.5"),
+ Amount.fromJSONString("EUR:1.5") * 3
+ )
+ assertEquals(Amount.fromJSONString("EUR:0"), Amount.fromJSONString("EUR:1.11") * 0)
+ assertEquals(Amount.fromJSONString("EUR:1.11"), Amount.fromJSONString("EUR:1.11") * 1)
+ assertEquals(Amount.fromJSONString("EUR:2.22"), Amount.fromJSONString("EUR:1.11") * 2)
+ assertEquals(Amount.fromJSONString("EUR:3.33"), Amount.fromJSONString("EUR:1.11") * 3)
+ assertEquals(Amount.fromJSONString("EUR:4.44"), Amount.fromJSONString("EUR:1.11") * 4)
+ assertEquals(Amount.fromJSONString("EUR:5.55"), Amount.fromJSONString("EUR:1.11") * 5)
+ assertEquals(
+ Amount.fromJSONString("EUR:1500000000.00000003"),
+ Amount.fromJSONString("EUR:500000000.00000001") * 3
+ )
+ assertThrows<AmountOverflowException>("times didn't overflow") {
+ Amount.fromJSONString("EUR:4000000000000000") * 2
+ }
+ }
+
+ @Test
+ fun testSubtraction() {
+ assertEquals(
+ Amount.fromJSONString("EUR:0"),
+ Amount.fromJSONString("EUR:1") - Amount.fromJSONString("EUR:1")
+ )
+ assertEquals(
+ Amount.fromJSONString("EUR:1.5"),
+ Amount.fromJSONString("EUR:3") - Amount.fromJSONString("EUR:1.5")
+ )
+ assertEquals(
+ Amount.fromJSONString("EUR:500000000.00000001"),
+ Amount.fromJSONString("EUR:500000000.00000002") - Amount.fromJSONString("EUR:0.00000001")
+ )
+ assertThrows<AmountOverflowException>("subtraction didn't underflow") {
+ Amount.fromJSONString("EUR:23.42") - Amount.fromJSONString("EUR:42.23")
+ }
+ assertThrows<AmountOverflowException>("subtraction didn't underflow") {
+ Amount.fromJSONString("EUR:0.5") - Amount.fromJSONString("EUR:0.50000001")
+ }
+ }
+
+ @Test
+ fun testIsZero() {
+ assertTrue(Amount.zero("EUR").isZero())
+ assertTrue(Amount.fromJSONString("EUR:0").isZero())
+ assertTrue(Amount.fromJSONString("EUR:0.0").isZero())
+ assertTrue(Amount.fromJSONString("EUR:0.00000").isZero())
+ assertTrue((Amount.fromJSONString("EUR:1.001") - Amount.fromJSONString("EUR:1.001")).isZero())
+
+ assertFalse(Amount.fromJSONString("EUR:0.00000001").isZero())
+ assertFalse(Amount.fromJSONString("EUR:1.0").isZero())
+ assertFalse(Amount.fromJSONString("EUR:0001.0").isZero())
+ }
+
+ @Test
+ fun testComparision() {
+ assertTrue(Amount.fromJSONString("EUR:0") <= Amount.fromJSONString("EUR:0"))
+ assertTrue(Amount.fromJSONString("EUR:0") <= Amount.fromJSONString("EUR:0.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:0") < Amount.fromJSONString("EUR:0.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:0") < Amount.fromJSONString("EUR:1"))
+ assertEquals(Amount.fromJSONString("EUR:0"), Amount.fromJSONString("EUR:0"))
+ assertEquals(Amount.fromJSONString("EUR:42"), Amount.fromJSONString("EUR:42"))
+ assertEquals(
+ Amount.fromJSONString("EUR:42.00000001"),
+ Amount.fromJSONString("EUR:42.00000001")
+ )
+ assertTrue(Amount.fromJSONString("EUR:42.00000001") >= Amount.fromJSONString("EUR:42.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:42.00000002") >= Amount.fromJSONString("EUR:42.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:42.00000002") > Amount.fromJSONString("EUR:42.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:0.00000002") > Amount.fromJSONString("EUR:0.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:0.00000001") > Amount.fromJSONString("EUR:0"))
+ assertTrue(Amount.fromJSONString("EUR:2") > Amount.fromJSONString("EUR:1"))
+
+ assertThrows<IllegalStateException>("could compare amounts with different currencies") {
+ Amount.fromJSONString("EUR:0.5") < Amount.fromJSONString("USD:0.50000001")
+ }
+ }
+
+ private inline fun <reified T : Throwable> assertThrows(
+ msg: String? = null,
+ function: () -> Any
+ ) {
+ try {
+ function.invoke()
+ fail(msg)
+ } catch (e: Exception) {
+ assertTrue(e is T)
+ }
+ }
+
+}
diff --git a/common/src/commonTest/kotlin/net/taler/common/TalerUriTest.kt b/common/src/commonTest/kotlin/net/taler/common/TalerUriTest.kt
new file mode 100644
index 0000000..f996fa9
--- /dev/null
+++ b/common/src/commonTest/kotlin/net/taler/common/TalerUriTest.kt
@@ -0,0 +1,66 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+import net.taler.common.TalerUri.WithdrawUriResult
+import net.taler.common.TalerUri.parseWithdrawUri
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertNull
+
+class TalerUriTest {
+
+ @Test
+ fun testParseWithdrawUri() {
+ // correct parsing
+ var uri = "taler://withdraw/bank.example.com/12345"
+ var expected = WithdrawUriResult("https://bank.example.com/", "12345")
+ assertEquals(expected, parseWithdrawUri(uri))
+
+ // correct parsing with insecure http
+ uri = "taler+http://withdraw/bank.example.org/foo"
+ expected = WithdrawUriResult("http://bank.example.org/", "foo")
+ assertEquals(expected, parseWithdrawUri(uri))
+
+ // correct parsing with long path
+ uri = "taler://withdraw/bank.example.com/foo/bar/23/42/1337/1234567890"
+ expected =
+ WithdrawUriResult("https://bank.example.com/foo/bar/23/42/1337", "1234567890")
+ assertEquals(expected, parseWithdrawUri(uri))
+
+ // rejects incorrect scheme
+ uri = "talerx://withdraw/bank.example.com/12345"
+ assertNull(parseWithdrawUri(uri))
+
+ // rejects incorrect authority
+ uri = "taler://withdrawx/bank.example.com/12345"
+ assertNull(parseWithdrawUri(uri))
+
+ // rejects incorrect authority with insecure http
+ uri = "taler+http://withdrawx/bank.example.com/12345"
+ assertNull(parseWithdrawUri(uri))
+
+ // rejects empty withdrawalId
+ uri = "taler://withdraw/bank.example.com//"
+ assertNull(parseWithdrawUri(uri))
+
+ // rejects empty path and withdrawalId
+ uri = "taler://withdraw/bank.example.com////"
+ assertNull(parseWithdrawUri(uri))
+ }
+
+}
diff --git a/common/src/commonTest/kotlin/net/taler/common/TestUtils.kt b/common/src/commonTest/kotlin/net/taler/common/TestUtils.kt
new file mode 100644
index 0000000..e3a6c17
--- /dev/null
+++ b/common/src/commonTest/kotlin/net/taler/common/TestUtils.kt
@@ -0,0 +1,26 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+import kotlin.random.Random
+
+private val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
+fun getRandomString(minLength: Int = 1, maxLength: Int = Random.nextInt(0, 1337)) =
+ (minLength..maxLength)
+ .map { Random.nextInt(0, charPool.size) }
+ .map(charPool::get)
+ .joinToString("")
diff --git a/common/src/commonTest/kotlin/net/taler/common/TimeTest.kt b/common/src/commonTest/kotlin/net/taler/common/TimeTest.kt
new file mode 100644
index 0000000..3ee0a99
--- /dev/null
+++ b/common/src/commonTest/kotlin/net/taler/common/TimeTest.kt
@@ -0,0 +1,49 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+import kotlinx.serialization.UnstableDefault
+import kotlinx.serialization.json.Json.Default.parse
+import kotlinx.serialization.json.Json.Default.stringify
+import net.taler.common.Timestamp.Companion.NEVER
+import kotlin.random.Random
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+// TODO test other functionality of Timestamp and Duration
+@UnstableDefault
+class TimeTest {
+
+ @Test
+ fun testSerialize() {
+ for (i in 0 until 42) {
+ val t = Random.nextLong()
+ assertEquals("""{"t_ms":$t}""", stringify(Timestamp.serializer(), Timestamp(t)))
+ }
+ assertEquals("""{"t_ms":"never"}""", stringify(Timestamp.serializer(), Timestamp(NEVER)))
+ }
+
+ @Test
+ fun testDeserialize() {
+ for (i in 0 until 42) {
+ val t = Random.nextLong()
+ assertEquals(Timestamp(t), parse(Timestamp.serializer(), """{ "t_ms": $t }"""))
+ }
+ assertEquals(Timestamp(NEVER), parse(Timestamp.serializer(), """{ "t_ms": "never" }"""))
+ }
+
+}
diff --git a/common/src/commonTest/kotlin/net/taler/common/VersionTest.kt b/common/src/commonTest/kotlin/net/taler/common/VersionTest.kt
new file mode 100644
index 0000000..f4f17ea
--- /dev/null
+++ b/common/src/commonTest/kotlin/net/taler/common/VersionTest.kt
@@ -0,0 +1,65 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertNull
+
+class VersionTest {
+
+ @Test
+ fun testParse() {
+ assertNull(Version.parse(""))
+ assertNull(Version.parse("foo"))
+ assertNull(Version.parse("foo:bar:foo"))
+ assertNull(Version.parse("0:0:0:"))
+ assertNull(Version.parse("0:0:"))
+ assertEquals(Version(0, 0, 0), Version.parse("0:0:0"))
+ assertEquals(Version(1, 2, 3), Version.parse("1:2:3"))
+ assertEquals(Version(1337, 42, 23), Version.parse("1337:42:23"))
+ }
+
+ @Test
+ fun testComparision() {
+ assertEquals(
+ Version.VersionMatchResult(true, 0),
+ Version.parse("0:0:0")!!.compare(Version.parse("0:0:0"))
+ )
+ assertEquals(
+ Version.VersionMatchResult(true, -1),
+ Version.parse("0:0:0")!!.compare(Version.parse("1:0:1"))
+ )
+ assertEquals(
+ Version.VersionMatchResult(true, -1),
+ Version.parse("0:0:0")!!.compare(Version.parse("1:5:1"))
+ )
+ assertEquals(
+ Version.VersionMatchResult(false, -1),
+ Version.parse("0:0:0")!!.compare(Version.parse("1:5:0"))
+ )
+ assertEquals(
+ Version.VersionMatchResult(false, 1),
+ Version.parse("1:0:0")!!.compare(Version.parse("0:5:0"))
+ )
+ assertEquals(
+ Version.VersionMatchResult(true, 0),
+ Version.parse("1:0:1")!!.compare(Version.parse("1:5:1"))
+ )
+ }
+
+}
diff --git a/common/src/jsMain/kotlin/net/taler/common/Time.kt b/common/src/jsMain/kotlin/net/taler/common/Time.kt
new file mode 100644
index 0000000..b114022
--- /dev/null
+++ b/common/src/jsMain/kotlin/net/taler/common/Time.kt
@@ -0,0 +1,23 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+import kotlin.js.Date
+
+actual fun nowMillis(): Long {
+ return Date().getMilliseconds().toLong()
+}
diff --git a/common/src/jvmMain/kotlin/net/taler/common/Time.kt b/common/src/jvmMain/kotlin/net/taler/common/Time.kt
new file mode 100644
index 0000000..6cd9040
--- /dev/null
+++ b/common/src/jvmMain/kotlin/net/taler/common/Time.kt
@@ -0,0 +1,21 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+actual fun nowMillis(): Long {
+ return System.currentTimeMillis()
+}
diff --git a/common/src/nativeMain/kotlin/net/taler/common/Time.kt b/common/src/nativeMain/kotlin/net/taler/common/Time.kt
new file mode 100644
index 0000000..8a4091a
--- /dev/null
+++ b/common/src/nativeMain/kotlin/net/taler/common/Time.kt
@@ -0,0 +1,23 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+import kotlin.system.getTimeMillis
+
+actual fun nowMillis(): Long {
+ return getTimeMillis()
+}
diff --git a/gradle.properties b/gradle.properties
index 29e08e8..aaf152a 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1 +1,4 @@
-kotlin.code.style=official \ No newline at end of file
+kotlin.code.style=official
+
+# prevent parallel execution of several compiler instances
+kotlin.native.disableCompilerDaemon=true
diff --git a/settings.gradle b/settings.gradle
index bf5e773..b22748a 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,3 +1,6 @@
-rootProject.name = 'wallet-kotlin'
-
enableFeaturePreview("GRADLE_METADATA")
+
+include ':common'
+project(':common').projectDir = file('./common')
+
+include ':wallet'
diff --git a/wallet/.gitignore b/wallet/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/wallet/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/wallet/build.gradle b/wallet/build.gradle
new file mode 100644
index 0000000..aacd0b3
--- /dev/null
+++ b/wallet/build.gradle
@@ -0,0 +1,193 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+plugins {
+ id 'org.jetbrains.kotlin.multiplatform'
+ id 'org.jetbrains.kotlin.plugin.serialization'
+}
+
+group 'net.taler'
+version '0.0.1'
+
+apply plugin: 'com.android.library'
+apply plugin: 'maven-publish'
+
+kotlin {
+ android {
+ repositories {
+ google()
+ maven { url "https://dl.bintray.com/terl/lazysodium-maven" }
+ }
+ }
+ js {
+ browser {
+ }
+ nodejs {
+ }
+ }
+ // For ARM, should be changed to iosArm32 or iosArm64
+ ios {
+ compilations.main.cinterops {
+ sodium {
+ packageName 'org.libsodium'
+ defFile project.file("src/nativeInterop/cinterop/sodium-static.def")
+ }
+ }
+ binaries {
+ framework {
+ baseName = "TalerWallet"
+ }
+ }
+ }
+ // For Linux, should be changed to e.g. linuxX64
+ // For MacOS, should be changed to e.g. macosX64
+ // For Windows, should be changed to e.g. mingwX64
+ linuxX64("linux") {
+ compilations.main.cinterops {
+ sodium {
+ packageName 'org.libsodium'
+ }
+ }
+ }
+
+ sourceSets {
+ def coroutines_version = "1.3.8"
+ def ktor_version = "1.3.2"
+ all {
+ languageSettings {
+ useExperimentalAnnotation('kotlin.ExperimentalStdlibApi')
+ }
+ dependencies {
+ }
+ }
+ commonMain {
+ dependencies {
+ implementation kotlin('stdlib-common')
+ implementation project(":common")
+
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutines_version"
+ implementation "io.ktor:ktor-client-core:$ktor_version"
+ implementation "io.ktor:ktor-client-logging:$ktor_version"
+ implementation "io.ktor:ktor-client-serialization:$ktor_version"
+ implementation "com.soywiz.korlibs.klock:klock:1.11.12"
+ }
+ }
+ commonTest {
+ dependencies {
+ implementation kotlin('test-common')
+ implementation kotlin('test-annotations-common')
+ implementation "io.ktor:ktor-client-mock:$ktor_version"
+ }
+ }
+ androidMain {
+ dependencies {
+ implementation kotlin('stdlib-jdk8')
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
+ implementation "io.ktor:ktor-client-android:$ktor_version"
+ implementation "io.ktor:ktor-client-logging-jvm:$ktor_version"
+ implementation "io.ktor:ktor-client-serialization-jvm:$ktor_version"
+ // TODO Android
+// implementation("com.goterl.lazycode:lazysodium-android:4.2.0@aar") {
+ implementation("com.goterl.lazycode:lazysodium-java:4.3.0") {
+ exclude group: "org.slf4j"
+ }
+ implementation 'net.java.dev.jna:jna:5.6.0@aar'
+ }
+ }
+ androidTest {
+ dependencies {
+ implementation kotlin('test')
+ implementation kotlin('test-junit')
+ implementation "io.ktor:ktor-client-mock-jvm:$ktor_version"
+ implementation "org.slf4j:slf4j-simple:1.7.30"
+ }
+ }
+ jsMain {
+ dependencies {
+ implementation kotlin('stdlib-js')
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-js:$coroutines_version"
+ implementation "io.ktor:ktor-client-js:$ktor_version"
+ implementation "io.ktor:ktor-client-logging-js:$ktor_version"
+ implementation "io.ktor:ktor-client-serialization-js:$ktor_version"
+ // bug: https://github.com/ktorio/ktor/issues/1822
+ api npm("text-encoding", '0.7.0') // work-around for above bug
+ api npm("bufferutil", '4.0.1') // work-around for above bug
+ api npm("utf-8-validate", '5.0.2') // work-around for above bug
+ api npm("abort-controller", '3.0.0') // work-around for above bug
+ api npm("node-fetch", '2.6.0') // work-around for above bug
+ api npm("fs", '*') // work-around for above bug
+
+ implementation npm('tweetnacl', '1.0.3')
+ implementation npm('ed2curve', '0.3.0')
+ implementation npm('hash.js', '1.1.7')
+ }
+ }
+ jsTest {
+ dependencies {
+ implementation kotlin('test-js')
+ implementation "io.ktor:ktor-client-mock-js:$ktor_version"
+ }
+ }
+ nativeMain {
+ dependsOn commonMain
+ dependencies {
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version"
+ implementation "io.ktor:ktor-client-logging-native:$ktor_version"
+ implementation "io.ktor:ktor-client-serialization-native:$ktor_version"
+ }
+ }
+ nativeTest {
+ dependsOn commonTest
+ dependencies {
+ implementation "io.ktor:ktor-client-mock-native:$ktor_version"
+ }
+ }
+ linuxMain {
+ dependsOn nativeMain
+ dependencies {
+ implementation "io.ktor:ktor-client-curl:$ktor_version"
+ }
+ }
+ iosMain {
+ dependsOn nativeMain
+ dependencies {
+ implementation "io.ktor:ktor-client-ios:$ktor_version"
+ }
+ }
+ configure([targets.linux, targets.iosArm64, targets.iosX64]) {
+ compilations.main.source(sourceSets.nativeMain)
+ compilations.test.source(sourceSets.nativeTest)
+ }
+ }
+}
+
+android {
+ compileSdkVersion 29
+ //noinspection GradleDependency
+ buildToolsVersion "29.0.2"
+
+ defaultConfig {
+ minSdkVersion 21
+ targetSdkVersion 29
+ versionCode 1
+ versionName "0.1"
+ }
+ sourceSets {
+ main {
+ manifest.srcFile 'src/androidMain/AndroidManifest.xml'
+ }
+ }
+}
diff --git a/src/androidMain/AndroidManifest.xml b/wallet/src/androidMain/AndroidManifest.xml
index 77fbf4a..77fbf4a 100644
--- a/src/androidMain/AndroidManifest.xml
+++ b/wallet/src/androidMain/AndroidManifest.xml
diff --git a/src/androidMain/kotlin/net/taler/wallet/kotlin/Db.kt b/wallet/src/androidMain/kotlin/net/taler/wallet/kotlin/Db.kt
index 45cbfc3..45cbfc3 100644
--- a/src/androidMain/kotlin/net/taler/wallet/kotlin/Db.kt
+++ b/wallet/src/androidMain/kotlin/net/taler/wallet/kotlin/Db.kt
diff --git a/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt b/wallet/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
index 502b8a0..502b8a0 100644
--- a/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
+++ b/wallet/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
diff --git a/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/RsaBlinding.kt b/wallet/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/RsaBlinding.kt
index 458a089..458a089 100644
--- a/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/RsaBlinding.kt
+++ b/wallet/src/androidMain/kotlin/net/taler/wallet/kotlin/crypto/RsaBlinding.kt
diff --git a/src/androidTest/kotlin/net/taler/wallet/kotlin/TestUtilsAndroid.kt b/wallet/src/androidTest/kotlin/net/taler/wallet/kotlin/TestUtilsAndroid.kt
index a362874..a362874 100644
--- a/src/androidTest/kotlin/net/taler/wallet/kotlin/TestUtilsAndroid.kt
+++ b/wallet/src/androidTest/kotlin/net/taler/wallet/kotlin/TestUtilsAndroid.kt
diff --git a/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/PlanchetTest.kt b/wallet/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/PlanchetTest.kt
index d7f1dae..d7f1dae 100644
--- a/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/PlanchetTest.kt
+++ b/wallet/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/PlanchetTest.kt
diff --git a/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/RefreshTest.kt b/wallet/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/RefreshTest.kt
index 6cdad75..6cdad75 100644
--- a/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/RefreshTest.kt
+++ b/wallet/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/RefreshTest.kt
diff --git a/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/RsaBlindingTest.kt b/wallet/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/RsaBlindingTest.kt
index 0ced114..0ced114 100644
--- a/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/RsaBlindingTest.kt
+++ b/wallet/src/androidTest/kotlin/net/taler/wallet/kotlin/crypto/RsaBlindingTest.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/Amount.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Amount.kt
index 2d39bb3..2d39bb3 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/Amount.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Amount.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/Base32Crockford.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Base32Crockford.kt
index 9043731..9043731 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/Base32Crockford.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Base32Crockford.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/Db.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Db.kt
index 3a5ecd6..3a5ecd6 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/Db.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Db.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/PaytoUri.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/PaytoUri.kt
index f6b11d2..f6b11d2 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/PaytoUri.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/PaytoUri.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/TalerUri.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/TalerUri.kt
index c489d71..c489d71 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/TalerUri.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/TalerUri.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/Time.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Time.kt
index 4143389..4143389 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/Time.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Time.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/Types.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Types.kt
index 04b17e7..04b17e7 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/Types.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Types.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/Utils.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Utils.kt
index 2549195..2549195 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/Utils.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Utils.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/Version.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Version.kt
index 45e7840..45e7840 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/Version.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/Version.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/WalletApi.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/WalletApi.kt
index 11fd181..11fd181 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/WalletApi.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/WalletApi.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Crypto.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Crypto.kt
index 226aa64..226aa64 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Crypto.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Crypto.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoImpl.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoImpl.kt
index 0780e45..0780e45 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoImpl.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoImpl.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Deposit.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Deposit.kt
index 3156d3f..3156d3f 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Deposit.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Deposit.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Kdf.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Kdf.kt
index 44f55cc..44f55cc 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Kdf.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Kdf.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Planchet.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Planchet.kt
index b29007e..b29007e 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Planchet.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Planchet.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Recoup.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Recoup.kt
index 0f2b6df..0f2b6df 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Recoup.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Recoup.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Refresh.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Refresh.kt
index cd24b07..cd24b07 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Refresh.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Refresh.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Signature.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Signature.kt
index 9b06756..9b06756 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Signature.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/crypto/Signature.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Auditor.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Auditor.kt
index 4df0bdf..4df0bdf 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Auditor.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Auditor.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Denomination.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Denomination.kt
index 88a81fd..88a81fd 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Denomination.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Denomination.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Exchange.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Exchange.kt
index 7a6ac7f..7a6ac7f 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Exchange.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Exchange.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/ExchangeRecord.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/ExchangeRecord.kt
index 9bfd649..9bfd649 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/ExchangeRecord.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/ExchangeRecord.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Keys.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Keys.kt
index 54806f9..54806f9 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Keys.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Keys.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Wire.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Wire.kt
index c8fae88..c8fae88 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Wire.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/exchange/Wire.kt
diff --git a/src/commonMain/kotlin/net/taler/wallet/kotlin/operations/Withdraw.kt b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/operations/Withdraw.kt
index e51e9ec..e51e9ec 100644
--- a/src/commonMain/kotlin/net/taler/wallet/kotlin/operations/Withdraw.kt
+++ b/wallet/src/commonMain/kotlin/net/taler/wallet/kotlin/operations/Withdraw.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/AmountTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/AmountTest.kt
index 08ee618..08ee618 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/AmountTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/AmountTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/Base32CrockfordTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/Base32CrockfordTest.kt
index 565a395..565a395 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/Base32CrockfordTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/Base32CrockfordTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/DbTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/DbTest.kt
index ab4770d..ab4770d 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/DbTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/DbTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/PaytoUriTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/PaytoUriTest.kt
index 4f080e3..4f080e3 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/PaytoUriTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/PaytoUriTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/TalerUriTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/TalerUriTest.kt
index cfcc8bd..cfcc8bd 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/TalerUriTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/TalerUriTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt
index 0ece68e..0ece68e 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/TimestampTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/TimestampTest.kt
index 1a12549..1a12549 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/TimestampTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/TimestampTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/VersionTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/VersionTest.kt
index d445ebc..d445ebc 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/VersionTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/VersionTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/WalletApiTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/WalletApiTest.kt
index 7971be5..7971be5 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/WalletApiTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/WalletApiTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/DepositTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/DepositTest.kt
index 399b754..399b754 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/DepositTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/DepositTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/EllipticCurveTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/EllipticCurveTest.kt
index 4e83b47..4e83b47 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/EllipticCurveTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/EllipticCurveTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/KdfTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/KdfTest.kt
index 974f9aa..974f9aa 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/KdfTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/KdfTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/RecoupTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/RecoupTest.kt
index ea74e3c..ea74e3c 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/RecoupTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/RecoupTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/RefreshPlanchetTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/RefreshPlanchetTest.kt
index 51eb5c6..51eb5c6 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/RefreshPlanchetTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/RefreshPlanchetTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha256Test.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha256Test.kt
index 3209e05..3209e05 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha256Test.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha256Test.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha512Test.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha512Test.kt
index 24be282..24be282 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha512Test.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/Sha512Test.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/SignatureTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/SignatureTest.kt
index 1306c14..1306c14 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/SignatureTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/crypto/SignatureTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/DenominationTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/DenominationTest.kt
index f48c97d..f48c97d 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/DenominationTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/DenominationTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/Denominations.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/Denominations.kt
index 8cfd7fe..8cfd7fe 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/Denominations.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/Denominations.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/KeysTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/KeysTest.kt
index a6b0c98..a6b0c98 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/KeysTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/KeysTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/UpdateTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/UpdateTest.kt
index 271dc09..271dc09 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/UpdateTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/UpdateTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/WireTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/WireTest.kt
index d09b44b..d09b44b 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/WireTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/exchange/WireTest.kt
diff --git a/src/commonTest/kotlin/net/taler/wallet/kotlin/operations/WithdrawTest.kt b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/operations/WithdrawTest.kt
index 541f24f..541f24f 100644
--- a/src/commonTest/kotlin/net/taler/wallet/kotlin/operations/WithdrawTest.kt
+++ b/wallet/src/commonTest/kotlin/net/taler/wallet/kotlin/operations/WithdrawTest.kt
diff --git a/src/jsMain/kotlin/net/taler/wallet/kotlin/Db.kt b/wallet/src/jsMain/kotlin/net/taler/wallet/kotlin/Db.kt
index 45cbfc3..45cbfc3 100644
--- a/src/jsMain/kotlin/net/taler/wallet/kotlin/Db.kt
+++ b/wallet/src/jsMain/kotlin/net/taler/wallet/kotlin/Db.kt
diff --git a/src/jsMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt b/wallet/src/jsMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
index e428f6a..e428f6a 100644
--- a/src/jsMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
+++ b/wallet/src/jsMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
diff --git a/src/jsTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt b/wallet/src/jsTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt
index 49466e0..49466e0 100644
--- a/src/jsTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt
+++ b/wallet/src/jsTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt
diff --git a/src/nativeInterop/cinterop/sodium-static.def b/wallet/src/nativeInterop/cinterop/sodium-static.def
index 7000cbb..7000cbb 100644
--- a/src/nativeInterop/cinterop/sodium-static.def
+++ b/wallet/src/nativeInterop/cinterop/sodium-static.def
diff --git a/src/nativeInterop/cinterop/sodium.def b/wallet/src/nativeInterop/cinterop/sodium.def
index 1c90295..1c90295 100644
--- a/src/nativeInterop/cinterop/sodium.def
+++ b/wallet/src/nativeInterop/cinterop/sodium.def
diff --git a/src/nativeMain/kotlin/net/taler/wallet/kotlin/Db.kt b/wallet/src/nativeMain/kotlin/net/taler/wallet/kotlin/Db.kt
index 45cbfc3..45cbfc3 100644
--- a/src/nativeMain/kotlin/net/taler/wallet/kotlin/Db.kt
+++ b/wallet/src/nativeMain/kotlin/net/taler/wallet/kotlin/Db.kt
diff --git a/src/nativeMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt b/wallet/src/nativeMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
index 7860607..7860607 100644
--- a/src/nativeMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
+++ b/wallet/src/nativeMain/kotlin/net/taler/wallet/kotlin/crypto/CryptoFactory.kt
diff --git a/src/nativeTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt b/wallet/src/nativeTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt
index c44a846..c44a846 100644
--- a/src/nativeTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt
+++ b/wallet/src/nativeTest/kotlin/net/taler/wallet/kotlin/TestUtils.kt