Skip to content

Commit c6926a8

Browse files
SessionHero01SessionHero01
authored andcommitted
Add addProPayment/getProProof integration
1 parent 5449aee commit c6926a8

File tree

10 files changed

+334
-0
lines changed

10 files changed

+334
-0
lines changed

library/src/main/cpp/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ set(SOURCES
9595
attachments.cpp
9696
webp_utils.cpp
9797
gif_utils.cpp
98+
pro_backend.cpp
99+
pro_proof.cpp
98100

99101
${cgif_SOURCE_DIR}/src/cgif.c
100102
${cgif_SOURCE_DIR}/src/cgif_rgb.c

library/src/main/cpp/jni_utils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ namespace jni_utils {
194194
std::span<char> get() const {
195195
return data;
196196
}
197+
198+
std::span<uint8_t> get_raw() const {
199+
return std::span<uint8_t>(reinterpret_cast<uint8_t *>(data.data()), data.size());
200+
}
197201
};
198202

199203
/**
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#include <jni.h>
2+
#include "jni_utils.h"
3+
#include "util.h"
4+
5+
#include <session/pro_backend.hpp>
6+
7+
using namespace jni_utils;
8+
9+
extern "C"
10+
JNIEXPORT jstring JNICALL
11+
Java_network_loki_messenger_libsession_1util_pro_AddProPaymentRequests_buildJson(JNIEnv *env,
12+
jobject thiz,
13+
jint version,
14+
jbyteArray master_private_key,
15+
jbyteArray rotating_private_key,
16+
jint payment_provider,
17+
jstring payment_transaction_id,
18+
jstring payment_order_id) {
19+
return run_catching_cxx_exception_or_throws<jstring>(env, [=]() {
20+
return util::jstringFromOptional(env, session::pro_backend::AddProPaymentRequest::build_to_json(
21+
version,
22+
JavaByteArrayRef(env, master_private_key).get(),
23+
JavaByteArrayRef(env, rotating_private_key).get(),
24+
static_cast<SESSION_PRO_BACKEND_PAYMENT_PROVIDER>(payment_provider),
25+
JavaStringRef(env, payment_transaction_id).get_raw(),
26+
JavaStringRef(env, payment_order_id).get_raw()
27+
)
28+
);
29+
});
30+
}
31+
32+
33+
extern "C"
34+
JNIEXPORT jobject JNICALL
35+
Java_network_loki_messenger_libsession_1util_pro_ProProofResponse_00024Companion_nativeParseRaw(
36+
JNIEnv *env, jobject thiz, jstring json) {
37+
return run_catching_cxx_exception_or_throws<jobject>(env, [=]() {
38+
auto response = session::pro_backend::AddProPaymentOrGetProProofResponse::parse(
39+
JavaStringRef(env, json).view()
40+
);
41+
42+
if (response.errors.empty()) {
43+
JavaLocalRef<jclass> pro_proof_class(env, env->FindClass("network/loki/messenger/libsession_util/pro/ProProof"));
44+
JavaLocalRef<jclass> success_class(env, env->FindClass("network/loki/messenger/libsession_util/pro/ProProofResponse$Success"));
45+
46+
return env->NewObject(
47+
success_class.get(),
48+
env->GetMethodID(success_class.get(), "<init>", "(Lnetwork/loki/messenger/libsession_util/pro/ProProof;)V"),
49+
env->NewObject(
50+
pro_proof_class.get(),
51+
env->GetMethodID(pro_proof_class.get(), "<init>", "(J)V"),
52+
reinterpret_cast<jlong>(new session::ProProof(response.proof))
53+
)
54+
);
55+
}
56+
57+
JavaLocalRef<jclass> error_class(env, env->FindClass("network/loki/messenger/libsession_util/pro/ProProofResponse$Failure"));
58+
59+
return env->NewObject(
60+
error_class.get(),
61+
env->GetMethodID(error_class.get(), "<init>", "(ILjava/util/List;)V"),
62+
static_cast<jint>(response.status),
63+
jstring_list_from_collection(env, response.errors)
64+
);
65+
});
66+
}
67+
68+
extern "C"
69+
JNIEXPORT jstring JNICALL
70+
Java_network_loki_messenger_libsession_1util_pro_GetProProofRequests_buildJson(JNIEnv *env,
71+
jint version,
72+
jobject thiz,
73+
jbyteArray master_private_key,
74+
jbyteArray rotating_private_key,
75+
jlong now_unix_ts) {
76+
return run_catching_cxx_exception_or_throws<jstring>(env, [=] () {
77+
return util::jstringFromOptional(env, session::pro_backend::GetProProofRequest::build_to_json(
78+
version,
79+
JavaByteArrayRef(env, master_private_key).get(),
80+
JavaByteArrayRef(env, rotating_private_key).get(),
81+
std::chrono::sys_time<std::chrono::milliseconds> { std::chrono::milliseconds{static_cast<int64_t>(now_unix_ts)} }
82+
));
83+
});
84+
}

library/src/main/cpp/pro_proof.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include <session/session_protocol.hpp>
2+
3+
#include <jni.h>
4+
#include "util.h"
5+
6+
7+
extern "C"
8+
JNIEXPORT jint JNICALL
9+
Java_network_loki_messenger_libsession_1util_pro_ProProof_00024Companion_nativeGetVersion(
10+
JNIEnv *env, jobject thiz, jlong native_value) {
11+
return static_cast<jint>(
12+
reinterpret_cast<session::ProProof*>(native_value)->version);
13+
}
14+
15+
16+
extern "C"
17+
JNIEXPORT jlong JNICALL
18+
Java_network_loki_messenger_libsession_1util_pro_ProProof_00024Companion_nativeGetExpiry(
19+
JNIEnv *env, jobject thiz, jlong native_value) {
20+
return static_cast<jlong>(
21+
reinterpret_cast<session::ProProof*>(native_value)->expiry_unix_ts.time_since_epoch().count());
22+
}
23+
24+
extern "C"
25+
JNIEXPORT jbyteArray JNICALL
26+
Java_network_loki_messenger_libsession_1util_pro_ProProof_00024Companion_nativeGetRotatingPubKey(
27+
JNIEnv *env, jobject thiz, jlong native_value) {
28+
const auto& rotating_pubkey =
29+
reinterpret_cast<session::ProProof*>(native_value)->rotating_pubkey;
30+
31+
return util::bytes_from_span(env, rotating_pubkey);
32+
}
33+
34+
extern "C"
35+
JNIEXPORT jstring JNICALL
36+
Java_network_loki_messenger_libsession_1util_pro_ProProof_00024Companion_nativeSerialize(
37+
JNIEnv *env, jobject thiz, jlong native_value) {
38+
// TODO: implement nativeSerialize()
39+
}
40+
41+
extern "C"
42+
JNIEXPORT jlong JNICALL
43+
Java_network_loki_messenger_libsession_1util_pro_ProProof_00024Companion_nativeDeserialize(
44+
JNIEnv *env, jobject thiz, jstring data) {
45+
// TODO: implement nativeDeserialize()
46+
}
47+
48+
extern "C"
49+
JNIEXPORT void JNICALL
50+
Java_network_loki_messenger_libsession_1util_pro_ProProof_00024Companion_nativeDestroy(JNIEnv *env,
51+
jobject thiz,
52+
jlong native_value) {
53+
delete reinterpret_cast<session::ProProof*>(native_value);
54+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package network.loki.messenger.libsession_util.pro
2+
3+
import network.loki.messenger.libsession_util.LibSessionUtilCApi
4+
5+
object AddProPaymentRequests : LibSessionUtilCApi() {
6+
private external fun buildJson(
7+
version: Int,
8+
masterPrivateKey: ByteArray,
9+
rotatingPrivateKey: ByteArray,
10+
paymentProvider: Int,
11+
paymentTransactionId: String,
12+
paymentOrderId: String,
13+
): String
14+
15+
fun buildJson(
16+
/**
17+
* Version of the request to build a hash for
18+
*/
19+
version: Int,
20+
/**
21+
* 64-byte libsodium style or 32 byte Ed25519 master private key
22+
*/
23+
masterPrivateKey: ByteArray,
24+
25+
/**
26+
* 64-byte libsodium style or 32 byte Ed25519 rotating private key
27+
*/
28+
rotatingPrivateKey: ByteArray,
29+
30+
/**
31+
* Provider that the payment to register is coming from
32+
*/
33+
paymentProvider: PaymentProvider,
34+
35+
/**
36+
* ID that is associated with the payment from the payment provider
37+
*/
38+
paymentTransactionId: String,
39+
40+
/**
41+
* Order ID that is associated with the payment
42+
*/
43+
paymentOrderId: String,
44+
45+
): String = buildJson(
46+
version = version,
47+
masterPrivateKey = masterPrivateKey,
48+
rotatingPrivateKey = rotatingPrivateKey,
49+
paymentProvider = paymentProvider.nativeValue,
50+
paymentTransactionId = paymentTransactionId,
51+
paymentOrderId = paymentOrderId,
52+
)
53+
}
54+
55+
56+
enum class AddProPaymentError(internal val nativeValue: Int) {
57+
Generic(1),
58+
AlreadyRedeemed(2),
59+
UnknownPayment(3),
60+
}
61+
62+
63+
64+
object AddProPaymentResponses {
65+
fun parse(jsonResponse: String): ProProofResponse<AddProPaymentError> {
66+
return when (val r = ProProofResponse.parseRaw(jsonResponse)) {
67+
is ProProofResponse.Failure<Int> -> {
68+
ProProofResponse.Failure(
69+
status = AddProPaymentError.entries.firstOrNull {
70+
it.nativeValue == r.status
71+
} ?: AddProPaymentError.Generic,
72+
errors = r.errors,
73+
)
74+
}
75+
76+
is ProProofResponse.Success -> {
77+
ProProofResponse.Success(r.proof)
78+
}
79+
}
80+
}
81+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package network.loki.messenger.libsession_util.pro
2+
3+
import network.loki.messenger.libsession_util.LibSessionUtilCApi
4+
5+
enum class GetProProofError {
6+
Generic,
7+
}
8+
9+
object GetProProofRequests : LibSessionUtilCApi() {
10+
external fun buildJson(
11+
version: Int,
12+
/**
13+
* 64-byte libsodium style or 32 byte Ed25519 master private key
14+
*/
15+
masterPrivateKey: ByteArray,
16+
17+
/**
18+
* 64-byte libsodium style or 32 byte Ed25519 rotating private key
19+
*/
20+
rotatingPrivateKey: ByteArray,
21+
nowUnixTs: Long,
22+
): String
23+
}
24+
25+
object GetProProofResponses {
26+
fun parse(json: String): ProProofResponse<GetProProofError> {
27+
return when (val r = ProProofResponse.parseRaw(json)) {
28+
is ProProofResponse.Success -> ProProofResponse.Success(r.proof)
29+
is ProProofResponse.Failure -> {
30+
ProProofResponse.Failure(GetProProofError.Generic, r.errors)
31+
}
32+
}
33+
}
34+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package network.loki.messenger.libsession_util.pro
2+
3+
enum class PaymentProvider(val nativeValue: Int) {
4+
GooglePlayStore(1),
5+
AppleAppStore(2),
6+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package network.loki.messenger.libsession_util.pro
2+
3+
import androidx.annotation.Keep
4+
import network.loki.messenger.libsession_util.LibSessionUtilCApi
5+
import java.time.Instant
6+
7+
class ProProof @Keep private constructor(private val nativeValue: Long) {
8+
9+
val version: Int get() = nativeGetVersion(nativeValue)
10+
val expiry: Instant get() = Instant.ofEpochSecond(nativeGetExpiry(nativeValue))
11+
val rotatingPubKey: ByteArray get() = nativeGetRotatingPubKey(nativeValue)
12+
13+
14+
/**
15+
* Serialize the [ProProof] to a byte array for storage or transmission
16+
*/
17+
fun serialize(): String = nativeSerialize(nativeValue)
18+
19+
20+
protected fun finalize() {
21+
nativeDestroy(nativeValue)
22+
}
23+
24+
25+
companion object : LibSessionUtilCApi() {
26+
private external fun nativeGetVersion(nativeValue: Long): Int
27+
private external fun nativeGetExpiry(nativeValue: Long): Long
28+
private external fun nativeGetRotatingPubKey(nativeValue: Long): ByteArray
29+
private external fun nativeSerialize(nativeValue: Long): String
30+
private external fun nativeDeserialize(data: String): Long
31+
private external fun nativeDestroy(nativeValue: Long)
32+
33+
/**
34+
* Deserialize a [ProProof] from a byte array
35+
*/
36+
fun deserialize(data: String): ProProof {
37+
return ProProof(nativeDeserialize(data))
38+
}
39+
}
40+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package network.loki.messenger.libsession_util.pro
2+
3+
import androidx.annotation.Keep
4+
import network.loki.messenger.libsession_util.LibSessionUtilCApi
5+
6+
7+
/**
8+
* Represents the response that returns a [ProProof]
9+
*/
10+
sealed interface ProProofResponse<out StatusCode> {
11+
data class Success @Keep constructor(val proof: ProProof) : ProProofResponse<Nothing>
12+
data class Failure<T>(val status: T, val errors: List<String>) : ProProofResponse<T>
13+
14+
companion object : LibSessionUtilCApi() {
15+
/**
16+
* Parses a raw JSON string into a [ProProofResponse] with an integer status code.
17+
*/
18+
private external fun nativeParseRaw(json: String): ProProofResponse<Int>
19+
20+
internal fun parseRaw(json: String): ProProofResponse<Int> {
21+
return nativeParseRaw(json)
22+
}
23+
}
24+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package network.loki.messenger.libsession_util.pro
2+
3+
typealias ResponseStatus = Int
4+
5+
const val RESPONSE_STATUS_SUCCESS: ResponseStatus = 200

0 commit comments

Comments
 (0)