@frak-labs/core-sdk 1.1.5-beta.5b65e64f → 1.1.5-beta.7c6aae18
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/dist/actions.d.cts +2 -2
- package/dist/actions.d.ts +2 -2
- package/dist/bundle.d.cts +3 -3
- package/dist/bundle.d.ts +3 -3
- package/dist/{index-CiHjUnfc.d.ts → index-CD-GW6rL.d.ts} +2 -2
- package/dist/{index-D25z5B9K.d.cts → index-D5_EwZ3f.d.cts} +2 -2
- package/dist/{index-BCoPwxjq.d.cts → index-DPez7SXh.d.cts} +2 -2
- package/dist/{index-trhAN7q9.d.ts → index-DQYipoH_.d.ts} +2 -2
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/{openSso-CENLMWJx.d.ts → openSso-CjZ8lAEA.d.ts} +5 -3
- package/dist/{openSso-CKvkAGts.d.cts → openSso-DSXbUP-j.d.cts} +5 -3
- package/dist/rewards.cjs +1 -1
- package/dist/rewards.cjs.map +1 -1
- package/dist/rewards.d.cts +22 -4
- package/dist/rewards.d.ts +22 -4
- package/dist/rewards.js +1 -1
- package/dist/rewards.js.map +1 -1
- package/package.json +2 -2
- package/src/rewards/index.ts +2 -0
- package/src/rewards/select.ts +42 -7
- package/src/types/resolvedConfig.ts +4 -0
package/dist/actions.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as openSso } from "./openSso-
|
|
2
|
-
import { C as displayEmbeddedWallet, S as displayModal, _ as getUserReferralStatus, a as ModalBuilder, b as ensureIdentity, c as watchWalletStatus, d as REFERRAL_SUCCESS_EVENT, f as setupReferral, g as prepareSso, h as processReferral, i as sendTransaction, l as trackPurchaseStatus, m as ProcessReferralOptions, n as siweAuthenticate, o as ModalStepBuilder, p as referralInteraction, r as SendTransactionParams, s as modalBuilder, t as SiweAuthenticateModalParams, u as sendInteraction, v as getMergeToken, x as displaySharingPage, y as getMerchantInformation } from "./index-
|
|
1
|
+
import { t as openSso } from "./openSso-DSXbUP-j.cjs";
|
|
2
|
+
import { C as displayEmbeddedWallet, S as displayModal, _ as getUserReferralStatus, a as ModalBuilder, b as ensureIdentity, c as watchWalletStatus, d as REFERRAL_SUCCESS_EVENT, f as setupReferral, g as prepareSso, h as processReferral, i as sendTransaction, l as trackPurchaseStatus, m as ProcessReferralOptions, n as siweAuthenticate, o as ModalStepBuilder, p as referralInteraction, r as SendTransactionParams, s as modalBuilder, t as SiweAuthenticateModalParams, u as sendInteraction, v as getMergeToken, x as displaySharingPage, y as getMerchantInformation } from "./index-DPez7SXh.cjs";
|
|
3
3
|
export { type ModalBuilder, type ModalStepBuilder, type ProcessReferralOptions, REFERRAL_SUCCESS_EVENT, type SendTransactionParams, type SiweAuthenticateModalParams, displayEmbeddedWallet, displayModal, displaySharingPage, ensureIdentity, getMerchantInformation, getMergeToken, getUserReferralStatus, modalBuilder, openSso, prepareSso, processReferral, referralInteraction, sendInteraction, sendTransaction, setupReferral, siweAuthenticate, trackPurchaseStatus, watchWalletStatus };
|
package/dist/actions.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as openSso } from "./openSso-
|
|
2
|
-
import { C as displayEmbeddedWallet, S as displayModal, _ as getUserReferralStatus, a as ModalBuilder, b as ensureIdentity, c as watchWalletStatus, d as REFERRAL_SUCCESS_EVENT, f as setupReferral, g as prepareSso, h as processReferral, i as sendTransaction, l as trackPurchaseStatus, m as ProcessReferralOptions, n as siweAuthenticate, o as ModalStepBuilder, p as referralInteraction, r as SendTransactionParams, s as modalBuilder, t as SiweAuthenticateModalParams, u as sendInteraction, v as getMergeToken, x as displaySharingPage, y as getMerchantInformation } from "./index-
|
|
1
|
+
import { t as openSso } from "./openSso-CjZ8lAEA.js";
|
|
2
|
+
import { C as displayEmbeddedWallet, S as displayModal, _ as getUserReferralStatus, a as ModalBuilder, b as ensureIdentity, c as watchWalletStatus, d as REFERRAL_SUCCESS_EVENT, f as setupReferral, g as prepareSso, h as processReferral, i as sendTransaction, l as trackPurchaseStatus, m as ProcessReferralOptions, n as siweAuthenticate, o as ModalStepBuilder, p as referralInteraction, r as SendTransactionParams, s as modalBuilder, t as SiweAuthenticateModalParams, u as sendInteraction, v as getMergeToken, x as displaySharingPage, y as getMerchantInformation } from "./index-DQYipoH_.js";
|
|
3
3
|
export { type ModalBuilder, type ModalStepBuilder, type ProcessReferralOptions, REFERRAL_SUCCESS_EVENT, type SendTransactionParams, type SiweAuthenticateModalParams, displayEmbeddedWallet, displayModal, displaySharingPage, ensureIdentity, getMerchantInformation, getMergeToken, getUserReferralStatus, modalBuilder, openSso, prepareSso, processReferral, referralInteraction, sendInteraction, sendTransaction, setupReferral, siweAuthenticate, trackPurchaseStatus, watchWalletStatus };
|
package/dist/bundle.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { S as UtmParams, _ as LocalizedI18nConfig, a as MerchantReward, b as TrackArrivalParams, c as RuleConditions, d as InteractionTypeKey, f as Currency, g as ListenerPreloadOption, h as Language, i as GetMerchantInformationReturnType, l as RuleField, m as I18nConfig, n as ConditionOperator, o as RewardTier, p as FrakWalletSdkConfig, r as EstimatedReward, s as RuleCondition, t as ConditionGroup, u as TokenAmountType, v as AttributionDefaults, x as TrackArrivalResult, y as AttributionParams } from "./merchantInformation-BSuahpjl.cjs";
|
|
2
|
-
import { A as SendTransactionTxType, B as FinalActionType, C as DisplayModalParamsType, D as ModalStepTypes, E as ModalRpcStepsResultType, F as OpenSsoParamsType, G as MerchantConfigResponse, H as ModalStepMetadata, I as OpenSsoReturnType, J as SdkResolvedConfig, K as ResolvedPlacement, L as PrepareSsoParamsType, M as SiweAuthenticateReturnType, N as SiweAuthenticationParams, O as SendTransactionModalStepType, P as LoginModalStepType, R as PrepareSsoReturnType, S as SharingPageProduct, T as ModalRpcStepsInput, U as IFrameLifecycleEvent, V as FinalModalStepType, W as ClientLifecycleEvent, _ as EmbeddedViewActionReferred, a as FrakContextV1, b as DisplaySharingPageParamsType, c as FrakLifecycleEvent, d as WalletStatusReturnType, f as UserReferralStatusType, g as LoggedOutEmbeddedView, h as DisplayEmbeddedWalletResultType, i as FrakContext, j as SiweAuthenticateModalStepType, k as SendTransactionReturnType, l as IFrameTransport, m as DisplayEmbeddedWalletParamsType, n as ssoPopupFeatures, o as FrakContextV2, p as SendInteractionParamsType, q as ResolvedSdkConfig, r as ssoPopupName, s as FrakClient, t as openSso, u as IFrameRpcSchema, v as EmbeddedViewActionSharing, w as ModalRpcMetadata, x as DisplaySharingPageResultType, y as LoggedInEmbeddedView, z as SsoMetadata } from "./openSso-
|
|
3
|
-
import { A as DEEP_LINK_SCHEME, C as triggerDeepLinkWithFallback, D as MergeAttributionInput, E as SdkHandshakeFailureReason, F as createIFrameFrakClient, I as CompressedData, L as HashProtectedData, M as getClientId, N as getBackendUrl, O as mergeAttribution, P as setupClient, R as KeyProvider, S as DeepLinkFallbackOptions, T as SdkEventMap, _ as withCache, a as FullSsoParams, b as isMobile, c as findIframeInOpener, d as formatAmount, f as decompressJsonFromB64, g as clearAllCache, h as base64urlEncode, i as CompressedSsoData, j as sdkConfigStore, k as FrakContextManager, l as getSupportedCurrency, m as base64urlDecode, n as getQueryParamCaseInsensitive, o as generateSsoUrl, p as compressJsonToB64, r as AppSpecificSsoMetadata, s as baseIframeProps, t as deleteQueryParamCaseInsensitive, u as getCurrencyAmountKey, v as isIOS, w as trackEvent, x as redirectToExternalBrowser, y as isInAppBrowser } from "./index-
|
|
4
|
-
import { C as displayEmbeddedWallet, S as displayModal, _ as getUserReferralStatus, a as ModalBuilder, b as ensureIdentity, c as watchWalletStatus, d as REFERRAL_SUCCESS_EVENT, f as setupReferral, g as prepareSso, h as processReferral, i as sendTransaction, l as trackPurchaseStatus, m as ProcessReferralOptions, n as siweAuthenticate, o as ModalStepBuilder, p as referralInteraction, r as SendTransactionParams, s as modalBuilder, t as SiweAuthenticateModalParams, u as sendInteraction, v as getMergeToken, x as displaySharingPage, y as getMerchantInformation } from "./index-
|
|
2
|
+
import { A as SendTransactionTxType, B as FinalActionType, C as DisplayModalParamsType, D as ModalStepTypes, E as ModalRpcStepsResultType, F as OpenSsoParamsType, G as MerchantConfigResponse, H as ModalStepMetadata, I as OpenSsoReturnType, J as SdkResolvedConfig, K as ResolvedPlacement, L as PrepareSsoParamsType, M as SiweAuthenticateReturnType, N as SiweAuthenticationParams, O as SendTransactionModalStepType, P as LoginModalStepType, R as PrepareSsoReturnType, S as SharingPageProduct, T as ModalRpcStepsInput, U as IFrameLifecycleEvent, V as FinalModalStepType, W as ClientLifecycleEvent, _ as EmbeddedViewActionReferred, a as FrakContextV1, b as DisplaySharingPageParamsType, c as FrakLifecycleEvent, d as WalletStatusReturnType, f as UserReferralStatusType, g as LoggedOutEmbeddedView, h as DisplayEmbeddedWalletResultType, i as FrakContext, j as SiweAuthenticateModalStepType, k as SendTransactionReturnType, l as IFrameTransport, m as DisplayEmbeddedWalletParamsType, n as ssoPopupFeatures, o as FrakContextV2, p as SendInteractionParamsType, q as ResolvedSdkConfig, r as ssoPopupName, s as FrakClient, t as openSso, u as IFrameRpcSchema, v as EmbeddedViewActionSharing, w as ModalRpcMetadata, x as DisplaySharingPageResultType, y as LoggedInEmbeddedView, z as SsoMetadata } from "./openSso-DSXbUP-j.cjs";
|
|
3
|
+
import { A as DEEP_LINK_SCHEME, C as triggerDeepLinkWithFallback, D as MergeAttributionInput, E as SdkHandshakeFailureReason, F as createIFrameFrakClient, I as CompressedData, L as HashProtectedData, M as getClientId, N as getBackendUrl, O as mergeAttribution, P as setupClient, R as KeyProvider, S as DeepLinkFallbackOptions, T as SdkEventMap, _ as withCache, a as FullSsoParams, b as isMobile, c as findIframeInOpener, d as formatAmount, f as decompressJsonFromB64, g as clearAllCache, h as base64urlEncode, i as CompressedSsoData, j as sdkConfigStore, k as FrakContextManager, l as getSupportedCurrency, m as base64urlDecode, n as getQueryParamCaseInsensitive, o as generateSsoUrl, p as compressJsonToB64, r as AppSpecificSsoMetadata, s as baseIframeProps, t as deleteQueryParamCaseInsensitive, u as getCurrencyAmountKey, v as isIOS, w as trackEvent, x as redirectToExternalBrowser, y as isInAppBrowser } from "./index-D5_EwZ3f.cjs";
|
|
4
|
+
import { C as displayEmbeddedWallet, S as displayModal, _ as getUserReferralStatus, a as ModalBuilder, b as ensureIdentity, c as watchWalletStatus, d as REFERRAL_SUCCESS_EVENT, f as setupReferral, g as prepareSso, h as processReferral, i as sendTransaction, l as trackPurchaseStatus, m as ProcessReferralOptions, n as siweAuthenticate, o as ModalStepBuilder, p as referralInteraction, r as SendTransactionParams, s as modalBuilder, t as SiweAuthenticateModalParams, u as sendInteraction, v as getMergeToken, x as displaySharingPage, y as getMerchantInformation } from "./index-DPez7SXh.cjs";
|
|
5
5
|
export { type AppSpecificSsoMetadata, type AttributionDefaults, type AttributionParams, type ClientLifecycleEvent, type CompressedData, type CompressedSsoData, type ConditionGroup, type ConditionOperator, type Currency, DEEP_LINK_SCHEME, type DeepLinkFallbackOptions, type DisplayEmbeddedWalletParamsType, type DisplayEmbeddedWalletResultType, type DisplayModalParamsType, type DisplaySharingPageParamsType, type DisplaySharingPageResultType, type EmbeddedViewActionReferred, type EmbeddedViewActionSharing, type EstimatedReward, type FinalActionType, type FinalModalStepType, type FrakClient, type FrakContext, FrakContextManager, type FrakContextV1, type FrakContextV2, type FrakLifecycleEvent, type FrakWalletSdkConfig, type FullSsoParams, type GetMerchantInformationReturnType, type HashProtectedData, type I18nConfig, type IFrameLifecycleEvent, type IFrameRpcSchema, type IFrameTransport, type InteractionTypeKey, type KeyProvider, type Language, type ListenerPreloadOption, type LocalizedI18nConfig, type LoggedInEmbeddedView, type LoggedOutEmbeddedView, type LoginModalStepType, type MerchantConfigResponse, type MerchantReward, type MergeAttributionInput, type ModalBuilder, type ModalRpcMetadata, type ModalRpcStepsInput, type ModalRpcStepsResultType, type ModalStepBuilder, type ModalStepMetadata, type ModalStepTypes, type OpenSsoParamsType, type OpenSsoReturnType, type PrepareSsoParamsType, type PrepareSsoReturnType, type ProcessReferralOptions, REFERRAL_SUCCESS_EVENT, type ResolvedPlacement, type ResolvedSdkConfig, type RewardTier, type RuleCondition, type RuleConditions, type RuleField, type SdkEventMap, type SdkHandshakeFailureReason, type SdkResolvedConfig, type SendInteractionParamsType, type SendTransactionModalStepType, type SendTransactionParams, type SendTransactionReturnType, type SendTransactionTxType, type SharingPageProduct, type SiweAuthenticateModalParams, type SiweAuthenticateModalStepType, type SiweAuthenticateReturnType, type SiweAuthenticationParams, type SsoMetadata, type TokenAmountType, type TrackArrivalParams, type TrackArrivalResult, type UserReferralStatusType, type UtmParams, type WalletStatusReturnType, base64urlDecode, base64urlEncode, baseIframeProps, clearAllCache, compressJsonToB64, createIFrameFrakClient, decompressJsonFromB64, deleteQueryParamCaseInsensitive, displayEmbeddedWallet, displayModal, displaySharingPage, ensureIdentity, findIframeInOpener, formatAmount, generateSsoUrl, getBackendUrl, getClientId, getCurrencyAmountKey, getMerchantInformation, getMergeToken, getQueryParamCaseInsensitive, getSupportedCurrency, getUserReferralStatus, isIOS, isInAppBrowser, isMobile, mergeAttribution, modalBuilder, openSso, prepareSso, processReferral, redirectToExternalBrowser, referralInteraction, sdkConfigStore, sendInteraction, sendTransaction, setupClient, setupReferral, siweAuthenticate, ssoPopupFeatures, ssoPopupName, trackEvent, trackPurchaseStatus, triggerDeepLinkWithFallback, watchWalletStatus, withCache };
|
package/dist/bundle.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { S as UtmParams, _ as LocalizedI18nConfig, a as MerchantReward, b as TrackArrivalParams, c as RuleConditions, d as InteractionTypeKey, f as Currency, g as ListenerPreloadOption, h as Language, i as GetMerchantInformationReturnType, l as RuleField, m as I18nConfig, n as ConditionOperator, o as RewardTier, p as FrakWalletSdkConfig, r as EstimatedReward, s as RuleCondition, t as ConditionGroup, u as TokenAmountType, v as AttributionDefaults, x as TrackArrivalResult, y as AttributionParams } from "./merchantInformation--tLnowAN.js";
|
|
2
|
-
import { A as SendTransactionTxType, B as FinalActionType, C as DisplayModalParamsType, D as ModalStepTypes, E as ModalRpcStepsResultType, F as OpenSsoParamsType, G as MerchantConfigResponse, H as ModalStepMetadata, I as OpenSsoReturnType, J as SdkResolvedConfig, K as ResolvedPlacement, L as PrepareSsoParamsType, M as SiweAuthenticateReturnType, N as SiweAuthenticationParams, O as SendTransactionModalStepType, P as LoginModalStepType, R as PrepareSsoReturnType, S as SharingPageProduct, T as ModalRpcStepsInput, U as IFrameLifecycleEvent, V as FinalModalStepType, W as ClientLifecycleEvent, _ as EmbeddedViewActionReferred, a as FrakContextV1, b as DisplaySharingPageParamsType, c as FrakLifecycleEvent, d as WalletStatusReturnType, f as UserReferralStatusType, g as LoggedOutEmbeddedView, h as DisplayEmbeddedWalletResultType, i as FrakContext, j as SiweAuthenticateModalStepType, k as SendTransactionReturnType, l as IFrameTransport, m as DisplayEmbeddedWalletParamsType, n as ssoPopupFeatures, o as FrakContextV2, p as SendInteractionParamsType, q as ResolvedSdkConfig, r as ssoPopupName, s as FrakClient, t as openSso, u as IFrameRpcSchema, v as EmbeddedViewActionSharing, w as ModalRpcMetadata, x as DisplaySharingPageResultType, y as LoggedInEmbeddedView, z as SsoMetadata } from "./openSso-
|
|
3
|
-
import { A as DEEP_LINK_SCHEME, C as triggerDeepLinkWithFallback, D as MergeAttributionInput, E as SdkHandshakeFailureReason, F as createIFrameFrakClient, I as CompressedData, L as HashProtectedData, M as getClientId, N as getBackendUrl, O as mergeAttribution, P as setupClient, R as KeyProvider, S as DeepLinkFallbackOptions, T as SdkEventMap, _ as withCache, a as FullSsoParams, b as isMobile, c as findIframeInOpener, d as formatAmount, f as decompressJsonFromB64, g as clearAllCache, h as base64urlEncode, i as CompressedSsoData, j as sdkConfigStore, k as FrakContextManager, l as getSupportedCurrency, m as base64urlDecode, n as getQueryParamCaseInsensitive, o as generateSsoUrl, p as compressJsonToB64, r as AppSpecificSsoMetadata, s as baseIframeProps, t as deleteQueryParamCaseInsensitive, u as getCurrencyAmountKey, v as isIOS, w as trackEvent, x as redirectToExternalBrowser, y as isInAppBrowser } from "./index-
|
|
4
|
-
import { C as displayEmbeddedWallet, S as displayModal, _ as getUserReferralStatus, a as ModalBuilder, b as ensureIdentity, c as watchWalletStatus, d as REFERRAL_SUCCESS_EVENT, f as setupReferral, g as prepareSso, h as processReferral, i as sendTransaction, l as trackPurchaseStatus, m as ProcessReferralOptions, n as siweAuthenticate, o as ModalStepBuilder, p as referralInteraction, r as SendTransactionParams, s as modalBuilder, t as SiweAuthenticateModalParams, u as sendInteraction, v as getMergeToken, x as displaySharingPage, y as getMerchantInformation } from "./index-
|
|
2
|
+
import { A as SendTransactionTxType, B as FinalActionType, C as DisplayModalParamsType, D as ModalStepTypes, E as ModalRpcStepsResultType, F as OpenSsoParamsType, G as MerchantConfigResponse, H as ModalStepMetadata, I as OpenSsoReturnType, J as SdkResolvedConfig, K as ResolvedPlacement, L as PrepareSsoParamsType, M as SiweAuthenticateReturnType, N as SiweAuthenticationParams, O as SendTransactionModalStepType, P as LoginModalStepType, R as PrepareSsoReturnType, S as SharingPageProduct, T as ModalRpcStepsInput, U as IFrameLifecycleEvent, V as FinalModalStepType, W as ClientLifecycleEvent, _ as EmbeddedViewActionReferred, a as FrakContextV1, b as DisplaySharingPageParamsType, c as FrakLifecycleEvent, d as WalletStatusReturnType, f as UserReferralStatusType, g as LoggedOutEmbeddedView, h as DisplayEmbeddedWalletResultType, i as FrakContext, j as SiweAuthenticateModalStepType, k as SendTransactionReturnType, l as IFrameTransport, m as DisplayEmbeddedWalletParamsType, n as ssoPopupFeatures, o as FrakContextV2, p as SendInteractionParamsType, q as ResolvedSdkConfig, r as ssoPopupName, s as FrakClient, t as openSso, u as IFrameRpcSchema, v as EmbeddedViewActionSharing, w as ModalRpcMetadata, x as DisplaySharingPageResultType, y as LoggedInEmbeddedView, z as SsoMetadata } from "./openSso-CjZ8lAEA.js";
|
|
3
|
+
import { A as DEEP_LINK_SCHEME, C as triggerDeepLinkWithFallback, D as MergeAttributionInput, E as SdkHandshakeFailureReason, F as createIFrameFrakClient, I as CompressedData, L as HashProtectedData, M as getClientId, N as getBackendUrl, O as mergeAttribution, P as setupClient, R as KeyProvider, S as DeepLinkFallbackOptions, T as SdkEventMap, _ as withCache, a as FullSsoParams, b as isMobile, c as findIframeInOpener, d as formatAmount, f as decompressJsonFromB64, g as clearAllCache, h as base64urlEncode, i as CompressedSsoData, j as sdkConfigStore, k as FrakContextManager, l as getSupportedCurrency, m as base64urlDecode, n as getQueryParamCaseInsensitive, o as generateSsoUrl, p as compressJsonToB64, r as AppSpecificSsoMetadata, s as baseIframeProps, t as deleteQueryParamCaseInsensitive, u as getCurrencyAmountKey, v as isIOS, w as trackEvent, x as redirectToExternalBrowser, y as isInAppBrowser } from "./index-CD-GW6rL.js";
|
|
4
|
+
import { C as displayEmbeddedWallet, S as displayModal, _ as getUserReferralStatus, a as ModalBuilder, b as ensureIdentity, c as watchWalletStatus, d as REFERRAL_SUCCESS_EVENT, f as setupReferral, g as prepareSso, h as processReferral, i as sendTransaction, l as trackPurchaseStatus, m as ProcessReferralOptions, n as siweAuthenticate, o as ModalStepBuilder, p as referralInteraction, r as SendTransactionParams, s as modalBuilder, t as SiweAuthenticateModalParams, u as sendInteraction, v as getMergeToken, x as displaySharingPage, y as getMerchantInformation } from "./index-DQYipoH_.js";
|
|
5
5
|
export { type AppSpecificSsoMetadata, type AttributionDefaults, type AttributionParams, type ClientLifecycleEvent, type CompressedData, type CompressedSsoData, type ConditionGroup, type ConditionOperator, type Currency, DEEP_LINK_SCHEME, type DeepLinkFallbackOptions, type DisplayEmbeddedWalletParamsType, type DisplayEmbeddedWalletResultType, type DisplayModalParamsType, type DisplaySharingPageParamsType, type DisplaySharingPageResultType, type EmbeddedViewActionReferred, type EmbeddedViewActionSharing, type EstimatedReward, type FinalActionType, type FinalModalStepType, type FrakClient, type FrakContext, FrakContextManager, type FrakContextV1, type FrakContextV2, type FrakLifecycleEvent, type FrakWalletSdkConfig, type FullSsoParams, type GetMerchantInformationReturnType, type HashProtectedData, type I18nConfig, type IFrameLifecycleEvent, type IFrameRpcSchema, type IFrameTransport, type InteractionTypeKey, type KeyProvider, type Language, type ListenerPreloadOption, type LocalizedI18nConfig, type LoggedInEmbeddedView, type LoggedOutEmbeddedView, type LoginModalStepType, type MerchantConfigResponse, type MerchantReward, type MergeAttributionInput, type ModalBuilder, type ModalRpcMetadata, type ModalRpcStepsInput, type ModalRpcStepsResultType, type ModalStepBuilder, type ModalStepMetadata, type ModalStepTypes, type OpenSsoParamsType, type OpenSsoReturnType, type PrepareSsoParamsType, type PrepareSsoReturnType, type ProcessReferralOptions, REFERRAL_SUCCESS_EVENT, type ResolvedPlacement, type ResolvedSdkConfig, type RewardTier, type RuleCondition, type RuleConditions, type RuleField, type SdkEventMap, type SdkHandshakeFailureReason, type SdkResolvedConfig, type SendInteractionParamsType, type SendTransactionModalStepType, type SendTransactionParams, type SendTransactionReturnType, type SendTransactionTxType, type SharingPageProduct, type SiweAuthenticateModalParams, type SiweAuthenticateModalStepType, type SiweAuthenticateReturnType, type SiweAuthenticationParams, type SsoMetadata, type TokenAmountType, type TrackArrivalParams, type TrackArrivalResult, type UserReferralStatusType, type UtmParams, type WalletStatusReturnType, base64urlDecode, base64urlEncode, baseIframeProps, clearAllCache, compressJsonToB64, createIFrameFrakClient, decompressJsonFromB64, deleteQueryParamCaseInsensitive, displayEmbeddedWallet, displayModal, displaySharingPage, ensureIdentity, findIframeInOpener, formatAmount, generateSsoUrl, getBackendUrl, getClientId, getCurrencyAmountKey, getMerchantInformation, getMergeToken, getQueryParamCaseInsensitive, getSupportedCurrency, getUserReferralStatus, isIOS, isInAppBrowser, isMobile, mergeAttribution, modalBuilder, openSso, prepareSso, processReferral, redirectToExternalBrowser, referralInteraction, sdkConfigStore, sendInteraction, sendTransaction, setupClient, setupReferral, siweAuthenticate, ssoPopupFeatures, ssoPopupName, trackEvent, trackPurchaseStatus, triggerDeepLinkWithFallback, watchWalletStatus, withCache };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { f as Currency, h as Language, p as FrakWalletSdkConfig, u as TokenAmountType, v as AttributionDefaults, y as AttributionParams } from "./merchantInformation--tLnowAN.js";
|
|
2
|
-
import { G as MerchantConfigResponse, J as SdkResolvedConfig, L as PrepareSsoParamsType, a as FrakContextV1, i as FrakContext, o as FrakContextV2, s as FrakClient, z as SsoMetadata } from "./openSso-
|
|
2
|
+
import { G as MerchantConfigResponse, J as SdkResolvedConfig, L as PrepareSsoParamsType, a as FrakContextV1, i as FrakContext, o as FrakContextV2, s as FrakClient, z as SsoMetadata } from "./openSso-CjZ8lAEA.js";
|
|
3
3
|
import { Hex } from "viem";
|
|
4
4
|
|
|
5
5
|
//#region src/types/compression.d.ts
|
|
@@ -646,4 +646,4 @@ declare function getQueryParamCaseInsensitive(searchParams: URLSearchParams, key
|
|
|
646
646
|
declare function deleteQueryParamCaseInsensitive(searchParams: URLSearchParams, key: string): void;
|
|
647
647
|
//#endregion
|
|
648
648
|
export { DEEP_LINK_SCHEME as A, triggerDeepLinkWithFallback as C, MergeAttributionInput as D, SdkHandshakeFailureReason as E, createIFrameFrakClient as F, CompressedData as I, HashProtectedData as L, getClientId as M, getBackendUrl as N, mergeAttribution as O, setupClient as P, KeyProvider as R, DeepLinkFallbackOptions as S, SdkEventMap as T, withCache as _, FullSsoParams as a, isMobile as b, findIframeInOpener as c, formatAmount as d, decompressJsonFromB64 as f, clearAllCache as g, base64urlEncode as h, CompressedSsoData as i, sdkConfigStore as j, FrakContextManager as k, getSupportedCurrency as l, base64urlDecode as m, getQueryParamCaseInsensitive as n, generateSsoUrl as o, compressJsonToB64 as p, AppSpecificSsoMetadata as r, baseIframeProps as s, deleteQueryParamCaseInsensitive as t, getCurrencyAmountKey as u, isIOS as v, trackEvent as w, redirectToExternalBrowser as x, isInAppBrowser as y };
|
|
649
|
-
//# sourceMappingURL=index-
|
|
649
|
+
//# sourceMappingURL=index-CD-GW6rL.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { f as Currency, h as Language, p as FrakWalletSdkConfig, u as TokenAmountType, v as AttributionDefaults, y as AttributionParams } from "./merchantInformation-BSuahpjl.cjs";
|
|
2
|
-
import { G as MerchantConfigResponse, J as SdkResolvedConfig, L as PrepareSsoParamsType, a as FrakContextV1, i as FrakContext, o as FrakContextV2, s as FrakClient, z as SsoMetadata } from "./openSso-
|
|
2
|
+
import { G as MerchantConfigResponse, J as SdkResolvedConfig, L as PrepareSsoParamsType, a as FrakContextV1, i as FrakContext, o as FrakContextV2, s as FrakClient, z as SsoMetadata } from "./openSso-DSXbUP-j.cjs";
|
|
3
3
|
import { Hex } from "viem";
|
|
4
4
|
|
|
5
5
|
//#region src/types/compression.d.ts
|
|
@@ -646,4 +646,4 @@ declare function getQueryParamCaseInsensitive(searchParams: URLSearchParams, key
|
|
|
646
646
|
declare function deleteQueryParamCaseInsensitive(searchParams: URLSearchParams, key: string): void;
|
|
647
647
|
//#endregion
|
|
648
648
|
export { DEEP_LINK_SCHEME as A, triggerDeepLinkWithFallback as C, MergeAttributionInput as D, SdkHandshakeFailureReason as E, createIFrameFrakClient as F, CompressedData as I, HashProtectedData as L, getClientId as M, getBackendUrl as N, mergeAttribution as O, setupClient as P, KeyProvider as R, DeepLinkFallbackOptions as S, SdkEventMap as T, withCache as _, FullSsoParams as a, isMobile as b, findIframeInOpener as c, formatAmount as d, decompressJsonFromB64 as f, clearAllCache as g, base64urlEncode as h, CompressedSsoData as i, sdkConfigStore as j, FrakContextManager as k, getSupportedCurrency as l, base64urlDecode as m, getQueryParamCaseInsensitive as n, generateSsoUrl as o, compressJsonToB64 as p, AppSpecificSsoMetadata as r, baseIframeProps as s, deleteQueryParamCaseInsensitive as t, getCurrencyAmountKey as u, isIOS as v, trackEvent as w, redirectToExternalBrowser as x, isInAppBrowser as y };
|
|
649
|
-
//# sourceMappingURL=index-
|
|
649
|
+
//# sourceMappingURL=index-D5_EwZ3f.d.cts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as GetMerchantInformationReturnType } from "./merchantInformation-BSuahpjl.cjs";
|
|
2
|
-
import { B as FinalActionType, C as DisplayModalParamsType, D as ModalStepTypes, E as ModalRpcStepsResultType, L as PrepareSsoParamsType, M as SiweAuthenticateReturnType, N as SiweAuthenticationParams, O as SendTransactionModalStepType, P as LoginModalStepType, R as PrepareSsoReturnType, V as FinalModalStepType, b as DisplaySharingPageParamsType, d as WalletStatusReturnType, f as UserReferralStatusType, h as DisplayEmbeddedWalletResultType, i as FrakContext, k as SendTransactionReturnType, m as DisplayEmbeddedWalletParamsType, p as SendInteractionParamsType, s as FrakClient, w as ModalRpcMetadata, x as DisplaySharingPageResultType } from "./openSso-
|
|
2
|
+
import { B as FinalActionType, C as DisplayModalParamsType, D as ModalStepTypes, E as ModalRpcStepsResultType, L as PrepareSsoParamsType, M as SiweAuthenticateReturnType, N as SiweAuthenticationParams, O as SendTransactionModalStepType, P as LoginModalStepType, R as PrepareSsoReturnType, V as FinalModalStepType, b as DisplaySharingPageParamsType, d as WalletStatusReturnType, f as UserReferralStatusType, h as DisplayEmbeddedWalletResultType, i as FrakContext, k as SendTransactionReturnType, m as DisplayEmbeddedWalletParamsType, p as SendInteractionParamsType, s as FrakClient, w as ModalRpcMetadata, x as DisplaySharingPageResultType } from "./openSso-DSXbUP-j.cjs";
|
|
3
3
|
|
|
4
4
|
//#region src/actions/displayEmbeddedWallet.d.ts
|
|
5
5
|
/**
|
|
@@ -645,4 +645,4 @@ declare function siweAuthenticate(client: FrakClient, {
|
|
|
645
645
|
}: SiweAuthenticateModalParams): Promise<SiweAuthenticateReturnType>;
|
|
646
646
|
//#endregion
|
|
647
647
|
export { displayEmbeddedWallet as C, displayModal as S, getUserReferralStatus as _, ModalBuilder as a, ensureIdentity as b, watchWalletStatus as c, REFERRAL_SUCCESS_EVENT as d, setupReferral as f, prepareSso as g, processReferral as h, sendTransaction as i, trackPurchaseStatus as l, ProcessReferralOptions as m, siweAuthenticate as n, ModalStepBuilder as o, referralInteraction as p, SendTransactionParams as r, modalBuilder as s, SiweAuthenticateModalParams as t, sendInteraction as u, getMergeToken as v, displaySharingPage as x, getMerchantInformation as y };
|
|
648
|
-
//# sourceMappingURL=index-
|
|
648
|
+
//# sourceMappingURL=index-DPez7SXh.d.cts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as GetMerchantInformationReturnType } from "./merchantInformation--tLnowAN.js";
|
|
2
|
-
import { B as FinalActionType, C as DisplayModalParamsType, D as ModalStepTypes, E as ModalRpcStepsResultType, L as PrepareSsoParamsType, M as SiweAuthenticateReturnType, N as SiweAuthenticationParams, O as SendTransactionModalStepType, P as LoginModalStepType, R as PrepareSsoReturnType, V as FinalModalStepType, b as DisplaySharingPageParamsType, d as WalletStatusReturnType, f as UserReferralStatusType, h as DisplayEmbeddedWalletResultType, i as FrakContext, k as SendTransactionReturnType, m as DisplayEmbeddedWalletParamsType, p as SendInteractionParamsType, s as FrakClient, w as ModalRpcMetadata, x as DisplaySharingPageResultType } from "./openSso-
|
|
2
|
+
import { B as FinalActionType, C as DisplayModalParamsType, D as ModalStepTypes, E as ModalRpcStepsResultType, L as PrepareSsoParamsType, M as SiweAuthenticateReturnType, N as SiweAuthenticationParams, O as SendTransactionModalStepType, P as LoginModalStepType, R as PrepareSsoReturnType, V as FinalModalStepType, b as DisplaySharingPageParamsType, d as WalletStatusReturnType, f as UserReferralStatusType, h as DisplayEmbeddedWalletResultType, i as FrakContext, k as SendTransactionReturnType, m as DisplayEmbeddedWalletParamsType, p as SendInteractionParamsType, s as FrakClient, w as ModalRpcMetadata, x as DisplaySharingPageResultType } from "./openSso-CjZ8lAEA.js";
|
|
3
3
|
|
|
4
4
|
//#region src/actions/displayEmbeddedWallet.d.ts
|
|
5
5
|
/**
|
|
@@ -645,4 +645,4 @@ declare function siweAuthenticate(client: FrakClient, {
|
|
|
645
645
|
}: SiweAuthenticateModalParams): Promise<SiweAuthenticateReturnType>;
|
|
646
646
|
//#endregion
|
|
647
647
|
export { displayEmbeddedWallet as C, displayModal as S, getUserReferralStatus as _, ModalBuilder as a, ensureIdentity as b, watchWalletStatus as c, REFERRAL_SUCCESS_EVENT as d, setupReferral as f, prepareSso as g, processReferral as h, sendTransaction as i, trackPurchaseStatus as l, ProcessReferralOptions as m, siweAuthenticate as n, ModalStepBuilder as o, referralInteraction as p, SendTransactionParams as r, modalBuilder as s, SiweAuthenticateModalParams as t, sendInteraction as u, getMergeToken as v, displaySharingPage as x, getMerchantInformation as y };
|
|
648
|
-
//# sourceMappingURL=index-
|
|
648
|
+
//# sourceMappingURL=index-DQYipoH_.d.ts.map
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { S as UtmParams, _ as LocalizedI18nConfig, a as MerchantReward, b as TrackArrivalParams, c as RuleConditions, d as InteractionTypeKey, f as Currency, g as ListenerPreloadOption, h as Language, i as GetMerchantInformationReturnType, l as RuleField, m as I18nConfig, n as ConditionOperator, o as RewardTier, p as FrakWalletSdkConfig, r as EstimatedReward, s as RuleCondition, t as ConditionGroup, u as TokenAmountType, v as AttributionDefaults, x as TrackArrivalResult, y as AttributionParams } from "./merchantInformation-BSuahpjl.cjs";
|
|
2
|
-
import { A as SendTransactionTxType, B as FinalActionType, C as DisplayModalParamsType, D as ModalStepTypes, E as ModalRpcStepsResultType, F as OpenSsoParamsType, G as MerchantConfigResponse, H as ModalStepMetadata, I as OpenSsoReturnType, J as SdkResolvedConfig, K as ResolvedPlacement, L as PrepareSsoParamsType, M as SiweAuthenticateReturnType, N as SiweAuthenticationParams, O as SendTransactionModalStepType, P as LoginModalStepType, R as PrepareSsoReturnType, S as SharingPageProduct, T as ModalRpcStepsInput, U as IFrameLifecycleEvent, V as FinalModalStepType, W as ClientLifecycleEvent, _ as EmbeddedViewActionReferred, a as FrakContextV1, b as DisplaySharingPageParamsType, c as FrakLifecycleEvent, d as WalletStatusReturnType, f as UserReferralStatusType, g as LoggedOutEmbeddedView, h as DisplayEmbeddedWalletResultType, i as FrakContext, j as SiweAuthenticateModalStepType, k as SendTransactionReturnType, l as IFrameTransport, m as DisplayEmbeddedWalletParamsType, n as ssoPopupFeatures, o as FrakContextV2, p as SendInteractionParamsType, q as ResolvedSdkConfig, r as ssoPopupName, s as FrakClient, u as IFrameRpcSchema, v as EmbeddedViewActionSharing, w as ModalRpcMetadata, x as DisplaySharingPageResultType, y as LoggedInEmbeddedView, z as SsoMetadata } from "./openSso-
|
|
3
|
-
import { A as DEEP_LINK_SCHEME, C as triggerDeepLinkWithFallback, D as MergeAttributionInput, E as SdkHandshakeFailureReason, F as createIFrameFrakClient, I as CompressedData, L as HashProtectedData, M as getClientId, N as getBackendUrl, O as mergeAttribution, P as setupClient, R as KeyProvider, S as DeepLinkFallbackOptions, T as SdkEventMap, _ as withCache, a as FullSsoParams, b as isMobile, c as findIframeInOpener, d as formatAmount, f as decompressJsonFromB64, g as clearAllCache, h as base64urlEncode, i as CompressedSsoData, j as sdkConfigStore, k as FrakContextManager, l as getSupportedCurrency, m as base64urlDecode, n as getQueryParamCaseInsensitive, o as generateSsoUrl, p as compressJsonToB64, r as AppSpecificSsoMetadata, s as baseIframeProps, t as deleteQueryParamCaseInsensitive, u as getCurrencyAmountKey, v as isIOS, w as trackEvent, x as redirectToExternalBrowser, y as isInAppBrowser } from "./index-
|
|
2
|
+
import { A as SendTransactionTxType, B as FinalActionType, C as DisplayModalParamsType, D as ModalStepTypes, E as ModalRpcStepsResultType, F as OpenSsoParamsType, G as MerchantConfigResponse, H as ModalStepMetadata, I as OpenSsoReturnType, J as SdkResolvedConfig, K as ResolvedPlacement, L as PrepareSsoParamsType, M as SiweAuthenticateReturnType, N as SiweAuthenticationParams, O as SendTransactionModalStepType, P as LoginModalStepType, R as PrepareSsoReturnType, S as SharingPageProduct, T as ModalRpcStepsInput, U as IFrameLifecycleEvent, V as FinalModalStepType, W as ClientLifecycleEvent, _ as EmbeddedViewActionReferred, a as FrakContextV1, b as DisplaySharingPageParamsType, c as FrakLifecycleEvent, d as WalletStatusReturnType, f as UserReferralStatusType, g as LoggedOutEmbeddedView, h as DisplayEmbeddedWalletResultType, i as FrakContext, j as SiweAuthenticateModalStepType, k as SendTransactionReturnType, l as IFrameTransport, m as DisplayEmbeddedWalletParamsType, n as ssoPopupFeatures, o as FrakContextV2, p as SendInteractionParamsType, q as ResolvedSdkConfig, r as ssoPopupName, s as FrakClient, u as IFrameRpcSchema, v as EmbeddedViewActionSharing, w as ModalRpcMetadata, x as DisplaySharingPageResultType, y as LoggedInEmbeddedView, z as SsoMetadata } from "./openSso-DSXbUP-j.cjs";
|
|
3
|
+
import { A as DEEP_LINK_SCHEME, C as triggerDeepLinkWithFallback, D as MergeAttributionInput, E as SdkHandshakeFailureReason, F as createIFrameFrakClient, I as CompressedData, L as HashProtectedData, M as getClientId, N as getBackendUrl, O as mergeAttribution, P as setupClient, R as KeyProvider, S as DeepLinkFallbackOptions, T as SdkEventMap, _ as withCache, a as FullSsoParams, b as isMobile, c as findIframeInOpener, d as formatAmount, f as decompressJsonFromB64, g as clearAllCache, h as base64urlEncode, i as CompressedSsoData, j as sdkConfigStore, k as FrakContextManager, l as getSupportedCurrency, m as base64urlDecode, n as getQueryParamCaseInsensitive, o as generateSsoUrl, p as compressJsonToB64, r as AppSpecificSsoMetadata, s as baseIframeProps, t as deleteQueryParamCaseInsensitive, u as getCurrencyAmountKey, v as isIOS, w as trackEvent, x as redirectToExternalBrowser, y as isInAppBrowser } from "./index-D5_EwZ3f.cjs";
|
|
4
4
|
export { type AppSpecificSsoMetadata, type AttributionDefaults, type AttributionParams, type ClientLifecycleEvent, type CompressedData, type CompressedSsoData, type ConditionGroup, type ConditionOperator, type Currency, DEEP_LINK_SCHEME, type DeepLinkFallbackOptions, type DisplayEmbeddedWalletParamsType, type DisplayEmbeddedWalletResultType, type DisplayModalParamsType, type DisplaySharingPageParamsType, type DisplaySharingPageResultType, type EmbeddedViewActionReferred, type EmbeddedViewActionSharing, type EstimatedReward, type FinalActionType, type FinalModalStepType, type FrakClient, type FrakContext, FrakContextManager, type FrakContextV1, type FrakContextV2, type FrakLifecycleEvent, type FrakWalletSdkConfig, type FullSsoParams, type GetMerchantInformationReturnType, type HashProtectedData, type I18nConfig, type IFrameLifecycleEvent, type IFrameRpcSchema, type IFrameTransport, type InteractionTypeKey, type KeyProvider, type Language, type ListenerPreloadOption, type LocalizedI18nConfig, type LoggedInEmbeddedView, type LoggedOutEmbeddedView, type LoginModalStepType, type MerchantConfigResponse, type MerchantReward, type MergeAttributionInput, type ModalRpcMetadata, type ModalRpcStepsInput, type ModalRpcStepsResultType, type ModalStepMetadata, type ModalStepTypes, type OpenSsoParamsType, type OpenSsoReturnType, type PrepareSsoParamsType, type PrepareSsoReturnType, type ResolvedPlacement, type ResolvedSdkConfig, type RewardTier, type RuleCondition, type RuleConditions, type RuleField, type SdkEventMap, type SdkHandshakeFailureReason, type SdkResolvedConfig, type SendInteractionParamsType, type SendTransactionModalStepType, type SendTransactionReturnType, type SendTransactionTxType, type SharingPageProduct, type SiweAuthenticateModalStepType, type SiweAuthenticateReturnType, type SiweAuthenticationParams, type SsoMetadata, type TokenAmountType, type TrackArrivalParams, type TrackArrivalResult, type UserReferralStatusType, type UtmParams, type WalletStatusReturnType, base64urlDecode, base64urlEncode, baseIframeProps, clearAllCache, compressJsonToB64, createIFrameFrakClient, decompressJsonFromB64, deleteQueryParamCaseInsensitive, findIframeInOpener, formatAmount, generateSsoUrl, getBackendUrl, getClientId, getCurrencyAmountKey, getQueryParamCaseInsensitive, getSupportedCurrency, isIOS, isInAppBrowser, isMobile, mergeAttribution, redirectToExternalBrowser, sdkConfigStore, setupClient, ssoPopupFeatures, ssoPopupName, trackEvent, triggerDeepLinkWithFallback, withCache };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { S as UtmParams, _ as LocalizedI18nConfig, a as MerchantReward, b as TrackArrivalParams, c as RuleConditions, d as InteractionTypeKey, f as Currency, g as ListenerPreloadOption, h as Language, i as GetMerchantInformationReturnType, l as RuleField, m as I18nConfig, n as ConditionOperator, o as RewardTier, p as FrakWalletSdkConfig, r as EstimatedReward, s as RuleCondition, t as ConditionGroup, u as TokenAmountType, v as AttributionDefaults, x as TrackArrivalResult, y as AttributionParams } from "./merchantInformation--tLnowAN.js";
|
|
2
|
-
import { A as SendTransactionTxType, B as FinalActionType, C as DisplayModalParamsType, D as ModalStepTypes, E as ModalRpcStepsResultType, F as OpenSsoParamsType, G as MerchantConfigResponse, H as ModalStepMetadata, I as OpenSsoReturnType, J as SdkResolvedConfig, K as ResolvedPlacement, L as PrepareSsoParamsType, M as SiweAuthenticateReturnType, N as SiweAuthenticationParams, O as SendTransactionModalStepType, P as LoginModalStepType, R as PrepareSsoReturnType, S as SharingPageProduct, T as ModalRpcStepsInput, U as IFrameLifecycleEvent, V as FinalModalStepType, W as ClientLifecycleEvent, _ as EmbeddedViewActionReferred, a as FrakContextV1, b as DisplaySharingPageParamsType, c as FrakLifecycleEvent, d as WalletStatusReturnType, f as UserReferralStatusType, g as LoggedOutEmbeddedView, h as DisplayEmbeddedWalletResultType, i as FrakContext, j as SiweAuthenticateModalStepType, k as SendTransactionReturnType, l as IFrameTransport, m as DisplayEmbeddedWalletParamsType, n as ssoPopupFeatures, o as FrakContextV2, p as SendInteractionParamsType, q as ResolvedSdkConfig, r as ssoPopupName, s as FrakClient, u as IFrameRpcSchema, v as EmbeddedViewActionSharing, w as ModalRpcMetadata, x as DisplaySharingPageResultType, y as LoggedInEmbeddedView, z as SsoMetadata } from "./openSso-
|
|
3
|
-
import { A as DEEP_LINK_SCHEME, C as triggerDeepLinkWithFallback, D as MergeAttributionInput, E as SdkHandshakeFailureReason, F as createIFrameFrakClient, I as CompressedData, L as HashProtectedData, M as getClientId, N as getBackendUrl, O as mergeAttribution, P as setupClient, R as KeyProvider, S as DeepLinkFallbackOptions, T as SdkEventMap, _ as withCache, a as FullSsoParams, b as isMobile, c as findIframeInOpener, d as formatAmount, f as decompressJsonFromB64, g as clearAllCache, h as base64urlEncode, i as CompressedSsoData, j as sdkConfigStore, k as FrakContextManager, l as getSupportedCurrency, m as base64urlDecode, n as getQueryParamCaseInsensitive, o as generateSsoUrl, p as compressJsonToB64, r as AppSpecificSsoMetadata, s as baseIframeProps, t as deleteQueryParamCaseInsensitive, u as getCurrencyAmountKey, v as isIOS, w as trackEvent, x as redirectToExternalBrowser, y as isInAppBrowser } from "./index-
|
|
2
|
+
import { A as SendTransactionTxType, B as FinalActionType, C as DisplayModalParamsType, D as ModalStepTypes, E as ModalRpcStepsResultType, F as OpenSsoParamsType, G as MerchantConfigResponse, H as ModalStepMetadata, I as OpenSsoReturnType, J as SdkResolvedConfig, K as ResolvedPlacement, L as PrepareSsoParamsType, M as SiweAuthenticateReturnType, N as SiweAuthenticationParams, O as SendTransactionModalStepType, P as LoginModalStepType, R as PrepareSsoReturnType, S as SharingPageProduct, T as ModalRpcStepsInput, U as IFrameLifecycleEvent, V as FinalModalStepType, W as ClientLifecycleEvent, _ as EmbeddedViewActionReferred, a as FrakContextV1, b as DisplaySharingPageParamsType, c as FrakLifecycleEvent, d as WalletStatusReturnType, f as UserReferralStatusType, g as LoggedOutEmbeddedView, h as DisplayEmbeddedWalletResultType, i as FrakContext, j as SiweAuthenticateModalStepType, k as SendTransactionReturnType, l as IFrameTransport, m as DisplayEmbeddedWalletParamsType, n as ssoPopupFeatures, o as FrakContextV2, p as SendInteractionParamsType, q as ResolvedSdkConfig, r as ssoPopupName, s as FrakClient, u as IFrameRpcSchema, v as EmbeddedViewActionSharing, w as ModalRpcMetadata, x as DisplaySharingPageResultType, y as LoggedInEmbeddedView, z as SsoMetadata } from "./openSso-CjZ8lAEA.js";
|
|
3
|
+
import { A as DEEP_LINK_SCHEME, C as triggerDeepLinkWithFallback, D as MergeAttributionInput, E as SdkHandshakeFailureReason, F as createIFrameFrakClient, I as CompressedData, L as HashProtectedData, M as getClientId, N as getBackendUrl, O as mergeAttribution, P as setupClient, R as KeyProvider, S as DeepLinkFallbackOptions, T as SdkEventMap, _ as withCache, a as FullSsoParams, b as isMobile, c as findIframeInOpener, d as formatAmount, f as decompressJsonFromB64, g as clearAllCache, h as base64urlEncode, i as CompressedSsoData, j as sdkConfigStore, k as FrakContextManager, l as getSupportedCurrency, m as base64urlDecode, n as getQueryParamCaseInsensitive, o as generateSsoUrl, p as compressJsonToB64, r as AppSpecificSsoMetadata, s as baseIframeProps, t as deleteQueryParamCaseInsensitive, u as getCurrencyAmountKey, v as isIOS, w as trackEvent, x as redirectToExternalBrowser, y as isInAppBrowser } from "./index-CD-GW6rL.js";
|
|
4
4
|
export { type AppSpecificSsoMetadata, type AttributionDefaults, type AttributionParams, type ClientLifecycleEvent, type CompressedData, type CompressedSsoData, type ConditionGroup, type ConditionOperator, type Currency, DEEP_LINK_SCHEME, type DeepLinkFallbackOptions, type DisplayEmbeddedWalletParamsType, type DisplayEmbeddedWalletResultType, type DisplayModalParamsType, type DisplaySharingPageParamsType, type DisplaySharingPageResultType, type EmbeddedViewActionReferred, type EmbeddedViewActionSharing, type EstimatedReward, type FinalActionType, type FinalModalStepType, type FrakClient, type FrakContext, FrakContextManager, type FrakContextV1, type FrakContextV2, type FrakLifecycleEvent, type FrakWalletSdkConfig, type FullSsoParams, type GetMerchantInformationReturnType, type HashProtectedData, type I18nConfig, type IFrameLifecycleEvent, type IFrameRpcSchema, type IFrameTransport, type InteractionTypeKey, type KeyProvider, type Language, type ListenerPreloadOption, type LocalizedI18nConfig, type LoggedInEmbeddedView, type LoggedOutEmbeddedView, type LoginModalStepType, type MerchantConfigResponse, type MerchantReward, type MergeAttributionInput, type ModalRpcMetadata, type ModalRpcStepsInput, type ModalRpcStepsResultType, type ModalStepMetadata, type ModalStepTypes, type OpenSsoParamsType, type OpenSsoReturnType, type PrepareSsoParamsType, type PrepareSsoReturnType, type ResolvedPlacement, type ResolvedSdkConfig, type RewardTier, type RuleCondition, type RuleConditions, type RuleField, type SdkEventMap, type SdkHandshakeFailureReason, type SdkResolvedConfig, type SendInteractionParamsType, type SendTransactionModalStepType, type SendTransactionReturnType, type SendTransactionTxType, type SharingPageProduct, type SiweAuthenticateModalStepType, type SiweAuthenticateReturnType, type SiweAuthenticationParams, type SsoMetadata, type TokenAmountType, type TrackArrivalParams, type TrackArrivalResult, type UserReferralStatusType, type UtmParams, type WalletStatusReturnType, base64urlDecode, base64urlEncode, baseIframeProps, clearAllCache, compressJsonToB64, createIFrameFrakClient, decompressJsonFromB64, deleteQueryParamCaseInsensitive, findIframeInOpener, formatAmount, generateSsoUrl, getBackendUrl, getClientId, getCurrencyAmountKey, getQueryParamCaseInsensitive, getSupportedCurrency, isIOS, isInAppBrowser, isMobile, mergeAttribution, redirectToExternalBrowser, sdkConfigStore, setupClient, ssoPopupFeatures, ssoPopupName, trackEvent, triggerDeepLinkWithFallback, withCache };
|
|
@@ -44,7 +44,8 @@ type ResolvedPlacement = {
|
|
|
44
44
|
referrerText?: string;
|
|
45
45
|
referrerNoRewardText?: string;
|
|
46
46
|
ctaText?: string;
|
|
47
|
-
ctaNoRewardText?: string;
|
|
47
|
+
ctaNoRewardText?: string; /** Custom illustration URL replacing the built-in gift icon. */
|
|
48
|
+
imageUrl?: string;
|
|
48
49
|
css?: string;
|
|
49
50
|
};
|
|
50
51
|
banner?: {
|
|
@@ -53,7 +54,8 @@ type ResolvedPlacement = {
|
|
|
53
54
|
referralCta?: string;
|
|
54
55
|
inappTitle?: string;
|
|
55
56
|
inappDescription?: string;
|
|
56
|
-
inappCta?: string;
|
|
57
|
+
inappCta?: string; /** Custom illustration URL replacing the built-in gift icon. */
|
|
58
|
+
imageUrl?: string;
|
|
57
59
|
css?: string;
|
|
58
60
|
};
|
|
59
61
|
};
|
|
@@ -1112,4 +1114,4 @@ declare const ssoPopupName = "frak-sso";
|
|
|
1112
1114
|
declare function openSso(client: FrakClient, inputArgs: OpenSsoParamsType): Promise<OpenSsoReturnType>;
|
|
1113
1115
|
//#endregion
|
|
1114
1116
|
export { SendTransactionTxType as A, FinalActionType as B, DisplayModalParamsType as C, ModalStepTypes as D, ModalRpcStepsResultType as E, OpenSsoParamsType as F, MerchantConfigResponse as G, ModalStepMetadata as H, OpenSsoReturnType as I, SdkResolvedConfig as J, ResolvedPlacement as K, PrepareSsoParamsType as L, SiweAuthenticateReturnType as M, SiweAuthenticationParams as N, SendTransactionModalStepType as O, LoginModalStepType as P, PrepareSsoReturnType as R, SharingPageProduct as S, ModalRpcStepsInput as T, IFrameLifecycleEvent as U, FinalModalStepType as V, ClientLifecycleEvent as W, EmbeddedViewActionReferred as _, FrakContextV1 as a, DisplaySharingPageParamsType as b, FrakLifecycleEvent as c, WalletStatusReturnType as d, UserReferralStatusType as f, LoggedOutEmbeddedView as g, DisplayEmbeddedWalletResultType as h, FrakContext as i, SiweAuthenticateModalStepType as j, SendTransactionReturnType as k, IFrameTransport as l, DisplayEmbeddedWalletParamsType as m, ssoPopupFeatures as n, FrakContextV2 as o, SendInteractionParamsType as p, ResolvedSdkConfig as q, ssoPopupName as r, FrakClient as s, openSso as t, IFrameRpcSchema as u, EmbeddedViewActionSharing as v, ModalRpcMetadata as w, DisplaySharingPageResultType as x, LoggedInEmbeddedView as y, SsoMetadata as z };
|
|
1115
|
-
//# sourceMappingURL=openSso-
|
|
1117
|
+
//# sourceMappingURL=openSso-CjZ8lAEA.d.ts.map
|
|
@@ -44,7 +44,8 @@ type ResolvedPlacement = {
|
|
|
44
44
|
referrerText?: string;
|
|
45
45
|
referrerNoRewardText?: string;
|
|
46
46
|
ctaText?: string;
|
|
47
|
-
ctaNoRewardText?: string;
|
|
47
|
+
ctaNoRewardText?: string; /** Custom illustration URL replacing the built-in gift icon. */
|
|
48
|
+
imageUrl?: string;
|
|
48
49
|
css?: string;
|
|
49
50
|
};
|
|
50
51
|
banner?: {
|
|
@@ -53,7 +54,8 @@ type ResolvedPlacement = {
|
|
|
53
54
|
referralCta?: string;
|
|
54
55
|
inappTitle?: string;
|
|
55
56
|
inappDescription?: string;
|
|
56
|
-
inappCta?: string;
|
|
57
|
+
inappCta?: string; /** Custom illustration URL replacing the built-in gift icon. */
|
|
58
|
+
imageUrl?: string;
|
|
57
59
|
css?: string;
|
|
58
60
|
};
|
|
59
61
|
};
|
|
@@ -1112,4 +1114,4 @@ declare const ssoPopupName = "frak-sso";
|
|
|
1112
1114
|
declare function openSso(client: FrakClient, inputArgs: OpenSsoParamsType): Promise<OpenSsoReturnType>;
|
|
1113
1115
|
//#endregion
|
|
1114
1116
|
export { SendTransactionTxType as A, FinalActionType as B, DisplayModalParamsType as C, ModalStepTypes as D, ModalRpcStepsResultType as E, OpenSsoParamsType as F, MerchantConfigResponse as G, ModalStepMetadata as H, OpenSsoReturnType as I, SdkResolvedConfig as J, ResolvedPlacement as K, PrepareSsoParamsType as L, SiweAuthenticateReturnType as M, SiweAuthenticationParams as N, SendTransactionModalStepType as O, LoginModalStepType as P, PrepareSsoReturnType as R, SharingPageProduct as S, ModalRpcStepsInput as T, IFrameLifecycleEvent as U, FinalModalStepType as V, ClientLifecycleEvent as W, EmbeddedViewActionReferred as _, FrakContextV1 as a, DisplaySharingPageParamsType as b, FrakLifecycleEvent as c, WalletStatusReturnType as d, UserReferralStatusType as f, LoggedOutEmbeddedView as g, DisplayEmbeddedWalletResultType as h, FrakContext as i, SiweAuthenticateModalStepType as j, SendTransactionReturnType as k, IFrameTransport as l, DisplayEmbeddedWalletParamsType as m, ssoPopupFeatures as n, FrakContextV2 as o, SendInteractionParamsType as p, ResolvedSdkConfig as q, ssoPopupName as r, FrakClient as s, openSso as t, IFrameRpcSchema as u, EmbeddedViewActionSharing as v, ModalRpcMetadata as w, DisplaySharingPageResultType as x, LoggedInEmbeddedView as y, SsoMetadata as z };
|
|
1115
|
-
//# sourceMappingURL=openSso-
|
|
1117
|
+
//# sourceMappingURL=openSso-DSXbUP-j.d.cts.map
|
package/dist/rewards.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./getCurrencyAmountKey-h2eOiYzv.cjs`);function t(e){return Array.isArray(e)?e:e.conditions}function n(e){if(typeof e==`number`)return e;if(typeof e==`string`&&e.trim()!==``){let t=Number(e);return Number.isFinite(t)?t:void 0}}function r(e,i,a){let o=[];for(let s of t(e)){if(`logic`in s){o.push(...r(s,i,a));continue}if(s.field===i&&a.has(s.operator)){let e=n(s.value);e!=null&&o.push(e)}}return o}const i=new Set([`gt`,`gte`,`between`]),a=new Set([`gt`,`gte`]);function o(e){let t=r(e,`purchase.amount`,i);return t.length>0?Math.min(...t):void 0}function s(e){let t=r(e,`time.timestamp`,a);if(t.length!==0)return new Date(Math.min(...t)*1e3)}function c(e,t){let n=Math.round((e+t)/2/10)*10;return Math.min(t,Math.max(e,n))}function l(e){return Math.max(100,e??0)}function u(e,t){return t==null?e:e<=100&&100<=t?100:c(e,t)}function d(e,t){let n=l(t);if(n<=0)return;let r=e.percent/100*n;return e.minAmount&&(r=Math.max(r,e.minAmount.eurAmount)),e.maxAmount&&(r=Math.min(r,e.maxAmount.eurAmount)),{basket:n,reward:r}}function f(e,t,n){let r=u(t,n);if(!(r<=0))return{basket:r,reward:e/100*r}}function p(e,t){switch(e.payoutType){case`fixed`:return e.amount[t];case`percentage`:return e.maxAmount?.[t]??0;case`tiered`:return e.tiers.reduce((e,n)=>`amount`in n?Math.max(e,n.amount[t]):e,0)}}function m(e){return e.payoutType===`percentage`?e.percent:e.payoutType===`tiered`?e.tiers.reduce((e,t)=>`percent`in t?Math.max(e,t.percent):e,0):0}function h(e,t){let n=p(e,t);return n>0?n:m(e)*1e-6}function g(t,n){let r=e.r(n),i=e.t(r);switch(t.payoutType){case`fixed`:return e.n(Math.round(t.amount[i]),r);case`percentage`:return`${t.percent} %`;case`tiered`:{let n=p(t,i);if(n>0)return e.n(Math.round(n),r);let a=m(t);return a>0?`${a} %`:e.n(0,r)}}}function _(t,n){if(t&&!(h(t,e.t(e.r(n)))<=0))return g(t,n)}function v(e,t){return t?e.replace(`{REWARD}`,t):e.replace(`{REWARD}`,``)}function y(e,t){return e.expiresAt!=null&&new Date(e.expiresAt).getTime()<=t}function b(e,t){let n=s(e.conditions);return n==null||n.getTime()<=t}function x(e,t){return t===`referee`?e.referee:e.referrer}function S(e,t,n){let r=x(e,n);return r?h(r,t):0}function C(t,n={}){let r=(n.now??new Date).getTime(),i=n.audience??`referrer`,a=e.t(e.r(n.currency)),o=(n.targetInteraction?t.filter(e=>e.interactionTypeKey===n.targetInteraction):t).filter(e=>!y(e,r)),c=o.filter(e=>b(e,r));if(c.length>0)return{campaign:c.reduce((e,t)=>S(t,a,i)>S(e,a,i)?t:e),status:`live`};let l=o.map(e=>({campaign:e,startsAt:s(e.conditions)})).filter(e=>e.startsAt!=null);if(l.length===0)return;let u=l.reduce((e,t)=>t.startsAt.getTime()<e.startsAt.getTime()?t:e);return{campaign:u.campaign,status:`upcoming`,startsAt:u.startsAt}}function w(e,t={}){let n=C(e,t);if(n)return
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./getCurrencyAmountKey-h2eOiYzv.cjs`);function t(e){return Array.isArray(e)?e:e.conditions}function n(e){if(typeof e==`number`)return e;if(typeof e==`string`&&e.trim()!==``){let t=Number(e);return Number.isFinite(t)?t:void 0}}function r(e,i,a){let o=[];for(let s of t(e)){if(`logic`in s){o.push(...r(s,i,a));continue}if(s.field===i&&a.has(s.operator)){let e=n(s.value);e!=null&&o.push(e)}}return o}const i=new Set([`gt`,`gte`,`between`]),a=new Set([`gt`,`gte`]);function o(e){let t=r(e,`purchase.amount`,i);return t.length>0?Math.min(...t):void 0}function s(e){let t=r(e,`time.timestamp`,a);if(t.length!==0)return new Date(Math.min(...t)*1e3)}function c(e,t){let n=Math.round((e+t)/2/10)*10;return Math.min(t,Math.max(e,n))}function l(e){return Math.max(100,e??0)}function u(e,t){return t==null?e:e<=100&&100<=t?100:c(e,t)}function d(e,t){let n=l(t);if(n<=0)return;let r=e.percent/100*n;return e.minAmount&&(r=Math.max(r,e.minAmount.eurAmount)),e.maxAmount&&(r=Math.min(r,e.maxAmount.eurAmount)),{basket:n,reward:r}}function f(e,t,n){let r=u(t,n);if(!(r<=0))return{basket:r,reward:e/100*r}}function p(e,t){switch(e.payoutType){case`fixed`:return e.amount[t];case`percentage`:return e.maxAmount?.[t]??0;case`tiered`:return e.tiers.reduce((e,n)=>`amount`in n?Math.max(e,n.amount[t]):e,0)}}function m(e){return e.payoutType===`percentage`?e.percent:e.payoutType===`tiered`?e.tiers.reduce((e,t)=>`percent`in t?Math.max(e,t.percent):e,0):0}function h(e,t){let n=p(e,t);return n>0?n:m(e)*1e-6}function g(t,n){let r=e.r(n),i=e.t(r);switch(t.payoutType){case`fixed`:return e.n(Math.round(t.amount[i]),r);case`percentage`:return`${t.percent} %`;case`tiered`:{let n=p(t,i);if(n>0)return e.n(Math.round(n),r);let a=m(t);return a>0?`${a} %`:e.n(0,r)}}}function _(t,n){if(t&&!(h(t,e.t(e.r(n)))<=0))return g(t,n)}function v(e,t){return t?e.replace(`{REWARD}`,t):e.replace(`{REWARD}`,``)}function y(e,t){return e.expiresAt!=null&&new Date(e.expiresAt).getTime()<=t}function b(e,t){let n=s(e.conditions);return n==null||n.getTime()<=t}function x(e,t){return t===`referee`?e.referee:e.referrer}function S(e,t,n){let r=x(e,n);return r?h(r,t):0}function C(t,n={}){let r=(n.now??new Date).getTime(),i=n.audience??`referrer`,a=e.t(e.r(n.currency)),o=(n.targetInteraction?t.filter(e=>e.interactionTypeKey===n.targetInteraction):t).filter(e=>!y(e,r)),c=o.filter(e=>b(e,r));if(c.length>0)return{campaign:c.reduce((e,t)=>S(t,a,i)>S(e,a,i)?t:e),status:`live`};let l=o.map(e=>({campaign:e,startsAt:s(e.conditions)})).filter(e=>e.startsAt!=null);if(l.length===0)return;let u=l.reduce((e,t)=>t.startsAt.getTime()<e.startsAt.getTime()?t:e);return{campaign:u.campaign,status:`upcoming`,startsAt:u.startsAt}}function w(e,t={}){let n=C(e,t);if(!n)return;let r=x(n.campaign,t.audience??`referrer`);if(!r)return;let i=_(r,t.currency);if(i)return{formatted:i,payoutType:r.payoutType}}function T(e,t={}){return w(e,t)?.formatted}exports.applyRewardPlaceholder=v,exports.buildPercentageExample=d,exports.buildTierExample=f,exports.extractMinPurchaseAmount=o,exports.extractStartDate=s,exports.formatBestReward=T,exports.formatEstimatedReward=g,exports.formatRewardOrHide=_,exports.getRewardValue=p,exports.pickFlatBasket=l,exports.pickTierBasket=u,exports.selectBestReward=w,exports.selectDisplayCampaign=C;
|
|
2
2
|
//# sourceMappingURL=rewards.cjs.map
|
package/dist/rewards.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rewards.cjs","names":["getSupportedCurrency","getCurrencyAmountKey","formatAmount","getCurrencyAmountKey","getSupportedCurrency"],"sources":["../src/rewards/conditions.ts","../src/rewards/example.ts","../src/rewards/value.ts","../src/rewards/format.ts","../src/rewards/select.ts"],"sourcesContent":["import type { ConditionGroup, RuleCondition, RuleConditions } from \"../types\";\n\ntype ConditionNode = RuleCondition | ConditionGroup;\n\nfunction conditionNodes(conditions: RuleConditions): ConditionNode[] {\n return Array.isArray(conditions) ? conditions : conditions.conditions;\n}\n\nfunction conditionValueToNumber(\n value: RuleCondition[\"value\"]\n): number | undefined {\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\" && value.trim() !== \"\") {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n}\n\n// Conditions arrive as a flat list or recursive groups; collect every numeric\n// value whose field + operator match, descending into nested groups.\nfunction collectConditionValues(\n conditions: RuleConditions,\n field: string,\n operators: ReadonlySet<RuleCondition[\"operator\"]>\n): number[] {\n const values: number[] = [];\n for (const node of conditionNodes(conditions)) {\n if (\"logic\" in node) {\n values.push(...collectConditionValues(node, field, operators));\n continue;\n }\n if (node.field === field && operators.has(node.operator)) {\n const value = conditionValueToNumber(node.value);\n if (value != null) values.push(value);\n }\n }\n return values;\n}\n\nconst MIN_PURCHASE_OPERATORS: ReadonlySet<RuleCondition[\"operator\"]> = new Set([\n \"gt\",\n \"gte\",\n \"between\",\n]);\nconst START_DATE_OPERATORS: ReadonlySet<RuleCondition[\"operator\"]> = new Set([\n \"gt\",\n \"gte\",\n]);\n\nexport function extractMinPurchaseAmount(\n conditions: RuleConditions\n): number | undefined {\n const values = collectConditionValues(\n conditions,\n \"purchase.amount\",\n MIN_PURCHASE_OPERATORS\n );\n return values.length > 0 ? Math.min(...values) : undefined;\n}\n\n// The business app encodes a campaign start as a `time.timestamp >= <unix s>`\n// rule condition; the endpoint returns it verbatim inside `conditions`.\nexport function extractStartDate(conditions: RuleConditions): Date | undefined {\n const values = collectConditionValues(\n conditions,\n \"time.timestamp\",\n START_DATE_OPERATORS\n );\n if (values.length === 0) return undefined;\n return new Date(Math.min(...values) * 1000);\n}\n","import type { EstimatedReward } from \"../types\";\n\ntype PercentageReward = Extract<EstimatedReward, { payoutType: \"percentage\" }>;\n\n// Reference order total used to turn a \"% of basket\" reward into a concrete\n// example amount. The campaign's minimum purchase overrides it when higher.\nconst REFERENCE_BASKET = 100;\n\nexport type RewardExample = {\n basket: number;\n reward: number;\n};\n\nfunction roundWithinRange(min: number, max: number): number {\n const rounded = Math.round((min + max) / 2 / 10) * 10;\n return Math.min(max, Math.max(min, rounded));\n}\n\nexport function pickFlatBasket(minPurchase: number | undefined): number {\n return Math.max(REFERENCE_BASKET, minPurchase ?? 0);\n}\n\n// Basket for a percentage tier: the reference when it sits inside the tier\n// range, a round number within the range otherwise, or the lower bound for an\n// open-ended (uncapped) top tier.\nexport function pickTierBasket(\n minValue: number,\n maxValue: number | undefined\n): number {\n if (maxValue == null) return minValue;\n if (minValue <= REFERENCE_BASKET && REFERENCE_BASKET <= maxValue) {\n return REFERENCE_BASKET;\n }\n return roundWithinRange(minValue, maxValue);\n}\n\nexport function buildPercentageExample(\n reward: PercentageReward,\n minPurchase: number | undefined\n): RewardExample | undefined {\n const basket = pickFlatBasket(minPurchase);\n if (basket <= 0) return undefined;\n let amount = (reward.percent / 100) * basket;\n if (reward.minAmount) amount = Math.max(amount, reward.minAmount.eurAmount);\n if (reward.maxAmount) amount = Math.min(amount, reward.maxAmount.eurAmount);\n return { basket, reward: amount };\n}\n\nexport function buildTierExample(\n percent: number,\n minValue: number,\n maxValue: number | undefined\n): RewardExample | undefined {\n const basket = pickTierBasket(minValue, maxValue);\n if (basket <= 0) return undefined;\n return { basket, reward: (percent / 100) * basket };\n}\n","import type { EstimatedReward, TokenAmountType } from \"../types\";\n\n/**\n * Comparable fiat value of a single reward, used to rank rewards against each\n * other.\n *\n * - `fixed` → the token amount in the requested currency\n * - `tiered` → the highest token amount across tiers\n * - `percentage` → the capped (`maxAmount`) value when present, otherwise `0`\n * (an uncapped percentage has no comparable fiat value)\n */\nexport function getRewardValue(\n reward: EstimatedReward,\n key: keyof TokenAmountType\n): number {\n switch (reward.payoutType) {\n case \"fixed\":\n return reward.amount[key];\n case \"percentage\":\n return reward.maxAmount?.[key] ?? 0;\n case \"tiered\":\n return reward.tiers.reduce(\n (max, tier) =>\n \"amount\" in tier ? Math.max(max, tier.amount[key]) : max,\n 0\n );\n }\n}\n\n/**\n * Highest percent a reward exposes: the flat `percentage` percent, or the\n * richest percent across `tiered` tiers, or `0` when it carries none.\n *\n * Shared by {@link getRewardRank} (to weight a percentage-only reward) and\n * `formatEstimatedReward` (to render it as `\"X %\"`), so the value the UI ranks\n * by and the value it prints stay derived from one tier traversal.\n */\nexport function maxRewardPercent(reward: EstimatedReward): number {\n if (reward.payoutType === \"percentage\") return reward.percent;\n if (reward.payoutType === \"tiered\") {\n return reward.tiers.reduce(\n (max, tier) =>\n \"percent\" in tier ? Math.max(max, tier.percent) : max,\n 0\n );\n }\n return 0;\n}\n\n// A reward with no money value (an uncapped percentage, or a percent-only\n// tier set) still renders as \"X %\", so it is worth surfacing. We give it a\n// positive ranking weight derived from its percent but scaled far below any\n// real-money reward, so the two invariants the UI relies on hold: (1) a reward\n// with real money always outranks a percentage-only reward, and (2) a\n// percentage-only reward still outranks a zero-value reward. Together they\n// guarantee the reward the ranking picks is always one we can display.\nconst PERCENT_ONLY_RANK_WEIGHT = 1e-6;\n\n/**\n * Ranking weight used to pick the single most attractive reward to surface.\n *\n * Mirrors {@link getRewardValue} (money value) but lifts a percentage-only\n * reward to a tiny positive weight instead of `0`, so it is never buried\n * behind a zero-value reward when choosing what to display.\n */\nexport function getRewardRank(\n reward: EstimatedReward,\n key: keyof TokenAmountType\n): number {\n const value = getRewardValue(reward, key);\n if (value > 0) return value;\n return maxRewardPercent(reward) * PERCENT_ONLY_RANK_WEIGHT;\n}\n","import type { Currency, EstimatedReward } from \"../types\";\nimport { formatAmount } from \"../utils/format/formatAmount\";\nimport { getCurrencyAmountKey } from \"../utils/format/getCurrencyAmountKey\";\nimport { getSupportedCurrency } from \"../utils/format/getSupportedCurrency\";\nimport { getRewardRank, getRewardValue, maxRewardPercent } from \"./value\";\n\n/**\n * Format an {@link EstimatedReward} into a human-readable string.\n *\n * - `fixed` → e.g. `\"5 €\"`\n * - `percentage` → e.g. `\"10 %\"`\n * - `tiered` → the richest tier: max token amount (e.g. `\"50 €\"`) or, when\n * tiers only carry percentages, the max percent (e.g. `\"10 %\"`)\n *\n * Percentages are always rendered as a `\"X %\"` string: the backend never sends\n * a reference basket, so the reward cannot be resolved to a concrete amount\n * here. Callers that need a worked example use the `example` helpers instead.\n */\nexport function formatEstimatedReward(\n reward: EstimatedReward,\n currency?: Currency\n): string {\n const supportedCurrency = getSupportedCurrency(currency);\n const key = getCurrencyAmountKey(supportedCurrency);\n\n switch (reward.payoutType) {\n case \"fixed\":\n return formatAmount(\n Math.round(reward.amount[key]),\n supportedCurrency\n );\n\n case \"percentage\":\n return `${reward.percent} %`;\n\n case \"tiered\": {\n const maxAmount = getRewardValue(reward, key);\n if (maxAmount > 0) {\n return formatAmount(Math.round(maxAmount), supportedCurrency);\n }\n const maxPercent = maxRewardPercent(reward);\n if (maxPercent > 0) {\n return `${maxPercent} %`;\n }\n return formatAmount(0, supportedCurrency);\n }\n }\n}\n\n/**\n * Format a reward for display, or return `undefined` when it is not worth\n * advertising. Callers rely on `undefined` to hide a badge / fall back to\n * other copy.\n *\n * A reward is hidden only when it carries no displayable value — a `fixed` or\n * `tiered` reward whose money value is `0` (e.g. an unknown token price). An\n * uncapped percentage always renders as `\"X %\"`, since the percent itself is\n * meaningful even without a money value.\n */\nexport function formatRewardOrHide(\n reward: EstimatedReward | undefined,\n currency?: Currency\n): string | undefined {\n if (!reward) return undefined;\n const key = getCurrencyAmountKey(getSupportedCurrency(currency));\n if (getRewardRank(reward, key) <= 0) return undefined;\n return formatEstimatedReward(reward, currency);\n}\n\n/**\n * Replace the `{REWARD}` placeholder in a text string with a reward value.\n * If no reward is provided, returns the text with `{REWARD}` stripped.\n */\nexport function applyRewardPlaceholder(\n text: string,\n reward: string | undefined\n): string {\n return reward\n ? text.replace(\"{REWARD}\", reward)\n : text.replace(\"{REWARD}\", \"\");\n}\n","import type { InteractionTypeKey } from \"../constants/interactionTypes\";\nimport type { Currency, MerchantReward, TokenAmountType } from \"../types\";\nimport { getCurrencyAmountKey } from \"../utils/format/getCurrencyAmountKey\";\nimport { getSupportedCurrency } from \"../utils/format/getSupportedCurrency\";\nimport { extractStartDate } from \"./conditions\";\nimport { formatRewardOrHide } from \"./format\";\nimport { getRewardRank } from \"./value\";\n\n/** Reward side a surface cares about: the sharer (`referrer`) or the referred\n * user (`referee`). Drives both campaign ranking and which side is displayed. */\nexport type RewardAudience = \"referrer\" | \"referee\";\n\nexport type DisplayCampaign = {\n campaign: MerchantReward;\n status: \"live\" | \"upcoming\";\n startsAt?: Date;\n};\n\nexport type SelectDisplayCampaignOptions = {\n /** Reference \"now\" for expiry / start gating; defaults to the current time. */\n now?: Date;\n /** Currency the ranking is expressed in; defaults to EUR. */\n currency?: Currency;\n /** When set, only campaigns triggered by this interaction are considered. */\n targetInteraction?: InteractionTypeKey;\n /** Reward side to rank campaigns by; defaults to `\"referrer\"`. */\n audience?: RewardAudience;\n};\n\nfunction isExpired(campaign: MerchantReward, nowMs: number): boolean {\n return (\n campaign.expiresAt != null &&\n new Date(campaign.expiresAt).getTime() <= nowMs\n );\n}\n\nfunction hasStarted(campaign: MerchantReward, nowMs: number): boolean {\n const startsAt = extractStartDate(campaign.conditions);\n return startsAt == null || startsAt.getTime() <= nowMs;\n}\n\nfunction audienceReward(campaign: MerchantReward, audience: RewardAudience) {\n return audience === \"referee\" ? campaign.referee : campaign.referrer;\n}\n\nfunction campaignRank(\n campaign: MerchantReward,\n key: keyof TokenAmountType,\n audience: RewardAudience\n): number {\n const reward = audienceReward(campaign, audience);\n return reward ? getRewardRank(reward, key) : 0;\n}\n\n/**\n * Pick the single campaign a merchant surface should display.\n *\n * Filters out expired (and, when `targetInteraction` is set, non-matching)\n * campaigns, then prefers the highest-ranked *live* campaign — ranked by the\n * `audience` reward side in the requested currency. When none has started yet\n * it falls back to the soonest-starting upcoming campaign (the endpoint does\n * not gate on the start-date condition, so future-start campaigns come\n * through).\n */\nexport function selectDisplayCampaign(\n rewards: readonly MerchantReward[],\n options: SelectDisplayCampaignOptions = {}\n): DisplayCampaign | undefined {\n const nowMs = (options.now ?? new Date()).getTime();\n const audience = options.audience ?? \"referrer\";\n const key = getCurrencyAmountKey(getSupportedCurrency(options.currency));\n\n const matching = options.targetInteraction\n ? rewards.filter(\n (campaign) =>\n campaign.interactionTypeKey === options.targetInteraction\n )\n : rewards;\n const active = matching.filter((campaign) => !isExpired(campaign, nowMs));\n\n const live = active.filter((campaign) => hasStarted(campaign, nowMs));\n if (live.length > 0) {\n const best = live.reduce((a, b) =>\n campaignRank(b, key, audience) > campaignRank(a, key, audience)\n ? b\n : a\n );\n return { campaign: best, status: \"live\" };\n }\n\n const upcoming = active\n .map((campaign) => ({\n campaign,\n startsAt: extractStartDate(campaign.conditions),\n }))\n .filter(\n (entry): entry is { campaign: MerchantReward; startsAt: Date } =>\n entry.startsAt != null\n );\n if (upcoming.length === 0) return undefined;\n\n const soonest = upcoming.reduce((a, b) =>\n b.startsAt.getTime() < a.startsAt.getTime() ? b : a\n );\n return {\n campaign: soonest.campaign,\n status: \"upcoming\",\n startsAt: soonest.startsAt,\n };\n}\n\n/**\n * Headline reward string for a merchant: picks the best campaign for `options`\n * and formats its `audience`-side reward, or returns `undefined` when there is\n * nothing worth showing.\n *\n * Single entry point shared by every \"headline reward\" surface (share button,\n * wallet modal, sharing/install screens) so they all show the same number for\n * a given merchant.\n */\nexport function formatBestReward(\n rewards: readonly MerchantReward[],\n options: SelectDisplayCampaignOptions = {}\n): string | undefined {\n const selected = selectDisplayCampaign(rewards, options);\n if (!selected) return undefined;\n const reward = audienceReward(\n selected.campaign,\n options.audience ?? \"referrer\"\n );\n return formatRewardOrHide(reward, options.currency);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rewards.cjs","names":["getSupportedCurrency","getCurrencyAmountKey","formatAmount","getCurrencyAmountKey","getSupportedCurrency"],"sources":["../src/rewards/conditions.ts","../src/rewards/example.ts","../src/rewards/value.ts","../src/rewards/format.ts","../src/rewards/select.ts"],"sourcesContent":["import type { ConditionGroup, RuleCondition, RuleConditions } from \"../types\";\n\ntype ConditionNode = RuleCondition | ConditionGroup;\n\nfunction conditionNodes(conditions: RuleConditions): ConditionNode[] {\n return Array.isArray(conditions) ? conditions : conditions.conditions;\n}\n\nfunction conditionValueToNumber(\n value: RuleCondition[\"value\"]\n): number | undefined {\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\" && value.trim() !== \"\") {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n}\n\n// Conditions arrive as a flat list or recursive groups; collect every numeric\n// value whose field + operator match, descending into nested groups.\nfunction collectConditionValues(\n conditions: RuleConditions,\n field: string,\n operators: ReadonlySet<RuleCondition[\"operator\"]>\n): number[] {\n const values: number[] = [];\n for (const node of conditionNodes(conditions)) {\n if (\"logic\" in node) {\n values.push(...collectConditionValues(node, field, operators));\n continue;\n }\n if (node.field === field && operators.has(node.operator)) {\n const value = conditionValueToNumber(node.value);\n if (value != null) values.push(value);\n }\n }\n return values;\n}\n\nconst MIN_PURCHASE_OPERATORS: ReadonlySet<RuleCondition[\"operator\"]> = new Set([\n \"gt\",\n \"gte\",\n \"between\",\n]);\nconst START_DATE_OPERATORS: ReadonlySet<RuleCondition[\"operator\"]> = new Set([\n \"gt\",\n \"gte\",\n]);\n\nexport function extractMinPurchaseAmount(\n conditions: RuleConditions\n): number | undefined {\n const values = collectConditionValues(\n conditions,\n \"purchase.amount\",\n MIN_PURCHASE_OPERATORS\n );\n return values.length > 0 ? Math.min(...values) : undefined;\n}\n\n// The business app encodes a campaign start as a `time.timestamp >= <unix s>`\n// rule condition; the endpoint returns it verbatim inside `conditions`.\nexport function extractStartDate(conditions: RuleConditions): Date | undefined {\n const values = collectConditionValues(\n conditions,\n \"time.timestamp\",\n START_DATE_OPERATORS\n );\n if (values.length === 0) return undefined;\n return new Date(Math.min(...values) * 1000);\n}\n","import type { EstimatedReward } from \"../types\";\n\ntype PercentageReward = Extract<EstimatedReward, { payoutType: \"percentage\" }>;\n\n// Reference order total used to turn a \"% of basket\" reward into a concrete\n// example amount. The campaign's minimum purchase overrides it when higher.\nconst REFERENCE_BASKET = 100;\n\nexport type RewardExample = {\n basket: number;\n reward: number;\n};\n\nfunction roundWithinRange(min: number, max: number): number {\n const rounded = Math.round((min + max) / 2 / 10) * 10;\n return Math.min(max, Math.max(min, rounded));\n}\n\nexport function pickFlatBasket(minPurchase: number | undefined): number {\n return Math.max(REFERENCE_BASKET, minPurchase ?? 0);\n}\n\n// Basket for a percentage tier: the reference when it sits inside the tier\n// range, a round number within the range otherwise, or the lower bound for an\n// open-ended (uncapped) top tier.\nexport function pickTierBasket(\n minValue: number,\n maxValue: number | undefined\n): number {\n if (maxValue == null) return minValue;\n if (minValue <= REFERENCE_BASKET && REFERENCE_BASKET <= maxValue) {\n return REFERENCE_BASKET;\n }\n return roundWithinRange(minValue, maxValue);\n}\n\nexport function buildPercentageExample(\n reward: PercentageReward,\n minPurchase: number | undefined\n): RewardExample | undefined {\n const basket = pickFlatBasket(minPurchase);\n if (basket <= 0) return undefined;\n let amount = (reward.percent / 100) * basket;\n if (reward.minAmount) amount = Math.max(amount, reward.minAmount.eurAmount);\n if (reward.maxAmount) amount = Math.min(amount, reward.maxAmount.eurAmount);\n return { basket, reward: amount };\n}\n\nexport function buildTierExample(\n percent: number,\n minValue: number,\n maxValue: number | undefined\n): RewardExample | undefined {\n const basket = pickTierBasket(minValue, maxValue);\n if (basket <= 0) return undefined;\n return { basket, reward: (percent / 100) * basket };\n}\n","import type { EstimatedReward, TokenAmountType } from \"../types\";\n\n/**\n * Comparable fiat value of a single reward, used to rank rewards against each\n * other.\n *\n * - `fixed` → the token amount in the requested currency\n * - `tiered` → the highest token amount across tiers\n * - `percentage` → the capped (`maxAmount`) value when present, otherwise `0`\n * (an uncapped percentage has no comparable fiat value)\n */\nexport function getRewardValue(\n reward: EstimatedReward,\n key: keyof TokenAmountType\n): number {\n switch (reward.payoutType) {\n case \"fixed\":\n return reward.amount[key];\n case \"percentage\":\n return reward.maxAmount?.[key] ?? 0;\n case \"tiered\":\n return reward.tiers.reduce(\n (max, tier) =>\n \"amount\" in tier ? Math.max(max, tier.amount[key]) : max,\n 0\n );\n }\n}\n\n/**\n * Highest percent a reward exposes: the flat `percentage` percent, or the\n * richest percent across `tiered` tiers, or `0` when it carries none.\n *\n * Shared by {@link getRewardRank} (to weight a percentage-only reward) and\n * `formatEstimatedReward` (to render it as `\"X %\"`), so the value the UI ranks\n * by and the value it prints stay derived from one tier traversal.\n */\nexport function maxRewardPercent(reward: EstimatedReward): number {\n if (reward.payoutType === \"percentage\") return reward.percent;\n if (reward.payoutType === \"tiered\") {\n return reward.tiers.reduce(\n (max, tier) =>\n \"percent\" in tier ? Math.max(max, tier.percent) : max,\n 0\n );\n }\n return 0;\n}\n\n// A reward with no money value (an uncapped percentage, or a percent-only\n// tier set) still renders as \"X %\", so it is worth surfacing. We give it a\n// positive ranking weight derived from its percent but scaled far below any\n// real-money reward, so the two invariants the UI relies on hold: (1) a reward\n// with real money always outranks a percentage-only reward, and (2) a\n// percentage-only reward still outranks a zero-value reward. Together they\n// guarantee the reward the ranking picks is always one we can display.\nconst PERCENT_ONLY_RANK_WEIGHT = 1e-6;\n\n/**\n * Ranking weight used to pick the single most attractive reward to surface.\n *\n * Mirrors {@link getRewardValue} (money value) but lifts a percentage-only\n * reward to a tiny positive weight instead of `0`, so it is never buried\n * behind a zero-value reward when choosing what to display.\n */\nexport function getRewardRank(\n reward: EstimatedReward,\n key: keyof TokenAmountType\n): number {\n const value = getRewardValue(reward, key);\n if (value > 0) return value;\n return maxRewardPercent(reward) * PERCENT_ONLY_RANK_WEIGHT;\n}\n","import type { Currency, EstimatedReward } from \"../types\";\nimport { formatAmount } from \"../utils/format/formatAmount\";\nimport { getCurrencyAmountKey } from \"../utils/format/getCurrencyAmountKey\";\nimport { getSupportedCurrency } from \"../utils/format/getSupportedCurrency\";\nimport { getRewardRank, getRewardValue, maxRewardPercent } from \"./value\";\n\n/**\n * Format an {@link EstimatedReward} into a human-readable string.\n *\n * - `fixed` → e.g. `\"5 €\"`\n * - `percentage` → e.g. `\"10 %\"`\n * - `tiered` → the richest tier: max token amount (e.g. `\"50 €\"`) or, when\n * tiers only carry percentages, the max percent (e.g. `\"10 %\"`)\n *\n * Percentages are always rendered as a `\"X %\"` string: the backend never sends\n * a reference basket, so the reward cannot be resolved to a concrete amount\n * here. Callers that need a worked example use the `example` helpers instead.\n */\nexport function formatEstimatedReward(\n reward: EstimatedReward,\n currency?: Currency\n): string {\n const supportedCurrency = getSupportedCurrency(currency);\n const key = getCurrencyAmountKey(supportedCurrency);\n\n switch (reward.payoutType) {\n case \"fixed\":\n return formatAmount(\n Math.round(reward.amount[key]),\n supportedCurrency\n );\n\n case \"percentage\":\n return `${reward.percent} %`;\n\n case \"tiered\": {\n const maxAmount = getRewardValue(reward, key);\n if (maxAmount > 0) {\n return formatAmount(Math.round(maxAmount), supportedCurrency);\n }\n const maxPercent = maxRewardPercent(reward);\n if (maxPercent > 0) {\n return `${maxPercent} %`;\n }\n return formatAmount(0, supportedCurrency);\n }\n }\n}\n\n/**\n * Format a reward for display, or return `undefined` when it is not worth\n * advertising. Callers rely on `undefined` to hide a badge / fall back to\n * other copy.\n *\n * A reward is hidden only when it carries no displayable value — a `fixed` or\n * `tiered` reward whose money value is `0` (e.g. an unknown token price). An\n * uncapped percentage always renders as `\"X %\"`, since the percent itself is\n * meaningful even without a money value.\n */\nexport function formatRewardOrHide(\n reward: EstimatedReward | undefined,\n currency?: Currency\n): string | undefined {\n if (!reward) return undefined;\n const key = getCurrencyAmountKey(getSupportedCurrency(currency));\n if (getRewardRank(reward, key) <= 0) return undefined;\n return formatEstimatedReward(reward, currency);\n}\n\n/**\n * Replace the `{REWARD}` placeholder in a text string with a reward value.\n * If no reward is provided, returns the text with `{REWARD}` stripped.\n */\nexport function applyRewardPlaceholder(\n text: string,\n reward: string | undefined\n): string {\n return reward\n ? text.replace(\"{REWARD}\", reward)\n : text.replace(\"{REWARD}\", \"\");\n}\n","import type { InteractionTypeKey } from \"../constants/interactionTypes\";\nimport type {\n Currency,\n EstimatedReward,\n MerchantReward,\n TokenAmountType,\n} from \"../types\";\nimport { getCurrencyAmountKey } from \"../utils/format/getCurrencyAmountKey\";\nimport { getSupportedCurrency } from \"../utils/format/getSupportedCurrency\";\nimport { extractStartDate } from \"./conditions\";\nimport { formatRewardOrHide } from \"./format\";\nimport { getRewardRank } from \"./value\";\n\n/** Reward side a surface cares about: the sharer (`referrer`) or the referred\n * user (`referee`). Drives both campaign ranking and which side is displayed. */\nexport type RewardAudience = \"referrer\" | \"referee\";\n\nexport type DisplayCampaign = {\n campaign: MerchantReward;\n status: \"live\" | \"upcoming\";\n startsAt?: Date;\n};\n\nexport type SelectDisplayCampaignOptions = {\n /** Reference \"now\" for expiry / start gating; defaults to the current time. */\n now?: Date;\n /** Currency the ranking is expressed in; defaults to EUR. */\n currency?: Currency;\n /** When set, only campaigns triggered by this interaction are considered. */\n targetInteraction?: InteractionTypeKey;\n /** Reward side to rank campaigns by; defaults to `\"referrer\"`. */\n audience?: RewardAudience;\n};\n\nfunction isExpired(campaign: MerchantReward, nowMs: number): boolean {\n return (\n campaign.expiresAt != null &&\n new Date(campaign.expiresAt).getTime() <= nowMs\n );\n}\n\nfunction hasStarted(campaign: MerchantReward, nowMs: number): boolean {\n const startsAt = extractStartDate(campaign.conditions);\n return startsAt == null || startsAt.getTime() <= nowMs;\n}\n\nfunction audienceReward(campaign: MerchantReward, audience: RewardAudience) {\n return audience === \"referee\" ? campaign.referee : campaign.referrer;\n}\n\nfunction campaignRank(\n campaign: MerchantReward,\n key: keyof TokenAmountType,\n audience: RewardAudience\n): number {\n const reward = audienceReward(campaign, audience);\n return reward ? getRewardRank(reward, key) : 0;\n}\n\n/**\n * Pick the single campaign a merchant surface should display.\n *\n * Filters out expired (and, when `targetInteraction` is set, non-matching)\n * campaigns, then prefers the highest-ranked *live* campaign — ranked by the\n * `audience` reward side in the requested currency. When none has started yet\n * it falls back to the soonest-starting upcoming campaign (the endpoint does\n * not gate on the start-date condition, so future-start campaigns come\n * through).\n */\nexport function selectDisplayCampaign(\n rewards: readonly MerchantReward[],\n options: SelectDisplayCampaignOptions = {}\n): DisplayCampaign | undefined {\n const nowMs = (options.now ?? new Date()).getTime();\n const audience = options.audience ?? \"referrer\";\n const key = getCurrencyAmountKey(getSupportedCurrency(options.currency));\n\n const matching = options.targetInteraction\n ? rewards.filter(\n (campaign) =>\n campaign.interactionTypeKey === options.targetInteraction\n )\n : rewards;\n const active = matching.filter((campaign) => !isExpired(campaign, nowMs));\n\n const live = active.filter((campaign) => hasStarted(campaign, nowMs));\n if (live.length > 0) {\n const best = live.reduce((a, b) =>\n campaignRank(b, key, audience) > campaignRank(a, key, audience)\n ? b\n : a\n );\n return { campaign: best, status: \"live\" };\n }\n\n const upcoming = active\n .map((campaign) => ({\n campaign,\n startsAt: extractStartDate(campaign.conditions),\n }))\n .filter(\n (entry): entry is { campaign: MerchantReward; startsAt: Date } =>\n entry.startsAt != null\n );\n if (upcoming.length === 0) return undefined;\n\n const soonest = upcoming.reduce((a, b) =>\n b.startsAt.getTime() < a.startsAt.getTime() ? b : a\n );\n return {\n campaign: soonest.campaign,\n status: \"upcoming\",\n startsAt: soonest.startsAt,\n };\n}\n\n/**\n * The single reward a merchant surface should display: its formatted string\n * plus the `payoutType` of the underlying reward, so surfaces can adapt their\n * presentation (e.g. hide percentage rewards, prefix tiered ones with \"Up to\").\n */\nexport type BestReward = {\n /** Display-ready reward string (e.g. `\"5 €\"`, `\"10 %\"`). */\n formatted: string;\n /** Payout type of the selected reward. */\n payoutType: EstimatedReward[\"payoutType\"];\n};\n\n/**\n * Pick the best campaign for `options` and resolve its `audience`-side reward\n * to a formatted string plus its `payoutType`, or `undefined` when there is\n * nothing worth showing.\n *\n * Single entry point shared by every \"headline reward\" surface (share button,\n * wallet modal, sharing/install screens) so they all show the same number for\n * a given merchant and can branch on the payout type.\n */\nexport function selectBestReward(\n rewards: readonly MerchantReward[],\n options: SelectDisplayCampaignOptions = {}\n): BestReward | undefined {\n const selected = selectDisplayCampaign(rewards, options);\n if (!selected) return undefined;\n const reward = audienceReward(\n selected.campaign,\n options.audience ?? \"referrer\"\n );\n if (!reward) return undefined;\n const formatted = formatRewardOrHide(reward, options.currency);\n if (!formatted) return undefined;\n return { formatted, payoutType: reward.payoutType };\n}\n\n/**\n * Headline reward string for a merchant: picks the best campaign for `options`\n * and formats its `audience`-side reward, or returns `undefined` when there is\n * nothing worth showing.\n *\n * Thin wrapper over {@link selectBestReward} for callers that only need the\n * formatted string.\n */\nexport function formatBestReward(\n rewards: readonly MerchantReward[],\n options: SelectDisplayCampaignOptions = {}\n): string | undefined {\n return selectBestReward(rewards, options)?.formatted;\n}\n"],"mappings":"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"}
|
package/dist/rewards.d.cts
CHANGED
|
@@ -75,13 +75,31 @@ type SelectDisplayCampaignOptions = {
|
|
|
75
75
|
*/
|
|
76
76
|
declare function selectDisplayCampaign(rewards: readonly MerchantReward[], options?: SelectDisplayCampaignOptions): DisplayCampaign | undefined;
|
|
77
77
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
78
|
+
* The single reward a merchant surface should display: its formatted string
|
|
79
|
+
* plus the `payoutType` of the underlying reward, so surfaces can adapt their
|
|
80
|
+
* presentation (e.g. hide percentage rewards, prefix tiered ones with "Up to").
|
|
81
|
+
*/
|
|
82
|
+
type BestReward = {
|
|
83
|
+
/** Display-ready reward string (e.g. `"5 €"`, `"10 %"`). */formatted: string; /** Payout type of the selected reward. */
|
|
84
|
+
payoutType: EstimatedReward["payoutType"];
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Pick the best campaign for `options` and resolve its `audience`-side reward
|
|
88
|
+
* to a formatted string plus its `payoutType`, or `undefined` when there is
|
|
80
89
|
* nothing worth showing.
|
|
81
90
|
*
|
|
82
91
|
* Single entry point shared by every "headline reward" surface (share button,
|
|
83
92
|
* wallet modal, sharing/install screens) so they all show the same number for
|
|
84
|
-
* a given merchant.
|
|
93
|
+
* a given merchant and can branch on the payout type.
|
|
94
|
+
*/
|
|
95
|
+
declare function selectBestReward(rewards: readonly MerchantReward[], options?: SelectDisplayCampaignOptions): BestReward | undefined;
|
|
96
|
+
/**
|
|
97
|
+
* Headline reward string for a merchant: picks the best campaign for `options`
|
|
98
|
+
* and formats its `audience`-side reward, or returns `undefined` when there is
|
|
99
|
+
* nothing worth showing.
|
|
100
|
+
*
|
|
101
|
+
* Thin wrapper over {@link selectBestReward} for callers that only need the
|
|
102
|
+
* formatted string.
|
|
85
103
|
*/
|
|
86
104
|
declare function formatBestReward(rewards: readonly MerchantReward[], options?: SelectDisplayCampaignOptions): string | undefined;
|
|
87
105
|
//#endregion
|
|
@@ -97,5 +115,5 @@ declare function formatBestReward(rewards: readonly MerchantReward[], options?:
|
|
|
97
115
|
*/
|
|
98
116
|
declare function getRewardValue(reward: EstimatedReward, key: keyof TokenAmountType): number;
|
|
99
117
|
//#endregion
|
|
100
|
-
export { type DisplayCampaign, type RewardAudience, type RewardExample, type SelectDisplayCampaignOptions, applyRewardPlaceholder, buildPercentageExample, buildTierExample, extractMinPurchaseAmount, extractStartDate, formatBestReward, formatEstimatedReward, formatRewardOrHide, getRewardValue, pickFlatBasket, pickTierBasket, selectDisplayCampaign };
|
|
118
|
+
export { type BestReward, type DisplayCampaign, type RewardAudience, type RewardExample, type SelectDisplayCampaignOptions, applyRewardPlaceholder, buildPercentageExample, buildTierExample, extractMinPurchaseAmount, extractStartDate, formatBestReward, formatEstimatedReward, formatRewardOrHide, getRewardValue, pickFlatBasket, pickTierBasket, selectBestReward, selectDisplayCampaign };
|
|
101
119
|
//# sourceMappingURL=rewards.d.cts.map
|
package/dist/rewards.d.ts
CHANGED
|
@@ -75,13 +75,31 @@ type SelectDisplayCampaignOptions = {
|
|
|
75
75
|
*/
|
|
76
76
|
declare function selectDisplayCampaign(rewards: readonly MerchantReward[], options?: SelectDisplayCampaignOptions): DisplayCampaign | undefined;
|
|
77
77
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
78
|
+
* The single reward a merchant surface should display: its formatted string
|
|
79
|
+
* plus the `payoutType` of the underlying reward, so surfaces can adapt their
|
|
80
|
+
* presentation (e.g. hide percentage rewards, prefix tiered ones with "Up to").
|
|
81
|
+
*/
|
|
82
|
+
type BestReward = {
|
|
83
|
+
/** Display-ready reward string (e.g. `"5 €"`, `"10 %"`). */formatted: string; /** Payout type of the selected reward. */
|
|
84
|
+
payoutType: EstimatedReward["payoutType"];
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Pick the best campaign for `options` and resolve its `audience`-side reward
|
|
88
|
+
* to a formatted string plus its `payoutType`, or `undefined` when there is
|
|
80
89
|
* nothing worth showing.
|
|
81
90
|
*
|
|
82
91
|
* Single entry point shared by every "headline reward" surface (share button,
|
|
83
92
|
* wallet modal, sharing/install screens) so they all show the same number for
|
|
84
|
-
* a given merchant.
|
|
93
|
+
* a given merchant and can branch on the payout type.
|
|
94
|
+
*/
|
|
95
|
+
declare function selectBestReward(rewards: readonly MerchantReward[], options?: SelectDisplayCampaignOptions): BestReward | undefined;
|
|
96
|
+
/**
|
|
97
|
+
* Headline reward string for a merchant: picks the best campaign for `options`
|
|
98
|
+
* and formats its `audience`-side reward, or returns `undefined` when there is
|
|
99
|
+
* nothing worth showing.
|
|
100
|
+
*
|
|
101
|
+
* Thin wrapper over {@link selectBestReward} for callers that only need the
|
|
102
|
+
* formatted string.
|
|
85
103
|
*/
|
|
86
104
|
declare function formatBestReward(rewards: readonly MerchantReward[], options?: SelectDisplayCampaignOptions): string | undefined;
|
|
87
105
|
//#endregion
|
|
@@ -97,5 +115,5 @@ declare function formatBestReward(rewards: readonly MerchantReward[], options?:
|
|
|
97
115
|
*/
|
|
98
116
|
declare function getRewardValue(reward: EstimatedReward, key: keyof TokenAmountType): number;
|
|
99
117
|
//#endregion
|
|
100
|
-
export { type DisplayCampaign, type RewardAudience, type RewardExample, type SelectDisplayCampaignOptions, applyRewardPlaceholder, buildPercentageExample, buildTierExample, extractMinPurchaseAmount, extractStartDate, formatBestReward, formatEstimatedReward, formatRewardOrHide, getRewardValue, pickFlatBasket, pickTierBasket, selectDisplayCampaign };
|
|
118
|
+
export { type BestReward, type DisplayCampaign, type RewardAudience, type RewardExample, type SelectDisplayCampaignOptions, applyRewardPlaceholder, buildPercentageExample, buildTierExample, extractMinPurchaseAmount, extractStartDate, formatBestReward, formatEstimatedReward, formatRewardOrHide, getRewardValue, pickFlatBasket, pickTierBasket, selectBestReward, selectDisplayCampaign };
|
|
101
119
|
//# sourceMappingURL=rewards.d.ts.map
|
package/dist/rewards.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{n as e,r as t,t as n}from"./getCurrencyAmountKey-DQcwjJiB.js";function r(e){return Array.isArray(e)?e:e.conditions}function i(e){if(typeof e==`number`)return e;if(typeof e==`string`&&e.trim()!==``){let t=Number(e);return Number.isFinite(t)?t:void 0}}function a(e,t,n){let o=[];for(let s of r(e)){if(`logic`in s){o.push(...a(s,t,n));continue}if(s.field===t&&n.has(s.operator)){let e=i(s.value);e!=null&&o.push(e)}}return o}const o=new Set([`gt`,`gte`,`between`]),s=new Set([`gt`,`gte`]);function c(e){let t=a(e,`purchase.amount`,o);return t.length>0?Math.min(...t):void 0}function l(e){let t=a(e,`time.timestamp`,s);if(t.length!==0)return new Date(Math.min(...t)*1e3)}function u(e,t){let n=Math.round((e+t)/2/10)*10;return Math.min(t,Math.max(e,n))}function d(e){return Math.max(100,e??0)}function f(e,t){return t==null?e:e<=100&&100<=t?100:u(e,t)}function p(e,t){let n=d(t);if(n<=0)return;let r=e.percent/100*n;return e.minAmount&&(r=Math.max(r,e.minAmount.eurAmount)),e.maxAmount&&(r=Math.min(r,e.maxAmount.eurAmount)),{basket:n,reward:r}}function m(e,t,n){let r=f(t,n);if(!(r<=0))return{basket:r,reward:e/100*r}}function h(e,t){switch(e.payoutType){case`fixed`:return e.amount[t];case`percentage`:return e.maxAmount?.[t]??0;case`tiered`:return e.tiers.reduce((e,n)=>`amount`in n?Math.max(e,n.amount[t]):e,0)}}function g(e){return e.payoutType===`percentage`?e.percent:e.payoutType===`tiered`?e.tiers.reduce((e,t)=>`percent`in t?Math.max(e,t.percent):e,0):0}function _(e,t){let n=h(e,t);return n>0?n:g(e)*1e-6}function v(r,i){let a=t(i),o=n(a);switch(r.payoutType){case`fixed`:return e(Math.round(r.amount[o]),a);case`percentage`:return`${r.percent} %`;case`tiered`:{let t=h(r,o);if(t>0)return e(Math.round(t),a);let n=g(r);return n>0?`${n} %`:e(0,a)}}}function y(e,r){if(e&&!(_(e,n(t(r)))<=0))return v(e,r)}function b(e,t){return t?e.replace(`{REWARD}`,t):e.replace(`{REWARD}`,``)}function x(e,t){return e.expiresAt!=null&&new Date(e.expiresAt).getTime()<=t}function S(e,t){let n=l(e.conditions);return n==null||n.getTime()<=t}function C(e,t){return t===`referee`?e.referee:e.referrer}function w(e,t,n){let r=C(e,n);return r?_(r,t):0}function T(e,r={}){let i=(r.now??new Date).getTime(),a=r.audience??`referrer`,o=n(t(r.currency)),s=(r.targetInteraction?e.filter(e=>e.interactionTypeKey===r.targetInteraction):e).filter(e=>!x(e,i)),c=s.filter(e=>S(e,i));if(c.length>0)return{campaign:c.reduce((e,t)=>w(t,o,a)>w(e,o,a)?t:e),status:`live`};let u=s.map(e=>({campaign:e,startsAt:l(e.conditions)})).filter(e=>e.startsAt!=null);if(u.length===0)return;let d=u.reduce((e,t)=>t.startsAt.getTime()<e.startsAt.getTime()?t:e);return{campaign:d.campaign,status:`upcoming`,startsAt:d.startsAt}}function E(e,t={}){let n=T(e,t);if(n)return
|
|
1
|
+
import{n as e,r as t,t as n}from"./getCurrencyAmountKey-DQcwjJiB.js";function r(e){return Array.isArray(e)?e:e.conditions}function i(e){if(typeof e==`number`)return e;if(typeof e==`string`&&e.trim()!==``){let t=Number(e);return Number.isFinite(t)?t:void 0}}function a(e,t,n){let o=[];for(let s of r(e)){if(`logic`in s){o.push(...a(s,t,n));continue}if(s.field===t&&n.has(s.operator)){let e=i(s.value);e!=null&&o.push(e)}}return o}const o=new Set([`gt`,`gte`,`between`]),s=new Set([`gt`,`gte`]);function c(e){let t=a(e,`purchase.amount`,o);return t.length>0?Math.min(...t):void 0}function l(e){let t=a(e,`time.timestamp`,s);if(t.length!==0)return new Date(Math.min(...t)*1e3)}function u(e,t){let n=Math.round((e+t)/2/10)*10;return Math.min(t,Math.max(e,n))}function d(e){return Math.max(100,e??0)}function f(e,t){return t==null?e:e<=100&&100<=t?100:u(e,t)}function p(e,t){let n=d(t);if(n<=0)return;let r=e.percent/100*n;return e.minAmount&&(r=Math.max(r,e.minAmount.eurAmount)),e.maxAmount&&(r=Math.min(r,e.maxAmount.eurAmount)),{basket:n,reward:r}}function m(e,t,n){let r=f(t,n);if(!(r<=0))return{basket:r,reward:e/100*r}}function h(e,t){switch(e.payoutType){case`fixed`:return e.amount[t];case`percentage`:return e.maxAmount?.[t]??0;case`tiered`:return e.tiers.reduce((e,n)=>`amount`in n?Math.max(e,n.amount[t]):e,0)}}function g(e){return e.payoutType===`percentage`?e.percent:e.payoutType===`tiered`?e.tiers.reduce((e,t)=>`percent`in t?Math.max(e,t.percent):e,0):0}function _(e,t){let n=h(e,t);return n>0?n:g(e)*1e-6}function v(r,i){let a=t(i),o=n(a);switch(r.payoutType){case`fixed`:return e(Math.round(r.amount[o]),a);case`percentage`:return`${r.percent} %`;case`tiered`:{let t=h(r,o);if(t>0)return e(Math.round(t),a);let n=g(r);return n>0?`${n} %`:e(0,a)}}}function y(e,r){if(e&&!(_(e,n(t(r)))<=0))return v(e,r)}function b(e,t){return t?e.replace(`{REWARD}`,t):e.replace(`{REWARD}`,``)}function x(e,t){return e.expiresAt!=null&&new Date(e.expiresAt).getTime()<=t}function S(e,t){let n=l(e.conditions);return n==null||n.getTime()<=t}function C(e,t){return t===`referee`?e.referee:e.referrer}function w(e,t,n){let r=C(e,n);return r?_(r,t):0}function T(e,r={}){let i=(r.now??new Date).getTime(),a=r.audience??`referrer`,o=n(t(r.currency)),s=(r.targetInteraction?e.filter(e=>e.interactionTypeKey===r.targetInteraction):e).filter(e=>!x(e,i)),c=s.filter(e=>S(e,i));if(c.length>0)return{campaign:c.reduce((e,t)=>w(t,o,a)>w(e,o,a)?t:e),status:`live`};let u=s.map(e=>({campaign:e,startsAt:l(e.conditions)})).filter(e=>e.startsAt!=null);if(u.length===0)return;let d=u.reduce((e,t)=>t.startsAt.getTime()<e.startsAt.getTime()?t:e);return{campaign:d.campaign,status:`upcoming`,startsAt:d.startsAt}}function E(e,t={}){let n=T(e,t);if(!n)return;let r=C(n.campaign,t.audience??`referrer`);if(!r)return;let i=y(r,t.currency);if(i)return{formatted:i,payoutType:r.payoutType}}function D(e,t={}){return E(e,t)?.formatted}export{b as applyRewardPlaceholder,p as buildPercentageExample,m as buildTierExample,c as extractMinPurchaseAmount,l as extractStartDate,D as formatBestReward,v as formatEstimatedReward,y as formatRewardOrHide,h as getRewardValue,d as pickFlatBasket,f as pickTierBasket,E as selectBestReward,T as selectDisplayCampaign};
|
|
2
2
|
//# sourceMappingURL=rewards.js.map
|
package/dist/rewards.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rewards.js","names":[],"sources":["../src/rewards/conditions.ts","../src/rewards/example.ts","../src/rewards/value.ts","../src/rewards/format.ts","../src/rewards/select.ts"],"sourcesContent":["import type { ConditionGroup, RuleCondition, RuleConditions } from \"../types\";\n\ntype ConditionNode = RuleCondition | ConditionGroup;\n\nfunction conditionNodes(conditions: RuleConditions): ConditionNode[] {\n return Array.isArray(conditions) ? conditions : conditions.conditions;\n}\n\nfunction conditionValueToNumber(\n value: RuleCondition[\"value\"]\n): number | undefined {\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\" && value.trim() !== \"\") {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n}\n\n// Conditions arrive as a flat list or recursive groups; collect every numeric\n// value whose field + operator match, descending into nested groups.\nfunction collectConditionValues(\n conditions: RuleConditions,\n field: string,\n operators: ReadonlySet<RuleCondition[\"operator\"]>\n): number[] {\n const values: number[] = [];\n for (const node of conditionNodes(conditions)) {\n if (\"logic\" in node) {\n values.push(...collectConditionValues(node, field, operators));\n continue;\n }\n if (node.field === field && operators.has(node.operator)) {\n const value = conditionValueToNumber(node.value);\n if (value != null) values.push(value);\n }\n }\n return values;\n}\n\nconst MIN_PURCHASE_OPERATORS: ReadonlySet<RuleCondition[\"operator\"]> = new Set([\n \"gt\",\n \"gte\",\n \"between\",\n]);\nconst START_DATE_OPERATORS: ReadonlySet<RuleCondition[\"operator\"]> = new Set([\n \"gt\",\n \"gte\",\n]);\n\nexport function extractMinPurchaseAmount(\n conditions: RuleConditions\n): number | undefined {\n const values = collectConditionValues(\n conditions,\n \"purchase.amount\",\n MIN_PURCHASE_OPERATORS\n );\n return values.length > 0 ? Math.min(...values) : undefined;\n}\n\n// The business app encodes a campaign start as a `time.timestamp >= <unix s>`\n// rule condition; the endpoint returns it verbatim inside `conditions`.\nexport function extractStartDate(conditions: RuleConditions): Date | undefined {\n const values = collectConditionValues(\n conditions,\n \"time.timestamp\",\n START_DATE_OPERATORS\n );\n if (values.length === 0) return undefined;\n return new Date(Math.min(...values) * 1000);\n}\n","import type { EstimatedReward } from \"../types\";\n\ntype PercentageReward = Extract<EstimatedReward, { payoutType: \"percentage\" }>;\n\n// Reference order total used to turn a \"% of basket\" reward into a concrete\n// example amount. The campaign's minimum purchase overrides it when higher.\nconst REFERENCE_BASKET = 100;\n\nexport type RewardExample = {\n basket: number;\n reward: number;\n};\n\nfunction roundWithinRange(min: number, max: number): number {\n const rounded = Math.round((min + max) / 2 / 10) * 10;\n return Math.min(max, Math.max(min, rounded));\n}\n\nexport function pickFlatBasket(minPurchase: number | undefined): number {\n return Math.max(REFERENCE_BASKET, minPurchase ?? 0);\n}\n\n// Basket for a percentage tier: the reference when it sits inside the tier\n// range, a round number within the range otherwise, or the lower bound for an\n// open-ended (uncapped) top tier.\nexport function pickTierBasket(\n minValue: number,\n maxValue: number | undefined\n): number {\n if (maxValue == null) return minValue;\n if (minValue <= REFERENCE_BASKET && REFERENCE_BASKET <= maxValue) {\n return REFERENCE_BASKET;\n }\n return roundWithinRange(minValue, maxValue);\n}\n\nexport function buildPercentageExample(\n reward: PercentageReward,\n minPurchase: number | undefined\n): RewardExample | undefined {\n const basket = pickFlatBasket(minPurchase);\n if (basket <= 0) return undefined;\n let amount = (reward.percent / 100) * basket;\n if (reward.minAmount) amount = Math.max(amount, reward.minAmount.eurAmount);\n if (reward.maxAmount) amount = Math.min(amount, reward.maxAmount.eurAmount);\n return { basket, reward: amount };\n}\n\nexport function buildTierExample(\n percent: number,\n minValue: number,\n maxValue: number | undefined\n): RewardExample | undefined {\n const basket = pickTierBasket(minValue, maxValue);\n if (basket <= 0) return undefined;\n return { basket, reward: (percent / 100) * basket };\n}\n","import type { EstimatedReward, TokenAmountType } from \"../types\";\n\n/**\n * Comparable fiat value of a single reward, used to rank rewards against each\n * other.\n *\n * - `fixed` → the token amount in the requested currency\n * - `tiered` → the highest token amount across tiers\n * - `percentage` → the capped (`maxAmount`) value when present, otherwise `0`\n * (an uncapped percentage has no comparable fiat value)\n */\nexport function getRewardValue(\n reward: EstimatedReward,\n key: keyof TokenAmountType\n): number {\n switch (reward.payoutType) {\n case \"fixed\":\n return reward.amount[key];\n case \"percentage\":\n return reward.maxAmount?.[key] ?? 0;\n case \"tiered\":\n return reward.tiers.reduce(\n (max, tier) =>\n \"amount\" in tier ? Math.max(max, tier.amount[key]) : max,\n 0\n );\n }\n}\n\n/**\n * Highest percent a reward exposes: the flat `percentage` percent, or the\n * richest percent across `tiered` tiers, or `0` when it carries none.\n *\n * Shared by {@link getRewardRank} (to weight a percentage-only reward) and\n * `formatEstimatedReward` (to render it as `\"X %\"`), so the value the UI ranks\n * by and the value it prints stay derived from one tier traversal.\n */\nexport function maxRewardPercent(reward: EstimatedReward): number {\n if (reward.payoutType === \"percentage\") return reward.percent;\n if (reward.payoutType === \"tiered\") {\n return reward.tiers.reduce(\n (max, tier) =>\n \"percent\" in tier ? Math.max(max, tier.percent) : max,\n 0\n );\n }\n return 0;\n}\n\n// A reward with no money value (an uncapped percentage, or a percent-only\n// tier set) still renders as \"X %\", so it is worth surfacing. We give it a\n// positive ranking weight derived from its percent but scaled far below any\n// real-money reward, so the two invariants the UI relies on hold: (1) a reward\n// with real money always outranks a percentage-only reward, and (2) a\n// percentage-only reward still outranks a zero-value reward. Together they\n// guarantee the reward the ranking picks is always one we can display.\nconst PERCENT_ONLY_RANK_WEIGHT = 1e-6;\n\n/**\n * Ranking weight used to pick the single most attractive reward to surface.\n *\n * Mirrors {@link getRewardValue} (money value) but lifts a percentage-only\n * reward to a tiny positive weight instead of `0`, so it is never buried\n * behind a zero-value reward when choosing what to display.\n */\nexport function getRewardRank(\n reward: EstimatedReward,\n key: keyof TokenAmountType\n): number {\n const value = getRewardValue(reward, key);\n if (value > 0) return value;\n return maxRewardPercent(reward) * PERCENT_ONLY_RANK_WEIGHT;\n}\n","import type { Currency, EstimatedReward } from \"../types\";\nimport { formatAmount } from \"../utils/format/formatAmount\";\nimport { getCurrencyAmountKey } from \"../utils/format/getCurrencyAmountKey\";\nimport { getSupportedCurrency } from \"../utils/format/getSupportedCurrency\";\nimport { getRewardRank, getRewardValue, maxRewardPercent } from \"./value\";\n\n/**\n * Format an {@link EstimatedReward} into a human-readable string.\n *\n * - `fixed` → e.g. `\"5 €\"`\n * - `percentage` → e.g. `\"10 %\"`\n * - `tiered` → the richest tier: max token amount (e.g. `\"50 €\"`) or, when\n * tiers only carry percentages, the max percent (e.g. `\"10 %\"`)\n *\n * Percentages are always rendered as a `\"X %\"` string: the backend never sends\n * a reference basket, so the reward cannot be resolved to a concrete amount\n * here. Callers that need a worked example use the `example` helpers instead.\n */\nexport function formatEstimatedReward(\n reward: EstimatedReward,\n currency?: Currency\n): string {\n const supportedCurrency = getSupportedCurrency(currency);\n const key = getCurrencyAmountKey(supportedCurrency);\n\n switch (reward.payoutType) {\n case \"fixed\":\n return formatAmount(\n Math.round(reward.amount[key]),\n supportedCurrency\n );\n\n case \"percentage\":\n return `${reward.percent} %`;\n\n case \"tiered\": {\n const maxAmount = getRewardValue(reward, key);\n if (maxAmount > 0) {\n return formatAmount(Math.round(maxAmount), supportedCurrency);\n }\n const maxPercent = maxRewardPercent(reward);\n if (maxPercent > 0) {\n return `${maxPercent} %`;\n }\n return formatAmount(0, supportedCurrency);\n }\n }\n}\n\n/**\n * Format a reward for display, or return `undefined` when it is not worth\n * advertising. Callers rely on `undefined` to hide a badge / fall back to\n * other copy.\n *\n * A reward is hidden only when it carries no displayable value — a `fixed` or\n * `tiered` reward whose money value is `0` (e.g. an unknown token price). An\n * uncapped percentage always renders as `\"X %\"`, since the percent itself is\n * meaningful even without a money value.\n */\nexport function formatRewardOrHide(\n reward: EstimatedReward | undefined,\n currency?: Currency\n): string | undefined {\n if (!reward) return undefined;\n const key = getCurrencyAmountKey(getSupportedCurrency(currency));\n if (getRewardRank(reward, key) <= 0) return undefined;\n return formatEstimatedReward(reward, currency);\n}\n\n/**\n * Replace the `{REWARD}` placeholder in a text string with a reward value.\n * If no reward is provided, returns the text with `{REWARD}` stripped.\n */\nexport function applyRewardPlaceholder(\n text: string,\n reward: string | undefined\n): string {\n return reward\n ? text.replace(\"{REWARD}\", reward)\n : text.replace(\"{REWARD}\", \"\");\n}\n","import type { InteractionTypeKey } from \"../constants/interactionTypes\";\nimport type { Currency, MerchantReward, TokenAmountType } from \"../types\";\nimport { getCurrencyAmountKey } from \"../utils/format/getCurrencyAmountKey\";\nimport { getSupportedCurrency } from \"../utils/format/getSupportedCurrency\";\nimport { extractStartDate } from \"./conditions\";\nimport { formatRewardOrHide } from \"./format\";\nimport { getRewardRank } from \"./value\";\n\n/** Reward side a surface cares about: the sharer (`referrer`) or the referred\n * user (`referee`). Drives both campaign ranking and which side is displayed. */\nexport type RewardAudience = \"referrer\" | \"referee\";\n\nexport type DisplayCampaign = {\n campaign: MerchantReward;\n status: \"live\" | \"upcoming\";\n startsAt?: Date;\n};\n\nexport type SelectDisplayCampaignOptions = {\n /** Reference \"now\" for expiry / start gating; defaults to the current time. */\n now?: Date;\n /** Currency the ranking is expressed in; defaults to EUR. */\n currency?: Currency;\n /** When set, only campaigns triggered by this interaction are considered. */\n targetInteraction?: InteractionTypeKey;\n /** Reward side to rank campaigns by; defaults to `\"referrer\"`. */\n audience?: RewardAudience;\n};\n\nfunction isExpired(campaign: MerchantReward, nowMs: number): boolean {\n return (\n campaign.expiresAt != null &&\n new Date(campaign.expiresAt).getTime() <= nowMs\n );\n}\n\nfunction hasStarted(campaign: MerchantReward, nowMs: number): boolean {\n const startsAt = extractStartDate(campaign.conditions);\n return startsAt == null || startsAt.getTime() <= nowMs;\n}\n\nfunction audienceReward(campaign: MerchantReward, audience: RewardAudience) {\n return audience === \"referee\" ? campaign.referee : campaign.referrer;\n}\n\nfunction campaignRank(\n campaign: MerchantReward,\n key: keyof TokenAmountType,\n audience: RewardAudience\n): number {\n const reward = audienceReward(campaign, audience);\n return reward ? getRewardRank(reward, key) : 0;\n}\n\n/**\n * Pick the single campaign a merchant surface should display.\n *\n * Filters out expired (and, when `targetInteraction` is set, non-matching)\n * campaigns, then prefers the highest-ranked *live* campaign — ranked by the\n * `audience` reward side in the requested currency. When none has started yet\n * it falls back to the soonest-starting upcoming campaign (the endpoint does\n * not gate on the start-date condition, so future-start campaigns come\n * through).\n */\nexport function selectDisplayCampaign(\n rewards: readonly MerchantReward[],\n options: SelectDisplayCampaignOptions = {}\n): DisplayCampaign | undefined {\n const nowMs = (options.now ?? new Date()).getTime();\n const audience = options.audience ?? \"referrer\";\n const key = getCurrencyAmountKey(getSupportedCurrency(options.currency));\n\n const matching = options.targetInteraction\n ? rewards.filter(\n (campaign) =>\n campaign.interactionTypeKey === options.targetInteraction\n )\n : rewards;\n const active = matching.filter((campaign) => !isExpired(campaign, nowMs));\n\n const live = active.filter((campaign) => hasStarted(campaign, nowMs));\n if (live.length > 0) {\n const best = live.reduce((a, b) =>\n campaignRank(b, key, audience) > campaignRank(a, key, audience)\n ? b\n : a\n );\n return { campaign: best, status: \"live\" };\n }\n\n const upcoming = active\n .map((campaign) => ({\n campaign,\n startsAt: extractStartDate(campaign.conditions),\n }))\n .filter(\n (entry): entry is { campaign: MerchantReward; startsAt: Date } =>\n entry.startsAt != null\n );\n if (upcoming.length === 0) return undefined;\n\n const soonest = upcoming.reduce((a, b) =>\n b.startsAt.getTime() < a.startsAt.getTime() ? b : a\n );\n return {\n campaign: soonest.campaign,\n status: \"upcoming\",\n startsAt: soonest.startsAt,\n };\n}\n\n/**\n * Headline reward string for a merchant: picks the best campaign for `options`\n * and formats its `audience`-side reward, or returns `undefined` when there is\n * nothing worth showing.\n *\n * Single entry point shared by every \"headline reward\" surface (share button,\n * wallet modal, sharing/install screens) so they all show the same number for\n * a given merchant.\n */\nexport function formatBestReward(\n rewards: readonly MerchantReward[],\n options: SelectDisplayCampaignOptions = {}\n): string | undefined {\n const selected = selectDisplayCampaign(rewards, options);\n if (!selected) return undefined;\n const reward = audienceReward(\n selected.campaign,\n options.audience ?? \"referrer\"\n );\n return formatRewardOrHide(reward, options.currency);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rewards.js","names":[],"sources":["../src/rewards/conditions.ts","../src/rewards/example.ts","../src/rewards/value.ts","../src/rewards/format.ts","../src/rewards/select.ts"],"sourcesContent":["import type { ConditionGroup, RuleCondition, RuleConditions } from \"../types\";\n\ntype ConditionNode = RuleCondition | ConditionGroup;\n\nfunction conditionNodes(conditions: RuleConditions): ConditionNode[] {\n return Array.isArray(conditions) ? conditions : conditions.conditions;\n}\n\nfunction conditionValueToNumber(\n value: RuleCondition[\"value\"]\n): number | undefined {\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\" && value.trim() !== \"\") {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n}\n\n// Conditions arrive as a flat list or recursive groups; collect every numeric\n// value whose field + operator match, descending into nested groups.\nfunction collectConditionValues(\n conditions: RuleConditions,\n field: string,\n operators: ReadonlySet<RuleCondition[\"operator\"]>\n): number[] {\n const values: number[] = [];\n for (const node of conditionNodes(conditions)) {\n if (\"logic\" in node) {\n values.push(...collectConditionValues(node, field, operators));\n continue;\n }\n if (node.field === field && operators.has(node.operator)) {\n const value = conditionValueToNumber(node.value);\n if (value != null) values.push(value);\n }\n }\n return values;\n}\n\nconst MIN_PURCHASE_OPERATORS: ReadonlySet<RuleCondition[\"operator\"]> = new Set([\n \"gt\",\n \"gte\",\n \"between\",\n]);\nconst START_DATE_OPERATORS: ReadonlySet<RuleCondition[\"operator\"]> = new Set([\n \"gt\",\n \"gte\",\n]);\n\nexport function extractMinPurchaseAmount(\n conditions: RuleConditions\n): number | undefined {\n const values = collectConditionValues(\n conditions,\n \"purchase.amount\",\n MIN_PURCHASE_OPERATORS\n );\n return values.length > 0 ? Math.min(...values) : undefined;\n}\n\n// The business app encodes a campaign start as a `time.timestamp >= <unix s>`\n// rule condition; the endpoint returns it verbatim inside `conditions`.\nexport function extractStartDate(conditions: RuleConditions): Date | undefined {\n const values = collectConditionValues(\n conditions,\n \"time.timestamp\",\n START_DATE_OPERATORS\n );\n if (values.length === 0) return undefined;\n return new Date(Math.min(...values) * 1000);\n}\n","import type { EstimatedReward } from \"../types\";\n\ntype PercentageReward = Extract<EstimatedReward, { payoutType: \"percentage\" }>;\n\n// Reference order total used to turn a \"% of basket\" reward into a concrete\n// example amount. The campaign's minimum purchase overrides it when higher.\nconst REFERENCE_BASKET = 100;\n\nexport type RewardExample = {\n basket: number;\n reward: number;\n};\n\nfunction roundWithinRange(min: number, max: number): number {\n const rounded = Math.round((min + max) / 2 / 10) * 10;\n return Math.min(max, Math.max(min, rounded));\n}\n\nexport function pickFlatBasket(minPurchase: number | undefined): number {\n return Math.max(REFERENCE_BASKET, minPurchase ?? 0);\n}\n\n// Basket for a percentage tier: the reference when it sits inside the tier\n// range, a round number within the range otherwise, or the lower bound for an\n// open-ended (uncapped) top tier.\nexport function pickTierBasket(\n minValue: number,\n maxValue: number | undefined\n): number {\n if (maxValue == null) return minValue;\n if (minValue <= REFERENCE_BASKET && REFERENCE_BASKET <= maxValue) {\n return REFERENCE_BASKET;\n }\n return roundWithinRange(minValue, maxValue);\n}\n\nexport function buildPercentageExample(\n reward: PercentageReward,\n minPurchase: number | undefined\n): RewardExample | undefined {\n const basket = pickFlatBasket(minPurchase);\n if (basket <= 0) return undefined;\n let amount = (reward.percent / 100) * basket;\n if (reward.minAmount) amount = Math.max(amount, reward.minAmount.eurAmount);\n if (reward.maxAmount) amount = Math.min(amount, reward.maxAmount.eurAmount);\n return { basket, reward: amount };\n}\n\nexport function buildTierExample(\n percent: number,\n minValue: number,\n maxValue: number | undefined\n): RewardExample | undefined {\n const basket = pickTierBasket(minValue, maxValue);\n if (basket <= 0) return undefined;\n return { basket, reward: (percent / 100) * basket };\n}\n","import type { EstimatedReward, TokenAmountType } from \"../types\";\n\n/**\n * Comparable fiat value of a single reward, used to rank rewards against each\n * other.\n *\n * - `fixed` → the token amount in the requested currency\n * - `tiered` → the highest token amount across tiers\n * - `percentage` → the capped (`maxAmount`) value when present, otherwise `0`\n * (an uncapped percentage has no comparable fiat value)\n */\nexport function getRewardValue(\n reward: EstimatedReward,\n key: keyof TokenAmountType\n): number {\n switch (reward.payoutType) {\n case \"fixed\":\n return reward.amount[key];\n case \"percentage\":\n return reward.maxAmount?.[key] ?? 0;\n case \"tiered\":\n return reward.tiers.reduce(\n (max, tier) =>\n \"amount\" in tier ? Math.max(max, tier.amount[key]) : max,\n 0\n );\n }\n}\n\n/**\n * Highest percent a reward exposes: the flat `percentage` percent, or the\n * richest percent across `tiered` tiers, or `0` when it carries none.\n *\n * Shared by {@link getRewardRank} (to weight a percentage-only reward) and\n * `formatEstimatedReward` (to render it as `\"X %\"`), so the value the UI ranks\n * by and the value it prints stay derived from one tier traversal.\n */\nexport function maxRewardPercent(reward: EstimatedReward): number {\n if (reward.payoutType === \"percentage\") return reward.percent;\n if (reward.payoutType === \"tiered\") {\n return reward.tiers.reduce(\n (max, tier) =>\n \"percent\" in tier ? Math.max(max, tier.percent) : max,\n 0\n );\n }\n return 0;\n}\n\n// A reward with no money value (an uncapped percentage, or a percent-only\n// tier set) still renders as \"X %\", so it is worth surfacing. We give it a\n// positive ranking weight derived from its percent but scaled far below any\n// real-money reward, so the two invariants the UI relies on hold: (1) a reward\n// with real money always outranks a percentage-only reward, and (2) a\n// percentage-only reward still outranks a zero-value reward. Together they\n// guarantee the reward the ranking picks is always one we can display.\nconst PERCENT_ONLY_RANK_WEIGHT = 1e-6;\n\n/**\n * Ranking weight used to pick the single most attractive reward to surface.\n *\n * Mirrors {@link getRewardValue} (money value) but lifts a percentage-only\n * reward to a tiny positive weight instead of `0`, so it is never buried\n * behind a zero-value reward when choosing what to display.\n */\nexport function getRewardRank(\n reward: EstimatedReward,\n key: keyof TokenAmountType\n): number {\n const value = getRewardValue(reward, key);\n if (value > 0) return value;\n return maxRewardPercent(reward) * PERCENT_ONLY_RANK_WEIGHT;\n}\n","import type { Currency, EstimatedReward } from \"../types\";\nimport { formatAmount } from \"../utils/format/formatAmount\";\nimport { getCurrencyAmountKey } from \"../utils/format/getCurrencyAmountKey\";\nimport { getSupportedCurrency } from \"../utils/format/getSupportedCurrency\";\nimport { getRewardRank, getRewardValue, maxRewardPercent } from \"./value\";\n\n/**\n * Format an {@link EstimatedReward} into a human-readable string.\n *\n * - `fixed` → e.g. `\"5 €\"`\n * - `percentage` → e.g. `\"10 %\"`\n * - `tiered` → the richest tier: max token amount (e.g. `\"50 €\"`) or, when\n * tiers only carry percentages, the max percent (e.g. `\"10 %\"`)\n *\n * Percentages are always rendered as a `\"X %\"` string: the backend never sends\n * a reference basket, so the reward cannot be resolved to a concrete amount\n * here. Callers that need a worked example use the `example` helpers instead.\n */\nexport function formatEstimatedReward(\n reward: EstimatedReward,\n currency?: Currency\n): string {\n const supportedCurrency = getSupportedCurrency(currency);\n const key = getCurrencyAmountKey(supportedCurrency);\n\n switch (reward.payoutType) {\n case \"fixed\":\n return formatAmount(\n Math.round(reward.amount[key]),\n supportedCurrency\n );\n\n case \"percentage\":\n return `${reward.percent} %`;\n\n case \"tiered\": {\n const maxAmount = getRewardValue(reward, key);\n if (maxAmount > 0) {\n return formatAmount(Math.round(maxAmount), supportedCurrency);\n }\n const maxPercent = maxRewardPercent(reward);\n if (maxPercent > 0) {\n return `${maxPercent} %`;\n }\n return formatAmount(0, supportedCurrency);\n }\n }\n}\n\n/**\n * Format a reward for display, or return `undefined` when it is not worth\n * advertising. Callers rely on `undefined` to hide a badge / fall back to\n * other copy.\n *\n * A reward is hidden only when it carries no displayable value — a `fixed` or\n * `tiered` reward whose money value is `0` (e.g. an unknown token price). An\n * uncapped percentage always renders as `\"X %\"`, since the percent itself is\n * meaningful even without a money value.\n */\nexport function formatRewardOrHide(\n reward: EstimatedReward | undefined,\n currency?: Currency\n): string | undefined {\n if (!reward) return undefined;\n const key = getCurrencyAmountKey(getSupportedCurrency(currency));\n if (getRewardRank(reward, key) <= 0) return undefined;\n return formatEstimatedReward(reward, currency);\n}\n\n/**\n * Replace the `{REWARD}` placeholder in a text string with a reward value.\n * If no reward is provided, returns the text with `{REWARD}` stripped.\n */\nexport function applyRewardPlaceholder(\n text: string,\n reward: string | undefined\n): string {\n return reward\n ? text.replace(\"{REWARD}\", reward)\n : text.replace(\"{REWARD}\", \"\");\n}\n","import type { InteractionTypeKey } from \"../constants/interactionTypes\";\nimport type {\n Currency,\n EstimatedReward,\n MerchantReward,\n TokenAmountType,\n} from \"../types\";\nimport { getCurrencyAmountKey } from \"../utils/format/getCurrencyAmountKey\";\nimport { getSupportedCurrency } from \"../utils/format/getSupportedCurrency\";\nimport { extractStartDate } from \"./conditions\";\nimport { formatRewardOrHide } from \"./format\";\nimport { getRewardRank } from \"./value\";\n\n/** Reward side a surface cares about: the sharer (`referrer`) or the referred\n * user (`referee`). Drives both campaign ranking and which side is displayed. */\nexport type RewardAudience = \"referrer\" | \"referee\";\n\nexport type DisplayCampaign = {\n campaign: MerchantReward;\n status: \"live\" | \"upcoming\";\n startsAt?: Date;\n};\n\nexport type SelectDisplayCampaignOptions = {\n /** Reference \"now\" for expiry / start gating; defaults to the current time. */\n now?: Date;\n /** Currency the ranking is expressed in; defaults to EUR. */\n currency?: Currency;\n /** When set, only campaigns triggered by this interaction are considered. */\n targetInteraction?: InteractionTypeKey;\n /** Reward side to rank campaigns by; defaults to `\"referrer\"`. */\n audience?: RewardAudience;\n};\n\nfunction isExpired(campaign: MerchantReward, nowMs: number): boolean {\n return (\n campaign.expiresAt != null &&\n new Date(campaign.expiresAt).getTime() <= nowMs\n );\n}\n\nfunction hasStarted(campaign: MerchantReward, nowMs: number): boolean {\n const startsAt = extractStartDate(campaign.conditions);\n return startsAt == null || startsAt.getTime() <= nowMs;\n}\n\nfunction audienceReward(campaign: MerchantReward, audience: RewardAudience) {\n return audience === \"referee\" ? campaign.referee : campaign.referrer;\n}\n\nfunction campaignRank(\n campaign: MerchantReward,\n key: keyof TokenAmountType,\n audience: RewardAudience\n): number {\n const reward = audienceReward(campaign, audience);\n return reward ? getRewardRank(reward, key) : 0;\n}\n\n/**\n * Pick the single campaign a merchant surface should display.\n *\n * Filters out expired (and, when `targetInteraction` is set, non-matching)\n * campaigns, then prefers the highest-ranked *live* campaign — ranked by the\n * `audience` reward side in the requested currency. When none has started yet\n * it falls back to the soonest-starting upcoming campaign (the endpoint does\n * not gate on the start-date condition, so future-start campaigns come\n * through).\n */\nexport function selectDisplayCampaign(\n rewards: readonly MerchantReward[],\n options: SelectDisplayCampaignOptions = {}\n): DisplayCampaign | undefined {\n const nowMs = (options.now ?? new Date()).getTime();\n const audience = options.audience ?? \"referrer\";\n const key = getCurrencyAmountKey(getSupportedCurrency(options.currency));\n\n const matching = options.targetInteraction\n ? rewards.filter(\n (campaign) =>\n campaign.interactionTypeKey === options.targetInteraction\n )\n : rewards;\n const active = matching.filter((campaign) => !isExpired(campaign, nowMs));\n\n const live = active.filter((campaign) => hasStarted(campaign, nowMs));\n if (live.length > 0) {\n const best = live.reduce((a, b) =>\n campaignRank(b, key, audience) > campaignRank(a, key, audience)\n ? b\n : a\n );\n return { campaign: best, status: \"live\" };\n }\n\n const upcoming = active\n .map((campaign) => ({\n campaign,\n startsAt: extractStartDate(campaign.conditions),\n }))\n .filter(\n (entry): entry is { campaign: MerchantReward; startsAt: Date } =>\n entry.startsAt != null\n );\n if (upcoming.length === 0) return undefined;\n\n const soonest = upcoming.reduce((a, b) =>\n b.startsAt.getTime() < a.startsAt.getTime() ? b : a\n );\n return {\n campaign: soonest.campaign,\n status: \"upcoming\",\n startsAt: soonest.startsAt,\n };\n}\n\n/**\n * The single reward a merchant surface should display: its formatted string\n * plus the `payoutType` of the underlying reward, so surfaces can adapt their\n * presentation (e.g. hide percentage rewards, prefix tiered ones with \"Up to\").\n */\nexport type BestReward = {\n /** Display-ready reward string (e.g. `\"5 €\"`, `\"10 %\"`). */\n formatted: string;\n /** Payout type of the selected reward. */\n payoutType: EstimatedReward[\"payoutType\"];\n};\n\n/**\n * Pick the best campaign for `options` and resolve its `audience`-side reward\n * to a formatted string plus its `payoutType`, or `undefined` when there is\n * nothing worth showing.\n *\n * Single entry point shared by every \"headline reward\" surface (share button,\n * wallet modal, sharing/install screens) so they all show the same number for\n * a given merchant and can branch on the payout type.\n */\nexport function selectBestReward(\n rewards: readonly MerchantReward[],\n options: SelectDisplayCampaignOptions = {}\n): BestReward | undefined {\n const selected = selectDisplayCampaign(rewards, options);\n if (!selected) return undefined;\n const reward = audienceReward(\n selected.campaign,\n options.audience ?? \"referrer\"\n );\n if (!reward) return undefined;\n const formatted = formatRewardOrHide(reward, options.currency);\n if (!formatted) return undefined;\n return { formatted, payoutType: reward.payoutType };\n}\n\n/**\n * Headline reward string for a merchant: picks the best campaign for `options`\n * and formats its `audience`-side reward, or returns `undefined` when there is\n * nothing worth showing.\n *\n * Thin wrapper over {@link selectBestReward} for callers that only need the\n * formatted string.\n */\nexport function formatBestReward(\n rewards: readonly MerchantReward[],\n options: SelectDisplayCampaignOptions = {}\n): string | undefined {\n return selectBestReward(rewards, options)?.formatted;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"url": "https://twitter.com/QNivelais"
|
|
12
12
|
}
|
|
13
13
|
],
|
|
14
|
-
"version": "1.1.5-beta.
|
|
14
|
+
"version": "1.1.5-beta.7c6aae18",
|
|
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",
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
"viem": "^2.x"
|
|
105
105
|
},
|
|
106
106
|
"dependencies": {
|
|
107
|
-
"@frak-labs/frame-connector": "0.2.0-beta.
|
|
107
|
+
"@frak-labs/frame-connector": "0.2.0-beta.7c6aae18",
|
|
108
108
|
"@openpanel/web": "^1.4.1"
|
|
109
109
|
},
|
|
110
110
|
"devDependencies": {
|
package/src/rewards/index.ts
CHANGED
|
@@ -18,10 +18,12 @@ export {
|
|
|
18
18
|
formatRewardOrHide,
|
|
19
19
|
} from "./format";
|
|
20
20
|
export {
|
|
21
|
+
type BestReward,
|
|
21
22
|
type DisplayCampaign,
|
|
22
23
|
formatBestReward,
|
|
23
24
|
type RewardAudience,
|
|
24
25
|
type SelectDisplayCampaignOptions,
|
|
26
|
+
selectBestReward,
|
|
25
27
|
selectDisplayCampaign,
|
|
26
28
|
} from "./select";
|
|
27
29
|
export { getRewardValue } from "./value";
|
package/src/rewards/select.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { InteractionTypeKey } from "../constants/interactionTypes";
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
Currency,
|
|
4
|
+
EstimatedReward,
|
|
5
|
+
MerchantReward,
|
|
6
|
+
TokenAmountType,
|
|
7
|
+
} from "../types";
|
|
3
8
|
import { getCurrencyAmountKey } from "../utils/format/getCurrencyAmountKey";
|
|
4
9
|
import { getSupportedCurrency } from "../utils/format/getSupportedCurrency";
|
|
5
10
|
import { extractStartDate } from "./conditions";
|
|
@@ -110,23 +115,53 @@ export function selectDisplayCampaign(
|
|
|
110
115
|
}
|
|
111
116
|
|
|
112
117
|
/**
|
|
113
|
-
*
|
|
114
|
-
*
|
|
118
|
+
* The single reward a merchant surface should display: its formatted string
|
|
119
|
+
* plus the `payoutType` of the underlying reward, so surfaces can adapt their
|
|
120
|
+
* presentation (e.g. hide percentage rewards, prefix tiered ones with "Up to").
|
|
121
|
+
*/
|
|
122
|
+
export type BestReward = {
|
|
123
|
+
/** Display-ready reward string (e.g. `"5 €"`, `"10 %"`). */
|
|
124
|
+
formatted: string;
|
|
125
|
+
/** Payout type of the selected reward. */
|
|
126
|
+
payoutType: EstimatedReward["payoutType"];
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Pick the best campaign for `options` and resolve its `audience`-side reward
|
|
131
|
+
* to a formatted string plus its `payoutType`, or `undefined` when there is
|
|
115
132
|
* nothing worth showing.
|
|
116
133
|
*
|
|
117
134
|
* Single entry point shared by every "headline reward" surface (share button,
|
|
118
135
|
* wallet modal, sharing/install screens) so they all show the same number for
|
|
119
|
-
* a given merchant.
|
|
136
|
+
* a given merchant and can branch on the payout type.
|
|
120
137
|
*/
|
|
121
|
-
export function
|
|
138
|
+
export function selectBestReward(
|
|
122
139
|
rewards: readonly MerchantReward[],
|
|
123
140
|
options: SelectDisplayCampaignOptions = {}
|
|
124
|
-
):
|
|
141
|
+
): BestReward | undefined {
|
|
125
142
|
const selected = selectDisplayCampaign(rewards, options);
|
|
126
143
|
if (!selected) return undefined;
|
|
127
144
|
const reward = audienceReward(
|
|
128
145
|
selected.campaign,
|
|
129
146
|
options.audience ?? "referrer"
|
|
130
147
|
);
|
|
131
|
-
|
|
148
|
+
if (!reward) return undefined;
|
|
149
|
+
const formatted = formatRewardOrHide(reward, options.currency);
|
|
150
|
+
if (!formatted) return undefined;
|
|
151
|
+
return { formatted, payoutType: reward.payoutType };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Headline reward string for a merchant: picks the best campaign for `options`
|
|
156
|
+
* and formats its `audience`-side reward, or returns `undefined` when there is
|
|
157
|
+
* nothing worth showing.
|
|
158
|
+
*
|
|
159
|
+
* Thin wrapper over {@link selectBestReward} for callers that only need the
|
|
160
|
+
* formatted string.
|
|
161
|
+
*/
|
|
162
|
+
export function formatBestReward(
|
|
163
|
+
rewards: readonly MerchantReward[],
|
|
164
|
+
options: SelectDisplayCampaignOptions = {}
|
|
165
|
+
): string | undefined {
|
|
166
|
+
return selectBestReward(rewards, options)?.formatted;
|
|
132
167
|
}
|
|
@@ -43,6 +43,8 @@ export type ResolvedPlacement = {
|
|
|
43
43
|
referrerNoRewardText?: string;
|
|
44
44
|
ctaText?: string;
|
|
45
45
|
ctaNoRewardText?: string;
|
|
46
|
+
/** Custom illustration URL replacing the built-in gift icon. */
|
|
47
|
+
imageUrl?: string;
|
|
46
48
|
css?: string;
|
|
47
49
|
};
|
|
48
50
|
banner?: {
|
|
@@ -52,6 +54,8 @@ export type ResolvedPlacement = {
|
|
|
52
54
|
inappTitle?: string;
|
|
53
55
|
inappDescription?: string;
|
|
54
56
|
inappCta?: string;
|
|
57
|
+
/** Custom illustration URL replacing the built-in gift icon. */
|
|
58
|
+
imageUrl?: string;
|
|
55
59
|
css?: string;
|
|
56
60
|
};
|
|
57
61
|
};
|