@mpgd/game-services 0.28.1 → 0.30.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.
- package/README.md +18 -3
- package/dist/account-deletion.d.ts +306 -0
- package/dist/account-deletion.js +491 -0
- package/dist/app-store-recovery.d.ts +6 -0
- package/dist/app-store-recovery.js +26 -16
- package/dist/app-store-server-notifications.d.ts +158 -0
- package/dist/app-store-server-notifications.js +270 -0
- package/dist/app-store-server.d.ts +8 -0
- package/dist/app-store-server.js +135 -37
- package/dist/app-store-verifier.d.ts +34 -0
- package/dist/app-store-verifier.js +161 -31
- package/dist/commerce-ledger.d.ts +55 -0
- package/dist/commerce-ledger.js +198 -0
- package/dist/commerce-reconciler.js +47 -7
- package/dist/evidence-verification.d.ts +19 -0
- package/dist/google-play-publisher-client.d.ts +2 -1
- package/dist/google-play-publisher-client.js +80 -0
- package/dist/google-play-purchase.d.ts +7 -0
- package/dist/google-play-purchase.js +32 -7
- package/dist/google-play-store-server.d.ts +160 -0
- package/dist/google-play-store-server.js +297 -0
- package/dist/guest-session.d.ts +112 -2
- package/dist/guest-session.js +196 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/notifications/delivery-provider.d.ts +7 -0
- package/dist/notifications/fcm.d.ts +30 -3
- package/dist/notifications/fcm.js +72 -13
- package/dist/notifications/service.js +33 -5
- package/dist/notifications/store-conformance.js +7 -1
- package/dist/notifications/store.d.ts +9 -0
- package/dist/notifications/store.js +41 -0
- package/dist/operation-results.d.ts +7 -0
- package/dist/purchase-sharing.d.ts +41 -0
- package/dist/purchase-sharing.js +37 -0
- package/dist/runtime.d.ts +6 -0
- package/dist/runtime.js +13 -0
- package/dist/server.d.ts +60 -1
- package/dist/server.js +536 -42
- package/dist/types.d.ts +30 -0
- package/dist/types.js +22 -0
- package/dist/verified-leaderboard.d.ts +13 -0
- package/dist/verified-leaderboard.js +31 -0
- package/package.json +17 -5
package/README.md
CHANGED
|
@@ -236,9 +236,11 @@ with native Node imports, without a bundler or TypeScript runtime loader.
|
|
|
236
236
|
## Guest session and account binding foundation
|
|
237
237
|
|
|
238
238
|
`createGuestSessionCoordinator` from `@mpgd/game-services/guest-session`
|
|
239
|
-
accepts a
|
|
240
|
-
|
|
241
|
-
|
|
239
|
+
accepts a `GuestSessionBackend` and a dedicated `SecureCredentialStore`.
|
|
240
|
+
The client never issues tokens or infers server authentication from
|
|
241
|
+
`installationId` or a local `playerId`; the reference guest identity Worker
|
|
242
|
+
in the kit repository (`apps/game-identity-worker`) is one backend that does,
|
|
243
|
+
over `createGuestSessionHttpBackend`. The backend must
|
|
242
244
|
authenticate opaque refresh tokens, verify external account proofs, atomically
|
|
243
245
|
deduplicate account binding by idempotency key, return `conflict` for an account
|
|
244
246
|
owned by another server user, and revoke sessions durably. It must define
|
|
@@ -277,6 +279,19 @@ family (not a refresh), and `getHeaders()` refreshes an expired access token
|
|
|
277
279
|
before answering, and one that expires within a minute in the background
|
|
278
280
|
(once per token, at most every ten seconds).
|
|
279
281
|
|
|
282
|
+
`createGuestSessionHttpBackend({ baseUrl })` is a `GuestSessionBackend` over
|
|
283
|
+
the HTTP routes in `guestIdentityHttpRoutes`, which the reference identity
|
|
284
|
+
Worker (`apps/game-identity-worker`) serves. It takes an `https:` base URL (or
|
|
285
|
+
`http:` on a local development host), never follows a redirect, and times a
|
|
286
|
+
request out after 15 seconds; a `200` that is not a JSON object is a failure,
|
|
287
|
+
so a logout is never assumed revoked. A refresh token the service refuses for
|
|
288
|
+
good on a refresh or a binding (revoked, replayed, expired, or unknown) throws
|
|
289
|
+
`GuestSessionRejectedError`, which the coordinator reports as
|
|
290
|
+
`GUEST_SESSION_REJECTED`; it then stops using that session (`current()` is
|
|
291
|
+
`undefined` and later calls fail with `GUEST_SESSION_NOT_READY` without a
|
|
292
|
+
request). Log out (it removes the dead token) and start a new coordinator for
|
|
293
|
+
a new guest. Any other failure stays `GUEST_SESSION_BACKEND_FAILED`.
|
|
294
|
+
|
|
280
295
|
Binding an external account never switches to a different server user on a
|
|
281
296
|
client callback. It does not merge purchases, currency, or progress. Use the
|
|
282
297
|
existing `progress-link` nonce/idempotency service separately for a
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Account deletion (Google Play "account deletion requirements", App Store
|
|
3
|
+
* Review Guideline 5.1.1(v)): the server erases what game services keep for
|
|
4
|
+
* a player, keeps only the purchase records the law requires (detached from
|
|
5
|
+
* the player), and has the identity service end the player's sessions.
|
|
6
|
+
*
|
|
7
|
+
* Retention decision (see docs/GAME_SERVICES_BACKEND.md#account-deletion):
|
|
8
|
+
* - Purchase ledger rows (`source: 'purchase'`), the revocations that reverse
|
|
9
|
+
* them and their notes are kept for five years, the period the Korean
|
|
10
|
+
* E-Commerce Act's enforcement decree (article 6(1)) sets for payment and
|
|
11
|
+
* supply records. They are rewritten so nothing links them to the player:
|
|
12
|
+
* a random ledger id and idempotency key, the player id replaced by
|
|
13
|
+
* `deleted:<deletionId>`, and a `playerId` payload key removed. What
|
|
14
|
+
* identifies the store transaction (store, product, platform transaction
|
|
15
|
+
* and order ids, the token digest, the store's own account binding) stays,
|
|
16
|
+
* so a dispute can be answered from the store receipt and the same store
|
|
17
|
+
* purchase can never be granted again.
|
|
18
|
+
* - Everything else (rewarded-ad and admin grants, scores, verified
|
|
19
|
+
* leaderboard entries, notification endpoints, consent records, notices,
|
|
20
|
+
* reminders, sends and their history) is deleted.
|
|
21
|
+
*/
|
|
22
|
+
import { type GameServicesHeaderResolver } from './request-headers.js';
|
|
23
|
+
import type { EntitlementLedgerPayload } from './types.js';
|
|
24
|
+
/** The public route a signed-in player deletes their own account through. */
|
|
25
|
+
export declare const accountDeletionEndpoint = "/game-services/account/delete";
|
|
26
|
+
/**
|
|
27
|
+
* The request header carrying the deletion confirmation: a short-lived,
|
|
28
|
+
* single-use token the identity service issues to the holder of the
|
|
29
|
+
* session's refresh token after the in-app second step. A bare access
|
|
30
|
+
* token (15 minutes, sent with every request) is not enough to destroy the
|
|
31
|
+
* account.
|
|
32
|
+
*/
|
|
33
|
+
export declare const accountDeletionConfirmationHeader = "x-mpgd-account-deletion-confirmation";
|
|
34
|
+
/**
|
|
35
|
+
* The longest confirmation the server accepts (characters); the identity
|
|
36
|
+
* service issues shorter ones.
|
|
37
|
+
*/
|
|
38
|
+
export declare const accountDeletionConfirmationMaxLength = 4096;
|
|
39
|
+
/**
|
|
40
|
+
* The identity service's check of a deletion confirmation: bound to the
|
|
41
|
+
* player, unexpired, and not used before; a confirmed token is consumed.
|
|
42
|
+
*/
|
|
43
|
+
export interface AccountDeletionConfirmationVerifier {
|
|
44
|
+
verifyAccountDeletionConfirmation(input: {
|
|
45
|
+
readonly playerId: string;
|
|
46
|
+
readonly confirmation: string;
|
|
47
|
+
}): Promise<{
|
|
48
|
+
readonly confirmed: boolean;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
51
|
+
/** How long the detached purchase records are kept (Korean E-Commerce Act decree, art. 6(1)). */
|
|
52
|
+
export declare const retainedPurchaseRecordYears = 5;
|
|
53
|
+
/** The prefix of the player id that replaces a deleted player's on the records kept. */
|
|
54
|
+
export declare const retainedPlayerIdPrefix = "deleted:";
|
|
55
|
+
export interface PlayerDataErasureInput {
|
|
56
|
+
/** The player whose data is erased. */
|
|
57
|
+
readonly playerId: string;
|
|
58
|
+
/** Replaces the player id on the purchase records kept (`deleted:<deletionId>`). */
|
|
59
|
+
readonly retainedPlayerId: string;
|
|
60
|
+
}
|
|
61
|
+
export interface PlayerDataErasureResult {
|
|
62
|
+
/** Rows deleted. */
|
|
63
|
+
readonly deleted: number;
|
|
64
|
+
/** Purchase ledger rows kept, detached from the player. */
|
|
65
|
+
readonly retained: number;
|
|
66
|
+
}
|
|
67
|
+
/** One store's part of an account deletion; idempotent, so it can run twice. */
|
|
68
|
+
export interface PlayerDataEraser {
|
|
69
|
+
erasePlayerData(input: PlayerDataErasureInput): Promise<PlayerDataErasureResult>;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The identity service's part (implemented by the identity Worker): revoke
|
|
73
|
+
* every session family of the player and delete the guest record, so no
|
|
74
|
+
* session authenticates as the player again. Idempotent: an unknown player
|
|
75
|
+
* succeeds. The game-services session bindings must stop accepting the
|
|
76
|
+
* player's access tokens at once too (not when they expire): the erasure
|
|
77
|
+
* runs right after, and only a request authenticated before the call can
|
|
78
|
+
* still write. It should delete the record last (or atomically): a failure
|
|
79
|
+
* after the sessions are revoked answers the player a retryable error, but
|
|
80
|
+
* the retry can no longer authenticate.
|
|
81
|
+
*/
|
|
82
|
+
export interface AccountDeletionIdentity {
|
|
83
|
+
deletePlayer(input: {
|
|
84
|
+
readonly playerId: string;
|
|
85
|
+
}): Promise<unknown>;
|
|
86
|
+
}
|
|
87
|
+
/** The audit entry of one deletion; it carries no player id or other personal data. */
|
|
88
|
+
export interface AccountDeletionAuditEntry {
|
|
89
|
+
readonly deletionId: string;
|
|
90
|
+
readonly requestedAt: string;
|
|
91
|
+
readonly completedAt: string;
|
|
92
|
+
/** `not-configured` only where no identity service exists (local development). */
|
|
93
|
+
readonly identity: 'deleted' | 'not-configured';
|
|
94
|
+
/**
|
|
95
|
+
* `false` when a store's erasure still failed after the
|
|
96
|
+
* identity was deleted: the erasure stays pending (with the player id)
|
|
97
|
+
* until `finishPendingAccountErasures` completes it and records a
|
|
98
|
+
* `complete: true` entry under the same `deletionId`.
|
|
99
|
+
*/
|
|
100
|
+
readonly complete: boolean;
|
|
101
|
+
/** Rows this request deleted; a retry after a failure counts only its own. */
|
|
102
|
+
readonly deleted: number;
|
|
103
|
+
readonly retained: number;
|
|
104
|
+
}
|
|
105
|
+
export interface AccountDeletionReceipt {
|
|
106
|
+
readonly status: 'deleted';
|
|
107
|
+
readonly deletionId: string;
|
|
108
|
+
readonly completedAt: string;
|
|
109
|
+
/**
|
|
110
|
+
* Purchase ledger rows (grants, the revocations reversing them, and their
|
|
111
|
+
* notes) this request kept, detached from the player, for the retention
|
|
112
|
+
* period. A retry after a partial failure counts only what it kept itself.
|
|
113
|
+
*/
|
|
114
|
+
readonly retainedPurchaseRecords: number;
|
|
115
|
+
}
|
|
116
|
+
export type AccountDeletionErrorCode =
|
|
117
|
+
/** No signed-in session, or a session that no longer authenticates. */
|
|
118
|
+
'UNAUTHORIZED'
|
|
119
|
+
/** The request named another player. */
|
|
120
|
+
| 'PLAYER_ID_MISMATCH'
|
|
121
|
+
/**
|
|
122
|
+
* No deletion confirmation, or one the identity service refused (expired,
|
|
123
|
+
* used, another player's). Get a new one and try again.
|
|
124
|
+
*/
|
|
125
|
+
| 'ACCOUNT_DELETION_CONFIRMATION_REQUIRED'
|
|
126
|
+
/** This server has no authentication or identity service for deletion. */
|
|
127
|
+
| 'ACCOUNT_DELETION_NOT_CONFIGURED'
|
|
128
|
+
/**
|
|
129
|
+
* The server failed before the identity was deleted (or answered 5xx, 408, 425, or 429);
|
|
130
|
+
* every step is idempotent, so retrying is safe.
|
|
131
|
+
*/
|
|
132
|
+
| 'ACCOUNT_DELETION_FAILED'
|
|
133
|
+
/** The server refused the request as malformed (another 4xx); retrying does not help. */
|
|
134
|
+
| 'ACCOUNT_DELETION_REJECTED'
|
|
135
|
+
/** The request did not reach the server or its answer was not read. */
|
|
136
|
+
| 'ACCOUNT_DELETION_UNREACHABLE';
|
|
137
|
+
export declare class AccountDeletionError extends Error {
|
|
138
|
+
readonly code: AccountDeletionErrorCode;
|
|
139
|
+
readonly retryable: boolean;
|
|
140
|
+
/**
|
|
141
|
+
* Whether the request may have reached the server. For
|
|
142
|
+
* `ACCOUNT_DELETION_UNREACHABLE` it was sent and its answer was lost or
|
|
143
|
+
* unreadable, so the deletion may have completed; for `UNAUTHORIZED` the
|
|
144
|
+
* server refused the session (`false`: no session on this device).
|
|
145
|
+
*/
|
|
146
|
+
readonly requestSent: boolean;
|
|
147
|
+
constructor(code: AccountDeletionErrorCode, options?: {
|
|
148
|
+
readonly cause?: unknown;
|
|
149
|
+
readonly requestSent?: boolean;
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
export interface AccountDeletionService {
|
|
153
|
+
/**
|
|
154
|
+
* Records the erasure as pending, deletes the identity (no session
|
|
155
|
+
* authenticates as the player any more, so nothing new is written), marks
|
|
156
|
+
* the pending erasure `identity-deleted`, then erases every store. A
|
|
157
|
+
* failure before the identity is deleted rejects with a retryable
|
|
158
|
+
* `ACCOUNT_DELETION_FAILED` and has erased nothing, so a misconfigured
|
|
159
|
+
* identity service never leaves a live account stripped of its data. Once
|
|
160
|
+
* the identity is deleted the player cannot retry, so each store is tried
|
|
161
|
+
* three times with a short backoff; a store that still fails leaves the
|
|
162
|
+
* erasure pending for `finishPendingAccountErasures` (the Worker's cron)
|
|
163
|
+
* and is reported in the audit entry (`complete: false`), never to the
|
|
164
|
+
* player.
|
|
165
|
+
*/
|
|
166
|
+
deletePlayerAccount(input: {
|
|
167
|
+
readonly playerId: string;
|
|
168
|
+
}): Promise<AccountDeletionReceipt>;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* An erasure kept across the identity deletion. It holds the player id, so
|
|
172
|
+
* it lives only until the erasure completes.
|
|
173
|
+
*/
|
|
174
|
+
export interface PendingAccountErasure extends PlayerDataErasureInput {
|
|
175
|
+
readonly deletionId: string;
|
|
176
|
+
readonly recordedAt: string;
|
|
177
|
+
/**
|
|
178
|
+
* `erasing` until the identity service confirmed the deletion. The sweep
|
|
179
|
+
* erases only `identity-deleted` erasures: an `erasing` one belongs to a
|
|
180
|
+
* request that failed or died before that confirmation, whose player most
|
|
181
|
+
* likely still exists and retries, so the sweep discards it once it is
|
|
182
|
+
* older than `staleErasingPendingMs` instead of erasing a live player.
|
|
183
|
+
* Residual gap: an identity call that committed but whose answer was lost
|
|
184
|
+
* on all three attempts (or a process that died before the mark) leaves
|
|
185
|
+
* an `erasing` entry, and
|
|
186
|
+
* the player's data then stays under the deleted id. Closing it needs the
|
|
187
|
+
* identity service to answer whether a player exists, which the binding
|
|
188
|
+
* does not offer yet.
|
|
189
|
+
*/
|
|
190
|
+
readonly phase: 'erasing' | 'identity-deleted';
|
|
191
|
+
/** Sweep attempts so far. */
|
|
192
|
+
readonly attempts: number;
|
|
193
|
+
/** When the sweep last tried it; the store lists least recently tried first. */
|
|
194
|
+
readonly attemptedAt?: string;
|
|
195
|
+
}
|
|
196
|
+
export interface PendingAccountErasureStore {
|
|
197
|
+
/** Inserts or replaces the erasure named by `deletionId`. */
|
|
198
|
+
put(erasure: PendingAccountErasure): Promise<void>;
|
|
199
|
+
clear(input: {
|
|
200
|
+
readonly deletionId: string;
|
|
201
|
+
}): Promise<void>;
|
|
202
|
+
/**
|
|
203
|
+
* At most `limit` erasures: `identity-deleted` ones first, then by least
|
|
204
|
+
* recently tried (`attemptedAt`, else `recordedAt`). With
|
|
205
|
+
* `identityDeletedBefore`, an `identity-deleted` erasure recorded after it
|
|
206
|
+
* is left out (it is not due for its final pass yet), so young entries
|
|
207
|
+
* never take the slots of due ones.
|
|
208
|
+
*/
|
|
209
|
+
list(input: {
|
|
210
|
+
readonly limit: number;
|
|
211
|
+
readonly identityDeletedBefore?: string;
|
|
212
|
+
}): Promise<readonly PendingAccountErasure[]>;
|
|
213
|
+
}
|
|
214
|
+
/** An `erasing` erasure older than this (one hour) is discarded by the sweep. */
|
|
215
|
+
export declare const staleErasingPendingMs: number;
|
|
216
|
+
/**
|
|
217
|
+
* The sweep erases an `identity-deleted` erasure once more, and only then
|
|
218
|
+
* clears it, at its first run at least this long (15 minutes) after the
|
|
219
|
+
* request: longer than any request that authenticated before the identity
|
|
220
|
+
* was deleted can still run. Until then the pending entry (with the player
|
|
221
|
+
* id) is kept, so a deployment must run the sweep (the Worker's cron).
|
|
222
|
+
*/
|
|
223
|
+
export declare const finalErasureDelayMs: number;
|
|
224
|
+
export declare function createInMemoryPendingAccountErasureStore(): PendingAccountErasureStore;
|
|
225
|
+
export declare function createAccountDeletionService(input: {
|
|
226
|
+
readonly erasers: readonly PlayerDataEraser[];
|
|
227
|
+
/**
|
|
228
|
+
* The identity service. `null` only for local development without one:
|
|
229
|
+
* the player's sessions then survive the deletion.
|
|
230
|
+
*/
|
|
231
|
+
readonly identity: AccountDeletionIdentity | null;
|
|
232
|
+
/** Keeps an erasure across the identity deletion; see `finishPendingAccountErasures`. */
|
|
233
|
+
readonly pending: PendingAccountErasureStore;
|
|
234
|
+
/** Records the audit entry. A failure is logged and does not fail the deletion. */
|
|
235
|
+
readonly audit?: (entry: AccountDeletionAuditEntry) => Promise<void>;
|
|
236
|
+
readonly now?: () => string;
|
|
237
|
+
readonly createDeletionId?: () => string;
|
|
238
|
+
/** Waits between retry attempts; defaults to a timer. */
|
|
239
|
+
readonly sleep?: (ms: number) => Promise<void>;
|
|
240
|
+
}): AccountDeletionService;
|
|
241
|
+
export interface PendingAccountErasureSweep {
|
|
242
|
+
/** `identity-deleted` erasures that every store completed and that were cleared. */
|
|
243
|
+
readonly finished: number;
|
|
244
|
+
/** Erasures a store failed (kept for the next sweep), and stale entries that could not be discarded. */
|
|
245
|
+
readonly failed: number;
|
|
246
|
+
/** Stale `erasing` erasures discarded without erasing. */
|
|
247
|
+
readonly discarded: number;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Finishes erasures a deletion left pending: an `identity-deleted` one is
|
|
251
|
+
* erased again `finalErasureDelayMs` after the request (every deletion
|
|
252
|
+
* gets this final pass, which removes what a request authenticated before
|
|
253
|
+
* the identity was deleted wrote later) and cleared once every store
|
|
254
|
+
* completed it, with an audit entry that marks the deletion complete; an
|
|
255
|
+
* `erasing` one older than
|
|
256
|
+
* `staleErasingPendingMs` is discarded without erasing. Run it from a
|
|
257
|
+
* scheduled job. A failing erasure is tried again later, least recently
|
|
258
|
+
* tried first, so one that keeps failing does not block the others.
|
|
259
|
+
*/
|
|
260
|
+
export declare function finishPendingAccountErasures(input: {
|
|
261
|
+
readonly erasers: readonly PlayerDataEraser[];
|
|
262
|
+
readonly pending: PendingAccountErasureStore;
|
|
263
|
+
readonly audit?: (entry: AccountDeletionAuditEntry) => Promise<void>;
|
|
264
|
+
readonly now?: () => string;
|
|
265
|
+
readonly limit?: number;
|
|
266
|
+
}): Promise<PendingAccountErasureSweep>;
|
|
267
|
+
/** The player id stored on a deleted player's kept purchase records. */
|
|
268
|
+
export declare function isRetainedPlayerId(playerId: string): boolean;
|
|
269
|
+
/** Refuses an erasure input whose ids could re-erase another deletion's kept records. */
|
|
270
|
+
export declare function assertPlayerDataErasureInput(input: PlayerDataErasureInput): PlayerDataErasureInput;
|
|
271
|
+
/** A fresh id for a kept ledger row; it carries nothing of the player's ids. */
|
|
272
|
+
export declare function createRetainedLedgerEntryId(): string;
|
|
273
|
+
/** The kept row's payload: the store transaction stays, the player id goes. */
|
|
274
|
+
export declare function detachRetainedLedgerPayload(payload: EntitlementLedgerPayload): EntitlementLedgerPayload;
|
|
275
|
+
export interface AccountDeletionFetchResponse {
|
|
276
|
+
readonly status: number;
|
|
277
|
+
text(): Promise<string>;
|
|
278
|
+
}
|
|
279
|
+
export type AccountDeletionFetch = (url: string, init: {
|
|
280
|
+
readonly method: 'POST';
|
|
281
|
+
readonly headers: Record<string, string>;
|
|
282
|
+
readonly body: string;
|
|
283
|
+
readonly signal?: AbortSignal;
|
|
284
|
+
}) => Promise<AccountDeletionFetchResponse>;
|
|
285
|
+
/** How long `deleteAccount()` waits for the session and the server by default. */
|
|
286
|
+
export declare const defaultAccountDeletionTimeoutMs = 30000;
|
|
287
|
+
export interface AccountDeletionClient {
|
|
288
|
+
/**
|
|
289
|
+
* Deletes the signed-in player's account on the server. Resolves with the
|
|
290
|
+
* receipt; rejects with an `AccountDeletionError`. After an
|
|
291
|
+
* `ACCOUNT_DELETION_UNREACHABLE` failure the deletion may have completed:
|
|
292
|
+
* a retry that answers `UNAUTHORIZED` means the session no longer exists.
|
|
293
|
+
*/
|
|
294
|
+
deleteAccount(input?: {
|
|
295
|
+
/** The identity service's deletion confirmation (`accountDeletionConfirmationHeader`). */
|
|
296
|
+
readonly confirmation?: string;
|
|
297
|
+
}): Promise<AccountDeletionReceipt>;
|
|
298
|
+
}
|
|
299
|
+
export declare function createAccountDeletionClient(input: {
|
|
300
|
+
readonly baseUrl: string;
|
|
301
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
302
|
+
readonly getHeaders?: GameServicesHeaderResolver;
|
|
303
|
+
readonly fetch?: AccountDeletionFetch;
|
|
304
|
+
/** Deadline for resolving the session headers and the server's answer; 30 s by default. */
|
|
305
|
+
readonly timeoutMs?: number;
|
|
306
|
+
}): AccountDeletionClient;
|