/** * `expo-transaction-sms-reader` — public API. * * Android-only. Wraps the Kotlin native module with: * - permission helpers (with status caching + "blocked" detection) * - typed listener subscriptions (ref-counted — multiple subscribers are safe) * - heuristic transaction parser (extensible via custom parsers) * - OTP detection / extraction * - aggregation utilities (summarise, groupBy, format) * - safe iOS / web stubs */ import { type EventSubscription } from 'expo-modules-core'; import { classifySms, extractOtp, isLikelyOtpSms, isLikelyPromotionalSms, isLikelyTransactionSms, normaliseBankCode, parseTransactionSms } from './parser'; import { type CustomParser, type GetRecentMessagesOptions, type ParsedTransaction, type RawSmsMessage, type SmsPermissionStatus, type SmsReceivedEvent, type StartListeningOptions, type SummarizeOptions, type TransactionChannel, type TransactionSummary, type TransactionType } from './ExpoTransactionSmsReader.types'; export * from './ExpoTransactionSmsReader.types'; export { classifySms, extractOtp, isLikelyOtpSms, isLikelyPromotionalSms, isLikelyTransactionSms, normaliseBankCode, parseTransactionSms, }; /** * Returns the current status for `READ_SMS` + `RECEIVE_SMS`. * * Resolves to `'denied'` on iOS / web — the package is Android-only, so there * is nothing to grant. */ export declare function getPermissionStatusAsync(): Promise; /** * Prompts the user to grant `READ_SMS` and `RECEIVE_SMS`. The prompt is shown * once per app session — repeated calls after a "Don't ask again" denial will * resolve to `'blocked'` (Android 11+) or `'denied'` (older). Direct the user * to system settings in either case. * * Tip: pair this with {@link openAppSettings} to give users a one-tap path * back to the permission screen when they've blocked the prompt. */ export declare function requestPermissionsAsync(): Promise; /** * Convenience wrapper — resolves the current status, requesting permissions * if they are not already granted. Returns the final status. */ export declare function ensurePermissionsAsync(): Promise; /** * Open the host app's system settings page. Useful when the user has * blocked the SMS permission and the only way back is the OS settings UI. * * No-op on iOS / web. */ export declare function openAppSettings(): Promise; /** * Register a parser that runs *before* the built-in heuristic parser. Useful * for bank-specific formats whose body matches the heuristics poorly. * * @returns an unregister function — call it to remove the parser. */ export declare function registerParser(parser: CustomParser): () => void; /** Remove every custom parser. */ export declare function clearParsers(): void; /** * Subscribe to live SMS events. The callback fires for every incoming SMS * (subject to `minConfidence` / `extraKeywords` / `senderAllowlist`) with * both the raw message and a parsed transaction (or `null` if no parser * produced a result). * * Calling this implicitly starts the native broadcast receiver — there is no * need to call {@link startListening} separately. Multiple subscribers are * supported; the native receiver is unregistered automatically when the last * subscription is removed. * * @returns an `EventSubscription` — call `.remove()` to unsubscribe. */ export declare function addSmsListener(callback: (event: SmsReceivedEvent) => void, options?: StartListeningOptions): EventSubscription; /** * Lower-level alternative to {@link addSmsListener} — explicitly starts the * broadcast receiver without registering a JS callback. Useful when another * subsystem (e.g. a foreground service) handles delivery itself, or when you * need the receiver running for the side-effect alone. */ export declare function startListening(options?: StartListeningOptions): Promise; /** Stop the native broadcast receiver. Safe to call when not listening. */ export declare function stopListening(): Promise; /** Whether the broadcast receiver is currently registered. */ export declare function isListening(): boolean; /** * Reads recent SMS from the system inbox. Requires `READ_SMS` to have been * granted — call {@link requestPermissionsAsync} first. * * Pairs each raw SMS with a parsed transaction (or `null`). Sorted newest * first. Throws {@link SmsPermissionError} when called without permission. */ export declare function getRecentMessages(options?: GetRecentMessagesOptions): Promise>; /** * Roll an array of parsed transactions into per-currency / per-channel / * per-sender totals. Skips transactions below `minConfidence` (default 0.4) * since those are likely false positives. */ export declare function summarizeTransactions(txns: Array, options?: SummarizeOptions): TransactionSummary; /** * Group an array of parsed transactions by an arbitrary key. Common picks * include `t => t.bankCode ?? t.sender`, `t => t.channel`, or * `t => new Date(t.timestamp).toDateString()`. */ export declare function groupTransactions(txns: Array, keyFn: (t: ParsedTransaction) => K): Record; /** * Filter parsed transactions down to a `[from, to]` time range (inclusive). * Both bounds are Unix epoch ms. */ export declare function filterByDateRange(txns: Array, from: number, to: number): ParsedTransaction[]; /** * Render an amount using the parsed transaction's currency. Falls back to a * plain number when the currency is unknown. Uses `Intl.NumberFormat` under * the hood — the locale defaults to the device locale. * * @example * formatAmount(t) // "₹1,500.00" (en-IN) * formatAmount(t, { locale: 'en-PK' }) // "PKR 1,500.00" */ export declare function formatAmount(t: Pick, options?: { locale?: string; fallbackCurrency?: string; }): string; /** * Compute the signed delta a transaction makes to the user's balance: * positive for CREDIT, negative for DEBIT, `0` for UNKNOWN. Failed and * pending transactions return `0`. */ export declare function signedAmount(t: Pick): number; export type { TransactionType, TransactionChannel }; //# sourceMappingURL=index.d.ts.map