import type { ChainType, IEnv } from '../../types'; /** * Path on the August public API that accepts a failed-redemption report. Chain * lives in the payload, not the path — see {@link IRedeemFailureEvent.chain}. */ export declare const CURATOR_ALERT_PATH = "/alerts/redeem-failure"; /** * Where a redeem failure is reported: the August public API, which is already * this SDK's read origin and already serves browsers. * * Browser delivery depends on CORS, and the API's allowlist is an enumerated * list of partner origins (`ALLOWED_ORIGIN_REGEX` in the backend), not a * wildcard. This POST sends `Content-Type: application/json`, so it is * preflighted; an integration served from an origin that is not on that list * loses every alert at the preflight. Onboarding a curator therefore has two * halves — enabling the vault and allowlisting the origin their users load. * * That service is the trust boundary, not the destination: it validates the * report, drops any vault it does not know or that has not opted in, * rate-limits per wallet and per vault, and only then forwards to the Telegram * bot that holds the token and the curator's channel. Nothing * credential-shaped ships in this bundle, which is also why this endpoint * takes no API key — a key in a browser bundle is a published key * (CLAUDE.md §5). See {@link reportRedeemFailure} for the trust model. */ export declare const DEFAULT_CURATOR_ALERT_ENDPOINT: string; /** Env equivalent of `monitoring.curatorAlerts.enabled: false`. Node only. */ export declare const CURATOR_ALERTS_DISABLE_ENV_VAR = "AUGUST_SDK_DISABLE_CURATOR_ALERTS"; /** Curator-alert reporting. Enabled by default; this is the opt-out. */ export interface ICuratorAlertsConfig { /** * `false` stops emitting entirely. `true` forces emitting even in an * environment the SDK would otherwise stay quiet in — it bypasses **every** * environment gate: `NODE_ENV` of `development`/`test`, a browser served * from a loopback or private host, and `monitoring.env` other than `PROD`. * It does NOT lift the mainnet-only restriction; only `endpoint` does. A * `DEV` or test * integration that sets it and then fails a mainnet redeem pages a real * curator, so use it only when deliberately exercising the path (pair it * with `endpoint` to aim at a test relay). The only thing that still wins is * the {@link CURATOR_ALERTS_DISABLE_ENV_VAR} kill switch. */ enabled?: boolean; /** * Override the relay endpoint. Defaults to * {@link DEFAULT_CURATOR_ALERT_ENDPOINT}. Setting it also lifts the * mainnet-only restriction, so a staging relay can receive testnet failures. */ endpoint?: string; } /** Fields every report carries, whatever stage the redemption failed at. */ interface IRedeemFailureBase { /** * Chain family the vault lives on. Carried rather than assumed so the * receiving endpoint stays one contract for every chain; it decides which * families it actually serves, and validates the identifiers below by that * family's rules. */ chain: ChainType; /** * Network within the family, in that family's own vocabulary — Stellar's * `mainnet`/`testnet`, Solana's `mainnet-beta`, an EVM network name. A plain * string rather than one family's union, because the receiving endpoint * validates it against the family named in `chain`; typing it as Stellar's * two values would make this the narrower half of a contract the rest of this * module describes as chain-agnostic. */ network: string; /** Vault identifier in the chain's own format. The endpoint routes on this. */ contractId: string; /** Account that attempted the redemption, in the chain's own format. */ eoa: string; /** Shares requested, in the vault's smallest unit (unscaled). */ sharesRaw: string; /** Failure detail; sanitized and capped before it leaves the process. */ error: string; } /** * A redemption the vault refused before anything reached chain — a failed * simulation, or a vault whose ledger state needs restoring. There is no * on-chain artifact, so the receiving endpoint has nothing to verify the claim * against and treats it as the weaker of the two. Which build stage raised it * stays legible in `error`. */ interface IRedeemBuildFailure extends IRedeemFailureBase { phase: 'simulation'; } /** * A redemption that executed on chain and failed. `txHash` is what makes this * the stronger claim — the endpoint can verify it — so it is required here * rather than optional, which is the whole reason these are two types. */ interface IRedeemSubmissionFailure extends IRedeemFailureBase { phase: 'submission'; /** The failed transaction. Verifiable, which is why it is not optional. */ txHash: string; /** Transaction result code, when the result XDR decoded. */ resultCode?: string; } /** * A redemption failure worth a curator's attention. * * Two members rather than one shape with optional fields, because `txHash` is * only meaningful — and is always available — on the submission path. As a * single interface, `{ phase: 'simulation', txHash }` and a submission report * with no hash both type-checked, and the receiving endpoint's `is_well_formed` * check was the only thing between either and a silently dropped alert. That * check stays, since a server cannot trust its input, but it is no longer * covering for a shape this SDK could have made unrepresentable. The two call * sites in `adapters/stellar/` are the ones this actually constrains, and they * are type-checked by `pnpm build`. * * @internal */ export type IRedeemFailureEvent = IRedeemBuildFailure | IRedeemSubmissionFailure; /** Ambient facts about the reporting SDK instance, supplied by `AugustBase`. */ export interface ICuratorAlertsContext { /** Carried on the payload so August can tell partner traffic apart. */ appName?: string; /** * `monitoring.env`. Anything other than `'PROD'` keeps the SDK quiet unless * `config.enabled` is explicitly `true`. */ environment?: IEnv; /** * Effective base URL of the August public API. Reports follow the API this * instance reads from, so a deployment pointed at a staging backend alerts * staging rather than production. */ apiBaseUrl?: string; } /** * Apply constructor config. Called unconditionally by `AugustBase` so an * instance that omits `curatorAlerts` RESETS to the defaults rather than * inheriting a prior instance's settings — same contract as * `setPublicApiBaseUrl` and `setAttribution`. * * Also the supported opt-out for code that calls the `Stellar` namespace * functions directly without constructing an `AugustSDK` (the testnet flow in * the docs), and the only one that works in a browser, where the env var is * unreadable. * * @param config - `monitoring.curatorAlerts`, or `null` to restore defaults. * @param context - Facts about the reporting instance; omitted entirely by a * caller that only wants to disable reporting. */ export declare function configureCuratorAlerts(config: ICuratorAlertsConfig | null, context?: ICuratorAlertsContext): void; /** * Drop every suppression key. Test-only seam — reconfiguration no longer * clears the window on its own when the configuration is unchanged, so a suite * that reports the same failure across cases needs an explicit reset. * @internal */ export declare function resetCuratorAlertDedupe(): void; /** * Whether an alert would be sent right now. * * Quiet by default outside production, mirroring `analytics`: a partner's Jest * suite or `next dev` session exercising a failing redeem must not page a real * curator. Two gates are needed for that, because they cover different * runtimes — `NODE_ENV` is the Node one, and bundlers strip or stub * `process.env` in the browser, so a locally-served app is recognised by its * hostname instead (CLAUDE.md §5). Without that gate, a browser app run * against mainnet from any loopback or private origin — `localhost`, a * container on `172.20.0.0/16`, `[::1]` — pages a real curator on every * failed redeem. `isLocalhost` in `core/analytics/env` lists the ranges. * * `enabled: true` overrides both — it is the documented way to exercise the * path deliberately, and the SDK's own suite relies on it. * * The env var is read per call (not once at module load) so a consumer that * sets it after import is still honoured, and a test can set and unset it * without re-importing. It deliberately outranks an explicit `enabled: true`: * it is the kill switch, and an operator setting it should not have to find * and edit the construction site to be obeyed. */ export declare function areCuratorAlertsEnabled(): boolean; /** * Report a failed vault redemption for the curator of that vault. * * **Why this exists.** Stellar vaults are instant-redeem only — there is no * request/queue path — so a curator whose users' redemptions are failing has * no signal at all today: the failure surfaces to the user, and to August's * internal Sentry, and stops there. Emitting from the SDK rather than from a * single frontend means any integration can report one — subject * to the CORS caveat on {@link DEFAULT_CURATOR_ALERT_ENDPOINT}. * * **Trust model.** The endpoint is public by construction — it ships in this * bundle — so the relay treats every event as untrusted input, not as an * attested fact. The SDK's job is to report accurately; the relay's job is to * verify, rate-limit per `{vault, wallet}`, and drop events naming a vault * outside its routing map. `'submission'` events carry a `txHash` the relay can * confirm on chain, which makes them unforgeable; `'simulation'` events have no * on-chain artifact and are treated as the weaker claim. Nothing * credential-shaped is reachable from here: no bot token, no chat id, no * curator identity. * * **Side effects.** At most one `POST` to the relay, fire-and-forget: this runs * inside a `catch` on a money path, so it never awaits, never throws back into * the caller, and never alters the error the caller sees. Suppressed to one * send per `{contractId, eoa, phase, resultCode, error class}` per 10 minutes, * so a wallet retrying a deterministic failure costs a single request. Note the * receiving service applies its own, coarser window on top. A no-op when * reporting is disabled (see {@link areCuratorAlertsEnabled}) and, unless a * custom endpoint is configured, for any network other than mainnet — a * testnet failure is not a curator's problem. * * @param event - The failed attempt. `error` is sanitized (secrets scrubbed via * `sanitizeString`) and capped at 1500 characters before it leaves the * process; `sharesRaw` is relayed unscaled, and the receiving service scales * it for display with the decimals it holds for that vault — which for an * offset vault are the asset's, not the share token's, so the figure a curator * sees is a magnitude rather than an exact amount. * @internal */ export declare function reportRedeemFailure(event: IRedeemFailureEvent): void; export {};