@metamask-previews/kyc-controller 0.0.0-preview-abca9bcea → 0.0.0-preview-ec24abb79
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/CHANGELOG.md +0 -12
- package/dist/KycController-method-action-types.cjs.map +1 -1
- package/dist/KycController-method-action-types.d.cts +4 -6
- package/dist/KycController-method-action-types.d.cts.map +1 -1
- package/dist/KycController-method-action-types.d.mts +4 -6
- package/dist/KycController-method-action-types.d.mts.map +1 -1
- package/dist/KycController-method-action-types.mjs.map +1 -1
- package/dist/KycController.cjs +300 -191
- package/dist/KycController.cjs.map +1 -1
- package/dist/KycController.d.cts +40 -46
- package/dist/KycController.d.cts.map +1 -1
- package/dist/KycController.d.mts +40 -46
- package/dist/KycController.d.mts.map +1 -1
- package/dist/KycController.mjs +299 -188
- package/dist/KycController.mjs.map +1 -1
- package/dist/KycService-method-action-types.cjs.map +1 -1
- package/dist/KycService-method-action-types.d.cts +6 -23
- package/dist/KycService-method-action-types.d.cts.map +1 -1
- package/dist/KycService-method-action-types.d.mts +6 -23
- package/dist/KycService-method-action-types.d.mts.map +1 -1
- package/dist/KycService-method-action-types.mjs.map +1 -1
- package/dist/KycService.cjs +119 -100
- package/dist/KycService.cjs.map +1 -1
- package/dist/KycService.d.cts +12 -38
- package/dist/KycService.d.cts.map +1 -1
- package/dist/KycService.d.mts +12 -38
- package/dist/KycService.d.mts.map +1 -1
- package/dist/KycService.mjs +119 -100
- package/dist/KycService.mjs.map +1 -1
- package/dist/index.cjs +1 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +5 -53
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +5 -53
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/ukyc/wrapEncryptionKey.cjs +9 -4
- package/dist/ukyc/wrapEncryptionKey.cjs.map +1 -1
- package/dist/ukyc/wrapEncryptionKey.d.cts +10 -8
- package/dist/ukyc/wrapEncryptionKey.d.cts.map +1 -1
- package/dist/ukyc/wrapEncryptionKey.d.mts +10 -8
- package/dist/ukyc/wrapEncryptionKey.d.mts.map +1 -1
- package/dist/ukyc/wrapEncryptionKey.mjs +9 -4
- package/dist/ukyc/wrapEncryptionKey.mjs.map +1 -1
- package/package.json +2 -2
- package/dist/logger.cjs +0 -9
- package/dist/logger.cjs.map +0 -1
- package/dist/logger.d.cts +0 -6
- package/dist/logger.d.cts.map +0 -1
- package/dist/logger.d.mts +0 -6
- package/dist/logger.d.mts.map +0 -1
- package/dist/logger.mjs +0 -6
- package/dist/logger.mjs.map +0 -1
- package/dist/vendorDisclaimerAcceptance.cjs +0 -74
- package/dist/vendorDisclaimerAcceptance.cjs.map +0 -1
- package/dist/vendorDisclaimerAcceptance.d.cts +0 -39
- package/dist/vendorDisclaimerAcceptance.d.cts.map +0 -1
- package/dist/vendorDisclaimerAcceptance.d.mts +0 -39
- package/dist/vendorDisclaimerAcceptance.d.mts.map +0 -1
- package/dist/vendorDisclaimerAcceptance.mjs +0 -67
- package/dist/vendorDisclaimerAcceptance.mjs.map +0 -1
- package/dist/vendors/MoonPayFrameHandler.cjs +0 -235
- package/dist/vendors/MoonPayFrameHandler.cjs.map +0 -1
- package/dist/vendors/MoonPayFrameHandler.d.cts +0 -74
- package/dist/vendors/MoonPayFrameHandler.d.cts.map +0 -1
- package/dist/vendors/MoonPayFrameHandler.d.mts +0 -74
- package/dist/vendors/MoonPayFrameHandler.d.mts.map +0 -1
- package/dist/vendors/MoonPayFrameHandler.mjs +0 -230
- package/dist/vendors/MoonPayFrameHandler.mjs.map +0 -1
package/dist/KycController.mjs
CHANGED
|
@@ -9,21 +9,23 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _KycController_instances, _KycController_sumsubLauncher,
|
|
12
|
+
var _KycController_instances, _KycController_sumsubLauncher, _KycController_keypair, _KycController_authClientToken, _KycController_generation, _KycController_sessionStatusPollIntervalMs, _KycController_pollTimer, _KycController_pollToken, _KycController_userStatusPollIntervalMs, _KycController_userStatusPollTimer, _KycController_userStatusPolling, _KycController_userStatusPollToken, _KycController_localUserSecretStore, _KycController_startConsentsSession, _KycController_recordSessionDisclaimers, _KycController_createSession, _KycController_clearAcceptedTerms, _KycController_clearMoonPaySession, _KycController_dropTermsUnlessForVendor, _KycController_hasTermsForVendor, _KycController_handleCheckOutcome, _KycController_handleAuthOutcome, _KycController_continueAfterAuthentication, _KycController_requireTermsReacceptance, _KycController_buildUkycSessionVendorFields, _KycController_createUkycSession, _KycController_fetchAndApplyUserStatus, _KycController_applyUserStatus, _KycController_ensureUserStatusPolling, _KycController_stopUserStatusPolling, _KycController_startSessionStatusPolling, _KycController_pollSessionStatusOnce, _KycController_stopPolling, _KycController_cancelPendingSession, _KycController_updateIfCurrent, _KycController_applyUpdate, _KycController_assertAttestedServerPublicKey, _KycController_fail;
|
|
13
13
|
import { BaseController } from "@metamask/base-controller";
|
|
14
14
|
import { stringToBytes } from "@metamask/utils";
|
|
15
15
|
import { x25519 } from "@noble/curves/ed25519";
|
|
16
|
+
import { decryptCredentials, generateKeyPair } from "./crypto.mjs";
|
|
16
17
|
import { toBase64Url } from "./encoding.mjs";
|
|
17
|
-
import { controllerLog } from "./logger.mjs";
|
|
18
18
|
import { deriveClientMaterial } from "./ukyc/deriveClientMaterial.mjs";
|
|
19
19
|
import { verifyJwtChain } from "./ukyc/jwtChain.mjs";
|
|
20
20
|
import { getOrCreateLocalUserSecret } from "./ukyc/localUserSecret.mjs";
|
|
21
21
|
import { encodeStorageAccessTokenForHeader, signStorageAccessToken } from "./ukyc/storageAccessToken.mjs";
|
|
22
22
|
import { wrapEncryptionKey } from "./ukyc/wrapEncryptionKey.mjs";
|
|
23
|
-
import { clearVendorDisclaimerAcceptance, hasVendorDisclaimerAcceptance, ironDisclaimerIds, recordVendorDisclaimerAcceptance } from "./vendorDisclaimerAcceptance.mjs";
|
|
24
|
-
import { clearMoonPaySession, MoonPayFrameHandler } from "./vendors/MoonPayFrameHandler.mjs";
|
|
25
23
|
// === GENERAL ===
|
|
26
24
|
export const controllerName = 'KycController';
|
|
25
|
+
const FRAMES_BASE_URL = 'https://blocks.moonpay.com/platform/v1';
|
|
26
|
+
const CHANNEL_CHECK = 'ch_1';
|
|
27
|
+
const CHANNEL_AUTH = 'ch_2';
|
|
28
|
+
const CHANNEL_RESET = 'ch_reset';
|
|
27
29
|
// Placeholder credentials for the SumSub sub-flow. These are demo values that
|
|
28
30
|
// must be replaced with real UKYC-issued material before production use.
|
|
29
31
|
const MOCK_JWT_TOKEN = 'mock-jwt-token';
|
|
@@ -114,19 +116,31 @@ const kycControllerMetadata = {
|
|
|
114
116
|
persist: false,
|
|
115
117
|
usedInUi: false,
|
|
116
118
|
},
|
|
117
|
-
|
|
119
|
+
termsAcceptedAt: {
|
|
118
120
|
includeInDebugSnapshot: true,
|
|
119
121
|
includeInStateLogs: true,
|
|
120
122
|
persist: true,
|
|
121
123
|
usedInUi: false,
|
|
122
124
|
},
|
|
123
|
-
|
|
125
|
+
acceptedDisclaimerIds: {
|
|
124
126
|
includeInDebugSnapshot: true,
|
|
125
127
|
includeInStateLogs: true,
|
|
126
128
|
persist: true,
|
|
127
129
|
usedInUi: false,
|
|
128
130
|
},
|
|
129
|
-
|
|
131
|
+
termsAcceptedVendor: {
|
|
132
|
+
includeInDebugSnapshot: true,
|
|
133
|
+
includeInStateLogs: true,
|
|
134
|
+
persist: true,
|
|
135
|
+
usedInUi: false,
|
|
136
|
+
},
|
|
137
|
+
sumsubTncAccepted: {
|
|
138
|
+
includeInDebugSnapshot: true,
|
|
139
|
+
includeInStateLogs: true,
|
|
140
|
+
persist: true,
|
|
141
|
+
usedInUi: false,
|
|
142
|
+
},
|
|
143
|
+
idosTncAccepted: {
|
|
130
144
|
includeInDebugSnapshot: true,
|
|
131
145
|
includeInStateLogs: true,
|
|
132
146
|
persist: true,
|
|
@@ -138,13 +152,13 @@ const kycControllerMetadata = {
|
|
|
138
152
|
persist: false,
|
|
139
153
|
usedInUi: false,
|
|
140
154
|
},
|
|
141
|
-
|
|
155
|
+
disclaimers: {
|
|
142
156
|
includeInDebugSnapshot: false,
|
|
143
157
|
includeInStateLogs: false,
|
|
144
158
|
persist: false,
|
|
145
159
|
usedInUi: true,
|
|
146
160
|
},
|
|
147
|
-
|
|
161
|
+
disclaimersError: {
|
|
148
162
|
includeInDebugSnapshot: true,
|
|
149
163
|
includeInStateLogs: true,
|
|
150
164
|
persist: false,
|
|
@@ -162,13 +176,13 @@ const kycControllerMetadata = {
|
|
|
162
176
|
persist: false,
|
|
163
177
|
usedInUi: true,
|
|
164
178
|
},
|
|
165
|
-
|
|
179
|
+
sessionToken: {
|
|
166
180
|
includeInDebugSnapshot: false,
|
|
167
181
|
includeInStateLogs: false,
|
|
168
182
|
persist: false,
|
|
169
183
|
usedInUi: false,
|
|
170
184
|
},
|
|
171
|
-
|
|
185
|
+
accessToken: {
|
|
172
186
|
includeInDebugSnapshot: false,
|
|
173
187
|
includeInStateLogs: false,
|
|
174
188
|
persist: false,
|
|
@@ -229,17 +243,6 @@ const kycControllerMetadata = {
|
|
|
229
243
|
usedInUi: true,
|
|
230
244
|
},
|
|
231
245
|
};
|
|
232
|
-
/**
|
|
233
|
-
* Constructs the default {@link KycVendorDisclaimersAccepted} value.
|
|
234
|
-
*
|
|
235
|
-
* @returns The default vendor-disclaimer acceptance map.
|
|
236
|
-
*/
|
|
237
|
-
export function getDefaultKycVendorDisclaimersAccepted() {
|
|
238
|
-
return { moonpay: null, iron: null };
|
|
239
|
-
}
|
|
240
|
-
export function getDefaultKycProviderDisclaimersAccepted() {
|
|
241
|
-
return { sumsub: null };
|
|
242
|
-
}
|
|
243
246
|
/**
|
|
244
247
|
* Constructs the default {@link KycController} state.
|
|
245
248
|
*
|
|
@@ -251,16 +254,18 @@ export function getDefaultKycControllerState() {
|
|
|
251
254
|
statusMessage: '',
|
|
252
255
|
error: null,
|
|
253
256
|
email: null,
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
+
termsAcceptedAt: null,
|
|
258
|
+
acceptedDisclaimerIds: [],
|
|
259
|
+
termsAcceptedVendor: null,
|
|
260
|
+
sumsubTncAccepted: null,
|
|
261
|
+
idosTncAccepted: null,
|
|
257
262
|
credentialReusabilityConsentGiven: null,
|
|
258
|
-
|
|
259
|
-
|
|
263
|
+
disclaimers: [],
|
|
264
|
+
disclaimersError: null,
|
|
260
265
|
sessionDisclaimers: null,
|
|
261
266
|
geoCountry: null,
|
|
262
|
-
|
|
263
|
-
|
|
267
|
+
sessionToken: null,
|
|
268
|
+
accessToken: null,
|
|
264
269
|
moonpayCustomerId: null,
|
|
265
270
|
activeVendor: 'moonpay',
|
|
266
271
|
activeProduct: null,
|
|
@@ -304,62 +309,45 @@ function isConsentConflictError(error) {
|
|
|
304
309
|
error.httpStatus === 409);
|
|
305
310
|
}
|
|
306
311
|
/**
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
*/
|
|
311
|
-
function isValidConsentRecordList(value) {
|
|
312
|
-
return (Array.isArray(value) &&
|
|
313
|
-
value.every((item) => typeof item === 'object' &&
|
|
314
|
-
item !== null &&
|
|
315
|
-
typeof item.key === 'string' &&
|
|
316
|
-
typeof item.version === 'string'));
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* Maps accepted disclaimer records onto unconsented catalog documents.
|
|
312
|
+
* Maps a session-disclaimer catalog into the `{ key, version }` records the
|
|
313
|
+
* record-consents API expects, or an empty list when the user declined that
|
|
314
|
+
* category.
|
|
320
315
|
*
|
|
321
316
|
* @param documents - Catalog documents for one consent category.
|
|
322
|
-
* @param accepted -
|
|
323
|
-
* @returns Consent records
|
|
317
|
+
* @param accepted - Whether the user accepted that category.
|
|
318
|
+
* @returns Consent records, or `[]` when not accepted.
|
|
324
319
|
*/
|
|
325
|
-
function
|
|
326
|
-
if (accepted
|
|
320
|
+
function consentRecordsFromCatalog(documents, accepted) {
|
|
321
|
+
if (!accepted) {
|
|
327
322
|
return [];
|
|
328
323
|
}
|
|
329
|
-
const acceptedKeys = new Set(accepted.map((record) => `${record.key}:${record.version}`));
|
|
330
324
|
return documents
|
|
331
|
-
.filter((document) => !document.consented
|
|
332
|
-
acceptedKeys.has(`${document.key}:${document.version}`))
|
|
325
|
+
.filter((document) => !document.consented)
|
|
333
326
|
.map(({ key, version }) => ({ key, version }));
|
|
334
327
|
}
|
|
335
328
|
/**
|
|
336
|
-
* Whether accepted
|
|
329
|
+
* Whether an accepted T&C2 category has no catalog documents. An empty list
|
|
330
|
+
* would otherwise skip the POST and count as success.
|
|
337
331
|
*
|
|
338
332
|
* @param documents - Catalog documents for one consent category.
|
|
339
|
-
* @param accepted -
|
|
340
|
-
* @returns `true` when the
|
|
333
|
+
* @param accepted - Whether the user accepted that category.
|
|
334
|
+
* @returns `true` when the user accepted and the catalog is empty.
|
|
341
335
|
*/
|
|
342
336
|
function isAcceptedCategoryEmpty(documents, accepted) {
|
|
343
|
-
return accepted
|
|
337
|
+
return accepted && documents.length === 0;
|
|
344
338
|
}
|
|
345
339
|
/**
|
|
346
|
-
* Whether accepted
|
|
347
|
-
* empty catalog or any
|
|
340
|
+
* Whether an accepted category is still missing consent after a 409 re-GET:
|
|
341
|
+
* empty catalog or any document still unconsented.
|
|
348
342
|
*
|
|
349
343
|
* @param documents - Latest catalog documents for one consent category.
|
|
350
|
-
* @param accepted -
|
|
344
|
+
* @param accepted - Whether the user accepted that category.
|
|
351
345
|
* @returns `true` when accepted documents are not fully consented.
|
|
352
346
|
*/
|
|
353
347
|
function acceptedCategoryStillMissing(documents, accepted) {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
if (documents.length === 0) {
|
|
358
|
-
return true;
|
|
359
|
-
}
|
|
360
|
-
const acceptedKeys = new Set(accepted.map((record) => `${record.key}:${record.version}`));
|
|
361
|
-
const relevant = documents.filter((document) => acceptedKeys.has(`${document.key}:${document.version}`));
|
|
362
|
-
return (relevant.length === 0 || relevant.some((document) => !document.consented));
|
|
348
|
+
return (accepted &&
|
|
349
|
+
(documents.length === 0 ||
|
|
350
|
+
documents.some((document) => !document.consented)));
|
|
363
351
|
}
|
|
364
352
|
/**
|
|
365
353
|
* Vendors other than MoonPay skip Check/Auth frames and use the empty-shell
|
|
@@ -395,9 +383,9 @@ const MESSENGER_EXPOSED_METHODS = [
|
|
|
395
383
|
/**
|
|
396
384
|
* `KycController` orchestrates the vendor-backed KYC / identity-verification
|
|
397
385
|
* flow (MoonPay identity + SumSub documents) behind a vendor-neutral, per
|
|
398
|
-
* product surface used by ramps and card. It owns all state
|
|
399
|
-
* orchestration (via `KycService`),
|
|
400
|
-
* platform-specific presentation (WebView/iframe, SumSub SDK)
|
|
386
|
+
* product surface used by ramps and card. It owns all state, HTTP
|
|
387
|
+
* orchestration (via `KycService`), crypto, and the frame message protocol;
|
|
388
|
+
* platform-specific presentation (WebView/iframe, SumSub SDK) is injected.
|
|
401
389
|
*/
|
|
402
390
|
export class KycController extends BaseController {
|
|
403
391
|
/**
|
|
@@ -421,8 +409,10 @@ export class KycController extends BaseController {
|
|
|
421
409
|
});
|
|
422
410
|
_KycController_instances.add(this);
|
|
423
411
|
_KycController_sumsubLauncher.set(this, void 0);
|
|
424
|
-
/**
|
|
425
|
-
|
|
412
|
+
/** Ephemeral X25519 keypair for the frame key exchange (never persisted). */
|
|
413
|
+
_KycController_keypair.set(this, void 0);
|
|
414
|
+
/** Auth-frame client token, kept out of state. */
|
|
415
|
+
_KycController_authClientToken.set(this, null);
|
|
426
416
|
/**
|
|
427
417
|
* Monotonic flow generation. Incremented by {@link reset} and
|
|
428
418
|
* {@link clearState} so in-flight async work (e.g. the KYC-required check)
|
|
@@ -459,13 +449,7 @@ export class KycController extends BaseController {
|
|
|
459
449
|
__classPrivateFieldSet(this, _KycController_sumsubLauncher, sumsubLauncher, "f");
|
|
460
450
|
__classPrivateFieldSet(this, _KycController_sessionStatusPollIntervalMs, sessionStatusPollIntervalMs, "f");
|
|
461
451
|
__classPrivateFieldSet(this, _KycController_userStatusPollIntervalMs, userStatusPollIntervalMs, "f");
|
|
462
|
-
__classPrivateFieldSet(this,
|
|
463
|
-
getState: () => this.state,
|
|
464
|
-
update: (updater) => __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, updater),
|
|
465
|
-
fail: (message) => __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, message),
|
|
466
|
-
onAuthenticated: async () => __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_continueAfterAuthentication).call(this),
|
|
467
|
-
requireTermsReacceptance: () => __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_requireTermsReacceptance).call(this),
|
|
468
|
-
}), "f");
|
|
452
|
+
__classPrivateFieldSet(this, _KycController_keypair, generateKeyPair(), "f");
|
|
469
453
|
this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
470
454
|
}
|
|
471
455
|
/**
|
|
@@ -488,19 +472,10 @@ export class KycController extends BaseController {
|
|
|
488
472
|
// forces `phase` back through `session`/`check`, breaking an in-flight
|
|
489
473
|
// Check/Auth frame flow. Leave the active flow untouched and let the
|
|
490
474
|
// consumer drive it (or call `reset` first to start over).
|
|
491
|
-
const vendor = params?.vendor ?? 'moonpay';
|
|
492
475
|
if (IN_PROGRESS_PHASES.includes(this.state.phase)) {
|
|
493
|
-
if (vendor === 'moonpay') {
|
|
494
|
-
__classPrivateFieldGet(this, _KycController_moonPayFrames, "f").ensureKeypair();
|
|
495
|
-
}
|
|
496
476
|
return;
|
|
497
477
|
}
|
|
498
|
-
|
|
499
|
-
__classPrivateFieldGet(this, _KycController_moonPayFrames, "f").startFlow();
|
|
500
|
-
}
|
|
501
|
-
else {
|
|
502
|
-
__classPrivateFieldGet(this, _KycController_moonPayFrames, "f").clear();
|
|
503
|
-
}
|
|
478
|
+
const vendor = params?.vendor ?? 'moonpay';
|
|
504
479
|
// `initialize` starts a fresh flow, so `activeProduct` is always reset to
|
|
505
480
|
// this call's product (or `null`). Otherwise a prior run's product could
|
|
506
481
|
// linger and cause `#continueAfterAuthentication` to auto-run the check /
|
|
@@ -510,9 +485,14 @@ export class KycController extends BaseController {
|
|
|
510
485
|
state.email = params.email;
|
|
511
486
|
}
|
|
512
487
|
state.activeVendor = vendor;
|
|
513
|
-
// MoonPay Check/Auth artifacts must not survive a switch to another
|
|
488
|
+
// MoonPay Check/Auth artifacts must not survive a switch to another
|
|
489
|
+
// vendor: leftover `sessionToken` would keep `buildCheckFrameUrl` alive,
|
|
490
|
+
// leftover `accessToken` / `#authClientToken` would keep Auth / KYC
|
|
491
|
+
// calls bound to MoonPay, and leftover `moonpayCustomerId` would make
|
|
492
|
+
// `getCustomerIdentity` report a MoonPay id under the wrong vendor.
|
|
514
493
|
if (vendor !== 'moonpay') {
|
|
515
|
-
|
|
494
|
+
__classPrivateFieldSet(this, _KycController_authClientToken, null, "f");
|
|
495
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_clearMoonPaySession).call(this, state);
|
|
516
496
|
}
|
|
517
497
|
state.activeProduct = params?.product ?? null;
|
|
518
498
|
});
|
|
@@ -560,14 +540,16 @@ export class KycController extends BaseController {
|
|
|
560
540
|
if (__classPrivateFieldGet(this, _KycController_generation, "f") !== generation) {
|
|
561
541
|
return;
|
|
562
542
|
}
|
|
563
|
-
|
|
543
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_dropTermsUnlessForVendor).call(this, vendor);
|
|
544
|
+
const hasTerms = Boolean(this.state.termsAcceptedAt) &&
|
|
545
|
+
this.state.acceptedDisclaimerIds.length > 0;
|
|
564
546
|
if (hasTerms && this.state.email) {
|
|
565
547
|
if (usesConsentsFlow(vendor)) {
|
|
566
548
|
// Consents-path vendors require T&C2 flags; if they weren't persisted
|
|
567
549
|
// (i.e. null from pre-migration state), require reacceptance.
|
|
568
|
-
const
|
|
569
|
-
|
|
570
|
-
|
|
550
|
+
const sumsubTncSigned = this.state.sumsubTncAccepted;
|
|
551
|
+
const idosTncSigned = this.state.idosTncAccepted;
|
|
552
|
+
if (sumsubTncSigned === null || idosTncSigned === null) {
|
|
571
553
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
|
|
572
554
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_clearAcceptedTerms).call(this, state);
|
|
573
555
|
state.phase = 'terms';
|
|
@@ -576,19 +558,12 @@ export class KycController extends BaseController {
|
|
|
576
558
|
return;
|
|
577
559
|
}
|
|
578
560
|
await __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_startConsentsSession).call(this, {
|
|
579
|
-
|
|
580
|
-
|
|
561
|
+
sumsubTncSigned,
|
|
562
|
+
idosTncSigned,
|
|
581
563
|
credentialReusabilityConsentGiven: this.state.credentialReusabilityConsentGiven ?? false,
|
|
582
564
|
});
|
|
583
565
|
}
|
|
584
566
|
else {
|
|
585
|
-
// TODO: should this be here? or should it exist at all?
|
|
586
|
-
if (vendor === 'moonpay' && this.state.vendorDisclaimers.length === 0) {
|
|
587
|
-
await this.loadDisclaimers();
|
|
588
|
-
if (__classPrivateFieldGet(this, _KycController_generation, "f") !== generation) {
|
|
589
|
-
return;
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
567
|
await __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_createSession).call(this);
|
|
593
568
|
}
|
|
594
569
|
return;
|
|
@@ -622,8 +597,8 @@ export class KycController extends BaseController {
|
|
|
622
597
|
// after this request succeeds.
|
|
623
598
|
state.activeVendor = params.vendor;
|
|
624
599
|
if (params.vendor !== 'moonpay') {
|
|
625
|
-
|
|
626
|
-
|
|
600
|
+
__classPrivateFieldSet(this, _KycController_authClientToken, null, "f");
|
|
601
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_clearMoonPaySession).call(this, state);
|
|
627
602
|
}
|
|
628
603
|
});
|
|
629
604
|
const generation = __classPrivateFieldGet(this, _KycController_generation, "f");
|
|
@@ -632,6 +607,10 @@ export class KycController extends BaseController {
|
|
|
632
607
|
vendor: params.vendor,
|
|
633
608
|
email: params.email,
|
|
634
609
|
});
|
|
610
|
+
if (__classPrivateFieldGet(this, _KycController_generation, "f") !== generation) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_dropTermsUnlessForVendor).call(this, params.vendor);
|
|
635
614
|
}
|
|
636
615
|
catch (error) {
|
|
637
616
|
if (__classPrivateFieldGet(this, _KycController_generation, "f") !== generation) {
|
|
@@ -660,18 +639,18 @@ export class KycController extends BaseController {
|
|
|
660
639
|
state.geoCountry = country;
|
|
661
640
|
});
|
|
662
641
|
}
|
|
663
|
-
const disclaimers = await this.messenger.call('KycService:
|
|
642
|
+
const disclaimers = await this.messenger.call('KycService:fetchDisclaimers', {
|
|
664
643
|
vendor: this.state.activeVendor,
|
|
665
644
|
country,
|
|
666
645
|
});
|
|
667
646
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_updateIfCurrent).call(this, generation, (state) => {
|
|
668
|
-
state.
|
|
669
|
-
state.
|
|
647
|
+
state.disclaimers = disclaimers;
|
|
648
|
+
state.disclaimersError = null;
|
|
670
649
|
});
|
|
671
650
|
}
|
|
672
651
|
catch (error) {
|
|
673
652
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_updateIfCurrent).call(this, generation, (state) => {
|
|
674
|
-
state.
|
|
653
|
+
state.disclaimersError = `Failed to load disclaimers: ${String(error)}`;
|
|
675
654
|
});
|
|
676
655
|
}
|
|
677
656
|
}
|
|
@@ -684,47 +663,44 @@ export class KycController extends BaseController {
|
|
|
684
663
|
* @param params.product - The consuming feature the flow runs for. See
|
|
685
664
|
* {@link initialize} for how the product drives the automatic post
|
|
686
665
|
* authentication continuation.
|
|
687
|
-
* @param params.
|
|
688
|
-
*
|
|
689
|
-
*
|
|
690
|
-
*
|
|
691
|
-
* customer accepted (`{ key, version }` records). Required for every vendor
|
|
692
|
-
* so callers explicitly declare acceptance.
|
|
666
|
+
* @param params.sumsubTncSigned - Whether Sumsub T&C were accepted (T&C2).
|
|
667
|
+
* Required for every vendor so callers explicitly declare acceptance.
|
|
668
|
+
* @param params.idosTncSigned - Whether idOS T&C were accepted (T&C2).
|
|
669
|
+
* Required for every vendor so callers explicitly declare acceptance.
|
|
693
670
|
* @param params.credentialReusabilityConsentGiven - Whether the customer
|
|
694
671
|
* consented to reuse existing idOS credentials. Used when recording
|
|
695
672
|
* session-scoped disclaimers on the consents path. Defaults to `false`.
|
|
696
673
|
*/
|
|
697
674
|
async acceptTermsAndStartSession(params) {
|
|
698
|
-
const
|
|
699
|
-
const
|
|
700
|
-
if (
|
|
701
|
-
|
|
675
|
+
const sumsubTncSigned = params?.sumsubTncSigned;
|
|
676
|
+
const idosTncSigned = params?.idosTncSigned;
|
|
677
|
+
if (typeof sumsubTncSigned !== 'boolean' ||
|
|
678
|
+
typeof idosTncSigned !== 'boolean') {
|
|
702
679
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, 'Missing T&C2 acceptance flags.');
|
|
703
680
|
return;
|
|
704
681
|
}
|
|
705
|
-
const credentialReusabilityConsentGiven = params
|
|
682
|
+
const credentialReusabilityConsentGiven = params.credentialReusabilityConsentGiven ?? false;
|
|
706
683
|
const termsAcceptedAt = new Date().toISOString();
|
|
707
|
-
const disclaimerIds = this.state.
|
|
684
|
+
const disclaimerIds = this.state.disclaimers.map((disclaimer) => disclaimer.id);
|
|
708
685
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
|
|
709
|
-
if (params
|
|
686
|
+
if (params.email) {
|
|
710
687
|
state.email = params.email;
|
|
711
688
|
}
|
|
712
|
-
if (params
|
|
689
|
+
if (params.product) {
|
|
713
690
|
state.activeProduct = params.product;
|
|
714
691
|
}
|
|
715
|
-
state.
|
|
716
|
-
state.
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
state.idosDisclaimersAccepted = idosDisclaimersAccepted;
|
|
692
|
+
state.termsAcceptedAt = termsAcceptedAt;
|
|
693
|
+
state.acceptedDisclaimerIds = disclaimerIds;
|
|
694
|
+
state.termsAcceptedVendor = state.activeVendor;
|
|
695
|
+
state.sumsubTncAccepted = sumsubTncSigned;
|
|
696
|
+
state.idosTncAccepted = idosTncSigned;
|
|
721
697
|
state.credentialReusabilityConsentGiven =
|
|
722
698
|
credentialReusabilityConsentGiven;
|
|
723
699
|
});
|
|
724
700
|
if (usesConsentsFlow(this.state.activeVendor)) {
|
|
725
701
|
await __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_startConsentsSession).call(this, {
|
|
726
|
-
|
|
727
|
-
|
|
702
|
+
sumsubTncSigned,
|
|
703
|
+
idosTncSigned,
|
|
728
704
|
credentialReusabilityConsentGiven,
|
|
729
705
|
});
|
|
730
706
|
return;
|
|
@@ -736,12 +712,7 @@ export class KycController extends BaseController {
|
|
|
736
712
|
*/
|
|
737
713
|
clearSavedTerms() {
|
|
738
714
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
|
|
739
|
-
|
|
740
|
-
getDefaultKycVendorDisclaimersAccepted();
|
|
741
|
-
state.providerDisclaimersAccepted =
|
|
742
|
-
getDefaultKycProviderDisclaimersAccepted();
|
|
743
|
-
state.idosDisclaimersAccepted = null;
|
|
744
|
-
state.credentialReusabilityConsentGiven = null;
|
|
715
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_clearAcceptedTerms).call(this, state);
|
|
745
716
|
});
|
|
746
717
|
}
|
|
747
718
|
/**
|
|
@@ -755,7 +726,68 @@ export class KycController extends BaseController {
|
|
|
755
726
|
* @returns An object whose optional `reply` should be posted back.
|
|
756
727
|
*/
|
|
757
728
|
async handleFrameMessage(params) {
|
|
758
|
-
|
|
729
|
+
const payload = params.message;
|
|
730
|
+
if (!payload) {
|
|
731
|
+
return {};
|
|
732
|
+
}
|
|
733
|
+
if (payload.kind === 'handshake') {
|
|
734
|
+
const channelId = payload.meta?.channelId;
|
|
735
|
+
return { reply: { version: 2, meta: { channelId }, kind: 'ack' } };
|
|
736
|
+
}
|
|
737
|
+
if (payload.kind !== 'complete') {
|
|
738
|
+
return {};
|
|
739
|
+
}
|
|
740
|
+
const channelId = payload.meta?.channelId;
|
|
741
|
+
// Only honor a Check/Auth `complete` for the MoonPay frame the flow is
|
|
742
|
+
// currently waiting on. This drops stale or duplicate messages — e.g. a
|
|
743
|
+
// late post after `reset()` (phase `idle`), after the flow already
|
|
744
|
+
// advanced past this frame, or after a vendor switch — so they cannot
|
|
745
|
+
// resurrect tokens, rewind `phase`, or recapture `moonpayCustomerId` on a
|
|
746
|
+
// controller that has moved on. Frame messages are external input and,
|
|
747
|
+
// unlike the async steps, are not covered by the `#generation` guard.
|
|
748
|
+
let expectedPhase = null;
|
|
749
|
+
if (channelId === CHANNEL_CHECK) {
|
|
750
|
+
expectedPhase = 'check';
|
|
751
|
+
}
|
|
752
|
+
else if (channelId === CHANNEL_AUTH) {
|
|
753
|
+
expectedPhase = 'auth';
|
|
754
|
+
}
|
|
755
|
+
if (!expectedPhase ||
|
|
756
|
+
this.state.phase !== expectedPhase ||
|
|
757
|
+
this.state.activeVendor !== 'moonpay') {
|
|
758
|
+
return {};
|
|
759
|
+
}
|
|
760
|
+
const status = payload.payload?.status;
|
|
761
|
+
const credsEnvelope = payload.payload?.credentials;
|
|
762
|
+
const customerId = payload.payload?.customer?.id ?? null;
|
|
763
|
+
if (customerId) {
|
|
764
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
|
|
765
|
+
state.moonpayCustomerId = customerId;
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
if (!status) {
|
|
769
|
+
return {};
|
|
770
|
+
}
|
|
771
|
+
let accessToken;
|
|
772
|
+
let clientToken;
|
|
773
|
+
if (credsEnvelope) {
|
|
774
|
+
try {
|
|
775
|
+
const { credentials } = decryptCredentials(credsEnvelope, __classPrivateFieldGet(this, _KycController_keypair, "f").privateKey);
|
|
776
|
+
accessToken = credentials.accessToken;
|
|
777
|
+
clientToken = credentials.clientToken;
|
|
778
|
+
}
|
|
779
|
+
catch (error) {
|
|
780
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, `Failed to decrypt frame credentials: ${String(error)}`);
|
|
781
|
+
return {};
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
if (channelId === CHANNEL_CHECK) {
|
|
785
|
+
await __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_handleCheckOutcome).call(this, status, accessToken, clientToken);
|
|
786
|
+
return {};
|
|
787
|
+
}
|
|
788
|
+
// channelId === CHANNEL_AUTH, guaranteed by the expectedPhase guard above.
|
|
789
|
+
await __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_handleAuthOutcome).call(this, status, accessToken);
|
|
790
|
+
return {};
|
|
759
791
|
}
|
|
760
792
|
/**
|
|
761
793
|
* Builds the Check-frame URL, or `null` when no session exists yet.
|
|
@@ -763,7 +795,15 @@ export class KycController extends BaseController {
|
|
|
763
795
|
* @returns The Check-frame URL or `null`.
|
|
764
796
|
*/
|
|
765
797
|
buildCheckFrameUrl() {
|
|
766
|
-
|
|
798
|
+
if (this.state.activeVendor !== 'moonpay' || !this.state.sessionToken) {
|
|
799
|
+
return null;
|
|
800
|
+
}
|
|
801
|
+
const url = new URL(`${FRAMES_BASE_URL}/check-connection`);
|
|
802
|
+
url.searchParams.set('sessionToken', this.state.sessionToken);
|
|
803
|
+
url.searchParams.set('publicKey', __classPrivateFieldGet(this, _KycController_keypair, "f").publicKeyHex);
|
|
804
|
+
url.searchParams.set('channelId', CHANNEL_CHECK);
|
|
805
|
+
url.searchParams.set('skipKyc', 'true');
|
|
806
|
+
return url.toString();
|
|
767
807
|
}
|
|
768
808
|
/**
|
|
769
809
|
* Builds the Auth-frame URL, or `null` when no client token is available.
|
|
@@ -771,7 +811,14 @@ export class KycController extends BaseController {
|
|
|
771
811
|
* @returns The Auth-frame URL or `null`.
|
|
772
812
|
*/
|
|
773
813
|
buildAuthFrameUrl() {
|
|
774
|
-
|
|
814
|
+
if (this.state.activeVendor !== 'moonpay' || !__classPrivateFieldGet(this, _KycController_authClientToken, "f")) {
|
|
815
|
+
return null;
|
|
816
|
+
}
|
|
817
|
+
const url = new URL(`${FRAMES_BASE_URL}/auth`);
|
|
818
|
+
url.searchParams.set('clientToken', __classPrivateFieldGet(this, _KycController_authClientToken, "f"));
|
|
819
|
+
url.searchParams.set('publicKey', __classPrivateFieldGet(this, _KycController_keypair, "f").publicKeyHex);
|
|
820
|
+
url.searchParams.set('channelId', CHANNEL_AUTH);
|
|
821
|
+
return url.toString();
|
|
775
822
|
}
|
|
776
823
|
/**
|
|
777
824
|
* Builds the Reset-frame URL.
|
|
@@ -779,7 +826,9 @@ export class KycController extends BaseController {
|
|
|
779
826
|
* @returns The Reset-frame URL.
|
|
780
827
|
*/
|
|
781
828
|
buildResetFrameUrl() {
|
|
782
|
-
|
|
829
|
+
const url = new URL(`${FRAMES_BASE_URL}/reset`);
|
|
830
|
+
url.searchParams.set('channelId', CHANNEL_RESET);
|
|
831
|
+
return url.toString();
|
|
783
832
|
}
|
|
784
833
|
/**
|
|
785
834
|
* Checks whether KYC is required for a product and caches the result.
|
|
@@ -790,9 +839,9 @@ export class KycController extends BaseController {
|
|
|
790
839
|
* @returns Whether KYC is required.
|
|
791
840
|
*/
|
|
792
841
|
async checkKycRequired(params) {
|
|
793
|
-
const {
|
|
794
|
-
if (!
|
|
795
|
-
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, 'Missing
|
|
842
|
+
const { accessToken } = this.state;
|
|
843
|
+
if (!accessToken) {
|
|
844
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, 'Missing accessToken — repeat the authentication step.');
|
|
796
845
|
return false;
|
|
797
846
|
}
|
|
798
847
|
const country = params.country ?? this.state.geoCountry;
|
|
@@ -808,11 +857,7 @@ export class KycController extends BaseController {
|
|
|
808
857
|
state.statusMessage = 'Checking KYC status...';
|
|
809
858
|
});
|
|
810
859
|
try {
|
|
811
|
-
const { kycRequired } = await this.messenger.call('KycService:checkKycRequired', {
|
|
812
|
-
accessToken: moonpayAccessToken,
|
|
813
|
-
country,
|
|
814
|
-
capabilities: [{ product: params.product }],
|
|
815
|
-
});
|
|
860
|
+
const { kycRequired } = await this.messenger.call('KycService:checkKycRequired', { accessToken, country, capabilities: [{ product: params.product }] });
|
|
816
861
|
// The flow was reset while the check was in flight; discard the result
|
|
817
862
|
// rather than resurrecting a done/cached state on an idle controller.
|
|
818
863
|
const applied = __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_updateIfCurrent).call(this, generation, (state) => {
|
|
@@ -1097,11 +1142,13 @@ export class KycController extends BaseController {
|
|
|
1097
1142
|
state.phase = 'idle';
|
|
1098
1143
|
state.statusMessage = '';
|
|
1099
1144
|
state.error = null;
|
|
1100
|
-
state.
|
|
1101
|
-
state.
|
|
1145
|
+
state.disclaimers = [];
|
|
1146
|
+
state.disclaimersError = null;
|
|
1102
1147
|
state.sessionDisclaimers = null;
|
|
1103
1148
|
state.credentialReusabilityConsentGiven = null;
|
|
1104
|
-
|
|
1149
|
+
state.sessionToken = null;
|
|
1150
|
+
state.accessToken = null;
|
|
1151
|
+
state.moonpayCustomerId = null;
|
|
1105
1152
|
state.activeVendor = 'moonpay';
|
|
1106
1153
|
state.activeProduct = null;
|
|
1107
1154
|
state.sumsub = {
|
|
@@ -1128,7 +1175,7 @@ export class KycController extends BaseController {
|
|
|
1128
1175
|
});
|
|
1129
1176
|
}
|
|
1130
1177
|
}
|
|
1131
|
-
_KycController_sumsubLauncher = new WeakMap(),
|
|
1178
|
+
_KycController_sumsubLauncher = new WeakMap(), _KycController_keypair = new WeakMap(), _KycController_authClientToken = new WeakMap(), _KycController_generation = new WeakMap(), _KycController_sessionStatusPollIntervalMs = new WeakMap(), _KycController_pollTimer = new WeakMap(), _KycController_pollToken = new WeakMap(), _KycController_userStatusPollIntervalMs = new WeakMap(), _KycController_userStatusPollTimer = new WeakMap(), _KycController_userStatusPolling = new WeakMap(), _KycController_userStatusPollToken = new WeakMap(), _KycController_instances = new WeakSet(), _KycController_localUserSecretStore = function _KycController_localUserSecretStore() {
|
|
1132
1179
|
return {
|
|
1133
1180
|
get: async (path, entropySourceId) => this.messenger.call('UserStorageController:performGetStorage', path, entropySourceId),
|
|
1134
1181
|
set: async (path, value, entropySourceId) => this.messenger.call('UserStorageController:performSetStorage', path, value, entropySourceId),
|
|
@@ -1140,14 +1187,13 @@ _KycController_sumsubLauncher = new WeakMap(), _KycController_moonPayFrames = ne
|
|
|
1140
1187
|
* SumSub — skipping MoonPay Check/Auth frames.
|
|
1141
1188
|
*
|
|
1142
1189
|
* @param consents - T&C2 flags mapped onto the session disclaimer catalog.
|
|
1143
|
-
* @param consents.
|
|
1144
|
-
* @param consents.
|
|
1190
|
+
* @param consents.sumsubTncSigned - Whether Sumsub T&C were accepted.
|
|
1191
|
+
* @param consents.idosTncSigned - Whether idOS T&C were accepted.
|
|
1145
1192
|
* @param consents.credentialReusabilityConsentGiven - Whether credential
|
|
1146
1193
|
* reuse was accepted.
|
|
1147
1194
|
*/
|
|
1148
1195
|
async function _KycController_startConsentsSession(consents) {
|
|
1149
|
-
const { email } = this.state;
|
|
1150
|
-
const acceptedDisclaimerIds = ironDisclaimerIds(this.state.vendorDisclaimersAccepted);
|
|
1196
|
+
const { email, acceptedDisclaimerIds } = this.state;
|
|
1151
1197
|
if (!email) {
|
|
1152
1198
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, 'Missing email for consents session.');
|
|
1153
1199
|
return;
|
|
@@ -1165,7 +1211,7 @@ async function _KycController_startConsentsSession(consents) {
|
|
|
1165
1211
|
state.sumsub.result = null;
|
|
1166
1212
|
state.sumsub.sessionStatus = null;
|
|
1167
1213
|
// Consents-path vendors have no MoonPay session/access tokens.
|
|
1168
|
-
|
|
1214
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_clearMoonPaySession).call(this, state);
|
|
1169
1215
|
});
|
|
1170
1216
|
try {
|
|
1171
1217
|
await this.messenger.call('KycService:submitVendorDisclaimers', {
|
|
@@ -1191,7 +1237,7 @@ async function _KycController_startConsentsSession(consents) {
|
|
|
1191
1237
|
await this.refreshKycStatus();
|
|
1192
1238
|
}
|
|
1193
1239
|
catch (statusError) {
|
|
1194
|
-
|
|
1240
|
+
console.error('KYC status refresh failed:', statusError);
|
|
1195
1241
|
}
|
|
1196
1242
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_updateIfCurrent).call(this, generation, (state) => {
|
|
1197
1243
|
state.phase = 'done';
|
|
@@ -1227,7 +1273,7 @@ async function _KycController_startConsentsSession(consents) {
|
|
|
1227
1273
|
await this.refreshKycStatus();
|
|
1228
1274
|
}
|
|
1229
1275
|
catch (statusError) {
|
|
1230
|
-
|
|
1276
|
+
console.error('KYC status refresh failed:', statusError);
|
|
1231
1277
|
}
|
|
1232
1278
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_updateIfCurrent).call(this, generation, (state) => {
|
|
1233
1279
|
if (state.phase !== 'error' && state.phase !== 'done') {
|
|
@@ -1255,7 +1301,7 @@ async function _KycController_startConsentsSession(consents) {
|
|
|
1255
1301
|
});
|
|
1256
1302
|
return;
|
|
1257
1303
|
}
|
|
1258
|
-
|
|
1304
|
+
console.error('Consents session failed:', error);
|
|
1259
1305
|
if (__classPrivateFieldGet(this, _KycController_generation, "f") !== generation) {
|
|
1260
1306
|
return;
|
|
1261
1307
|
}
|
|
@@ -1282,8 +1328,8 @@ async function _KycController_startConsentsSession(consents) {
|
|
|
1282
1328
|
*
|
|
1283
1329
|
* @param sessionId - The UKYC session id.
|
|
1284
1330
|
* @param consents - T&C2 flags mapped onto catalog documents.
|
|
1285
|
-
* @param consents.
|
|
1286
|
-
* @param consents.
|
|
1331
|
+
* @param consents.sumsubTncSigned - Whether Sumsub T&C were accepted.
|
|
1332
|
+
* @param consents.idosTncSigned - Whether idOS T&C were accepted.
|
|
1287
1333
|
* @param consents.credentialReusabilityConsentGiven - Whether credential
|
|
1288
1334
|
* reuse was accepted.
|
|
1289
1335
|
* @param generation - Flow generation captured by the caller.
|
|
@@ -1297,12 +1343,12 @@ async function _KycController_recordSessionDisclaimers(sessionId, consents, gene
|
|
|
1297
1343
|
state.sessionDisclaimers = catalog;
|
|
1298
1344
|
state.statusMessage = 'Submitting consents...';
|
|
1299
1345
|
});
|
|
1300
|
-
if (isAcceptedCategoryEmpty(catalog.idOS, consents.
|
|
1301
|
-
isAcceptedCategoryEmpty(catalog.kycProvider, consents.
|
|
1346
|
+
if (isAcceptedCategoryEmpty(catalog.idOS, consents.idosTncSigned) ||
|
|
1347
|
+
isAcceptedCategoryEmpty(catalog.kycProvider, consents.sumsubTncSigned)) {
|
|
1302
1348
|
throw new Error('Session disclaimer catalog is missing documents for an accepted category.');
|
|
1303
1349
|
}
|
|
1304
|
-
const idOS =
|
|
1305
|
-
const kycProvider =
|
|
1350
|
+
const idOS = consentRecordsFromCatalog(catalog.idOS, consents.idosTncSigned);
|
|
1351
|
+
const kycProvider = consentRecordsFromCatalog(catalog.kycProvider, consents.sumsubTncSigned);
|
|
1306
1352
|
const reuseUnchanged = catalog.credentialReusabilityConsentGiven ===
|
|
1307
1353
|
consents.credentialReusabilityConsentGiven;
|
|
1308
1354
|
if (idOS.length === 0 && kycProvider.length === 0 && reuseUnchanged) {
|
|
@@ -1333,9 +1379,8 @@ async function _KycController_recordSessionDisclaimers(sessionId, consents, gene
|
|
|
1333
1379
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
|
|
1334
1380
|
state.sessionDisclaimers = latest;
|
|
1335
1381
|
});
|
|
1336
|
-
|
|
1337
|
-
const
|
|
1338
|
-
const stillMissingProvider = acceptedCategoryStillMissing(latest.kycProvider, consents.providerDisclaimersAccepted);
|
|
1382
|
+
const stillMissingIdos = acceptedCategoryStillMissing(latest.idOS, consents.idosTncSigned);
|
|
1383
|
+
const stillMissingProvider = acceptedCategoryStillMissing(latest.kycProvider, consents.sumsubTncSigned);
|
|
1339
1384
|
const stillMissingReuse = consents.credentialReusabilityConsentGiven &&
|
|
1340
1385
|
!latest.credentialReusabilityConsentGiven;
|
|
1341
1386
|
if (stillMissingIdos || stillMissingProvider || stillMissingReuse) {
|
|
@@ -1347,9 +1392,7 @@ async function _KycController_recordSessionDisclaimers(sessionId, consents, gene
|
|
|
1347
1392
|
* Creates a vendor session from the currently stored terms + email.
|
|
1348
1393
|
*/
|
|
1349
1394
|
async function _KycController_createSession() {
|
|
1350
|
-
const { email } = this.state;
|
|
1351
|
-
const termsAcceptedAt = this.state.vendorDisclaimersAccepted.moonpay?.termsAcceptedAt;
|
|
1352
|
-
const acceptedDisclaimerIds = this.state.vendorDisclaimers.map((disclaimer) => disclaimer.id);
|
|
1395
|
+
const { email, termsAcceptedAt, acceptedDisclaimerIds } = this.state;
|
|
1353
1396
|
if (!email) {
|
|
1354
1397
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, 'Missing email for session creation.');
|
|
1355
1398
|
return;
|
|
@@ -1364,7 +1407,7 @@ async function _KycController_createSession() {
|
|
|
1364
1407
|
// (or, on failure, invalid) session token, `buildAuthFrameUrl` cannot
|
|
1365
1408
|
// return a URL tied to an old client token, and `checkKycRequired` cannot
|
|
1366
1409
|
// run with an access token from an earlier authentication. The Check/Auth
|
|
1367
|
-
// frames re-populate these for the new session. Because `
|
|
1410
|
+
// frames re-populate these for the new session. Because `sessionToken` is
|
|
1368
1411
|
// cleared here and only re-set on success, a failed creation leaves it
|
|
1369
1412
|
// `null` rather than resurrecting the previous session.
|
|
1370
1413
|
// Capture the flow generation so a `reset()` landing while the create
|
|
@@ -1372,24 +1415,24 @@ async function _KycController_createSession() {
|
|
|
1372
1415
|
// the now-idle controller (failure). The synchronous update below runs
|
|
1373
1416
|
// before any `await`, so it needs no guard.
|
|
1374
1417
|
const generation = __classPrivateFieldGet(this, _KycController_generation, "f");
|
|
1375
|
-
|
|
1418
|
+
__classPrivateFieldSet(this, _KycController_authClientToken, null, "f");
|
|
1376
1419
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
|
|
1377
1420
|
state.error = null;
|
|
1378
1421
|
state.phase = 'session';
|
|
1379
1422
|
state.statusMessage = 'Creating session...';
|
|
1380
|
-
state.
|
|
1381
|
-
state.
|
|
1423
|
+
state.sessionToken = null;
|
|
1424
|
+
state.accessToken = null;
|
|
1382
1425
|
});
|
|
1383
1426
|
try {
|
|
1384
1427
|
const { sessionToken } = await this.messenger.call('KycService:createSession', { email, termsAcceptedAt, disclaimerIds: acceptedDisclaimerIds });
|
|
1385
1428
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_updateIfCurrent).call(this, generation, (state) => {
|
|
1386
|
-
state.
|
|
1429
|
+
state.sessionToken = sessionToken;
|
|
1387
1430
|
state.phase = 'check';
|
|
1388
1431
|
state.statusMessage = 'Authenticating via Check frame...';
|
|
1389
1432
|
});
|
|
1390
1433
|
}
|
|
1391
1434
|
catch (error) {
|
|
1392
|
-
|
|
1435
|
+
console.error('Session creation failed:', error);
|
|
1393
1436
|
// A reset() superseded this flow while the request was in flight; leave
|
|
1394
1437
|
// the idle controller alone rather than forcing it back to `terms`.
|
|
1395
1438
|
if (__classPrivateFieldGet(this, _KycController_generation, "f") !== generation) {
|
|
@@ -1409,13 +1452,82 @@ async function _KycController_createSession() {
|
|
|
1409
1452
|
});
|
|
1410
1453
|
await this.loadDisclaimers();
|
|
1411
1454
|
}
|
|
1412
|
-
}, _KycController_clearAcceptedTerms = function _KycController_clearAcceptedTerms(state
|
|
1413
|
-
|
|
1414
|
-
state.
|
|
1415
|
-
state.
|
|
1416
|
-
|
|
1417
|
-
state.
|
|
1455
|
+
}, _KycController_clearAcceptedTerms = function _KycController_clearAcceptedTerms(state) {
|
|
1456
|
+
state.termsAcceptedAt = null;
|
|
1457
|
+
state.acceptedDisclaimerIds = [];
|
|
1458
|
+
state.termsAcceptedVendor = null;
|
|
1459
|
+
state.sumsubTncAccepted = null;
|
|
1460
|
+
state.idosTncAccepted = null;
|
|
1418
1461
|
state.credentialReusabilityConsentGiven = null;
|
|
1462
|
+
}, _KycController_clearMoonPaySession = function _KycController_clearMoonPaySession(state) {
|
|
1463
|
+
state.moonpayCustomerId = null;
|
|
1464
|
+
state.sessionToken = null;
|
|
1465
|
+
state.accessToken = null;
|
|
1466
|
+
}, _KycController_dropTermsUnlessForVendor = function _KycController_dropTermsUnlessForVendor(vendor) {
|
|
1467
|
+
if (__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_hasTermsForVendor).call(this, vendor)) {
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1470
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
|
|
1471
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_clearAcceptedTerms).call(this, state);
|
|
1472
|
+
});
|
|
1473
|
+
}, _KycController_hasTermsForVendor = function _KycController_hasTermsForVendor(vendor) {
|
|
1474
|
+
if (this.state.termsAcceptedVendor === null) {
|
|
1475
|
+
return false;
|
|
1476
|
+
}
|
|
1477
|
+
return this.state.termsAcceptedVendor === vendor;
|
|
1478
|
+
}, _KycController_handleCheckOutcome =
|
|
1479
|
+
/**
|
|
1480
|
+
* Applies a Check-frame outcome.
|
|
1481
|
+
*
|
|
1482
|
+
* @param status - The frame status.
|
|
1483
|
+
* @param accessToken - The decrypted access token, if any.
|
|
1484
|
+
* @param clientToken - The decrypted client token, if any.
|
|
1485
|
+
*/
|
|
1486
|
+
async function _KycController_handleCheckOutcome(status, accessToken, clientToken) {
|
|
1487
|
+
if (status === 'active' && accessToken) {
|
|
1488
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
|
|
1489
|
+
state.accessToken = accessToken;
|
|
1490
|
+
state.phase = 'form';
|
|
1491
|
+
state.statusMessage = 'Already authenticated. Review to submit.';
|
|
1492
|
+
});
|
|
1493
|
+
await __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_continueAfterAuthentication).call(this);
|
|
1494
|
+
return;
|
|
1495
|
+
}
|
|
1496
|
+
if (status === 'connectionRequired' && clientToken) {
|
|
1497
|
+
__classPrivateFieldSet(this, _KycController_authClientToken, clientToken, "f");
|
|
1498
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
|
|
1499
|
+
state.phase = 'auth';
|
|
1500
|
+
state.statusMessage = 'Verify your email via OTP in the Auth frame.';
|
|
1501
|
+
});
|
|
1502
|
+
return;
|
|
1503
|
+
}
|
|
1504
|
+
if (status === 'termsAcceptanceRequired') {
|
|
1505
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_requireTermsReacceptance).call(this);
|
|
1506
|
+
return;
|
|
1507
|
+
}
|
|
1508
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, `Check frame returned status: ${status}`);
|
|
1509
|
+
}, _KycController_handleAuthOutcome =
|
|
1510
|
+
/**
|
|
1511
|
+
* Applies an Auth-frame outcome.
|
|
1512
|
+
*
|
|
1513
|
+
* @param status - The frame status.
|
|
1514
|
+
* @param accessToken - The decrypted access token, if any.
|
|
1515
|
+
*/
|
|
1516
|
+
async function _KycController_handleAuthOutcome(status, accessToken) {
|
|
1517
|
+
if (status === 'active' && accessToken) {
|
|
1518
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_applyUpdate).call(this, (state) => {
|
|
1519
|
+
state.accessToken = accessToken;
|
|
1520
|
+
state.phase = 'form';
|
|
1521
|
+
state.statusMessage = 'Authenticated. Review to submit.';
|
|
1522
|
+
});
|
|
1523
|
+
await __classPrivateFieldGet(this, _KycController_instances, "m", _KycController_continueAfterAuthentication).call(this);
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
if (status === 'termsAcceptanceRequired') {
|
|
1527
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_requireTermsReacceptance).call(this);
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_fail).call(this, `Auth frame returned status: ${status}`);
|
|
1419
1531
|
}, _KycController_continueAfterAuthentication =
|
|
1420
1532
|
/**
|
|
1421
1533
|
* Continues the flow once authentication has completed (phase `form`).
|
|
@@ -1467,7 +1579,7 @@ async function _KycController_continueAfterAuthentication() {
|
|
|
1467
1579
|
return {
|
|
1468
1580
|
vendor: 'moonpay',
|
|
1469
1581
|
vendorMetadata: {
|
|
1470
|
-
moonPayAccessToken: this.state.
|
|
1582
|
+
moonPayAccessToken: this.state.accessToken,
|
|
1471
1583
|
moonPayUserId: this.state.moonpayCustomerId,
|
|
1472
1584
|
},
|
|
1473
1585
|
};
|
|
@@ -1535,8 +1647,7 @@ async function _KycController_createUkycSession(generation) {
|
|
|
1535
1647
|
// authorizes later storage reads without granting write or delete access.
|
|
1536
1648
|
const ukycCapabilityToken = signStorageAccessToken({
|
|
1537
1649
|
material: clientMaterial,
|
|
1538
|
-
|
|
1539
|
-
operations: ['read', 'write'],
|
|
1650
|
+
operations: ['read'],
|
|
1540
1651
|
expiresAt: new Date(Date.now() + UKYC_CAPABILITY_TOKEN_TTL_MS),
|
|
1541
1652
|
});
|
|
1542
1653
|
const wrappedUkycCapabilityToken = wrapEncryptionKey(sessionClientPrivateKey, capabilityTokenSchema.serverPublicKey.x, stringToBytes(encodeStorageAccessTokenForHeader(ukycCapabilityToken)));
|
|
@@ -1723,7 +1834,7 @@ async function _KycController_pollSessionStatusOnce(sessionId, token) {
|
|
|
1723
1834
|
__classPrivateFieldSet(this, _KycController_pollTimer, null, "f");
|
|
1724
1835
|
}
|
|
1725
1836
|
}, _KycController_cancelPendingSession = function _KycController_cancelPendingSession() {
|
|
1726
|
-
|
|
1837
|
+
__classPrivateFieldSet(this, _KycController_authClientToken, null, "f");
|
|
1727
1838
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_stopPolling).call(this);
|
|
1728
1839
|
__classPrivateFieldGet(this, _KycController_instances, "m", _KycController_stopUserStatusPolling).call(this);
|
|
1729
1840
|
__classPrivateFieldSet(this, _KycController_generation, __classPrivateFieldGet(this, _KycController_generation, "f") + 1, "f");
|