@frak-labs/core-sdk 0.0.19 → 0.1.0-beta.00226d62

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 (148) hide show
  1. package/cdn/bundle.iife.js +14 -0
  2. package/dist/actions-CEEObPYc.js +1 -0
  3. package/dist/actions-DbQhWYx8.cjs +1 -0
  4. package/dist/actions.cjs +1 -1
  5. package/dist/actions.d.cts +3 -1400
  6. package/dist/actions.d.ts +3 -1400
  7. package/dist/actions.js +1 -1
  8. package/dist/bundle.cjs +1 -13
  9. package/dist/bundle.d.cts +6 -2022
  10. package/dist/bundle.d.ts +6 -2022
  11. package/dist/bundle.js +1 -13
  12. package/dist/index-7OZ39x1U.d.ts +195 -0
  13. package/dist/index-C6FxkWPC.d.cts +511 -0
  14. package/dist/index-UFX7xCg3.d.ts +351 -0
  15. package/dist/index-d8xS4ryI.d.ts +511 -0
  16. package/dist/index-p4FqSp8z.d.cts +351 -0
  17. package/dist/index-zDq-VlKx.d.cts +195 -0
  18. package/dist/index.cjs +1 -13
  19. package/dist/index.d.cts +4 -1373
  20. package/dist/index.d.ts +4 -1373
  21. package/dist/index.js +1 -13
  22. package/dist/interaction-DMJ3ZfaF.d.cts +45 -0
  23. package/dist/interaction-KX1h9a7V.d.ts +45 -0
  24. package/dist/interactions-DnfM3oe0.js +1 -0
  25. package/dist/interactions-EIXhNLf6.cjs +1 -0
  26. package/dist/interactions.cjs +1 -1
  27. package/dist/interactions.d.cts +2 -182
  28. package/dist/interactions.d.ts +2 -182
  29. package/dist/interactions.js +1 -1
  30. package/dist/openSso-D--Airj6.d.cts +1018 -0
  31. package/dist/openSso-DsKJ4y0j.d.ts +1018 -0
  32. package/dist/productTypes-BUkXJKZ7.cjs +1 -0
  33. package/dist/productTypes-CGb1MmBF.js +1 -0
  34. package/dist/src-B_xO0AR6.cjs +13 -0
  35. package/dist/src-D2d52OZa.js +13 -0
  36. package/dist/trackEvent-CHnYa85W.js +1 -0
  37. package/dist/trackEvent-GuQm_1Nm.cjs +1 -0
  38. package/package.json +27 -18
  39. package/src/actions/displayEmbeddedWallet.test.ts +194 -0
  40. package/src/actions/displayEmbeddedWallet.ts +20 -0
  41. package/src/actions/displayModal.test.ts +387 -0
  42. package/src/actions/displayModal.ts +131 -0
  43. package/src/actions/getProductInformation.test.ts +133 -0
  44. package/src/actions/getProductInformation.ts +14 -0
  45. package/src/actions/index.ts +29 -0
  46. package/src/actions/openSso.test.ts +407 -0
  47. package/src/actions/openSso.ts +116 -0
  48. package/src/actions/prepareSso.test.ts +223 -0
  49. package/src/actions/prepareSso.ts +48 -0
  50. package/src/actions/referral/processReferral.test.ts +357 -0
  51. package/src/actions/referral/processReferral.ts +230 -0
  52. package/src/actions/referral/referralInteraction.test.ts +153 -0
  53. package/src/actions/referral/referralInteraction.ts +57 -0
  54. package/src/actions/sendInteraction.test.ts +219 -0
  55. package/src/actions/sendInteraction.ts +32 -0
  56. package/src/actions/trackPurchaseStatus.test.ts +287 -0
  57. package/src/actions/trackPurchaseStatus.ts +53 -0
  58. package/src/actions/watchWalletStatus.test.ts +372 -0
  59. package/src/actions/watchWalletStatus.ts +94 -0
  60. package/src/actions/wrapper/modalBuilder.test.ts +253 -0
  61. package/src/actions/wrapper/modalBuilder.ts +212 -0
  62. package/src/actions/wrapper/sendTransaction.test.ts +164 -0
  63. package/src/actions/wrapper/sendTransaction.ts +62 -0
  64. package/src/actions/wrapper/siweAuthenticate.test.ts +290 -0
  65. package/src/actions/wrapper/siweAuthenticate.ts +94 -0
  66. package/src/bundle.ts +3 -0
  67. package/src/clients/DebugInfo.test.ts +418 -0
  68. package/src/clients/DebugInfo.ts +182 -0
  69. package/src/clients/createIFrameFrakClient.ts +287 -0
  70. package/src/clients/index.ts +3 -0
  71. package/src/clients/setupClient.test.ts +343 -0
  72. package/src/clients/setupClient.ts +73 -0
  73. package/src/clients/transports/iframeLifecycleManager.test.ts +399 -0
  74. package/src/clients/transports/iframeLifecycleManager.ts +90 -0
  75. package/src/constants/interactionTypes.test.ts +128 -0
  76. package/src/constants/interactionTypes.ts +44 -0
  77. package/src/constants/locales.ts +14 -0
  78. package/src/constants/productTypes.test.ts +130 -0
  79. package/src/constants/productTypes.ts +33 -0
  80. package/src/index.ts +101 -0
  81. package/src/interactions/index.ts +5 -0
  82. package/src/interactions/pressEncoder.test.ts +215 -0
  83. package/src/interactions/pressEncoder.ts +53 -0
  84. package/src/interactions/purchaseEncoder.test.ts +291 -0
  85. package/src/interactions/purchaseEncoder.ts +99 -0
  86. package/src/interactions/referralEncoder.test.ts +170 -0
  87. package/src/interactions/referralEncoder.ts +47 -0
  88. package/src/interactions/retailEncoder.test.ts +107 -0
  89. package/src/interactions/retailEncoder.ts +37 -0
  90. package/src/interactions/webshopEncoder.test.ts +56 -0
  91. package/src/interactions/webshopEncoder.ts +30 -0
  92. package/src/types/client.ts +14 -0
  93. package/src/types/compression.ts +22 -0
  94. package/src/types/config.ts +111 -0
  95. package/src/types/context.ts +13 -0
  96. package/src/types/index.ts +71 -0
  97. package/src/types/lifecycle/client.ts +46 -0
  98. package/src/types/lifecycle/iframe.ts +35 -0
  99. package/src/types/lifecycle/index.ts +2 -0
  100. package/src/types/rpc/displayModal.ts +84 -0
  101. package/src/types/rpc/embedded/index.ts +68 -0
  102. package/src/types/rpc/embedded/loggedIn.ts +55 -0
  103. package/src/types/rpc/embedded/loggedOut.ts +28 -0
  104. package/src/types/rpc/interaction.ts +43 -0
  105. package/src/types/rpc/modal/final.ts +46 -0
  106. package/src/types/rpc/modal/generic.ts +46 -0
  107. package/src/types/rpc/modal/index.ts +20 -0
  108. package/src/types/rpc/modal/login.ts +32 -0
  109. package/src/types/rpc/modal/openSession.ts +25 -0
  110. package/src/types/rpc/modal/siweAuthenticate.ts +37 -0
  111. package/src/types/rpc/modal/transaction.ts +33 -0
  112. package/src/types/rpc/productInformation.ts +59 -0
  113. package/src/types/rpc/sso.ts +80 -0
  114. package/src/types/rpc/walletStatus.ts +35 -0
  115. package/src/types/rpc.ts +158 -0
  116. package/src/types/transport.ts +34 -0
  117. package/src/utils/FrakContext.test.ts +407 -0
  118. package/src/utils/FrakContext.ts +158 -0
  119. package/src/utils/compression/b64.test.ts +181 -0
  120. package/src/utils/compression/b64.ts +29 -0
  121. package/src/utils/compression/compress.test.ts +123 -0
  122. package/src/utils/compression/compress.ts +11 -0
  123. package/src/utils/compression/decompress.test.ts +145 -0
  124. package/src/utils/compression/decompress.ts +11 -0
  125. package/src/utils/compression/index.ts +3 -0
  126. package/src/utils/computeProductId.test.ts +80 -0
  127. package/src/utils/computeProductId.ts +11 -0
  128. package/src/utils/constants.test.ts +23 -0
  129. package/src/utils/constants.ts +4 -0
  130. package/src/utils/formatAmount.test.ts +113 -0
  131. package/src/utils/formatAmount.ts +18 -0
  132. package/src/utils/getCurrencyAmountKey.test.ts +44 -0
  133. package/src/utils/getCurrencyAmountKey.ts +15 -0
  134. package/src/utils/getSupportedCurrency.test.ts +51 -0
  135. package/src/utils/getSupportedCurrency.ts +14 -0
  136. package/src/utils/getSupportedLocale.test.ts +64 -0
  137. package/src/utils/getSupportedLocale.ts +16 -0
  138. package/src/utils/iframeHelper.test.ts +450 -0
  139. package/src/utils/iframeHelper.ts +143 -0
  140. package/src/utils/index.ts +21 -0
  141. package/src/utils/sso.test.ts +361 -0
  142. package/src/utils/sso.ts +119 -0
  143. package/src/utils/ssoUrlListener.test.ts +252 -0
  144. package/src/utils/ssoUrlListener.ts +60 -0
  145. package/src/utils/trackEvent.test.ts +162 -0
  146. package/src/utils/trackEvent.ts +26 -0
  147. package/cdn/bundle.js +0 -19
  148. package/cdn/bundle.js.LICENSE.txt +0 -10
@@ -0,0 +1,361 @@
1
+ /**
2
+ * Tests for SSO URL generation utility
3
+ * Tests generateSsoUrl and compressed parameter formatting
4
+ */
5
+
6
+ import { vi } from "vitest";
7
+
8
+ // Mock compression functions
9
+ vi.mock("./compression/compress", () => ({
10
+ compressJsonToB64: vi.fn((data: unknown) => {
11
+ // Return base64url-like string for testing
12
+ return `compressed_${JSON.stringify(data)}`;
13
+ }),
14
+ }));
15
+
16
+ import type { Hex } from "viem";
17
+ import { describe, expect, it } from "../../tests/vitest-fixtures";
18
+ import type { PrepareSsoParamsType } from "../types";
19
+ import { compressJsonToB64 } from "./compression/compress";
20
+ import { generateSsoUrl } from "./sso";
21
+
22
+ describe("generateSsoUrl", () => {
23
+ const mockProductId =
24
+ "0x1234567890123456789012345678901234567890123456789012345678901234" as Hex;
25
+ const walletUrl = "https://wallet.frak.id";
26
+
27
+ describe("basic URL generation", () => {
28
+ it("should generate SSO URL with basic params", () => {
29
+ const params: PrepareSsoParamsType = {};
30
+ const name = "Test App";
31
+
32
+ const result = generateSsoUrl(
33
+ walletUrl,
34
+ params,
35
+ mockProductId,
36
+ name
37
+ );
38
+
39
+ expect(result).toContain("https://wallet.frak.id/sso");
40
+ expect(result).toContain("?p=");
41
+ });
42
+
43
+ it("should include compressed parameters in URL", () => {
44
+ const params: PrepareSsoParamsType = {
45
+ directExit: true,
46
+ };
47
+ const name = "My App";
48
+
49
+ const result = generateSsoUrl(
50
+ walletUrl,
51
+ params,
52
+ mockProductId,
53
+ name
54
+ );
55
+
56
+ expect(result).toContain("?p=compressed_");
57
+ expect(compressJsonToB64).toHaveBeenCalled();
58
+ });
59
+
60
+ it("should set /sso pathname", () => {
61
+ const params: PrepareSsoParamsType = {};
62
+ const name = "App";
63
+
64
+ const result = generateSsoUrl(
65
+ walletUrl,
66
+ params,
67
+ mockProductId,
68
+ name
69
+ );
70
+
71
+ const url = new URL(result);
72
+ expect(url.pathname).toBe("/sso");
73
+ });
74
+
75
+ it("should preserve wallet base URL", () => {
76
+ const customWalletUrl = "https://custom-wallet.com";
77
+ const params: PrepareSsoParamsType = {};
78
+ const name = "App";
79
+
80
+ const result = generateSsoUrl(
81
+ customWalletUrl,
82
+ params,
83
+ mockProductId,
84
+ name
85
+ );
86
+
87
+ expect(result).toContain("https://custom-wallet.com/sso");
88
+ });
89
+ });
90
+
91
+ describe("parameter compression format", () => {
92
+ it("should compress params with name and productId", () => {
93
+ const params: PrepareSsoParamsType = {};
94
+ const name = "Test App";
95
+
96
+ generateSsoUrl(walletUrl, params, mockProductId, name);
97
+
98
+ expect(compressJsonToB64).toHaveBeenCalledWith(
99
+ expect.objectContaining({
100
+ p: mockProductId,
101
+ m: expect.objectContaining({
102
+ n: name,
103
+ }),
104
+ })
105
+ );
106
+ });
107
+
108
+ it("should include redirectUrl in compressed params", () => {
109
+ const params: PrepareSsoParamsType = {
110
+ redirectUrl: "https://example.com/callback",
111
+ };
112
+ const name = "App";
113
+
114
+ generateSsoUrl(walletUrl, params, mockProductId, name);
115
+
116
+ expect(compressJsonToB64).toHaveBeenCalledWith(
117
+ expect.objectContaining({
118
+ r: "https://example.com/callback",
119
+ })
120
+ );
121
+ });
122
+
123
+ it("should include directExit in compressed params", () => {
124
+ const params: PrepareSsoParamsType = {
125
+ directExit: true,
126
+ };
127
+ const name = "App";
128
+
129
+ generateSsoUrl(walletUrl, params, mockProductId, name);
130
+
131
+ expect(compressJsonToB64).toHaveBeenCalledWith(
132
+ expect.objectContaining({
133
+ d: true,
134
+ })
135
+ );
136
+ });
137
+
138
+ it("should include lang in compressed params", () => {
139
+ const params: PrepareSsoParamsType = {
140
+ lang: "fr",
141
+ };
142
+ const name = "App";
143
+
144
+ generateSsoUrl(walletUrl, params, mockProductId, name);
145
+
146
+ expect(compressJsonToB64).toHaveBeenCalledWith(
147
+ expect.objectContaining({
148
+ l: "fr",
149
+ })
150
+ );
151
+ });
152
+
153
+ it("should include custom CSS when provided", () => {
154
+ const params: PrepareSsoParamsType = {};
155
+ const name = "App";
156
+ const css = "body { color: red; }";
157
+
158
+ generateSsoUrl(walletUrl, params, mockProductId, name, css);
159
+
160
+ expect(compressJsonToB64).toHaveBeenCalledWith(
161
+ expect.objectContaining({
162
+ m: expect.objectContaining({
163
+ css: "body { color: red; }",
164
+ }),
165
+ })
166
+ );
167
+ });
168
+
169
+ it("should include metadata logoUrl", () => {
170
+ const params: PrepareSsoParamsType = {
171
+ metadata: {
172
+ logoUrl: "https://example.com/logo.png",
173
+ },
174
+ };
175
+ const name = "App";
176
+
177
+ generateSsoUrl(walletUrl, params, mockProductId, name);
178
+
179
+ expect(compressJsonToB64).toHaveBeenCalledWith(
180
+ expect.objectContaining({
181
+ m: expect.objectContaining({
182
+ l: "https://example.com/logo.png",
183
+ }),
184
+ })
185
+ );
186
+ });
187
+
188
+ it("should include metadata homepageLink", () => {
189
+ const params: PrepareSsoParamsType = {
190
+ metadata: {
191
+ homepageLink: "https://example.com",
192
+ },
193
+ };
194
+ const name = "App";
195
+
196
+ generateSsoUrl(walletUrl, params, mockProductId, name);
197
+
198
+ expect(compressJsonToB64).toHaveBeenCalledWith(
199
+ expect.objectContaining({
200
+ m: expect.objectContaining({
201
+ h: "https://example.com",
202
+ }),
203
+ })
204
+ );
205
+ });
206
+
207
+ it("should include all metadata fields together", () => {
208
+ const params: PrepareSsoParamsType = {
209
+ metadata: {
210
+ logoUrl: "https://example.com/logo.png",
211
+ homepageLink: "https://example.com",
212
+ },
213
+ };
214
+ const name = "Full App";
215
+ const css = "body { background: blue; }";
216
+
217
+ generateSsoUrl(walletUrl, params, mockProductId, name, css);
218
+
219
+ expect(compressJsonToB64).toHaveBeenCalledWith(
220
+ expect.objectContaining({
221
+ m: {
222
+ n: "Full App",
223
+ css: "body { background: blue; }",
224
+ l: "https://example.com/logo.png",
225
+ h: "https://example.com",
226
+ },
227
+ })
228
+ );
229
+ });
230
+ });
231
+
232
+ describe("full parameter combinations", () => {
233
+ it("should handle all parameters together", () => {
234
+ const params: PrepareSsoParamsType = {
235
+ redirectUrl: "https://example.com/callback",
236
+ directExit: false,
237
+ lang: "fr",
238
+ metadata: {
239
+ logoUrl: "https://example.com/logo.png",
240
+ homepageLink: "https://example.com/home",
241
+ },
242
+ };
243
+ const name = "Complete App";
244
+ const css = "body { margin: 0; }";
245
+
246
+ const result = generateSsoUrl(
247
+ walletUrl,
248
+ params,
249
+ mockProductId,
250
+ name,
251
+ css
252
+ );
253
+
254
+ expect(result).toContain("https://wallet.frak.id/sso");
255
+ expect(result).toContain("?p=");
256
+ expect(compressJsonToB64).toHaveBeenCalledWith({
257
+ r: "https://example.com/callback",
258
+ d: false,
259
+ l: "fr",
260
+ p: mockProductId,
261
+ m: {
262
+ n: "Complete App",
263
+ css: "body { margin: 0; }",
264
+ l: "https://example.com/logo.png",
265
+ h: "https://example.com/home",
266
+ },
267
+ });
268
+ });
269
+
270
+ it("should handle minimal parameters", () => {
271
+ const params: PrepareSsoParamsType = {};
272
+ const name = "Minimal App";
273
+
274
+ const result = generateSsoUrl(
275
+ walletUrl,
276
+ params,
277
+ mockProductId,
278
+ name
279
+ );
280
+
281
+ expect(result).toBeDefined();
282
+ expect(compressJsonToB64).toHaveBeenCalledWith(
283
+ expect.objectContaining({
284
+ p: mockProductId,
285
+ m: expect.objectContaining({
286
+ n: "Minimal App",
287
+ }),
288
+ })
289
+ );
290
+ });
291
+ });
292
+
293
+ describe("edge cases", () => {
294
+ it("should handle empty name", () => {
295
+ const params: PrepareSsoParamsType = {};
296
+ const name = "";
297
+
298
+ const result = generateSsoUrl(
299
+ walletUrl,
300
+ params,
301
+ mockProductId,
302
+ name
303
+ );
304
+
305
+ expect(result).toBeDefined();
306
+ expect(compressJsonToB64).toHaveBeenCalledWith(
307
+ expect.objectContaining({
308
+ m: expect.objectContaining({
309
+ n: "",
310
+ }),
311
+ })
312
+ );
313
+ });
314
+
315
+ it("should handle undefined optional parameters", () => {
316
+ const params: PrepareSsoParamsType = {};
317
+ const name = "App";
318
+
319
+ generateSsoUrl(walletUrl, params, mockProductId, name, undefined);
320
+
321
+ expect(compressJsonToB64).toHaveBeenCalledWith(
322
+ expect.objectContaining({
323
+ m: expect.objectContaining({
324
+ n: "App",
325
+ css: undefined,
326
+ }),
327
+ })
328
+ );
329
+ });
330
+
331
+ it("should handle wallet URL with trailing slash", () => {
332
+ const walletUrlWithSlash = "https://wallet.frak.id/";
333
+ const params: PrepareSsoParamsType = {};
334
+ const name = "App";
335
+
336
+ const result = generateSsoUrl(
337
+ walletUrlWithSlash,
338
+ params,
339
+ mockProductId,
340
+ name
341
+ );
342
+
343
+ expect(result).toContain("https://wallet.frak.id/sso");
344
+ });
345
+
346
+ it("should handle different product IDs", () => {
347
+ const differentProductId =
348
+ "0xabcdefabcdefabcdefabcdefabcdefabcdefabcdabcdefabcdefabcdefabcd" as Hex;
349
+ const params: PrepareSsoParamsType = {};
350
+ const name = "App";
351
+
352
+ generateSsoUrl(walletUrl, params, differentProductId, name);
353
+
354
+ expect(compressJsonToB64).toHaveBeenCalledWith(
355
+ expect.objectContaining({
356
+ p: differentProductId,
357
+ })
358
+ );
359
+ });
360
+ });
361
+ });
@@ -0,0 +1,119 @@
1
+ import type { Hex } from "viem";
2
+ import type { PrepareSsoParamsType, SsoMetadata } from "../types";
3
+ import { compressJsonToB64 } from "./compression/compress";
4
+
5
+ export type AppSpecificSsoMetadata = SsoMetadata & {
6
+ name: string;
7
+ css?: string;
8
+ };
9
+
10
+ /**
11
+ * The full SSO params that will be used for compression
12
+ */
13
+ export type FullSsoParams = Omit<PrepareSsoParamsType, "metadata"> & {
14
+ metadata: AppSpecificSsoMetadata;
15
+ productId: Hex;
16
+ };
17
+
18
+ /**
19
+ * Generate SSO URL with compressed parameters
20
+ * This mirrors the wallet's getOpenSsoLink() function
21
+ *
22
+ * @param walletUrl - Base wallet URL (e.g., "https://wallet.frak.id")
23
+ * @param params - SSO parameters
24
+ * @param productId - Product identifier
25
+ * @param name - Application name
26
+ * @param css - Optional custom CSS
27
+ * @returns Complete SSO URL ready to open in popup or redirect
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * const ssoUrl = generateSsoUrl(
32
+ * "https://wallet.frak.id",
33
+ * { metadata: { logoUrl: "..." }, directExit: true },
34
+ * "0x123...",
35
+ * "My App"
36
+ * );
37
+ * // Returns: https://wallet.frak.id/sso?p=<compressed_base64>
38
+ * ```
39
+ */
40
+ export function generateSsoUrl(
41
+ walletUrl: string,
42
+ params: PrepareSsoParamsType,
43
+ productId: Hex,
44
+ name: string,
45
+ css?: string
46
+ ): string {
47
+ // Build full params with app-specific metadata
48
+ const fullParams: FullSsoParams = {
49
+ redirectUrl: params.redirectUrl,
50
+ directExit: params.directExit,
51
+ lang: params.lang,
52
+ productId,
53
+ metadata: {
54
+ name,
55
+ css,
56
+ logoUrl: params.metadata?.logoUrl,
57
+ homepageLink: params.metadata?.homepageLink,
58
+ },
59
+ };
60
+
61
+ // Compress params to minimal format
62
+ const compressedParam = ssoParamsToCompressed(fullParams);
63
+
64
+ // Encode to base64url
65
+ const compressedString = compressJsonToB64(compressedParam);
66
+
67
+ // Build URL matching wallet's expected format: /sso?p=<compressed>
68
+ const ssoUrl = new URL(walletUrl);
69
+ ssoUrl.pathname = "/sso";
70
+ ssoUrl.searchParams.set("p", compressedString);
71
+
72
+ return ssoUrl.toString();
73
+ }
74
+
75
+ /**
76
+ * Map full sso params to compressed sso params
77
+ * @param params
78
+ */
79
+ function ssoParamsToCompressed(params: FullSsoParams) {
80
+ return {
81
+ r: params.redirectUrl,
82
+ d: params.directExit,
83
+ l: params.lang,
84
+ p: params.productId,
85
+ m: {
86
+ n: params.metadata?.name,
87
+ css: params.metadata?.css,
88
+ l: params.metadata?.logoUrl,
89
+ h: params.metadata?.homepageLink,
90
+ },
91
+ };
92
+ }
93
+
94
+ /**
95
+ * Type of compressed the sso data
96
+ */
97
+ export type CompressedSsoData = {
98
+ // Potential id from backend
99
+ id?: Hex;
100
+ // redirect url
101
+ r?: string;
102
+ // direct exit
103
+ d?: boolean;
104
+ // language
105
+ l?: "en" | "fr";
106
+ // product id
107
+ p: Hex;
108
+ // metadata
109
+ m: {
110
+ // product name
111
+ n: string;
112
+ // custom css
113
+ css?: string;
114
+ // logo
115
+ l?: string;
116
+ // home page link
117
+ h?: string;
118
+ };
119
+ };