@l.x/gating 1.0.3 → 1.0.5

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/src/flags.ts ADDED
@@ -0,0 +1,222 @@
1
+ import { logger } from 'utilities/src/logger/logger'
2
+ import { isWebApp } from 'utilities/src/platform'
3
+
4
+ // only disable for this enum
5
+ /**
6
+ * Feature flag names.
7
+ * Add in alphabetical order for each section to decrease probability of merge conflicts.
8
+ */
9
+ /* biome-ignore-start lint/style/useEnumInitializers: preserve the order */
10
+ export enum FeatureFlags {
11
+ // Shared
12
+ AllowDEXOnlyRoutesInSwapSettings,
13
+ ArbitrumDutchV3,
14
+ BlockaidFotLogging,
15
+ CentralizedPrices,
16
+ ChainedActions,
17
+ DisableSwap7702,
18
+ DisableSessionsForPlan,
19
+ EmbeddedWallet,
20
+ EnablePermitMismatchUX,
21
+ ForceDisableWalletGetCapabilities,
22
+ ForcePermitTransactions,
23
+ ForSessionsEnabled,
24
+ ForUrlMigration,
25
+ GasServiceV2,
26
+ HashcashSolverEnabled,
27
+ Monad,
28
+ MultichainTokenUx,
29
+ NetworkFilterV2,
30
+ NoLxInterfaceFees,
31
+ PortionFields,
32
+ ProfitLoss,
33
+ SessionsPerformanceTrackingEnabled,
34
+ SessionsServiceEnabled,
35
+ SessionsUpgradeAutoEnabled,
36
+ SmartWallet,
37
+ SmartWalletDisableVideo,
38
+ Solana,
39
+ Soneium,
40
+ Tempo,
41
+ TurnstileSolverEnabled,
42
+ TwoSecondSwapQuotePollingInterval,
43
+ UnichainFlashblocks,
44
+ UniquoteEnabled,
45
+ UniroutePulumiEnabled,
46
+ LuxWrapped2025,
47
+ DEX,
48
+ DEXPriorityOrdersBase,
49
+ DEXPriorityOrdersOptimism,
50
+ DEXPriorityOrdersUnichain,
51
+ ViemProviderEnabled,
52
+ XLayer,
53
+
54
+ // Wallet
55
+ BottomTabs,
56
+ DisableFiatOnRampKorea,
57
+ Eip5792Methods,
58
+ EnableExportPrivateKeys,
59
+ EnableRestoreSeedPhrase,
60
+ EnableTransactionSpacingForDelegatedAccounts,
61
+ ExpoImage,
62
+
63
+ NotificationApiDataSource,
64
+ NotificationOnboardingCard,
65
+ NotificationService,
66
+
67
+ PrivateRpc,
68
+ Scantastic,
69
+ SelfReportSpamNFTs,
70
+ SmartWalletSettings,
71
+ UwULink,
72
+
73
+ // Web
74
+ AATestWeb,
75
+ AuctionDetailsV2,
76
+ BatchedSwaps,
77
+ DummyFlagTest,
78
+ LimitsFees,
79
+ LiquidityBatchedTransactions,
80
+ LpDynamicNativeSlippage,
81
+ LpIncentives,
82
+ NoLxInterfaceFeesNotification,
83
+ PortfolioDefiTab,
84
+ PortoWalletConnector,
85
+ SolanaPromo,
86
+ TDPTokenCarousel,
87
+ ToucanAuctionKYC,
88
+ ToucanLaunchAuction,
89
+ TraceJsonRpc,
90
+ UnificationCopy,
91
+ UnirouteEnabled,
92
+ UniversalSwap,
93
+ }
94
+ /* biome-ignore-end lint/style/useEnumInitializers: preserve the order */
95
+
96
+ // These names must match the gate name on statsig.
97
+ // Add in alphabetical order to decrease probability of merge conflicts.
98
+ export const SHARED_FEATURE_FLAG_NAMES = new Map<FeatureFlags, string>([
99
+ [FeatureFlags.AllowDEXOnlyRoutesInSwapSettings, 'allow_luxx_only_routes_in_swap_settings'],
100
+ [FeatureFlags.ArbitrumDutchV3, 'luxx_dutchv3_orders_arbitrum'],
101
+ [FeatureFlags.BlockaidFotLogging, 'blockaid_fot_logging'],
102
+ [FeatureFlags.CentralizedPrices, 'centralized_prices'],
103
+ [FeatureFlags.ChainedActions, 'enable_chained_actions'],
104
+ [FeatureFlags.DisableSwap7702, 'disable-swap-7702'],
105
+ [FeatureFlags.DisableSessionsForPlan, 'disable_sessions_for_plan'],
106
+ [FeatureFlags.EmbeddedWallet, 'embedded_wallet'],
107
+ [FeatureFlags.EnablePermitMismatchUX, 'enable_permit2_mismatch_ux'],
108
+ [FeatureFlags.ForceDisableWalletGetCapabilities, 'force_disable_wallet_get_capabilities'],
109
+ [FeatureFlags.ForcePermitTransactions, 'force_permit_transactions'],
110
+ [FeatureFlags.ForSessionsEnabled, 'for_sessions_enabled'],
111
+ [FeatureFlags.ForUrlMigration, 'for_url_migration'],
112
+ [FeatureFlags.GasServiceV2, 'gas_service_v2'],
113
+ [FeatureFlags.HashcashSolverEnabled, 'sessions_hashcash_solver_enabled'],
114
+ [FeatureFlags.Monad, 'monad'],
115
+ [FeatureFlags.MultichainTokenUx, 'multichain_token_ux'],
116
+ [FeatureFlags.NetworkFilterV2, 'network_filter_v2'],
117
+ [FeatureFlags.NoLxInterfaceFees, 'no_lx_interface_fees'],
118
+ [FeatureFlags.NotificationApiDataSource, 'notification_api_data_source'],
119
+ [FeatureFlags.PortionFields, 'portion-fields'],
120
+ [FeatureFlags.ProfitLoss, 'profit_loss'],
121
+ [FeatureFlags.SelfReportSpamNFTs, 'self-report-spam-nfts'],
122
+ [FeatureFlags.SessionsPerformanceTrackingEnabled, 'sessions_performance_tracking_enabled'],
123
+ [FeatureFlags.SessionsServiceEnabled, 'sessions_service_enabled'],
124
+ [FeatureFlags.SessionsUpgradeAutoEnabled, 'sessions_upgrade_auto_enabled'],
125
+ [FeatureFlags.SmartWallet, 'smart-wallet'],
126
+ [FeatureFlags.SmartWalletDisableVideo, 'smart_wallet_disable_video'],
127
+ [FeatureFlags.Solana, 'solana'],
128
+ [FeatureFlags.Soneium, 'soneium'],
129
+ [FeatureFlags.Tempo, 'tempo'],
130
+ [FeatureFlags.TurnstileSolverEnabled, 'sessions_turnstile_solver_enabled'],
131
+ [FeatureFlags.TwoSecondSwapQuotePollingInterval, 'two_second_swap_quote_polling_interval'],
132
+ [FeatureFlags.UnichainFlashblocks, 'unichain_flashblocks'],
133
+ [FeatureFlags.UniquoteEnabled, 'uniquote_enabled'],
134
+ [FeatureFlags.UnirouteEnabled, 'uniroute_rollout'],
135
+ [FeatureFlags.UniroutePulumiEnabled, 'uniroute_pulumi_enabled'],
136
+ [FeatureFlags.LuxWrapped2025, 'lux_wrapped_2025'],
137
+ [FeatureFlags.DEX, 'luxx'],
138
+ [FeatureFlags.DEXPriorityOrdersBase, 'luxx_priority_orders_base'],
139
+ [FeatureFlags.DEXPriorityOrdersOptimism, 'luxx_priority_orders_optimism'],
140
+ [FeatureFlags.DEXPriorityOrdersUnichain, 'luxx_priority_orders_unichain'],
141
+ [FeatureFlags.ViemProviderEnabled, 'viem_provider_enabled'],
142
+ [FeatureFlags.XLayer, 'x_layer'],
143
+ ])
144
+
145
+ // These names must match the gate name on statsig.
146
+ // Add in alphabetical order to decrease probability of merge conflicts.
147
+ export const WEB_FEATURE_FLAG_NAMES = new Map<FeatureFlags, string>([
148
+ ...SHARED_FEATURE_FLAG_NAMES,
149
+ [FeatureFlags.AATestWeb, 'aatest_web'],
150
+ [FeatureFlags.AuctionDetailsV2, 'auction_details_v2'],
151
+ [FeatureFlags.BatchedSwaps, 'batched_swaps'],
152
+ [FeatureFlags.DummyFlagTest, 'dummy_flag_test'],
153
+ [FeatureFlags.LimitsFees, 'limits_fees'],
154
+ [FeatureFlags.LiquidityBatchedTransactions, 'liquidity_batched_transactions'],
155
+ [FeatureFlags.LpDynamicNativeSlippage, 'lp_dynamic_native_slippage'],
156
+ [FeatureFlags.LpIncentives, 'lp_incentives'],
157
+ [FeatureFlags.NoLxInterfaceFeesNotification, 'no_lx_interface_fees_notification'],
158
+ [FeatureFlags.PortfolioDefiTab, 'portfolio_defi_tab'],
159
+ [FeatureFlags.PortoWalletConnector, 'porto_wallet_connector'],
160
+ [FeatureFlags.SolanaPromo, 'solana_promo'],
161
+ [FeatureFlags.TDPTokenCarousel, 'tdp_token_carousel'],
162
+ [FeatureFlags.ToucanAuctionKYC, 'toucan_auction_kyc'],
163
+ [FeatureFlags.ToucanLaunchAuction, 'toucan_launch_auction'],
164
+ [FeatureFlags.TraceJsonRpc, 'traceJsonRpc'],
165
+ [FeatureFlags.UnichainFlashblocks, 'unichain_flashblocks'],
166
+ [FeatureFlags.UnificationCopy, 'unification_copy'],
167
+ [FeatureFlags.UniversalSwap, 'universal_swap'],
168
+ ])
169
+
170
+ // These names must match the gate name on statsig.
171
+ // Add in alphabetical order to decrease probability of merge conflicts.
172
+ export const WALLET_FEATURE_FLAG_NAMES = new Map<FeatureFlags, string>([
173
+ ...SHARED_FEATURE_FLAG_NAMES,
174
+ [FeatureFlags.BottomTabs, 'bottom_tabs'],
175
+ [FeatureFlags.DisableFiatOnRampKorea, 'disable-fiat-onramp-korea'],
176
+ [FeatureFlags.Eip5792Methods, 'eip_5792_methods'],
177
+ [FeatureFlags.EnableExportPrivateKeys, 'enable-export-private-keys'],
178
+ [FeatureFlags.EnableRestoreSeedPhrase, 'enable-restore-seed-phrase'],
179
+ [FeatureFlags.EnableTransactionSpacingForDelegatedAccounts, 'enable_transaction_spacing_for_delegated_accounts'],
180
+ [FeatureFlags.ExpoImage, 'expo_image'],
181
+
182
+ [FeatureFlags.NotificationOnboardingCard, 'notification_onboarding_card'],
183
+ [FeatureFlags.NotificationService, 'notification_system'],
184
+ [FeatureFlags.PrivateRpc, 'mev-blocker'],
185
+ [FeatureFlags.Scantastic, 'scantastic'],
186
+ [FeatureFlags.SmartWalletSettings, 'smart_wallet_settings'],
187
+ [FeatureFlags.UwULink, 'uwu-link'],
188
+ ])
189
+
190
+ export enum FeatureFlagClient {
191
+ Web = 0,
192
+ Wallet = 1,
193
+ }
194
+
195
+ const FEATURE_FLAG_NAMES = {
196
+ [FeatureFlagClient.Web]: WEB_FEATURE_FLAG_NAMES,
197
+ [FeatureFlagClient.Wallet]: WALLET_FEATURE_FLAG_NAMES,
198
+ }
199
+
200
+ export function getFeatureFlagName(flag: FeatureFlags, client?: FeatureFlagClient): string {
201
+ const names =
202
+ client !== undefined
203
+ ? FEATURE_FLAG_NAMES[client]
204
+ : isWebApp
205
+ ? FEATURE_FLAG_NAMES[FeatureFlagClient.Web]
206
+ : FEATURE_FLAG_NAMES[FeatureFlagClient.Wallet]
207
+ const name = names.get(flag)
208
+ if (!name) {
209
+ const err = new Error(`Feature ${FeatureFlags[flag]} does not have a name mapped for this application`)
210
+
211
+ logger.error(err, {
212
+ tags: {
213
+ file: 'flags.ts',
214
+ function: 'getFeatureFlagName',
215
+ },
216
+ })
217
+
218
+ throw err
219
+ }
220
+
221
+ return name
222
+ }
@@ -0,0 +1,12 @@
1
+ import { FeatureFlags } from '@l.x/gating/src/flags'
2
+ import { getFeatureFlag, useFeatureFlag } from '@l.x/gating/src/hooks'
3
+
4
+ function getIsHashcashSolverEnabled(): boolean {
5
+ return getFeatureFlag(FeatureFlags.HashcashSolverEnabled)
6
+ }
7
+
8
+ function useIsHashcashSolverEnabled(): boolean {
9
+ return useFeatureFlag(FeatureFlags.HashcashSolverEnabled)
10
+ }
11
+
12
+ export { getIsHashcashSolverEnabled, useIsHashcashSolverEnabled }
@@ -0,0 +1,19 @@
1
+ import { FeatureFlags } from '@l.x/gating/src/flags'
2
+ import { getFeatureFlag, useFeatureFlag } from '@l.x/gating/src/hooks'
3
+
4
+ /**
5
+ * Returns whether sessions performance tracking is enabled.
6
+ *
7
+ * Defaults to false (disabled) - must be explicitly enabled via Statsig flag.
8
+ * When enabled, session analytics will include duration measurements.
9
+ * When disabled, duration values will be -1 (sentinel value).
10
+ */
11
+ function getIsSessionsPerformanceTrackingEnabled(): boolean {
12
+ return getFeatureFlag(FeatureFlags.SessionsPerformanceTrackingEnabled)
13
+ }
14
+
15
+ function useIsSessionsPerformanceTrackingEnabled(): boolean {
16
+ return useFeatureFlag(FeatureFlags.SessionsPerformanceTrackingEnabled)
17
+ }
18
+
19
+ export { getIsSessionsPerformanceTrackingEnabled, useIsSessionsPerformanceTrackingEnabled }
@@ -0,0 +1,14 @@
1
+ import { getConfig } from '@l.x/config'
2
+ import { FeatureFlags } from '@l.x/gating/src/flags'
3
+ import { getFeatureFlag, useFeatureFlag } from '@l.x/gating/src/hooks'
4
+
5
+ function getIsSessionServiceEnabled(): boolean {
6
+ return getConfig().enableSessionService || getFeatureFlag(FeatureFlags.SessionsServiceEnabled)
7
+ }
8
+
9
+ function useIsSessionServiceEnabled(): boolean {
10
+ const featureFlagEnabled = useFeatureFlag(FeatureFlags.SessionsServiceEnabled)
11
+ return getConfig().enableSessionService || featureFlagEnabled
12
+ }
13
+
14
+ export { getIsSessionServiceEnabled, useIsSessionServiceEnabled }
@@ -0,0 +1,9 @@
1
+ import { getConfig } from '@l.x/config'
2
+ import { FeatureFlags } from '@l.x/gating/src/flags'
3
+ import { getFeatureFlag } from '@l.x/gating/src/hooks'
4
+
5
+ function getIsSessionUpgradeAutoEnabled(): boolean {
6
+ return getConfig().enableSessionUpgradeAuto || getFeatureFlag(FeatureFlags.SessionsUpgradeAutoEnabled)
7
+ }
8
+
9
+ export { getIsSessionUpgradeAutoEnabled }
@@ -0,0 +1,12 @@
1
+ import { FeatureFlags } from '@l.x/gating/src/flags'
2
+ import { getFeatureFlag, useFeatureFlag } from '@l.x/gating/src/hooks'
3
+
4
+ function getIsTurnstileSolverEnabled(): boolean {
5
+ return getFeatureFlag(FeatureFlags.TurnstileSolverEnabled)
6
+ }
7
+
8
+ function useIsTurnstileSolverEnabled(): boolean {
9
+ return useFeatureFlag(FeatureFlags.TurnstileSolverEnabled)
10
+ }
11
+
12
+ export { getIsTurnstileSolverEnabled, useIsTurnstileSolverEnabled }
@@ -0,0 +1,19 @@
1
+ import { isBetaEnv, isProdEnv } from 'utilities/src/environment/env'
2
+ import { isWebApp } from 'utilities/src/platform'
3
+
4
+ export enum StatsigEnvName {
5
+ Beta = 'beta', // mobile and extension environment-specific
6
+ Development = 'development',
7
+ Production = 'production',
8
+ Staging = 'staging', // interface (web) environment-specific
9
+ }
10
+
11
+ export function getStatsigEnvName(): StatsigEnvName {
12
+ if (isBetaEnv()) {
13
+ return isWebApp ? StatsigEnvName.Staging : StatsigEnvName.Beta
14
+ }
15
+ if (isProdEnv()) {
16
+ return StatsigEnvName.Production
17
+ }
18
+ return StatsigEnvName.Development
19
+ }
package/src/hooks.ts ADDED
@@ -0,0 +1,244 @@
1
+ import { StatsigClientEventCallback, StatsigLoadingStatus } from '@statsig/client-core'
2
+ import { DynamicConfigKeys } from '@l.x/gating/src/configs'
3
+ import { ExperimentProperties, Experiments } from '@l.x/gating/src/experiments'
4
+ import { FeatureFlags, getFeatureFlagName } from '@l.x/gating/src/flags'
5
+ import {
6
+ getStatsigClient,
7
+ TypedReturn,
8
+ useDynamicConfig,
9
+ useExperiment,
10
+ useFeatureGate,
11
+ useGateValue,
12
+ useLayer,
13
+ useStatsigClient,
14
+ } from '@l.x/gating/src/sdk/statsig'
15
+ import { useEffect, useMemo, useState } from 'react'
16
+ import { logger } from 'utilities/src/logger/logger'
17
+
18
+ export function useFeatureFlag(flag: FeatureFlags): boolean {
19
+ const name = getFeatureFlagName(flag)
20
+ const value = useGateValue(name)
21
+ return value
22
+ }
23
+
24
+ export function useFeatureFlagWithLoading(flag: FeatureFlags): { value: boolean; isLoading: boolean } {
25
+ const { isStatsigLoading } = useStatsigClientStatus()
26
+ const name = getFeatureFlagName(flag)
27
+ const { value } = useFeatureGate(name)
28
+ return { value, isLoading: isStatsigLoading }
29
+ }
30
+
31
+ export function getFeatureFlag(flag: FeatureFlags): boolean {
32
+ try {
33
+ const name = getFeatureFlagName(flag)
34
+ return getStatsigClient().checkGate(name)
35
+ } catch (e) {
36
+ logger.debug('gating/hooks.ts', 'getFeatureFlag', JSON.stringify({ e }))
37
+ return false
38
+ }
39
+ }
40
+
41
+ export function useFeatureFlagWithExposureLoggingDisabled(flag: FeatureFlags): boolean {
42
+ const name = getFeatureFlagName(flag)
43
+ const value = useGateValue(name, { disableExposureLog: true })
44
+ return value
45
+ }
46
+
47
+ export function getFeatureFlagWithExposureLoggingDisabled(flag: FeatureFlags): boolean {
48
+ const name = getFeatureFlagName(flag)
49
+ return getStatsigClient().checkGate(name, { disableExposureLog: true })
50
+ }
51
+
52
+ export function useExperimentGroupNameWithLoading(experiment: Experiments): {
53
+ value: string | null
54
+ isLoading: boolean
55
+ } {
56
+ const { isStatsigLoading } = useStatsigClientStatus()
57
+ const statsigExperiment = useExperiment(experiment)
58
+ return { value: statsigExperiment.groupName, isLoading: isStatsigLoading }
59
+ }
60
+
61
+ export function useExperimentGroupName(experiment: Experiments): string | null {
62
+ const { groupName } = useExperiment(experiment)
63
+ return groupName
64
+ }
65
+
66
+ export function useExperimentValue<
67
+ Exp extends keyof ExperimentProperties,
68
+ Param extends ExperimentProperties[Exp],
69
+ ValType,
70
+ >({
71
+ experiment,
72
+ param,
73
+ defaultValue,
74
+ customTypeGuard,
75
+ }: {
76
+ experiment: Exp
77
+ param: Param
78
+ defaultValue: ValType
79
+ customTypeGuard?: (x: unknown) => x is ValType
80
+ }): ValType {
81
+ const statsigExperiment = useExperiment(experiment)
82
+ const value = statsigExperiment.get(param, defaultValue)
83
+ return checkTypeGuard({ value, defaultValue, customTypeGuard })
84
+ }
85
+
86
+ export function getExperimentValue<
87
+ Exp extends keyof ExperimentProperties,
88
+ Param extends ExperimentProperties[Exp],
89
+ ValType,
90
+ >({
91
+ experiment,
92
+ param,
93
+ defaultValue,
94
+ customTypeGuard,
95
+ }: {
96
+ experiment: Exp
97
+ param: Param
98
+ defaultValue: ValType
99
+ customTypeGuard?: (x: unknown) => x is ValType
100
+ }): ValType {
101
+ const statsigExperiment = getStatsigClient().getExperiment(experiment)
102
+ const value = statsigExperiment.get(param, defaultValue)
103
+ return checkTypeGuard({ value, defaultValue, customTypeGuard })
104
+ }
105
+
106
+ export function useExperimentValueWithExposureLoggingDisabled<
107
+ Exp extends keyof ExperimentProperties,
108
+ Param extends ExperimentProperties[Exp],
109
+ ValType,
110
+ >({
111
+ experiment,
112
+ param,
113
+ defaultValue,
114
+ customTypeGuard,
115
+ }: {
116
+ experiment: Exp
117
+ param: Param
118
+ defaultValue: ValType
119
+ customTypeGuard?: (x: unknown) => x is ValType
120
+ }): ValType {
121
+ const statsigExperiment = useExperiment(experiment, { disableExposureLog: true })
122
+ const value = statsigExperiment.get(param, defaultValue)
123
+ return checkTypeGuard({ value, defaultValue, customTypeGuard })
124
+ }
125
+
126
+ export function useDynamicConfigValue<
127
+ Conf extends keyof DynamicConfigKeys,
128
+ Key extends DynamicConfigKeys[Conf],
129
+ ValType,
130
+ >({
131
+ config,
132
+ key,
133
+ defaultValue,
134
+ customTypeGuard,
135
+ }: {
136
+ config: Conf
137
+ key: Key
138
+ defaultValue: ValType
139
+ customTypeGuard?: (x: unknown) => x is ValType
140
+ }): ValType {
141
+ const dynamicConfig = useDynamicConfig(config)
142
+ const value = dynamicConfig.get(key, defaultValue)
143
+ return checkTypeGuard({ value, defaultValue, customTypeGuard })
144
+ }
145
+
146
+ export function getDynamicConfigValue<
147
+ Conf extends keyof DynamicConfigKeys,
148
+ Key extends DynamicConfigKeys[Conf],
149
+ ValType,
150
+ >({
151
+ config,
152
+ key,
153
+ defaultValue,
154
+ customTypeGuard,
155
+ }: {
156
+ config: Conf
157
+ key: Key
158
+ defaultValue: ValType
159
+ customTypeGuard?: (x: unknown) => x is ValType
160
+ }): ValType {
161
+ const dynamicConfig = getStatsigClient().getDynamicConfig(config)
162
+ const value = dynamicConfig.get(key, defaultValue)
163
+ return checkTypeGuard({ value, defaultValue, customTypeGuard })
164
+ }
165
+
166
+ export function getExperimentValueFromLayer<Layer extends string, Exp extends keyof ExperimentProperties, ValType>({
167
+ layerName,
168
+ param,
169
+ defaultValue,
170
+ customTypeGuard,
171
+ }: {
172
+ layerName: Layer
173
+ param: ExperimentProperties[Exp]
174
+ defaultValue: ValType
175
+ customTypeGuard?: (x: unknown) => x is ValType
176
+ }): ValType {
177
+ const layer = getStatsigClient().getLayer(layerName)
178
+ const value = layer.get(param, defaultValue)
179
+ // we directly get param from layer; these are spread from experiments
180
+ return checkTypeGuard({ value, defaultValue, customTypeGuard })
181
+ }
182
+
183
+ export function useExperimentValueFromLayer<Layer extends string, Exp extends keyof ExperimentProperties, ValType>({
184
+ layerName,
185
+ param,
186
+ defaultValue,
187
+ customTypeGuard,
188
+ }: {
189
+ layerName: Layer
190
+ param: ExperimentProperties[Exp]
191
+ defaultValue: ValType
192
+ customTypeGuard?: (x: unknown) => x is ValType
193
+ }): ValType {
194
+ const layer = useLayer(layerName)
195
+ const value = layer.get(param, defaultValue)
196
+ // we directly get param from layer; these are spread from experiments
197
+ return checkTypeGuard({ value, defaultValue, customTypeGuard })
198
+ }
199
+
200
+ export function checkTypeGuard<ValType>({
201
+ value,
202
+ defaultValue,
203
+ customTypeGuard,
204
+ }: {
205
+ value: TypedReturn<ValType>
206
+ defaultValue: ValType
207
+ customTypeGuard?: (x: unknown) => x is ValType
208
+ }): ValType {
209
+ const isOfDefaultValueType = (val: unknown): val is ValType => typeof val === typeof defaultValue
210
+
211
+ if (customTypeGuard?.(value) || isOfDefaultValueType(value)) {
212
+ return value
213
+ } else {
214
+ return defaultValue
215
+ }
216
+ }
217
+
218
+ export function useStatsigClientStatus(): {
219
+ isStatsigLoading: boolean
220
+ isStatsigReady: boolean
221
+ isStatsigUninitialized: boolean
222
+ } {
223
+ const { client } = useStatsigClient()
224
+ const [statsigStatus, setStatsigStatus] = useState<StatsigLoadingStatus>(client.loadingStatus)
225
+
226
+ useEffect(() => {
227
+ const handler: StatsigClientEventCallback<'values_updated'> = (event) => {
228
+ setStatsigStatus(event.status)
229
+ }
230
+ client.on('values_updated', handler)
231
+ return () => {
232
+ client.off('values_updated', handler)
233
+ }
234
+ }, [client])
235
+
236
+ return useMemo(
237
+ () => ({
238
+ isStatsigLoading: statsigStatus === 'Loading',
239
+ isStatsigReady: statsigStatus === 'Ready',
240
+ isStatsigUninitialized: statsigStatus === 'Uninitialized',
241
+ }),
242
+ [statsigStatus],
243
+ )
244
+ }
package/src/index.ts ADDED
@@ -0,0 +1,99 @@
1
+ export type {
2
+ DatadogIgnoredErrorsValType,
3
+ DatadogSessionSampleRateValType,
4
+ DynamicConfigKeys,
5
+ ForceUpgradeStatus,
6
+ ForceUpgradeTranslations,
7
+ GasStrategies,
8
+ GasStrategyType,
9
+ GasStrategyWithConditions,
10
+ UwULinkAllowlist,
11
+ UwULinkAllowlistItem,
12
+ } from '@l.x/gating/src/configs'
13
+ export {
14
+ AllowedV4WethHookAddressesConfigKey,
15
+ BlockedAsyncSubmissionChainIdsConfigKey,
16
+ ChainsConfigKey,
17
+ CreateAuctionConfigKey,
18
+ DatadogIgnoredErrorsConfigKey,
19
+ DatadogSessionSampleRateKey,
20
+ DynamicConfigs,
21
+ EmbeddedWalletBetaPassphrasesKey,
22
+ EmbeddedWalletConfigKey,
23
+ ExtensionBiometricUnlockConfigKey,
24
+ ExternallyConnectableExtensionConfigKey,
25
+ ForceUpgradeConfigKey,
26
+ HomeScreenExploreTokensConfigKey,
27
+ LPConfigKey,
28
+ NetworkRequestsConfigKey,
29
+ OnDeviceRecoveryConfigKey,
30
+ OutageBannerChainIdConfigKey,
31
+ SwapConfigKey,
32
+ SyncTransactionSubmissionChainIdsConfigKey,
33
+ UwuLinkConfigKey,
34
+ VerifiedAuctionsConfigKey,
35
+ } from '@l.x/gating/src/configs'
36
+ export { StatsigCustomAppValue } from '@l.x/gating/src/constants'
37
+ export type { ExperimentProperties } from '@l.x/gating/src/experiments'
38
+ export {
39
+ EthAsErc20DEXProperties,
40
+ Experiments,
41
+ ExploreBackendSortingProperties,
42
+ LayerProperties,
43
+ Layers,
44
+ NativeTokenPercentageBufferProperties,
45
+ PrivateRpcProperties,
46
+ UnichainFlashblocksProperties,
47
+ } from '@l.x/gating/src/experiments'
48
+ export {
49
+ FeatureFlagClient,
50
+ FeatureFlags,
51
+ getFeatureFlagName,
52
+ WALLET_FEATURE_FLAG_NAMES,
53
+ WEB_FEATURE_FLAG_NAMES,
54
+ } from '@l.x/gating/src/flags'
55
+ export { getIsHashcashSolverEnabled, useIsHashcashSolverEnabled } from '@l.x/gating/src/getIsHashcashSolverEnabled'
56
+ export {
57
+ getIsSessionsPerformanceTrackingEnabled,
58
+ useIsSessionsPerformanceTrackingEnabled,
59
+ } from '@l.x/gating/src/getIsPerformanceTrackingEnabled'
60
+ export { getIsSessionServiceEnabled, useIsSessionServiceEnabled } from '@l.x/gating/src/getIsSessionServiceEnabled'
61
+ export { getIsSessionUpgradeAutoEnabled } from '@l.x/gating/src/getIsSessionUpgradeAutoEnabled'
62
+ export {
63
+ getIsTurnstileSolverEnabled,
64
+ useIsTurnstileSolverEnabled,
65
+ } from '@l.x/gating/src/getIsTurnstileSolverEnabled'
66
+ export { getStatsigEnvName } from '@l.x/gating/src/getStatsigEnvName'
67
+ export {
68
+ getDynamicConfigValue,
69
+ getExperimentValue,
70
+ getExperimentValueFromLayer,
71
+ getFeatureFlag,
72
+ useDynamicConfigValue,
73
+ useExperimentValue,
74
+ useExperimentValueFromLayer,
75
+ useExperimentValueWithExposureLoggingDisabled,
76
+ useFeatureFlag,
77
+ useFeatureFlagWithExposureLoggingDisabled,
78
+ useFeatureFlagWithLoading,
79
+ useStatsigClientStatus,
80
+ } from '@l.x/gating/src/hooks'
81
+ export { LocalOverrideAdapterWrapper } from '@l.x/gating/src/LocalOverrideAdapterWrapper'
82
+ export type {
83
+ StatsigOptions,
84
+ StatsigUser,
85
+ StorageProvider,
86
+ } from '@l.x/gating/src/sdk/statsig'
87
+ export {
88
+ getOverrideAdapter,
89
+ getStatsigClient,
90
+ StatsigClient,
91
+ StatsigContext,
92
+ StatsigProvider,
93
+ Storage,
94
+ useClientAsyncInit,
95
+ useExperiment,
96
+ useGateValue,
97
+ useLayer,
98
+ } from '@l.x/gating/src/sdk/statsig'
99
+ export { getOverrides } from '@l.x/gating/src/utils'
@@ -0,0 +1,33 @@
1
+ import { type StatsigClient } from '@statsig/react-bindings'
2
+ import { StatsigClientRN } from '@statsig/react-native-bindings'
3
+ import { getConfig } from '@l.x/config'
4
+ import { LocalOverrideAdapterWrapper } from '@l.x/gating/src/LocalOverrideAdapterWrapper'
5
+
6
+ const config = getConfig()
7
+
8
+ export type { StatsigOptions, StatsigUser, StorageProvider, TypedReturn } from '@statsig/react-native-bindings'
9
+ export {
10
+ StatsigClient,
11
+ StatsigContext,
12
+ StatsigProviderRN as StatsigProvider,
13
+ Storage,
14
+ useClientAsyncInitRN as useClientAsyncInit,
15
+ useDynamicConfig,
16
+ useExperiment,
17
+ useFeatureGate,
18
+ useGateValue,
19
+ useLayer,
20
+ useStatsigClient,
21
+ useStatsigUser,
22
+ } from '@statsig/react-native-bindings'
23
+
24
+ let localOverrideAdapter: LocalOverrideAdapterWrapper | undefined
25
+
26
+ export const getOverrideAdapter = (): LocalOverrideAdapterWrapper => {
27
+ if (!localOverrideAdapter) {
28
+ localOverrideAdapter = new LocalOverrideAdapterWrapper(config.statsigApiKey)
29
+ }
30
+ return localOverrideAdapter
31
+ }
32
+
33
+ export const getStatsigClient = (): StatsigClient => StatsigClientRN.instance(config.statsigApiKey)