Skip to content

Commit a7da666

Browse files
committed
feat: finished wrapping most pro backend calls
1 parent 687b3b4 commit a7da666

File tree

3 files changed

+127
-50
lines changed

3 files changed

+127
-50
lines changed

include/pro/pro.hpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ std::string_view proBackendEnumToString(SESSION_PRO_BACKEND_PLAN v);
2121
std::string_view proBackendEnumToString(SESSION_PRO_BACKEND_USER_PRO_STATUS v);
2222
std::string_view proBackendEnumToString(SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT v);
2323

24+
template <typename T>
25+
Napi::Value toJsOrNullIfErrors(
26+
const Napi::Env& env, const T& value, const std::vector<std::string>& errors) {
27+
return errors.empty() ? toJs(env, value) : env.Null();
28+
}
29+
2430
template <>
2531
struct toJs_impl<pro_backend::ProRevocationItem> {
2632
auto operator()(const Napi::Env& env, pro_backend::ProRevocationItem i) const {
@@ -46,7 +52,7 @@ struct toJs_impl<pro_backend::ProPaymentItem> {
4652
obj["unredeemedTsMs"] = toJs(env, p.unredeemed_unix_ts);
4753
obj["redeemedTsMs"] = toJs(env, p.redeemed_unix_ts);
4854
obj["expiryTsMs"] = toJs(env, p.expiry_unix_ts);
49-
obj["gracePeriodDurationMs"] = toJs(env, p.grace_period_duration_ms.count());
55+
obj["gracePeriodDurationMs"] = toJs(env, p.grace_period_duration_ms);
5056
obj["platformRefundExpiryTsMs"] = toJs(env, p.platform_refund_expiry_unix_ts);
5157
obj["revokedTsMs"] = toJs(env, p.revoked_unix_ts);
5258

@@ -244,7 +250,7 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
244250
auto parsed = pro_backend::AddProPaymentOrGetProProofResponse::parse(json_str);
245251

246252
auto obj = toJs(env, static_cast<pro_backend::ResponseHeader>(parsed));
247-
obj["proof"] = parsed.errors.empty() ? toJs(env, parsed.proof) : env.Null();
253+
obj["proof"] = toJsOrNullIfErrors(env, parsed.proof, parsed.errors);
248254

249255
return obj;
250256
});
@@ -343,7 +349,7 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
343349
auto master_privkey =
344350
toCppBuffer(master_privkey_js, "proStatusRequestBody.masterPrivkey");
345351

346-
assert_length(master_privkey, 64, "master_privkey");
352+
assert_length(master_privkey, 64, "proStatusRequestBody.master_privkey");
347353

348354
auto json = pro_backend::GetProStatusRequest::build_to_json(
349355
static_cast<uint8_t>(requestVersion.Int32Value()),
@@ -377,20 +383,17 @@ class ProWrapper : public Napi::ObjectWrap<ProWrapper> {
377383

378384
auto obj = toJs(env, static_cast<pro_backend::ResponseHeader>(parsed));
379385

380-
obj["items"] = parsed.errors.empty() ? toJs(env, parsed.items) : env.Null();
381-
obj["userStatus"] = parsed.errors.empty()
382-
? toJs(env, proBackendEnumToString(parsed.user_status))
383-
: env.Null();
384-
obj["errorReport"] = parsed.errors.empty()
385-
? toJs(env, proBackendEnumToString(parsed.error_report))
386-
: env.Null();
387-
obj["autoRenewing"] =
388-
parsed.errors.empty() ? toJs(env, parsed.auto_renewing) : env.Null();
389-
390-
obj["expiryTsMs"] =
391-
parsed.errors.empty() ? toJs(env, parsed.expiry_unix_ts_ms) : env.Null();
386+
obj["items"] = toJsOrNullIfErrors(env, parsed.items, parsed.errors);
387+
obj["userStatus"] = toJsOrNullIfErrors(
388+
env, proBackendEnumToString(parsed.user_status), parsed.errors);
389+
390+
obj["errorReport"] = toJsOrNullIfErrors(
391+
env, proBackendEnumToString(parsed.error_report), parsed.errors);
392+
393+
obj["autoRenewing"] = toJsOrNullIfErrors(env, parsed.auto_renewing, parsed.errors);
394+
obj["expiryTsMs"] = toJsOrNullIfErrors(env, parsed.expiry_unix_ts_ms, parsed.errors);
392395
obj["gracePeriodMs"] =
393-
parsed.errors.empty() ? toJs(env, parsed.grace_period_duration_ms) : env.Null();
396+
toJsOrNullIfErrors(env, parsed.grace_period_duration_ms, parsed.errors);
394397

395398
return obj;
396399
});

src/pro/pro.cpp

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PAYMENT_PROVIDER v)
77
case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_GOOGLE_PLAY_STORE: return "GOOGLE_PLAY_STORE";
88
case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_IOS_APP_STORE: return "IOS_APP_STORE";
99
case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_COUNT:
10-
// TODO: do we want to assert this cant happen? or should it be allowed?
11-
return "Count";
10+
throw std::invalid_argument("SESSION_PRO_BACKEND_PAYMENT_PROVIDER_COUNT");
1211
}
1312
__builtin_unreachable();
1413
}
@@ -21,8 +20,7 @@ std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_PAYMENT_STATUS v) {
2120
case SESSION_PRO_BACKEND_PAYMENT_STATUS_EXPIRED: return "EXPIRED";
2221
case SESSION_PRO_BACKEND_PAYMENT_STATUS_REFUNDED: return "REFUNDED";
2322
case SESSION_PRO_BACKEND_PAYMENT_STATUS_COUNT:
24-
// TODO: do we want to assert this cant happen? or should it be allowed?
25-
return "COUNT";
23+
throw std::invalid_argument("SESSION_PRO_BACKEND_PAYMENT_STATUS_COUNT");
2624
}
2725
__builtin_unreachable();
2826
}
@@ -34,8 +32,7 @@ std::string_view proBackendEnumToString(SESSION_PRO_BACKEND_PLAN v) {
3432
case SESSION_PRO_BACKEND_PLAN_THREE_MONTHS: return "THREE_MONTHS";
3533
case SESSION_PRO_BACKEND_PLAN_TWELVE_MONTHS: return "TWELVE_MONTHS";
3634
case SESSION_PRO_BACKEND_PLAN_COUNT:
37-
// TODO: do we want to assert this cant happen? or should it be allowed?
38-
return "COUNT";
35+
throw std::invalid_argument("SESSION_PRO_BACKEND_PLAN_COUNT");
3936
}
4037
__builtin_unreachable();
4138
}
@@ -46,8 +43,7 @@ std::string_view proBackendEnumToString(SESSION_PRO_BACKEND_USER_PRO_STATUS v) {
4643
case SESSION_PRO_BACKEND_USER_PRO_STATUS_ACTIVE: return "ACTIVE";
4744
case SESSION_PRO_BACKEND_USER_PRO_STATUS_EXPIRED: return "EXPIRED";
4845
case SESSION_PRO_BACKEND_USER_PRO_STATUS_COUNT:
49-
// TODO: do we want to assert this cant happen? or should it be allowed?
50-
return "COUNT";
46+
throw std::invalid_argument("SESSION_PRO_BACKEND_USER_PRO_STATUS_COUNT");
5147
}
5248
__builtin_unreachable();
5349
}
@@ -57,8 +53,7 @@ std::string_view ProBackendEnumToString(SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR
5753
case SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT_SUCCESS: return "SUCCESS";
5854
case SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT_GENERIC_ERROR: return "GENERIC_ERROR";
5955
case SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT_COUNT:
60-
// TODO: do we want to assert this cant happen? or should it be allowed?
61-
return "COUNT";
56+
throw std::invalid_argument("SESSION_PRO_BACKEND_GET_PRO_STATUS_ERROR_REPORT_COUNT");
6257
}
6358
__builtin_unreachable();
6459
}
@@ -70,20 +65,19 @@ std::string_view proBackendEnumPlanToString(SESSION_PRO_BACKEND_PLAN v) {
7065
case SESSION_PRO_BACKEND_PLAN_THREE_MONTHS: return "THREE_MONTHS";
7166
case SESSION_PRO_BACKEND_PLAN_TWELVE_MONTHS: return "TWELVE_MONTHS";
7267
case SESSION_PRO_BACKEND_PLAN_COUNT:
73-
// TODO: do we want to assert this cant happen? or should it be allowed?
74-
return "COUNT";
68+
throw std::invalid_argument("SESSION_PRO_BACKEND_PLAN_COUNT");
7569
}
7670
__builtin_unreachable();
7771
}
7872

7973
std::string_view proBackendEnumPaymentProviderToString(SESSION_PRO_BACKEND_PAYMENT_PROVIDER v) {
8074
switch (v) {
81-
case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_NIL: return "NIL";
82-
case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_GOOGLE_PLAY_STORE: return "GOOGLE_PLAY_STORE";
83-
case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_IOS_APP_STORE: return "IOS_APP_STORE";
75+
// Note: we want those to map ProOriginatingPlatform keys
76+
case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_NIL: return "Nil";
77+
case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_GOOGLE_PLAY_STORE: return "GooglePlayStore";
78+
case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_IOS_APP_STORE: return "iOSAppStore";
8479
case SESSION_PRO_BACKEND_PAYMENT_PROVIDER_COUNT:
85-
// TODO: do we want to assert this cant happen? or should it be allowed?
86-
return "COUNT";
80+
throw std::invalid_argument("SESSION_PRO_BACKEND_PAYMENT_PROVIDER_COUNT");
8781
}
8882
__builtin_unreachable();
8983
}
@@ -96,8 +90,7 @@ std::string_view proBackendEnumPaymentStatusToString(SESSION_PRO_BACKEND_PAYMENT
9690
case SESSION_PRO_BACKEND_PAYMENT_STATUS_EXPIRED: return "EXPIRED";
9791
case SESSION_PRO_BACKEND_PAYMENT_STATUS_REFUNDED: return "REFUNDED";
9892
case SESSION_PRO_BACKEND_PAYMENT_STATUS_COUNT:
99-
// TODO: do we want to assert this cant happen? or should it be allowed?
100-
return "COUNT";
93+
throw std::invalid_argument("SESSION_PRO_BACKEND_PAYMENT_STATUS_COUNT");
10194
}
10295
__builtin_unreachable();
10396
}

types/pro/pro.d.ts

Lines changed: 96 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/// <reference path="../shared.d.ts" />
1+
/// <reference path="../shared.d.ts" />;
22

33
declare module 'libsession_util_nodejs' {
44
type WithProRotatingEd25519PrivKey = { proRotatingEd25519PrivKey: string | null };
@@ -74,6 +74,85 @@ declare module 'libsession_util_nodejs' {
7474
expiryUnixTsMs: number;
7575
};
7676

77+
type WithMasterPrivKey = { masterPrivKey: Uint8Array };
78+
79+
type ProPaymentItem = {
80+
/**
81+
* Describes the current status of the consumption of the payment for Session Pro entitlement
82+
* The status should be used to determine which timestamps should be used.
83+
84+
* For example, a payment can be in a redeemed state whilst also have a refunded timestamp set
85+
* if the payment was refunded and then the refund was reversed. We preserve all timestamps for
86+
* book-keeping purposes.
87+
*/
88+
status: 'NIL' | 'UNREDEEMED' | 'REDEEMED' | 'EXPIRED' | 'REFUNDED';
89+
/**
90+
* Session Pro product/plan item that was purchased
91+
*/
92+
plan: 'NIL' | 'ONE_MONTH' | 'THREE_MONTHS' | 'TWELVE_MONTHS';
93+
/**
94+
* Store front that this particular payment came from
95+
*/
96+
paymentProvider: ProOriginatingPlatform;
97+
/**
98+
* Flag indicating whether or not this payment will automatically bill itself at the end of the
99+
billing cycle.
100+
*/
101+
autoRenewing: boolean;
102+
/**
103+
* Unix timestamp of when the payment was witnessed by the Pro Backend. Always set
104+
*/
105+
unredeemedTsMs: number;
106+
/**
107+
* Unix timestamp of when the payment was redeemed. 0 if not activated
108+
*/
109+
redeemedTsMs: number;
110+
/**
111+
* Unix timestamp of when the payment was expiry. 0 if not activated
112+
*/
113+
expiryTsMs: number;
114+
/**
115+
* Duration of the grace period, e.g. when the payment provider will start to attempt to renew
116+
* the Session Pro subscription. During the period between
117+
* [expiry_unix_ts, expiry_unix_ts + grace_period_duration_ms] the user continues to have
118+
* entitlement to Session Pro. This value is only applicable if `auto_renewing` is `true`.
119+
*/
120+
gracePeriodDurationMs: number;
121+
/**
122+
* Unix deadline timestamp of when the user is able to refund the subscription via the payment
123+
provider.
124+
* Thereafter the user must initiate a refund manually via Session support.
125+
*/
126+
platformRefundExpiryTsMs: number;
127+
/**
128+
* Unix timestamp of when the payment was revoked or refunded. 0 if not applicable.
129+
*/
130+
revokedTsMs: number;
131+
/**
132+
* When payment provider is set to Google Play Store, this is the platform-specific purchase
133+
token.
134+
* This information should be considered as confidential and stored appropriately.
135+
*/
136+
googlePaymentToken: string | null;
137+
/**
138+
* When payment provider is set to iOS App Store, this is the platform-specific original
139+
transaction ID.
140+
* This information should be considered as confidential and stored appropriately.
141+
*/
142+
appleOriginalTxId: string | null;
143+
/**
144+
* When payment provider is set to iOS App Store, this is the platform-specific transaction ID
145+
* This information should be considered as confidential and stored appropriately.
146+
*/
147+
appleTxId: string | null;
148+
/**
149+
* When payment provider is set to iOS App Store, this is the platform-specific web line order
150+
* ID.
151+
* This information should be considered as confidential and stored appropriately.
152+
*/
153+
appleWebLineOrderId: string | null;
154+
};
155+
77156
type ProWrapper = {
78157
proFeaturesForMessage: (args: {
79158
utf16: string;
@@ -83,12 +162,13 @@ declare module 'libsession_util_nodejs' {
83162
*/
84163
proFeatures: ProFeatures;
85164
}) => WithProFeatures & { success: boolean; error: string | null; codepointCount: number };
86-
proProofRequestBody: (args: {
87-
requestVersion: number;
88-
masterPrivkey: Uint8Array;
89-
rotatingPrivkey: Uint8Array;
90-
unixTsMs: number;
91-
}) => string;
165+
proProofRequestBody: (
166+
args: WithMasterPrivKey & {
167+
requestVersion: number;
168+
rotatingPrivkey: Uint8Array;
169+
unixTsMs: number;
170+
}
171+
) => string;
92172

93173
proProofParseResponse: (args: {
94174
json: string;
@@ -97,22 +177,23 @@ declare module 'libsession_util_nodejs' {
97177
/**
98178
* @param version: Request version. The latest accepted version is 0
99179
* @param ticket: 4-byte monotonic integer for the caller's revocation list iteration. Set to 0 if unknown; otherwise, use the latest known `ticket` from a prior `GetProRevocationsResponse` to allow
100-
/// the Session Pro Backend to omit the revocation list if it has not changed.
180+
the Session Pro Backend to omit the revocation list if it has not changed.
101181
* @returns the stringified body to include in the request
102182
*/
103183
proRevocationsRequestBody: (args: { requestVersion: number; ticket: number }) => string;
104184

105185
proRevocationsParseResponse: (args: { json: string }) => WithProBackendResponse & {
106186
ticket: number | null;
107-
items: Array<ProRevocationItem>;
187+
items: Array<ProRevocationItem> | null;
108188
};
109189

110-
proStatusRequestBody: (args: {
111-
requestVersion: number;
112-
masterPrivkey: Uint8Array;
113-
unixTsMs: number;
114-
withPaymentHistory: boolean;
115-
}) => string;
190+
proStatusRequestBody: (
191+
args: WithMasterPrivKey & {
192+
requestVersion: number;
193+
unixTsMs: number;
194+
withPaymentHistory: boolean;
195+
}
196+
) => string;
116197

117198
proStatusParseResponse: (args: { json: string }) => WithProBackendResponse & {
118199
ticket: number | null;

0 commit comments

Comments
 (0)