diff --git a/include/pro/pro.hpp b/include/pro/pro.hpp index 4f7a62f..72722cf 100644 --- a/include/pro/pro.hpp +++ b/include/pro/pro.hpp @@ -8,11 +8,19 @@ #include "../../node_modules/node-addon-api/napi.h" #include "../meta/meta_base_wrapper.hpp" #include "../utilities.hpp" +#include "./types.hpp" #include "meta/meta_base_wrapper.hpp" +#include "session/pro_backend.h" #include "session/pro_backend.hpp" +#include "session/session_protocol.h" #include "session/session_protocol.hpp" namespace session::nodeapi { +std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PAYMENT_PROVIDER v); +std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PAYMENT_STATUS v); +std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PLAN v); +std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_USER_PRO_STATUS v); +std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT v); class ProWrapper : public Napi::ObjectWrap { @@ -36,6 +44,26 @@ class ProWrapper : public Napi::ObjectWrap { "proProofRequestBody", static_cast( napi_writable | napi_configurable)), + StaticMethod<&ProWrapper::proProofResponseBody>( + "proProofResponseBody", + static_cast( + napi_writable | napi_configurable)), + StaticMethod<&ProWrapper::proRevocationsRequestBody>( + "proRevocationsRequestBody", + static_cast( + napi_writable | napi_configurable)), + StaticMethod<&ProWrapper::proRevocationsResponseBody>( + "proRevocationsResponseBody", + static_cast( + napi_writable | napi_configurable)), + StaticMethod<&ProWrapper::proStatusRequestBody>( + "proStatusRequestBody", + static_cast( + napi_writable | napi_configurable)), + StaticMethod<&ProWrapper::proStatusResponseBody>( + "proStatusResponseBody", + static_cast( + napi_writable | napi_configurable)), }); } @@ -99,7 +127,7 @@ class ProWrapper : public Napi::ObjectWrap { return wrapResult(info, [&] { // we expect arguments that match: // first: { - // "requestVersion": string, + // "requestVersion": number, // "masterPrivkey": Uint8Array, // "rotatingPrivkey": Uint8Array, // "unixTsMs": number, @@ -141,6 +169,189 @@ class ProWrapper : public Napi::ObjectWrap { return json; }); }; + + static Napi::Value proProofResponseBody(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + // we expect arguments that match: + // first: { + // "json": string, + // } + + assertInfoLength(info, 1); + assertIsObject(info[0]); + auto env = info.Env(); + + auto first = info[0].As(); + + if (first.IsEmpty()) + throw std::invalid_argument("proProofResponseBody first received empty"); + + assertIsString(first.Get("json"), "proProofResponseBody.jsonStr"); + auto json_str = toCppString(first.Get("json"), "proProofResponseBody.jsonStr"); + auto json = pro_backend::AddProPaymentOrGetProProofResponse::parse(json_str); + + auto obj = Napi::Object::New(env); + + obj["status"] = toJs(env, json.status); + obj["errors"] = toJs(env, json.errors); + obj["proof"] = json.errors.empty() ? toJs(env, json.proof) : env.Null(); + + return obj; + }); + }; + + static Napi::Value proRevocationsRequestBody(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + // we expect arguments that match: + // first: { + // "requestVersion": number, + // "ticket": number, + // } + + assertInfoLength(info, 1); + assertIsObject(info[0]); + auto env = info.Env(); + + auto first = info[0].As(); + + if (first.IsEmpty()) + throw std::invalid_argument("proRevocationsRequestBody first received empty"); + + assertIsNumber(first.Get("requestVersion"), "proRevocationsRequestBody.requestVersion"); + assertIsNumber(first.Get("ticket"), "proRevocationsRequestBody.ticket"); + auto requestVersion = first.Get("requestVersion").As(); + auto ticket = first.Get("ticket").As(); + + auto revocationsRequest = pro_backend::GetProRevocationsRequest{ + .version = static_cast(requestVersion.Int32Value()), + .ticket = ticket.Uint32Value(), + }; + + auto json = revocationsRequest.to_json(); + + return json; + }); + }; + + static Napi::Value proRevocationsResponseBody(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + // we expect arguments that match: + // first: { + // "json": string, + // } + + assertInfoLength(info, 1); + assertIsObject(info[0]); + auto env = info.Env(); + + auto first = info[0].As(); + + if (first.IsEmpty()) + throw std::invalid_argument("proRevocationsResponseBody first received empty"); + + assertIsString(first.Get("json"), "proRevocationsResponseBody.jsonStr"); + auto json_str = toCppString(first.Get("json"), "proRevocationsResponseBody.jsonStr"); + auto json = pro_backend::GetProRevocationsResponse::parse(json_str); + + auto obj = Napi::Object::New(env); + + obj["status"] = toJs(env, json.status); + obj["errors"] = toJs(env, json.errors); + obj["ticket"] = json.errors.empty() ? toJs(env, json.ticket) : env.Null(); + // FIXME: implement + // obj["items"] = json.errors.empty() ? toJs(env, json.items) : env.Null(); + + return obj; + }); + }; + + static Napi::Value proStatusRequestBody(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + // we expect arguments that match: + // first: { + // "requestVersion": number, + // "masterPrivkey": Uint8Array, + // "unixTsMs": number, + // "withPaymentHistory": boolean, + // } + + assertInfoLength(info, 1); + assertIsObject(info[0]); + auto env = info.Env(); + + auto first = info[0].As(); + + if (first.IsEmpty()) + throw std::invalid_argument("proStatusRequestBody first received empty"); + + assertIsNumber(first.Get("requestVersion"), "proStatusRequestBody.requestVersion"); + assertIsNumber(first.Get("unixTsMs"), "proStatusRequestBody.unixTsMs"); + assertIsBoolean( + first.Get("withPaymentHistory"), "proStatusRequestBody.withPaymentHistory"); + auto requestVersion = first.Get("requestVersion").As(); + auto unix_ts_ms = toCppSysMs(first.Get("unixTsMs"), "proStatusRequestBody.unixTsMs"); + auto withPaymentHistory = toCppBoolean( + first.Get("withPaymentHistory"), "proStatusRequestBody.withPaymentHistory"); + assertIsUInt8Array(first.Get("masterPrivkey"), "proStatusRequestBody.masterPrivkey"); + + auto master_privkey_js = first.Get("masterPrivkey"); + auto master_privkey = + toCppBuffer(master_privkey_js, "proStatusRequestBody.masterPrivkey"); + + assert_length(master_privkey, 64, "master_privkey"); + + auto json = pro_backend::GetProStatusRequest::build_to_json( + static_cast(requestVersion.Int32Value()), + master_privkey, + unix_ts_ms, + withPaymentHistory); + + return json; + }); + }; + + static Napi::Value proStatusResponseBody(const Napi::CallbackInfo& info) { + return wrapResult(info, [&] { + // we expect arguments that match: + // first: { + // "json": string, + // } + + assertInfoLength(info, 1); + assertIsObject(info[0]); + auto env = info.Env(); + + auto first = info[0].As(); + + if (first.IsEmpty()) + throw std::invalid_argument("proStatusResponseBody first received empty"); + + assertIsString(first.Get("json"), "proStatusResponseBody.jsonStr"); + auto json_str = toCppString(first.Get("json"), "proStatusResponseBody.jsonStr"); + auto json = pro_backend::GetProStatusResponse::parse(json_str); + + auto obj = Napi::Object::New(env); + + obj["status"] = toJs(env, json.status); + obj["errors"] = toJs(env, json.errors); + // FIXME: implement + // obj["items"] = json.errors.empty() ? toJs(env, json.items) : env.Null(); + obj["userStatus"] = json.errors.empty() + ? toJs(env, ProBackendEnumToString(json.user_status)) + : env.Null(); + obj["errorReport"] = json.errors.empty() + ? toJs(env, ProBackendEnumToString(json.error_report)) + : env.Null(); + obj["autoRenewing"] = json.errors.empty() ? toJs(env, json.auto_renewing) : env.Null(); + + // FIXME: implement + // obj["expiryUnixTsMs"] = json.errors.empty() ? toJs(env, json.expiry_unix_ts_ms) : + // env.Null(); obj["gracePeriodDurationMs"] = json.errors.empty() ? toJs(env, + // json.grace_period_duration_ms) : env.Null(); + + return obj; + }); + }; }; }; // namespace session::nodeapi diff --git a/include/utilities.hpp b/include/utilities.hpp index e98085f..ae4f5e1 100644 --- a/include/utilities.hpp +++ b/include/utilities.hpp @@ -2,6 +2,7 @@ #include +#include #include #include #include diff --git a/src/pro/pro.cpp b/src/pro/pro.cpp index 37b739f..0490e4a 100644 --- a/src/pro/pro.cpp +++ b/src/pro/pro.cpp @@ -1 +1,61 @@ -#include "pro/pro.hpp" \ No newline at end of file +#include "pro/pro.hpp" + +namespace session::nodeapi { +std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PAYMENT_PROVIDER v) { + switch (v) { + case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_NIL: return "NIL"; + case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_GOOGLE_PLAY_STORE: return "GOOGLE_PLAY_STORE"; + case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_IOS_APP_STORE: return "IOS_APP_STORE"; + case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_COUNT: + // TODO: do we want to assert this cant happen? or should it be allowed? + return "Count"; + } +} + +std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PAYMENT_STATUS v) { + switch (v) { + case SESSION_PRO_BACKEND_PAYMENT_STATUS_NIL: return "NIL"; + case SESSION_PRO_BACKEND_PAYMENT_STATUS_UNREDEEMED: return "UNREDEEMED"; + case SESSION_PRO_BACKEND_PAYMENT_STATUS_REDEEMED: return "REDEEMED"; + case SESSION_PRO_BACKEND_PAYMENT_STATUS_EXPIRED: return "EXPIRED"; + case SESSION_PRO_BACKEND_PAYMENT_STATUS_REFUNDED: return "REFUNDED"; + case SESSION_PRO_BACKEND_PAYMENT_STATUS_COUNT: + // TODO: do we want to assert this cant happen? or should it be allowed? + return "COUNT"; + } +} + +std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PLAN v) { + switch (v) { + case SESSION_PRO_BACKEND_PLAN_NIL: return "NIL"; + case SESSION_PRO_BACKEND_PLAN_ONE_MONTH: return "ONE_MONTH"; + case SESSION_PRO_BACKEND_PLAN_THREE_MONTHS: return "THREE_MONTHS"; + case SESSION_PRO_BACKEND_PLAN_TWELVE_MONTHS: return "TWELVE_MONTHS"; + case SESSION_PRO_BACKEND_PLAN_COUNT: + // TODO: do we want to assert this cant happen? or should it be allowed? + return "COUNT"; + } +} + +std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_USER_PRO_STATUS v) { + switch (v) { + case SESSION_PRO_BACKEND_USER_PRO_STATUS_NEVER_BEEN_PRO: return "NEVER_BEEN_PRO"; + case SESSION_PRO_BACKEND_USER_PRO_STATUS_ACTIVE: return "ACTIVE"; + case SESSION_PRO_BACKEND_USER_PRO_STATUS_EXPIRED: return "EXPIRED"; + case SESSION_PRO_BACKEND_USER_PRO_STATUS_COUNT: + // TODO: do we want to assert this cant happen? or should it be allowed? + return "COUNT"; + } +} + +std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT v) { + switch (v) { + case SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT_SUCCESS: return "SUCCESS"; + case SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT_GENERIC_ERROR: return "GENERIC_ERROR"; + case SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT_COUNT: + // TODO: do we want to assert this cant happen? or should it be allowed? + return "COUNT"; + } +} + +} diff --git a/types/pro/pro.d.ts b/types/pro/pro.d.ts index 806c15c..b531c6b 100644 --- a/types/pro/pro.d.ts +++ b/types/pro/pro.d.ts @@ -33,6 +33,11 @@ declare module 'libsession_util_nodejs' { proProof: ProProof; }; + type WithProBackendResponse = { + status: number; + errors: Array; + } + // Must match session-desktop export enum ProOriginatingPlatform { Nil = 'Nil', @@ -75,12 +80,53 @@ declare module 'libsession_util_nodejs' { proFeatures: ProFeatures; }) => WithProFeatures & { success: boolean; error: string | null; codepointCount: number }; proProofRequestBody: (args: { - requestVersion: string, + requestVersion: number, masterPrivkey: Uint8Array, rotatingPrivkey: Uint8Array, unixTsMs: number, } ) => string; + + proProofResponseBody: (args: { + json: string, + } + ) => WithProBackendResponse & { proof: ProProof | null }; + + proRevocationsRequestBody: (args: { + requestVersion: number, + ticket: number, + } + ) => string; + + proRevocationsResponseBody: (args: { + json: string, + } + ) => WithProBackendResponse & { + ticket: number | null; + items: Array + }; + + proStatusRequestBody: (args: { + requestVersion: number, + masterPrivkey: Uint8Array, + unixTsMs: number, + withPaymentHistory: boolean, + } + ) => string; + + proStatusResponseBody: (args: { + json: string, + } + ) => WithProBackendResponse & { + ticket: number | null; + items: Array; + userStatus: number; + errorReport: number; + autoRenewing: boolean; + expiryUnixTsMs: number; + gracePeriodDurationMs: number; + }; + }; export type ProActionsCalls = MakeWrapperActionCalls;