@metamask-previews/kyc-controller 0.0.0-preview-8bfa290fb → 0.2.0-preview-0a30e47

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.
Files changed (203) hide show
  1. package/CHANGELOG.md +30 -49
  2. package/dist/{KycController-method-action-types.d.mts → KycController-method-action-types.d.ts} +35 -7
  3. package/dist/KycController-method-action-types.d.ts.map +1 -0
  4. package/dist/{KycController-method-action-types.mjs → KycController-method-action-types.js} +1 -1
  5. package/dist/KycController-method-action-types.js.map +1 -0
  6. package/dist/{KycController.d.mts → KycController.d.ts} +87 -45
  7. package/dist/KycController.d.ts.map +1 -0
  8. package/dist/KycController.js +1991 -0
  9. package/dist/KycController.js.map +1 -0
  10. package/dist/{KycService-method-action-types.d.mts → KycService-method-action-types.d.ts} +16 -16
  11. package/dist/KycService-method-action-types.d.ts.map +1 -0
  12. package/dist/{KycService-method-action-types.mjs → KycService-method-action-types.js} +1 -1
  13. package/dist/KycService-method-action-types.js.map +1 -0
  14. package/dist/{KycService.d.mts → KycService.d.ts} +23 -23
  15. package/dist/KycService.d.ts.map +1 -0
  16. package/dist/{KycService.mjs → KycService.js} +194 -185
  17. package/dist/KycService.js.map +1 -0
  18. package/dist/{countryCodes.d.cts → countryCodes.d.ts} +1 -1
  19. package/dist/countryCodes.d.ts.map +1 -0
  20. package/dist/{countryCodes.mjs → countryCodes.js} +1 -1
  21. package/dist/countryCodes.js.map +1 -0
  22. package/dist/{crypto.d.mts → crypto.d.ts} +1 -1
  23. package/dist/crypto.d.ts.map +1 -0
  24. package/dist/{crypto.mjs → crypto.js} +7 -7
  25. package/dist/crypto.js.map +1 -0
  26. package/dist/{encoding.d.mts → encoding.d.ts} +1 -1
  27. package/dist/encoding.d.ts.map +1 -0
  28. package/dist/{encoding.mjs → encoding.js} +2 -2
  29. package/dist/encoding.js.map +1 -0
  30. package/dist/index.d.ts +19 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +12 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/{logger.d.cts → logger.d.ts} +2 -3
  35. package/dist/logger.d.ts.map +1 -0
  36. package/dist/{logger.mjs → logger.js} +2 -2
  37. package/dist/logger.js.map +1 -0
  38. package/dist/{selectors.d.mts → selectors.d.ts} +4 -4
  39. package/dist/selectors.d.ts.map +1 -0
  40. package/dist/{selectors.mjs → selectors.js} +2 -2
  41. package/dist/selectors.js.map +1 -0
  42. package/dist/{types.d.cts → types.d.ts} +72 -13
  43. package/dist/types.d.ts.map +1 -0
  44. package/dist/{types.mjs → types.js} +1 -1
  45. package/dist/types.js.map +1 -0
  46. package/dist/ukyc/{constants.d.mts → constants.d.ts} +9 -9
  47. package/dist/ukyc/constants.d.ts.map +1 -0
  48. package/dist/ukyc/{constants.mjs → constants.js} +1 -1
  49. package/dist/ukyc/constants.js.map +1 -0
  50. package/dist/ukyc/{deriveClientMaterial.d.cts → deriveClientMaterial.d.ts} +1 -1
  51. package/dist/ukyc/deriveClientMaterial.d.ts.map +1 -0
  52. package/dist/ukyc/{deriveClientMaterial.mjs → deriveClientMaterial.js} +7 -7
  53. package/dist/ukyc/deriveClientMaterial.js.map +1 -0
  54. package/dist/ukyc/{jwtChain.d.mts → jwtChain.d.ts} +1 -1
  55. package/dist/ukyc/jwtChain.d.ts.map +1 -0
  56. package/dist/ukyc/{jwtChain.mjs → jwtChain.js} +4 -4
  57. package/dist/ukyc/jwtChain.js.map +1 -0
  58. package/dist/ukyc/{localUserSecret.d.mts → localUserSecret.d.ts} +1 -1
  59. package/dist/ukyc/localUserSecret.d.ts.map +1 -0
  60. package/dist/ukyc/{localUserSecret.mjs → localUserSecret.js} +4 -4
  61. package/dist/ukyc/localUserSecret.js.map +1 -0
  62. package/dist/ukyc/{storageAccessToken.d.mts → storageAccessToken.d.ts} +2 -2
  63. package/dist/ukyc/storageAccessToken.d.ts.map +1 -0
  64. package/dist/ukyc/{storageAccessToken.mjs → storageAccessToken.js} +5 -5
  65. package/dist/ukyc/storageAccessToken.js.map +1 -0
  66. package/dist/ukyc/{testToken.d.mts → testToken.d.ts} +2 -2
  67. package/dist/ukyc/testToken.d.ts.map +1 -0
  68. package/dist/ukyc/{testToken.mjs → testToken.js} +5 -5
  69. package/dist/ukyc/testToken.js.map +1 -0
  70. package/dist/ukyc/{wrapEncryptionKey.d.mts → wrapEncryptionKey.d.ts} +1 -1
  71. package/dist/ukyc/wrapEncryptionKey.d.ts.map +1 -0
  72. package/dist/ukyc/{wrapEncryptionKey.mjs → wrapEncryptionKey.js} +3 -4
  73. package/dist/ukyc/wrapEncryptionKey.js.map +1 -0
  74. package/dist/ukyc/{wrappedRelayPayload.d.mts → wrappedRelayPayload.d.ts} +3 -3
  75. package/dist/ukyc/wrappedRelayPayload.d.ts.map +1 -0
  76. package/dist/ukyc/{wrappedRelayPayload.mjs → wrappedRelayPayload.js} +2 -2
  77. package/dist/ukyc/wrappedRelayPayload.js.map +1 -0
  78. package/dist/vendorDisclaimerAcceptance.d.ts +39 -0
  79. package/dist/vendorDisclaimerAcceptance.d.ts.map +1 -0
  80. package/dist/vendorDisclaimerAcceptance.js +67 -0
  81. package/dist/vendorDisclaimerAcceptance.js.map +1 -0
  82. package/dist/vendors/MoonPayFrameHandler.d.ts +74 -0
  83. package/dist/vendors/MoonPayFrameHandler.d.ts.map +1 -0
  84. package/dist/vendors/MoonPayFrameHandler.js +218 -0
  85. package/dist/vendors/MoonPayFrameHandler.js.map +1 -0
  86. package/package.json +19 -23
  87. package/dist/KycController-method-action-types.cjs +0 -7
  88. package/dist/KycController-method-action-types.cjs.map +0 -1
  89. package/dist/KycController-method-action-types.d.cts +0 -239
  90. package/dist/KycController-method-action-types.d.cts.map +0 -1
  91. package/dist/KycController-method-action-types.d.mts.map +0 -1
  92. package/dist/KycController-method-action-types.mjs.map +0 -1
  93. package/dist/KycController.cjs +0 -1882
  94. package/dist/KycController.cjs.map +0 -1
  95. package/dist/KycController.d.cts +0 -395
  96. package/dist/KycController.d.cts.map +0 -1
  97. package/dist/KycController.d.mts.map +0 -1
  98. package/dist/KycController.mjs +0 -1877
  99. package/dist/KycController.mjs.map +0 -1
  100. package/dist/KycService-method-action-types.cjs +0 -7
  101. package/dist/KycService-method-action-types.cjs.map +0 -1
  102. package/dist/KycService-method-action-types.d.cts +0 -220
  103. package/dist/KycService-method-action-types.d.cts.map +0 -1
  104. package/dist/KycService-method-action-types.d.mts.map +0 -1
  105. package/dist/KycService-method-action-types.mjs.map +0 -1
  106. package/dist/KycService.cjs +0 -637
  107. package/dist/KycService.cjs.map +0 -1
  108. package/dist/KycService.d.cts +0 -552
  109. package/dist/KycService.d.cts.map +0 -1
  110. package/dist/KycService.d.mts.map +0 -1
  111. package/dist/KycService.mjs.map +0 -1
  112. package/dist/countryCodes.cjs +0 -274
  113. package/dist/countryCodes.cjs.map +0 -1
  114. package/dist/countryCodes.d.cts.map +0 -1
  115. package/dist/countryCodes.d.mts +0 -18
  116. package/dist/countryCodes.d.mts.map +0 -1
  117. package/dist/countryCodes.mjs.map +0 -1
  118. package/dist/crypto.cjs +0 -154
  119. package/dist/crypto.cjs.map +0 -1
  120. package/dist/crypto.d.cts +0 -84
  121. package/dist/crypto.d.cts.map +0 -1
  122. package/dist/crypto.d.mts.map +0 -1
  123. package/dist/crypto.mjs.map +0 -1
  124. package/dist/encoding.cjs +0 -40
  125. package/dist/encoding.cjs.map +0 -1
  126. package/dist/encoding.d.cts +0 -24
  127. package/dist/encoding.d.cts.map +0 -1
  128. package/dist/encoding.d.mts.map +0 -1
  129. package/dist/encoding.mjs.map +0 -1
  130. package/dist/index.cjs +0 -37
  131. package/dist/index.cjs.map +0 -1
  132. package/dist/index.d.cts +0 -19
  133. package/dist/index.d.cts.map +0 -1
  134. package/dist/index.d.mts +0 -19
  135. package/dist/index.d.mts.map +0 -1
  136. package/dist/index.mjs +0 -12
  137. package/dist/index.mjs.map +0 -1
  138. package/dist/logger.cjs +0 -9
  139. package/dist/logger.cjs.map +0 -1
  140. package/dist/logger.d.cts.map +0 -1
  141. package/dist/logger.d.mts +0 -6
  142. package/dist/logger.d.mts.map +0 -1
  143. package/dist/logger.mjs.map +0 -1
  144. package/dist/selectors.cjs +0 -30
  145. package/dist/selectors.cjs.map +0 -1
  146. package/dist/selectors.d.cts +0 -24
  147. package/dist/selectors.d.cts.map +0 -1
  148. package/dist/selectors.d.mts.map +0 -1
  149. package/dist/selectors.mjs.map +0 -1
  150. package/dist/types.cjs +0 -10
  151. package/dist/types.cjs.map +0 -1
  152. package/dist/types.d.cts.map +0 -1
  153. package/dist/types.d.mts +0 -217
  154. package/dist/types.d.mts.map +0 -1
  155. package/dist/types.mjs.map +0 -1
  156. package/dist/ukyc/constants.cjs +0 -75
  157. package/dist/ukyc/constants.cjs.map +0 -1
  158. package/dist/ukyc/constants.d.cts +0 -69
  159. package/dist/ukyc/constants.d.cts.map +0 -1
  160. package/dist/ukyc/constants.d.mts.map +0 -1
  161. package/dist/ukyc/constants.mjs.map +0 -1
  162. package/dist/ukyc/deriveClientMaterial.cjs +0 -65
  163. package/dist/ukyc/deriveClientMaterial.cjs.map +0 -1
  164. package/dist/ukyc/deriveClientMaterial.d.cts.map +0 -1
  165. package/dist/ukyc/deriveClientMaterial.d.mts +0 -54
  166. package/dist/ukyc/deriveClientMaterial.d.mts.map +0 -1
  167. package/dist/ukyc/deriveClientMaterial.mjs.map +0 -1
  168. package/dist/ukyc/jwtChain.cjs +0 -54
  169. package/dist/ukyc/jwtChain.cjs.map +0 -1
  170. package/dist/ukyc/jwtChain.d.cts +0 -40
  171. package/dist/ukyc/jwtChain.d.cts.map +0 -1
  172. package/dist/ukyc/jwtChain.d.mts.map +0 -1
  173. package/dist/ukyc/jwtChain.mjs.map +0 -1
  174. package/dist/ukyc/localUserSecret.cjs +0 -98
  175. package/dist/ukyc/localUserSecret.cjs.map +0 -1
  176. package/dist/ukyc/localUserSecret.d.cts +0 -65
  177. package/dist/ukyc/localUserSecret.d.cts.map +0 -1
  178. package/dist/ukyc/localUserSecret.d.mts.map +0 -1
  179. package/dist/ukyc/localUserSecret.mjs.map +0 -1
  180. package/dist/ukyc/storageAccessToken.cjs +0 -139
  181. package/dist/ukyc/storageAccessToken.cjs.map +0 -1
  182. package/dist/ukyc/storageAccessToken.d.cts +0 -99
  183. package/dist/ukyc/storageAccessToken.d.cts.map +0 -1
  184. package/dist/ukyc/storageAccessToken.d.mts.map +0 -1
  185. package/dist/ukyc/storageAccessToken.mjs.map +0 -1
  186. package/dist/ukyc/testToken.cjs +0 -61
  187. package/dist/ukyc/testToken.cjs.map +0 -1
  188. package/dist/ukyc/testToken.d.cts +0 -50
  189. package/dist/ukyc/testToken.d.cts.map +0 -1
  190. package/dist/ukyc/testToken.d.mts.map +0 -1
  191. package/dist/ukyc/testToken.mjs.map +0 -1
  192. package/dist/ukyc/wrapEncryptionKey.cjs +0 -31
  193. package/dist/ukyc/wrapEncryptionKey.cjs.map +0 -1
  194. package/dist/ukyc/wrapEncryptionKey.d.cts +0 -36
  195. package/dist/ukyc/wrapEncryptionKey.d.cts.map +0 -1
  196. package/dist/ukyc/wrapEncryptionKey.d.mts.map +0 -1
  197. package/dist/ukyc/wrapEncryptionKey.mjs.map +0 -1
  198. package/dist/ukyc/wrappedRelayPayload.cjs +0 -32
  199. package/dist/ukyc/wrappedRelayPayload.cjs.map +0 -1
  200. package/dist/ukyc/wrappedRelayPayload.d.cts +0 -35
  201. package/dist/ukyc/wrappedRelayPayload.d.cts.map +0 -1
  202. package/dist/ukyc/wrappedRelayPayload.d.mts.map +0 -1
  203. package/dist/ukyc/wrappedRelayPayload.mjs.map +0 -1
@@ -0,0 +1,74 @@
1
+ import type { KycPhase, KycVendor } from '../types.js';
2
+ type MoonPayFrameState = {
3
+ activeVendor: KycVendor;
4
+ moonpayAccessToken: string | null;
5
+ moonpayCustomerId: string | null;
6
+ moonpaySessionToken: string | null;
7
+ phase: KycPhase;
8
+ statusMessage: string;
9
+ };
10
+ export type MoonPayFrameHandlerOptions = {
11
+ getState: () => MoonPayFrameState;
12
+ update: (updater: (state: MoonPayFrameState) => void) => void;
13
+ fail: (message: string) => void;
14
+ onAuthenticated: () => Promise<void>;
15
+ requireTermsReacceptance: () => void;
16
+ };
17
+ /**
18
+ * Owns MoonPay Check/Auth frame state and protocol handling.
19
+ */
20
+ export declare class MoonPayFrameHandler {
21
+ #private;
22
+ constructor({ getState, update, fail, onAuthenticated, requireTermsReacceptance, }: MoonPayFrameHandlerOptions);
23
+ /**
24
+ * Creates a fresh keypair for a new MoonPay flow.
25
+ */
26
+ startFlow(): void;
27
+ /**
28
+ * Ensures an in-progress MoonPay flow has a frame keypair.
29
+ */
30
+ ensureKeypair(): void;
31
+ /**
32
+ * Clears all non-persisted MoonPay frame artifacts.
33
+ */
34
+ clear(): void;
35
+ /**
36
+ * Clears authentication associated with an earlier MoonPay session.
37
+ */
38
+ clearAuthentication(): void;
39
+ /**
40
+ * Handles a message posted by a MoonPay Check/Auth frame.
41
+ *
42
+ * @param message - The raw message posted by the frame.
43
+ * @returns An object whose optional `reply` should be posted back.
44
+ */
45
+ handleMessage(message: unknown): Promise<{
46
+ reply?: unknown;
47
+ }>;
48
+ /**
49
+ * Builds the Check-frame URL, or `null` when no session exists yet.
50
+ *
51
+ * @returns The Check-frame URL or `null`.
52
+ */
53
+ buildCheckFrameUrl(): string | null;
54
+ /**
55
+ * Builds the Auth-frame URL, or `null` when no client token is available.
56
+ *
57
+ * @returns The Auth-frame URL or `null`.
58
+ */
59
+ buildAuthFrameUrl(): string | null;
60
+ /**
61
+ * Builds the Reset-frame URL.
62
+ *
63
+ * @returns The Reset-frame URL.
64
+ */
65
+ buildResetFrameUrl(): string;
66
+ }
67
+ /**
68
+ * Drops persisted-in-memory MoonPay session artifacts from controller state.
69
+ *
70
+ * @param state - The state to mutate.
71
+ */
72
+ export declare function clearMoonPaySession(state: MoonPayFrameState): void;
73
+ export {};
74
+ //# sourceMappingURL=MoonPayFrameHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MoonPayFrameHandler.d.ts","sourceRoot":"","sources":["../../src/vendors/MoonPayFrameHandler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAOvD,KAAK,iBAAiB,GAAG;IACvB,YAAY,EAAE,SAAS,CAAC;IACxB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,KAAK,EAAE,QAAQ,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAoBF,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,MAAM,iBAAiB,CAAC;IAClC,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,KAAK,IAAI,CAAC;IAC9D,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,wBAAwB,EAAE,MAAM,IAAI,CAAC;CACtC,CAAC;AAEF;;GAEG;AACH,qBAAa,mBAAmB;;IAiB9B,YAAY,EACV,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,eAAe,EACf,wBAAwB,GACzB,EAAE,0BAA0B,EAM5B;IAED;;OAEG;IACH,SAAS,IAAI,IAAI,CAEhB;IAED;;OAEG;IACH,aAAa,IAAI,IAAI,CAEpB;IAED;;OAEG;IACH,KAAK,IAAI,IAAI,CAGZ;IAED;;OAEG;IACH,mBAAmB,IAAI,IAAI,CAE1B;IAED;;;;;OAKG;IACG,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CA2ElE;IAED;;;;OAIG;IACH,kBAAkB,IAAI,MAAM,GAAG,IAAI,CAelC;IAED;;;;OAIG;IACH,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAcjC;IAED;;;;OAIG;IACH,kBAAkB,IAAI,MAAM,CAI3B;CAkDF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAIlE"}
@@ -0,0 +1,218 @@
1
+ import { decryptCredentials, generateKeyPair } from '../crypto.js';
2
+ const FRAMES_BASE_URL = 'https://blocks.moonpay.com/platform/v1';
3
+ const CHANNEL_CHECK = 'ch_1';
4
+ const CHANNEL_AUTH = 'ch_2';
5
+ const CHANNEL_RESET = 'ch_reset';
6
+ /**
7
+ * Owns MoonPay Check/Auth frame state and protocol handling.
8
+ */
9
+ export class MoonPayFrameHandler {
10
+ #getState;
11
+ #update;
12
+ #fail;
13
+ #onAuthenticated;
14
+ #requireTermsReacceptance;
15
+ /** MoonPay Check/Auth frame X25519 keypair (never persisted). */
16
+ #frameKeypair = null;
17
+ /** Auth-frame client token, kept out of controller state. */
18
+ #authClientToken = null;
19
+ constructor({ getState, update, fail, onAuthenticated, requireTermsReacceptance, }) {
20
+ this.#getState = getState;
21
+ this.#update = update;
22
+ this.#fail = fail;
23
+ this.#onAuthenticated = onAuthenticated;
24
+ this.#requireTermsReacceptance = requireTermsReacceptance;
25
+ }
26
+ /**
27
+ * Creates a fresh keypair for a new MoonPay flow.
28
+ */
29
+ startFlow() {
30
+ this.#frameKeypair = generateKeyPair();
31
+ }
32
+ /**
33
+ * Ensures an in-progress MoonPay flow has a frame keypair.
34
+ */
35
+ ensureKeypair() {
36
+ this.#frameKeypair ??= generateKeyPair();
37
+ }
38
+ /**
39
+ * Clears all non-persisted MoonPay frame artifacts.
40
+ */
41
+ clear() {
42
+ this.#frameKeypair = null;
43
+ this.#authClientToken = null;
44
+ }
45
+ /**
46
+ * Clears authentication associated with an earlier MoonPay session.
47
+ */
48
+ clearAuthentication() {
49
+ this.#authClientToken = null;
50
+ }
51
+ /**
52
+ * Handles a message posted by a MoonPay Check/Auth frame.
53
+ *
54
+ * @param message - The raw message posted by the frame.
55
+ * @returns An object whose optional `reply` should be posted back.
56
+ */
57
+ async handleMessage(message) {
58
+ const payload = message;
59
+ if (!payload) {
60
+ return {};
61
+ }
62
+ if (payload.kind === 'handshake') {
63
+ const channelId = payload.meta?.channelId;
64
+ return { reply: { version: 2, meta: { channelId }, kind: 'ack' } };
65
+ }
66
+ if (payload.kind !== 'complete') {
67
+ return {};
68
+ }
69
+ const channelId = payload.meta?.channelId;
70
+ const state = this.#getState();
71
+ // Only honor a completion for the MoonPay frame the flow is currently
72
+ // waiting on. This drops stale or duplicate messages after reset, phase
73
+ // advancement, or a vendor switch so they cannot restore tokens or rewind
74
+ // the flow. Unlike awaited controller work, external frame messages are
75
+ // not protected by the controller's generation guard.
76
+ let expectedPhase = null;
77
+ if (channelId === CHANNEL_CHECK) {
78
+ expectedPhase = 'check';
79
+ }
80
+ else if (channelId === CHANNEL_AUTH) {
81
+ expectedPhase = 'auth';
82
+ }
83
+ if (!expectedPhase ||
84
+ state.phase !== expectedPhase ||
85
+ state.activeVendor !== 'moonpay') {
86
+ return {};
87
+ }
88
+ const status = payload.payload?.status;
89
+ const credentialsEnvelope = payload.payload?.credentials;
90
+ const customerId = payload.payload?.customer?.id ?? null;
91
+ if (customerId) {
92
+ this.#update((draft) => {
93
+ draft.moonpayCustomerId = customerId;
94
+ });
95
+ }
96
+ if (!status) {
97
+ return {};
98
+ }
99
+ let accessToken;
100
+ let clientToken;
101
+ if (credentialsEnvelope && this.#frameKeypair) {
102
+ try {
103
+ const { credentials } = decryptCredentials(credentialsEnvelope, this.#frameKeypair.privateKey);
104
+ accessToken = credentials.accessToken;
105
+ clientToken = credentials.clientToken;
106
+ }
107
+ catch (error) {
108
+ this.#fail(`Failed to decrypt frame credentials: ${String(error)}`);
109
+ return {};
110
+ }
111
+ }
112
+ if (channelId === CHANNEL_CHECK) {
113
+ await this.#handleCheckOutcome(status, accessToken, clientToken);
114
+ }
115
+ else {
116
+ await this.#handleAuthOutcome(status, accessToken);
117
+ }
118
+ return {};
119
+ }
120
+ /**
121
+ * Builds the Check-frame URL, or `null` when no session exists yet.
122
+ *
123
+ * @returns The Check-frame URL or `null`.
124
+ */
125
+ buildCheckFrameUrl() {
126
+ const state = this.#getState();
127
+ if (state.activeVendor !== 'moonpay' ||
128
+ !state.moonpaySessionToken ||
129
+ !this.#frameKeypair) {
130
+ return null;
131
+ }
132
+ const url = new URL(`${FRAMES_BASE_URL}/check-connection`);
133
+ url.searchParams.set('sessionToken', state.moonpaySessionToken);
134
+ url.searchParams.set('publicKey', this.#frameKeypair.publicKeyHex);
135
+ url.searchParams.set('channelId', CHANNEL_CHECK);
136
+ url.searchParams.set('skipKyc', 'true');
137
+ return url.toString();
138
+ }
139
+ /**
140
+ * Builds the Auth-frame URL, or `null` when no client token is available.
141
+ *
142
+ * @returns The Auth-frame URL or `null`.
143
+ */
144
+ buildAuthFrameUrl() {
145
+ const state = this.#getState();
146
+ if (state.activeVendor !== 'moonpay' ||
147
+ !this.#authClientToken ||
148
+ !this.#frameKeypair) {
149
+ return null;
150
+ }
151
+ const url = new URL(`${FRAMES_BASE_URL}/auth`);
152
+ url.searchParams.set('clientToken', this.#authClientToken);
153
+ url.searchParams.set('publicKey', this.#frameKeypair.publicKeyHex);
154
+ url.searchParams.set('channelId', CHANNEL_AUTH);
155
+ return url.toString();
156
+ }
157
+ /**
158
+ * Builds the Reset-frame URL.
159
+ *
160
+ * @returns The Reset-frame URL.
161
+ */
162
+ buildResetFrameUrl() {
163
+ const url = new URL(`${FRAMES_BASE_URL}/reset`);
164
+ url.searchParams.set('channelId', CHANNEL_RESET);
165
+ return url.toString();
166
+ }
167
+ async #handleCheckOutcome(status, accessToken, clientToken) {
168
+ if (status === 'active' && accessToken) {
169
+ this.#update((state) => {
170
+ state.moonpayAccessToken = accessToken;
171
+ state.phase = 'form';
172
+ state.statusMessage = 'Already authenticated. Review to submit.';
173
+ });
174
+ await this.#onAuthenticated();
175
+ return;
176
+ }
177
+ if (status === 'connectionRequired' && clientToken) {
178
+ this.#authClientToken = clientToken;
179
+ this.#update((state) => {
180
+ state.phase = 'auth';
181
+ state.statusMessage = 'Verify your email via OTP in the Auth frame.';
182
+ });
183
+ return;
184
+ }
185
+ if (status === 'termsAcceptanceRequired') {
186
+ this.#requireTermsReacceptance();
187
+ return;
188
+ }
189
+ this.#fail(`Check frame returned status: ${status}`);
190
+ }
191
+ async #handleAuthOutcome(status, accessToken) {
192
+ if (status === 'active' && accessToken) {
193
+ this.#update((state) => {
194
+ state.moonpayAccessToken = accessToken;
195
+ state.phase = 'form';
196
+ state.statusMessage = 'Authenticated. Review to submit.';
197
+ });
198
+ await this.#onAuthenticated();
199
+ return;
200
+ }
201
+ if (status === 'termsAcceptanceRequired') {
202
+ this.#requireTermsReacceptance();
203
+ return;
204
+ }
205
+ this.#fail(`Auth frame returned status: ${status}`);
206
+ }
207
+ }
208
+ /**
209
+ * Drops persisted-in-memory MoonPay session artifacts from controller state.
210
+ *
211
+ * @param state - The state to mutate.
212
+ */
213
+ export function clearMoonPaySession(state) {
214
+ state.moonpayCustomerId = null;
215
+ state.moonpaySessionToken = null;
216
+ state.moonpayAccessToken = null;
217
+ }
218
+ //# sourceMappingURL=MoonPayFrameHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MoonPayFrameHandler.js","sourceRoot":"","sources":["../../src/vendors/MoonPayFrameHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { decryptCredentials, generateKeyPair } from '../crypto.js';\nimport type { EncryptedCredentialsEnvelope, X25519KeyPair } from '../crypto.js';\nimport type { KycPhase, KycVendor } from '../types.js';\n\nconst FRAMES_BASE_URL = 'https://blocks.moonpay.com/platform/v1';\nconst CHANNEL_CHECK = 'ch_1';\nconst CHANNEL_AUTH = 'ch_2';\nconst CHANNEL_RESET = 'ch_reset';\n\ntype MoonPayFrameState = {\n activeVendor: KycVendor;\n moonpayAccessToken: string | null;\n moonpayCustomerId: string | null;\n moonpaySessionToken: string | null;\n phase: KycPhase;\n statusMessage: string;\n};\n\ntype FrameMessage = {\n meta?: { channelId?: string };\n kind?: string;\n payload?: {\n status?:\n | 'active'\n | 'connectionRequired'\n | 'termsAcceptanceRequired'\n | 'pending'\n | 'unavailable'\n | 'failed';\n credentials?: EncryptedCredentialsEnvelope | string;\n customer?: { id?: string };\n };\n};\n\ntype FrameStatus = NonNullable<FrameMessage['payload']>['status'];\n\nexport type MoonPayFrameHandlerOptions = {\n getState: () => MoonPayFrameState;\n update: (updater: (state: MoonPayFrameState) => void) => void;\n fail: (message: string) => void;\n onAuthenticated: () => Promise<void>;\n requireTermsReacceptance: () => void;\n};\n\n/**\n * Owns MoonPay Check/Auth frame state and protocol handling.\n */\nexport class MoonPayFrameHandler {\n readonly #getState: MoonPayFrameHandlerOptions['getState'];\n\n readonly #update: MoonPayFrameHandlerOptions['update'];\n\n readonly #fail: MoonPayFrameHandlerOptions['fail'];\n\n readonly #onAuthenticated: MoonPayFrameHandlerOptions['onAuthenticated'];\n\n readonly #requireTermsReacceptance: MoonPayFrameHandlerOptions['requireTermsReacceptance'];\n\n /** MoonPay Check/Auth frame X25519 keypair (never persisted). */\n #frameKeypair: X25519KeyPair | null = null;\n\n /** Auth-frame client token, kept out of controller state. */\n #authClientToken: string | null = null;\n\n constructor({\n getState,\n update,\n fail,\n onAuthenticated,\n requireTermsReacceptance,\n }: MoonPayFrameHandlerOptions) {\n this.#getState = getState;\n this.#update = update;\n this.#fail = fail;\n this.#onAuthenticated = onAuthenticated;\n this.#requireTermsReacceptance = requireTermsReacceptance;\n }\n\n /**\n * Creates a fresh keypair for a new MoonPay flow.\n */\n startFlow(): void {\n this.#frameKeypair = generateKeyPair();\n }\n\n /**\n * Ensures an in-progress MoonPay flow has a frame keypair.\n */\n ensureKeypair(): void {\n this.#frameKeypair ??= generateKeyPair();\n }\n\n /**\n * Clears all non-persisted MoonPay frame artifacts.\n */\n clear(): void {\n this.#frameKeypair = null;\n this.#authClientToken = null;\n }\n\n /**\n * Clears authentication associated with an earlier MoonPay session.\n */\n clearAuthentication(): void {\n this.#authClientToken = null;\n }\n\n /**\n * Handles a message posted by a MoonPay Check/Auth frame.\n *\n * @param message - The raw message posted by the frame.\n * @returns An object whose optional `reply` should be posted back.\n */\n async handleMessage(message: unknown): Promise<{ reply?: unknown }> {\n const payload = message as FrameMessage | undefined;\n\n if (!payload) {\n return {};\n }\n\n if (payload.kind === 'handshake') {\n const channelId = payload.meta?.channelId;\n return { reply: { version: 2, meta: { channelId }, kind: 'ack' } };\n }\n\n if (payload.kind !== 'complete') {\n return {};\n }\n\n const channelId = payload.meta?.channelId;\n const state = this.#getState();\n\n // Only honor a completion for the MoonPay frame the flow is currently\n // waiting on. This drops stale or duplicate messages after reset, phase\n // advancement, or a vendor switch so they cannot restore tokens or rewind\n // the flow. Unlike awaited controller work, external frame messages are\n // not protected by the controller's generation guard.\n let expectedPhase: KycPhase | null = null;\n if (channelId === CHANNEL_CHECK) {\n expectedPhase = 'check';\n } else if (channelId === CHANNEL_AUTH) {\n expectedPhase = 'auth';\n }\n\n if (\n !expectedPhase ||\n state.phase !== expectedPhase ||\n state.activeVendor !== 'moonpay'\n ) {\n return {};\n }\n\n const status = payload.payload?.status;\n const credentialsEnvelope = payload.payload?.credentials;\n const customerId = payload.payload?.customer?.id ?? null;\n\n if (customerId) {\n this.#update((draft) => {\n draft.moonpayCustomerId = customerId;\n });\n }\n\n if (!status) {\n return {};\n }\n\n let accessToken: string | undefined;\n let clientToken: string | undefined;\n if (credentialsEnvelope && this.#frameKeypair) {\n try {\n const { credentials } = decryptCredentials(\n credentialsEnvelope,\n this.#frameKeypair.privateKey,\n );\n accessToken = credentials.accessToken;\n clientToken = credentials.clientToken;\n } catch (error) {\n this.#fail(`Failed to decrypt frame credentials: ${String(error)}`);\n return {};\n }\n }\n\n if (channelId === CHANNEL_CHECK) {\n await this.#handleCheckOutcome(status, accessToken, clientToken);\n } else {\n await this.#handleAuthOutcome(status, accessToken);\n }\n return {};\n }\n\n /**\n * Builds the Check-frame URL, or `null` when no session exists yet.\n *\n * @returns The Check-frame URL or `null`.\n */\n buildCheckFrameUrl(): string | null {\n const state = this.#getState();\n if (\n state.activeVendor !== 'moonpay' ||\n !state.moonpaySessionToken ||\n !this.#frameKeypair\n ) {\n return null;\n }\n const url = new URL(`${FRAMES_BASE_URL}/check-connection`);\n url.searchParams.set('sessionToken', state.moonpaySessionToken);\n url.searchParams.set('publicKey', this.#frameKeypair.publicKeyHex);\n url.searchParams.set('channelId', CHANNEL_CHECK);\n url.searchParams.set('skipKyc', 'true');\n return url.toString();\n }\n\n /**\n * Builds the Auth-frame URL, or `null` when no client token is available.\n *\n * @returns The Auth-frame URL or `null`.\n */\n buildAuthFrameUrl(): string | null {\n const state = this.#getState();\n if (\n state.activeVendor !== 'moonpay' ||\n !this.#authClientToken ||\n !this.#frameKeypair\n ) {\n return null;\n }\n const url = new URL(`${FRAMES_BASE_URL}/auth`);\n url.searchParams.set('clientToken', this.#authClientToken);\n url.searchParams.set('publicKey', this.#frameKeypair.publicKeyHex);\n url.searchParams.set('channelId', CHANNEL_AUTH);\n return url.toString();\n }\n\n /**\n * Builds the Reset-frame URL.\n *\n * @returns The Reset-frame URL.\n */\n buildResetFrameUrl(): string {\n const url = new URL(`${FRAMES_BASE_URL}/reset`);\n url.searchParams.set('channelId', CHANNEL_RESET);\n return url.toString();\n }\n\n async #handleCheckOutcome(\n status: FrameStatus,\n accessToken?: string,\n clientToken?: string,\n ): Promise<void> {\n if (status === 'active' && accessToken) {\n this.#update((state) => {\n state.moonpayAccessToken = accessToken;\n state.phase = 'form';\n state.statusMessage = 'Already authenticated. Review to submit.';\n });\n await this.#onAuthenticated();\n return;\n }\n if (status === 'connectionRequired' && clientToken) {\n this.#authClientToken = clientToken;\n this.#update((state) => {\n state.phase = 'auth';\n state.statusMessage = 'Verify your email via OTP in the Auth frame.';\n });\n return;\n }\n if (status === 'termsAcceptanceRequired') {\n this.#requireTermsReacceptance();\n return;\n }\n this.#fail(`Check frame returned status: ${status}`);\n }\n\n async #handleAuthOutcome(\n status: FrameStatus,\n accessToken?: string,\n ): Promise<void> {\n if (status === 'active' && accessToken) {\n this.#update((state) => {\n state.moonpayAccessToken = accessToken;\n state.phase = 'form';\n state.statusMessage = 'Authenticated. Review to submit.';\n });\n await this.#onAuthenticated();\n return;\n }\n if (status === 'termsAcceptanceRequired') {\n this.#requireTermsReacceptance();\n return;\n }\n this.#fail(`Auth frame returned status: ${status}`);\n }\n}\n\n/**\n * Drops persisted-in-memory MoonPay session artifacts from controller state.\n *\n * @param state - The state to mutate.\n */\nexport function clearMoonPaySession(state: MoonPayFrameState): void {\n state.moonpayCustomerId = null;\n state.moonpaySessionToken = null;\n state.moonpayAccessToken = null;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/kyc-controller",
3
- "version": "0.0.0-preview-8bfa290fb",
3
+ "version": "0.2.0-preview-0a30e47",
4
4
  "description": "Shared KYC / identity verification controller used across MetaMask clients",
5
5
  "keywords": [
6
6
  "Ethereum",
@@ -18,19 +18,12 @@
18
18
  "files": [
19
19
  "dist/"
20
20
  ],
21
+ "type": "module",
21
22
  "sideEffects": false,
22
- "main": "./dist/index.cjs",
23
- "types": "./dist/index.d.cts",
24
23
  "exports": {
25
24
  ".": {
26
- "import": {
27
- "types": "./dist/index.d.mts",
28
- "default": "./dist/index.mjs"
29
- },
30
- "require": {
31
- "types": "./dist/index.d.cts",
32
- "default": "./dist/index.cjs"
33
- }
25
+ "types": "./dist/index.d.ts",
26
+ "default": "./dist/index.js"
34
27
  },
35
28
  "./package.json": "./package.json"
36
29
  },
@@ -39,10 +32,12 @@
39
32
  "registry": "https://registry.npmjs.org/"
40
33
  },
41
34
  "scripts": {
42
- "build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references",
43
- "build:all": "ts-bridge --project tsconfig.build.json --verbose --clean",
35
+ "build": "tsc --project tsconfig.build.json",
36
+ "build:all": "tsc --build tsconfig.build.json --verbose",
37
+ "build:clean": "yarn build:only-clean && yarn build",
44
38
  "build:docs": "typedoc",
45
- "build:watch": "yarn build && chokidar 'src/**/*.ts' -c 'ts-bridge --project tsconfig.build.json --verbose --no-references' --initial",
39
+ "build:only-clean": "rimraf './dist' './tsconfig.build.tsbuildinfo'",
40
+ "build:watch": "yarn build && chokidar 'src/**/*.ts' -c 'tsc --project tsconfig.build.json' --initial",
46
41
  "changelog:update": "../../scripts/update-changelog.sh @metamask/kyc-controller",
47
42
  "changelog:validate": "../../scripts/validate-changelog.sh @metamask/kyc-controller",
48
43
  "lint:tsconfigs": "tsx ../../scripts/lint-tsconfigs/lint-tsconfigs.mts",
@@ -57,12 +52,12 @@
57
52
  "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch"
58
53
  },
59
54
  "dependencies": {
60
- "@metamask/base-controller": "^9.1.0",
61
- "@metamask/base-data-service": "^1.0.0",
62
- "@metamask/controller-utils": "^12.3.0",
63
- "@metamask/geolocation-controller": "^1.0.0",
64
- "@metamask/messenger": "^2.0.0",
65
- "@metamask/profile-sync-controller": "^29.0.0",
55
+ "@metamask/base-controller": "^10.0.0",
56
+ "@metamask/base-data-service": "^2.0.0",
57
+ "@metamask/controller-utils": "^13.0.0",
58
+ "@metamask/geolocation-controller": "^2.0.0",
59
+ "@metamask/messenger": "^3.0.0",
60
+ "@metamask/profile-sync-controller": "^31.0.0",
66
61
  "@metamask/superstruct": "^3.4.1",
67
62
  "@metamask/utils": "^11.12.0",
68
63
  "@noble/ciphers": "^1.3.0",
@@ -75,19 +70,20 @@
75
70
  },
76
71
  "devDependencies": {
77
72
  "@metamask/auto-changelog": "^6.1.0",
78
- "@ts-bridge/cli": "^0.6.4",
79
73
  "@types/jest": "^30.0.0",
74
+ "@typescript/native": "npm:typescript@^7.0.2",
80
75
  "chokidar-cli": "^3.0.0",
81
76
  "deepmerge": "^4.2.2",
82
77
  "jest": "^30.4.2",
83
78
  "nock": "^13.3.1",
79
+ "rimraf": "^5.0.5",
84
80
  "ts-jest": "^29.4.11",
85
81
  "tsx": "^4.20.5",
86
82
  "typedoc": "^0.25.13",
87
83
  "typedoc-plugin-missing-exports": "^2.0.0",
88
- "typescript": "~5.3.3"
84
+ "typescript": "npm:@typescript/typescript6@^6.0.2"
89
85
  },
90
86
  "engines": {
91
- "node": "^18.18 || >=20"
87
+ "node": "^22.14.0 || ^24"
92
88
  }
93
89
  }
@@ -1,7 +0,0 @@
1
- "use strict";
2
- /**
3
- * This file is auto generated.
4
- * Do not edit manually.
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- //# sourceMappingURL=KycController-method-action-types.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"KycController-method-action-types.cjs","sourceRoot":"","sources":["../src/KycController-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { KycController } from './KycController.js';\n\n/**\n * Resolves persisted terms + geolocation, and auto-creates a session when\n * terms are already accepted and an email is available.\n *\n * @param params - Optional parameters.\n * @param params.email - The account email to associate with the session.\n * @param params.product - The consuming feature the flow runs for. When\n * provided, the controller automatically runs the KYC-required check once\n * authentication completes (and chains into document verification when KYC\n * is required). When omitted, the flow stops at `form` and the consumer must\n * call `checkKycRequired` manually.\n * @param params.vendor - Identity vendor for this flow. Non-MoonPay vendors\n * skip Check/Auth frames and use the consents path. Defaults to `moonpay`.\n */\nexport type KycControllerInitializeAction = {\n type: `KycController:initialize`;\n handler: KycController['initialize'];\n};\n\n/**\n * Creates (or resumes) an empty-shell customer for the given identity\n * vendor. Exposed so a consumer can ensure the customer exists before\n * showing T&C screens independently of {@link initialize}.\n *\n * A call while a session flow is already in progress is a no-op — matching\n * {@link initialize} — so a vendor switch cannot leave Check/Auth frames\n * attached to the wrong vendor. Call {@link reset} first to start over.\n *\n * @param params - The parameters.\n * @param params.vendor - Identity vendor for the customer.\n * @param params.email - Email for the vendor customer.\n */\nexport type KycControllerCreateVendorCustomerAction = {\n type: `KycController:createVendorCustomer`;\n handler: KycController['createVendorCustomer'];\n};\n\n/**\n * Loads the disclaimers for the resolved (or provided) country.\n *\n * @param params - Optional parameters.\n * @param params.country - ISO 3166-1 alpha-3 country code override.\n */\nexport type KycControllerLoadDisclaimersAction = {\n type: `KycController:loadDisclaimers`;\n handler: KycController['loadDisclaimers'];\n};\n\n/**\n * Captures terms acceptance for the currently loaded disclaimers and creates\n * a session.\n *\n * @param params - The parameters.\n * @param params.email - The account email to associate with the session.\n * @param params.product - The consuming feature the flow runs for. See\n * {@link initialize} for how the product drives the automatic post\n * authentication continuation.\n * @param params.sumsubTncSigned - Whether Sumsub T&C were accepted (T&C2).\n * Required for every vendor so callers explicitly declare acceptance.\n * @param params.idosTncSigned - Whether idOS T&C were accepted (T&C2).\n * Required for every vendor so callers explicitly declare acceptance.\n * @param params.credentialReusabilityConsentGiven - Whether the customer\n * consented to reuse existing idOS credentials. Used when recording\n * session-scoped disclaimers on the consents path. Defaults to `false`.\n */\nexport type KycControllerAcceptTermsAndStartSessionAction = {\n type: `KycController:acceptTermsAndStartSession`;\n handler: KycController['acceptTermsAndStartSession'];\n};\n\n/**\n * Clears the persisted terms acceptance.\n */\nexport type KycControllerClearSavedTermsAction = {\n type: `KycController:clearSavedTerms`;\n handler: KycController['clearSavedTerms'];\n};\n\n/**\n * Handles a message posted by a Check/Auth frame and advances the flow.\n *\n * The transport-agnostic caller (WebView on mobile, iframe on web) forwards\n * the raw message and injects the returned `reply` back into the frame.\n *\n * @param params - The parameters.\n * @param params.message - The raw message posted by the frame.\n * @returns An object whose optional `reply` should be posted back.\n */\nexport type KycControllerHandleFrameMessageAction = {\n type: `KycController:handleFrameMessage`;\n handler: KycController['handleFrameMessage'];\n};\n\n/**\n * Builds the Check-frame URL, or `null` when no session exists yet.\n *\n * @returns The Check-frame URL or `null`.\n */\nexport type KycControllerBuildCheckFrameUrlAction = {\n type: `KycController:buildCheckFrameUrl`;\n handler: KycController['buildCheckFrameUrl'];\n};\n\n/**\n * Builds the Auth-frame URL, or `null` when no client token is available.\n *\n * @returns The Auth-frame URL or `null`.\n */\nexport type KycControllerBuildAuthFrameUrlAction = {\n type: `KycController:buildAuthFrameUrl`;\n handler: KycController['buildAuthFrameUrl'];\n};\n\n/**\n * Builds the Reset-frame URL.\n *\n * @returns The Reset-frame URL.\n */\nexport type KycControllerBuildResetFrameUrlAction = {\n type: `KycController:buildResetFrameUrl`;\n handler: KycController['buildResetFrameUrl'];\n};\n\n/**\n * Checks whether KYC is required for a product and caches the result.\n *\n * @param params - The parameters.\n * @param params.product - The consuming feature.\n * @param params.country - Optional alpha-3 country override.\n * @returns Whether KYC is required.\n */\nexport type KycControllerCheckKycRequiredAction = {\n type: `KycController:checkKycRequired`;\n handler: KycController['checkKycRequired'];\n};\n\n/**\n * Reads the cached \"is KYC required\" result for a product.\n *\n * @param params - The parameters.\n * @param params.product - The consuming feature.\n * @returns The cached value, or `undefined` if not yet checked.\n */\nexport type KycControllerGetKycStatusAction = {\n type: `KycController:getKycStatus`;\n handler: KycController['getKycStatus'];\n};\n\n/**\n * Returns the vendor-scoped identity for the currently authenticated\n * customer, or `null` when the flow has not yet captured a vendor customer\n * id (before authentication or after {@link reset}), or when a MoonPay id\n * is present under a different `activeVendor`.\n *\n * Exposed so consumers (e.g. ramps autoramp creation) can attach the vendor\n * customer id to downstream calls without reading the full KYC state, which\n * also holds session/access tokens. The id is session-scoped and never\n * persisted.\n *\n * @returns The current {@link KycCustomerIdentity}, or `null`.\n */\nexport type KycControllerGetCustomerIdentityAction = {\n type: `KycController:getCustomerIdentity`;\n handler: KycController['getCustomerIdentity'];\n};\n\n/**\n * Runs the SumSub document-verification sub-flow end to end:\n *\n * 1. creates a UKYC session, receiving per-secret encryption schemas;\n * 2. verifies the `encryptionDataKey` schema's `jwtChain` against the\n * idOS enclave JWKS and the `ukycCapabilityToken` schema's `jwtChain` against\n * the idOS relay JWKS, then confirms each attested session server public\n * key;\n * 3. derives the `data_encryption_key` from the wallet's UKYC\n * `local_user_secret` and wraps it for the session server;\n * 4. mints a client-signed, read-only `ukyc_capability_token`, wraps it the\n * same way as the encryption key, and submits both via authorizations;\n * 5. fetches the SumSub applicant access token; and\n * 6. presents the SDK via the injected launcher.\n *\n * If a UKYC session already exists (the consents path creates it before\n * recording session disclaimers), steps 1–4 are skipped.\n *\n * If authorizations report the applicant is already approved on the relay\n * while the vendor is still finalizing (`kycStatus: approved`,\n * `finalStatus: pending`), the sub-flow stops at step 4 with a\n * `vendorProcessing` status and a message rather than launching the SDK.\n *\n * @param params - Optional parameters.\n * @param params.locale - BCP-47 locale for the SDK UI.\n * @param params.debug - Enables SDK debug logging.\n * @returns The SDK result.\n */\nexport type KycControllerStartSumSubAction = {\n type: `KycController:startSumSub`;\n handler: KycController['startSumSub'];\n};\n\n/**\n * Refreshes the user-keyed simplified KYC status from `GET /kyc/status`,\n * stores it on state, publishes {@link KycControllerStatusChangedEvent}, and\n * schedules short-interval polling while the status is `pending`.\n *\n * @returns The latest status payload.\n */\nexport type KycControllerRefreshKycStatusAction = {\n type: `KycController:refreshKycStatus`;\n handler: KycController['refreshKycStatus'];\n};\n\n/**\n * Fetches the current UKYC session status for the active sub-flow and records\n * it on state. Useful for a one-off refresh outside the automatic polling\n * loop that {@link startSumSub} runs.\n *\n * @returns The fetched session status.\n * @throws If there is no active SumSub session to query.\n */\nexport type KycControllerGetSessionStatusAction = {\n type: `KycController:getSessionStatus`;\n handler: KycController['getSessionStatus'];\n};\n\n/**\n * Resets the flow to idle, clearing session tokens and sub-flow state while\n * preserving persisted terms acceptance and the per-product cache.\n */\nexport type KycControllerResetAction = {\n type: `KycController:reset`;\n handler: KycController['reset'];\n};\n\n/**\n * Restores the controller to its default state, discarding everything\n * {@link reset} deliberately keeps: the session email, the persisted terms\n * acceptance, the per-product KYC-required cache and the user-keyed status.\n *\n * Intended for a full wallet reset, where no trace of the previous\n * customer may survive into the next wallet.\n */\nexport type KycControllerClearStateAction = {\n type: `KycController:clearState`;\n handler: KycController['clearState'];\n};\n\n/**\n * Union of all KycController action types.\n */\nexport type KycControllerMethodActions =\n | KycControllerInitializeAction\n | KycControllerCreateVendorCustomerAction\n | KycControllerLoadDisclaimersAction\n | KycControllerAcceptTermsAndStartSessionAction\n | KycControllerClearSavedTermsAction\n | KycControllerHandleFrameMessageAction\n | KycControllerBuildCheckFrameUrlAction\n | KycControllerBuildAuthFrameUrlAction\n | KycControllerBuildResetFrameUrlAction\n | KycControllerCheckKycRequiredAction\n | KycControllerGetKycStatusAction\n | KycControllerGetCustomerIdentityAction\n | KycControllerStartSumSubAction\n | KycControllerRefreshKycStatusAction\n | KycControllerGetSessionStatusAction\n | KycControllerResetAction\n | KycControllerClearStateAction;\n"]}