import { ChainID, Options } from "../types"; /** Wallet event kinds that `autocapture` can switch on or off individually. */ export type AutocaptureEventType = "connect" | "disconnect" | "signature" | "transaction" | "chain"; /** * What the policy knows about the event being considered. * * An object rather than a bare chain id on purpose. The `excludeChains` fix * had to thread an explicit chain through every gate because the policy had * no identity of its own, and each further per-event input would widen those * signatures again. New inputs extend this type instead. */ export interface TrackingContext { /** * The event's own chain, when it has one. It wins over the SDK's central * chain, because the two differ whenever the event did not come from the * active provider: a second wallet signing through its own transport, or a * wagmi mutation naming an explicit chain. */ chainId?: ChainID; /** * The page the event describes, when it is not the current one. A web * vitals report describes the page as loaded, and an SPA may have moved * to another route by the time it is sent. Host and path exclusions are * checked against this URL when it is given. */ url?: string; } /** What the policy needs from the SDK it advises. */ export interface TrackingPolicyDeps { /** * The CURRENT options. * * A getter, not a captured object: `FormoAnalytics.options` is public and * mutable, so a consumer can replace it after init * (`formo.options = { ...formo.options, tracking: false }`). The gates used * to read `this.options` on every call, so that took effect immediately, * and holding the constructor's object here would silently freeze * configuration at init time. */ options(): Options; /** Consent state. Separate from options because the visitor can change it. */ hasOptedOut(): boolean; /** The SDK's central chain, used when an event carries none of its own. */ currentChainId(): ChainID | undefined; } export interface ITrackingPolicy { shouldTrack(context?: TrackingContext): boolean; isTrackingSuppressed(): boolean; isChainExcluded(context?: TrackingContext): boolean; isPageExcluded(): boolean; isPersistedIdentityPurgeRequired(): boolean; isAutocaptureEnabled(eventType: AutocaptureEventType): boolean; } /** * Every "may we track this?" decision, in one place. * * Split out of `FormoAnalytics` so the rules can be read and tested without * an SDK instance, and so option parsing happens once rather than being * re-derived at each gate. */ export declare class TrackingPolicy implements ITrackingPolicy { private readonly deps; constructor(deps: TrackingPolicyDeps); /** * `tracking` as an options object, or null when it is absent, a boolean, or * anything else. Every exclusion rule lives on the object form, so a null * here means "no exclusions configured", not "excluded". */ private trackingOptions; /** * Visitor-level tracking suppression. * * True when the SDK must not persist any identity/session/chain state or * send any events for this visitor: an explicit opt-out, or a * jurisdiction/timezone/host/path exclusion. Public entry points that write * state before reaching `shouldTrack()` (identify / connect / detect) check * this first, so a suppressed visitor leaves no cookies or session state. */ isTrackingSuppressed(): boolean; /** * Whether the environment is excluded: the visitor's timezone, the current * hostname, or the current pathname. * * Timezone is visitor-level and stable for the session. Host and path are * current-page-level and transient, so a SPA navigating back to an allowed * path resumes tracking for later actions. */ private isEnvironmentExcluded; /** The page to check: `url` when given and valid, else the current page. */ private pageLocation; /** Exact match against `tracking.excludeHosts`. */ private isHostExcluded; /** Exact match against `tracking.excludePaths`. */ private isPathExcluded; /** * Case-insensitive match of the browser-resolved timezone against * `tracking.excludeTimezones`. Client-side and best-effort; see the option's * own documentation. */ private isTimezoneExcluded; /** * Whether the CURRENT PAGE is excluded, as opposed to the visitor. * * Host and path exclusions are transient: identity written on an allowed * page must survive a visit to an excluded route, so callers that persist * or restore identity skip the work here rather than purging. */ isPageExcluded(): boolean; /** * Whether a persisted identity cookie should be actively purged, not merely * left unwritten. * * Host and path exclusions are deliberately absent: they are transient * current-page states, so a cookie legitimately written on an allowed page * must survive a visit to an excluded route. */ isPersistedIdentityPurgeRequired(): boolean; /** * Whether the chain in play is in `tracking.excludeChains`. * * Separate from `shouldTrack()` so `identify()` can ask *before* mutating * identity state. `trackEvent()` drops an excluded event silently, but * `identify()` marks the wallet as identified first, so without this an * identify on an excluded chain is dedup-marked and then discarded, and the * wallet never re-emits for the rest of the session even after switching to * an allowed chain. On the Privy path that loses a whole cluster at once. */ isChainExcluded(context?: TrackingContext): boolean; /** * The shared chain rule, so `shouldTrack()` and `isChainExcluded()` cannot * drift apart. Callers have already established that `excludeChains` is * non-empty. * * Fails CLOSED on an unknown chain. `resolveChainIdForProvider` reports 0 * when it has never heard a chain from the signing wallet, and 0 is in no * exclusion list, so treating it as "not excluded" would let through exactly * the events an operator excluded: the wallet on the excluded chain is often * the one we know least about. An explicit exclusion is a directive, so an * unresolvable chain is refused. * * Keyed on 0 and deliberately NOT on `undefined`. 0 is the explicit "we * asked and could not tell" marker. `undefined` means no chain state yet, * which is a legitimate transient (the Privy path reconciles a Solana wallet * through exactly that state), and refusing it would drop real events. * `backfillActiveWallet()` never persists 0, so an unresolvable chain cannot * leak into the central value and reach the unscoped events (page / track / * identify) that fall back to it. */ private isChainRefused; /** Whether an event may be tracked at all, given consent and configuration. */ shouldTrack(context?: TrackingContext): boolean; /** Whether a wallet event kind is enabled for autocapture. Defaults to on. */ isAutocaptureEnabled(eventType: AutocaptureEventType): boolean; } //# sourceMappingURL=TrackingPolicy.d.ts.map