@frak-labs/core-sdk 1.0.0 → 1.0.1
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/cdn/bundle.js +3 -3
- package/dist/actions-BlCQVBQJ.js +1 -0
- package/dist/actions-Bwj4zSdB.cjs +1 -0
- package/dist/actions.cjs +1 -1
- package/dist/actions.d.cts +2 -2
- package/dist/actions.d.ts +2 -2
- package/dist/actions.js +1 -1
- package/dist/bundle.cjs +1 -1
- package/dist/bundle.d.cts +4 -4
- package/dist/bundle.d.ts +4 -4
- package/dist/bundle.js +1 -1
- package/dist/{index-Dwmo109y.d.cts → index-9TdOc_ub.d.ts} +169 -44
- package/dist/{index-BphwTmKA.d.cts → index-BWic1g0J.d.cts} +1 -1
- package/dist/{index-BV5D9DsW.d.ts → index-DPIqLMCR.d.cts} +169 -44
- package/dist/{index-_f8EuN_1.d.ts → index-Du4nB3qO.d.ts} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/{openSso-BwEK2M98.d.cts → openSso-3YqtmSkM.d.ts} +116 -10
- package/dist/{openSso-C1Wzl5-i.d.ts → openSso-SP6T9cHA.d.cts} +115 -9
- package/dist/sdkConfigStore-BXzz5PlK.js +1 -0
- package/dist/sdkConfigStore-DDL_fjYX.cjs +1 -0
- package/dist/src-CqKED785.cjs +13 -0
- package/dist/src-u4vW9qh0.js +13 -0
- package/package.json +1 -1
- package/src/actions/referral/processReferral.test.ts +129 -8
- package/src/actions/referral/processReferral.ts +27 -17
- package/src/clients/createIFrameFrakClient.ts +84 -3
- package/src/index.ts +8 -1
- package/src/types/config.ts +9 -0
- package/src/types/context.ts +16 -4
- package/src/types/index.ts +2 -0
- package/src/types/lifecycle/client.ts +7 -0
- package/src/types/resolvedConfig.ts +10 -0
- package/src/types/rpc/displaySharingPage.ts +18 -0
- package/src/types/rpc/interaction.ts +1 -1
- package/src/types/tracking.ts +37 -1
- package/src/utils/FrakContext.test.ts +239 -9
- package/src/utils/FrakContext.ts +83 -21
- package/src/utils/analytics/events/component.ts +58 -0
- package/src/utils/analytics/events/index.ts +20 -0
- package/src/utils/analytics/events/lifecycle.ts +26 -0
- package/src/utils/analytics/events/referral.ts +11 -0
- package/src/utils/analytics/index.ts +8 -0
- package/src/utils/{trackEvent.test.ts → analytics/trackEvent.test.ts} +22 -30
- package/src/utils/analytics/trackEvent.ts +34 -0
- package/src/utils/frakContextV2Codec.test.ts +241 -0
- package/src/utils/frakContextV2Codec.ts +197 -0
- package/src/utils/index.ts +5 -1
- package/src/utils/mergeAttribution.test.ts +153 -0
- package/src/utils/mergeAttribution.ts +75 -0
- package/dist/actions-D4aBXbdp.cjs +0 -1
- package/dist/actions-Dq_uN-wn.js +0 -1
- package/dist/src-B1eliIi6.cjs +0 -13
- package/dist/src-C0UH1GsN.js +0 -13
- package/dist/trackEvent-BqJqRZ-u.cjs +0 -1
- package/dist/trackEvent-Bqq4jd6R.js +0 -1
- package/src/utils/trackEvent.ts +0 -41
|
@@ -1,8 +1,65 @@
|
|
|
1
|
-
import { OpenPanel } from "@openpanel/web";
|
|
2
|
-
import { LifecycleMessage, RpcClient } from "@frak-labs/frame-connector";
|
|
3
1
|
import { Address, Hex } from "viem";
|
|
2
|
+
import { LifecycleMessage, RpcClient } from "@frak-labs/frame-connector";
|
|
3
|
+
import { OpenPanel } from "@openpanel/web";
|
|
4
4
|
import { SiweMessage } from "viem/siwe";
|
|
5
5
|
|
|
6
|
+
//#region src/types/tracking.d.ts
|
|
7
|
+
type UtmParams = {
|
|
8
|
+
source?: string;
|
|
9
|
+
medium?: string;
|
|
10
|
+
campaign?: string;
|
|
11
|
+
term?: string;
|
|
12
|
+
content?: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Attribution parameters appended to outbound sharing URLs.
|
|
16
|
+
*
|
|
17
|
+
* Defaults are derived from the V2 Frak context when available:
|
|
18
|
+
* - `utmSource`: `"frak"`
|
|
19
|
+
* - `utmMedium`: `"referral"`
|
|
20
|
+
* - `utmCampaign`: merchantId (`context.m`)
|
|
21
|
+
* - `via`: `"frak"`
|
|
22
|
+
* - `ref`: clientId (`context.c`)
|
|
23
|
+
*
|
|
24
|
+
* Fields explicitly set here override the defaults. Existing params on the
|
|
25
|
+
* base URL are preserved (gap-fill policy) to respect merchant-provided UTMs.
|
|
26
|
+
*/
|
|
27
|
+
type AttributionParams = {
|
|
28
|
+
utmSource?: string;
|
|
29
|
+
utmMedium?: string;
|
|
30
|
+
utmCampaign?: string;
|
|
31
|
+
utmContent?: string;
|
|
32
|
+
utmTerm?: string;
|
|
33
|
+
via?: string;
|
|
34
|
+
ref?: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Merchant-level attribution defaults.
|
|
38
|
+
*
|
|
39
|
+
* Same shape as {@link AttributionParams} minus `utmContent`, because
|
|
40
|
+
* `utm_content` describes the specific content/creative being shared and is
|
|
41
|
+
* inherently per-call or per-product (never a merchant-wide default).
|
|
42
|
+
*
|
|
43
|
+
* Used as the shape for both:
|
|
44
|
+
* - `FrakWalletSdkConfig.attribution` (SDK-side compile-time defaults)
|
|
45
|
+
* - Backend merchant-config attribution (dashboard-driven defaults)
|
|
46
|
+
*/
|
|
47
|
+
type AttributionDefaults = Omit<AttributionParams, "utmContent">;
|
|
48
|
+
type TrackArrivalParams = {
|
|
49
|
+
/** Sharer wallet address. Accepted in both V1 (legacy) and V2 (authenticated sharer) contexts. */referrerWallet?: Address;
|
|
50
|
+
referrerClientId?: string;
|
|
51
|
+
referrerMerchantId?: string; /** Epoch seconds timestamp from the referral link creation */
|
|
52
|
+
referralTimestamp?: number;
|
|
53
|
+
landingUrl?: string;
|
|
54
|
+
utmParams?: UtmParams;
|
|
55
|
+
};
|
|
56
|
+
type TrackArrivalResult = {
|
|
57
|
+
success: boolean;
|
|
58
|
+
identityGroupId?: string;
|
|
59
|
+
touchpointId?: string;
|
|
60
|
+
error?: string;
|
|
61
|
+
};
|
|
62
|
+
//#endregion
|
|
6
63
|
//#region src/types/config.d.ts
|
|
7
64
|
/**
|
|
8
65
|
* All the currencies available
|
|
@@ -82,6 +139,13 @@ type FrakWalletSdkConfig = {
|
|
|
82
139
|
* @defaultValue true
|
|
83
140
|
*/
|
|
84
141
|
waitForBackendConfig?: boolean;
|
|
142
|
+
/**
|
|
143
|
+
* Default attribution params (UTM / via / ref) appended to outbound
|
|
144
|
+
* sharing URLs. Per-call `displaySharingPage` overrides win, then backend
|
|
145
|
+
* config, then this SDK-level default. `utm_content` is intentionally
|
|
146
|
+
* excluded — it is per-content/per-product, never a merchant-wide default.
|
|
147
|
+
*/
|
|
148
|
+
attribution?: AttributionDefaults;
|
|
85
149
|
};
|
|
86
150
|
/**
|
|
87
151
|
* Custom i18n configuration for the modal
|
|
@@ -199,6 +263,12 @@ type ResolvedSdkConfig = {
|
|
|
199
263
|
translations?: Record<string, string>;
|
|
200
264
|
placements?: Record<string, ResolvedPlacement>; /** Global component defaults (used when no placement override exists) */
|
|
201
265
|
components?: ResolvedPlacement["components"];
|
|
266
|
+
/**
|
|
267
|
+
* Default attribution params applied when building outbound sharing URLs.
|
|
268
|
+
* Per-call overrides win over these backend defaults; `utm_content` is
|
|
269
|
+
* intentionally excluded (per-content/per-product, never a merchant default).
|
|
270
|
+
*/
|
|
271
|
+
attribution?: AttributionDefaults;
|
|
202
272
|
};
|
|
203
273
|
/**
|
|
204
274
|
* Internal SDK config store state
|
|
@@ -221,7 +291,8 @@ type SdkResolvedConfig = {
|
|
|
221
291
|
css?: string; /** Global translations (for reference / component fallback) */
|
|
222
292
|
translations?: Record<string, string>; /** Named placements (keyed by placement ID) */
|
|
223
293
|
placements?: Record<string, ResolvedPlacement>; /** Global component defaults (fallback for placement-level overrides) */
|
|
224
|
-
components?: ResolvedPlacement["components"];
|
|
294
|
+
components?: ResolvedPlacement["components"]; /** Merged attribution defaults: backend > SDK static config */
|
|
295
|
+
attribution?: AttributionDefaults;
|
|
225
296
|
};
|
|
226
297
|
//#endregion
|
|
227
298
|
//#region src/types/lifecycle/client.d.ts
|
|
@@ -276,6 +347,13 @@ type ResolvedConfigEvent = {
|
|
|
276
347
|
* When present, listener should execute identity merge in background.
|
|
277
348
|
*/
|
|
278
349
|
pendingMergeToken?: string;
|
|
350
|
+
/**
|
|
351
|
+
* Persistent per-origin anonymous id generated on the partner site
|
|
352
|
+
* (SDK-side localStorage). Propagated here so the listener can
|
|
353
|
+
* set it as an OpenPanel global property and stitch SDK events
|
|
354
|
+
* with listener events in the same funnel.
|
|
355
|
+
*/
|
|
356
|
+
sdkAnonymousId?: string;
|
|
279
357
|
sdkConfig?: ResolvedSdkConfig;
|
|
280
358
|
};
|
|
281
359
|
};
|
|
@@ -651,6 +729,11 @@ type SharingPageProduct = {
|
|
|
651
729
|
* When provided and the product is selected, this link is used instead of the default sharing link
|
|
652
730
|
*/
|
|
653
731
|
link?: string;
|
|
732
|
+
/**
|
|
733
|
+
* Optional `utm_content` value to apply when this product is selected.
|
|
734
|
+
* Falls back to the page-level `attribution.utmContent` when omitted.
|
|
735
|
+
*/
|
|
736
|
+
utmContent?: string;
|
|
654
737
|
};
|
|
655
738
|
/**
|
|
656
739
|
* Parameters to display the sharing page
|
|
@@ -668,6 +751,18 @@ type DisplaySharingPageParamsType = {
|
|
|
668
751
|
* If not provided, the sharing link will be generated from the current page URL + merchant context
|
|
669
752
|
*/
|
|
670
753
|
link?: string;
|
|
754
|
+
/**
|
|
755
|
+
* Optional attribution overrides for the outbound sharing URL.
|
|
756
|
+
*
|
|
757
|
+
* When provided (even as an empty object), Frak adds standard affiliation
|
|
758
|
+
* params (`utm_source=frak`, `utm_medium=referral`, `utm_campaign=<merchantId>`,
|
|
759
|
+
* `ref=<clientId>`, `via=frak`) alongside `fCtx`. Existing UTMs on the base
|
|
760
|
+
* URL are preserved (gap-fill). Set this to `null` to disable attribution
|
|
761
|
+
* params entirely (only `fCtx` is added).
|
|
762
|
+
*
|
|
763
|
+
* @default {} — defaults applied
|
|
764
|
+
*/
|
|
765
|
+
attribution?: AttributionParams | null;
|
|
671
766
|
/**
|
|
672
767
|
* Optional metadata overrides for the sharing page
|
|
673
768
|
*/
|
|
@@ -856,7 +951,7 @@ type DisplayEmbeddedWalletResultType = {
|
|
|
856
951
|
* @group RPC Schema
|
|
857
952
|
*/
|
|
858
953
|
type SendInteractionParamsType = {
|
|
859
|
-
type: "arrival"; /**
|
|
954
|
+
type: "arrival"; /** Sharer wallet address. Accepted in both V1 (legacy, wallet-only) and V2 (authenticated sharer) contexts. */
|
|
860
955
|
referrerWallet?: Address;
|
|
861
956
|
referrerClientId?: string;
|
|
862
957
|
referrerMerchantId?: string; /** Epoch seconds timestamp from the referral link creation */
|
|
@@ -1201,15 +1296,26 @@ type FrakContextV1 = {
|
|
|
1201
1296
|
/** Referrer wallet address */r: Address;
|
|
1202
1297
|
};
|
|
1203
1298
|
/**
|
|
1204
|
-
* V2 Frak Context — anonymous-first referral context.
|
|
1205
|
-
*
|
|
1299
|
+
* V2 Frak Context — anonymous-first referral context with optional wallet.
|
|
1300
|
+
*
|
|
1301
|
+
* Carries merchant context (`m`) and creation timestamp (`t`) unconditionally.
|
|
1302
|
+
* Identifies the sharer via either the anonymous clientId (`c`) or, when the
|
|
1303
|
+
* sharer is authenticated, the stronger wallet identifier (`w`). A valid V2
|
|
1304
|
+
* context MUST contain at least one of `c` or `w`; both may be present when
|
|
1305
|
+
* a logged-in user shares a link (best attribution signal).
|
|
1306
|
+
*
|
|
1307
|
+
* `w` takes precedence as the source of truth because the wallet is bound to
|
|
1308
|
+
* the user's WebAuthn credential, survives localStorage clears, and is global
|
|
1309
|
+
* across merchants — unlike `c`, which is a per-browser UUID.
|
|
1310
|
+
*
|
|
1206
1311
|
* @ignore
|
|
1207
1312
|
*/
|
|
1208
1313
|
type FrakContextV2 = {
|
|
1209
|
-
/** Version discriminator */v: 2; /**
|
|
1210
|
-
c: string; /** Merchant ID (UUID) */
|
|
1314
|
+
/** Version discriminator */v: 2; /** Merchant ID (UUID) */
|
|
1211
1315
|
m: string; /** Link creation timestamp (epoch seconds) */
|
|
1212
|
-
t: number;
|
|
1316
|
+
t: number; /** Sharer's anonymous clientId (UUID from localStorage). Optional when `w` is provided. */
|
|
1317
|
+
c?: string; /** Sharer's wallet address. Preferred source of truth when the sharer is authenticated. Optional when `c` is provided. */
|
|
1318
|
+
w?: Address;
|
|
1213
1319
|
};
|
|
1214
1320
|
/**
|
|
1215
1321
|
* The current Frak Context — union of all versions.
|
|
@@ -1291,4 +1397,4 @@ declare const ssoPopupName = "frak-sso";
|
|
|
1291
1397
|
*/
|
|
1292
1398
|
declare function openSso(client: FrakClient, args: OpenSsoParamsType): Promise<OpenSsoReturnType>;
|
|
1293
1399
|
//#endregion
|
|
1294
|
-
export { ResolvedPlacement as $, ModalRpcMetadata as A, LoginModalStepType as B, EmbeddedViewActionReferred as C, DisplaySharingPageResultType as D, DisplaySharingPageParamsType as E, SendTransactionReturnType as F, SsoMetadata as G, OpenSsoReturnType as H, SendTransactionTxType as I, ModalStepMetadata as J, FinalActionType as K, SiweAuthenticateModalStepType as L, ModalRpcStepsResultType as M, ModalStepTypes as N, SharingPageProduct as O, SendTransactionModalStepType as P, MerchantConfigResponse as Q, SiweAuthenticateReturnType as R, LoggedOutEmbeddedView as S, LoggedInEmbeddedView as T, PrepareSsoParamsType as U, OpenSsoParamsType as V, PrepareSsoReturnType as W, IFrameLifecycleEvent as X, InteractionTypeKey as Y, ClientLifecycleEvent as Z, RewardTier as _, FrakContextV1 as a, Language as at, DisplayEmbeddedWalletParamsType as b, isV2Context as c, IFrameTransport as d, ResolvedSdkConfig as et, IFrameRpcSchema as f, GetMerchantInformationReturnType as g, EstimatedReward as h, FrakContext as i, I18nConfig as it, ModalRpcStepsInput as j, DisplayModalParamsType as k, FrakClient as l, UserReferralStatusType as m, ssoPopupFeatures as n, Currency as nt, FrakContextV2 as o, LocalizedI18nConfig as ot, WalletStatusReturnType as p, FinalModalStepType as q, ssoPopupName as r, FrakWalletSdkConfig as rt, isV1Context as s, openSso as t, SdkResolvedConfig as tt, FrakLifecycleEvent as u, TokenAmountType as v, EmbeddedViewActionSharing as w, DisplayEmbeddedWalletResultType as x, SendInteractionParamsType as y, SiweAuthenticationParams as z };
|
|
1400
|
+
export { ResolvedPlacement as $, ModalRpcMetadata as A, LoginModalStepType as B, EmbeddedViewActionReferred as C, DisplaySharingPageResultType as D, DisplaySharingPageParamsType as E, SendTransactionReturnType as F, SsoMetadata as G, OpenSsoReturnType as H, SendTransactionTxType as I, ModalStepMetadata as J, FinalActionType as K, SiweAuthenticateModalStepType as L, ModalRpcStepsResultType as M, ModalStepTypes as N, SharingPageProduct as O, SendTransactionModalStepType as P, MerchantConfigResponse as Q, SiweAuthenticateReturnType as R, LoggedOutEmbeddedView as S, LoggedInEmbeddedView as T, PrepareSsoParamsType as U, OpenSsoParamsType as V, PrepareSsoReturnType as W, IFrameLifecycleEvent as X, InteractionTypeKey as Y, ClientLifecycleEvent as Z, RewardTier as _, FrakContextV1 as a, Language as at, DisplayEmbeddedWalletParamsType as b, isV2Context as c, AttributionParams as ct, IFrameTransport as d, UtmParams as dt, ResolvedSdkConfig as et, IFrameRpcSchema as f, GetMerchantInformationReturnType as g, EstimatedReward as h, FrakContext as i, I18nConfig as it, ModalRpcStepsInput as j, DisplayModalParamsType as k, FrakClient as l, TrackArrivalParams as lt, UserReferralStatusType as m, ssoPopupFeatures as n, Currency as nt, FrakContextV2 as o, LocalizedI18nConfig as ot, WalletStatusReturnType as p, FinalModalStepType as q, ssoPopupName as r, FrakWalletSdkConfig as rt, isV1Context as s, AttributionDefaults as st, openSso as t, SdkResolvedConfig as tt, FrakLifecycleEvent as u, TrackArrivalResult as ut, TokenAmountType as v, EmbeddedViewActionSharing as w, DisplayEmbeddedWalletResultType as x, SendInteractionParamsType as y, SiweAuthenticationParams as z };
|
|
@@ -1,8 +1,65 @@
|
|
|
1
|
+
import { OpenPanel } from "@openpanel/web";
|
|
1
2
|
import { Address, Hex } from "viem";
|
|
2
3
|
import { LifecycleMessage, RpcClient } from "@frak-labs/frame-connector";
|
|
3
|
-
import { OpenPanel } from "@openpanel/web";
|
|
4
4
|
import { SiweMessage } from "viem/siwe";
|
|
5
5
|
|
|
6
|
+
//#region src/types/tracking.d.ts
|
|
7
|
+
type UtmParams = {
|
|
8
|
+
source?: string;
|
|
9
|
+
medium?: string;
|
|
10
|
+
campaign?: string;
|
|
11
|
+
term?: string;
|
|
12
|
+
content?: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Attribution parameters appended to outbound sharing URLs.
|
|
16
|
+
*
|
|
17
|
+
* Defaults are derived from the V2 Frak context when available:
|
|
18
|
+
* - `utmSource`: `"frak"`
|
|
19
|
+
* - `utmMedium`: `"referral"`
|
|
20
|
+
* - `utmCampaign`: merchantId (`context.m`)
|
|
21
|
+
* - `via`: `"frak"`
|
|
22
|
+
* - `ref`: clientId (`context.c`)
|
|
23
|
+
*
|
|
24
|
+
* Fields explicitly set here override the defaults. Existing params on the
|
|
25
|
+
* base URL are preserved (gap-fill policy) to respect merchant-provided UTMs.
|
|
26
|
+
*/
|
|
27
|
+
type AttributionParams = {
|
|
28
|
+
utmSource?: string;
|
|
29
|
+
utmMedium?: string;
|
|
30
|
+
utmCampaign?: string;
|
|
31
|
+
utmContent?: string;
|
|
32
|
+
utmTerm?: string;
|
|
33
|
+
via?: string;
|
|
34
|
+
ref?: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Merchant-level attribution defaults.
|
|
38
|
+
*
|
|
39
|
+
* Same shape as {@link AttributionParams} minus `utmContent`, because
|
|
40
|
+
* `utm_content` describes the specific content/creative being shared and is
|
|
41
|
+
* inherently per-call or per-product (never a merchant-wide default).
|
|
42
|
+
*
|
|
43
|
+
* Used as the shape for both:
|
|
44
|
+
* - `FrakWalletSdkConfig.attribution` (SDK-side compile-time defaults)
|
|
45
|
+
* - Backend merchant-config attribution (dashboard-driven defaults)
|
|
46
|
+
*/
|
|
47
|
+
type AttributionDefaults = Omit<AttributionParams, "utmContent">;
|
|
48
|
+
type TrackArrivalParams = {
|
|
49
|
+
/** Sharer wallet address. Accepted in both V1 (legacy) and V2 (authenticated sharer) contexts. */referrerWallet?: Address;
|
|
50
|
+
referrerClientId?: string;
|
|
51
|
+
referrerMerchantId?: string; /** Epoch seconds timestamp from the referral link creation */
|
|
52
|
+
referralTimestamp?: number;
|
|
53
|
+
landingUrl?: string;
|
|
54
|
+
utmParams?: UtmParams;
|
|
55
|
+
};
|
|
56
|
+
type TrackArrivalResult = {
|
|
57
|
+
success: boolean;
|
|
58
|
+
identityGroupId?: string;
|
|
59
|
+
touchpointId?: string;
|
|
60
|
+
error?: string;
|
|
61
|
+
};
|
|
62
|
+
//#endregion
|
|
6
63
|
//#region src/types/config.d.ts
|
|
7
64
|
/**
|
|
8
65
|
* All the currencies available
|
|
@@ -82,6 +139,13 @@ type FrakWalletSdkConfig = {
|
|
|
82
139
|
* @defaultValue true
|
|
83
140
|
*/
|
|
84
141
|
waitForBackendConfig?: boolean;
|
|
142
|
+
/**
|
|
143
|
+
* Default attribution params (UTM / via / ref) appended to outbound
|
|
144
|
+
* sharing URLs. Per-call `displaySharingPage` overrides win, then backend
|
|
145
|
+
* config, then this SDK-level default. `utm_content` is intentionally
|
|
146
|
+
* excluded — it is per-content/per-product, never a merchant-wide default.
|
|
147
|
+
*/
|
|
148
|
+
attribution?: AttributionDefaults;
|
|
85
149
|
};
|
|
86
150
|
/**
|
|
87
151
|
* Custom i18n configuration for the modal
|
|
@@ -199,6 +263,12 @@ type ResolvedSdkConfig = {
|
|
|
199
263
|
translations?: Record<string, string>;
|
|
200
264
|
placements?: Record<string, ResolvedPlacement>; /** Global component defaults (used when no placement override exists) */
|
|
201
265
|
components?: ResolvedPlacement["components"];
|
|
266
|
+
/**
|
|
267
|
+
* Default attribution params applied when building outbound sharing URLs.
|
|
268
|
+
* Per-call overrides win over these backend defaults; `utm_content` is
|
|
269
|
+
* intentionally excluded (per-content/per-product, never a merchant default).
|
|
270
|
+
*/
|
|
271
|
+
attribution?: AttributionDefaults;
|
|
202
272
|
};
|
|
203
273
|
/**
|
|
204
274
|
* Internal SDK config store state
|
|
@@ -221,7 +291,8 @@ type SdkResolvedConfig = {
|
|
|
221
291
|
css?: string; /** Global translations (for reference / component fallback) */
|
|
222
292
|
translations?: Record<string, string>; /** Named placements (keyed by placement ID) */
|
|
223
293
|
placements?: Record<string, ResolvedPlacement>; /** Global component defaults (fallback for placement-level overrides) */
|
|
224
|
-
components?: ResolvedPlacement["components"];
|
|
294
|
+
components?: ResolvedPlacement["components"]; /** Merged attribution defaults: backend > SDK static config */
|
|
295
|
+
attribution?: AttributionDefaults;
|
|
225
296
|
};
|
|
226
297
|
//#endregion
|
|
227
298
|
//#region src/types/lifecycle/client.d.ts
|
|
@@ -276,6 +347,13 @@ type ResolvedConfigEvent = {
|
|
|
276
347
|
* When present, listener should execute identity merge in background.
|
|
277
348
|
*/
|
|
278
349
|
pendingMergeToken?: string;
|
|
350
|
+
/**
|
|
351
|
+
* Persistent per-origin anonymous id generated on the partner site
|
|
352
|
+
* (SDK-side localStorage). Propagated here so the listener can
|
|
353
|
+
* set it as an OpenPanel global property and stitch SDK events
|
|
354
|
+
* with listener events in the same funnel.
|
|
355
|
+
*/
|
|
356
|
+
sdkAnonymousId?: string;
|
|
279
357
|
sdkConfig?: ResolvedSdkConfig;
|
|
280
358
|
};
|
|
281
359
|
};
|
|
@@ -651,6 +729,11 @@ type SharingPageProduct = {
|
|
|
651
729
|
* When provided and the product is selected, this link is used instead of the default sharing link
|
|
652
730
|
*/
|
|
653
731
|
link?: string;
|
|
732
|
+
/**
|
|
733
|
+
* Optional `utm_content` value to apply when this product is selected.
|
|
734
|
+
* Falls back to the page-level `attribution.utmContent` when omitted.
|
|
735
|
+
*/
|
|
736
|
+
utmContent?: string;
|
|
654
737
|
};
|
|
655
738
|
/**
|
|
656
739
|
* Parameters to display the sharing page
|
|
@@ -668,6 +751,18 @@ type DisplaySharingPageParamsType = {
|
|
|
668
751
|
* If not provided, the sharing link will be generated from the current page URL + merchant context
|
|
669
752
|
*/
|
|
670
753
|
link?: string;
|
|
754
|
+
/**
|
|
755
|
+
* Optional attribution overrides for the outbound sharing URL.
|
|
756
|
+
*
|
|
757
|
+
* When provided (even as an empty object), Frak adds standard affiliation
|
|
758
|
+
* params (`utm_source=frak`, `utm_medium=referral`, `utm_campaign=<merchantId>`,
|
|
759
|
+
* `ref=<clientId>`, `via=frak`) alongside `fCtx`. Existing UTMs on the base
|
|
760
|
+
* URL are preserved (gap-fill). Set this to `null` to disable attribution
|
|
761
|
+
* params entirely (only `fCtx` is added).
|
|
762
|
+
*
|
|
763
|
+
* @default {} — defaults applied
|
|
764
|
+
*/
|
|
765
|
+
attribution?: AttributionParams | null;
|
|
671
766
|
/**
|
|
672
767
|
* Optional metadata overrides for the sharing page
|
|
673
768
|
*/
|
|
@@ -856,7 +951,7 @@ type DisplayEmbeddedWalletResultType = {
|
|
|
856
951
|
* @group RPC Schema
|
|
857
952
|
*/
|
|
858
953
|
type SendInteractionParamsType = {
|
|
859
|
-
type: "arrival"; /**
|
|
954
|
+
type: "arrival"; /** Sharer wallet address. Accepted in both V1 (legacy, wallet-only) and V2 (authenticated sharer) contexts. */
|
|
860
955
|
referrerWallet?: Address;
|
|
861
956
|
referrerClientId?: string;
|
|
862
957
|
referrerMerchantId?: string; /** Epoch seconds timestamp from the referral link creation */
|
|
@@ -1201,15 +1296,26 @@ type FrakContextV1 = {
|
|
|
1201
1296
|
/** Referrer wallet address */r: Address;
|
|
1202
1297
|
};
|
|
1203
1298
|
/**
|
|
1204
|
-
* V2 Frak Context — anonymous-first referral context.
|
|
1205
|
-
*
|
|
1299
|
+
* V2 Frak Context — anonymous-first referral context with optional wallet.
|
|
1300
|
+
*
|
|
1301
|
+
* Carries merchant context (`m`) and creation timestamp (`t`) unconditionally.
|
|
1302
|
+
* Identifies the sharer via either the anonymous clientId (`c`) or, when the
|
|
1303
|
+
* sharer is authenticated, the stronger wallet identifier (`w`). A valid V2
|
|
1304
|
+
* context MUST contain at least one of `c` or `w`; both may be present when
|
|
1305
|
+
* a logged-in user shares a link (best attribution signal).
|
|
1306
|
+
*
|
|
1307
|
+
* `w` takes precedence as the source of truth because the wallet is bound to
|
|
1308
|
+
* the user's WebAuthn credential, survives localStorage clears, and is global
|
|
1309
|
+
* across merchants — unlike `c`, which is a per-browser UUID.
|
|
1310
|
+
*
|
|
1206
1311
|
* @ignore
|
|
1207
1312
|
*/
|
|
1208
1313
|
type FrakContextV2 = {
|
|
1209
|
-
/** Version discriminator */v: 2; /**
|
|
1210
|
-
c: string; /** Merchant ID (UUID) */
|
|
1314
|
+
/** Version discriminator */v: 2; /** Merchant ID (UUID) */
|
|
1211
1315
|
m: string; /** Link creation timestamp (epoch seconds) */
|
|
1212
|
-
t: number;
|
|
1316
|
+
t: number; /** Sharer's anonymous clientId (UUID from localStorage). Optional when `w` is provided. */
|
|
1317
|
+
c?: string; /** Sharer's wallet address. Preferred source of truth when the sharer is authenticated. Optional when `c` is provided. */
|
|
1318
|
+
w?: Address;
|
|
1213
1319
|
};
|
|
1214
1320
|
/**
|
|
1215
1321
|
* The current Frak Context — union of all versions.
|
|
@@ -1291,4 +1397,4 @@ declare const ssoPopupName = "frak-sso";
|
|
|
1291
1397
|
*/
|
|
1292
1398
|
declare function openSso(client: FrakClient, args: OpenSsoParamsType): Promise<OpenSsoReturnType>;
|
|
1293
1399
|
//#endregion
|
|
1294
|
-
export { ResolvedPlacement as $, ModalRpcMetadata as A, LoginModalStepType as B, EmbeddedViewActionReferred as C, DisplaySharingPageResultType as D, DisplaySharingPageParamsType as E, SendTransactionReturnType as F, SsoMetadata as G, OpenSsoReturnType as H, SendTransactionTxType as I, ModalStepMetadata as J, FinalActionType as K, SiweAuthenticateModalStepType as L, ModalRpcStepsResultType as M, ModalStepTypes as N, SharingPageProduct as O, SendTransactionModalStepType as P, MerchantConfigResponse as Q, SiweAuthenticateReturnType as R, LoggedOutEmbeddedView as S, LoggedInEmbeddedView as T, PrepareSsoParamsType as U, OpenSsoParamsType as V, PrepareSsoReturnType as W, IFrameLifecycleEvent as X, InteractionTypeKey as Y, ClientLifecycleEvent as Z, RewardTier as _, FrakContextV1 as a, Language as at, DisplayEmbeddedWalletParamsType as b, isV2Context as c, IFrameTransport as d, ResolvedSdkConfig as et, IFrameRpcSchema as f, GetMerchantInformationReturnType as g, EstimatedReward as h, FrakContext as i, I18nConfig as it, ModalRpcStepsInput as j, DisplayModalParamsType as k, FrakClient as l, UserReferralStatusType as m, ssoPopupFeatures as n, Currency as nt, FrakContextV2 as o, LocalizedI18nConfig as ot, WalletStatusReturnType as p, FinalModalStepType as q, ssoPopupName as r, FrakWalletSdkConfig as rt, isV1Context as s, openSso as t, SdkResolvedConfig as tt, FrakLifecycleEvent as u, TokenAmountType as v, EmbeddedViewActionSharing as w, DisplayEmbeddedWalletResultType as x, SendInteractionParamsType as y, SiweAuthenticationParams as z };
|
|
1400
|
+
export { ResolvedPlacement as $, ModalRpcMetadata as A, LoginModalStepType as B, EmbeddedViewActionReferred as C, DisplaySharingPageResultType as D, DisplaySharingPageParamsType as E, SendTransactionReturnType as F, SsoMetadata as G, OpenSsoReturnType as H, SendTransactionTxType as I, ModalStepMetadata as J, FinalActionType as K, SiweAuthenticateModalStepType as L, ModalRpcStepsResultType as M, ModalStepTypes as N, SharingPageProduct as O, SendTransactionModalStepType as P, MerchantConfigResponse as Q, SiweAuthenticateReturnType as R, LoggedOutEmbeddedView as S, LoggedInEmbeddedView as T, PrepareSsoParamsType as U, OpenSsoParamsType as V, PrepareSsoReturnType as W, IFrameLifecycleEvent as X, InteractionTypeKey as Y, ClientLifecycleEvent as Z, RewardTier as _, FrakContextV1 as a, Language as at, DisplayEmbeddedWalletParamsType as b, isV2Context as c, AttributionParams as ct, IFrameTransport as d, UtmParams as dt, ResolvedSdkConfig as et, IFrameRpcSchema as f, GetMerchantInformationReturnType as g, EstimatedReward as h, FrakContext as i, I18nConfig as it, ModalRpcStepsInput as j, DisplayModalParamsType as k, FrakClient as l, TrackArrivalParams as lt, UserReferralStatusType as m, ssoPopupFeatures as n, Currency as nt, FrakContextV2 as o, LocalizedI18nConfig as ot, WalletStatusReturnType as p, FinalModalStepType as q, ssoPopupName as r, FrakWalletSdkConfig as rt, isV1Context as s, AttributionDefaults as st, openSso as t, SdkResolvedConfig as tt, FrakLifecycleEvent as u, TrackArrivalResult as ut, TokenAmountType as v, EmbeddedViewActionSharing as w, DisplayEmbeddedWalletResultType as x, SendInteractionParamsType as y, SiweAuthenticationParams as z };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{bytesToHex as e,hexToBytes as t,isAddress as n,keccak256 as r,toHex as i}from"viem";import{jsonEncode as a}from"@frak-labs/frame-connector";const o=`frak-client-id`;function s(){return typeof crypto<`u`&&crypto.randomUUID?crypto.randomUUID():`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e===`x`?t:t&3|8).toString(16)})}function c(){if(typeof window>`u`||!window.localStorage)return console.warn(`[Frak SDK] No Window / localStorage available to save the clientId`),s();let e=localStorage.getItem(o);return e||(e=s(),localStorage.setItem(o,e)),e}function l({domain:e}={}){return r(i((e??window.location.host).replace(`www.`,``)))}function u(e){return btoa(Array.from(e,e=>String.fromCharCode(e)).join(``)).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function d(e){let t=e.length%4;return Uint8Array.from(atob(e.replace(/-/g,`+`).replace(/_/g,`/`).padEnd(e.length+(t===0?0:4-t),`=`)),e=>e.charCodeAt(0))}function f(e){return u(a(e))}function p(e,t,n,r,i,a){let o=f(m({redirectUrl:t.redirectUrl,directExit:t.directExit,lang:t.lang,merchantId:n,metadata:{name:r,css:a,logoUrl:t.metadata?.logoUrl,homepageLink:t.metadata?.homepageLink},clientId:i})),s=new URL(e);return s.pathname=`/sso`,s.searchParams.set(`p`,o),s.toString()}function m(e){return{r:e.redirectUrl,cId:e.clientId,d:e.directExit,l:e.lang,m:e.merchantId,md:{n:e.metadata?.name,css:e.metadata?.css,l:e.metadata?.logoUrl,h:e.metadata?.homepageLink}}}const h=`menubar=no,status=no,scrollbars=no,fullscreen=no,width=500, height=800`,g=`frak-sso`;async function ee(e,t){let{metadata:n,customizations:r,walletUrl:i}=e.config;if(t.openInSameWindow??!!t.redirectUrl)return await e.request({method:`frak_openSso`,params:[t,n.name,r?.css]});let a=t.ssoPopupUrl??p(i??`https://wallet.frak.id`,t,l(),n.name,c(),r?.css),o=window.open(a,g,h);if(!o)throw Error(`Popup was blocked. Please allow popups for this site.`);return o.focus(),await e.request({method:`frak_openSso`,params:[t,n.name,r?.css]})??{}}function te(e,t,n){if(!e){console.debug(`[Frak] No client provided, skipping event tracking`);return}try{e.openPanel?.track(t,n)}catch(e){console.debug(`[Frak] Failed to track event:`,t,e)}}const _=`https://backend.frak.id`;function ne(e){return e.includes(`localhost:3000`)||e.includes(`localhost:3010`)}function v(e){return ne(e)?`https://localhost:3030`:e.includes(`wallet-dev.frak.id`)||e.includes(`wallet.gcp-dev.frak.id`)?`https://backend.gcp-dev.frak.id`:_}function y(e){if(e)return v(e);if(typeof window<`u`){let e=window.FrakSetup?.client?.config?.walletUrl;if(e)return v(e)}return _}var b=class extends Map{maxSize;constructor(e){super(),this.maxSize=e}get(e){let t=super.get(e);return super.has(e)&&(super.delete(e),super.set(e,t)),t}set(e,t){if(super.has(e)&&super.delete(e),super.set(e,t),this.maxSize&&this.size>this.maxSize){let e=super.keys().next().value;e!==void 0&&super.delete(e)}return this}};const x=new b(1024),S=new b(1024),C=3e4,w=new b(1024);async function T(e,{cacheKey:t,cacheTime:n=C}){if(n>0){let e=S.get(t);if(e&&Date.now()-e.created<n)return e.data}let r=w.get(t);if(r&&Date.now()-r<1e3)throw Error(`Cache: ${t} recently failed, backing off`);let i=x.get(t);i||(i=e(),x.set(t,i));try{let e=await i;return S.set(t,{data:e,created:Date.now()}),w.delete(t),e}catch(e){throw w.set(t,Date.now()),e}finally{x.delete(t)}}function E(e){return{clear:()=>{x.delete(e),S.delete(e)},has:(t=C)=>{let n=S.get(e);return n?Date.now()-n.created<t:!1}}}function D(){x.clear(),S.clear(),w.clear()}function re(e){return`r`in e&&!(`v`in e)}function O(e){return`v`in e&&e.v===2}const k=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function A(e){return typeof e==`string`&&k.test(e)}function j(e){let t=e.replace(/-/g,``),n=new Uint8Array(16);for(let e=0;e<16;e++)n[e]=Number.parseInt(t.substring(e*2,e*2+2),16);return n}function M(e){let t=``;for(let n=0;n<16;n++)t+=e[n].toString(16).padStart(2,`0`);return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20,32)}`}function ie(e){if(!A(e.m)||!Number.isInteger(e.t)||e.t<0||e.t>4294967295)return null;let r=typeof e.c==`string`&&e.c.length>0,i=typeof e.w==`string`&&n(e.w);if(!r&&!i||r&&!A(e.c))return null;let a=new Uint8Array(21+(r?16:0)+(i?20:0)),o=new DataView(a.buffer,a.byteOffset,a.byteLength),s=0;return a[s++]=2|(r?16:0)|(i?32:0),a.set(j(e.m),s),s+=16,o.setUint32(s,e.t,!1),s+=4,r&&(a.set(j(e.c),s),s+=16),i&&(a.set(t(e.w),s),s+=20),a}function ae(t){if(t.length<21)return null;let r=t[0];if((r&15)!=2||r&192)return null;let i=(r&16)!=0,a=(r&32)!=0;if(!i&&!a)return null;let o=21+(i?16:0)+(a?20:0);if(t.length!==o)return null;let s=1,c=M(t.subarray(s,s+16));s+=16;let l=new DataView(t.buffer,t.byteOffset,t.byteLength).getUint32(s,!1);s+=4;let u={v:2,m:c,t:l};if(i&&(u.c=M(t.subarray(s,s+16)),s+=16),a){let r=e(t.subarray(s,s+20),{size:20});if(!n(r))return null;u.w=r,s+=20}return u}const N=`fCtx`;function P(e){if(e)try{if(O(e)){let t=ie(e);return t?u(t):void 0}return u(t(e.r))}catch(t){console.error(`Error compressing Frak context`,{e:t,context:e})}}function F(t){if(!(!t||t.length===0))try{let r=d(t);if(r.length!==20)return ae(r)||void 0;let i=e(r,{size:20});if(n(i))return{r:i}}catch(e){console.error(`Error decompressing Frak context`,{e,context:t})}}function I({url:e}){if(!e)return null;let t=new URL(e).searchParams.get(N);return t?F(t):null}const L=`frak`;function oe(e,t){let n=O(e);return{utm_source:t.utmSource??L,utm_medium:t.utmMedium??`referral`,utm_campaign:t.utmCampaign??(n?e.m:void 0),utm_content:t.utmContent,utm_term:t.utmTerm,via:t.via??L,ref:t.ref??(n?e.c:void 0)}}function se(e,t,n){let r=oe(t,n??{});for(let[t,n]of Object.entries(r))n===void 0||n===``||e.searchParams.has(t)||e.searchParams.set(t,n)}function R({url:e,context:t,attribution:n}){if(!e)return null;let r=P(t);if(!r)return null;let i=new URL(e);return i.searchParams.set(N,r),se(i,t,n),i.toString()}function z(e){let t=new URL(e);return t.searchParams.delete(N),t.toString()}function ce({url:e,context:t}){if(!window.location?.href||typeof window>`u`){console.error(`No window found, can't update context`);return}let n=e??window.location.href,r;r=t===null?z(n):R({url:n,context:t}),r&&window.history.replaceState(null,``,r.toString())}const B={compress:P,decompress:F,parse:I,update:R,remove:z,replaceUrl:ce},V=`__frakSdkConfig`,H=`frak-config-cache`,U=`frak-merchant-id`,W={key:H},G=typeof window<`u`;function K(){return{isResolved:!1,merchantId:``}}let q=null;function J(){if(!G)return null;try{let e=localStorage.getItem(W.key);if(!e)return null;let t=JSON.parse(e);return t.config?.isResolved?(q=t,t):null}catch{return null}}function Y(){return(q??J())?.config}function le(){let e=q??J();return e?Date.now()-e.timestamp<3e4:!1}function ue(e){if(!(!G||!e.isResolved))try{let t={config:e,timestamp:Date.now()};localStorage.setItem(W.key,JSON.stringify(t)),q=t}catch{}}function X(){if(G){q=null;try{localStorage.removeItem(W.key)}catch{}}}function de(){G&&(window[V]||(window[V]=Y()??K()))}de();function Z(){return G?window[V]??K():K()}function Q(e){G&&window.dispatchEvent(new CustomEvent(`frak:config`,{detail:e}))}function fe(e){return e??(G?window.location.hostname:``)}async function pe(e,t,n){try{let r=y(t),i=n?`&lang=${encodeURIComponent(n)}`:``,a=await fetch(`${r}/user/merchant/resolve?domain=${encodeURIComponent(e)}${i}`);if(!a.ok){console.warn(`[Frak SDK] Merchant lookup failed for domain ${e}: ${a.status}`);return}let o=await a.json();if(G)try{sessionStorage.setItem(U,o.merchantId)}catch{}return o}catch(e){console.warn(`[Frak SDK] Failed to fetch merchant config:`,e);return}}const $={getConfig:Z,get isResolved(){return Z().isResolved},get isCacheFresh(){return le()},setCacheScope(e,t){W.key=`${H}:${`${e}:${t??``}`}`,q=null},setConfig(e){if(G&&(window[V]=e),ue(e),Q(e),G&&e.merchantId)try{sessionStorage.setItem(U,e.merchantId)}catch{}},reset(){let e=Y()??K();G&&(window[V]=e),Q(e)},clearCache(){if(X(),D(),G)try{sessionStorage.removeItem(U)}catch{}},resolve(e,t,n){let r=fe(e);return r?T(async()=>{let e=await pe(r,t,n);if(!e)throw Error(`Config resolution returned empty`);return e},{cacheKey:`sdkConfig:${r}:${n??``}`,cacheTime:1/0}).catch(()=>void 0):Promise.resolve(void 0)},getMerchantId(){let e=Z();if(e.isResolved&&e.merchantId)return e.merchantId;if(G)try{return sessionStorage.getItem(U)??void 0}catch{}},async resolveMerchantId(e,t){return $.getMerchantId()||(await $.resolve(e,t))?.merchantId}};export{l as _,D as a,y as c,h as d,g as f,u as g,d as h,O as i,te as l,f as m,B as n,E as o,p,re as r,T as s,$ as t,ee as u,c as v};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let e=require(`viem`),t=require(`@frak-labs/frame-connector`);const n=`frak-client-id`;function r(){return typeof crypto<`u`&&crypto.randomUUID?crypto.randomUUID():`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e===`x`?t:t&3|8).toString(16)})}function i(){if(typeof window>`u`||!window.localStorage)return console.warn(`[Frak SDK] No Window / localStorage available to save the clientId`),r();let e=localStorage.getItem(n);return e||(e=r(),localStorage.setItem(n,e)),e}function a({domain:t}={}){return(0,e.keccak256)((0,e.toHex)((t??window.location.host).replace(`www.`,``)))}function o(e){return btoa(Array.from(e,e=>String.fromCharCode(e)).join(``)).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function s(e){let t=e.length%4;return Uint8Array.from(atob(e.replace(/-/g,`+`).replace(/_/g,`/`).padEnd(e.length+(t===0?0:4-t),`=`)),e=>e.charCodeAt(0))}function c(e){return o((0,t.jsonEncode)(e))}function l(e,t,n,r,i,a){let o=c(u({redirectUrl:t.redirectUrl,directExit:t.directExit,lang:t.lang,merchantId:n,metadata:{name:r,css:a,logoUrl:t.metadata?.logoUrl,homepageLink:t.metadata?.homepageLink},clientId:i})),s=new URL(e);return s.pathname=`/sso`,s.searchParams.set(`p`,o),s.toString()}function u(e){return{r:e.redirectUrl,cId:e.clientId,d:e.directExit,l:e.lang,m:e.merchantId,md:{n:e.metadata?.name,css:e.metadata?.css,l:e.metadata?.logoUrl,h:e.metadata?.homepageLink}}}const d=`menubar=no,status=no,scrollbars=no,fullscreen=no,width=500, height=800`,f=`frak-sso`;async function ee(e,t){let{metadata:n,customizations:r,walletUrl:o}=e.config;if(t.openInSameWindow??!!t.redirectUrl)return await e.request({method:`frak_openSso`,params:[t,n.name,r?.css]});let s=t.ssoPopupUrl??l(o??`https://wallet.frak.id`,t,a(),n.name,i(),r?.css),c=window.open(s,f,d);if(!c)throw Error(`Popup was blocked. Please allow popups for this site.`);return c.focus(),await e.request({method:`frak_openSso`,params:[t,n.name,r?.css]})??{}}function p(e,t,n){if(!e){console.debug(`[Frak] No client provided, skipping event tracking`);return}try{e.openPanel?.track(t,n)}catch(e){console.debug(`[Frak] Failed to track event:`,t,e)}}const m=`https://backend.frak.id`;function h(e){return e.includes(`localhost:3000`)||e.includes(`localhost:3010`)}function g(e){return h(e)?`https://localhost:3030`:e.includes(`wallet-dev.frak.id`)||e.includes(`wallet.gcp-dev.frak.id`)?`https://backend.gcp-dev.frak.id`:m}function _(e){if(e)return g(e);if(typeof window<`u`){let e=window.FrakSetup?.client?.config?.walletUrl;if(e)return g(e)}return m}var v=class extends Map{maxSize;constructor(e){super(),this.maxSize=e}get(e){let t=super.get(e);return super.has(e)&&(super.delete(e),super.set(e,t)),t}set(e,t){if(super.has(e)&&super.delete(e),super.set(e,t),this.maxSize&&this.size>this.maxSize){let e=super.keys().next().value;e!==void 0&&super.delete(e)}return this}};const y=new v(1024),b=new v(1024),x=3e4,S=new v(1024);async function C(e,{cacheKey:t,cacheTime:n=x}){if(n>0){let e=b.get(t);if(e&&Date.now()-e.created<n)return e.data}let r=S.get(t);if(r&&Date.now()-r<1e3)throw Error(`Cache: ${t} recently failed, backing off`);let i=y.get(t);i||(i=e(),y.set(t,i));try{let e=await i;return b.set(t,{data:e,created:Date.now()}),S.delete(t),e}catch(e){throw S.set(t,Date.now()),e}finally{y.delete(t)}}function w(e){return{clear:()=>{y.delete(e),b.delete(e)},has:(t=x)=>{let n=b.get(e);return n?Date.now()-n.created<t:!1}}}function T(){y.clear(),b.clear(),S.clear()}function te(e){return`r`in e&&!(`v`in e)}function E(e){return`v`in e&&e.v===2}const D=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function O(e){return typeof e==`string`&&D.test(e)}function k(e){let t=e.replace(/-/g,``),n=new Uint8Array(16);for(let e=0;e<16;e++)n[e]=Number.parseInt(t.substring(e*2,e*2+2),16);return n}function A(e){let t=``;for(let n=0;n<16;n++)t+=e[n].toString(16).padStart(2,`0`);return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20,32)}`}function j(t){if(!O(t.m)||!Number.isInteger(t.t)||t.t<0||t.t>4294967295)return null;let n=typeof t.c==`string`&&t.c.length>0,r=typeof t.w==`string`&&(0,e.isAddress)(t.w);if(!n&&!r||n&&!O(t.c))return null;let i=new Uint8Array(21+(n?16:0)+(r?20:0)),a=new DataView(i.buffer,i.byteOffset,i.byteLength),o=0;return i[o++]=2|(n?16:0)|(r?32:0),i.set(k(t.m),o),o+=16,a.setUint32(o,t.t,!1),o+=4,n&&(i.set(k(t.c),o),o+=16),r&&(i.set((0,e.hexToBytes)(t.w),o),o+=20),i}function ne(t){if(t.length<21)return null;let n=t[0];if((n&15)!=2||n&192)return null;let r=(n&16)!=0,i=(n&32)!=0;if(!r&&!i)return null;let a=21+(r?16:0)+(i?20:0);if(t.length!==a)return null;let o=1,s=A(t.subarray(o,o+16));o+=16;let c=new DataView(t.buffer,t.byteOffset,t.byteLength).getUint32(o,!1);o+=4;let l={v:2,m:s,t:c};if(r&&(l.c=A(t.subarray(o,o+16)),o+=16),i){let n=(0,e.bytesToHex)(t.subarray(o,o+20),{size:20});if(!(0,e.isAddress)(n))return null;l.w=n,o+=20}return l}const M=`fCtx`;function N(t){if(t)try{if(E(t)){let e=j(t);return e?o(e):void 0}return o((0,e.hexToBytes)(t.r))}catch(e){console.error(`Error compressing Frak context`,{e,context:t})}}function P(t){if(!(!t||t.length===0))try{let n=s(t);if(n.length!==20)return ne(n)||void 0;let r=(0,e.bytesToHex)(n,{size:20});if((0,e.isAddress)(r))return{r}}catch(e){console.error(`Error decompressing Frak context`,{e,context:t})}}function F({url:e}){if(!e)return null;let t=new URL(e).searchParams.get(M);return t?P(t):null}const I=`frak`;function L(e,t){let n=E(e);return{utm_source:t.utmSource??I,utm_medium:t.utmMedium??`referral`,utm_campaign:t.utmCampaign??(n?e.m:void 0),utm_content:t.utmContent,utm_term:t.utmTerm,via:t.via??I,ref:t.ref??(n?e.c:void 0)}}function R(e,t,n){let r=L(t,n??{});for(let[t,n]of Object.entries(r))n===void 0||n===``||e.searchParams.has(t)||e.searchParams.set(t,n)}function z({url:e,context:t,attribution:n}){if(!e)return null;let r=N(t);if(!r)return null;let i=new URL(e);return i.searchParams.set(M,r),R(i,t,n),i.toString()}function B(e){let t=new URL(e);return t.searchParams.delete(M),t.toString()}function re({url:e,context:t}){if(!window.location?.href||typeof window>`u`){console.error(`No window found, can't update context`);return}let n=e??window.location.href,r;r=t===null?B(n):z({url:n,context:t}),r&&window.history.replaceState(null,``,r.toString())}const V={compress:N,decompress:P,parse:F,update:z,remove:B,replaceUrl:re},H=`__frakSdkConfig`,U=`frak-config-cache`,W=`frak-merchant-id`,G={key:U},K=typeof window<`u`;function q(){return{isResolved:!1,merchantId:``}}let J=null;function Y(){if(!K)return null;try{let e=localStorage.getItem(G.key);if(!e)return null;let t=JSON.parse(e);return t.config?.isResolved?(J=t,t):null}catch{return null}}function X(){return(J??Y())?.config}function ie(){let e=J??Y();return e?Date.now()-e.timestamp<3e4:!1}function ae(e){if(!(!K||!e.isResolved))try{let t={config:e,timestamp:Date.now()};localStorage.setItem(G.key,JSON.stringify(t)),J=t}catch{}}function oe(){if(K){J=null;try{localStorage.removeItem(G.key)}catch{}}}function se(){K&&(window[H]||(window[H]=X()??q()))}se();function Z(){return K?window[H]??q():q()}function Q(e){K&&window.dispatchEvent(new CustomEvent(`frak:config`,{detail:e}))}function ce(e){return e??(K?window.location.hostname:``)}async function le(e,t,n){try{let r=_(t),i=n?`&lang=${encodeURIComponent(n)}`:``,a=await fetch(`${r}/user/merchant/resolve?domain=${encodeURIComponent(e)}${i}`);if(!a.ok){console.warn(`[Frak SDK] Merchant lookup failed for domain ${e}: ${a.status}`);return}let o=await a.json();if(K)try{sessionStorage.setItem(W,o.merchantId)}catch{}return o}catch(e){console.warn(`[Frak SDK] Failed to fetch merchant config:`,e);return}}const $={getConfig:Z,get isResolved(){return Z().isResolved},get isCacheFresh(){return ie()},setCacheScope(e,t){G.key=`${U}:${`${e}:${t??``}`}`,J=null},setConfig(e){if(K&&(window[H]=e),ae(e),Q(e),K&&e.merchantId)try{sessionStorage.setItem(W,e.merchantId)}catch{}},reset(){let e=X()??q();K&&(window[H]=e),Q(e)},clearCache(){if(oe(),T(),K)try{sessionStorage.removeItem(W)}catch{}},resolve(e,t,n){let r=ce(e);return r?C(async()=>{let e=await le(r,t,n);if(!e)throw Error(`Config resolution returned empty`);return e},{cacheKey:`sdkConfig:${r}:${n??``}`,cacheTime:1/0}).catch(()=>void 0):Promise.resolve(void 0)},getMerchantId(){let e=Z();if(e.isResolved&&e.merchantId)return e.merchantId;if(K)try{return sessionStorage.getItem(W)??void 0}catch{}},async resolveMerchantId(e,t){return $.getMerchantId()||(await $.resolve(e,t))?.merchantId}};Object.defineProperty(exports,`_`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`g`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`h`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return V}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return te}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return $}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return ee}}),Object.defineProperty(exports,`v`,{enumerable:!0,get:function(){return i}});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const e=require(`./sdkConfigStore-DDL_fjYX.cjs`);let t=require(`@frak-labs/frame-connector`),n=require(`@openpanel/web`);function r(n){return(0,t.jsonDecode)(e.h(n))}const i=`nexus-wallet-backup`,a=`frakwallet://`;function o(){let e=navigator.userAgent;return/Android/i.test(e)&&/Chrome\/\d+/i.test(e)}function s(e){return`intent://${e.slice(13)}#Intent;scheme=frakwallet;end`}function c(e,t){let n=t?.timeout??2500,r=!1,i=()=>{document.hidden&&(r=!0)};document.addEventListener(`visibilitychange`,i);let a=o()&&l(e)?s(e):e;window.location.href=a,setTimeout(()=>{document.removeEventListener(`visibilitychange`,i),r||t?.onFallback?.()},n)}function l(e){return e.startsWith(a)}const u={eur:`fr-FR`,usd:`en-US`,gbp:`en-GB`};function d(e){return e&&e in u?e:`eur`}function f(e){return e?u[e]??u.eur:u.eur}function p(e,t){let n=f(t),r=d(t);return e.toLocaleString(n,{style:`currency`,currency:r,minimumFractionDigits:0,maximumFractionDigits:2})}function m(e){return e?`${e}Amount`:`eurAmount`}const h={id:`frak-wallet`,name:`frak-wallet`,title:`Frak Wallet`,allow:`publickey-credentials-get *; clipboard-write; web-share *`,style:{width:`0`,height:`0`,border:`0`,position:`absolute`,zIndex:2000001,top:`-1000px`,left:`-1000px`,colorScheme:`auto`}};function g({walletBaseUrl:t,config:n}){let r=document.querySelector(`#frak-wallet`);r&&r.remove();let i=document.createElement(`iframe`);i.id=h.id,i.name=h.name,i.allow=h.allow,i.style.zIndex=h.style.zIndex.toString(),_({iframe:i,isVisible:!1});let a=n?.walletUrl??t??`https://wallet.frak.id`,o=e.v();return i.src=`${a}/listener?clientId=${encodeURIComponent(o)}`,new Promise(e=>{i.addEventListener(`load`,()=>e(i)),document.body.appendChild(i)})}function _({iframe:e,isVisible:t}){if(!t){e.style.width=`0`,e.style.height=`0`,e.style.border=`0`,e.style.position=`fixed`,e.style.top=`-1000px`,e.style.left=`-1000px`;return}e.style.position=`fixed`,e.style.top=`0`,e.style.left=`0`,e.style.width=`100%`,e.style.height=`100%`,e.style.pointerEvents=`auto`}function v(e=`/listener`){if(!window.opener)return null;let t=t=>{try{return t.location.origin===window.location.origin&&t.location.pathname===e}catch{return!1}};if(t(window.opener))return window.opener;try{let e=window.opener.frames;for(let n=0;n<e.length;n++)if(t(e[n]))return e[n];return null}catch(t){return console.error(`[findIframeInOpener] Error finding iframe with pathname ${e}:`,t),null}}function y(){if(typeof navigator>`u`)return!1;let e=navigator.userAgent;return!!(/iPhone|iPad|iPod/i.test(e)||/Macintosh/i.test(e)&&navigator.maxTouchPoints>1)}const b=y();function x(){if(typeof navigator>`u`)return!1;let e=navigator.userAgent.toLowerCase();return e.includes(`instagram`)||e.includes(`fban`)||e.includes(`fbav`)||e.includes(`facebook`)}const S=x();function C(e){b&&e.startsWith(`https://`)?window.location.href=`x-safari-https://${e.slice(8)}`:b&&e.startsWith(`http://`)?window.location.href=`x-safari-http://${e.slice(7)}`:window.location.href=`https://backend.frak.id/common/social?u=${encodeURIComponent(e)}`}function w({perCall:e,defaults:t,productUtmContent:n}){if(e===null)return;let r=e!==void 0,i=t!==void 0&&Object.keys(t).length>0;if(!r&&!i&&!(n!==void 0&&n!==``))return;let a={...t,...e??{}},o=n??e?.utmContent;return o!==void 0&&o!==``?a.utmContent=o:delete a.utmContent,a}function T(e,t){if(typeof window>`u`)return;let n=new URL(window.location.href),r=n.searchParams.get(`sso`);r&&(t.then(()=>{e.sendLifecycle({clientLifecycle:`sso-redirect-complete`,data:{compressed:r}}),console.log(`[SSO URL Listener] Forwarded compressed SSO data to iframe`)}).catch(e=>{console.error(`[SSO URL Listener] Failed to forward SSO data:`,e)}),n.searchParams.delete(`sso`),window.history.replaceState({},``,n.toString()),console.log(`[SSO URL Listener] SSO parameter detected and URL cleaned`))}var E=class e{config;iframe;isSetupDone=!1;lastResponse=null;lastRequest=null;constructor(e,t){this.config=e,this.iframe=t,this.lastRequest=null,this.lastResponse=null}setLastResponse(e,t){this.lastResponse={message:e,response:t,timestamp:Date.now()}}setLastRequest(e){this.lastRequest={event:e,timestamp:Date.now()}}updateSetupStatus(e){this.isSetupDone=e}base64Encode(e){try{return btoa(JSON.stringify(e))}catch(e){return console.warn(`Failed to encode debug data`,e),btoa(`Failed to encode data`)}}getIframeStatus(){return this.iframe?{loading:this.iframe.hasAttribute(`loading`),url:this.iframe.src,readyState:this.iframe.contentDocument?.readyState?+(this.iframe.contentDocument.readyState===`complete`):-1,contentWindow:!!this.iframe.contentWindow,isConnected:this.iframe.isConnected}:null}getNavigatorInfo(){return navigator?{userAgent:navigator.userAgent,language:navigator.language,onLine:navigator.onLine,screenWidth:window.screen.width,screenHeight:window.screen.height,pixelRatio:window.devicePixelRatio}:null}gatherDebugInfo(e){let n=this.getIframeStatus(),r=this.getNavigatorInfo(),i=`Unknown`;return e instanceof t.FrakRpcError?i=`FrakRpcError: ${e.code} '${e.message}'`:e instanceof Error?i=e.message:typeof e==`string`&&(i=e),{timestamp:new Date().toISOString(),encodedUrl:btoa(window.location.href),encodedConfig:this.config?this.base64Encode(this.config):`no-config`,navigatorInfo:r?this.base64Encode(r):`no-navigator`,iframeStatus:n?this.base64Encode(n):`not-iframe`,lastRequest:this.lastRequest?this.base64Encode(this.lastRequest):`No Frak request logged`,lastResponse:this.lastResponse?this.base64Encode(this.lastResponse):`No Frak response logged`,clientStatus:this.isSetupDone?`setup`:`not-setup`,error:i}}static empty(){return new e}formatDebugInfo(e){let t=this.gatherDebugInfo(e);return`
|
|
2
|
+
Debug Information:
|
|
3
|
+
-----------------
|
|
4
|
+
Timestamp: ${t.timestamp}
|
|
5
|
+
URL: ${t.encodedUrl}
|
|
6
|
+
Config: ${t.encodedConfig}
|
|
7
|
+
Navigator Info: ${t.navigatorInfo}
|
|
8
|
+
IFrame Status: ${t.iframeStatus}
|
|
9
|
+
Last Request: ${t.lastRequest}
|
|
10
|
+
Last Response: ${t.lastResponse}
|
|
11
|
+
Client Status: ${t.clientStatus}
|
|
12
|
+
Error: ${t.error}
|
|
13
|
+
`.trim()}};const D=(()=>{if(typeof navigator>`u`)return!1;let e=navigator.userAgent;if(!(/iPhone|iPad|iPod/i.test(e)||/Macintosh/i.test(e)&&navigator.maxTouchPoints>1))return!1;let t=e.toLowerCase();return t.includes(`instagram`)||t.includes(`fban`)||t.includes(`fbav`)||t.includes(`facebook`)})();function O(e){e?localStorage.setItem(i,e):localStorage.removeItem(i)}function k(e,t){try{let n=new URL(e);if(!n.searchParams.has(`u`))return e;let r=M(window.location.href,t);return n.searchParams.delete(`u`),n.searchParams.append(`u`,r),n.toString()}catch{return e}}function A(e){let t=new URL(window.location.href);e&&t.searchParams.set(`fmt`,e);let n=t.protocol===`http:`?`x-safari-http`:`x-safari-https`;window.location.href=`${n}://${t.host}${t.pathname}${t.search}${t.hash}`}function j(e){return e.includes(`/common/social`)}function M(e,t){if(!t)return e;try{let n=new URL(e);return n.searchParams.set(`fmt`,t),n.toString()}catch{return`${e}${e.includes(`?`)?`&`:`?`}fmt=${encodeURIComponent(t)}`}}function N(e,t,n,r,i){if(i){let e=k(t,r);window.open(e,`_blank`);return}if(l(t)){let i=k(t,r);c(i,{onFallback:()=>{e.contentWindow?.postMessage({clientLifecycle:`deep-link-failed`,data:{originalUrl:i}},n)}})}else if(D&&j(t))A(r);else{let e=k(t,r);window.location.href=e}}function P({iframe:e,targetOrigin:n}){let r=new t.Deferred;return{handleEvent:t=>{if(!(`iframeLifecycle`in t))return;let{iframeLifecycle:a,data:o}=t;switch(a){case`connected`:r.resolve(!0);break;case`do-backup`:O(o.backup);break;case`remove-backup`:localStorage.removeItem(i);break;case`show`:case`hide`:_({iframe:e,isVisible:a===`show`});break;case`redirect`:N(e,o.baseRedirectUrl,n,o.mergeToken,o.openInNewTab);break}},isConnected:r.promise}}function F({config:r,iframe:i}){let a=r?.walletUrl??`https://wallet.frak.id`,o=typeof navigator<`u`?navigator.language?.split(`-`)[0]:void 0,s=r.metadata.lang??(o===`en`||o===`fr`?o:void 0),c=r.domain??(typeof window<`u`?window.location.hostname:``);e.t.setCacheScope(c,s),e.t.reset();let l=e.t.isCacheFresh?void 0:e.t.resolve(r.domain,r.walletUrl,s),u=P({iframe:i,targetOrigin:a}),d=new t.Deferred,f=Date.now(),p=new E(r,i);if(!i.contentWindow)throw new t.FrakRpcError(t.RpcErrorCodes.configError,`The iframe does not have a content window`);let m=(0,t.createRpcClient)({emittingTransport:i.contentWindow,listeningTransport:window,targetOrigin:a,middleware:[{async onRequest(e,n){if(!await u.isConnected)throw new t.FrakRpcError(t.RpcErrorCodes.clientNotConnected,`The iframe provider isn't connected yet`);return await d.promise,n}},{onRequest(e,t){return p.setLastRequest(e),t},onResponse(e,t){return p.setLastResponse(e,t),t}}],lifecycleHandlers:{iframeLifecycle:(e,t)=>{u.handleEvent(e)}}}),h=I(m,u),g=async()=>{h(),m.cleanup(),i.remove(),e.a(),e.t.clearCache(),e.t.reset()},_;{console.log(`[Frak SDK] Initializing OpenPanel`),_=new n.OpenPanel({apiUrl:`https://op-api.gcp.frak.id`,clientId:`f305d11d-b93b-487c-80d4-92deb7903e98`,trackScreenViews:!0,trackOutgoingLinks:!0,trackAttributes:!1,filter:({type:t,payload:n})=>(t!==`track`||!n?.properties||`sdkVersion`in n.properties||(n.properties={...n.properties,sdkVersion:`1.0.1`,userAnonymousClientId:e.v()}),!0)}),_.setGlobalProperties({sdkVersion:`1.0.1`,userAnonymousClientId:e.v()}),_.init(),_.track(`sdk_initialized`,{sdkVersion:`1.0.1`});let t=!1,r=setTimeout(()=>{t||(t=!0,_?.track(`sdk_iframe_handshake_failed`,{reason:`timeout`}))},3e4);u.isConnected.then(()=>{t||(t=!0,clearTimeout(r),_?.track(`sdk_iframe_connected`,{handshake_duration_ms:Date.now()-f}))}).catch(()=>{t||(t=!0,clearTimeout(r),_?.track(`sdk_iframe_handshake_failed`,{reason:`unknown`}))})}let v=L({config:r,rpcClient:m,lifecycleManager:u,configPromise:l,contextSent:d,openPanel:_}).then(()=>p.updateSetupStatus(!0)).catch(e=>{throw d.reject(e),e});return{config:r,debugInfo:p,waitForConnection:u.isConnected,waitForSetup:v,request:m.request,listenerRequest:m.listen,destroy:g,openPanel:_}}function I(e,t){let n,r,i=()=>e.sendLifecycle({clientLifecycle:`heartbeat`});async function a(){i(),n=setInterval(i,1e3),r=setTimeout(()=>{o(),console.log(`Heartbeat timeout: connection failed`)},3e4),await t.isConnected,o()}function o(){n&&clearInterval(n),r&&clearTimeout(r)}return a(),o}async function L({config:t,rpcClient:n,lifecycleManager:r,configPromise:a,contextSent:o,openPanel:s}){await r.isConnected,T(n,r.isConnected);let c=new URL(window.location.href),l=c.searchParams.get(`fmt`)??void 0;l&&(c.searchParams.delete(`fmt`),window.history.replaceState({},``,c.toString()));let u=n=>{let r=n?.merchantId??t.metadata.merchantId??``,i=n?.domain??``,a=n?.allowedDomains??[],o=n?.sdkConfig,s=o?.attribution||t.attribution?{...t.attribution,...o?.attribution}:void 0;e.t.setConfig(o?{isResolved:!0,merchantId:r,domain:i,allowedDomains:a,hasRawSdkConfig:!0,name:o.name??t.metadata.name,logoUrl:o.logoUrl??t.metadata.logoUrl,homepageLink:o.homepageLink??t.metadata.homepageLink,lang:o.lang??t.metadata.lang,currency:o.currency??t.metadata.currency,hidden:o.hidden,css:o.css,translations:o.translations,placements:o.placements,components:o.components,attribution:s}:{isResolved:!0,merchantId:r,domain:i,allowedDomains:a,name:t.metadata.name,logoUrl:t.metadata.logoUrl,homepageLink:t.metadata.homepageLink,lang:t.metadata.lang,currency:t.metadata.currency,attribution:s})},d=!1,f=t=>{let r=d?void 0:l;d=!0;let i=t.hasRawSdkConfig?{name:t.name,logoUrl:t.logoUrl,homepageLink:t.homepageLink,lang:t.lang,currency:t.currency,hidden:t.hidden,css:t.css,translations:t.translations,placements:t.placements,attribution:t.attribution}:t.attribution?{attribution:t.attribution}:void 0,a=e.v();if(s){let e=s.global??{};s.setGlobalProperties({...e,merchantId:t.merchantId,domain:t.domain??``})}n.sendLifecycle({clientLifecycle:`resolved-config`,data:{merchantId:t.merchantId,domain:t.domain??``,allowedDomains:t.allowedDomains??[],sourceUrl:window.location.href,...a&&{sdkAnonymousId:a},...r&&{pendingMergeToken:r},...i&&{sdkConfig:i}}})};e.t.isResolved&&(f(e.t.getConfig()),o.resolve()),a&&(u(await a),f(e.t.getConfig()),o.resolve());async function p(){let e=t.customizations?.css;e&&n.sendLifecycle({clientLifecycle:`modal-css`,data:{cssLink:e}})}async function m(){let e=t.customizations?.i18n;e&&n.sendLifecycle({clientLifecycle:`modal-i18n`,data:{i18n:e}})}async function h(){if(typeof window>`u`)return;let e=window.localStorage.getItem(i);e&&n.sendLifecycle({clientLifecycle:`restore-backup`,data:{backup:e}})}(await Promise.allSettled([p(),m(),h()])).some(e=>e.status===`rejected`)&&s?.track(`sdk_iframe_handshake_failed`,{reason:`asset_push`})}async function R({config:e}){let t=z(e),n=await g({config:t});if(!n){console.error(`Failed to create iframe`);return}let r=F({config:t,iframe:n});if(await r.waitForSetup,!await r.waitForConnection){console.error(`Failed to connect to client`);return}return r}function z(e){let t=d(e.metadata?.currency);return{...e,metadata:{...e.metadata,currency:t}}}Object.defineProperty(exports,`_`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,`b`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`g`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`h`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return F}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return R}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,`v`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`x`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`y`,{enumerable:!0,get:function(){return c}});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import{a as e,h as t,t as n,v as r}from"./sdkConfigStore-BXzz5PlK.js";import{Deferred as i,FrakRpcError as a,RpcErrorCodes as o,createRpcClient as s,jsonDecode as c}from"@frak-labs/frame-connector";import{OpenPanel as l}from"@openpanel/web";function u(e){return c(t(e))}const d=`nexus-wallet-backup`,f=`frakwallet://`;function p(){let e=navigator.userAgent;return/Android/i.test(e)&&/Chrome\/\d+/i.test(e)}function m(e){return`intent://${e.slice(13)}#Intent;scheme=frakwallet;end`}function h(e,t){let n=t?.timeout??2500,r=!1,i=()=>{document.hidden&&(r=!0)};document.addEventListener(`visibilitychange`,i);let a=p()&&g(e)?m(e):e;window.location.href=a,setTimeout(()=>{document.removeEventListener(`visibilitychange`,i),r||t?.onFallback?.()},n)}function g(e){return e.startsWith(f)}const _={eur:`fr-FR`,usd:`en-US`,gbp:`en-GB`};function v(e){return e&&e in _?e:`eur`}function y(e){return e?_[e]??_.eur:_.eur}function b(e,t){let n=y(t),r=v(t);return e.toLocaleString(n,{style:`currency`,currency:r,minimumFractionDigits:0,maximumFractionDigits:2})}function x(e){return e?`${e}Amount`:`eurAmount`}const S={id:`frak-wallet`,name:`frak-wallet`,title:`Frak Wallet`,allow:`publickey-credentials-get *; clipboard-write; web-share *`,style:{width:`0`,height:`0`,border:`0`,position:`absolute`,zIndex:2000001,top:`-1000px`,left:`-1000px`,colorScheme:`auto`}};function C({walletBaseUrl:e,config:t}){let n=document.querySelector(`#frak-wallet`);n&&n.remove();let i=document.createElement(`iframe`);i.id=S.id,i.name=S.name,i.allow=S.allow,i.style.zIndex=S.style.zIndex.toString(),w({iframe:i,isVisible:!1});let a=t?.walletUrl??e??`https://wallet.frak.id`,o=r();return i.src=`${a}/listener?clientId=${encodeURIComponent(o)}`,new Promise(e=>{i.addEventListener(`load`,()=>e(i)),document.body.appendChild(i)})}function w({iframe:e,isVisible:t}){if(!t){e.style.width=`0`,e.style.height=`0`,e.style.border=`0`,e.style.position=`fixed`,e.style.top=`-1000px`,e.style.left=`-1000px`;return}e.style.position=`fixed`,e.style.top=`0`,e.style.left=`0`,e.style.width=`100%`,e.style.height=`100%`,e.style.pointerEvents=`auto`}function T(e=`/listener`){if(!window.opener)return null;let t=t=>{try{return t.location.origin===window.location.origin&&t.location.pathname===e}catch{return!1}};if(t(window.opener))return window.opener;try{let e=window.opener.frames;for(let n=0;n<e.length;n++)if(t(e[n]))return e[n];return null}catch(t){return console.error(`[findIframeInOpener] Error finding iframe with pathname ${e}:`,t),null}}function E(){if(typeof navigator>`u`)return!1;let e=navigator.userAgent;return!!(/iPhone|iPad|iPod/i.test(e)||/Macintosh/i.test(e)&&navigator.maxTouchPoints>1)}const D=E();function O(){if(typeof navigator>`u`)return!1;let e=navigator.userAgent.toLowerCase();return e.includes(`instagram`)||e.includes(`fban`)||e.includes(`fbav`)||e.includes(`facebook`)}const k=O();function A(e){D&&e.startsWith(`https://`)?window.location.href=`x-safari-https://${e.slice(8)}`:D&&e.startsWith(`http://`)?window.location.href=`x-safari-http://${e.slice(7)}`:window.location.href=`https://backend.frak.id/common/social?u=${encodeURIComponent(e)}`}function j({perCall:e,defaults:t,productUtmContent:n}){if(e===null)return;let r=e!==void 0,i=t!==void 0&&Object.keys(t).length>0;if(!r&&!i&&!(n!==void 0&&n!==``))return;let a={...t,...e??{}},o=n??e?.utmContent;return o!==void 0&&o!==``?a.utmContent=o:delete a.utmContent,a}function M(e,t){if(typeof window>`u`)return;let n=new URL(window.location.href),r=n.searchParams.get(`sso`);r&&(t.then(()=>{e.sendLifecycle({clientLifecycle:`sso-redirect-complete`,data:{compressed:r}}),console.log(`[SSO URL Listener] Forwarded compressed SSO data to iframe`)}).catch(e=>{console.error(`[SSO URL Listener] Failed to forward SSO data:`,e)}),n.searchParams.delete(`sso`),window.history.replaceState({},``,n.toString()),console.log(`[SSO URL Listener] SSO parameter detected and URL cleaned`))}var N=class e{config;iframe;isSetupDone=!1;lastResponse=null;lastRequest=null;constructor(e,t){this.config=e,this.iframe=t,this.lastRequest=null,this.lastResponse=null}setLastResponse(e,t){this.lastResponse={message:e,response:t,timestamp:Date.now()}}setLastRequest(e){this.lastRequest={event:e,timestamp:Date.now()}}updateSetupStatus(e){this.isSetupDone=e}base64Encode(e){try{return btoa(JSON.stringify(e))}catch(e){return console.warn(`Failed to encode debug data`,e),btoa(`Failed to encode data`)}}getIframeStatus(){return this.iframe?{loading:this.iframe.hasAttribute(`loading`),url:this.iframe.src,readyState:this.iframe.contentDocument?.readyState?+(this.iframe.contentDocument.readyState===`complete`):-1,contentWindow:!!this.iframe.contentWindow,isConnected:this.iframe.isConnected}:null}getNavigatorInfo(){return navigator?{userAgent:navigator.userAgent,language:navigator.language,onLine:navigator.onLine,screenWidth:window.screen.width,screenHeight:window.screen.height,pixelRatio:window.devicePixelRatio}:null}gatherDebugInfo(e){let t=this.getIframeStatus(),n=this.getNavigatorInfo(),r=`Unknown`;return e instanceof a?r=`FrakRpcError: ${e.code} '${e.message}'`:e instanceof Error?r=e.message:typeof e==`string`&&(r=e),{timestamp:new Date().toISOString(),encodedUrl:btoa(window.location.href),encodedConfig:this.config?this.base64Encode(this.config):`no-config`,navigatorInfo:n?this.base64Encode(n):`no-navigator`,iframeStatus:t?this.base64Encode(t):`not-iframe`,lastRequest:this.lastRequest?this.base64Encode(this.lastRequest):`No Frak request logged`,lastResponse:this.lastResponse?this.base64Encode(this.lastResponse):`No Frak response logged`,clientStatus:this.isSetupDone?`setup`:`not-setup`,error:r}}static empty(){return new e}formatDebugInfo(e){let t=this.gatherDebugInfo(e);return`
|
|
2
|
+
Debug Information:
|
|
3
|
+
-----------------
|
|
4
|
+
Timestamp: ${t.timestamp}
|
|
5
|
+
URL: ${t.encodedUrl}
|
|
6
|
+
Config: ${t.encodedConfig}
|
|
7
|
+
Navigator Info: ${t.navigatorInfo}
|
|
8
|
+
IFrame Status: ${t.iframeStatus}
|
|
9
|
+
Last Request: ${t.lastRequest}
|
|
10
|
+
Last Response: ${t.lastResponse}
|
|
11
|
+
Client Status: ${t.clientStatus}
|
|
12
|
+
Error: ${t.error}
|
|
13
|
+
`.trim()}};const P=(()=>{if(typeof navigator>`u`)return!1;let e=navigator.userAgent;if(!(/iPhone|iPad|iPod/i.test(e)||/Macintosh/i.test(e)&&navigator.maxTouchPoints>1))return!1;let t=e.toLowerCase();return t.includes(`instagram`)||t.includes(`fban`)||t.includes(`fbav`)||t.includes(`facebook`)})();function F(e){e?localStorage.setItem(d,e):localStorage.removeItem(d)}function I(e,t){try{let n=new URL(e);if(!n.searchParams.has(`u`))return e;let r=z(window.location.href,t);return n.searchParams.delete(`u`),n.searchParams.append(`u`,r),n.toString()}catch{return e}}function L(e){let t=new URL(window.location.href);e&&t.searchParams.set(`fmt`,e);let n=t.protocol===`http:`?`x-safari-http`:`x-safari-https`;window.location.href=`${n}://${t.host}${t.pathname}${t.search}${t.hash}`}function R(e){return e.includes(`/common/social`)}function z(e,t){if(!t)return e;try{let n=new URL(e);return n.searchParams.set(`fmt`,t),n.toString()}catch{return`${e}${e.includes(`?`)?`&`:`?`}fmt=${encodeURIComponent(t)}`}}function B(e,t,n,r,i){if(i){let e=I(t,r);window.open(e,`_blank`);return}if(g(t)){let i=I(t,r);h(i,{onFallback:()=>{e.contentWindow?.postMessage({clientLifecycle:`deep-link-failed`,data:{originalUrl:i}},n)}})}else if(P&&R(t))L(r);else{let e=I(t,r);window.location.href=e}}function V({iframe:e,targetOrigin:t}){let n=new i;return{handleEvent:r=>{if(!(`iframeLifecycle`in r))return;let{iframeLifecycle:i,data:a}=r;switch(i){case`connected`:n.resolve(!0);break;case`do-backup`:F(a.backup);break;case`remove-backup`:localStorage.removeItem(d);break;case`show`:case`hide`:w({iframe:e,isVisible:i===`show`});break;case`redirect`:B(e,a.baseRedirectUrl,t,a.mergeToken,a.openInNewTab);break}},isConnected:n.promise}}function H({config:t,iframe:c}){let u=t?.walletUrl??`https://wallet.frak.id`,d=typeof navigator<`u`?navigator.language?.split(`-`)[0]:void 0,f=t.metadata.lang??(d===`en`||d===`fr`?d:void 0),p=t.domain??(typeof window<`u`?window.location.hostname:``);n.setCacheScope(p,f),n.reset();let m=n.isCacheFresh?void 0:n.resolve(t.domain,t.walletUrl,f),h=V({iframe:c,targetOrigin:u}),g=new i,_=Date.now(),v=new N(t,c);if(!c.contentWindow)throw new a(o.configError,`The iframe does not have a content window`);let y=s({emittingTransport:c.contentWindow,listeningTransport:window,targetOrigin:u,middleware:[{async onRequest(e,t){if(!await h.isConnected)throw new a(o.clientNotConnected,`The iframe provider isn't connected yet`);return await g.promise,t}},{onRequest(e,t){return v.setLastRequest(e),t},onResponse(e,t){return v.setLastResponse(e,t),t}}],lifecycleHandlers:{iframeLifecycle:(e,t)=>{h.handleEvent(e)}}}),b=U(y,h),x=async()=>{b(),y.cleanup(),c.remove(),e(),n.clearCache(),n.reset()},S;{console.log(`[Frak SDK] Initializing OpenPanel`),S=new l({apiUrl:`https://op-api.gcp.frak.id`,clientId:`f305d11d-b93b-487c-80d4-92deb7903e98`,trackScreenViews:!0,trackOutgoingLinks:!0,trackAttributes:!1,filter:({type:e,payload:t})=>(e!==`track`||!t?.properties||`sdkVersion`in t.properties||(t.properties={...t.properties,sdkVersion:`1.0.1`,userAnonymousClientId:r()}),!0)}),S.setGlobalProperties({sdkVersion:`1.0.1`,userAnonymousClientId:r()}),S.init(),S.track(`sdk_initialized`,{sdkVersion:`1.0.1`});let e=!1,t=setTimeout(()=>{e||(e=!0,S?.track(`sdk_iframe_handshake_failed`,{reason:`timeout`}))},3e4);h.isConnected.then(()=>{e||(e=!0,clearTimeout(t),S?.track(`sdk_iframe_connected`,{handshake_duration_ms:Date.now()-_}))}).catch(()=>{e||(e=!0,clearTimeout(t),S?.track(`sdk_iframe_handshake_failed`,{reason:`unknown`}))})}let C=W({config:t,rpcClient:y,lifecycleManager:h,configPromise:m,contextSent:g,openPanel:S}).then(()=>v.updateSetupStatus(!0)).catch(e=>{throw g.reject(e),e});return{config:t,debugInfo:v,waitForConnection:h.isConnected,waitForSetup:C,request:y.request,listenerRequest:y.listen,destroy:x,openPanel:S}}function U(e,t){let n,r,i=()=>e.sendLifecycle({clientLifecycle:`heartbeat`});async function a(){i(),n=setInterval(i,1e3),r=setTimeout(()=>{o(),console.log(`Heartbeat timeout: connection failed`)},3e4),await t.isConnected,o()}function o(){n&&clearInterval(n),r&&clearTimeout(r)}return a(),o}async function W({config:e,rpcClient:t,lifecycleManager:i,configPromise:a,contextSent:o,openPanel:s}){await i.isConnected,M(t,i.isConnected);let c=new URL(window.location.href),l=c.searchParams.get(`fmt`)??void 0;l&&(c.searchParams.delete(`fmt`),window.history.replaceState({},``,c.toString()));let u=t=>{let r=t?.merchantId??e.metadata.merchantId??``,i=t?.domain??``,a=t?.allowedDomains??[],o=t?.sdkConfig,s=o?.attribution||e.attribution?{...e.attribution,...o?.attribution}:void 0;n.setConfig(o?{isResolved:!0,merchantId:r,domain:i,allowedDomains:a,hasRawSdkConfig:!0,name:o.name??e.metadata.name,logoUrl:o.logoUrl??e.metadata.logoUrl,homepageLink:o.homepageLink??e.metadata.homepageLink,lang:o.lang??e.metadata.lang,currency:o.currency??e.metadata.currency,hidden:o.hidden,css:o.css,translations:o.translations,placements:o.placements,components:o.components,attribution:s}:{isResolved:!0,merchantId:r,domain:i,allowedDomains:a,name:e.metadata.name,logoUrl:e.metadata.logoUrl,homepageLink:e.metadata.homepageLink,lang:e.metadata.lang,currency:e.metadata.currency,attribution:s})},f=!1,p=e=>{let n=f?void 0:l;f=!0;let i=e.hasRawSdkConfig?{name:e.name,logoUrl:e.logoUrl,homepageLink:e.homepageLink,lang:e.lang,currency:e.currency,hidden:e.hidden,css:e.css,translations:e.translations,placements:e.placements,attribution:e.attribution}:e.attribution?{attribution:e.attribution}:void 0,a=r();if(s){let t=s.global??{};s.setGlobalProperties({...t,merchantId:e.merchantId,domain:e.domain??``})}t.sendLifecycle({clientLifecycle:`resolved-config`,data:{merchantId:e.merchantId,domain:e.domain??``,allowedDomains:e.allowedDomains??[],sourceUrl:window.location.href,...a&&{sdkAnonymousId:a},...n&&{pendingMergeToken:n},...i&&{sdkConfig:i}}})};n.isResolved&&(p(n.getConfig()),o.resolve()),a&&(u(await a),p(n.getConfig()),o.resolve());async function m(){let n=e.customizations?.css;n&&t.sendLifecycle({clientLifecycle:`modal-css`,data:{cssLink:n}})}async function h(){let n=e.customizations?.i18n;n&&t.sendLifecycle({clientLifecycle:`modal-i18n`,data:{i18n:n}})}async function g(){if(typeof window>`u`)return;let e=window.localStorage.getItem(d);e&&t.sendLifecycle({clientLifecycle:`restore-backup`,data:{backup:e}})}(await Promise.allSettled([m(),h(),g()])).some(e=>e.status===`rejected`)&&s?.track(`sdk_iframe_handshake_failed`,{reason:`asset_push`})}async function G({config:e}){let t=K(e),n=await C({config:t});if(!n){console.error(`Failed to create iframe`);return}let r=H({config:t,iframe:n});if(await r.waitForSetup,!await r.waitForConnection){console.error(`Failed to connect to client`);return}return r}function K(e){let t=v(e.metadata?.currency);return{...e,metadata:{...e.metadata,currency:t}}}export{g as _,D as a,f as b,S as c,x as d,b as f,p as g,_ as h,j as i,C as l,v as m,H as n,k as o,y as p,N as r,A as s,G as t,T as u,m as v,u as x,h as y};
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"url": "https://twitter.com/QNivelais"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
14
|
-
"version": "1.0.
|
|
14
|
+
"version": "1.0.1",
|
|
15
15
|
"description": "Core SDK of the Frak wallet, low level library to interact directly with the frak ecosystem.",
|
|
16
16
|
"repository": {
|
|
17
17
|
"url": "https://github.com/frak-id/wallet",
|