@mpgd/platform 0.20.0 → 0.22.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
  import { type tags } from 'typia';
2
2
  import { PlatformOperationError, type CommerceAdapter, type CommerceCapabilities } from './index.js';
3
- import type { ActiveSubscription, CommerceErrorCode, CommerceErrorInfo, CommerceEvent, CommerceLogicalProductId, CommerceProvider, FetchProductsInput, FinishTransactionInput, FinishTransactionResult, GetAvailablePurchasesInput, IsoTimestamp, NonEmptyString, NonNegativeInteger, PurchaseKind, RequestPurchaseInput, RequestPurchaseResult, StoreId, StoreProduct, StorePurchase } from './commerce-contract.js';
3
+ import type { ActiveSubscription, CommerceErrorCode, CommerceErrorInfo, CommerceEvent, CommerceLogicalProductId, CommerceProvider, CommerceServiceCapabilities, FetchProductsInput, FinishTransactionInput, FinishTransactionResult, GetAvailablePurchasesInput, IsoTimestamp, NonEmptyString, NonNegativeInteger, PositiveQuantity, PurchaseKind, RequestPurchaseInput, RequestPurchaseResult, StoreId, StoreProduct, StorePurchase } from './commerce-contract.js';
4
4
  export { createUnsupportedCommerceCapabilities, deriveLegacyCommerceCapabilities, type LegacyCommerceCapabilities, } from './commerce-capabilities.js';
5
5
  export type { CommerceAccountBindingPolicy, CommerceAuthorityCapabilities, CommerceCapabilities, CommerceCatalogCapabilities, CommerceEvidenceAuthority, CommerceFinishOwner, CommerceLifecycleCapabilities, CommercePurchaseCapabilities, } from './index.js';
6
6
  /**
@@ -11,7 +11,7 @@ export type { CommerceAccountBindingPolicy, CommerceAuthorityCapabilities, Comme
11
11
  */
12
12
  export declare const commerceProtocolVersion: '2.0.0-draft.1';
13
13
  export declare const commerceProtocol: 'mpgd.commerce.v2';
14
- export type { ActiveSubscription, ActiveSubscriptionState, CommerceErrorCode, CommerceErrorInfo, CommerceEvent, CommerceLogicalProductId, CommerceProvider, FetchProductsInput, FetchProductsType, FinishTransactionInput, FinishTransactionResult, GetAvailablePurchasesInput, PurchaseKind, PurchaseSource, RequestPurchaseInput, RequestPurchaseResult, StoreId, StoreOffer, StorePrice, StoreProduct, StorePurchase, StorePurchaseAccountBinding, StorePurchaseState, } from './commerce-contract.js';
14
+ export type { ActiveSubscription, ActiveSubscriptionState, CommerceErrorCode, CommerceErrorInfo, CommerceEvent, CommerceLogicalProductId, CommerceProvider, CommerceServiceCapabilities, CommerceServiceStoreCapabilities, FetchProductsInput, FetchProductsType, FinishTransactionInput, FinishTransactionResult, GetAvailablePurchasesInput, PurchaseKind, PurchaseSource, RequestPurchaseInput, RequestPurchaseResult, StoreId, StoreOffer, StorePrice, StoreProduct, StorePurchase, StorePurchaseAccountBinding, StorePurchaseState, } from './commerce-contract.js';
15
15
  export declare const commerceErrorCodes: readonly ["USER_CANCELLED", "OUTCOME_UNKNOWN", "ALREADY_OWNED", "IN_PROGRESS", "ITEM_UNAVAILABLE", "NOT_PREPARED", "NETWORK", "STORE_UNAVAILABLE", "CONFIGURATION_REQUIRED", "ACTION_REQUIRED", "ACCOUNT_BINDING_REQUIRED", "INSUFFICIENT_BALANCE", "INVALID_RESPONSE", "UNKNOWN"];
16
16
  /** Bridge event envelope; `sequence` is per session and starts at 0. */
17
17
  export interface CommerceEventEnvelope {
@@ -46,6 +46,12 @@ export interface CreditSpendInput {
46
46
  readonly currency: NonEmptyString;
47
47
  readonly amount: number & tags.ExclusiveMinimum<0>;
48
48
  readonly idempotencyKey: NonEmptyString;
49
+ /**
50
+ * The offer being bought; the wallet prices the spend against it and issues
51
+ * an entitlement. Without it the spend is a plain debit of `amount` with no
52
+ * entitlement, an owner-side form the conformance vectors use; a wallet
53
+ * service should require it from game clients.
54
+ */
49
55
  readonly logicalId?: CommerceLogicalProductId;
50
56
  }
51
57
  export interface CreditDebit {
@@ -56,6 +62,8 @@ export type CreditSpendResult = {
56
62
  readonly status: 'debited';
57
63
  readonly entitlementId: NonEmptyString;
58
64
  readonly debits: readonly CreditDebit[];
65
+ /** When the wallet settled the spend; a replay repeats the original time. */
66
+ readonly createdAt?: IsoTimestamp;
59
67
  /** A repeated idempotency key returns the original debits. */
60
68
  readonly alreadyProcessed?: boolean;
61
69
  } | {
@@ -69,6 +77,8 @@ export interface CreditEntitlement {
69
77
  readonly idempotencyKey: NonEmptyString;
70
78
  readonly createdAt: IsoTimestamp;
71
79
  readonly debits: readonly CreditDebit[];
80
+ /** Units bought at spend time; the provider reports it rather than deriving one from today's price. */
81
+ readonly quantity?: PositiveQuantity;
72
82
  }
73
83
  export interface CreditBalance {
74
84
  readonly titleId: NonEmptyString;
@@ -99,6 +109,13 @@ export interface CreditLot {
99
109
  /** Derived from the origin, never supplied by the caller. */
100
110
  readonly spendScope: CreditLotSpendScope;
101
111
  }
112
+ /**
113
+ * The client a consuming project implements against its wallet service.
114
+ * `createCreditCommerceProvider` (`@mpgd/platform/commerce-wallet`) turns it
115
+ * into a `CommerceProvider`. A `spend` of a membership offer starts the
116
+ * membership under the spend's idempotency key as its subscription id; the
117
+ * wallet service alone renews, lapses, and expires it.
118
+ */
102
119
  export interface CreditWalletClient {
103
120
  readonly store: StoreId;
104
121
  listOffers(input: {
@@ -108,6 +125,7 @@ export interface CreditWalletClient {
108
125
  listUnredeemed(input: {
109
126
  readonly titleId: string;
110
127
  }): Promise<readonly CreditEntitlement[]>;
128
+ /** Redeems an entitlement for the ledger entry that granted it; the wallet service verifies the pair. */
111
129
  redeem(input: {
112
130
  readonly entitlementId: string;
113
131
  readonly ledgerEntryId: string;
@@ -117,7 +135,15 @@ export interface CreditWalletClient {
117
135
  getBalance(input: {
118
136
  readonly titleId: string;
119
137
  }): Promise<CreditBalance>;
120
- subscribe?(listener: (event: CommerceEvent) => void): () => void;
138
+ /** Memberships the wallet service reports as active for the title; absent when the wallet sells none. */
139
+ getActiveSubscriptions?(input: {
140
+ readonly titleId: string;
141
+ }): Promise<readonly ActiveSubscription[]>;
142
+ /** With `input.titleId`, only events that concern that title (platform memberships concern every title). */
143
+ subscribe?(listener: (event: CommerceEvent) => void, input?: CreditWalletSubscribeInput): () => void;
144
+ }
145
+ export interface CreditWalletSubscribeInput {
146
+ readonly titleId?: string;
121
147
  }
122
148
  export interface CommerceBridgeGetCapabilitiesPayload {
123
149
  readonly protocol: typeof commerceProtocol;
@@ -224,8 +250,9 @@ export interface DerivedPurchaseIdempotencyKeyInput {
224
250
  * the same key: `store:<storeId>:<transactionId>` by default, with each
225
251
  * component percent-encoded (`encodeURIComponent`) so ids containing `:`
226
252
  * cannot collide, and the forms v1 ledgers already use for Google Play
227
- * (`play-token-sha256:<hex>`) and Apps in Toss (`apps-in-toss:purchase:<orderId>`),
228
- * which stay byte-identical.
253
+ * (`play-token-sha256:<hex>`) and Apps in Toss
254
+ * (`apps-in-toss:purchase:<encodeURIComponent(orderId)>`), which stay
255
+ * byte-identical.
229
256
  */
230
257
  export declare function createDerivedPurchaseIdempotencyKey(input: DerivedPurchaseIdempotencyKeyInput): Promise<string>;
231
258
  /** Byte-for-byte the v1 `createGooglePlayTokenTransactionId` form; A4 replaces the two copies with this helper. */
@@ -266,6 +293,8 @@ export declare const isActiveSubscription: (input: unknown) => input is ActiveSu
266
293
  export declare const assertFetchProductsInput: (input: unknown) => FetchProductsInput;
267
294
  export declare const assertCommerceCapabilities: (input: unknown) => CommerceCapabilities;
268
295
  export declare const isCommerceCapabilities: (input: unknown) => input is CommerceCapabilities;
296
+ export declare const assertCommerceServiceCapabilities: (input: unknown) => CommerceServiceCapabilities;
297
+ export declare const isCommerceServiceCapabilities: (input: unknown) => input is CommerceServiceCapabilities;
269
298
  export declare const assertCommerceErrorInfo: (input: unknown) => CommerceErrorInfo;
270
299
  export declare const assertCreditOffer: (input: unknown) => CreditOffer;
271
300
  export declare const assertCreditSpendInput: (input: unknown) => CreditSpendInput;
package/dist/commerce.js CHANGED
@@ -204,8 +204,9 @@ export function assertRequestPurchaseSupported(capabilities, input, kind) {
204
204
  * the same key: `store:<storeId>:<transactionId>` by default, with each
205
205
  * component percent-encoded (`encodeURIComponent`) so ids containing `:`
206
206
  * cannot collide, and the forms v1 ledgers already use for Google Play
207
- * (`play-token-sha256:<hex>`) and Apps in Toss (`apps-in-toss:purchase:<orderId>`),
208
- * which stay byte-identical.
207
+ * (`play-token-sha256:<hex>`) and Apps in Toss
208
+ * (`apps-in-toss:purchase:<encodeURIComponent(orderId)>`), which stay
209
+ * byte-identical.
209
210
  */
210
211
  export async function createDerivedPurchaseIdempotencyKey(input) {
211
212
  const store = readIdentifier(input.store, 128);
@@ -220,7 +221,8 @@ export async function createDerivedPurchaseIdempotencyKey(input) {
220
221
  throw new TypeError('Derived purchase keys require a transaction id.');
221
222
  }
222
223
  if (store === 'apps-in-toss') {
223
- return `apps-in-toss:purchase:${transactionId}`;
224
+ // Byte for byte the v1 `createAppsInTossPurchaseIdempotencyKey` form.
225
+ return `apps-in-toss:purchase:${encodeURIComponent(transactionId)}`;
224
226
  }
225
227
  return `store:${encodeURIComponent(store)}:${encodeURIComponent(transactionId)}`;
226
228
  }
@@ -3307,6 +3309,207 @@ export const isCommerceCapabilities = (() => {
3307
3309
  }));
3308
3310
  return (input, _exceptionable = true) => "object" === typeof input && null !== input && _io0(input, true);
3309
3311
  })();
3312
+ export const assertCommerceServiceCapabilities = (() => {
3313
+ const _ao0 = (input, _path, _exceptionable = true) => ("string" === typeof input.commerceProtocolVersion && (1 <= input.commerceProtocolVersion.length || _assertGuard_1._assertGuard(_exceptionable, {
3314
+ method: "typia.createAssertEquals",
3315
+ path: _path + ".commerceProtocolVersion",
3316
+ expected: "string & CommerceMinLength<1>",
3317
+ value: input.commerceProtocolVersion
3318
+ }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
3319
+ method: "typia.createAssertEquals",
3320
+ path: _path + ".commerceProtocolVersion",
3321
+ expected: "(string & CommerceMinLength<1>)",
3322
+ value: input.commerceProtocolVersion
3323
+ }, _errorFactory)) && ((Array.isArray(input.stores) || _assertGuard_1._assertGuard(_exceptionable, {
3324
+ method: "typia.createAssertEquals",
3325
+ path: _path + ".stores",
3326
+ expected: "ReadonlyArray<CommerceServiceStoreCapabilities>",
3327
+ value: input.stores
3328
+ }, _errorFactory)) && input.stores.every((elem, _index3) => ("object" === typeof elem && null !== elem || _assertGuard_1._assertGuard(_exceptionable, {
3329
+ method: "typia.createAssertEquals",
3330
+ path: _path + ".stores[" + _index3 + "]",
3331
+ expected: "CommerceServiceStoreCapabilities",
3332
+ value: elem
3333
+ }, _errorFactory)) && _ao1(elem, _path + ".stores[" + _index3 + "]", true && _exceptionable) || _assertGuard_1._assertGuard(_exceptionable, {
3334
+ method: "typia.createAssertEquals",
3335
+ path: _path + ".stores[" + _index3 + "]",
3336
+ expected: "CommerceServiceStoreCapabilities",
3337
+ value: elem
3338
+ }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
3339
+ method: "typia.createAssertEquals",
3340
+ path: _path + ".stores",
3341
+ expected: "ReadonlyArray<CommerceServiceStoreCapabilities>",
3342
+ value: input.stores
3343
+ }, _errorFactory)) && (2 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).every(key => {
3344
+ if (["commerceProtocolVersion", "stores"].some(prop => key === prop))
3345
+ return true;
3346
+ const value = input[key];
3347
+ if (undefined === value)
3348
+ return true;
3349
+ return _assertGuard_1._assertGuard(_exceptionable, {
3350
+ method: "typia.createAssertEquals",
3351
+ path: _path + _accessExpressionAsString_1._accessExpressionAsString(key),
3352
+ expected: "undefined",
3353
+ value: value
3354
+ }, _errorFactory);
3355
+ })));
3356
+ const _ao1 = (input, _path, _exceptionable = true) => ("string" === typeof input.store && (1 <= input.store.length || _assertGuard_1._assertGuard(_exceptionable, {
3357
+ method: "typia.createAssertEquals",
3358
+ path: _path + ".store",
3359
+ expected: "string & CommerceMinLength<1>",
3360
+ value: input.store
3361
+ }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
3362
+ method: "typia.createAssertEquals",
3363
+ path: _path + ".store",
3364
+ expected: "(string & CommerceMinLength<1>)",
3365
+ value: input.store
3366
+ }, _errorFactory)) && ((Array.isArray(input.schemas) || _assertGuard_1._assertGuard(_exceptionable, {
3367
+ method: "typia.createAssertEquals",
3368
+ path: _path + ".schemas",
3369
+ expected: "ReadonlyArray<NonEmptyString>",
3370
+ value: input.schemas
3371
+ }, _errorFactory)) && input.schemas.every((elem, _index4) => "string" === typeof elem && (1 <= elem.length || _assertGuard_1._assertGuard(_exceptionable, {
3372
+ method: "typia.createAssertEquals",
3373
+ path: _path + ".schemas[" + _index4 + "]",
3374
+ expected: "string & CommerceMinLength<1>",
3375
+ value: elem
3376
+ }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
3377
+ method: "typia.createAssertEquals",
3378
+ path: _path + ".schemas[" + _index4 + "]",
3379
+ expected: "(string & CommerceMinLength<1>)",
3380
+ value: elem
3381
+ }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
3382
+ method: "typia.createAssertEquals",
3383
+ path: _path + ".schemas",
3384
+ expected: "ReadonlyArray<NonEmptyString>",
3385
+ value: input.schemas
3386
+ }, _errorFactory)) && ("client" === input.finish || "host" === input.finish || "none" === input.finish || "server" === input.finish || _assertGuard_1._assertGuard(_exceptionable, {
3387
+ method: "typia.createAssertEquals",
3388
+ path: _path + ".finish",
3389
+ expected: "(\"client\" | \"host\" | \"none\" | \"server\")",
3390
+ value: input.finish
3391
+ }, _errorFactory)) && (("object" === typeof input.purchase && null !== input.purchase || _assertGuard_1._assertGuard(_exceptionable, {
3392
+ method: "typia.createAssertEquals",
3393
+ path: _path + ".purchase",
3394
+ expected: "{ readonly consumable: boolean; readonly durable: boolean; readonly subscription: boolean; }",
3395
+ value: input.purchase
3396
+ }, _errorFactory)) && _ao2(input.purchase, _path + ".purchase", true && _exceptionable) || _assertGuard_1._assertGuard(_exceptionable, {
3397
+ method: "typia.createAssertEquals",
3398
+ path: _path + ".purchase",
3399
+ expected: "{ readonly consumable: boolean; readonly durable: boolean; readonly subscription: boolean; }",
3400
+ value: input.purchase
3401
+ }, _errorFactory)) && (4 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).every(key => {
3402
+ if (["store", "schemas", "finish", "purchase"].some(prop => key === prop))
3403
+ return true;
3404
+ const value = input[key];
3405
+ if (undefined === value)
3406
+ return true;
3407
+ return _assertGuard_1._assertGuard(_exceptionable, {
3408
+ method: "typia.createAssertEquals",
3409
+ path: _path + _accessExpressionAsString_1._accessExpressionAsString(key),
3410
+ expected: "undefined",
3411
+ value: value
3412
+ }, _errorFactory);
3413
+ })));
3414
+ const _ao2 = (input, _path, _exceptionable = true) => ("boolean" === typeof input.consumable || _assertGuard_1._assertGuard(_exceptionable, {
3415
+ method: "typia.createAssertEquals",
3416
+ path: _path + ".consumable",
3417
+ expected: "boolean",
3418
+ value: input.consumable
3419
+ }, _errorFactory)) && ("boolean" === typeof input.durable || _assertGuard_1._assertGuard(_exceptionable, {
3420
+ method: "typia.createAssertEquals",
3421
+ path: _path + ".durable",
3422
+ expected: "boolean",
3423
+ value: input.durable
3424
+ }, _errorFactory)) && ("boolean" === typeof input.subscription || _assertGuard_1._assertGuard(_exceptionable, {
3425
+ method: "typia.createAssertEquals",
3426
+ path: _path + ".subscription",
3427
+ expected: "boolean",
3428
+ value: input.subscription
3429
+ }, _errorFactory)) && (3 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).every(key => {
3430
+ if (["consumable", "durable", "subscription"].some(prop => key === prop))
3431
+ return true;
3432
+ const value = input[key];
3433
+ if (undefined === value)
3434
+ return true;
3435
+ return _assertGuard_1._assertGuard(_exceptionable, {
3436
+ method: "typia.createAssertEquals",
3437
+ path: _path + _accessExpressionAsString_1._accessExpressionAsString(key),
3438
+ expected: "undefined",
3439
+ value: value
3440
+ }, _errorFactory);
3441
+ })));
3442
+ const _io0 = (input, _exceptionable = true) => "string" === typeof input.commerceProtocolVersion && 1 <= input.commerceProtocolVersion.length && (Array.isArray(input.stores) && input.stores.every((elem, _index1) => "object" === typeof elem && null !== elem && _io1(elem, true && _exceptionable))) && (2 === Object.keys(input).length || Object.keys(input).every(key => {
3443
+ if (["commerceProtocolVersion", "stores"].some(prop => key === prop))
3444
+ return true;
3445
+ const value = input[key];
3446
+ if (undefined === value)
3447
+ return true;
3448
+ return false;
3449
+ }));
3450
+ const _io1 = (input, _exceptionable = true) => "string" === typeof input.store && 1 <= input.store.length && (Array.isArray(input.schemas) && input.schemas.every((elem, _index2) => "string" === typeof elem && 1 <= elem.length)) && ("client" === input.finish || "host" === input.finish || "none" === input.finish || "server" === input.finish) && ("object" === typeof input.purchase && null !== input.purchase && _io2(input.purchase, true && _exceptionable)) && (4 === Object.keys(input).length || Object.keys(input).every(key => {
3451
+ if (["store", "schemas", "finish", "purchase"].some(prop => key === prop))
3452
+ return true;
3453
+ const value = input[key];
3454
+ if (undefined === value)
3455
+ return true;
3456
+ return false;
3457
+ }));
3458
+ const _io2 = (input, _exceptionable = true) => "boolean" === typeof input.consumable && "boolean" === typeof input.durable && "boolean" === typeof input.subscription && (3 === Object.keys(input).length || Object.keys(input).every(key => {
3459
+ if (["consumable", "durable", "subscription"].some(prop => key === prop))
3460
+ return true;
3461
+ const value = input[key];
3462
+ if (undefined === value)
3463
+ return true;
3464
+ return false;
3465
+ }));
3466
+ const __is = (input, _exceptionable = true) => "object" === typeof input && null !== input && _io0(input, true);
3467
+ let _errorFactory;
3468
+ return (input, errorFactory) => {
3469
+ if (false === __is(input)) {
3470
+ _errorFactory = errorFactory;
3471
+ ((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _assertGuard_1._assertGuard(true, {
3472
+ method: "typia.createAssertEquals",
3473
+ path: _path + "",
3474
+ expected: "CommerceServiceCapabilities",
3475
+ value: input
3476
+ }, _errorFactory)) && _ao0(input, _path + "", true) || _assertGuard_1._assertGuard(true, {
3477
+ method: "typia.createAssertEquals",
3478
+ path: _path + "",
3479
+ expected: "CommerceServiceCapabilities",
3480
+ value: input
3481
+ }, _errorFactory))(input, "$input", true);
3482
+ }
3483
+ return input;
3484
+ };
3485
+ })();
3486
+ export const isCommerceServiceCapabilities = (() => {
3487
+ const _io0 = (input, _exceptionable = true) => "string" === typeof input.commerceProtocolVersion && 1 <= input.commerceProtocolVersion.length && (Array.isArray(input.stores) && input.stores.every((elem, _index1) => "object" === typeof elem && null !== elem && _io1(elem, true && _exceptionable))) && (2 === Object.keys(input).length || Object.keys(input).every(key => {
3488
+ if (["commerceProtocolVersion", "stores"].some(prop => key === prop))
3489
+ return true;
3490
+ const value = input[key];
3491
+ if (undefined === value)
3492
+ return true;
3493
+ return false;
3494
+ }));
3495
+ const _io1 = (input, _exceptionable = true) => "string" === typeof input.store && 1 <= input.store.length && (Array.isArray(input.schemas) && input.schemas.every((elem, _index2) => "string" === typeof elem && 1 <= elem.length)) && ("client" === input.finish || "host" === input.finish || "none" === input.finish || "server" === input.finish) && ("object" === typeof input.purchase && null !== input.purchase && _io2(input.purchase, true && _exceptionable)) && (4 === Object.keys(input).length || Object.keys(input).every(key => {
3496
+ if (["store", "schemas", "finish", "purchase"].some(prop => key === prop))
3497
+ return true;
3498
+ const value = input[key];
3499
+ if (undefined === value)
3500
+ return true;
3501
+ return false;
3502
+ }));
3503
+ const _io2 = (input, _exceptionable = true) => "boolean" === typeof input.consumable && "boolean" === typeof input.durable && "boolean" === typeof input.subscription && (3 === Object.keys(input).length || Object.keys(input).every(key => {
3504
+ if (["consumable", "durable", "subscription"].some(prop => key === prop))
3505
+ return true;
3506
+ const value = input[key];
3507
+ if (undefined === value)
3508
+ return true;
3509
+ return false;
3510
+ }));
3511
+ return (input, _exceptionable = true) => "object" === typeof input && null !== input && _io0(input, true);
3512
+ })();
3310
3513
  export const assertCommerceErrorInfo = (() => {
3311
3514
  const _iv0 = new Set(["ACCOUNT_BINDING_REQUIRED", "ACTION_REQUIRED", "ALREADY_OWNED", "CONFIGURATION_REQUIRED", "INSUFFICIENT_BALANCE", "INVALID_RESPONSE", "IN_PROGRESS", "ITEM_UNAVAILABLE", "NETWORK", "NOT_PREPARED", "OUTCOME_UNKNOWN", "STORE_UNAVAILABLE", "UNKNOWN", "USER_CANCELLED"]);
3312
3515
  const _av0 = new Set(["ACCOUNT_BINDING_REQUIRED", "ACTION_REQUIRED", "ALREADY_OWNED", "CONFIGURATION_REQUIRED", "INSUFFICIENT_BALANCE", "INVALID_RESPONSE", "IN_PROGRESS", "ITEM_UNAVAILABLE", "NETWORK", "NOT_PREPARED", "OUTCOME_UNKNOWN", "STORE_UNAVAILABLE", "UNKNOWN", "USER_CANCELLED"]);
@@ -3650,7 +3853,7 @@ export const assertCreditSpendInput = (() => {
3650
3853
  })();
3651
3854
  export const assertCreditSpendResult = (() => {
3652
3855
  const _iv0 = new Set(["ACCOUNT_BINDING_REQUIRED", "ACTION_REQUIRED", "ALREADY_OWNED", "CONFIGURATION_REQUIRED", "INSUFFICIENT_BALANCE", "INVALID_RESPONSE", "IN_PROGRESS", "ITEM_UNAVAILABLE", "NETWORK", "NOT_PREPARED", "OUTCOME_UNKNOWN", "STORE_UNAVAILABLE", "UNKNOWN", "USER_CANCELLED"]);
3653
- const _ae0 = "({ readonly status: \"debited\"; readonly entitlementId: NonEmptyString; readonly debits: readonly CreditDebit[]; readonly alreadyProcessed?: boolean; } | { readonly status: \"rejected\"; readonly error: CommerceErrorInfo; })";
3856
+ const _ae0 = "({ readonly status: \"debited\"; readonly entitlementId: NonEmptyString; readonly debits: readonly CreditDebit[]; readonly createdAt?: IsoTimestamp; readonly alreadyProcessed?: boolean; } | { readonly status: \"rejected\"; readonly error: CommerceErrorInfo; })";
3654
3857
  const _av0 = new Set(["ACCOUNT_BINDING_REQUIRED", "ACTION_REQUIRED", "ALREADY_OWNED", "CONFIGURATION_REQUIRED", "INSUFFICIENT_BALANCE", "INVALID_RESPONSE", "IN_PROGRESS", "ITEM_UNAVAILABLE", "NETWORK", "NOT_PREPARED", "OUTCOME_UNKNOWN", "STORE_UNAVAILABLE", "UNKNOWN", "USER_CANCELLED"]);
3655
3858
  const _ae1 = "(\"ACCOUNT_BINDING_REQUIRED\" | \"ACTION_REQUIRED\" | \"ALREADY_OWNED\" | \"CONFIGURATION_REQUIRED\" | \"INSUFFICIENT_BALANCE\" | \"INVALID_RESPONSE\" | \"IN_PROGRESS\" | \"ITEM_UNAVAILABLE\" | \"NETWORK\" | \"NOT_PREPARED\" | \"OUTCOME_UNKNOWN\" | \"STORE_UNAVAILABLE\" | \"UNKNOWN\" | \"USER_CANCELLED\")";
3656
3859
  const _ao0 = (input, _path, _exceptionable = true) => ("debited" === input.status || _assertGuard_1._assertGuard(_exceptionable, {
@@ -3688,13 +3891,23 @@ export const assertCreditSpendResult = (() => {
3688
3891
  path: _path + ".debits",
3689
3892
  expected: "ReadonlyArray<CreditDebit>",
3690
3893
  value: input.debits
3894
+ }, _errorFactory)) && (undefined === input.createdAt || "string" === typeof input.createdAt && (_isFormatDateTime_1._isFormatDateTime(input.createdAt) || _assertGuard_1._assertGuard(_exceptionable, {
3895
+ method: "typia.createAssertEquals",
3896
+ path: _path + ".createdAt",
3897
+ expected: "string & CommerceDateTimeFormat",
3898
+ value: input.createdAt
3899
+ }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
3900
+ method: "typia.createAssertEquals",
3901
+ path: _path + ".createdAt",
3902
+ expected: "((string & CommerceDateTimeFormat) | undefined)",
3903
+ value: input.createdAt
3691
3904
  }, _errorFactory)) && (undefined === input.alreadyProcessed || "boolean" === typeof input.alreadyProcessed || _assertGuard_1._assertGuard(_exceptionable, {
3692
3905
  method: "typia.createAssertEquals",
3693
3906
  path: _path + ".alreadyProcessed",
3694
3907
  expected: "(boolean | undefined)",
3695
3908
  value: input.alreadyProcessed
3696
3909
  }, _errorFactory)) && (3 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).every(key => {
3697
- if (["status", "entitlementId", "debits", "alreadyProcessed"].some(prop => key === prop))
3910
+ if (["status", "entitlementId", "debits", "createdAt", "alreadyProcessed"].some(prop => key === prop))
3698
3911
  return true;
3699
3912
  const value = input[key];
3700
3913
  if (undefined === value)
@@ -3813,8 +4026,8 @@ export const assertCreditSpendResult = (() => {
3813
4026
  value: input
3814
4027
  }, _errorFactory);
3815
4028
  })();
3816
- const _io0 = (input, _exceptionable = true) => "debited" === input.status && ("string" === typeof input.entitlementId && 1 <= input.entitlementId.length) && (Array.isArray(input.debits) && input.debits.every((elem, _index1) => "object" === typeof elem && null !== elem && _io1(elem, true && _exceptionable))) && (undefined === input.alreadyProcessed || "boolean" === typeof input.alreadyProcessed) && (3 === Object.keys(input).length || Object.keys(input).every(key => {
3817
- if (["status", "entitlementId", "debits", "alreadyProcessed"].some(prop => key === prop))
4029
+ const _io0 = (input, _exceptionable = true) => "debited" === input.status && ("string" === typeof input.entitlementId && 1 <= input.entitlementId.length) && (Array.isArray(input.debits) && input.debits.every((elem, _index1) => "object" === typeof elem && null !== elem && _io1(elem, true && _exceptionable))) && (undefined === input.createdAt || "string" === typeof input.createdAt && _isFormatDateTime_1._isFormatDateTime(input.createdAt)) && (undefined === input.alreadyProcessed || "boolean" === typeof input.alreadyProcessed) && (3 === Object.keys(input).length || Object.keys(input).every(key => {
4030
+ if (["status", "entitlementId", "debits", "createdAt", "alreadyProcessed"].some(prop => key === prop))
3818
4031
  return true;
3819
4032
  const value = input[key];
3820
4033
  if (undefined === value)
@@ -3944,8 +4157,23 @@ export const assertCreditEntitlement = (() => {
3944
4157
  path: _path + ".debits",
3945
4158
  expected: "ReadonlyArray<CreditDebit>",
3946
4159
  value: input.debits
4160
+ }, _errorFactory)) && (undefined === input.quantity || "number" === typeof input.quantity && (_isTypeUint32_1._isTypeUint32(input.quantity) || _assertGuard_1._assertGuard(_exceptionable, {
4161
+ method: "typia.createAssertEquals",
4162
+ path: _path + ".quantity",
4163
+ expected: "number & CommerceUint32",
4164
+ value: input.quantity
4165
+ }, _errorFactory)) && (1 <= input.quantity || _assertGuard_1._assertGuard(_exceptionable, {
4166
+ method: "typia.createAssertEquals",
4167
+ path: _path + ".quantity",
4168
+ expected: "number & CommerceMinimum<1>",
4169
+ value: input.quantity
4170
+ }, _errorFactory)) || _assertGuard_1._assertGuard(_exceptionable, {
4171
+ method: "typia.createAssertEquals",
4172
+ path: _path + ".quantity",
4173
+ expected: "((number & CommerceUint32 & CommerceMinimum<1>) | undefined)",
4174
+ value: input.quantity
3947
4175
  }, _errorFactory)) && (6 === Object.keys(input).length || (false === _exceptionable || Object.keys(input).every(key => {
3948
- if (["entitlementId", "titleId", "logicalId", "idempotencyKey", "createdAt", "debits"].some(prop => key === prop))
4176
+ if (["entitlementId", "titleId", "logicalId", "idempotencyKey", "createdAt", "debits", "quantity"].some(prop => key === prop))
3949
4177
  return true;
3950
4178
  const value = input[key];
3951
4179
  if (undefined === value)
@@ -3990,8 +4218,8 @@ export const assertCreditEntitlement = (() => {
3990
4218
  value: value
3991
4219
  }, _errorFactory);
3992
4220
  })));
3993
- const _io0 = (input, _exceptionable = true) => "string" === typeof input.entitlementId && 1 <= input.entitlementId.length && ("string" === typeof input.titleId && 1 <= input.titleId.length) && ("string" === typeof input.logicalId && 1 <= input.logicalId.length) && ("string" === typeof input.idempotencyKey && 1 <= input.idempotencyKey.length) && ("string" === typeof input.createdAt && _isFormatDateTime_1._isFormatDateTime(input.createdAt)) && (Array.isArray(input.debits) && input.debits.every((elem, _index1) => "object" === typeof elem && null !== elem && _io1(elem, true && _exceptionable))) && (6 === Object.keys(input).length || Object.keys(input).every(key => {
3994
- if (["entitlementId", "titleId", "logicalId", "idempotencyKey", "createdAt", "debits"].some(prop => key === prop))
4221
+ const _io0 = (input, _exceptionable = true) => "string" === typeof input.entitlementId && 1 <= input.entitlementId.length && ("string" === typeof input.titleId && 1 <= input.titleId.length) && ("string" === typeof input.logicalId && 1 <= input.logicalId.length) && ("string" === typeof input.idempotencyKey && 1 <= input.idempotencyKey.length) && ("string" === typeof input.createdAt && _isFormatDateTime_1._isFormatDateTime(input.createdAt)) && (Array.isArray(input.debits) && input.debits.every((elem, _index1) => "object" === typeof elem && null !== elem && _io1(elem, true && _exceptionable))) && (undefined === input.quantity || "number" === typeof input.quantity && (_isTypeUint32_1._isTypeUint32(input.quantity) && 1 <= input.quantity)) && (6 === Object.keys(input).length || Object.keys(input).every(key => {
4222
+ if (["entitlementId", "titleId", "logicalId", "idempotencyKey", "createdAt", "debits", "quantity"].some(prop => key === prop))
3995
4223
  return true;
3996
4224
  const value = input[key];
3997
4225
  if (undefined === value)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpgd/platform",
3
- "version": "0.20.0",
3
+ "version": "0.22.0",
4
4
  "description": "Shared platform gateway, monetization, ads, leaderboard, identity, lifecycle, and storage contracts for mpgd games.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -56,6 +56,10 @@
56
56
  "./commerce-conformance": {
57
57
  "types": "./dist/commerce-conformance.d.ts",
58
58
  "default": "./dist/commerce-conformance.js"
59
+ },
60
+ "./commerce-wallet": {
61
+ "types": "./dist/commerce-wallet.d.ts",
62
+ "default": "./dist/commerce-wallet.js"
59
63
  }
60
64
  },
61
65
  "files": [
@@ -80,6 +84,6 @@
80
84
  "lint": "ttsc --noEmit",
81
85
  "format": "ttsc format",
82
86
  "fix": "ttsc fix",
83
- "test": "vitest run && node test/capability-conformance-dist-import.mjs && node test/storage-conformance-dist-import.mjs && node test/ads-dist-import.mjs && node test/commerce-dist-import.mjs && node test/commerce-conformance-dist-import.mjs && cd ../.. && node tools/run-ttsx.mjs packages/platform/test/commerce-derived-key-parity.ts"
87
+ "test": "vitest run && node test/capability-conformance-dist-import.mjs && node test/storage-conformance-dist-import.mjs && node test/ads-dist-import.mjs && node test/commerce-dist-import.mjs && node test/commerce-conformance-dist-import.mjs && node test/wallet-commerce-dist-import.mjs && cd ../.. && node tools/run-ttsx.mjs packages/platform/test/commerce-derived-key-parity.ts"
84
88
  }
85
89
  }