@oxy.so/core 4.8.0 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AccountsApi = exports.AccountAgentKeysApi = exports.AccountMembersApi = exports.kindAcceptsAccountCategories = exports.isSelectableAccountCategoryId = exports.isOperatorSwitchTargetKind = exports.isDelegatedActAsEligibleKind = exports.SELECTABLE_ACCOUNT_CATEGORY_IDS = exports.MAX_ACCOUNT_CATEGORIES = exports.ACCOUNT_KINDS = exports.ACCOUNT_CATEGORY_IDS = void 0;
3
+ exports.AccountsApi = exports.AccountInvitationsApi = exports.AccountAgentKeysApi = exports.AccountMembersApi = exports.kindAcceptsAccountCategories = exports.isSelectableAccountCategoryId = exports.isOperatorSwitchTargetKind = exports.isDelegatedActAsEligibleKind = exports.SELECTABLE_ACCOUNT_CATEGORY_IDS = exports.MAX_ACCOUNT_CATEGORIES = exports.ACCOUNT_KINDS = exports.ACCOUNT_CATEGORY_IDS = void 0;
4
4
  /**
5
5
  * `oxy.accounts` — the unified account graph (`/accounts`).
6
6
  *
@@ -65,7 +65,8 @@ class AccountMembersApi {
65
65
  return res.members ?? [];
66
66
  }
67
67
  /**
68
- * Add a member to an account.
68
+ * @deprecated The API returns 410. Use accounts.invitations.create with an email.
69
+ * Access is granted only after recipient confirmation.
69
70
  * @param accountId - The account's `_id`.
70
71
  * @param data - Target user's username or email and role (never `owner`).
71
72
  * The server resolves `usernameOrEmail` to a personal account; an unknown
@@ -119,10 +120,40 @@ class AccountAgentKeysApi {
119
120
  }
120
121
  }
121
122
  exports.AccountAgentKeysApi = AccountAgentKeysApi;
123
+ /** Consent-based invitations; never cached or queued as offline mutations. */
124
+ class AccountInvitationsApi {
125
+ constructor(ctx) {
126
+ this.ctx = ctx;
127
+ }
128
+ async list(accountId) {
129
+ return (await this.ctx.request('GET', `/accounts/${enc(accountId)}/invitations`, undefined, { cache: false })).invitations;
130
+ }
131
+ async create(accountId, data) {
132
+ return (await this.ctx.request('POST', `/accounts/${enc(accountId)}/invitations`, data, { cache: false })).invitation;
133
+ }
134
+ async resend(accountId, id) {
135
+ return (await this.ctx.request('POST', `/accounts/${enc(accountId)}/invitations/${enc(id)}/resend`, undefined, { cache: false })).invitation;
136
+ }
137
+ async cancel(accountId, id) {
138
+ return this.ctx.request('DELETE', `/accounts/${enc(accountId)}/invitations/${enc(id)}`, undefined, { cache: false });
139
+ }
140
+ async preview(token) {
141
+ return this.ctx.request('POST', '/accounts/invitations/preview', { token }, { cache: false });
142
+ }
143
+ /** selectedUserId must equal the currently authenticated personal account. */
144
+ async accept(token, selectedUserId) {
145
+ const result = await this.ctx.request('POST', '/accounts/invitations/accept', { token, selectedUserId, confirmed: true }, { cache: false });
146
+ invalidateAccountMembership(this.ctx, result.accountId);
147
+ (0, accountCacheSweep_1.evictOxyAccountForestCache)(this.ctx.http);
148
+ return result;
149
+ }
150
+ }
151
+ exports.AccountInvitationsApi = AccountInvitationsApi;
122
152
  class AccountsApi {
123
153
  constructor(ctx) {
124
154
  this.ctx = ctx;
125
155
  this.members = new AccountMembersApi(ctx);
156
+ this.invitations = new AccountInvitationsApi(ctx);
126
157
  this.agentKeys = new AccountAgentKeysApi(ctx);
127
158
  }
128
159
  /**
@@ -22,6 +22,15 @@ class BillingApi {
22
22
  constructor(ctx) {
23
23
  this.ctx = ctx;
24
24
  }
25
+ async renewProductSubscription(request) {
26
+ return contracts_1.personalPlanCheckoutResultSchema.parse(await this.ctx.request('POST', '/billing/product-subscriptions/renew', contracts_1.productSubscriptionRenewalRequestSchema.parse(request), { cache: false }));
27
+ }
28
+ async startProductPlanCheckout(request) {
29
+ return contracts_1.personalPlanCheckoutResultSchema.parse(await this.ctx.request('POST', '/billing/checkout/product-plan', contracts_1.productPlanCheckoutRequestSchema.parse(request), { cache: false }));
30
+ }
31
+ async productPlans(productId) {
32
+ return contracts_1.productPlanCatalogueSchema.parse(await this.ctx.request('GET', `/billing/product-plans/${encodeURIComponent(productId)}`, undefined, { cache: false }));
33
+ }
25
34
  async startPersonalPlanCheckout(request) {
26
35
  return contracts_1.personalPlanCheckoutResultSchema.parse(await this.ctx.request('POST', '/billing/checkout/personal-plan', contracts_1.personalPlanCheckoutRequestSchema.parse(request), { cache: false }));
27
36
  }
@@ -1436,6 +1436,13 @@ const dict = {
1436
1436
  },
1437
1437
  },
1438
1438
  preferences: {
1439
+ displayCurrency: {
1440
+ label: 'Display currency',
1441
+ saveFailed: 'Could not save display currency. Please try again.',
1442
+ unavailable: 'Equivalent in {{currency}} unavailable',
1443
+ approximate: 'Approx. {{amount}}',
1444
+ estimate: 'Display estimate. The final payable amount is quoted in FAIR at checkout.',
1445
+ },
1439
1446
  title: 'Preferences',
1440
1447
  subtitle: 'Theme, motion, and regional settings',
1441
1448
  sections: {
@@ -1436,6 +1436,13 @@ const dict = {
1436
1436
  },
1437
1437
  },
1438
1438
  preferences: {
1439
+ displayCurrency: {
1440
+ label: 'Moneda mostrada',
1441
+ saveFailed: 'No se ha podido guardar la moneda. Inténtalo de nuevo.',
1442
+ unavailable: 'Equivalencia en {{currency}} no disponible',
1443
+ approximate: 'Aprox. {{amount}}',
1444
+ estimate: 'Importe orientativo. El importe final se cotiza en FAIR al pagar.',
1445
+ },
1439
1446
  title: 'Preferencias',
1440
1447
  subtitle: 'Tema, movimiento y configuración regional',
1441
1448
  sections: {
@@ -54,7 +54,8 @@ export class AccountMembersApi {
54
54
  return res.members ?? [];
55
55
  }
56
56
  /**
57
- * Add a member to an account.
57
+ * @deprecated The API returns 410. Use accounts.invitations.create with an email.
58
+ * Access is granted only after recipient confirmation.
58
59
  * @param accountId - The account's `_id`.
59
60
  * @param data - Target user's username or email and role (never `owner`).
60
61
  * The server resolves `usernameOrEmail` to a personal account; an unknown
@@ -106,10 +107,39 @@ export class AccountAgentKeysApi {
106
107
  return agentKeyOperationResultSchema.parse(response);
107
108
  }
108
109
  }
110
+ /** Consent-based invitations; never cached or queued as offline mutations. */
111
+ export class AccountInvitationsApi {
112
+ constructor(ctx) {
113
+ this.ctx = ctx;
114
+ }
115
+ async list(accountId) {
116
+ return (await this.ctx.request('GET', `/accounts/${enc(accountId)}/invitations`, undefined, { cache: false })).invitations;
117
+ }
118
+ async create(accountId, data) {
119
+ return (await this.ctx.request('POST', `/accounts/${enc(accountId)}/invitations`, data, { cache: false })).invitation;
120
+ }
121
+ async resend(accountId, id) {
122
+ return (await this.ctx.request('POST', `/accounts/${enc(accountId)}/invitations/${enc(id)}/resend`, undefined, { cache: false })).invitation;
123
+ }
124
+ async cancel(accountId, id) {
125
+ return this.ctx.request('DELETE', `/accounts/${enc(accountId)}/invitations/${enc(id)}`, undefined, { cache: false });
126
+ }
127
+ async preview(token) {
128
+ return this.ctx.request('POST', '/accounts/invitations/preview', { token }, { cache: false });
129
+ }
130
+ /** selectedUserId must equal the currently authenticated personal account. */
131
+ async accept(token, selectedUserId) {
132
+ const result = await this.ctx.request('POST', '/accounts/invitations/accept', { token, selectedUserId, confirmed: true }, { cache: false });
133
+ invalidateAccountMembership(this.ctx, result.accountId);
134
+ evictOxyAccountForestCache(this.ctx.http);
135
+ return result;
136
+ }
137
+ }
109
138
  export class AccountsApi {
110
139
  constructor(ctx) {
111
140
  this.ctx = ctx;
112
141
  this.members = new AccountMembersApi(ctx);
142
+ this.invitations = new AccountInvitationsApi(ctx);
113
143
  this.agentKeys = new AccountAgentKeysApi(ctx);
114
144
  }
115
145
  /**
@@ -1,4 +1,4 @@
1
- import { personalPlanCheckoutRequestSchema, personalPlanCheckoutResultSchema, } from '@oxy.so/contracts';
1
+ import { personalPlanCheckoutRequestSchema, productPlanCheckoutRequestSchema, productSubscriptionRenewalRequestSchema, productPlanCatalogueSchema, personalPlanCheckoutResultSchema, } from '@oxy.so/contracts';
2
2
  /**
3
3
  * `oxy.billing` — the signed-in user's subscription, wallet and payment history.
4
4
  *
@@ -19,6 +19,15 @@ export class BillingApi {
19
19
  constructor(ctx) {
20
20
  this.ctx = ctx;
21
21
  }
22
+ async renewProductSubscription(request) {
23
+ return personalPlanCheckoutResultSchema.parse(await this.ctx.request('POST', '/billing/product-subscriptions/renew', productSubscriptionRenewalRequestSchema.parse(request), { cache: false }));
24
+ }
25
+ async startProductPlanCheckout(request) {
26
+ return personalPlanCheckoutResultSchema.parse(await this.ctx.request('POST', '/billing/checkout/product-plan', productPlanCheckoutRequestSchema.parse(request), { cache: false }));
27
+ }
28
+ async productPlans(productId) {
29
+ return productPlanCatalogueSchema.parse(await this.ctx.request('GET', `/billing/product-plans/${encodeURIComponent(productId)}`, undefined, { cache: false }));
30
+ }
22
31
  async startPersonalPlanCheckout(request) {
23
32
  return personalPlanCheckoutResultSchema.parse(await this.ctx.request('POST', '/billing/checkout/personal-plan', personalPlanCheckoutRequestSchema.parse(request), { cache: false }));
24
33
  }
@@ -1434,6 +1434,13 @@ const dict = {
1434
1434
  },
1435
1435
  },
1436
1436
  preferences: {
1437
+ displayCurrency: {
1438
+ label: 'Display currency',
1439
+ saveFailed: 'Could not save display currency. Please try again.',
1440
+ unavailable: 'Equivalent in {{currency}} unavailable',
1441
+ approximate: 'Approx. {{amount}}',
1442
+ estimate: 'Display estimate. The final payable amount is quoted in FAIR at checkout.',
1443
+ },
1437
1444
  title: 'Preferences',
1438
1445
  subtitle: 'Theme, motion, and regional settings',
1439
1446
  sections: {
@@ -1434,6 +1434,13 @@ const dict = {
1434
1434
  },
1435
1435
  },
1436
1436
  preferences: {
1437
+ displayCurrency: {
1438
+ label: 'Moneda mostrada',
1439
+ saveFailed: 'No se ha podido guardar la moneda. Inténtalo de nuevo.',
1440
+ unavailable: 'Equivalencia en {{currency}} no disponible',
1441
+ approximate: 'Aprox. {{amount}}',
1442
+ estimate: 'Importe orientativo. El importe final se cotiza en FAIR al pagar.',
1443
+ },
1437
1444
  title: 'Preferencias',
1438
1445
  subtitle: 'Tema, movimiento y configuración regional',
1439
1446
  sections: {
@@ -336,7 +336,8 @@ export declare class AccountMembersApi {
336
336
  */
337
337
  list(accountId: string): Promise<AccountMember[]>;
338
338
  /**
339
- * Add a member to an account.
339
+ * @deprecated The API returns 410. Use accounts.invitations.create with an email.
340
+ * Access is granted only after recipient confirmation.
340
341
  * @param accountId - The account's `_id`.
341
342
  * @param data - Target user's username or email and role (never `owner`).
342
343
  * The server resolves `usernameOrEmail` to a personal account; an unknown
@@ -393,10 +394,46 @@ export declare class AccountAgentKeysApi {
393
394
  revokedMethodIds: string[];
394
395
  }>;
395
396
  }
397
+ export interface AccountInvitation {
398
+ id: string;
399
+ accountId: string;
400
+ email: string;
401
+ role: Exclude<AccountRole, 'owner'>;
402
+ status: 'pending' | 'expired' | 'accepted' | 'cancelled';
403
+ expiresAt: string;
404
+ createdAt: string;
405
+ }
406
+ export interface AccountInvitationPreview {
407
+ invitation: AccountInvitation;
408
+ account: {
409
+ id: string;
410
+ username: string | null;
411
+ displayName: string | null;
412
+ };
413
+ }
414
+ /** Consent-based invitations; never cached or queued as offline mutations. */
415
+ export declare class AccountInvitationsApi {
416
+ private readonly ctx;
417
+ constructor(ctx: OxyContext);
418
+ list(accountId: string): Promise<AccountInvitation[]>;
419
+ create(accountId: string, data: {
420
+ email: string;
421
+ role: Exclude<AccountRole, 'owner'>;
422
+ inherit?: boolean;
423
+ }): Promise<AccountInvitation>;
424
+ resend(accountId: string, id: string): Promise<AccountInvitation>;
425
+ cancel(accountId: string, id: string): Promise<AccountSuccessResult>;
426
+ preview(token: string): Promise<AccountInvitationPreview>;
427
+ /** selectedUserId must equal the currently authenticated personal account. */
428
+ accept(token: string, selectedUserId: string): Promise<AccountSuccessResult & {
429
+ accountId: string;
430
+ }>;
431
+ }
396
432
  export declare class AccountsApi {
397
433
  private readonly ctx;
398
434
  /** Who can act on an account, and with what role. */
399
435
  readonly members: AccountMembersApi;
436
+ readonly invitations: AccountInvitationsApi;
400
437
  readonly agentKeys: AccountAgentKeysApi;
401
438
  constructor(ctx: OxyContext);
402
439
  /**
@@ -1,4 +1,4 @@
1
- import { type PersonalPlanCheckoutRequest, type PersonalPlanCheckoutResult } from '@oxy.so/contracts';
1
+ import { type ProductSubscriptionRenewalRequest, type ProductPlanCheckoutRequest, type ProductPlanCatalogue, type PersonalPlanCheckoutRequest, type PersonalPlanCheckoutResult } from '@oxy.so/contracts';
2
2
  /**
3
3
  * `oxy.billing` — the signed-in user's subscription, wallet and payment history.
4
4
  *
@@ -101,6 +101,9 @@ export interface WalletTransactionsPage {
101
101
  export declare class BillingApi {
102
102
  protected readonly ctx: OxyContext;
103
103
  constructor(ctx: OxyContext);
104
+ renewProductSubscription(request: ProductSubscriptionRenewalRequest): Promise<PersonalPlanCheckoutResult>;
105
+ startProductPlanCheckout(request: ProductPlanCheckoutRequest): Promise<PersonalPlanCheckoutResult>;
106
+ productPlans(productId: string): Promise<ProductPlanCatalogue>;
104
107
  startPersonalPlanCheckout(request: PersonalPlanCheckoutRequest): Promise<PersonalPlanCheckoutResult>;
105
108
  /** Public versioned personal plans. Discovery never proves customer access. */
106
109
  personalPlans(): Promise<PersonalPlanCatalogue>;
@@ -8,7 +8,7 @@ export declare class SafetyApi {
8
8
  accessToken: string | null;
9
9
  }): Promise<{
10
10
  allowed: boolean;
11
- reason: "public" | "owner" | "private" | "blocked" | "unavailable";
11
+ reason: "unavailable" | "owner" | "public" | "private" | "blocked";
12
12
  policyVersion: "1";
13
13
  }>;
14
14
  }
@@ -1425,6 +1425,13 @@ declare const dict: {
1425
1425
  };
1426
1426
  };
1427
1427
  preferences: {
1428
+ displayCurrency: {
1429
+ label: string;
1430
+ saveFailed: string;
1431
+ unavailable: string;
1432
+ approximate: string;
1433
+ estimate: string;
1434
+ };
1428
1435
  title: string;
1429
1436
  subtitle: string;
1430
1437
  sections: {
@@ -1425,6 +1425,13 @@ declare const dict: {
1425
1425
  };
1426
1426
  };
1427
1427
  preferences: {
1428
+ displayCurrency: {
1429
+ label: string;
1430
+ saveFailed: string;
1431
+ unavailable: string;
1432
+ approximate: string;
1433
+ estimate: string;
1434
+ };
1428
1435
  title: string;
1429
1436
  subtitle: string;
1430
1437
  sections: {
@@ -101,3 +101,4 @@ export type { PkcePair, BuildOAuthAuthorizeUrlParams, OxyAuthScreen } from './ut
101
101
  export { packageInfo } from './constants/version';
102
102
  export type { Organization, OrganizationType, CreateOrganization, UpdateOrganization, OrganizationSearch, OrganizationClaim, } from '@oxy.so/contracts';
103
103
  export type { ProfileAccessInput, ProfileAccessDecision } from '@oxy.so/contracts';
104
+ export type { AccountInvitation, AccountInvitationPreview } from './api/accounts';
@@ -242,6 +242,8 @@ export interface NotificationPreferences {
242
242
  * Persisted on the User document.
243
243
  */
244
244
  export interface UserPreferences {
245
+ /** Preferred display units only; never changes a payment's denomination. */
246
+ displayCurrency?: 'USD' | 'EUR' | 'FAIR';
245
247
  /** BCP-47 language tag, e.g. "en-US", "es-ES". Empty string = follow device. */
246
248
  language?: string;
247
249
  /** Theme mode preference. */
@@ -36,8 +36,8 @@ export declare const oxyRequesterAssertionClaimsSchema: z.ZodObject<{
36
36
  /** The one native agent this requester may reach with it. */
37
37
  agentId: z.ZodString;
38
38
  }, "strict", z.ZodTypeAny, {
39
- sub: string;
40
39
  exp: number;
40
+ sub: string;
41
41
  aud: string;
42
42
  iss: string;
43
43
  jti: string;
@@ -46,8 +46,8 @@ export declare const oxyRequesterAssertionClaimsSchema: z.ZodObject<{
46
46
  cid: string;
47
47
  agentId: string;
48
48
  }, {
49
- sub: string;
50
49
  exp: number;
50
+ sub: string;
51
51
  aud: string;
52
52
  iss: string;
53
53
  jti: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxy.so/core",
3
- "version": "4.8.0",
3
+ "version": "4.9.0",
4
4
  "description": "OxyHQ SDK Foundation — API client, authentication, cryptographic identity, and shared utilities",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -178,7 +178,7 @@
178
178
  "dependencies": {
179
179
  "@noble/ciphers": "^1.3.0",
180
180
  "@noble/hashes": "^1.8.0",
181
- "@oxy.so/contracts": "4.14.0",
181
+ "@oxy.so/contracts": "4.15.0",
182
182
  "@oxy.so/protocol": "^1.2.2",
183
183
  "@oxy.so/telemetry": "^1.2.0",
184
184
  "@scure/bip39": "^1.6.0",
@@ -391,7 +391,8 @@ export class AccountMembersApi {
391
391
  }
392
392
 
393
393
  /**
394
- * Add a member to an account.
394
+ * @deprecated The API returns 410. Use accounts.invitations.create with an email.
395
+ * Access is granted only after recipient confirmation.
395
396
  * @param accountId - The account's `_id`.
396
397
  * @param data - Target user's username or email and role (never `owner`).
397
398
  * The server resolves `usernameOrEmail` to a personal account; an unknown
@@ -476,13 +477,93 @@ export class AccountAgentKeysApi {
476
477
  }
477
478
  }
478
479
 
480
+ export interface AccountInvitation {
481
+ id: string;
482
+ accountId: string;
483
+ email: string;
484
+ role: Exclude<AccountRole, 'owner'>;
485
+ status: 'pending' | 'expired' | 'accepted' | 'cancelled';
486
+ expiresAt: string;
487
+ createdAt: string;
488
+ }
489
+ export interface AccountInvitationPreview {
490
+ invitation: AccountInvitation;
491
+ account: { id: string; username: string | null; displayName: string | null };
492
+ }
493
+
494
+ /** Consent-based invitations; never cached or queued as offline mutations. */
495
+ export class AccountInvitationsApi {
496
+ constructor(private readonly ctx: OxyContext) {}
497
+ async list(accountId: string): Promise<AccountInvitation[]> {
498
+ return (
499
+ await this.ctx.request<{ invitations: AccountInvitation[] }>(
500
+ 'GET',
501
+ `/accounts/${enc(accountId)}/invitations`,
502
+ undefined,
503
+ { cache: false },
504
+ )
505
+ ).invitations;
506
+ }
507
+ async create(
508
+ accountId: string,
509
+ data: { email: string; role: Exclude<AccountRole, 'owner'>; inherit?: boolean },
510
+ ): Promise<AccountInvitation> {
511
+ return (
512
+ await this.ctx.request<{ invitation: AccountInvitation }>(
513
+ 'POST',
514
+ `/accounts/${enc(accountId)}/invitations`,
515
+ data,
516
+ { cache: false },
517
+ )
518
+ ).invitation;
519
+ }
520
+ async resend(accountId: string, id: string): Promise<AccountInvitation> {
521
+ return (
522
+ await this.ctx.request<{ invitation: AccountInvitation }>(
523
+ 'POST',
524
+ `/accounts/${enc(accountId)}/invitations/${enc(id)}/resend`,
525
+ undefined,
526
+ { cache: false },
527
+ )
528
+ ).invitation;
529
+ }
530
+ async cancel(accountId: string, id: string): Promise<AccountSuccessResult> {
531
+ return this.ctx.request(
532
+ 'DELETE',
533
+ `/accounts/${enc(accountId)}/invitations/${enc(id)}`,
534
+ undefined,
535
+ { cache: false },
536
+ );
537
+ }
538
+ async preview(token: string): Promise<AccountInvitationPreview> {
539
+ return this.ctx.request('POST', '/accounts/invitations/preview', { token }, { cache: false });
540
+ }
541
+ /** selectedUserId must equal the currently authenticated personal account. */
542
+ async accept(
543
+ token: string,
544
+ selectedUserId: string,
545
+ ): Promise<AccountSuccessResult & { accountId: string }> {
546
+ const result = await this.ctx.request<AccountSuccessResult & { accountId: string }>(
547
+ 'POST',
548
+ '/accounts/invitations/accept',
549
+ { token, selectedUserId, confirmed: true },
550
+ { cache: false },
551
+ );
552
+ invalidateAccountMembership(this.ctx, result.accountId);
553
+ evictOxyAccountForestCache(this.ctx.http);
554
+ return result;
555
+ }
556
+ }
557
+
479
558
  export class AccountsApi {
480
559
  /** Who can act on an account, and with what role. */
481
560
  readonly members: AccountMembersApi;
561
+ readonly invitations: AccountInvitationsApi;
482
562
  readonly agentKeys: AccountAgentKeysApi;
483
563
 
484
564
  constructor(private readonly ctx: OxyContext) {
485
565
  this.members = new AccountMembersApi(ctx);
566
+ this.invitations = new AccountInvitationsApi(ctx);
486
567
  this.agentKeys = new AccountAgentKeysApi(ctx);
487
568
  }
488
569
 
@@ -1,5 +1,11 @@
1
1
  import {
2
2
  personalPlanCheckoutRequestSchema,
3
+ productPlanCheckoutRequestSchema,
4
+ productSubscriptionRenewalRequestSchema,
5
+ type ProductSubscriptionRenewalRequest,
6
+ productPlanCatalogueSchema,
7
+ type ProductPlanCheckoutRequest,
8
+ type ProductPlanCatalogue,
3
9
  personalPlanCheckoutResultSchema,
4
10
  type PersonalPlanCheckoutRequest,
5
11
  type PersonalPlanCheckoutResult,
@@ -127,6 +133,43 @@ export interface WalletTransactionsPage {
127
133
  export class BillingApi {
128
134
  constructor(protected readonly ctx: OxyContext) {}
129
135
 
136
+ async renewProductSubscription(
137
+ request: ProductSubscriptionRenewalRequest,
138
+ ): Promise<PersonalPlanCheckoutResult> {
139
+ return personalPlanCheckoutResultSchema.parse(
140
+ await this.ctx.request<unknown>(
141
+ 'POST',
142
+ '/billing/product-subscriptions/renew',
143
+ productSubscriptionRenewalRequestSchema.parse(request),
144
+ { cache: false },
145
+ ),
146
+ );
147
+ }
148
+
149
+ async startProductPlanCheckout(
150
+ request: ProductPlanCheckoutRequest,
151
+ ): Promise<PersonalPlanCheckoutResult> {
152
+ return personalPlanCheckoutResultSchema.parse(
153
+ await this.ctx.request<unknown>(
154
+ 'POST',
155
+ '/billing/checkout/product-plan',
156
+ productPlanCheckoutRequestSchema.parse(request),
157
+ { cache: false },
158
+ ),
159
+ );
160
+ }
161
+
162
+ async productPlans(productId: string): Promise<ProductPlanCatalogue> {
163
+ return productPlanCatalogueSchema.parse(
164
+ await this.ctx.request<unknown>(
165
+ 'GET',
166
+ `/billing/product-plans/${encodeURIComponent(productId)}`,
167
+ undefined,
168
+ { cache: false },
169
+ ),
170
+ );
171
+ }
172
+
130
173
  async startPersonalPlanCheckout(
131
174
  request: PersonalPlanCheckoutRequest,
132
175
  ): Promise<PersonalPlanCheckoutResult> {
@@ -1465,6 +1465,14 @@ const dict = {
1465
1465
  },
1466
1466
  },
1467
1467
  preferences: {
1468
+ displayCurrency: {
1469
+ label: 'Display currency',
1470
+ saveFailed: 'Could not save display currency. Please try again.',
1471
+ unavailable: 'Equivalent in {{currency}} unavailable',
1472
+ approximate: 'Approx. {{amount}}',
1473
+ estimate: 'Display estimate. The final payable amount is quoted in FAIR at checkout.',
1474
+ },
1475
+
1468
1476
  title: 'Preferences',
1469
1477
  subtitle: 'Theme, motion, and regional settings',
1470
1478
  sections: {
@@ -1470,6 +1470,14 @@ const dict = {
1470
1470
  },
1471
1471
  },
1472
1472
  preferences: {
1473
+ displayCurrency: {
1474
+ label: 'Moneda mostrada',
1475
+ saveFailed: 'No se ha podido guardar la moneda. Inténtalo de nuevo.',
1476
+ unavailable: 'Equivalencia en {{currency}} no disponible',
1477
+ approximate: 'Aprox. {{amount}}',
1478
+ estimate: 'Importe orientativo. El importe final se cotiza en FAIR al pagar.',
1479
+ },
1480
+
1473
1481
  title: 'Preferencias',
1474
1482
  subtitle: 'Tema, movimiento y configuración regional',
1475
1483
  sections: {
package/src/index.ts CHANGED
@@ -616,3 +616,4 @@ export type {
616
616
  } from '@oxy.so/contracts';
617
617
 
618
618
  export type { ProfileAccessInput, ProfileAccessDecision } from '@oxy.so/contracts';
619
+ export type { AccountInvitation, AccountInvitationPreview } from './api/accounts';
@@ -264,6 +264,8 @@ export interface NotificationPreferences {
264
264
  * Persisted on the User document.
265
265
  */
266
266
  export interface UserPreferences {
267
+ /** Preferred display units only; never changes a payment's denomination. */
268
+ displayCurrency?: 'USD' | 'EUR' | 'FAIR';
267
269
  /** BCP-47 language tag, e.g. "en-US", "es-ES". Empty string = follow device. */
268
270
  language?: string;
269
271
  /** Theme mode preference. */