declare const BRIDGE_VERSION = 2; interface BridgeMessage { type: string; [key: string]: unknown; } interface BridgeInitMessage extends BridgeMessage { type: 'cherry:init'; version: number; token: string; capabilities: string[]; } interface BridgeReadyMessage extends BridgeMessage { type: 'cherry:ready'; version: number; } interface BridgeRequest extends BridgeMessage { type: 'cherry:request'; id: string; method: string; params?: Record; } interface BridgeResponse extends BridgeMessage { type: 'cherry:response'; id: string; result?: unknown; error?: { code: string; message: string; }; } interface BridgeEvent extends BridgeMessage { type: 'cherry:event'; event: string; data?: unknown; } type CherryPlatform = 'webview' | 'iframe' | 'standalone'; interface CherryEnvironment { isEmbedded: boolean; platform: CherryPlatform; } interface LaunchTokenPayload { sub: string; app_id: string; room_id: string; origin: string; user: { display_name: string; avatar_url: string; }; room: { title: string; member_count: number; }; iat: number; exp: number; jti: string; /** Token scope — `'inline'` (blink card) or `'fullscreen'` (runner). */ scope?: 'inline' | 'fullscreen' | string; /** Render mode — mirrors `scope` for the host bridge. */ mode?: 'inline' | 'fullscreen' | string; /** Mini-app this token renders (absent on bot-hosted `url` blinks). */ mini_app_id?: string; /** * Unique id of the blink message this token is bound to. Use it as the * stable key to look up / bind per-message state at (or before) render. */ message_id?: string; /** Route within the miniapp the blink should open. */ route?: string; /** Snapshot payload baked into the token at send time (tamper-proof). */ params?: Record; /** Inline render height bucket. */ height?: 'compact' | 'medium' | 'tall' | string; /** * Explicit initial render height (CSS px) the host opens the card at, so it * doesn't jump before the first `host.resize`. Bounded by the `height` * bucket. Read it to render the blink at exactly the declared height. */ initial_height?: number; /** Whether the blink is interactive (false for read-only snapshots). */ interactive?: boolean; /** `'user_share'` for user-shared read-only snapshots (no bot behind it). */ source?: string; /** Wallet that sent the blink (message author — bot wallet or sharer). */ sender?: string; /** Bot-hosted blink URL (only on `type: 'url'` blinks). */ blink_url?: string; /** Viewer wallet, for fullscreen `launch-as-viewer` tokens. */ viewer_wallet?: string; } /** * Resolved context for an inline blink — the unique identity + payload of the * specific interactive message the mini-app is rendering. Available via * `CherryMiniApp.blink` / `useCherryBlink()` only when launched as an inline * blink (`mode=inline`); `null` otherwise. */ interface CherryBlinkContext { /** Unique id of this blink message — distinct per sent blink. */ messageId: string; /** Room the blink lives in. */ roomId: string; /** * Wallet currently viewing the blink. Note this is whoever has the chat open * — it equals `sender` when the author views their own shared message, and * the other participant when they view it. */ viewerWallet: string; /** Wallet that sent the blink (message author), if known. */ sender: string | null; /** Mini-app being rendered (absent on bot-hosted `url` blinks). */ miniAppId: string | null; /** Owning embed app id, if any. */ appId: string | null; /** Route opened within the mini-app. */ route: string; /** Snapshot payload baked into this blink (read-only). */ params: Record; /** Inline render height bucket. */ height: 'compact' | 'medium' | 'tall' | string; /** * Explicit initial render height (CSS px) the host opens the card at, or * `null` when the sender didn't pin one (the host then uses the bucket * height). Render the blink at this height to avoid a layout jump. */ initialHeight: number | null; /** False for read-only shared snapshots. */ interactive: boolean; /** `'user_share'` for user-shared snapshots, otherwise the bot source. */ source: string | null; /** * True when this is a non-interactive PREVIEW render shown in the share * picker, before the message exists. In preview mode `messageId`/`roomId` * are empty — render purely from `params` (don't rely on per-message state); * that's what keeps the preview consistent with the eventual shared blink. */ isPreview: boolean; /** Monotonic version of `params` (bumped by `bot:blink_update`). */ blinkParamsVersion: number | null; /** Launch-token unix timestamps. */ issuedAt: number | null; expiresAt: number | null; /** Launch-token unique id. */ jti: string | null; } interface CherryUser { publicKey: string; displayName: string; avatarUrl: string; } interface CherryRoom { id: string; title: string; memberCount: number; } interface CherryNavigate { /** Open user profile by wallet address, domain (e.g. "alice.sol"), or @handle */ userProfile(identifier: string): Promise; /** Open room by roomId or @handle (e.g. "@mygroup") */ openRoom(identifier: string): Promise; } /** * Options for `CherryMiniApp.share` — hand a "result" snapshot to the Cherry * host so the user can share it into a DM or group as an interactive blink. * * The miniapp does NOT name itself: the host derives the miniapp identity from * the current session's launch token, so a miniapp can only ever share itself. * The shared blink is rendered read-only on the receiver side. */ interface ShareBlinkOptions { /** Route within this miniapp the receiver opens (defaults to "/"). */ route?: string; /** Snapshot payload the receiver's miniapp renders (<= 4 KB JSON, depth <= 8). */ params?: Record; /** Inline render height bucket. */ height?: 'compact' | 'medium' | 'tall'; /** * Explicit initial render height (CSS px) the receiver's card opens at, so it * doesn't jump. Must be <= the `height` bucket max (compact 96 / medium 220 / * tall 420). Omit to start at the bucket height. */ initialHeight?: number; /** Optional caption shown alongside the blink card. */ caption?: string; /** * Declare that this miniapp can render a live, read-only PREVIEW of the * shared result from `route` + `params` alone. When true, the Cherry host * shows a real preview in the share picker (launched with `mode=preview`, * `cherry.blink.isPreview === true`); when false/omitted it shows a generic * skeleton. Only set this if your `route` renders correctly from `params` * without a real `messageId`/room. */ previewable?: boolean; } interface ShareBlinkResult { /** True when the user picked a recipient and the share was sent. */ shared: boolean; /** The room the blink was shared into (present only when `shared` is true). */ roomId?: string; /** * Unique id of the created blink message (present only when `shared` is true). * Record it to correlate later callbacks / `bot:blink_update` events back to * what this miniapp sent. */ messageId?: string; } interface CherryWallet { publicKey: string; /** Signs a transaction. Accepts Transaction, VersionedTransaction, Uint8Array, or base64 string. Returns signed bytes. */ signTransaction(transaction: unknown): Promise; /** Signs all transactions in a single batch request. Returns array of signed bytes. */ signAllTransactions(transactions: unknown[]): Promise; /** Signs and sends a transaction. Returns signature string. */ signAndSendTransaction(transaction: unknown): Promise; /** Signs an arbitrary message. Returns signature bytes. */ signMessage(message: Uint8Array): Promise; } type CherryMiniAppEvent = 'suspended' | 'resumed' | 'walletDisconnected' /** Inline blink params were updated by the bot (`answerCallback.updateBlink`). */ | 'blink:update'; type EventListener = (data: T) => void; interface CherryMiniAppOptions { /** Milliseconds to wait for cherry:init from the host. Default: 10_000 */ initTimeout?: number; /** * When `true`, only Cherry-injected signals are used for environment * detection (`window.__cherry` / `cherry_embed=1`). Fallbacks such as * `ReactNativeWebView` or `window.parent !== window` are disabled. * * Use once all Cherry hosts you target have been updated to inject the * new signals, to prevent false positives in wallet in-app browsers. * Default: `false`. */ strict?: boolean; } declare class CherryMiniApp { private readonly bridge; private readonly eventListeners; private removeHostListener; private _isReady; private _user; private _room; private _launchToken; private _publicKey; private _blink; private readonly initTimeout; constructor(options?: CherryMiniAppOptions); get isReady(): boolean; get user(): CherryUser; get room(): CherryRoom; get launchToken(): string; /** * Inline blink context (messageId, sender, viewer, params, …) — populated * only when launched as an inline blink. `null` for fullscreen/embed. */ get blink(): CherryBlinkContext | null; init(): Promise; /** * Inline-mode bootstrap. Reads the launch token from the URL and pulls the * viewer/room context from the host via a `host.init` bridge request (the * inline host has no user-bearing token to push, so identity comes from the * host, not the token). The blink's `params`/`messageId`/`route` are also * available on the host.init response and via the launch token claims. */ private initInline; private waitForInit; /** * Returns a stable wallet facade. Methods are arrow functions bound to the * outer CherryMiniApp instance so `this` always resolves correctly. * `publicKey` is a getter that reads the live `_publicKey` field. */ get wallet(): { readonly publicKey: string | null; signTransaction(transaction: unknown): Promise; signAllTransactions(transactions: unknown[]): Promise; signAndSendTransaction(transaction: unknown): Promise; signMessage(message: Uint8Array): Promise; }; getPublicKey(): string | null; readonly navigate: CherryNavigate; /** * Hand a "result" snapshot to the Cherry host so the user can share it into * a DM or group as an interactive blink. The host opens a recipient picker * with a preview; the returned promise resolves once the user picks a * recipient (or cancels). The miniapp identity is taken from the current * session — a miniapp can only share itself, read-only. */ share(options?: ShareBlinkOptions): Promise; on(event: CherryMiniAppEvent, listener: EventListener): void; off(event: CherryMiniAppEvent, listener: EventListener): void; private emit; destroy(): void; private assertReady; } export { type BridgeMessage as B, CherryMiniApp as C, type LaunchTokenPayload as L, type ShareBlinkOptions as S, BRIDGE_VERSION as a, type BridgeEvent as b, type BridgeInitMessage as c, type BridgeReadyMessage as d, type BridgeRequest as e, type BridgeResponse as f, type CherryBlinkContext as g, type CherryEnvironment as h, type CherryMiniAppEvent as i, type CherryMiniAppOptions as j, type CherryNavigate as k, type CherryPlatform as l, type CherryRoom as m, type CherryUser as n, type CherryWallet as o, type ShareBlinkResult as p };