@tma.js/init-data-node 1.1.1 → 1.1.3
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/dist/index.cjs.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../sdk/dist/index.mjs","../src/validate.ts"],"sourcesContent":["var Rt = Object.defineProperty;\nvar It = (r, t, e) => t in r ? Rt(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;\nvar o = (r, t, e) => (It(r, typeof t != \"symbol\" ? t + \"\" : t, e), e);\nfunction H(r) {\n return typeof r == \"object\" && r !== null && !Array.isArray(r);\n}\nfunction ut() {\n return performance.getEntriesByType(\"navigation\")[0] || null;\n}\nfunction Lt() {\n const r = ut();\n return r ? r.type === \"reload\" : null;\n}\nfunction I() {\n return new TypeError(\"Value has unexpected type\");\n}\nclass F extends Error {\n constructor(e, { cause: s, type: n } = {}) {\n super(`Unable to parse value${n ? ` as ${n}` : \"\"}`, { cause: s });\n /**\n * Parser name.\n */\n o(this, \"type\");\n this.value = e, Object.setPrototypeOf(this, F.prototype), this.type = n;\n }\n}\nclass z {\n constructor(t, e, s) {\n this.parser = t, this.isOptional = e, this.type = s;\n }\n parse(t) {\n if (!(this.isOptional && t === void 0))\n try {\n return this.parser(t);\n } catch (e) {\n throw new F(t, { type: this.type, cause: e });\n }\n }\n optional() {\n return this.isOptional = !0, this;\n }\n}\nfunction $t(r) {\n if (Array.isArray(r))\n return r;\n if (typeof r == \"string\")\n try {\n const t = JSON.parse(r);\n if (Array.isArray(t))\n return t;\n } catch {\n }\n throw I();\n}\nclass Tt extends z {\n constructor(e, s, n) {\n super($t, s, n);\n o(this, \"itemParser\");\n this.itemParser = typeof e == \"function\" ? e : e.parse.bind(e);\n }\n parse(e) {\n const s = super.parse(e);\n return s === void 0 ? s : s.map(this.itemParser);\n }\n of(e) {\n return this.itemParser = typeof e == \"function\" ? e : e.parse.bind(e), this;\n }\n}\nfunction L(r, t) {\n return () => new z(r, !1, t);\n}\nclass G extends Error {\n constructor(t, { cause: e, type: s } = {}) {\n super(`Unable to parse field \"${t}\"${s ? ` as ${s}` : \"\"}`, { cause: e }), Object.setPrototypeOf(this, G.prototype);\n }\n}\nfunction ht(r, t) {\n const e = {};\n for (const s in r) {\n const n = r[s];\n if (!n)\n continue;\n let i, a;\n if (typeof n == \"function\" || \"parse\" in n)\n i = s, a = typeof n == \"function\" ? n : n.parse.bind(n);\n else {\n const { type: h } = n;\n i = n.from || s, a = typeof h == \"function\" ? h : h.parse.bind(h);\n }\n let c;\n const p = t(i);\n try {\n c = a(p);\n } catch (h) {\n throw h instanceof F ? new G(i, {\n type: h.type,\n cause: h\n }) : new G(i, { cause: h });\n }\n c !== void 0 && (e[s] = c);\n }\n return e;\n}\nfunction Bt(r) {\n return new Tt((t) => t, !1, r);\n}\nconst k = L((r) => {\n if (typeof r == \"boolean\")\n return r;\n const t = String(r);\n if (t === \"1\" || t === \"true\")\n return !0;\n if (t === \"0\" || t === \"false\")\n return !1;\n throw I();\n}, \"boolean\"), q = L((r) => {\n if (typeof r == \"number\")\n return r;\n if (typeof r == \"string\") {\n const t = Number(r);\n if (!Number.isNaN(t))\n return t;\n }\n throw I();\n}, \"number\"), pt = L((r) => r instanceof Date ? r : new Date(q().parse(r) * 1e3), \"Date\");\nfunction Y(r) {\n let t = r;\n if (typeof t == \"string\" && (t = JSON.parse(t)), typeof t != \"object\" || t === null || Array.isArray(t))\n throw I();\n return t;\n}\nfunction f(r, t) {\n return new z((e) => {\n const s = Y(e);\n return ht(r, (n) => s[n]);\n }, !1, t);\n}\nfunction lt(r) {\n return /^#[\\da-f]{6}$/i.test(r);\n}\nfunction Dt(r) {\n return /^#[\\da-f]{3}$/i.test(r);\n}\nfunction dt(r) {\n const t = r.replace(/\\s/g, \"\").toLowerCase();\n if (lt(t))\n return t;\n if (Dt(t)) {\n let s = \"#\";\n for (let n = 0; n < 3; n += 1)\n s += t[1 + n].repeat(2);\n return s;\n }\n const e = t.match(/^rgb\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)$/) || t.match(/^rgba\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3}),\\d{1,3}\\)$/);\n if (e === null)\n throw new Error(`Value \"${r}\" does not satisfy any of known RGB formats.`);\n return e.slice(1).reduce((s, n) => {\n const i = parseInt(n, 10).toString(16);\n return s + (i.length === 1 ? \"0\" : \"\") + i;\n }, \"#\");\n}\nfunction ft(r) {\n const t = dt(r);\n return Math.sqrt(\n [0.299, 0.587, 0.114].reduce((s, n, i) => {\n const a = parseInt(t.slice(1 + i * 2, 1 + (i + 1) * 2), 16);\n return s + a * a * n;\n }, 0)\n ) < 120;\n}\nconst u = L((r) => {\n if (typeof r == \"string\" || typeof r == \"number\")\n return r.toString();\n throw I();\n}, \"string\"), gt = L((r) => dt(u().parse(r)), \"rgb\");\nfunction X(r, t) {\n return new z((e) => {\n if (typeof e != \"string\" && !(e instanceof URLSearchParams))\n throw I();\n const s = typeof e == \"string\" ? new URLSearchParams(e) : e;\n return ht(r, (n) => {\n const i = s.get(n);\n return i === null ? void 0 : i;\n });\n }, !1, t);\n}\nfunction Wt() {\n return f({\n id: q(),\n type: u(),\n title: u(),\n photoUrl: {\n type: u().optional(),\n from: \"photo_url\"\n },\n username: u().optional()\n }, \"Chat\");\n}\nclass Ot {\n constructor(t) {\n this.initData = t;\n }\n /**\n * @see InitDataParsed.authDate\n */\n get authDate() {\n return this.initData.authDate;\n }\n /**\n * @see InitDataParsed.canSendAfter\n */\n get canSendAfter() {\n return this.initData.canSendAfter;\n }\n /**\n * Date after which it is allowed to call\n * the [answerWebAppQuery](https://core.telegram.org/bots/api#answerwebappquery) method.\n */\n get canSendAfterDate() {\n const { canSendAfter: t } = this;\n return t === void 0 ? void 0 : new Date(this.authDate.getTime() + t * 1e3);\n }\n /**\n * @see InitDataParsed.chat\n */\n get chat() {\n return this.initData.chat;\n }\n /**\n * @see InitDataParsed.chatType\n */\n get chatType() {\n return this.initData.chatType;\n }\n /**\n * @see InitDataParsed.chatInstance\n */\n get chatInstance() {\n return this.initData.chatInstance;\n }\n /**\n * @see InitDataParsed.hash\n */\n get hash() {\n return this.initData.hash;\n }\n /**\n * @see InitDataParsed.queryId\n */\n get queryId() {\n return this.initData.queryId;\n }\n /**\n * @see InitDataParsed.receiver\n */\n get receiver() {\n return this.initData.receiver;\n }\n /**\n * @see InitDataParsed.startParam\n */\n get startParam() {\n return this.initData.startParam;\n }\n /**\n * @see InitDataParsed.user\n */\n get user() {\n return this.initData.user;\n }\n}\nfunction rt() {\n return f({\n addedToAttachmentMenu: {\n type: k().optional(),\n from: \"added_to_attachment_menu\"\n },\n allowsWriteToPm: {\n type: k().optional(),\n from: \"allows_write_to_pm\"\n },\n firstName: {\n type: u(),\n from: \"first_name\"\n },\n id: q(),\n isBot: {\n type: k().optional(),\n from: \"is_bot\"\n },\n isPremium: {\n type: k().optional(),\n from: \"is_premium\"\n },\n languageCode: {\n type: u().optional(),\n from: \"language_code\"\n },\n lastName: {\n type: u().optional(),\n from: \"last_name\"\n },\n photoUrl: {\n type: u().optional(),\n from: \"photo_url\"\n },\n username: u().optional()\n }, \"User\");\n}\nfunction wt() {\n return X({\n authDate: {\n type: pt(),\n from: \"auth_date\"\n },\n canSendAfter: {\n type: q().optional(),\n from: \"can_send_after\"\n },\n chat: Wt().optional(),\n chatInstance: {\n type: u().optional(),\n from: \"chat_instance\"\n },\n chatType: {\n type: u().optional(),\n from: \"chat_type\"\n },\n hash: u(),\n queryId: {\n type: u().optional(),\n from: \"query_id\"\n },\n receiver: rt().optional(),\n startParam: {\n type: u().optional(),\n from: \"start_param\"\n },\n user: rt().optional()\n }, \"InitData\");\n}\nfunction tr(r) {\n return wt().parse(r);\n}\nfunction Nt(r) {\n return r.replace(/(^|_)bg/, (t, e) => `${e}background`).replace(/_([a-z])/g, (t, e) => e.toUpperCase());\n}\nfunction Ht(r) {\n return r.replace(/[A-Z]/g, (t) => `_${t.toLowerCase()}`).replace(/(^|_)background/, (t, e) => `${e}bg`);\n}\nconst _t = L(\n (r) => {\n const t = gt().optional();\n return Object.entries(Y(r)).reduce((e, [s, n]) => (e[Nt(s)] = t.parse(n), e), {});\n },\n \"ThemeParams\"\n);\nfunction bt(r) {\n return _t().parse(r);\n}\nfunction er(r = {}) {\n return m(\"web_app_request_theme\", \"theme_changed\", r).then(bt);\n}\nfunction Ut(r) {\n return JSON.stringify(\n Object.entries(r).reduce((t, [e, s]) => (s && (t[Ht(e)] = s), t), {})\n );\n}\nclass w {\n constructor() {\n o(this, \"listeners\", /* @__PURE__ */ new Map());\n o(this, \"subscribeListeners\", []);\n }\n /**\n * Adds specified event listener.\n * @param event - event name.\n * @param listener - event listener.\n * @param once - should listener called only once.\n */\n addListener(t, e, s) {\n let n = this.listeners.get(t);\n return n || (n = [], this.listeners.set(t, n)), n.push([e, s]), () => this.off(t, e);\n }\n emit(t, ...e) {\n this.subscribeListeners.forEach((n) => n(t, ...e));\n const s = this.listeners.get(t);\n s && s.forEach(([n, i], a) => {\n n(...e), i && s.splice(a, 1);\n });\n }\n /**\n * Adds event listener.\n * @param event - event name.\n * @param listener - event listener.\n * @returns Function to remove event listener.\n */\n on(t, e) {\n return this.addListener(t, e, !1);\n }\n /**\n * Adds event listener following the logic, described in `on` method, but calls specified\n * listener only once, removing it after.\n * @param event - event name.\n * @param listener - event listener.\n * @returns Function to remove event listener.\n * @see on\n */\n once(t, e) {\n return this.addListener(t, e, !0);\n }\n /**\n * Removes event listener. In case, specified listener was bound several times, it removes\n * only a single one.\n * @param event - event name.\n * @param listener - event listener.\n */\n off(t, e) {\n const s = this.listeners.get(t);\n if (s) {\n for (let n = 0; n < s.length; n += 1)\n if (e === s[n][0]) {\n s.splice(n, 1);\n return;\n }\n }\n }\n /**\n * Adds event listener to all events.\n * @param listener - events listener.\n * @returns Function to remove event listener.\n * @see on\n * @see once\n */\n subscribe(t) {\n return this.subscribeListeners.push(t), () => this.unsubscribe(t);\n }\n /**\n * Removes global event listener. In case, specified listener was bound several times, it removes\n * only a single one.\n * @param listener - events listener.\n * @returns Function to remove event listener.\n */\n unsubscribe(t) {\n for (let e = 0; e < this.subscribeListeners.length; e += 1)\n if (this.subscribeListeners[e] === t) {\n this.subscribeListeners.splice(e, 1);\n return;\n }\n }\n}\nclass b {\n constructor(t, e) {\n this.state = t, this.ee = e;\n }\n internalSet(t, e) {\n return this.state[t] === e || e === void 0 ? !1 : (this.state[t] = e, this.ee.emit(`change:${t}`, e), !0);\n }\n /**\n * Returns copy of current state.\n */\n clone() {\n return { ...this.state };\n }\n set(t, e) {\n let s = !1;\n if (typeof t == \"string\")\n s = this.internalSet(t, e);\n else\n for (const n in t)\n this.internalSet(n, t[n]) && (s = !0);\n s && this.ee.emit(\"change\");\n }\n /**\n * Returns value by specified key.\n * @param key - state key.\n */\n get(t) {\n return this.state[t];\n }\n}\nclass Mt {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n this.state = new b(t, this.ee);\n }\n /**\n * @since v6.10\n */\n get accentTextColor() {\n return this.get(\"accentTextColor\");\n }\n get backgroundColor() {\n return this.get(\"backgroundColor\");\n }\n get buttonColor() {\n return this.get(\"buttonColor\");\n }\n get buttonTextColor() {\n return this.get(\"buttonTextColor\");\n }\n get destructiveTextColor() {\n return this.get(\"destructiveTextColor\");\n }\n /**\n * Retrieves palette color value by its name.\n * @param key - palette key name.\n */\n get(t) {\n return this.state.get(t);\n }\n /**\n * Returns the copy of the internal state of the current component instance.\n */\n getState() {\n return this.state.clone();\n }\n /**\n * @since v6.10\n */\n get headerBackgroundColor() {\n return this.get(\"headerBackgroundColor\");\n }\n get hintColor() {\n return this.get(\"hintColor\");\n }\n /**\n * Returns true in case, current color scheme is recognized as dark. This\n * value is calculated according to theme background color.\n */\n get isDark() {\n return !this.backgroundColor || ft(this.backgroundColor);\n }\n get linkColor() {\n return this.get(\"linkColor\");\n }\n get secondaryBackgroundColor() {\n return this.get(\"secondaryBackgroundColor\");\n }\n /**\n * @since v6.10\n */\n get sectionBackgroundColor() {\n return this.get(\"sectionBackgroundColor\");\n }\n /**\n * @since v6.10\n */\n get sectionHeaderTextColor() {\n return this.get(\"sectionHeaderTextColor\");\n }\n /**\n * Starts listening to theme changes and applies them.\n * @returns Function to stop listening.\n */\n listen() {\n return y(\"theme_changed\", (t) => {\n this.state.set(bt(t.theme_params));\n });\n }\n /**\n * @since v6.10\n */\n get subtitleTextColor() {\n return this.get(\"subtitleTextColor\");\n }\n get textColor() {\n return this.get(\"textColor\");\n }\n}\nfunction mt() {\n return X({\n botInline: {\n type: k().optional(),\n from: \"tgWebAppBotInline\"\n },\n initData: {\n type: wt().optional(),\n from: \"tgWebAppData\"\n },\n initDataRaw: {\n type: u().optional(),\n from: \"tgWebAppData\"\n },\n platform: {\n type: u(),\n from: \"tgWebAppPlatform\"\n },\n showSettings: {\n type: k().optional(),\n from: \"tgWebAppShowSettings\"\n },\n startParam: {\n type: u().optional(),\n from: \"tgWebAppStartParam\"\n },\n themeParams: {\n type: _t(),\n from: \"tgWebAppThemeParams\"\n },\n version: {\n type: u(),\n from: \"tgWebAppVersion\"\n }\n }, \"LaunchParams\");\n}\nfunction jt(r) {\n return mt().parse(r);\n}\nfunction yt(r) {\n const t = r.includes(\"?\") ? r.replace(\"#\", \"&\").slice(r.indexOf(\"?\") + 1) : r.slice(r.indexOf(\"#\") + 1);\n return jt(t);\n}\nfunction Gt() {\n return yt(window.location.href);\n}\nfunction Ft() {\n const r = ut();\n if (!r)\n throw new Error(\"Unable to get first navigation entry.\");\n return yt(r.name);\n}\nfunction zt() {\n try {\n return Ft();\n } catch {\n }\n try {\n return Gt();\n } catch {\n }\n return null;\n}\nfunction Jt(r) {\n const {\n initDataRaw: t,\n themeParams: e,\n platform: s,\n version: n,\n showSettings: i,\n botInline: a\n } = r, c = new URLSearchParams();\n return t && c.set(\"tgWebAppData\", t), c.set(\"tgWebAppPlatform\", s), c.set(\"tgWebAppThemeParams\", Ut(e)), c.set(\"tgWebAppVersion\", n), typeof i == \"boolean\" && c.set(\"tgWebAppShowSettings\", i ? \"1\" : \"0\"), typeof a == \"boolean\" && c.set(\"tgWebAppBotInline\", a ? \"1\" : \"0\"), c.toString();\n}\nconst Et = \"telegram-mini-apps-launch-params\";\nfunction Qt() {\n const r = sessionStorage.getItem(Et);\n return r ? mt().parse(r) : null;\n}\nfunction Zt(r) {\n sessionStorage.setItem(Et, Jt(r));\n}\nfunction Kt() {\n try {\n return window.self !== window.top;\n } catch {\n return !0;\n }\n}\nfunction Yt() {\n const r = Qt(), t = zt(), e = Lt();\n if (r) {\n if (t)\n return {\n launchParams: t,\n isPageReload: Kt() ? e || r.initDataRaw === t.initDataRaw : !0\n };\n if (e)\n return {\n launchParams: r,\n isPageReload: e\n };\n throw new Error(\"Unable to retrieve current launch parameters, which must exist.\");\n }\n if (t)\n return {\n launchParams: t,\n isPageReload: !1\n };\n throw new Error(\"Unable to retrieve any launch parameters.\");\n}\nconst st = \"tmajsLaunchData\";\nfunction Ct() {\n const r = window[st];\n if (r)\n return r;\n const t = Yt();\n return window[st] = t, Zt(t.launchParams), t;\n}\nfunction rr() {\n try {\n return Ct(), !0;\n } catch {\n return !1;\n }\n}\nfunction Xt(r) {\n return \"external\" in r && H(r.external) && \"notify\" in r.external && typeof r.external.notify == \"function\";\n}\nfunction te(r) {\n return \"TelegramWebviewProxy\" in r && H(r.TelegramWebviewProxy) && \"postEvent\" in r.TelegramWebviewProxy && typeof r.TelegramWebviewProxy.postEvent == \"function\";\n}\nfunction vt() {\n try {\n return window.self !== window.top;\n } catch {\n return !0;\n }\n}\nclass tt extends Error {\n constructor(t, e) {\n super(`Method \"${t}\" is unsupported in the Mini Apps version ${e}.`), Object.setPrototypeOf(this, tt.prototype);\n }\n}\nclass et extends Error {\n constructor(t, e, s) {\n super(`Parameter \"${e}\" in method \"${t}\" is unsupported in the Mini Apps version ${s}.`), Object.setPrototypeOf(this, et.prototype);\n }\n}\nclass Pt {\n constructor(t, e) {\n this.prefix = t, this.enabled = e;\n }\n /**\n * Prints message into a console in case, logger is currently enabled.\n * @param level - log level.\n * @param args - arguments.\n */\n print(t, ...e) {\n if (!this.enabled)\n return;\n const s = /* @__PURE__ */ new Date(), n = Intl.DateTimeFormat(\"en-GB\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n fractionalSecondDigits: 3,\n timeZone: \"UTC\"\n }).format(s);\n console[t](`[${n}]`, this.prefix, ...e);\n }\n /**\n * Disables the logger.\n */\n disable() {\n this.enabled = !1;\n }\n /**\n * Prints error message into a console.\n * @param args\n */\n error(...t) {\n this.print(\"error\", ...t);\n }\n /**\n * Enables the logger.\n */\n enable() {\n this.enabled = !0;\n }\n /**\n * Prints log message into a console.\n * @param args\n */\n log(...t) {\n this.print(\"log\", ...t);\n }\n /**\n * Prints warning message into a console.\n * @param args\n */\n warn(...t) {\n this.print(\"warn\", ...t);\n }\n}\nlet kt = \"https://web.telegram.org\";\nconst V = new Pt(\"[SDK]\", !1);\nfunction sr(r) {\n if (r) {\n V.enable();\n return;\n }\n V.disable();\n}\nfunction nr(r) {\n kt = r;\n}\nfunction ee() {\n return kt;\n}\nconst re = f({\n eventType: u(),\n eventData: (r) => r\n});\nfunction se(r, t) {\n window.dispatchEvent(new MessageEvent(\"message\", {\n data: JSON.stringify({ eventType: r, eventData: t })\n }));\n}\nfunction ne() {\n const r = window;\n \"TelegramGameProxy_receiveEvent\" in r || [\n [\"TelegramGameProxy_receiveEvent\"],\n // Windows Phone.\n [\"TelegramGameProxy\", \"receiveEvent\"],\n // Desktop.\n [\"Telegram\", \"WebView\", \"receiveEvent\"]\n // Android and iOS.\n ].forEach((t) => {\n let e = r;\n t.forEach((s, n, i) => {\n if (n === i.length - 1) {\n e[s] = se;\n return;\n }\n s in e || (e[s] = {}), e = e[s];\n });\n });\n}\nfunction ie(r) {\n ne(), window.addEventListener(\"message\", (t) => {\n try {\n const { eventType: e, eventData: s } = re.parse(t.data);\n r(e, s);\n } catch {\n }\n });\n}\nfunction oe() {\n return f({\n req_id: u(),\n data: (r) => r === null ? r : u().optional().parse(r)\n });\n}\nfunction ae() {\n return f({\n req_id: u(),\n result: (r) => r,\n error: u().optional()\n });\n}\nfunction ce() {\n return f({\n slug: u(),\n status: u()\n });\n}\nfunction ue() {\n return f({ status: u() });\n}\nfunction he() {\n return f({\n button_id: (r) => r == null ? void 0 : u().parse(r)\n });\n}\nfunction pe() {\n return f({\n data: u().optional()\n });\n}\nfunction le() {\n return f({\n theme_params: (r) => {\n const t = gt().optional();\n return Object.entries(Y(r)).reduce((e, [s, n]) => (e[s] = t.parse(n), e), {});\n }\n });\n}\nfunction de() {\n return f({\n height: q(),\n width: (r) => r == null ? window.innerWidth : q().parse(r),\n is_state_stable: k(),\n is_expanded: k()\n });\n}\nfunction fe() {\n return f({ status: u() });\n}\nfunction ge() {\n const r = new w(), t = (e, ...s) => {\n V.log(\"Emitting processed event:\", e, ...s), r.emit(e, ...s);\n };\n return window.addEventListener(\"resize\", () => {\n t(\"viewport_changed\", {\n width: window.innerWidth,\n height: window.innerHeight,\n is_state_stable: !0,\n is_expanded: !0\n });\n }), ie((e, s) => {\n V.log(\"Received raw event:\", e, s);\n try {\n switch (e) {\n case \"viewport_changed\":\n return t(e, de().parse(s));\n case \"theme_changed\":\n return t(e, le().parse(s));\n case \"popup_closed\":\n return (\n // Sent on desktop.\n s == null ? t(e, {}) : t(e, he().parse(s))\n );\n case \"set_custom_style\":\n return t(e, u().parse(s));\n case \"qr_text_received\":\n return t(e, pe().parse(s));\n case \"clipboard_text_received\":\n return t(e, oe().parse(s));\n case \"invoice_closed\":\n return t(e, ce().parse(s));\n case \"phone_requested\":\n return t(\"phone_requested\", ue().parse(s));\n case \"custom_method_invoked\":\n return t(\"custom_method_invoked\", ae().parse(s));\n case \"write_access_requested\":\n return t(\"write_access_requested\", fe().parse(s));\n case \"main_button_pressed\":\n case \"back_button_pressed\":\n case \"settings_button_pressed\":\n case \"scan_qr_popup_closed\":\n case \"reload_iframe\":\n return t(e);\n default:\n return t(e, s);\n }\n } catch (n) {\n V.error(\"Error processing event:\", n);\n }\n }), r;\n}\nconst Q = \"telegram-mini-apps-cached-emitter\";\nfunction U() {\n const r = window;\n return r[Q] === void 0 && (r[Q] = ge()), r[Q];\n}\nfunction $(r, t) {\n U().off(r, t);\n}\nfunction y(r, t) {\n return U().on(r, t), () => $(r, t);\n}\nfunction ir(r, t) {\n return U().once(r, t), () => $(r, t);\n}\nfunction we(r) {\n U().unsubscribe(r);\n}\nfunction or(r) {\n return U().subscribe(r), () => we(r);\n}\nfunction _e(r, t) {\n const e = r.split(\".\"), s = t.split(\".\"), n = Math.max(e.length, s.length);\n for (let i = 0; i < n; i += 1) {\n const a = parseInt(e[i] || \"0\", 10), c = parseInt(s[i] || \"0\", 10);\n if (a !== c)\n return a > c ? 1 : -1;\n }\n return 0;\n}\nfunction P(r, t) {\n return _e(r, t) <= 0;\n}\nfunction R(r, t, e) {\n if (typeof e == \"string\") {\n if (r === \"web_app_open_link\" && t === \"try_instant_view\")\n return P(\"6.4\", e);\n if (r === \"web_app_set_header_color\" && t === \"color\")\n return P(\"6.9\", e);\n }\n switch (r) {\n case \"web_app_open_tg_link\":\n case \"web_app_open_invoice\":\n case \"web_app_setup_back_button\":\n case \"web_app_set_background_color\":\n case \"web_app_set_header_color\":\n case \"web_app_trigger_haptic_feedback\":\n return P(\"6.1\", t);\n case \"web_app_open_popup\":\n return P(\"6.2\", t);\n case \"web_app_close_scan_qr_popup\":\n case \"web_app_open_scan_qr_popup\":\n case \"web_app_read_text_from_clipboard\":\n return P(\"6.4\", t);\n case \"web_app_switch_inline_query\":\n return P(\"6.7\", t);\n case \"web_app_invoke_custom_method\":\n case \"web_app_request_write_access\":\n case \"web_app_request_phone\":\n return P(\"6.9\", t);\n case \"web_app_setup_settings_button\":\n return P(\"6.10\", t);\n default:\n return !0;\n }\n}\nfunction E(r, t) {\n return (e) => R(t[e], r);\n}\nfunction St(r, t) {\n return (e) => {\n const [s, n] = t[e];\n return R(s, n, r);\n };\n}\nfunction d(r, t, e) {\n let s = {}, n;\n t === void 0 && e === void 0 ? s = {} : t !== void 0 && e !== void 0 ? (s = e, n = t) : t !== void 0 && (\"targetOrigin\" in t ? s = t : n = t);\n const { targetOrigin: i = ee() } = s;\n if (V.log(`Calling method \"${r}\"`, n), vt()) {\n window.parent.postMessage(JSON.stringify({\n eventType: r,\n eventData: n\n }), i);\n return;\n }\n if (Xt(window)) {\n window.external.notify(JSON.stringify({ eventType: r, eventData: n }));\n return;\n }\n if (te(window)) {\n window.TelegramWebviewProxy.postEvent(r, JSON.stringify(n));\n return;\n }\n throw new Error(\n \"Unable to determine current environment and possible way to send event.\"\n );\n}\nfunction be(r) {\n return (t, e) => {\n if (!R(t, r))\n throw new tt(t, r);\n if (H(e)) {\n let s;\n if (t === \"web_app_open_link\" && \"try_instant_view\" in e ? s = \"try_instant_view\" : t === \"web_app_set_header_color\" && \"color\" in e && (s = \"color\"), s && !R(t, s, r))\n throw new et(t, s, r);\n }\n return d(t, e);\n };\n}\nclass J extends Error {\n constructor(t) {\n super(`Async call timeout exceeded. Timeout: ${t}`), Object.setPrototypeOf(this, J.prototype);\n }\n}\nfunction ar(r) {\n return r instanceof J;\n}\nfunction me(r) {\n return new Promise((t) => {\n setTimeout(t, r);\n });\n}\nfunction ye(r) {\n return new Promise((t, e) => {\n setTimeout(e, r, new J(r));\n });\n}\nfunction xt(r, t) {\n return Promise.race([\n r(),\n ye(t)\n ]);\n}\nfunction m(r, t, e, s) {\n let n, i, a, c;\n typeof t == \"string\" || Array.isArray(t) ? (a = Array.isArray(t) ? t : [t], n = e) : (i = t, a = Array.isArray(e) ? e : [e], n = s), H(i) && typeof i.req_id == \"string\" && (c = i.req_id);\n const { postEvent: p = d, timeout: h } = n || {}, g = n && \"capture\" in n ? n.capture : null, _ = () => new Promise((A, l) => {\n const C = a.map((v) => y(v, (M) => {\n c && (!H(M) || M.req_id !== c) || typeof g == \"function\" && !g(M) || (x(), A(M));\n })), x = () => C.forEach((v) => v());\n try {\n p(r, i);\n } catch (v) {\n x(), l(v);\n }\n });\n return typeof h == \"number\" ? xt(_, h) : _();\n}\nasync function O(r, t, e, s = {}) {\n const { result: n, error: i } = await m(\n \"web_app_invoke_custom_method\",\n {\n method: r,\n params: t,\n req_id: e\n },\n \"custom_method_invoked\",\n s\n );\n if (i)\n throw new Error(i);\n return n;\n}\nclass Ee {\n constructor(t, e, s = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"on\", (t, e) => t === \"click\" ? y(\"back_button_pressed\", e) : this.ee.on(t, e));\n /**\n * Removes event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"off\", (t, e) => t === \"click\" ? $(\"back_button_pressed\", e) : this.ee.off(t, e));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = s, this.state = new b({ isVisible: t }, this.ee), this.supports = E(e, {\n show: \"web_app_setup_back_button\",\n hide: \"web_app_setup_back_button\"\n });\n }\n set isVisible(t) {\n this.state.set(\"isVisible\", t), this.postEvent(\"web_app_setup_back_button\", { is_visible: t });\n }\n /**\n * True if BackButton is currently visible.\n */\n get isVisible() {\n return this.state.get(\"isVisible\");\n }\n /**\n * Hides the BackButton.\n */\n hide() {\n this.isVisible = !1;\n }\n /**\n * Shows the BackButton.\n */\n show() {\n this.isVisible = !0;\n }\n}\nfunction nt(r, t) {\n return r + (r.length > 0 && t.length > 0 ? ` ${t}` : t);\n}\nfunction Ce(...r) {\n return r.reduce((t, e) => {\n let s = \"\";\n return typeof e == \"string\" ? s = e : typeof e == \"object\" && e !== null && (s = Object.entries(e).reduce((n, [i, a]) => a ? nt(n, i) : n, \"\")), nt(t, s);\n }, \"\");\n}\nfunction ve(r) {\n return typeof r == \"object\" && r !== null && !Array.isArray(null);\n}\nfunction cr(...r) {\n return r.reduce((t, e) => (ve(e) && Object.entries(e).forEach(([s, n]) => {\n const i = Ce(t[s], n);\n i.length > 0 && (t[s] = i);\n }), t), {});\n}\nclass Pe {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n this.postEvent = e, this.state = new b({ isConfirmationNeeded: t }, this.ee);\n }\n set isConfirmationNeeded(t) {\n this.state.set(\"isConfirmationNeeded\", t), this.postEvent(\"web_app_setup_closing_behavior\", { need_confirmation: t });\n }\n /**\n * Returns true, if the confirmation dialog enabled while the user is trying\n * to close the Mini App.\n */\n get isConfirmationNeeded() {\n return this.state.get(\"isConfirmationNeeded\");\n }\n /**\n * Disables the confirmation dialog while the user is trying to close the\n * Mini App.\n */\n disableConfirmation() {\n this.isConfirmationNeeded = !1;\n }\n /**\n * Enables the confirmation dialog while the user is trying to close the\n * Mini App.\n */\n enableConfirmation() {\n this.isConfirmationNeeded = !0;\n }\n}\nfunction it(r, t) {\n return r.reduce((e, s) => (e[s] = t, e), {});\n}\nclass ke {\n constructor(t, e, s = d) {\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.createRequestId = e, this.postEvent = s, this.supports = E(t, {\n delete: \"web_app_invoke_custom_method\",\n get: \"web_app_invoke_custom_method\",\n getKeys: \"web_app_invoke_custom_method\",\n set: \"web_app_invoke_custom_method\"\n });\n }\n /**\n * Deletes specified key or keys from the cloud storage.\n * @param keyOrKeys - key or keys to delete.\n * @param options - request execution options.\n */\n async delete(t, e = {}) {\n const s = Array.isArray(t) ? t : [t];\n s.length !== 0 && await O(\n \"deleteStorageValues\",\n { keys: s },\n this.createRequestId(),\n { ...e, postEvent: this.postEvent }\n );\n }\n /**\n * Returns list of all keys presented in the cloud storage.\n * @param options - request execution options.\n */\n async getKeys(t = {}) {\n const e = await O(\n \"getStorageKeys\",\n {},\n this.createRequestId(),\n { ...t, postEvent: this.postEvent }\n );\n return Bt().of(u()).parse(e);\n }\n async get(t, e = {}) {\n const s = Array.isArray(t) ? t : [t];\n if (s.length === 0)\n return it(s, \"\");\n const n = f(\n it(s, u())\n ), i = await O(\n \"getStorageValues\",\n { keys: s },\n this.createRequestId(),\n { ...e, postEvent: this.postEvent }\n ).then((a) => n.parse(a));\n return Array.isArray(t) ? i : i[t];\n }\n /**\n * Saves specified value by key.\n * @param key - storage key.\n * @param value - storage value.\n * @param options - request execution options.\n */\n async set(t, e, s = {}) {\n await O(\n \"saveStorageValue\",\n { key: t, value: e },\n this.createRequestId(),\n { ...s, postEvent: this.postEvent }\n );\n }\n}\nclass Se {\n constructor(t, e = d) {\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.supports = E(t, {\n impactOccurred: \"web_app_trigger_haptic_feedback\",\n notificationOccurred: \"web_app_trigger_haptic_feedback\",\n selectionChanged: \"web_app_trigger_haptic_feedback\"\n });\n }\n /**\n * A method tells that an impact occurred. The Telegram app may play the\n * appropriate haptics based on style value passed.\n * @param style - impact style.\n */\n impactOccurred(t) {\n this.postEvent(\"web_app_trigger_haptic_feedback\", {\n type: \"impact\",\n impact_style: t\n });\n }\n /**\n * A method tells that a task or action has succeeded, failed, or produced\n * a warning. The Telegram app may play the appropriate haptics based on\n * type value passed.\n * @param type - notification type.\n */\n notificationOccurred(t) {\n this.postEvent(\"web_app_trigger_haptic_feedback\", {\n type: \"notification\",\n notification_type: t\n });\n }\n /**\n * A method tells that the user has changed a selection. The Telegram app\n * may play the appropriate haptics.\n *\n * Do not use this feedback when the user makes or confirms a selection;\n * use it only when the selection changes.\n */\n selectionChanged() {\n this.postEvent(\"web_app_trigger_haptic_feedback\", { type: \"selection_change\" });\n }\n}\nfunction xe() {\n const r = document.createElement(\"style\");\n r.id = \"telegram-custom-styles\", document.head.appendChild(r), y(\"set_custom_style\", (t) => {\n r.innerHTML = t;\n });\n}\nfunction qt(r) {\n return `telegram-mini-apps-${r}`;\n}\nfunction T(r, t) {\n sessionStorage.setItem(qt(r), JSON.stringify(t));\n}\nfunction B(r) {\n const t = sessionStorage.getItem(qt(r));\n return t ? JSON.parse(t) : null;\n}\nfunction qe(r, t, e) {\n const { isVisible: s = !1 } = r ? B(\"back-button\") || {} : {}, n = new Ee(s, t, e);\n return n.on(\"change\", () => {\n T(\"back-button\", { isVisible: n.isVisible });\n }), n;\n}\nfunction Ae(r, t) {\n const { isConfirmationNeeded: e = !1 } = r ? B(\"closing-behavior\") || {} : {}, s = new Pe(e, t);\n return s.on(\"change\", () => T(\"closing-behavior\", {\n isConfirmationNeeded: s.isConfirmationNeeded\n })), s;\n}\nclass Ve {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n o(this, \"postEvent\");\n /**\n * Adds new event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"on\", (t, e) => (\n // FIXME: Event 'main_button_pressed' is still being received on Android\n // even if the main button is disabled.\n // Issue: https://github.com/Telegram-Mini-Apps/tma.js/issues/3\n t === \"click\" ? y(\"main_button_pressed\", e) : this.ee.on(t, e)\n ));\n /**\n * Removes event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"off\", (t, e) => t === \"click\" ? $(\"main_button_pressed\", e) : this.ee.off(t, e));\n const {\n postEvent: e = d,\n text: s,\n textColor: n,\n backgroundColor: i,\n isEnabled: a,\n isVisible: c,\n isLoaderVisible: p\n } = t;\n this.postEvent = e, this.state = new b({\n backgroundColor: i,\n isEnabled: a,\n isVisible: c,\n isLoaderVisible: p,\n text: s,\n textColor: n\n }, this.ee);\n }\n /**\n * Sends current local state to Telegram application.\n */\n commit() {\n this.text !== \"\" && this.postEvent(\"web_app_setup_main_button\", {\n is_visible: this.isVisible,\n is_active: this.isEnabled,\n is_progress_visible: this.isLoaderVisible,\n text: this.text,\n color: this.backgroundColor,\n text_color: this.textColor\n });\n }\n set isEnabled(t) {\n this.setParams({ isEnabled: t });\n }\n /**\n * True if the Main Button is currently enabled.\n */\n get isEnabled() {\n return this.state.get(\"isEnabled\");\n }\n set isLoaderVisible(t) {\n this.setParams({ isLoaderVisible: t });\n }\n /**\n * True if the Main Button loader is currently visible.\n */\n get isLoaderVisible() {\n return this.state.get(\"isLoaderVisible\");\n }\n set isVisible(t) {\n this.setParams({ isVisible: t });\n }\n /**\n * True if the Main Button is currently visible.\n */\n get isVisible() {\n return this.state.get(\"isVisible\");\n }\n /**\n * The Main Button background color.\n */\n get backgroundColor() {\n return this.state.get(\"backgroundColor\");\n }\n /**\n * The Main Button text.\n */\n get text() {\n return this.state.get(\"text\");\n }\n /**\n * The Main Button text color.\n */\n get textColor() {\n return this.state.get(\"textColor\");\n }\n /**\n * Disables the Main Button.\n */\n disable() {\n return this.isEnabled = !1, this;\n }\n /**\n * Enables the Main Button.\n */\n enable() {\n return this.isEnabled = !0, this;\n }\n /**\n * Hides the Main Button.\n */\n hide() {\n return this.isVisible = !1, this;\n }\n /**\n * Hides the Main Button loader.\n */\n hideLoader() {\n return this.isLoaderVisible = !1, this;\n }\n /**\n * Shows the Main Button. Note that opening the Mini App from the attachment menu hides the\n * main button until the user interacts with the Mini App interface.\n */\n show() {\n return this.isVisible = !0, this;\n }\n /**\n * A method to show a loading indicator on the Main Button. It is recommended to display\n * loader if the action tied to the button may take a long time.\n */\n showLoader() {\n return this.isLoaderVisible = !0, this;\n }\n /**\n * Sets new Main Button text. Minimal length for text is 1 symbol, and maximum is 64 symbols.\n * @param text - new text.\n */\n setText(t) {\n return this.setParams({ text: t });\n }\n /**\n * Sets new Main Button text color.\n * @param textColor - new text color.\n */\n setTextColor(t) {\n return this.setParams({ textColor: t });\n }\n /**\n * Updates current Main Button color.\n * @param backgroundColor - color to set.\n */\n setBackgroundColor(t) {\n return this.setParams({ backgroundColor: t });\n }\n /**\n * Allows setting multiple Main Button parameters.\n * @param params - Main Button parameters.\n */\n setParams(t) {\n return this.state.set(t), this.commit(), this;\n }\n}\nfunction Re(r, t, e, s) {\n const {\n backgroundColor: n = t,\n isEnabled: i = !1,\n isVisible: a = !1,\n isLoaderVisible: c = !1,\n textColor: p = e,\n text: h = \"\"\n } = r ? B(\"main-button\") || {} : {}, g = new Ve({\n backgroundColor: n,\n isEnabled: i,\n isLoaderVisible: c,\n isVisible: a,\n postEvent: s,\n text: h,\n textColor: p\n }), _ = () => T(\"main-button\", {\n backgroundColor: g.backgroundColor,\n isEnabled: g.isEnabled,\n isLoaderVisible: g.isLoaderVisible,\n isVisible: g.isVisible,\n text: g.text,\n textColor: g.textColor\n });\n return g.on(\"change\", _), g;\n}\nconst Ie = X({\n contact: f({\n userId: {\n type: q(),\n from: \"user_id\"\n },\n phoneNumber: {\n type: u(),\n from: \"phone_number\"\n },\n firstName: {\n type: u(),\n from: \"first_name\"\n },\n lastName: {\n type: u().optional(),\n from: \"last_name\"\n }\n }),\n authDate: {\n type: pt(),\n from: \"auth_date\"\n },\n hash: u()\n});\nclass Le {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n o(this, \"botInline\");\n o(this, \"postEvent\");\n o(this, \"createRequestId\");\n o(this, \"requestingPhoneAccess\", !1);\n o(this, \"requestingWriteAccess\", !1);\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n /**\n * Checks if specified method parameter is supported by current component.\n */\n o(this, \"supportsParam\");\n const {\n postEvent: e = d,\n headerColor: s,\n backgroundColor: n,\n version: i,\n botInline: a,\n createRequestId: c\n } = t, p = E(i, {\n requestPhoneAccess: \"web_app_request_phone\",\n requestWriteAccess: \"web_app_request_write_access\",\n switchInlineQuery: \"web_app_switch_inline_query\",\n setHeaderColor: \"web_app_set_header_color\",\n setBackgroundColor: \"web_app_set_background_color\"\n });\n this.postEvent = e, this.botInline = a, this.createRequestId = c, this.supports = (h) => !(!p(h) || h === \"switchInlineQuery\" && !a), this.state = new b({ backgroundColor: n, headerColor: s }, this.ee), this.supportsParam = St(i, {\n \"setHeaderColor.color\": [\"web_app_set_header_color\", \"color\"]\n });\n }\n /**\n * Attempts to get requested contact.\n */\n async getRequestedContact() {\n return O(\n \"getRequestedContact\",\n {},\n this.createRequestId(),\n {\n postEvent: this.postEvent,\n timeout: 1e4\n }\n ).then((t) => Ie.parse(t));\n }\n /**\n * The Mini App background color.\n */\n get backgroundColor() {\n return this.state.get(\"backgroundColor\");\n }\n /**\n * Closes the Mini App.\n */\n close() {\n this.postEvent(\"web_app_close\");\n }\n /**\n * The Mini App header color. Could either be a header color key or RGB color.\n */\n get headerColor() {\n return this.state.get(\"headerColor\");\n }\n /**\n * True if Mini App is currently launched in bot inline mode.\n */\n get isBotInline() {\n return this.botInline;\n }\n /**\n * True if current Mini App background color recognized as dark.\n */\n get isDark() {\n return ft(this.backgroundColor);\n }\n /**\n * True if phone access is currently being requested.\n */\n get isRequestingPhoneAccess() {\n return this.requestingPhoneAccess;\n }\n /**\n * True if write access is currently being requested.\n */\n get isRequestingWriteAccess() {\n return this.requestingWriteAccess;\n }\n /**\n * Informs the Telegram app that the Mini App is ready to be displayed.\n *\n * It is recommended to call this method as early as possible, as soon as all essential\n * interface elements loaded. Once this method called, the loading placeholder is hidden\n * and the Mini App shown.\n *\n * If the method not called, the placeholder will be hidden only when the page fully loaded.\n */\n ready() {\n this.postEvent(\"web_app_ready\");\n }\n /**\n * Requests current user contact information. In contrary to requestPhoneAccess, this method\n * returns promise with contact information that rejects in case, user denied access, or request\n * failed.\n * @param options - additional options.\n */\n async requestContact({ timeout: t = 5e3 } = {}) {\n try {\n return await this.getRequestedContact();\n } catch {\n }\n if (await this.requestPhoneAccess() !== \"sent\")\n throw new Error(\"Access denied.\");\n const s = Date.now() + t;\n let n = 50;\n return xt(async () => {\n for (; Date.now() < s; ) {\n try {\n return await this.getRequestedContact();\n } catch {\n }\n await me(n), n += 50;\n }\n throw new Error(\"Unable to retrieve requested contact.\");\n }, t);\n }\n /**\n * Requests current user phone access. Method returns promise, which resolves\n * status of the request. In case, user accepted the request, Mini App bot will receive\n * the according notification.\n *\n * To obtain the retrieved information instead, utilize the requestContact method.\n * @param options - additional options.\n * @see requestContact\n */\n requestPhoneAccess(t = {}) {\n if (this.requestingPhoneAccess)\n throw new Error(\"Phone access is already being requested.\");\n return this.requestingPhoneAccess = !0, m(\"web_app_request_phone\", \"phone_requested\", {\n ...t,\n postEvent: this.postEvent\n }).then((e) => e.status).finally(() => {\n this.requestingPhoneAccess = !1;\n });\n }\n /**\n * Requests write message access to current user.\n * @param options - additional options.\n */\n requestWriteAccess(t = {}) {\n if (this.requestingWriteAccess)\n throw new Error(\"Write access is already being requested.\");\n return this.requestingWriteAccess = !0, m(\"web_app_request_write_access\", \"write_access_requested\", {\n ...t,\n postEvent: this.postEvent\n }).then((e) => e.status).finally(() => {\n this.requestingWriteAccess = !1;\n });\n }\n /**\n * A method used to send data to the bot. When this method called, a service message sent to\n * the bot containing the data of the length up to 4096 bytes, and the Mini App closed. See the\n * field `web_app_data` in the class [Message](https://core.telegram.org/bots/api#message).\n *\n * This method is only available for Mini Apps launched via a Keyboard button.\n * @param data - data to send to bot.\n * @throws {Error} data has incorrect size.\n */\n sendData(t) {\n const { size: e } = new Blob([t]);\n if (e === 0 || e > 4096)\n throw new Error(`Passed data has incorrect size: ${e}`);\n this.postEvent(\"web_app_data_send\", { data: t });\n }\n /**\n * Updates current Mini App header color.\n * @param color - color key or RGB color.\n */\n setHeaderColor(t) {\n this.postEvent(\"web_app_set_header_color\", lt(t) ? { color: t } : { color_key: t }), this.state.set(\"headerColor\", t);\n }\n /**\n * Updates current Mini App background color.\n * @param color - RGB color.\n */\n setBackgroundColor(t) {\n this.postEvent(\"web_app_set_background_color\", { color: t }), this.state.set(\"backgroundColor\", t);\n }\n /**\n * Inserts the bot's username and the specified inline query in the current chat's input field.\n * Query may be empty, in which case only the bot's username will be inserted. The client prompts\n * the user to choose a specific chat, then opens that chat and inserts the bot's username and\n * the specified inline query in the input field.\n * @param text - text which should be inserted in the input after the current bot name. Max\n * length is 256 symbols.\n * @param chatTypes - List of chat types which could be chosen to send the message. Could be\n * empty list.\n */\n switchInlineQuery(t, e = []) {\n if (!this.supports(\"switchInlineQuery\") && !this.isBotInline)\n throw new Error(\"Method is unsupported because Mini App should be launched in inline mode.\");\n this.postEvent(\"web_app_switch_inline_query\", {\n query: t,\n chat_types: e\n });\n }\n}\nfunction $e(r, t, e, s, n, i) {\n const {\n backgroundColor: a = t,\n headerColor: c = \"bg_color\"\n } = r ? B(\"mini-app\") || {} : {}, p = new Le({\n headerColor: c,\n backgroundColor: a,\n version: e,\n botInline: s,\n createRequestId: n,\n postEvent: i\n }), h = () => T(\"mini-app\", {\n backgroundColor: p.backgroundColor,\n headerColor: p.headerColor\n });\n return p.on(\"change\", h), p;\n}\nfunction Te() {\n let r = 0;\n return () => (r += 1, r.toString());\n}\nclass Be {\n constructor(t, e, s = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"on\", (t, e) => t === \"click\" ? y(\"settings_button_pressed\", e) : this.ee.on(t, e));\n /**\n * Removes event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"off\", (t, e) => t === \"click\" ? $(\"settings_button_pressed\", e) : this.ee.off(t, e));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = s, this.state = new b({ isVisible: t }, this.ee), this.supports = E(e, {\n show: \"web_app_setup_settings_button\",\n hide: \"web_app_setup_settings_button\"\n });\n }\n set isVisible(t) {\n this.state.set(\"isVisible\", t), this.postEvent(\"web_app_setup_settings_button\", { is_visible: t });\n }\n /**\n * True if SettingsButton is currently visible.\n */\n get isVisible() {\n return this.state.get(\"isVisible\");\n }\n /**\n * Hides the SettingsButton.\n */\n hide() {\n this.isVisible = !1;\n }\n /**\n * Shows the SettingsButton.\n */\n show() {\n this.isVisible = !0;\n }\n}\nfunction De(r, t, e) {\n const { isVisible: s = !1 } = r ? B(\"settings-button\") || {} : {}, n = new Be(s, t, e);\n return n.on(\"change\", () => {\n T(\"settings-button\", { isVisible: n.isVisible });\n }), n;\n}\nfunction We(r) {\n const t = new Mt(r);\n return t.listen(), t;\n}\nfunction Oe(r) {\n return [\"macos\", \"tdesktop\", \"unigram\", \"web\", \"weba\"].includes(r);\n}\nasync function At(r) {\n const t = await m(\"web_app_request_viewport\", \"viewport_changed\", r);\n return {\n height: t.height,\n width: t.width,\n isExpanded: t.is_expanded,\n isStateStable: t.is_state_stable\n };\n}\nfunction D(r) {\n return r < 0 ? 0 : r;\n}\nclass Ne {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n o(this, \"postEvent\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n const {\n height: e,\n isExpanded: s,\n width: n,\n stableHeight: i,\n postEvent: a = d\n } = t;\n this.postEvent = a, this.state = new b({\n height: D(e),\n isExpanded: s,\n stableHeight: D(i),\n width: D(n)\n }, this.ee);\n }\n /**\n * Request viewport information from the Telegram application and updates current Viewport\n * instance.\n * @param options - options to request fresh data.\n */\n sync(t) {\n return At(t).then(({ height: e, isExpanded: s, width: n, isStateStable: i }) => {\n this.state.set({\n height: e,\n width: n,\n isExpanded: s,\n stableHeight: i ? e : this.state.get(\"stableHeight\")\n });\n });\n }\n /**\n * The current height of the visible area of the Mini App.\n *\n * The application can display just the top part of the Mini App, with its\n * lower part remaining outside the screen area. From this position, the\n * user can \"pull\" the Mini App to its maximum height, while the bot can do\n * the same by calling `expand` method. As the position of the Mini App\n * changes, the current height value of the visible area will be updated\n * in real time.\n *\n * Please note that the refresh rate of this value is not sufficient\n * to smoothly follow the lower border of the window. It should not be\n * used to pin interface elements to the bottom of the visible area. It's\n * more appropriate to use the value of the `stableHeight`\n * field for this purpose.\n */\n get height() {\n return this.state.get(\"height\");\n }\n /**\n * The height of the visible area of the Mini App in its last stable state.\n *\n * The application can display just the top part of the Mini App, with its\n * lower part remaining outside the screen area. From this position,\n * the user can \"pull\" the Mini App to its maximum height, while the bot can\n * do the same by calling `expand` method.\n *\n * Unlike the value of `height`, the value of `stableHeight`\n * does not change as the position of the Mini App changes with user\n * gestures or during animations. The value of `stableHeight`\n * will be updated after all gestures and animations are completed and\n * the Mini App reaches its final size.\n */\n get stableHeight() {\n return this.state.get(\"stableHeight\");\n }\n /**\n * Starts listening to viewport changes and applies them.\n * @returns Function to stop listening.\n */\n listen() {\n return y(\"viewport_changed\", (t) => {\n const {\n height: e,\n width: s,\n is_expanded: n,\n is_state_stable: i\n } = t, a = {\n height: D(e),\n isExpanded: n,\n width: D(s)\n };\n i && (a.stableHeight = a.height), this.state.set(a);\n });\n }\n /**\n * Returns true if the Mini App is expanded to the maximum available height.\n * Otherwise, if the Mini App occupies part of the screen and can be expanded\n * to the full height using `expand` method.\n * @see expand\n */\n get isExpanded() {\n return this.state.get(\"isExpanded\");\n }\n /**\n * Current viewport width.\n */\n get width() {\n return this.state.get(\"width\");\n }\n /**\n * A method that expands the Mini App to the maximum available height. To\n * find out if the Mini App is expanded to the maximum height, refer to the\n * value of the `isExpanded`.\n * @see isExpanded\n */\n expand() {\n this.postEvent(\"web_app_expand\"), this.state.set(\"isExpanded\", !0);\n }\n /**\n * Returns true in case current viewport height is stable and is not going to\n * change in the next moment.\n */\n get isStable() {\n return this.stableHeight === this.height;\n }\n}\nfunction j(r) {\n const t = new Ne(r);\n return t.on(\"change\", () => T(\"viewport\", {\n height: t.height,\n isExpanded: t.isExpanded,\n stableHeight: t.stableHeight,\n width: t.width\n })), t.listen(), t;\n}\nfunction He(r, t, e, s) {\n const n = r ? B(\"viewport\") : null;\n if (n)\n return j({ ...n, postEvent: e });\n if (Oe(t))\n return j({\n height: window.innerHeight,\n isExpanded: !0,\n postEvent: e,\n stableHeight: window.innerHeight,\n width: window.innerWidth\n });\n if (s)\n return At({\n postEvent: e,\n timeout: 5e3\n }).then(({ height: a, isStateStable: c, ...p }) => j({\n ...p,\n height: a,\n stableHeight: c ? a : 0\n }));\n const i = j({\n width: 0,\n height: 0,\n isExpanded: !1,\n postEvent: e,\n stableHeight: 0\n });\n return i.sync({ postEvent: e, timeout: 5e3 }).catch((a) => {\n console.error(\"Unable to actualize viewport state\", a);\n }), i;\n}\nfunction S(r, t) {\n document.documentElement.style.setProperty(r, t);\n}\nfunction Ue(r, t) {\n const e = () => {\n S(\"--tg-background-color\", r.backgroundColor);\n }, s = () => {\n const {\n backgroundColor: n,\n secondaryBackgroundColor: i\n } = t;\n r.headerColor === \"bg_color\" ? n && S(\"--tg-header-color\", n) : r.headerColor === \"secondary_bg_color\" ? i && S(\"--tg-header-color\", i) : S(\"--tg-header-color\", r.headerColor);\n };\n t.on(\"change\", s), r.on(\"change:backgroundColor\", e), r.on(\"change:headerColor\", s), e(), s();\n}\nfunction Me(r) {\n const t = () => {\n const e = r.getState();\n Object.entries(e).forEach(([s, n]) => {\n if (n) {\n const i = s.replace(/[A-Z]/g, (a) => `-${a.toLowerCase()}`);\n S(`--tg-theme-${i}`, n);\n }\n });\n };\n r.on(\"change\", t), t();\n}\nfunction ot(r) {\n const t = () => S(\"--tg-viewport-height\", `${r.height}px`), e = () => S(\"--tg-viewport-width\", `${r.width}px`), s = () => S(\"--tg-viewport-height\", `${r.stableHeight}px`);\n r.on(\"change:height\", t), r.on(\"change:width\", e), r.on(\"change:stableHeight\", s), t(), e(), s();\n}\nfunction je(r) {\n return typeof r == \"object\" ? r : r ? {\n themeParams: !0,\n viewport: !0,\n miniApp: !0\n } : {};\n}\nfunction at(r, t, e, s) {\n const n = je(r);\n n.miniApp && Ue(t, e), n.themeParams && Me(e), n.viewport && (s instanceof Promise ? s.then(ot) : ot(s));\n}\nfunction Ge(r) {\n const { hostname: t, pathname: e } = new URL(r, window.location.href);\n if (t !== \"t.me\")\n throw new Error(`Incorrect hostname: ${t}`);\n const s = e.match(/^\\/(\\$|invoice\\/)([A-Za-z0-9\\-_=]+)$/);\n if (s === null)\n throw new Error('Link pathname has incorrect format. Expected to receive \"/invoice/{slug}\" or \"/${slug}\"');\n return s[2];\n}\nclass Fe {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.state = new b({ isOpened: !1 }, this.ee), this.supports = E(t, { open: \"web_app_open_invoice\" });\n }\n set isOpened(t) {\n this.state.set(\"isOpened\", t);\n }\n /**\n * True if invoice is currently opened.\n */\n get isOpened() {\n return this.state.get(\"isOpened\");\n }\n async open(t, e) {\n if (this.isOpened)\n throw new Error(\"Invoice is already opened\");\n const s = e ? Ge(t) : t;\n this.isOpened = !0;\n try {\n return (await m(\n \"web_app_open_invoice\",\n { slug: s },\n \"invoice_closed\",\n {\n postEvent: this.postEvent,\n capture(i) {\n return s === i.slug;\n }\n }\n )).status;\n } finally {\n this.isOpened = !1;\n }\n }\n}\nfunction ze(r) {\n const t = r.message.trim(), e = (r.title || \"\").trim(), s = r.buttons || [];\n let n;\n if (e.length > 64)\n throw new Error(`Title has incorrect size: ${e.length}`);\n if (t.length === 0 || t.length > 256)\n throw new Error(`Message has incorrect size: ${t.length}`);\n if (s.length > 3)\n throw new Error(`Buttons have incorrect size: ${s.length}`);\n return s.length === 0 ? n = [{ type: \"close\", id: \"\" }] : n = s.map((i) => {\n const { id: a = \"\" } = i;\n if (a.length > 64)\n throw new Error(`Button ID has incorrect size: ${a}`);\n if (i.type === void 0 || i.type === \"default\" || i.type === \"destructive\") {\n const c = i.text.trim();\n if (c.length === 0 || c.length > 64) {\n const p = i.type || \"default\";\n throw new Error(`Button text with type \"${p}\" has incorrect size: ${i.text.length}`);\n }\n return { ...i, text: c, id: a };\n }\n return { ...i, id: a };\n }), { title: e, message: t, buttons: n };\n}\nclass Je {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.state = new b({ isOpened: !1 }, this.ee), this.supports = E(t, { open: \"web_app_open_popup\" });\n }\n set isOpened(t) {\n this.state.set(\"isOpened\", t);\n }\n /**\n * True if popup is currently opened.\n */\n get isOpened() {\n return this.state.get(\"isOpened\");\n }\n /**\n * A method that shows a native popup described by the `params` argument.\n * Promise will be resolved when popup is closed. Resolved value will have\n * an identifier of pressed button.\n *\n * In case, user clicked outside the popup or clicked top right popup close\n * button, null will be returned.\n *\n * FIXME: In desktop, this function may work incorrectly.\n * Issue: https://github.com/Telegram-Mini-Apps/tma.js/issues/7\n * @param options - popup parameters.\n * @throws {Error} Popup is already opened.\n */\n open(t) {\n if (this.isOpened)\n throw new Error(\"Popup is already opened.\");\n return this.isOpened = !0, m(\n \"web_app_open_popup\",\n ze(t),\n \"popup_closed\",\n { postEvent: this.postEvent }\n ).then(({ button_id: e = null }) => e).finally(() => {\n this.isOpened = !1;\n });\n }\n}\nclass Qe {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.state = new b({ isOpened: !1 }, this.ee), this.supports = E(t, {\n close: \"web_app_close_scan_qr_popup\",\n open: \"web_app_open_scan_qr_popup\"\n });\n }\n /**\n * Closes scanner.\n */\n close() {\n this.postEvent(\"web_app_close_scan_qr_popup\"), this.isOpened = !1;\n }\n set isOpened(t) {\n this.state.set(\"isOpened\", t);\n }\n /**\n * Returns true in case, QR scanner is currently opened.\n */\n get isOpened() {\n return this.state.get(\"isOpened\");\n }\n /**\n * Opens scanner with specified title shown to user. Method returns promise\n * with scanned QR content in case, it was scanned. It will contain null in\n * case, scanner was closed.\n * @param text - title to display.\n */\n async open(t) {\n if (this.isOpened)\n throw new Error(\"QR scanner is already opened.\");\n this.isOpened = !0;\n try {\n const e = await m(\n \"web_app_open_scan_qr_popup\",\n { text: t },\n [\"qr_text_received\", \"scan_qr_popup_closed\"],\n { postEvent: this.postEvent }\n );\n return typeof e == \"object\" && typeof e.data == \"string\" ? e.data : null;\n } finally {\n this.isOpened = !1;\n }\n }\n}\nclass Ze {\n constructor(t, e, s = d) {\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n /**\n * Checks if specified method parameter is supported by current component.\n */\n o(this, \"supportsParam\");\n this.version = t, this.createRequestId = e, this.postEvent = s, this.supports = E(t, {\n readTextFromClipboard: \"web_app_read_text_from_clipboard\"\n }), this.supportsParam = St(t, {\n \"openLink.tryInstantView\": [\"web_app_open_link\", \"try_instant_view\"]\n });\n }\n /**\n * Opens a link in an external browser. The Mini App will not be closed.\n *\n * Note that this method can be called only in response to the user\n * interaction with the Mini App interface (e.g. click inside the Mini App\n * or on the main button).\n * @param url - URL to be opened.\n * @param tryInstantView\n */\n openLink(t, e) {\n const s = new URL(t, window.location.href).toString();\n if (!R(\"web_app_open_link\", this.version)) {\n window.open(s, \"_blank\");\n return;\n }\n this.postEvent(\"web_app_open_link\", {\n url: s,\n ...typeof e == \"boolean\" ? { try_instant_view: e } : {}\n });\n }\n /**\n * Opens a Telegram link inside Telegram app. The Mini App will be closed. It expects passing\n * link in full format, with hostname \"t.me\".\n * @param url - URL to be opened.\n * @throws {Error} URL has not allowed hostname.\n */\n openTelegramLink(t) {\n const {\n hostname: e,\n pathname: s,\n search: n\n } = new URL(t, window.location.href);\n if (e !== \"t.me\")\n throw new Error(`URL has not allowed hostname: ${e}. Only \"t.me\" is allowed`);\n if (!R(\"web_app_open_tg_link\", this.version)) {\n window.location.href = t;\n return;\n }\n this.postEvent(\"web_app_open_tg_link\", { path_full: s + n });\n }\n /**\n * Reads text from clipboard and returns string or null. null is returned\n * in cases:\n * - Value in clipboard is not text\n * - Access to clipboard is not allowed\n */\n readTextFromClipboard() {\n return m(\n \"web_app_read_text_from_clipboard\",\n { req_id: this.createRequestId() },\n \"clipboard_text_received\",\n { postEvent: this.postEvent }\n ).then(({ data: t = null }) => t);\n }\n}\nfunction ur(r = {}) {\n const {\n async: t = !1,\n complete: e = t,\n cssVars: s = !1,\n acceptCustomStyles: n = !1\n } = r;\n try {\n const {\n launchParams: {\n initData: i,\n initDataRaw: a,\n version: c,\n platform: p,\n themeParams: h,\n botInline: g = !1\n },\n isPageReload: _\n } = Ct(), A = Te(), l = be(c);\n vt() && (n && xe(), l(\"iframe_ready\", { reload_supported: !0 }), y(\"reload_iframe\", () => window.location.reload()));\n const C = {\n backButton: qe(_, c, l),\n closingBehavior: Ae(_, l),\n cloudStorage: new ke(c, A, l),\n createRequestId: A,\n hapticFeedback: new Se(c, l),\n invoice: new Fe(c, l),\n mainButton: Re(\n _,\n h.buttonColor || \"#000000\",\n h.buttonTextColor || \"#ffffff\",\n l\n ),\n miniApp: $e(\n _,\n h.backgroundColor || \"#ffffff\",\n c,\n g,\n A,\n l\n ),\n popup: new Je(c, l),\n postEvent: l,\n qrScanner: new Qe(c, l),\n settingsButton: De(_, c, l),\n themeParams: We(h),\n utils: new Ze(c, A, l),\n ...i ? {\n initData: new Ot(i),\n initDataRaw: a\n } : {}\n }, x = He(_, p, l, e);\n return x instanceof Promise || e ? Promise.resolve(x).then((v) => (at(\n s,\n C.miniApp,\n C.themeParams,\n v\n ), { ...C, viewport: v })) : (at(\n s,\n C.miniApp,\n C.themeParams,\n x\n ), { ...C, viewport: x });\n } catch (i) {\n if (e)\n return Promise.reject(i);\n throw i;\n }\n}\nfunction W(r, t) {\n return r.startsWith(t) ? r : `${t}${r}`;\n}\nfunction hr(r) {\n const t = r.match(/#(.+)/);\n return t ? t[1] : null;\n}\nasync function N(r) {\n return r === 0 ? !0 : Promise.race([\n new Promise((t) => {\n window.addEventListener(\"popstate\", function e() {\n window.removeEventListener(\"popstate\", e), t(!0);\n }), window.history.go(r);\n }),\n // Usually, it takes about 1ms to emit this event, but we use some buffer.\n new Promise((t) => {\n setTimeout(t, 50, !1);\n })\n ]);\n}\nasync function Ke() {\n if (window.history.length <= 1 || (window.history.pushState(null, \"\"), await N(1 - window.history.length)))\n return;\n let t = await N(-1);\n for (; t; )\n t = await N(-1);\n}\nclass Ye {\n constructor(t, e, {\n debug: s = !1,\n loggerPrefix: n = \"Navigator\"\n }) {\n o(this, \"logger\");\n o(this, \"entries\");\n if (this.entriesCursor = e, t.length === 0)\n throw new Error(\"Entries list should not be empty.\");\n if (e >= t.length)\n throw new Error(\"Cursor should be less than entries count.\");\n this.entries = t.map(({ pathname: i = \"\", search: a, hash: c }) => {\n if (!i.startsWith(\"/\") && i.length > 0)\n throw new Error('Pathname should start with \"/\"');\n return {\n pathname: W(i, \"/\"),\n search: a ? W(a, \"?\") : \"\",\n hash: c ? W(c, \"#\") : \"\"\n };\n }), this.logger = new Pt(`[${n}]`, s);\n }\n /**\n * Converts entry to the navigation entry.\n * @param entry - entry data\n */\n formatEntry(t) {\n let e;\n if (typeof t == \"string\")\n e = t;\n else {\n const {\n pathname: a = \"\",\n search: c,\n hash: p\n } = t;\n e = a + (c ? W(c, \"?\") : \"\") + (p ? W(p, \"#\") : \"\");\n }\n const {\n pathname: s,\n search: n,\n hash: i\n } = new URL(e, `https://localhost${this.path}`);\n return {\n pathname: s,\n search: n,\n hash: i\n };\n }\n /**\n * Current entry.\n */\n get entry() {\n return this.entries[this.entriesCursor];\n }\n /**\n * Goes back in history.\n */\n back() {\n return this.go(-1);\n }\n /**\n * Current entries cursor.\n */\n get cursor() {\n return this.entriesCursor;\n }\n /**\n * True if navigator can go back.\n */\n get canGoBack() {\n return this.entriesCursor > 0;\n }\n /**\n * True if navigator can go forward.\n */\n get canGoForward() {\n return this.entriesCursor !== this.entries.length - 1;\n }\n /**\n * Goes forward in history.\n */\n forward() {\n return this.go(1);\n }\n /**\n * Moves entries cursor by specified delta.\n * @param delta - cursor delta.\n */\n go(t) {\n this.logger.log(`called go(${t})`);\n const e = Math.min(\n this.entries.length - 1,\n Math.max(this.entriesCursor + t, 0)\n );\n if (this.entriesCursor === e)\n return this.performGo({\n updated: !1,\n delta: t\n });\n const s = this.entry;\n this.entriesCursor = e;\n const n = this.entry;\n return this.logger.log(\"State changed\", { before: s, after: n }), this.performGo({\n updated: !0,\n delta: t,\n before: s,\n after: n\n });\n }\n /**\n * Returns copy of navigator entries.\n */\n getEntries() {\n return this.entries.map((t) => ({ ...t }));\n }\n /**\n * Current hash.\n * @example\n * \"\", \"#\", \"#hash\"\n */\n get hash() {\n return this.entry.hash;\n }\n /**\n * Pushes new entry. Method replaces all entries after the current one with the inserted.\n * @param entry - entry data.\n *\n * @example Pushing absolute pathname.\n * push(\"/absolute-path\"); // \"/absolute-path\"\n *\n * @example Pushing relative pathname.\n * // Pushing relative path replaces N last path parts, where N is pushed pathname parts count.\n * // Pushing empty path is recognized as relative, but not replacing the last pathname part.\n * push(\"relative\"); // \"/home/root\" -> \"/home/relative\"\n *\n * @example Pushing query parameters.\n * push(\"/absolute?my-param=1\"); // \"/home\" -> \"/absolute?my-param=1\"\n * push(\"relative?my-param=1\"); // \"/home/root\" -> \"/home/relative?my-param=1\"\n * push(\"?my-param=1\"); // \"/home\" -> \"/home?my-param=1\"\n *\n * @example Pushing hash.\n * push(\"#my-hash\"); // \"/home\" -> \"/home#my-hash\"\n * push(\"johny#my-hash\"); // \"/home/root\" -> \"/home/johny#my-hash\"\n */\n push(t) {\n this.entriesCursor !== this.entries.length - 1 && this.entries.splice(this.entriesCursor + 1);\n const e = this.formatEntry(t), s = this.entry;\n this.entriesCursor += 1, this.entries[this.entriesCursor] = e;\n const n = this.entry;\n return this.logger.log(\"State changed\", { before: s, after: n }), this.performPush({\n before: s,\n after: n\n });\n }\n /**\n * Current full path including pathname, query parameters and hash.\n */\n get path() {\n return `${this.pathname}${this.search}${this.hash}`;\n }\n /**\n * Current pathname.\n * @example\n * \"/\", \"/abc\"\n */\n get pathname() {\n return this.entry.pathname;\n }\n /**\n * Replaces current entry. Has the same logic as `push` method.\n * @param entry - entry data.\n * @see push\n * @returns True if changes were done.\n */\n replace(t) {\n const e = this.formatEntry(t);\n if (this.search === e.search && this.pathname === e.pathname && this.hash === e.hash)\n return this.performReplace({\n updated: !1,\n entry: e\n });\n const s = this.entry;\n this.entries[this.entriesCursor] = e;\n const n = this.entry;\n return this.logger.log(\"State changed\", { before: s, after: n }), this.performReplace({\n updated: !0,\n before: s,\n after: n\n });\n }\n /**\n * Current query parameters.\n * @example\n * \"\", \"?\", \"?a=1\"\n */\n get search() {\n return this.entry.search;\n }\n}\nconst ct = 0, Z = 1, K = 2;\nclass Vt extends Ye {\n constructor(e, s, n = {}) {\n super(e, s, {\n ...n,\n loggerPrefix: \"HashNavigator\"\n });\n o(this, \"ee\", new w());\n o(this, \"attached\", !1);\n /**\n * Handles window \"popstate\" event.\n * @param state - event state.\n */\n o(this, \"onPopState\", async ({ state: e }) => {\n if (this.logger.log('\"popstate\" event received. State:', e), e === null)\n return this.push(window.location.hash.slice(1));\n if (e === ct) {\n this.logger.log(\"Void reached. Moving history forward\"), window.history.forward();\n return;\n }\n if (e === Z)\n return this.back();\n if (e === K)\n return this.forward();\n });\n o(this, \"back\", () => super.back());\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n }\n /**\n * Creates navigator from current window location hash.\n * @param options - options passed to constructor.\n */\n static fromLocation(e) {\n const {\n search: s,\n pathname: n,\n hash: i\n } = new URL(\n window.location.hash.slice(1),\n window.location.href\n );\n return new Vt([{ search: s, pathname: n, hash: i }], 0, e);\n }\n async performGo(e) {\n e.updated && (this.attached && await this.syncHistory(), this.emitChanged(e.before, e.after));\n }\n async performPush({ before: e, after: s }) {\n this.attached && await this.syncHistory(), this.emitChanged(e, s);\n }\n async performReplace(e) {\n e.updated && (this.attached && window.history.replaceState(null, \"\", `#${this.path}`), this.emitChanged(e.before, e.after));\n }\n /**\n * Synchronizes current navigator state with browser history.\n */\n async syncHistory() {\n window.removeEventListener(\"popstate\", this.onPopState);\n const e = `#${this.path}`;\n await Ke(), d(\"web_app_setup_back_button\", { is_visible: this.canGoBack }), this.canGoBack && this.canGoForward ? (this.logger.log(\"Setting up history: [<-, *, ->]\"), window.history.replaceState(Z, \"\"), window.history.pushState(null, \"\", e), window.history.pushState(K, \"\"), await N(-1)) : this.canGoBack ? (this.logger.log(\"Setting up history: [<-, *]\"), window.history.replaceState(Z, \"\"), window.history.pushState(null, \"\", e)) : this.canGoForward ? (this.logger.log(\"Setting up history: [*, ->]\"), window.history.replaceState(null, e), window.history.pushState(K, \"\"), await N(-1)) : (this.logger.log(\"Setting up history: [~, *]\"), window.history.replaceState(ct, \"\"), window.history.pushState(null, \"\", e)), window.addEventListener(\"popstate\", this.onPopState);\n }\n emitChanged(e, s) {\n this.ee.emit(\"change\", {\n navigator: this,\n from: e,\n to: s\n });\n }\n /**\n * Attaches current navigator to the browser history allowing navigator to manipulate it.\n */\n async attach() {\n if (!this.attached)\n return this.logger.log(\"Attaching\", this), this.attached = !0, y(\"back_button_pressed\", this.back), this.syncHistory();\n }\n /**\n * Detaches current navigator from the browser history.\n */\n detach() {\n this.attached && (this.logger.log(\"Detaching\", this), this.attached = !1, window.removeEventListener(\"popstate\", this.onPopState), $(\"back_button_pressed\", this.back));\n }\n}\nexport {\n Ee as BackButton,\n Pe as ClosingBehavior,\n ke as CloudStorage,\n Se as HapticFeedback,\n Vt as HashNavigator,\n Ot as InitData,\n Fe as Invoice,\n Ve as MainButton,\n tt as MethodUnsupportedError,\n Le as MiniApp,\n Ye as Navigator,\n et as ParameterUnsupportedError,\n Je as Popup,\n Qe as QRScanner,\n Be as SettingsButton,\n Mt as ThemeParams,\n J as TimeoutError,\n Ze as Utils,\n Ne as Viewport,\n Wt as chatParser,\n Ce as classNames,\n _e as compareVersions,\n be as createPostEvent,\n hr as getHash,\n ur as init,\n wt as initDataParser,\n O as invokeCustomMethod,\n ft as isColorDark,\n vt as isIframe,\n lt as isRGB,\n Dt as isRGBShort,\n H as isRecord,\n Oe as isStableViewportPlatform,\n rr as isTMA,\n ar as isTimeoutError,\n mt as launchParamsParser,\n cr as mergeClassNames,\n $ as off,\n y as on,\n ir as once,\n tr as parseInitData,\n jt as parseLaunchParams,\n bt as parseThemeParams,\n d as postEvent,\n m as request,\n er as requestThemeParams,\n At as requestViewport,\n Ct as retrieveLaunchData,\n Jt as serializeLaunchParams,\n Ut as serializeThemeParams,\n sr as setDebug,\n nr as setTargetOrigin,\n or as subscribe,\n R as supports,\n _t as themeParamsParser,\n dt as toRGB,\n we as unsubscribe,\n rt as userParser,\n xt as withTimeout\n};\n//# sourceMappingURL=index.mjs.map\n","import { createHmac } from 'node:crypto';\nimport { URLSearchParams } from 'node:url';\n\nexport interface ValidateOptions {\n /**\n * Time in seconds which states, how long from creation time is init data\n * considered valid.\n *\n * In other words, in case, when authDate + expiresIn is before current\n * time, init data recognized as expired.\n *\n * In case, this value is equal to 0, function does not check init data\n * expiration.\n * @default 86400 (1 day)\n */\n expiresIn?: number;\n}\n\n/**\n * Validates passed init data presented as search params converted to string,\n * or its object presentation.\n *\n * @param sp - search parameters.\n * @param token - Telegram bot secret token.\n * @param options - validation options.\n * @see toSearchParams\n * @throws {TypeError} \"hash\" should be string.\n * @throws {Error} \"hash\" is empty or not found.\n * @throws {TypeError} \"auth_date\" should be string.\n * @throws {TypeError} \"auth_date\" does not represent integer.\n * @throws {Error} \"auth_date\" is empty or not found.\n * @throws {Error} Init data expired.\n * @throws {Error} Sign invalid.\n */\nexport function validate(\n sp: string | URLSearchParams,\n token: string,\n options: ValidateOptions = {},\n): void {\n const searchParams = typeof sp === 'string' ? new URLSearchParams(sp) : sp;\n\n // Init data creation time.\n let authDate = new Date(0);\n\n // Init data sign.\n let hash = '';\n\n // All search params pairs presented as `k=v`.\n const pairs: string[] = [];\n\n // Iterate over all key-value pairs of parsed parameters and find required\n // parameters.\n searchParams.forEach((value, key) => {\n if (key === 'hash') {\n hash = value;\n return;\n }\n\n if (key === 'auth_date') {\n const authDateNum = parseInt(value, 10);\n\n if (Number.isNaN(authDateNum)) {\n throw new TypeError('\"auth_date\" should present integer');\n }\n authDate = new Date(authDateNum * 1000);\n }\n\n // Append new pair.\n pairs.push(`${key}=${value}`);\n });\n\n // Hash and auth date always required.\n if (hash.length === 0) {\n throw new Error('\"hash\" is empty or not found');\n }\n\n if (authDate.getTime() === 0) {\n throw new Error('\"auth_date\" is empty or not found');\n }\n\n // In case, expiration time passed, we do additional parameters check.\n const { expiresIn = 86400 } = options;\n\n if (expiresIn > 0) {\n // Check if init data expired.\n if (authDate.getTime() + expiresIn * 1000 < new Date().getTime()) {\n throw new Error('Init data expired');\n }\n }\n\n // According to docs, we sort all the pairs in alphabetical order.\n pairs.sort();\n\n // Compute sign.\n const computedHash = createHmac(\n 'sha256',\n createHmac('sha256', 'WebAppData').update(token).digest(),\n )\n .update(pairs.join('\\n'))\n .digest()\n .toString('hex');\n\n // In case, our sign is not equal to found one, we should throw an error.\n if (computedHash !== hash) {\n throw new Error('Signature is invalid');\n }\n}\n"],"names":["Rt","It","r","e","o","I","F","s","n","z","L","G","ht","i","a","h","c","p","k","q","pt","Y","f","u","X","Wt","rt","wt","tr","validate","sp","token","options","searchParams","URLSearchParams","authDate","hash","pairs","value","key","authDateNum","expiresIn","createHmac"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../sdk/dist/index.mjs","../src/validate.ts"],"sourcesContent":["var Rt = Object.defineProperty;\nvar It = (r, t, e) => t in r ? Rt(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;\nvar o = (r, t, e) => (It(r, typeof t != \"symbol\" ? t + \"\" : t, e), e);\nfunction H(r) {\n return typeof r == \"object\" && r !== null && !Array.isArray(r);\n}\nfunction ut() {\n return performance.getEntriesByType(\"navigation\")[0] || null;\n}\nfunction Lt() {\n const r = ut();\n return r ? r.type === \"reload\" : null;\n}\nfunction I() {\n return new TypeError(\"Value has unexpected type\");\n}\nclass F extends Error {\n constructor(e, { cause: s, type: n } = {}) {\n super(`Unable to parse value${n ? ` as ${n}` : \"\"}`, { cause: s });\n /**\n * Parser name.\n */\n o(this, \"type\");\n this.value = e, Object.setPrototypeOf(this, F.prototype), this.type = n;\n }\n}\nclass z {\n constructor(t, e, s) {\n this.parser = t, this.isOptional = e, this.type = s;\n }\n parse(t) {\n if (!(this.isOptional && t === void 0))\n try {\n return this.parser(t);\n } catch (e) {\n throw new F(t, { type: this.type, cause: e });\n }\n }\n optional() {\n return this.isOptional = !0, this;\n }\n}\nfunction $t(r) {\n if (Array.isArray(r))\n return r;\n if (typeof r == \"string\")\n try {\n const t = JSON.parse(r);\n if (Array.isArray(t))\n return t;\n } catch {\n }\n throw I();\n}\nclass Tt extends z {\n constructor(e, s, n) {\n super($t, s, n);\n o(this, \"itemParser\");\n this.itemParser = typeof e == \"function\" ? e : e.parse.bind(e);\n }\n parse(e) {\n const s = super.parse(e);\n return s === void 0 ? s : s.map(this.itemParser);\n }\n of(e) {\n return this.itemParser = typeof e == \"function\" ? e : e.parse.bind(e), this;\n }\n}\nfunction L(r, t) {\n return () => new z(r, !1, t);\n}\nclass G extends Error {\n constructor(t, { cause: e, type: s } = {}) {\n super(`Unable to parse field \"${t}\"${s ? ` as ${s}` : \"\"}`, { cause: e }), Object.setPrototypeOf(this, G.prototype);\n }\n}\nfunction ht(r, t) {\n const e = {};\n for (const s in r) {\n const n = r[s];\n if (!n)\n continue;\n let i, a;\n if (typeof n == \"function\" || \"parse\" in n)\n i = s, a = typeof n == \"function\" ? n : n.parse.bind(n);\n else {\n const { type: h } = n;\n i = n.from || s, a = typeof h == \"function\" ? h : h.parse.bind(h);\n }\n let c;\n const p = t(i);\n try {\n c = a(p);\n } catch (h) {\n throw h instanceof F ? new G(i, {\n type: h.type,\n cause: h\n }) : new G(i, { cause: h });\n }\n c !== void 0 && (e[s] = c);\n }\n return e;\n}\nfunction Bt(r) {\n return new Tt((t) => t, !1, r);\n}\nconst k = L((r) => {\n if (typeof r == \"boolean\")\n return r;\n const t = String(r);\n if (t === \"1\" || t === \"true\")\n return !0;\n if (t === \"0\" || t === \"false\")\n return !1;\n throw I();\n}, \"boolean\"), q = L((r) => {\n if (typeof r == \"number\")\n return r;\n if (typeof r == \"string\") {\n const t = Number(r);\n if (!Number.isNaN(t))\n return t;\n }\n throw I();\n}, \"number\"), pt = L((r) => r instanceof Date ? r : new Date(q().parse(r) * 1e3), \"Date\");\nfunction Y(r) {\n let t = r;\n if (typeof t == \"string\" && (t = JSON.parse(t)), typeof t != \"object\" || t === null || Array.isArray(t))\n throw I();\n return t;\n}\nfunction f(r, t) {\n return new z((e) => {\n const s = Y(e);\n return ht(r, (n) => s[n]);\n }, !1, t);\n}\nfunction lt(r) {\n return /^#[\\da-f]{6}$/i.test(r);\n}\nfunction Dt(r) {\n return /^#[\\da-f]{3}$/i.test(r);\n}\nfunction dt(r) {\n const t = r.replace(/\\s/g, \"\").toLowerCase();\n if (lt(t))\n return t;\n if (Dt(t)) {\n let s = \"#\";\n for (let n = 0; n < 3; n += 1)\n s += t[1 + n].repeat(2);\n return s;\n }\n const e = t.match(/^rgb\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)$/) || t.match(/^rgba\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3}),\\d{1,3}\\)$/);\n if (e === null)\n throw new Error(`Value \"${r}\" does not satisfy any of known RGB formats.`);\n return e.slice(1).reduce((s, n) => {\n const i = parseInt(n, 10).toString(16);\n return s + (i.length === 1 ? \"0\" : \"\") + i;\n }, \"#\");\n}\nfunction ft(r) {\n const t = dt(r);\n return Math.sqrt(\n [0.299, 0.587, 0.114].reduce((s, n, i) => {\n const a = parseInt(t.slice(1 + i * 2, 1 + (i + 1) * 2), 16);\n return s + a * a * n;\n }, 0)\n ) < 120;\n}\nconst u = L((r) => {\n if (typeof r == \"string\" || typeof r == \"number\")\n return r.toString();\n throw I();\n}, \"string\"), gt = L((r) => dt(u().parse(r)), \"rgb\");\nfunction X(r, t) {\n return new z((e) => {\n if (typeof e != \"string\" && !(e instanceof URLSearchParams))\n throw I();\n const s = typeof e == \"string\" ? new URLSearchParams(e) : e;\n return ht(r, (n) => {\n const i = s.get(n);\n return i === null ? void 0 : i;\n });\n }, !1, t);\n}\nfunction Wt() {\n return f({\n id: q(),\n type: u(),\n title: u(),\n photoUrl: {\n type: u().optional(),\n from: \"photo_url\"\n },\n username: u().optional()\n }, \"Chat\");\n}\nclass Ot {\n constructor(t) {\n this.initData = t;\n }\n /**\n * @see InitDataParsed.authDate\n */\n get authDate() {\n return this.initData.authDate;\n }\n /**\n * @see InitDataParsed.canSendAfter\n */\n get canSendAfter() {\n return this.initData.canSendAfter;\n }\n /**\n * Date after which it is allowed to call\n * the [answerWebAppQuery](https://core.telegram.org/bots/api#answerwebappquery) method.\n */\n get canSendAfterDate() {\n const { canSendAfter: t } = this;\n return t === void 0 ? void 0 : new Date(this.authDate.getTime() + t * 1e3);\n }\n /**\n * @see InitDataParsed.chat\n */\n get chat() {\n return this.initData.chat;\n }\n /**\n * @see InitDataParsed.chatType\n */\n get chatType() {\n return this.initData.chatType;\n }\n /**\n * @see InitDataParsed.chatInstance\n */\n get chatInstance() {\n return this.initData.chatInstance;\n }\n /**\n * @see InitDataParsed.hash\n */\n get hash() {\n return this.initData.hash;\n }\n /**\n * @see InitDataParsed.queryId\n */\n get queryId() {\n return this.initData.queryId;\n }\n /**\n * @see InitDataParsed.receiver\n */\n get receiver() {\n return this.initData.receiver;\n }\n /**\n * @see InitDataParsed.startParam\n */\n get startParam() {\n return this.initData.startParam;\n }\n /**\n * @see InitDataParsed.user\n */\n get user() {\n return this.initData.user;\n }\n}\nfunction rt() {\n return f({\n addedToAttachmentMenu: {\n type: k().optional(),\n from: \"added_to_attachment_menu\"\n },\n allowsWriteToPm: {\n type: k().optional(),\n from: \"allows_write_to_pm\"\n },\n firstName: {\n type: u(),\n from: \"first_name\"\n },\n id: q(),\n isBot: {\n type: k().optional(),\n from: \"is_bot\"\n },\n isPremium: {\n type: k().optional(),\n from: \"is_premium\"\n },\n languageCode: {\n type: u().optional(),\n from: \"language_code\"\n },\n lastName: {\n type: u().optional(),\n from: \"last_name\"\n },\n photoUrl: {\n type: u().optional(),\n from: \"photo_url\"\n },\n username: u().optional()\n }, \"User\");\n}\nfunction wt() {\n return X({\n authDate: {\n type: pt(),\n from: \"auth_date\"\n },\n canSendAfter: {\n type: q().optional(),\n from: \"can_send_after\"\n },\n chat: Wt().optional(),\n chatInstance: {\n type: u().optional(),\n from: \"chat_instance\"\n },\n chatType: {\n type: u().optional(),\n from: \"chat_type\"\n },\n hash: u(),\n queryId: {\n type: u().optional(),\n from: \"query_id\"\n },\n receiver: rt().optional(),\n startParam: {\n type: u().optional(),\n from: \"start_param\"\n },\n user: rt().optional()\n }, \"InitData\");\n}\nfunction er(r) {\n return wt().parse(r);\n}\nfunction Nt(r) {\n return r.replace(/(^|_)bg/, (t, e) => `${e}background`).replace(/_([a-z])/g, (t, e) => e.toUpperCase());\n}\nfunction Ht(r) {\n return r.replace(/[A-Z]/g, (t) => `_${t.toLowerCase()}`).replace(/(^|_)background/, (t, e) => `${e}bg`);\n}\nconst _t = L(\n (r) => {\n const t = gt().optional();\n return Object.entries(Y(r)).reduce((e, [s, n]) => (e[Nt(s)] = t.parse(n), e), {});\n },\n \"ThemeParams\"\n);\nfunction bt(r) {\n return _t().parse(r);\n}\nfunction rr(r = {}) {\n return m(\"web_app_request_theme\", \"theme_changed\", r).then(bt);\n}\nfunction Ut(r) {\n return JSON.stringify(\n Object.entries(r).reduce((t, [e, s]) => (s && (t[Ht(e)] = s), t), {})\n );\n}\nclass w {\n constructor() {\n o(this, \"listeners\", /* @__PURE__ */ new Map());\n o(this, \"subscribeListeners\", []);\n }\n /**\n * Adds specified event listener.\n * @param event - event name.\n * @param listener - event listener.\n * @param once - should listener called only once.\n */\n addListener(t, e, s) {\n let n = this.listeners.get(t);\n return n || (n = [], this.listeners.set(t, n)), n.push([e, s]), () => this.off(t, e);\n }\n emit(t, ...e) {\n this.subscribeListeners.forEach((n) => n(t, ...e));\n const s = this.listeners.get(t);\n s && s.forEach(([n, i], a) => {\n n(...e), i && s.splice(a, 1);\n });\n }\n /**\n * Adds event listener.\n * @param event - event name.\n * @param listener - event listener.\n * @returns Function to remove event listener.\n */\n on(t, e) {\n return this.addListener(t, e, !1);\n }\n /**\n * Adds event listener following the logic, described in `on` method, but calls specified\n * listener only once, removing it after.\n * @param event - event name.\n * @param listener - event listener.\n * @returns Function to remove event listener.\n * @see on\n */\n once(t, e) {\n return this.addListener(t, e, !0);\n }\n /**\n * Removes event listener. In case, specified listener was bound several times, it removes\n * only a single one.\n * @param event - event name.\n * @param listener - event listener.\n */\n off(t, e) {\n const s = this.listeners.get(t);\n if (s) {\n for (let n = 0; n < s.length; n += 1)\n if (e === s[n][0]) {\n s.splice(n, 1);\n return;\n }\n }\n }\n /**\n * Adds event listener to all events.\n * @param listener - events listener.\n * @returns Function to remove event listener.\n * @see on\n * @see once\n */\n subscribe(t) {\n return this.subscribeListeners.push(t), () => this.unsubscribe(t);\n }\n /**\n * Removes global event listener. In case, specified listener was bound several times, it removes\n * only a single one.\n * @param listener - events listener.\n * @returns Function to remove event listener.\n */\n unsubscribe(t) {\n for (let e = 0; e < this.subscribeListeners.length; e += 1)\n if (this.subscribeListeners[e] === t) {\n this.subscribeListeners.splice(e, 1);\n return;\n }\n }\n}\nclass b {\n constructor(t, e) {\n this.state = t, this.ee = e;\n }\n internalSet(t, e) {\n return this.state[t] === e || e === void 0 ? !1 : (this.state[t] = e, this.ee.emit(`change:${t}`, e), !0);\n }\n /**\n * Returns copy of current state.\n */\n clone() {\n return { ...this.state };\n }\n set(t, e) {\n let s = !1;\n if (typeof t == \"string\")\n s = this.internalSet(t, e);\n else\n for (const n in t)\n this.internalSet(n, t[n]) && (s = !0);\n s && this.ee.emit(\"change\");\n }\n /**\n * Returns value by specified key.\n * @param key - state key.\n */\n get(t) {\n return this.state[t];\n }\n}\nclass Mt {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n this.state = new b(t, this.ee);\n }\n /**\n * @since v6.10\n */\n get accentTextColor() {\n return this.get(\"accentTextColor\");\n }\n get backgroundColor() {\n return this.get(\"backgroundColor\");\n }\n get buttonColor() {\n return this.get(\"buttonColor\");\n }\n get buttonTextColor() {\n return this.get(\"buttonTextColor\");\n }\n get destructiveTextColor() {\n return this.get(\"destructiveTextColor\");\n }\n /**\n * Retrieves palette color value by its name.\n * @param key - palette key name.\n */\n get(t) {\n return this.state.get(t);\n }\n /**\n * Returns the copy of the internal state of the current component instance.\n */\n getState() {\n return this.state.clone();\n }\n /**\n * @since v6.10\n */\n get headerBackgroundColor() {\n return this.get(\"headerBackgroundColor\");\n }\n get hintColor() {\n return this.get(\"hintColor\");\n }\n /**\n * Returns true in case, current color scheme is recognized as dark. This\n * value is calculated according to theme background color.\n */\n get isDark() {\n return !this.backgroundColor || ft(this.backgroundColor);\n }\n get linkColor() {\n return this.get(\"linkColor\");\n }\n get secondaryBackgroundColor() {\n return this.get(\"secondaryBackgroundColor\");\n }\n /**\n * @since v6.10\n */\n get sectionBackgroundColor() {\n return this.get(\"sectionBackgroundColor\");\n }\n /**\n * @since v6.10\n */\n get sectionHeaderTextColor() {\n return this.get(\"sectionHeaderTextColor\");\n }\n /**\n * Starts listening to theme changes and applies them.\n * @returns Function to stop listening.\n */\n listen() {\n return y(\"theme_changed\", (t) => {\n this.state.set(bt(t.theme_params));\n });\n }\n /**\n * @since v6.10\n */\n get subtitleTextColor() {\n return this.get(\"subtitleTextColor\");\n }\n get textColor() {\n return this.get(\"textColor\");\n }\n}\nfunction mt() {\n return X({\n botInline: {\n type: k().optional(),\n from: \"tgWebAppBotInline\"\n },\n initData: {\n type: wt().optional(),\n from: \"tgWebAppData\"\n },\n initDataRaw: {\n type: u().optional(),\n from: \"tgWebAppData\"\n },\n platform: {\n type: u(),\n from: \"tgWebAppPlatform\"\n },\n showSettings: {\n type: k().optional(),\n from: \"tgWebAppShowSettings\"\n },\n startParam: {\n type: u().optional(),\n from: \"tgWebAppStartParam\"\n },\n themeParams: {\n type: _t(),\n from: \"tgWebAppThemeParams\"\n },\n version: {\n type: u(),\n from: \"tgWebAppVersion\"\n }\n }, \"LaunchParams\");\n}\nfunction jt(r) {\n return mt().parse(r);\n}\nfunction yt(r) {\n const t = r.includes(\"?\") ? r.replace(\"#\", \"&\").slice(r.indexOf(\"?\") + 1) : r.slice(r.indexOf(\"#\") + 1);\n return jt(t);\n}\nfunction Gt() {\n return yt(window.location.href);\n}\nfunction Ft() {\n const r = ut();\n if (!r)\n throw new Error(\"Unable to get first navigation entry.\");\n return yt(r.name);\n}\nfunction zt() {\n try {\n return Ft();\n } catch {\n }\n try {\n return Gt();\n } catch {\n }\n return null;\n}\nfunction Jt(r) {\n const {\n initDataRaw: t,\n themeParams: e,\n platform: s,\n version: n,\n showSettings: i,\n botInline: a\n } = r, c = new URLSearchParams();\n return t && c.set(\"tgWebAppData\", t), c.set(\"tgWebAppPlatform\", s), c.set(\"tgWebAppThemeParams\", Ut(e)), c.set(\"tgWebAppVersion\", n), typeof i == \"boolean\" && c.set(\"tgWebAppShowSettings\", i ? \"1\" : \"0\"), typeof a == \"boolean\" && c.set(\"tgWebAppBotInline\", a ? \"1\" : \"0\"), c.toString();\n}\nconst Et = \"telegram-mini-apps-launch-params\";\nfunction Qt() {\n const r = sessionStorage.getItem(Et);\n return r ? mt().parse(r) : null;\n}\nfunction Zt(r) {\n sessionStorage.setItem(Et, Jt(r));\n}\nfunction Kt() {\n try {\n return window.self !== window.top;\n } catch {\n return !0;\n }\n}\nfunction Yt() {\n const r = Qt(), t = zt(), e = Lt();\n if (r) {\n if (t)\n return {\n launchParams: t,\n isPageReload: Kt() ? e || r.initDataRaw === t.initDataRaw : !0\n };\n if (e)\n return {\n launchParams: r,\n isPageReload: e\n };\n throw new Error(\"Unable to retrieve current launch parameters, which must exist.\");\n }\n if (t)\n return {\n launchParams: t,\n isPageReload: !1\n };\n throw new Error(\"Unable to retrieve any launch parameters.\");\n}\nconst st = \"tmajsLaunchData\";\nfunction Ct() {\n const r = window[st];\n if (r)\n return r;\n const t = Yt();\n return window[st] = t, Zt(t.launchParams), t;\n}\nfunction sr() {\n try {\n return Ct(), !0;\n } catch {\n return !1;\n }\n}\nfunction Xt(r) {\n return \"external\" in r && H(r.external) && \"notify\" in r.external && typeof r.external.notify == \"function\";\n}\nfunction te(r) {\n return \"TelegramWebviewProxy\" in r && H(r.TelegramWebviewProxy) && \"postEvent\" in r.TelegramWebviewProxy && typeof r.TelegramWebviewProxy.postEvent == \"function\";\n}\nfunction vt() {\n try {\n return window.self !== window.top;\n } catch {\n return !0;\n }\n}\nclass tt extends Error {\n constructor(t, e) {\n super(`Method \"${t}\" is unsupported in the Mini Apps version ${e}.`), Object.setPrototypeOf(this, tt.prototype);\n }\n}\nclass et extends Error {\n constructor(t, e, s) {\n super(`Parameter \"${e}\" in method \"${t}\" is unsupported in the Mini Apps version ${s}.`), Object.setPrototypeOf(this, et.prototype);\n }\n}\nclass Pt {\n constructor(t, e) {\n this.prefix = t, this.enabled = e;\n }\n /**\n * Prints message into a console in case, logger is currently enabled.\n * @param level - log level.\n * @param args - arguments.\n */\n print(t, ...e) {\n if (!this.enabled)\n return;\n const s = /* @__PURE__ */ new Date(), n = Intl.DateTimeFormat(\"en-GB\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n fractionalSecondDigits: 3,\n timeZone: \"UTC\"\n }).format(s);\n console[t](`[${n}]`, this.prefix, ...e);\n }\n /**\n * Disables the logger.\n */\n disable() {\n this.enabled = !1;\n }\n /**\n * Prints error message into a console.\n * @param args\n */\n error(...t) {\n this.print(\"error\", ...t);\n }\n /**\n * Enables the logger.\n */\n enable() {\n this.enabled = !0;\n }\n /**\n * Prints log message into a console.\n * @param args\n */\n log(...t) {\n this.print(\"log\", ...t);\n }\n /**\n * Prints warning message into a console.\n * @param args\n */\n warn(...t) {\n this.print(\"warn\", ...t);\n }\n}\nlet kt = \"https://web.telegram.org\";\nconst V = new Pt(\"[SDK]\", !1);\nfunction nr(r) {\n if (r) {\n V.enable();\n return;\n }\n V.disable();\n}\nfunction ir(r) {\n kt = r;\n}\nfunction ee() {\n return kt;\n}\nconst re = f({\n eventType: u(),\n eventData: (r) => r\n});\nfunction se(r) {\n return re.parse(r);\n}\nfunction ne(r, t) {\n window.dispatchEvent(new MessageEvent(\"message\", {\n data: JSON.stringify({ eventType: r, eventData: t })\n }));\n}\nfunction ie() {\n const r = window;\n \"TelegramGameProxy_receiveEvent\" in r || [\n [\"TelegramGameProxy_receiveEvent\"],\n // Windows Phone.\n [\"TelegramGameProxy\", \"receiveEvent\"],\n // Desktop.\n [\"Telegram\", \"WebView\", \"receiveEvent\"]\n // Android and iOS.\n ].forEach((t) => {\n let e = r;\n t.forEach((s, n, i) => {\n if (n === i.length - 1) {\n e[s] = ne;\n return;\n }\n s in e || (e[s] = {}), e = e[s];\n });\n });\n}\nfunction oe(r) {\n ie(), window.addEventListener(\"message\", (t) => {\n try {\n const { eventType: e, eventData: s } = se(t.data);\n r(e, s);\n } catch {\n }\n });\n}\nfunction ae() {\n return f({\n req_id: u(),\n data: (r) => r === null ? r : u().optional().parse(r)\n });\n}\nfunction ce() {\n return f({\n req_id: u(),\n result: (r) => r,\n error: u().optional()\n });\n}\nfunction ue() {\n return f({\n slug: u(),\n status: u()\n });\n}\nfunction he() {\n return f({ status: u() });\n}\nfunction pe() {\n return f({\n button_id: (r) => r == null ? void 0 : u().parse(r)\n });\n}\nfunction le() {\n return f({\n data: u().optional()\n });\n}\nfunction de() {\n return f({\n theme_params: (r) => {\n const t = gt().optional();\n return Object.entries(Y(r)).reduce((e, [s, n]) => (e[s] = t.parse(n), e), {});\n }\n });\n}\nfunction fe() {\n return f({\n height: q(),\n width: (r) => r == null ? window.innerWidth : q().parse(r),\n is_state_stable: k(),\n is_expanded: k()\n });\n}\nfunction ge() {\n return f({ status: u() });\n}\nfunction we() {\n const r = new w(), t = (e, ...s) => {\n V.log(\"Emitting processed event:\", e, ...s), r.emit(e, ...s);\n };\n return window.addEventListener(\"resize\", () => {\n t(\"viewport_changed\", {\n width: window.innerWidth,\n height: window.innerHeight,\n is_state_stable: !0,\n is_expanded: !0\n });\n }), oe((e, s) => {\n V.log(\"Received raw event:\", e, s);\n try {\n switch (e) {\n case \"viewport_changed\":\n return t(e, fe().parse(s));\n case \"theme_changed\":\n return t(e, de().parse(s));\n case \"popup_closed\":\n return (\n // Sent on desktop.\n s == null ? t(e, {}) : t(e, pe().parse(s))\n );\n case \"set_custom_style\":\n return t(e, u().parse(s));\n case \"qr_text_received\":\n return t(e, le().parse(s));\n case \"clipboard_text_received\":\n return t(e, ae().parse(s));\n case \"invoice_closed\":\n return t(e, ue().parse(s));\n case \"phone_requested\":\n return t(\"phone_requested\", he().parse(s));\n case \"custom_method_invoked\":\n return t(\"custom_method_invoked\", ce().parse(s));\n case \"write_access_requested\":\n return t(\"write_access_requested\", ge().parse(s));\n case \"main_button_pressed\":\n case \"back_button_pressed\":\n case \"settings_button_pressed\":\n case \"scan_qr_popup_closed\":\n case \"reload_iframe\":\n return t(e);\n default:\n return t(e, s);\n }\n } catch (n) {\n V.error(\"Error processing event:\", n);\n }\n }), r;\n}\nconst Q = \"telegram-mini-apps-cached-emitter\";\nfunction U() {\n const r = window;\n return r[Q] === void 0 && (r[Q] = we()), r[Q];\n}\nfunction $(r, t) {\n U().off(r, t);\n}\nfunction y(r, t) {\n return U().on(r, t), () => $(r, t);\n}\nfunction or(r, t) {\n return U().once(r, t), () => $(r, t);\n}\nfunction _e(r) {\n U().unsubscribe(r);\n}\nfunction ar(r) {\n return U().subscribe(r), () => _e(r);\n}\nfunction be(r, t) {\n const e = r.split(\".\"), s = t.split(\".\"), n = Math.max(e.length, s.length);\n for (let i = 0; i < n; i += 1) {\n const a = parseInt(e[i] || \"0\", 10), c = parseInt(s[i] || \"0\", 10);\n if (a !== c)\n return a > c ? 1 : -1;\n }\n return 0;\n}\nfunction P(r, t) {\n return be(r, t) <= 0;\n}\nfunction R(r, t, e) {\n if (typeof e == \"string\") {\n if (r === \"web_app_open_link\" && t === \"try_instant_view\")\n return P(\"6.4\", e);\n if (r === \"web_app_set_header_color\" && t === \"color\")\n return P(\"6.9\", e);\n }\n switch (r) {\n case \"web_app_open_tg_link\":\n case \"web_app_open_invoice\":\n case \"web_app_setup_back_button\":\n case \"web_app_set_background_color\":\n case \"web_app_set_header_color\":\n case \"web_app_trigger_haptic_feedback\":\n return P(\"6.1\", t);\n case \"web_app_open_popup\":\n return P(\"6.2\", t);\n case \"web_app_close_scan_qr_popup\":\n case \"web_app_open_scan_qr_popup\":\n case \"web_app_read_text_from_clipboard\":\n return P(\"6.4\", t);\n case \"web_app_switch_inline_query\":\n return P(\"6.7\", t);\n case \"web_app_invoke_custom_method\":\n case \"web_app_request_write_access\":\n case \"web_app_request_phone\":\n return P(\"6.9\", t);\n case \"web_app_setup_settings_button\":\n return P(\"6.10\", t);\n default:\n return !0;\n }\n}\nfunction E(r, t) {\n return (e) => R(t[e], r);\n}\nfunction St(r, t) {\n return (e) => {\n const [s, n] = t[e];\n return R(s, n, r);\n };\n}\nfunction d(r, t, e) {\n let s = {}, n;\n t === void 0 && e === void 0 ? s = {} : t !== void 0 && e !== void 0 ? (s = e, n = t) : t !== void 0 && (\"targetOrigin\" in t ? s = t : n = t);\n const { targetOrigin: i = ee() } = s;\n if (V.log(`Calling method \"${r}\"`, n), vt()) {\n window.parent.postMessage(JSON.stringify({\n eventType: r,\n eventData: n\n }), i);\n return;\n }\n if (Xt(window)) {\n window.external.notify(JSON.stringify({ eventType: r, eventData: n }));\n return;\n }\n if (te(window)) {\n window.TelegramWebviewProxy.postEvent(r, JSON.stringify(n));\n return;\n }\n throw new Error(\n \"Unable to determine current environment and possible way to send event.\"\n );\n}\nfunction me(r) {\n return (t, e) => {\n if (!R(t, r))\n throw new tt(t, r);\n if (H(e)) {\n let s;\n if (t === \"web_app_open_link\" && \"try_instant_view\" in e ? s = \"try_instant_view\" : t === \"web_app_set_header_color\" && \"color\" in e && (s = \"color\"), s && !R(t, s, r))\n throw new et(t, s, r);\n }\n return d(t, e);\n };\n}\nclass J extends Error {\n constructor(t) {\n super(`Async call timeout exceeded. Timeout: ${t}`), Object.setPrototypeOf(this, J.prototype);\n }\n}\nfunction cr(r) {\n return r instanceof J;\n}\nfunction ye(r) {\n return new Promise((t) => {\n setTimeout(t, r);\n });\n}\nfunction Ee(r) {\n return new Promise((t, e) => {\n setTimeout(e, r, new J(r));\n });\n}\nfunction xt(r, t) {\n return Promise.race([\n r(),\n Ee(t)\n ]);\n}\nfunction m(r, t, e, s) {\n let n, i, a, c;\n typeof t == \"string\" || Array.isArray(t) ? (a = Array.isArray(t) ? t : [t], n = e) : (i = t, a = Array.isArray(e) ? e : [e], n = s), H(i) && typeof i.req_id == \"string\" && (c = i.req_id);\n const { postEvent: p = d, timeout: h } = n || {}, g = n && \"capture\" in n ? n.capture : null, _ = () => new Promise((A, l) => {\n const C = a.map((v) => y(v, (M) => {\n c && (!H(M) || M.req_id !== c) || typeof g == \"function\" && !g(M) || (x(), A(M));\n })), x = () => C.forEach((v) => v());\n try {\n p(r, i);\n } catch (v) {\n x(), l(v);\n }\n });\n return typeof h == \"number\" ? xt(_, h) : _();\n}\nasync function O(r, t, e, s = {}) {\n const { result: n, error: i } = await m(\n \"web_app_invoke_custom_method\",\n {\n method: r,\n params: t,\n req_id: e\n },\n \"custom_method_invoked\",\n s\n );\n if (i)\n throw new Error(i);\n return n;\n}\nclass Ce {\n constructor(t, e, s = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"on\", (t, e) => t === \"click\" ? y(\"back_button_pressed\", e) : this.ee.on(t, e));\n /**\n * Removes event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"off\", (t, e) => t === \"click\" ? $(\"back_button_pressed\", e) : this.ee.off(t, e));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = s, this.state = new b({ isVisible: t }, this.ee), this.supports = E(e, {\n show: \"web_app_setup_back_button\",\n hide: \"web_app_setup_back_button\"\n });\n }\n set isVisible(t) {\n this.state.set(\"isVisible\", t), this.postEvent(\"web_app_setup_back_button\", { is_visible: t });\n }\n /**\n * True if BackButton is currently visible.\n */\n get isVisible() {\n return this.state.get(\"isVisible\");\n }\n /**\n * Hides the BackButton.\n */\n hide() {\n this.isVisible = !1;\n }\n /**\n * Shows the BackButton.\n */\n show() {\n this.isVisible = !0;\n }\n}\nfunction nt(r, t) {\n return r + (r.length > 0 && t.length > 0 ? ` ${t}` : t);\n}\nfunction ve(...r) {\n return r.reduce((t, e) => {\n let s = \"\";\n return typeof e == \"string\" ? s = e : typeof e == \"object\" && e !== null && (s = Object.entries(e).reduce((n, [i, a]) => a ? nt(n, i) : n, \"\")), nt(t, s);\n }, \"\");\n}\nfunction Pe(r) {\n return typeof r == \"object\" && r !== null && !Array.isArray(null);\n}\nfunction ur(...r) {\n return r.reduce((t, e) => (Pe(e) && Object.entries(e).forEach(([s, n]) => {\n const i = ve(t[s], n);\n i.length > 0 && (t[s] = i);\n }), t), {});\n}\nclass ke {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n this.postEvent = e, this.state = new b({ isConfirmationNeeded: t }, this.ee);\n }\n set isConfirmationNeeded(t) {\n this.state.set(\"isConfirmationNeeded\", t), this.postEvent(\"web_app_setup_closing_behavior\", { need_confirmation: t });\n }\n /**\n * Returns true, if the confirmation dialog enabled while the user is trying\n * to close the Mini App.\n */\n get isConfirmationNeeded() {\n return this.state.get(\"isConfirmationNeeded\");\n }\n /**\n * Disables the confirmation dialog while the user is trying to close the\n * Mini App.\n */\n disableConfirmation() {\n this.isConfirmationNeeded = !1;\n }\n /**\n * Enables the confirmation dialog while the user is trying to close the\n * Mini App.\n */\n enableConfirmation() {\n this.isConfirmationNeeded = !0;\n }\n}\nfunction it(r, t) {\n return r.reduce((e, s) => (e[s] = t, e), {});\n}\nclass Se {\n constructor(t, e, s = d) {\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.createRequestId = e, this.postEvent = s, this.supports = E(t, {\n delete: \"web_app_invoke_custom_method\",\n get: \"web_app_invoke_custom_method\",\n getKeys: \"web_app_invoke_custom_method\",\n set: \"web_app_invoke_custom_method\"\n });\n }\n /**\n * Deletes specified key or keys from the cloud storage.\n * @param keyOrKeys - key or keys to delete.\n * @param options - request execution options.\n */\n async delete(t, e = {}) {\n const s = Array.isArray(t) ? t : [t];\n s.length !== 0 && await O(\n \"deleteStorageValues\",\n { keys: s },\n this.createRequestId(),\n { ...e, postEvent: this.postEvent }\n );\n }\n /**\n * Returns list of all keys presented in the cloud storage.\n * @param options - request execution options.\n */\n async getKeys(t = {}) {\n const e = await O(\n \"getStorageKeys\",\n {},\n this.createRequestId(),\n { ...t, postEvent: this.postEvent }\n );\n return Bt().of(u()).parse(e);\n }\n async get(t, e = {}) {\n const s = Array.isArray(t) ? t : [t];\n if (s.length === 0)\n return it(s, \"\");\n const n = f(\n it(s, u())\n ), i = await O(\n \"getStorageValues\",\n { keys: s },\n this.createRequestId(),\n { ...e, postEvent: this.postEvent }\n ).then((a) => n.parse(a));\n return Array.isArray(t) ? i : i[t];\n }\n /**\n * Saves specified value by key.\n * @param key - storage key.\n * @param value - storage value.\n * @param options - request execution options.\n */\n async set(t, e, s = {}) {\n await O(\n \"saveStorageValue\",\n { key: t, value: e },\n this.createRequestId(),\n { ...s, postEvent: this.postEvent }\n );\n }\n}\nclass xe {\n constructor(t, e = d) {\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.supports = E(t, {\n impactOccurred: \"web_app_trigger_haptic_feedback\",\n notificationOccurred: \"web_app_trigger_haptic_feedback\",\n selectionChanged: \"web_app_trigger_haptic_feedback\"\n });\n }\n /**\n * A method tells that an impact occurred. The Telegram app may play the\n * appropriate haptics based on style value passed.\n * @param style - impact style.\n */\n impactOccurred(t) {\n this.postEvent(\"web_app_trigger_haptic_feedback\", {\n type: \"impact\",\n impact_style: t\n });\n }\n /**\n * A method tells that a task or action has succeeded, failed, or produced\n * a warning. The Telegram app may play the appropriate haptics based on\n * type value passed.\n * @param type - notification type.\n */\n notificationOccurred(t) {\n this.postEvent(\"web_app_trigger_haptic_feedback\", {\n type: \"notification\",\n notification_type: t\n });\n }\n /**\n * A method tells that the user has changed a selection. The Telegram app\n * may play the appropriate haptics.\n *\n * Do not use this feedback when the user makes or confirms a selection;\n * use it only when the selection changes.\n */\n selectionChanged() {\n this.postEvent(\"web_app_trigger_haptic_feedback\", { type: \"selection_change\" });\n }\n}\nfunction qe() {\n const r = document.createElement(\"style\");\n r.id = \"telegram-custom-styles\", document.head.appendChild(r), y(\"set_custom_style\", (t) => {\n r.innerHTML = t;\n });\n}\nfunction qt(r) {\n return `telegram-mini-apps-${r}`;\n}\nfunction T(r, t) {\n sessionStorage.setItem(qt(r), JSON.stringify(t));\n}\nfunction B(r) {\n const t = sessionStorage.getItem(qt(r));\n return t ? JSON.parse(t) : null;\n}\nfunction Ae(r, t, e) {\n const { isVisible: s = !1 } = r ? B(\"back-button\") || {} : {}, n = new Ce(s, t, e);\n return n.on(\"change\", () => {\n T(\"back-button\", { isVisible: n.isVisible });\n }), n;\n}\nfunction Ve(r, t) {\n const { isConfirmationNeeded: e = !1 } = r ? B(\"closing-behavior\") || {} : {}, s = new ke(e, t);\n return s.on(\"change\", () => T(\"closing-behavior\", {\n isConfirmationNeeded: s.isConfirmationNeeded\n })), s;\n}\nclass Re {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n o(this, \"postEvent\");\n /**\n * Adds new event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"on\", (t, e) => (\n // FIXME: Event 'main_button_pressed' is still being received on Android\n // even if the main button is disabled.\n // Issue: https://github.com/Telegram-Mini-Apps/tma.js/issues/3\n t === \"click\" ? y(\"main_button_pressed\", e) : this.ee.on(t, e)\n ));\n /**\n * Removes event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"off\", (t, e) => t === \"click\" ? $(\"main_button_pressed\", e) : this.ee.off(t, e));\n const {\n postEvent: e = d,\n text: s,\n textColor: n,\n backgroundColor: i,\n isEnabled: a,\n isVisible: c,\n isLoaderVisible: p\n } = t;\n this.postEvent = e, this.state = new b({\n backgroundColor: i,\n isEnabled: a,\n isVisible: c,\n isLoaderVisible: p,\n text: s,\n textColor: n\n }, this.ee);\n }\n /**\n * Sends current local state to Telegram application.\n */\n commit() {\n this.text !== \"\" && this.postEvent(\"web_app_setup_main_button\", {\n is_visible: this.isVisible,\n is_active: this.isEnabled,\n is_progress_visible: this.isLoaderVisible,\n text: this.text,\n color: this.backgroundColor,\n text_color: this.textColor\n });\n }\n set isEnabled(t) {\n this.setParams({ isEnabled: t });\n }\n /**\n * True if the Main Button is currently enabled.\n */\n get isEnabled() {\n return this.state.get(\"isEnabled\");\n }\n set isLoaderVisible(t) {\n this.setParams({ isLoaderVisible: t });\n }\n /**\n * True if the Main Button loader is currently visible.\n */\n get isLoaderVisible() {\n return this.state.get(\"isLoaderVisible\");\n }\n set isVisible(t) {\n this.setParams({ isVisible: t });\n }\n /**\n * True if the Main Button is currently visible.\n */\n get isVisible() {\n return this.state.get(\"isVisible\");\n }\n /**\n * The Main Button background color.\n */\n get backgroundColor() {\n return this.state.get(\"backgroundColor\");\n }\n /**\n * The Main Button text.\n */\n get text() {\n return this.state.get(\"text\");\n }\n /**\n * The Main Button text color.\n */\n get textColor() {\n return this.state.get(\"textColor\");\n }\n /**\n * Disables the Main Button.\n */\n disable() {\n return this.isEnabled = !1, this;\n }\n /**\n * Enables the Main Button.\n */\n enable() {\n return this.isEnabled = !0, this;\n }\n /**\n * Hides the Main Button.\n */\n hide() {\n return this.isVisible = !1, this;\n }\n /**\n * Hides the Main Button loader.\n */\n hideLoader() {\n return this.isLoaderVisible = !1, this;\n }\n /**\n * Shows the Main Button. Note that opening the Mini App from the attachment menu hides the\n * main button until the user interacts with the Mini App interface.\n */\n show() {\n return this.isVisible = !0, this;\n }\n /**\n * A method to show a loading indicator on the Main Button. It is recommended to display\n * loader if the action tied to the button may take a long time.\n */\n showLoader() {\n return this.isLoaderVisible = !0, this;\n }\n /**\n * Sets new Main Button text. Minimal length for text is 1 symbol, and maximum is 64 symbols.\n * @param text - new text.\n */\n setText(t) {\n return this.setParams({ text: t });\n }\n /**\n * Sets new Main Button text color.\n * @param textColor - new text color.\n */\n setTextColor(t) {\n return this.setParams({ textColor: t });\n }\n /**\n * Updates current Main Button color.\n * @param backgroundColor - color to set.\n */\n setBackgroundColor(t) {\n return this.setParams({ backgroundColor: t });\n }\n /**\n * Allows setting multiple Main Button parameters.\n * @param params - Main Button parameters.\n */\n setParams(t) {\n return this.state.set(t), this.commit(), this;\n }\n}\nfunction Ie(r, t, e, s) {\n const {\n backgroundColor: n = t,\n isEnabled: i = !1,\n isVisible: a = !1,\n isLoaderVisible: c = !1,\n textColor: p = e,\n text: h = \"\"\n } = r ? B(\"main-button\") || {} : {}, g = new Re({\n backgroundColor: n,\n isEnabled: i,\n isLoaderVisible: c,\n isVisible: a,\n postEvent: s,\n text: h,\n textColor: p\n }), _ = () => T(\"main-button\", {\n backgroundColor: g.backgroundColor,\n isEnabled: g.isEnabled,\n isLoaderVisible: g.isLoaderVisible,\n isVisible: g.isVisible,\n text: g.text,\n textColor: g.textColor\n });\n return g.on(\"change\", _), g;\n}\nconst Le = X({\n contact: f({\n userId: {\n type: q(),\n from: \"user_id\"\n },\n phoneNumber: {\n type: u(),\n from: \"phone_number\"\n },\n firstName: {\n type: u(),\n from: \"first_name\"\n },\n lastName: {\n type: u().optional(),\n from: \"last_name\"\n }\n }),\n authDate: {\n type: pt(),\n from: \"auth_date\"\n },\n hash: u()\n});\nclass $e {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n o(this, \"botInline\");\n o(this, \"postEvent\");\n o(this, \"createRequestId\");\n o(this, \"requestingPhoneAccess\", !1);\n o(this, \"requestingWriteAccess\", !1);\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n /**\n * Checks if specified method parameter is supported by current component.\n */\n o(this, \"supportsParam\");\n const {\n postEvent: e = d,\n headerColor: s,\n backgroundColor: n,\n version: i,\n botInline: a,\n createRequestId: c\n } = t, p = E(i, {\n requestPhoneAccess: \"web_app_request_phone\",\n requestWriteAccess: \"web_app_request_write_access\",\n switchInlineQuery: \"web_app_switch_inline_query\",\n setHeaderColor: \"web_app_set_header_color\",\n setBackgroundColor: \"web_app_set_background_color\"\n });\n this.postEvent = e, this.botInline = a, this.createRequestId = c, this.supports = (h) => !(!p(h) || h === \"switchInlineQuery\" && !a), this.state = new b({ backgroundColor: n, headerColor: s }, this.ee), this.supportsParam = St(i, {\n \"setHeaderColor.color\": [\"web_app_set_header_color\", \"color\"]\n });\n }\n /**\n * Attempts to get requested contact.\n */\n async getRequestedContact() {\n return O(\n \"getRequestedContact\",\n {},\n this.createRequestId(),\n {\n postEvent: this.postEvent,\n timeout: 1e4\n }\n ).then((t) => Le.parse(t));\n }\n /**\n * The Mini App background color.\n */\n get backgroundColor() {\n return this.state.get(\"backgroundColor\");\n }\n /**\n * Closes the Mini App.\n */\n close() {\n this.postEvent(\"web_app_close\");\n }\n /**\n * The Mini App header color. Could either be a header color key or RGB color.\n */\n get headerColor() {\n return this.state.get(\"headerColor\");\n }\n /**\n * True if Mini App is currently launched in bot inline mode.\n */\n get isBotInline() {\n return this.botInline;\n }\n /**\n * True if current Mini App background color recognized as dark.\n */\n get isDark() {\n return ft(this.backgroundColor);\n }\n /**\n * True if phone access is currently being requested.\n */\n get isRequestingPhoneAccess() {\n return this.requestingPhoneAccess;\n }\n /**\n * True if write access is currently being requested.\n */\n get isRequestingWriteAccess() {\n return this.requestingWriteAccess;\n }\n /**\n * Informs the Telegram app that the Mini App is ready to be displayed.\n *\n * It is recommended to call this method as early as possible, as soon as all essential\n * interface elements loaded. Once this method called, the loading placeholder is hidden\n * and the Mini App shown.\n *\n * If the method not called, the placeholder will be hidden only when the page fully loaded.\n */\n ready() {\n this.postEvent(\"web_app_ready\");\n }\n /**\n * Requests current user contact information. In contrary to requestPhoneAccess, this method\n * returns promise with contact information that rejects in case, user denied access, or request\n * failed.\n * @param options - additional options.\n */\n async requestContact({ timeout: t = 5e3 } = {}) {\n try {\n return await this.getRequestedContact();\n } catch {\n }\n if (await this.requestPhoneAccess() !== \"sent\")\n throw new Error(\"Access denied.\");\n const s = Date.now() + t;\n let n = 50;\n return xt(async () => {\n for (; Date.now() < s; ) {\n try {\n return await this.getRequestedContact();\n } catch {\n }\n await ye(n), n += 50;\n }\n throw new Error(\"Unable to retrieve requested contact.\");\n }, t);\n }\n /**\n * Requests current user phone access. Method returns promise, which resolves\n * status of the request. In case, user accepted the request, Mini App bot will receive\n * the according notification.\n *\n * To obtain the retrieved information instead, utilize the requestContact method.\n * @param options - additional options.\n * @see requestContact\n */\n requestPhoneAccess(t = {}) {\n if (this.requestingPhoneAccess)\n throw new Error(\"Phone access is already being requested.\");\n return this.requestingPhoneAccess = !0, m(\"web_app_request_phone\", \"phone_requested\", {\n ...t,\n postEvent: this.postEvent\n }).then((e) => e.status).finally(() => {\n this.requestingPhoneAccess = !1;\n });\n }\n /**\n * Requests write message access to current user.\n * @param options - additional options.\n */\n requestWriteAccess(t = {}) {\n if (this.requestingWriteAccess)\n throw new Error(\"Write access is already being requested.\");\n return this.requestingWriteAccess = !0, m(\"web_app_request_write_access\", \"write_access_requested\", {\n ...t,\n postEvent: this.postEvent\n }).then((e) => e.status).finally(() => {\n this.requestingWriteAccess = !1;\n });\n }\n /**\n * A method used to send data to the bot. When this method called, a service message sent to\n * the bot containing the data of the length up to 4096 bytes, and the Mini App closed. See the\n * field `web_app_data` in the class [Message](https://core.telegram.org/bots/api#message).\n *\n * This method is only available for Mini Apps launched via a Keyboard button.\n * @param data - data to send to bot.\n * @throws {Error} data has incorrect size.\n */\n sendData(t) {\n const { size: e } = new Blob([t]);\n if (e === 0 || e > 4096)\n throw new Error(`Passed data has incorrect size: ${e}`);\n this.postEvent(\"web_app_data_send\", { data: t });\n }\n /**\n * Updates current Mini App header color.\n * @param color - color key or RGB color.\n */\n setHeaderColor(t) {\n this.postEvent(\"web_app_set_header_color\", lt(t) ? { color: t } : { color_key: t }), this.state.set(\"headerColor\", t);\n }\n /**\n * Updates current Mini App background color.\n * @param color - RGB color.\n */\n setBackgroundColor(t) {\n this.postEvent(\"web_app_set_background_color\", { color: t }), this.state.set(\"backgroundColor\", t);\n }\n /**\n * Inserts the bot's username and the specified inline query in the current chat's input field.\n * Query may be empty, in which case only the bot's username will be inserted. The client prompts\n * the user to choose a specific chat, then opens that chat and inserts the bot's username and\n * the specified inline query in the input field.\n * @param text - text which should be inserted in the input after the current bot name. Max\n * length is 256 symbols.\n * @param chatTypes - List of chat types which could be chosen to send the message. Could be\n * empty list.\n */\n switchInlineQuery(t, e = []) {\n if (!this.supports(\"switchInlineQuery\") && !this.isBotInline)\n throw new Error(\"Method is unsupported because Mini App should be launched in inline mode.\");\n this.postEvent(\"web_app_switch_inline_query\", {\n query: t,\n chat_types: e\n });\n }\n}\nfunction Te(r, t, e, s, n, i) {\n const {\n backgroundColor: a = t,\n headerColor: c = \"bg_color\"\n } = r ? B(\"mini-app\") || {} : {}, p = new $e({\n headerColor: c,\n backgroundColor: a,\n version: e,\n botInline: s,\n createRequestId: n,\n postEvent: i\n }), h = () => T(\"mini-app\", {\n backgroundColor: p.backgroundColor,\n headerColor: p.headerColor\n });\n return p.on(\"change\", h), p;\n}\nfunction Be() {\n let r = 0;\n return () => (r += 1, r.toString());\n}\nclass De {\n constructor(t, e, s = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"on\", (t, e) => t === \"click\" ? y(\"settings_button_pressed\", e) : this.ee.on(t, e));\n /**\n * Removes event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"off\", (t, e) => t === \"click\" ? $(\"settings_button_pressed\", e) : this.ee.off(t, e));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = s, this.state = new b({ isVisible: t }, this.ee), this.supports = E(e, {\n show: \"web_app_setup_settings_button\",\n hide: \"web_app_setup_settings_button\"\n });\n }\n set isVisible(t) {\n this.state.set(\"isVisible\", t), this.postEvent(\"web_app_setup_settings_button\", { is_visible: t });\n }\n /**\n * True if SettingsButton is currently visible.\n */\n get isVisible() {\n return this.state.get(\"isVisible\");\n }\n /**\n * Hides the SettingsButton.\n */\n hide() {\n this.isVisible = !1;\n }\n /**\n * Shows the SettingsButton.\n */\n show() {\n this.isVisible = !0;\n }\n}\nfunction We(r, t, e) {\n const { isVisible: s = !1 } = r ? B(\"settings-button\") || {} : {}, n = new De(s, t, e);\n return n.on(\"change\", () => {\n T(\"settings-button\", { isVisible: n.isVisible });\n }), n;\n}\nfunction Oe(r) {\n const t = new Mt(r);\n return t.listen(), t;\n}\nfunction Ne(r) {\n return [\"macos\", \"tdesktop\", \"unigram\", \"web\", \"weba\"].includes(r);\n}\nasync function At(r) {\n const t = await m(\"web_app_request_viewport\", \"viewport_changed\", r);\n return {\n height: t.height,\n width: t.width,\n isExpanded: t.is_expanded,\n isStateStable: t.is_state_stable\n };\n}\nfunction D(r) {\n return r < 0 ? 0 : r;\n}\nclass He {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n o(this, \"postEvent\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n const {\n height: e,\n isExpanded: s,\n width: n,\n stableHeight: i,\n postEvent: a = d\n } = t;\n this.postEvent = a, this.state = new b({\n height: D(e),\n isExpanded: s,\n stableHeight: D(i),\n width: D(n)\n }, this.ee);\n }\n /**\n * Request viewport information from the Telegram application and updates current Viewport\n * instance.\n * @param options - options to request fresh data.\n */\n sync(t) {\n return At(t).then(({ height: e, isExpanded: s, width: n, isStateStable: i }) => {\n this.state.set({\n height: e,\n width: n,\n isExpanded: s,\n stableHeight: i ? e : this.state.get(\"stableHeight\")\n });\n });\n }\n /**\n * The current height of the visible area of the Mini App.\n *\n * The application can display just the top part of the Mini App, with its\n * lower part remaining outside the screen area. From this position, the\n * user can \"pull\" the Mini App to its maximum height, while the bot can do\n * the same by calling `expand` method. As the position of the Mini App\n * changes, the current height value of the visible area will be updated\n * in real time.\n *\n * Please note that the refresh rate of this value is not sufficient\n * to smoothly follow the lower border of the window. It should not be\n * used to pin interface elements to the bottom of the visible area. It's\n * more appropriate to use the value of the `stableHeight`\n * field for this purpose.\n */\n get height() {\n return this.state.get(\"height\");\n }\n /**\n * The height of the visible area of the Mini App in its last stable state.\n *\n * The application can display just the top part of the Mini App, with its\n * lower part remaining outside the screen area. From this position,\n * the user can \"pull\" the Mini App to its maximum height, while the bot can\n * do the same by calling `expand` method.\n *\n * Unlike the value of `height`, the value of `stableHeight`\n * does not change as the position of the Mini App changes with user\n * gestures or during animations. The value of `stableHeight`\n * will be updated after all gestures and animations are completed and\n * the Mini App reaches its final size.\n */\n get stableHeight() {\n return this.state.get(\"stableHeight\");\n }\n /**\n * Starts listening to viewport changes and applies them.\n * @returns Function to stop listening.\n */\n listen() {\n return y(\"viewport_changed\", (t) => {\n const {\n height: e,\n width: s,\n is_expanded: n,\n is_state_stable: i\n } = t, a = {\n height: D(e),\n isExpanded: n,\n width: D(s)\n };\n i && (a.stableHeight = a.height), this.state.set(a);\n });\n }\n /**\n * Returns true if the Mini App is expanded to the maximum available height.\n * Otherwise, if the Mini App occupies part of the screen and can be expanded\n * to the full height using `expand` method.\n * @see expand\n */\n get isExpanded() {\n return this.state.get(\"isExpanded\");\n }\n /**\n * Current viewport width.\n */\n get width() {\n return this.state.get(\"width\");\n }\n /**\n * A method that expands the Mini App to the maximum available height. To\n * find out if the Mini App is expanded to the maximum height, refer to the\n * value of the `isExpanded`.\n * @see isExpanded\n */\n expand() {\n this.postEvent(\"web_app_expand\"), this.state.set(\"isExpanded\", !0);\n }\n /**\n * Returns true in case current viewport height is stable and is not going to\n * change in the next moment.\n */\n get isStable() {\n return this.stableHeight === this.height;\n }\n}\nfunction j(r) {\n const t = new He(r);\n return t.on(\"change\", () => T(\"viewport\", {\n height: t.height,\n isExpanded: t.isExpanded,\n stableHeight: t.stableHeight,\n width: t.width\n })), t.listen(), t;\n}\nfunction Ue(r, t, e, s) {\n const n = r ? B(\"viewport\") : null;\n if (n)\n return j({ ...n, postEvent: e });\n if (Ne(t))\n return j({\n height: window.innerHeight,\n isExpanded: !0,\n postEvent: e,\n stableHeight: window.innerHeight,\n width: window.innerWidth\n });\n if (s)\n return At({\n postEvent: e,\n timeout: 5e3\n }).then(({ height: a, isStateStable: c, ...p }) => j({\n ...p,\n height: a,\n stableHeight: c ? a : 0\n }));\n const i = j({\n width: 0,\n height: 0,\n isExpanded: !1,\n postEvent: e,\n stableHeight: 0\n });\n return i.sync({ postEvent: e, timeout: 5e3 }).catch((a) => {\n console.error(\"Unable to actualize viewport state\", a);\n }), i;\n}\nfunction S(r, t) {\n document.documentElement.style.setProperty(r, t);\n}\nfunction Me(r, t) {\n const e = () => {\n S(\"--tg-background-color\", r.backgroundColor);\n }, s = () => {\n const {\n backgroundColor: n,\n secondaryBackgroundColor: i\n } = t;\n r.headerColor === \"bg_color\" ? n && S(\"--tg-header-color\", n) : r.headerColor === \"secondary_bg_color\" ? i && S(\"--tg-header-color\", i) : S(\"--tg-header-color\", r.headerColor);\n };\n t.on(\"change\", s), r.on(\"change:backgroundColor\", e), r.on(\"change:headerColor\", s), e(), s();\n}\nfunction je(r) {\n const t = () => {\n const e = r.getState();\n Object.entries(e).forEach(([s, n]) => {\n if (n) {\n const i = s.replace(/[A-Z]/g, (a) => `-${a.toLowerCase()}`);\n S(`--tg-theme-${i}`, n);\n }\n });\n };\n r.on(\"change\", t), t();\n}\nfunction ot(r) {\n const t = () => S(\"--tg-viewport-height\", `${r.height}px`), e = () => S(\"--tg-viewport-width\", `${r.width}px`), s = () => S(\"--tg-viewport-height\", `${r.stableHeight}px`);\n r.on(\"change:height\", t), r.on(\"change:width\", e), r.on(\"change:stableHeight\", s), t(), e(), s();\n}\nfunction Ge(r) {\n return typeof r == \"object\" ? r : r ? {\n themeParams: !0,\n viewport: !0,\n miniApp: !0\n } : {};\n}\nfunction at(r, t, e, s) {\n const n = Ge(r);\n n.miniApp && Me(t, e), n.themeParams && je(e), n.viewport && (s instanceof Promise ? s.then(ot) : ot(s));\n}\nfunction Fe(r) {\n const { hostname: t, pathname: e } = new URL(r, window.location.href);\n if (t !== \"t.me\")\n throw new Error(`Incorrect hostname: ${t}`);\n const s = e.match(/^\\/(\\$|invoice\\/)([A-Za-z0-9\\-_=]+)$/);\n if (s === null)\n throw new Error('Link pathname has incorrect format. Expected to receive \"/invoice/{slug}\" or \"/${slug}\"');\n return s[2];\n}\nclass ze {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.state = new b({ isOpened: !1 }, this.ee), this.supports = E(t, { open: \"web_app_open_invoice\" });\n }\n set isOpened(t) {\n this.state.set(\"isOpened\", t);\n }\n /**\n * True if invoice is currently opened.\n */\n get isOpened() {\n return this.state.get(\"isOpened\");\n }\n async open(t, e) {\n if (this.isOpened)\n throw new Error(\"Invoice is already opened\");\n const s = e ? Fe(t) : t;\n this.isOpened = !0;\n try {\n return (await m(\n \"web_app_open_invoice\",\n { slug: s },\n \"invoice_closed\",\n {\n postEvent: this.postEvent,\n capture(i) {\n return s === i.slug;\n }\n }\n )).status;\n } finally {\n this.isOpened = !1;\n }\n }\n}\nfunction Je(r) {\n const t = r.message.trim(), e = (r.title || \"\").trim(), s = r.buttons || [];\n let n;\n if (e.length > 64)\n throw new Error(`Title has incorrect size: ${e.length}`);\n if (t.length === 0 || t.length > 256)\n throw new Error(`Message has incorrect size: ${t.length}`);\n if (s.length > 3)\n throw new Error(`Buttons have incorrect size: ${s.length}`);\n return s.length === 0 ? n = [{ type: \"close\", id: \"\" }] : n = s.map((i) => {\n const { id: a = \"\" } = i;\n if (a.length > 64)\n throw new Error(`Button ID has incorrect size: ${a}`);\n if (i.type === void 0 || i.type === \"default\" || i.type === \"destructive\") {\n const c = i.text.trim();\n if (c.length === 0 || c.length > 64) {\n const p = i.type || \"default\";\n throw new Error(`Button text with type \"${p}\" has incorrect size: ${i.text.length}`);\n }\n return { ...i, text: c, id: a };\n }\n return { ...i, id: a };\n }), { title: e, message: t, buttons: n };\n}\nclass Qe {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.state = new b({ isOpened: !1 }, this.ee), this.supports = E(t, { open: \"web_app_open_popup\" });\n }\n set isOpened(t) {\n this.state.set(\"isOpened\", t);\n }\n /**\n * True if popup is currently opened.\n */\n get isOpened() {\n return this.state.get(\"isOpened\");\n }\n /**\n * A method that shows a native popup described by the `params` argument.\n * Promise will be resolved when popup is closed. Resolved value will have\n * an identifier of pressed button.\n *\n * In case, user clicked outside the popup or clicked top right popup close\n * button, null will be returned.\n *\n * FIXME: In desktop, this function may work incorrectly.\n * Issue: https://github.com/Telegram-Mini-Apps/tma.js/issues/7\n * @param options - popup parameters.\n * @throws {Error} Popup is already opened.\n */\n open(t) {\n if (this.isOpened)\n throw new Error(\"Popup is already opened.\");\n return this.isOpened = !0, m(\n \"web_app_open_popup\",\n Je(t),\n \"popup_closed\",\n { postEvent: this.postEvent }\n ).then(({ button_id: e = null }) => e).finally(() => {\n this.isOpened = !1;\n });\n }\n}\nclass Ze {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.state = new b({ isOpened: !1 }, this.ee), this.supports = E(t, {\n close: \"web_app_close_scan_qr_popup\",\n open: \"web_app_open_scan_qr_popup\"\n });\n }\n /**\n * Closes scanner.\n */\n close() {\n this.postEvent(\"web_app_close_scan_qr_popup\"), this.isOpened = !1;\n }\n set isOpened(t) {\n this.state.set(\"isOpened\", t);\n }\n /**\n * Returns true in case, QR scanner is currently opened.\n */\n get isOpened() {\n return this.state.get(\"isOpened\");\n }\n /**\n * Opens scanner with specified title shown to user. Method returns promise\n * with scanned QR content in case, it was scanned. It will contain null in\n * case, scanner was closed.\n * @param text - title to display.\n */\n async open(t) {\n if (this.isOpened)\n throw new Error(\"QR scanner is already opened.\");\n this.isOpened = !0;\n try {\n const e = await m(\n \"web_app_open_scan_qr_popup\",\n { text: t },\n [\"qr_text_received\", \"scan_qr_popup_closed\"],\n { postEvent: this.postEvent }\n );\n return typeof e == \"object\" && typeof e.data == \"string\" ? e.data : null;\n } finally {\n this.isOpened = !1;\n }\n }\n}\nclass Ke {\n constructor(t, e, s = d) {\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n /**\n * Checks if specified method parameter is supported by current component.\n */\n o(this, \"supportsParam\");\n this.version = t, this.createRequestId = e, this.postEvent = s, this.supports = E(t, {\n readTextFromClipboard: \"web_app_read_text_from_clipboard\"\n }), this.supportsParam = St(t, {\n \"openLink.tryInstantView\": [\"web_app_open_link\", \"try_instant_view\"]\n });\n }\n /**\n * Opens a link in an external browser. The Mini App will not be closed.\n *\n * Note that this method can be called only in response to the user\n * interaction with the Mini App interface (e.g. click inside the Mini App\n * or on the main button).\n * @param url - URL to be opened.\n * @param tryInstantView\n */\n openLink(t, e) {\n const s = new URL(t, window.location.href).toString();\n if (!R(\"web_app_open_link\", this.version)) {\n window.open(s, \"_blank\");\n return;\n }\n this.postEvent(\"web_app_open_link\", {\n url: s,\n ...typeof e == \"boolean\" ? { try_instant_view: e } : {}\n });\n }\n /**\n * Opens a Telegram link inside Telegram app. The Mini App will be closed. It expects passing\n * link in full format, with hostname \"t.me\".\n * @param url - URL to be opened.\n * @throws {Error} URL has not allowed hostname.\n */\n openTelegramLink(t) {\n const {\n hostname: e,\n pathname: s,\n search: n\n } = new URL(t, window.location.href);\n if (e !== \"t.me\")\n throw new Error(`URL has not allowed hostname: ${e}. Only \"t.me\" is allowed`);\n if (!R(\"web_app_open_tg_link\", this.version)) {\n window.location.href = t;\n return;\n }\n this.postEvent(\"web_app_open_tg_link\", { path_full: s + n });\n }\n /**\n * Reads text from clipboard and returns string or null. null is returned\n * in cases:\n * - Value in clipboard is not text\n * - Access to clipboard is not allowed\n */\n readTextFromClipboard() {\n return m(\n \"web_app_read_text_from_clipboard\",\n { req_id: this.createRequestId() },\n \"clipboard_text_received\",\n { postEvent: this.postEvent }\n ).then(({ data: t = null }) => t);\n }\n}\nfunction hr(r = {}) {\n const {\n async: t = !1,\n complete: e = t,\n cssVars: s = !1,\n acceptCustomStyles: n = !1\n } = r;\n try {\n const {\n launchParams: {\n initData: i,\n initDataRaw: a,\n version: c,\n platform: p,\n themeParams: h,\n botInline: g = !1\n },\n isPageReload: _\n } = Ct(), A = Be(), l = me(c);\n vt() && (n && qe(), l(\"iframe_ready\", { reload_supported: !0 }), y(\"reload_iframe\", () => window.location.reload()));\n const C = {\n backButton: Ae(_, c, l),\n closingBehavior: Ve(_, l),\n cloudStorage: new Se(c, A, l),\n createRequestId: A,\n hapticFeedback: new xe(c, l),\n invoice: new ze(c, l),\n mainButton: Ie(\n _,\n h.buttonColor || \"#000000\",\n h.buttonTextColor || \"#ffffff\",\n l\n ),\n miniApp: Te(\n _,\n h.backgroundColor || \"#ffffff\",\n c,\n g,\n A,\n l\n ),\n popup: new Qe(c, l),\n postEvent: l,\n qrScanner: new Ze(c, l),\n settingsButton: We(_, c, l),\n themeParams: Oe(h),\n utils: new Ke(c, A, l),\n ...i ? {\n initData: new Ot(i),\n initDataRaw: a\n } : {}\n }, x = Ue(_, p, l, e);\n return x instanceof Promise || e ? Promise.resolve(x).then((v) => (at(\n s,\n C.miniApp,\n C.themeParams,\n v\n ), { ...C, viewport: v })) : (at(\n s,\n C.miniApp,\n C.themeParams,\n x\n ), { ...C, viewport: x });\n } catch (i) {\n if (e)\n return Promise.reject(i);\n throw i;\n }\n}\nfunction W(r, t) {\n return r.startsWith(t) ? r : `${t}${r}`;\n}\nfunction pr(r) {\n const t = r.match(/#(.+)/);\n return t ? t[1] : null;\n}\nasync function N(r) {\n return r === 0 ? !0 : Promise.race([\n new Promise((t) => {\n window.addEventListener(\"popstate\", function e() {\n window.removeEventListener(\"popstate\", e), t(!0);\n }), window.history.go(r);\n }),\n // Usually, it takes about 1ms to emit this event, but we use some buffer.\n new Promise((t) => {\n setTimeout(t, 50, !1);\n })\n ]);\n}\nasync function Ye() {\n if (window.history.length <= 1 || (window.history.pushState(null, \"\"), await N(1 - window.history.length)))\n return;\n let t = await N(-1);\n for (; t; )\n t = await N(-1);\n}\nclass Xe {\n constructor(t, e, {\n debug: s = !1,\n loggerPrefix: n = \"Navigator\"\n }) {\n o(this, \"logger\");\n o(this, \"entries\");\n if (this.entriesCursor = e, t.length === 0)\n throw new Error(\"Entries list should not be empty.\");\n if (e >= t.length)\n throw new Error(\"Cursor should be less than entries count.\");\n this.entries = t.map(({ pathname: i = \"\", search: a, hash: c }) => {\n if (!i.startsWith(\"/\") && i.length > 0)\n throw new Error('Pathname should start with \"/\"');\n return {\n pathname: W(i, \"/\"),\n search: a ? W(a, \"?\") : \"\",\n hash: c ? W(c, \"#\") : \"\"\n };\n }), this.logger = new Pt(`[${n}]`, s);\n }\n /**\n * Converts entry to the navigation entry.\n * @param entry - entry data\n */\n formatEntry(t) {\n let e;\n if (typeof t == \"string\")\n e = t;\n else {\n const {\n pathname: a = \"\",\n search: c,\n hash: p\n } = t;\n e = a + (c ? W(c, \"?\") : \"\") + (p ? W(p, \"#\") : \"\");\n }\n const {\n pathname: s,\n search: n,\n hash: i\n } = new URL(e, `https://localhost${this.path}`);\n return {\n pathname: s,\n search: n,\n hash: i\n };\n }\n /**\n * Current entry.\n */\n get entry() {\n return this.entries[this.entriesCursor];\n }\n /**\n * Goes back in history.\n */\n back() {\n return this.go(-1);\n }\n /**\n * Current entries cursor.\n */\n get cursor() {\n return this.entriesCursor;\n }\n /**\n * True if navigator can go back.\n */\n get canGoBack() {\n return this.entriesCursor > 0;\n }\n /**\n * True if navigator can go forward.\n */\n get canGoForward() {\n return this.entriesCursor !== this.entries.length - 1;\n }\n /**\n * Goes forward in history.\n */\n forward() {\n return this.go(1);\n }\n /**\n * Moves entries cursor by specified delta.\n * @param delta - cursor delta.\n */\n go(t) {\n this.logger.log(`called go(${t})`);\n const e = Math.min(\n this.entries.length - 1,\n Math.max(this.entriesCursor + t, 0)\n );\n if (this.entriesCursor === e)\n return this.performGo({\n updated: !1,\n delta: t\n });\n const s = this.entry;\n this.entriesCursor = e;\n const n = this.entry;\n return this.logger.log(\"State changed\", { before: s, after: n }), this.performGo({\n updated: !0,\n delta: t,\n before: s,\n after: n\n });\n }\n /**\n * Returns copy of navigator entries.\n */\n getEntries() {\n return this.entries.map((t) => ({ ...t }));\n }\n /**\n * Current hash.\n * @example\n * \"\", \"#\", \"#hash\"\n */\n get hash() {\n return this.entry.hash;\n }\n /**\n * Pushes new entry. Method replaces all entries after the current one with the inserted.\n * @param entry - entry data.\n *\n * @example Pushing absolute pathname.\n * push(\"/absolute-path\"); // \"/absolute-path\"\n *\n * @example Pushing relative pathname.\n * // Pushing relative path replaces N last path parts, where N is pushed pathname parts count.\n * // Pushing empty path is recognized as relative, but not replacing the last pathname part.\n * push(\"relative\"); // \"/home/root\" -> \"/home/relative\"\n *\n * @example Pushing query parameters.\n * push(\"/absolute?my-param=1\"); // \"/home\" -> \"/absolute?my-param=1\"\n * push(\"relative?my-param=1\"); // \"/home/root\" -> \"/home/relative?my-param=1\"\n * push(\"?my-param=1\"); // \"/home\" -> \"/home?my-param=1\"\n *\n * @example Pushing hash.\n * push(\"#my-hash\"); // \"/home\" -> \"/home#my-hash\"\n * push(\"johny#my-hash\"); // \"/home/root\" -> \"/home/johny#my-hash\"\n */\n push(t) {\n this.entriesCursor !== this.entries.length - 1 && this.entries.splice(this.entriesCursor + 1);\n const e = this.formatEntry(t), s = this.entry;\n this.entriesCursor += 1, this.entries[this.entriesCursor] = e;\n const n = this.entry;\n return this.logger.log(\"State changed\", { before: s, after: n }), this.performPush({\n before: s,\n after: n\n });\n }\n /**\n * Current full path including pathname, query parameters and hash.\n */\n get path() {\n return `${this.pathname}${this.search}${this.hash}`;\n }\n /**\n * Current pathname.\n * @example\n * \"/\", \"/abc\"\n */\n get pathname() {\n return this.entry.pathname;\n }\n /**\n * Replaces current entry. Has the same logic as `push` method.\n * @param entry - entry data.\n * @see push\n * @returns True if changes were done.\n */\n replace(t) {\n const e = this.formatEntry(t);\n if (this.search === e.search && this.pathname === e.pathname && this.hash === e.hash)\n return this.performReplace({\n updated: !1,\n entry: e\n });\n const s = this.entry;\n this.entries[this.entriesCursor] = e;\n const n = this.entry;\n return this.logger.log(\"State changed\", { before: s, after: n }), this.performReplace({\n updated: !0,\n before: s,\n after: n\n });\n }\n /**\n * Current query parameters.\n * @example\n * \"\", \"?\", \"?a=1\"\n */\n get search() {\n return this.entry.search;\n }\n}\nconst ct = 0, Z = 1, K = 2;\nclass Vt extends Xe {\n constructor(e, s, n = {}) {\n super(e, s, {\n ...n,\n loggerPrefix: \"HashNavigator\"\n });\n o(this, \"ee\", new w());\n o(this, \"attached\", !1);\n /**\n * Handles window \"popstate\" event.\n * @param state - event state.\n */\n o(this, \"onPopState\", async ({ state: e }) => {\n if (this.logger.log('\"popstate\" event received. State:', e), e === null)\n return this.push(window.location.hash.slice(1));\n if (e === ct) {\n this.logger.log(\"Void reached. Moving history forward\"), window.history.forward();\n return;\n }\n if (e === Z)\n return this.back();\n if (e === K)\n return this.forward();\n });\n o(this, \"back\", () => super.back());\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n }\n /**\n * Creates navigator from current window location hash.\n * @param options - options passed to constructor.\n */\n static fromLocation(e) {\n const {\n search: s,\n pathname: n,\n hash: i\n } = new URL(\n window.location.hash.slice(1),\n window.location.href\n );\n return new Vt([{ search: s, pathname: n, hash: i }], 0, e);\n }\n async performGo(e) {\n e.updated && (this.attached && await this.syncHistory(), this.emitChanged(e.before, e.after));\n }\n async performPush({ before: e, after: s }) {\n this.attached && await this.syncHistory(), this.emitChanged(e, s);\n }\n async performReplace(e) {\n e.updated && (this.attached && window.history.replaceState(null, \"\", `#${this.path}`), this.emitChanged(e.before, e.after));\n }\n /**\n * Synchronizes current navigator state with browser history.\n */\n async syncHistory() {\n window.removeEventListener(\"popstate\", this.onPopState);\n const e = `#${this.path}`;\n await Ye(), d(\"web_app_setup_back_button\", { is_visible: this.canGoBack }), this.canGoBack && this.canGoForward ? (this.logger.log(\"Setting up history: [<-, *, ->]\"), window.history.replaceState(Z, \"\"), window.history.pushState(null, \"\", e), window.history.pushState(K, \"\"), await N(-1)) : this.canGoBack ? (this.logger.log(\"Setting up history: [<-, *]\"), window.history.replaceState(Z, \"\"), window.history.pushState(null, \"\", e)) : this.canGoForward ? (this.logger.log(\"Setting up history: [*, ->]\"), window.history.replaceState(null, e), window.history.pushState(K, \"\"), await N(-1)) : (this.logger.log(\"Setting up history: [~, *]\"), window.history.replaceState(ct, \"\"), window.history.pushState(null, \"\", e)), window.addEventListener(\"popstate\", this.onPopState);\n }\n emitChanged(e, s) {\n this.ee.emit(\"change\", {\n navigator: this,\n from: e,\n to: s\n });\n }\n /**\n * Attaches current navigator to the browser history allowing navigator to manipulate it.\n */\n async attach() {\n if (!this.attached)\n return this.logger.log(\"Attaching\", this), this.attached = !0, y(\"back_button_pressed\", this.back), this.syncHistory();\n }\n /**\n * Detaches current navigator from the browser history.\n */\n detach() {\n this.attached && (this.logger.log(\"Detaching\", this), this.attached = !1, window.removeEventListener(\"popstate\", this.onPopState), $(\"back_button_pressed\", this.back));\n }\n}\nexport {\n Ce as BackButton,\n ke as ClosingBehavior,\n Se as CloudStorage,\n xe as HapticFeedback,\n Vt as HashNavigator,\n Ot as InitData,\n ze as Invoice,\n Re as MainButton,\n tt as MethodUnsupportedError,\n $e as MiniApp,\n Xe as Navigator,\n et as ParameterUnsupportedError,\n F as ParseError,\n G as ParseSchemaFieldError,\n Qe as Popup,\n Ze as QRScanner,\n De as SettingsButton,\n Mt as ThemeParams,\n J as TimeoutError,\n Ke as Utils,\n He as Viewport,\n Bt as array,\n k as boolean,\n Wt as chatParser,\n ve as classNames,\n be as compareVersions,\n me as createPostEvent,\n pt as date,\n pr as getHash,\n hr as init,\n wt as initDataParser,\n O as invokeCustomMethod,\n ft as isColorDark,\n vt as isIframe,\n lt as isRGB,\n Dt as isRGBShort,\n H as isRecord,\n Ne as isStableViewportPlatform,\n sr as isTMA,\n cr as isTimeoutError,\n f as json,\n mt as launchParamsParser,\n ur as mergeClassNames,\n q as number,\n $ as off,\n y as on,\n or as once,\n er as parseInitData,\n jt as parseLaunchParams,\n se as parseMessage,\n bt as parseThemeParams,\n d as postEvent,\n m as request,\n rr as requestThemeParams,\n At as requestViewport,\n Ct as retrieveLaunchData,\n gt as rgb,\n X as searchParams,\n Jt as serializeLaunchParams,\n Ut as serializeThemeParams,\n nr as setDebug,\n ir as setTargetOrigin,\n u as string,\n ar as subscribe,\n R as supports,\n _t as themeParamsParser,\n dt as toRGB,\n _e as unsubscribe,\n rt as userParser,\n xt as withTimeout\n};\n//# sourceMappingURL=index.mjs.map\n","import { createHmac } from 'node:crypto';\nimport { URLSearchParams } from 'node:url';\n\nexport interface ValidateOptions {\n /**\n * Time in seconds which states, how long from creation time is init data\n * considered valid.\n *\n * In other words, in case, when authDate + expiresIn is before current\n * time, init data recognized as expired.\n *\n * In case, this value is equal to 0, function does not check init data\n * expiration.\n * @default 86400 (1 day)\n */\n expiresIn?: number;\n}\n\n/**\n * Validates passed init data presented as search params converted to string,\n * or its object presentation.\n *\n * @param sp - search parameters.\n * @param token - Telegram bot secret token.\n * @param options - validation options.\n * @see toSearchParams\n * @throws {TypeError} \"hash\" should be string.\n * @throws {Error} \"hash\" is empty or not found.\n * @throws {TypeError} \"auth_date\" should be string.\n * @throws {TypeError} \"auth_date\" does not represent integer.\n * @throws {Error} \"auth_date\" is empty or not found.\n * @throws {Error} Init data expired.\n * @throws {Error} Sign invalid.\n */\nexport function validate(\n sp: string | URLSearchParams,\n token: string,\n options: ValidateOptions = {},\n): void {\n const searchParams = typeof sp === 'string' ? new URLSearchParams(sp) : sp;\n\n // Init data creation time.\n let authDate = new Date(0);\n\n // Init data sign.\n let hash = '';\n\n // All search params pairs presented as `k=v`.\n const pairs: string[] = [];\n\n // Iterate over all key-value pairs of parsed parameters and find required\n // parameters.\n searchParams.forEach((value, key) => {\n if (key === 'hash') {\n hash = value;\n return;\n }\n\n if (key === 'auth_date') {\n const authDateNum = parseInt(value, 10);\n\n if (Number.isNaN(authDateNum)) {\n throw new TypeError('\"auth_date\" should present integer');\n }\n authDate = new Date(authDateNum * 1000);\n }\n\n // Append new pair.\n pairs.push(`${key}=${value}`);\n });\n\n // Hash and auth date always required.\n if (hash.length === 0) {\n throw new Error('\"hash\" is empty or not found');\n }\n\n if (authDate.getTime() === 0) {\n throw new Error('\"auth_date\" is empty or not found');\n }\n\n // In case, expiration time passed, we do additional parameters check.\n const { expiresIn = 86400 } = options;\n\n if (expiresIn > 0) {\n // Check if init data expired.\n if (authDate.getTime() + expiresIn * 1000 < new Date().getTime()) {\n throw new Error('Init data expired');\n }\n }\n\n // According to docs, we sort all the pairs in alphabetical order.\n pairs.sort();\n\n // Compute sign.\n const computedHash = createHmac(\n 'sha256',\n createHmac('sha256', 'WebAppData').update(token).digest(),\n )\n .update(pairs.join('\\n'))\n .digest()\n .toString('hex');\n\n // In case, our sign is not equal to found one, we should throw an error.\n if (computedHash !== hash) {\n throw new Error('Signature is invalid');\n }\n}\n"],"names":["Rt","It","r","e","o","I","F","s","n","z","L","G","ht","i","a","h","c","p","k","q","pt","Y","f","u","X","Wt","rt","wt","er","validate","sp","token","options","searchParams","URLSearchParams","authDate","hash","pairs","value","key","authDateNum","expiresIn","createHmac"],"mappings":"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"}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../sdk/dist/index.mjs","../src/validate.ts"],"sourcesContent":["var Rt = Object.defineProperty;\nvar It = (r, t, e) => t in r ? Rt(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;\nvar o = (r, t, e) => (It(r, typeof t != \"symbol\" ? t + \"\" : t, e), e);\nfunction H(r) {\n return typeof r == \"object\" && r !== null && !Array.isArray(r);\n}\nfunction ut() {\n return performance.getEntriesByType(\"navigation\")[0] || null;\n}\nfunction Lt() {\n const r = ut();\n return r ? r.type === \"reload\" : null;\n}\nfunction I() {\n return new TypeError(\"Value has unexpected type\");\n}\nclass F extends Error {\n constructor(e, { cause: s, type: n } = {}) {\n super(`Unable to parse value${n ? ` as ${n}` : \"\"}`, { cause: s });\n /**\n * Parser name.\n */\n o(this, \"type\");\n this.value = e, Object.setPrototypeOf(this, F.prototype), this.type = n;\n }\n}\nclass z {\n constructor(t, e, s) {\n this.parser = t, this.isOptional = e, this.type = s;\n }\n parse(t) {\n if (!(this.isOptional && t === void 0))\n try {\n return this.parser(t);\n } catch (e) {\n throw new F(t, { type: this.type, cause: e });\n }\n }\n optional() {\n return this.isOptional = !0, this;\n }\n}\nfunction $t(r) {\n if (Array.isArray(r))\n return r;\n if (typeof r == \"string\")\n try {\n const t = JSON.parse(r);\n if (Array.isArray(t))\n return t;\n } catch {\n }\n throw I();\n}\nclass Tt extends z {\n constructor(e, s, n) {\n super($t, s, n);\n o(this, \"itemParser\");\n this.itemParser = typeof e == \"function\" ? e : e.parse.bind(e);\n }\n parse(e) {\n const s = super.parse(e);\n return s === void 0 ? s : s.map(this.itemParser);\n }\n of(e) {\n return this.itemParser = typeof e == \"function\" ? e : e.parse.bind(e), this;\n }\n}\nfunction L(r, t) {\n return () => new z(r, !1, t);\n}\nclass G extends Error {\n constructor(t, { cause: e, type: s } = {}) {\n super(`Unable to parse field \"${t}\"${s ? ` as ${s}` : \"\"}`, { cause: e }), Object.setPrototypeOf(this, G.prototype);\n }\n}\nfunction ht(r, t) {\n const e = {};\n for (const s in r) {\n const n = r[s];\n if (!n)\n continue;\n let i, a;\n if (typeof n == \"function\" || \"parse\" in n)\n i = s, a = typeof n == \"function\" ? n : n.parse.bind(n);\n else {\n const { type: h } = n;\n i = n.from || s, a = typeof h == \"function\" ? h : h.parse.bind(h);\n }\n let c;\n const p = t(i);\n try {\n c = a(p);\n } catch (h) {\n throw h instanceof F ? new G(i, {\n type: h.type,\n cause: h\n }) : new G(i, { cause: h });\n }\n c !== void 0 && (e[s] = c);\n }\n return e;\n}\nfunction Bt(r) {\n return new Tt((t) => t, !1, r);\n}\nconst k = L((r) => {\n if (typeof r == \"boolean\")\n return r;\n const t = String(r);\n if (t === \"1\" || t === \"true\")\n return !0;\n if (t === \"0\" || t === \"false\")\n return !1;\n throw I();\n}, \"boolean\"), q = L((r) => {\n if (typeof r == \"number\")\n return r;\n if (typeof r == \"string\") {\n const t = Number(r);\n if (!Number.isNaN(t))\n return t;\n }\n throw I();\n}, \"number\"), pt = L((r) => r instanceof Date ? r : new Date(q().parse(r) * 1e3), \"Date\");\nfunction Y(r) {\n let t = r;\n if (typeof t == \"string\" && (t = JSON.parse(t)), typeof t != \"object\" || t === null || Array.isArray(t))\n throw I();\n return t;\n}\nfunction f(r, t) {\n return new z((e) => {\n const s = Y(e);\n return ht(r, (n) => s[n]);\n }, !1, t);\n}\nfunction lt(r) {\n return /^#[\\da-f]{6}$/i.test(r);\n}\nfunction Dt(r) {\n return /^#[\\da-f]{3}$/i.test(r);\n}\nfunction dt(r) {\n const t = r.replace(/\\s/g, \"\").toLowerCase();\n if (lt(t))\n return t;\n if (Dt(t)) {\n let s = \"#\";\n for (let n = 0; n < 3; n += 1)\n s += t[1 + n].repeat(2);\n return s;\n }\n const e = t.match(/^rgb\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)$/) || t.match(/^rgba\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3}),\\d{1,3}\\)$/);\n if (e === null)\n throw new Error(`Value \"${r}\" does not satisfy any of known RGB formats.`);\n return e.slice(1).reduce((s, n) => {\n const i = parseInt(n, 10).toString(16);\n return s + (i.length === 1 ? \"0\" : \"\") + i;\n }, \"#\");\n}\nfunction ft(r) {\n const t = dt(r);\n return Math.sqrt(\n [0.299, 0.587, 0.114].reduce((s, n, i) => {\n const a = parseInt(t.slice(1 + i * 2, 1 + (i + 1) * 2), 16);\n return s + a * a * n;\n }, 0)\n ) < 120;\n}\nconst u = L((r) => {\n if (typeof r == \"string\" || typeof r == \"number\")\n return r.toString();\n throw I();\n}, \"string\"), gt = L((r) => dt(u().parse(r)), \"rgb\");\nfunction X(r, t) {\n return new z((e) => {\n if (typeof e != \"string\" && !(e instanceof URLSearchParams))\n throw I();\n const s = typeof e == \"string\" ? new URLSearchParams(e) : e;\n return ht(r, (n) => {\n const i = s.get(n);\n return i === null ? void 0 : i;\n });\n }, !1, t);\n}\nfunction Wt() {\n return f({\n id: q(),\n type: u(),\n title: u(),\n photoUrl: {\n type: u().optional(),\n from: \"photo_url\"\n },\n username: u().optional()\n }, \"Chat\");\n}\nclass Ot {\n constructor(t) {\n this.initData = t;\n }\n /**\n * @see InitDataParsed.authDate\n */\n get authDate() {\n return this.initData.authDate;\n }\n /**\n * @see InitDataParsed.canSendAfter\n */\n get canSendAfter() {\n return this.initData.canSendAfter;\n }\n /**\n * Date after which it is allowed to call\n * the [answerWebAppQuery](https://core.telegram.org/bots/api#answerwebappquery) method.\n */\n get canSendAfterDate() {\n const { canSendAfter: t } = this;\n return t === void 0 ? void 0 : new Date(this.authDate.getTime() + t * 1e3);\n }\n /**\n * @see InitDataParsed.chat\n */\n get chat() {\n return this.initData.chat;\n }\n /**\n * @see InitDataParsed.chatType\n */\n get chatType() {\n return this.initData.chatType;\n }\n /**\n * @see InitDataParsed.chatInstance\n */\n get chatInstance() {\n return this.initData.chatInstance;\n }\n /**\n * @see InitDataParsed.hash\n */\n get hash() {\n return this.initData.hash;\n }\n /**\n * @see InitDataParsed.queryId\n */\n get queryId() {\n return this.initData.queryId;\n }\n /**\n * @see InitDataParsed.receiver\n */\n get receiver() {\n return this.initData.receiver;\n }\n /**\n * @see InitDataParsed.startParam\n */\n get startParam() {\n return this.initData.startParam;\n }\n /**\n * @see InitDataParsed.user\n */\n get user() {\n return this.initData.user;\n }\n}\nfunction rt() {\n return f({\n addedToAttachmentMenu: {\n type: k().optional(),\n from: \"added_to_attachment_menu\"\n },\n allowsWriteToPm: {\n type: k().optional(),\n from: \"allows_write_to_pm\"\n },\n firstName: {\n type: u(),\n from: \"first_name\"\n },\n id: q(),\n isBot: {\n type: k().optional(),\n from: \"is_bot\"\n },\n isPremium: {\n type: k().optional(),\n from: \"is_premium\"\n },\n languageCode: {\n type: u().optional(),\n from: \"language_code\"\n },\n lastName: {\n type: u().optional(),\n from: \"last_name\"\n },\n photoUrl: {\n type: u().optional(),\n from: \"photo_url\"\n },\n username: u().optional()\n }, \"User\");\n}\nfunction wt() {\n return X({\n authDate: {\n type: pt(),\n from: \"auth_date\"\n },\n canSendAfter: {\n type: q().optional(),\n from: \"can_send_after\"\n },\n chat: Wt().optional(),\n chatInstance: {\n type: u().optional(),\n from: \"chat_instance\"\n },\n chatType: {\n type: u().optional(),\n from: \"chat_type\"\n },\n hash: u(),\n queryId: {\n type: u().optional(),\n from: \"query_id\"\n },\n receiver: rt().optional(),\n startParam: {\n type: u().optional(),\n from: \"start_param\"\n },\n user: rt().optional()\n }, \"InitData\");\n}\nfunction tr(r) {\n return wt().parse(r);\n}\nfunction Nt(r) {\n return r.replace(/(^|_)bg/, (t, e) => `${e}background`).replace(/_([a-z])/g, (t, e) => e.toUpperCase());\n}\nfunction Ht(r) {\n return r.replace(/[A-Z]/g, (t) => `_${t.toLowerCase()}`).replace(/(^|_)background/, (t, e) => `${e}bg`);\n}\nconst _t = L(\n (r) => {\n const t = gt().optional();\n return Object.entries(Y(r)).reduce((e, [s, n]) => (e[Nt(s)] = t.parse(n), e), {});\n },\n \"ThemeParams\"\n);\nfunction bt(r) {\n return _t().parse(r);\n}\nfunction er(r = {}) {\n return m(\"web_app_request_theme\", \"theme_changed\", r).then(bt);\n}\nfunction Ut(r) {\n return JSON.stringify(\n Object.entries(r).reduce((t, [e, s]) => (s && (t[Ht(e)] = s), t), {})\n );\n}\nclass w {\n constructor() {\n o(this, \"listeners\", /* @__PURE__ */ new Map());\n o(this, \"subscribeListeners\", []);\n }\n /**\n * Adds specified event listener.\n * @param event - event name.\n * @param listener - event listener.\n * @param once - should listener called only once.\n */\n addListener(t, e, s) {\n let n = this.listeners.get(t);\n return n || (n = [], this.listeners.set(t, n)), n.push([e, s]), () => this.off(t, e);\n }\n emit(t, ...e) {\n this.subscribeListeners.forEach((n) => n(t, ...e));\n const s = this.listeners.get(t);\n s && s.forEach(([n, i], a) => {\n n(...e), i && s.splice(a, 1);\n });\n }\n /**\n * Adds event listener.\n * @param event - event name.\n * @param listener - event listener.\n * @returns Function to remove event listener.\n */\n on(t, e) {\n return this.addListener(t, e, !1);\n }\n /**\n * Adds event listener following the logic, described in `on` method, but calls specified\n * listener only once, removing it after.\n * @param event - event name.\n * @param listener - event listener.\n * @returns Function to remove event listener.\n * @see on\n */\n once(t, e) {\n return this.addListener(t, e, !0);\n }\n /**\n * Removes event listener. In case, specified listener was bound several times, it removes\n * only a single one.\n * @param event - event name.\n * @param listener - event listener.\n */\n off(t, e) {\n const s = this.listeners.get(t);\n if (s) {\n for (let n = 0; n < s.length; n += 1)\n if (e === s[n][0]) {\n s.splice(n, 1);\n return;\n }\n }\n }\n /**\n * Adds event listener to all events.\n * @param listener - events listener.\n * @returns Function to remove event listener.\n * @see on\n * @see once\n */\n subscribe(t) {\n return this.subscribeListeners.push(t), () => this.unsubscribe(t);\n }\n /**\n * Removes global event listener. In case, specified listener was bound several times, it removes\n * only a single one.\n * @param listener - events listener.\n * @returns Function to remove event listener.\n */\n unsubscribe(t) {\n for (let e = 0; e < this.subscribeListeners.length; e += 1)\n if (this.subscribeListeners[e] === t) {\n this.subscribeListeners.splice(e, 1);\n return;\n }\n }\n}\nclass b {\n constructor(t, e) {\n this.state = t, this.ee = e;\n }\n internalSet(t, e) {\n return this.state[t] === e || e === void 0 ? !1 : (this.state[t] = e, this.ee.emit(`change:${t}`, e), !0);\n }\n /**\n * Returns copy of current state.\n */\n clone() {\n return { ...this.state };\n }\n set(t, e) {\n let s = !1;\n if (typeof t == \"string\")\n s = this.internalSet(t, e);\n else\n for (const n in t)\n this.internalSet(n, t[n]) && (s = !0);\n s && this.ee.emit(\"change\");\n }\n /**\n * Returns value by specified key.\n * @param key - state key.\n */\n get(t) {\n return this.state[t];\n }\n}\nclass Mt {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n this.state = new b(t, this.ee);\n }\n /**\n * @since v6.10\n */\n get accentTextColor() {\n return this.get(\"accentTextColor\");\n }\n get backgroundColor() {\n return this.get(\"backgroundColor\");\n }\n get buttonColor() {\n return this.get(\"buttonColor\");\n }\n get buttonTextColor() {\n return this.get(\"buttonTextColor\");\n }\n get destructiveTextColor() {\n return this.get(\"destructiveTextColor\");\n }\n /**\n * Retrieves palette color value by its name.\n * @param key - palette key name.\n */\n get(t) {\n return this.state.get(t);\n }\n /**\n * Returns the copy of the internal state of the current component instance.\n */\n getState() {\n return this.state.clone();\n }\n /**\n * @since v6.10\n */\n get headerBackgroundColor() {\n return this.get(\"headerBackgroundColor\");\n }\n get hintColor() {\n return this.get(\"hintColor\");\n }\n /**\n * Returns true in case, current color scheme is recognized as dark. This\n * value is calculated according to theme background color.\n */\n get isDark() {\n return !this.backgroundColor || ft(this.backgroundColor);\n }\n get linkColor() {\n return this.get(\"linkColor\");\n }\n get secondaryBackgroundColor() {\n return this.get(\"secondaryBackgroundColor\");\n }\n /**\n * @since v6.10\n */\n get sectionBackgroundColor() {\n return this.get(\"sectionBackgroundColor\");\n }\n /**\n * @since v6.10\n */\n get sectionHeaderTextColor() {\n return this.get(\"sectionHeaderTextColor\");\n }\n /**\n * Starts listening to theme changes and applies them.\n * @returns Function to stop listening.\n */\n listen() {\n return y(\"theme_changed\", (t) => {\n this.state.set(bt(t.theme_params));\n });\n }\n /**\n * @since v6.10\n */\n get subtitleTextColor() {\n return this.get(\"subtitleTextColor\");\n }\n get textColor() {\n return this.get(\"textColor\");\n }\n}\nfunction mt() {\n return X({\n botInline: {\n type: k().optional(),\n from: \"tgWebAppBotInline\"\n },\n initData: {\n type: wt().optional(),\n from: \"tgWebAppData\"\n },\n initDataRaw: {\n type: u().optional(),\n from: \"tgWebAppData\"\n },\n platform: {\n type: u(),\n from: \"tgWebAppPlatform\"\n },\n showSettings: {\n type: k().optional(),\n from: \"tgWebAppShowSettings\"\n },\n startParam: {\n type: u().optional(),\n from: \"tgWebAppStartParam\"\n },\n themeParams: {\n type: _t(),\n from: \"tgWebAppThemeParams\"\n },\n version: {\n type: u(),\n from: \"tgWebAppVersion\"\n }\n }, \"LaunchParams\");\n}\nfunction jt(r) {\n return mt().parse(r);\n}\nfunction yt(r) {\n const t = r.includes(\"?\") ? r.replace(\"#\", \"&\").slice(r.indexOf(\"?\") + 1) : r.slice(r.indexOf(\"#\") + 1);\n return jt(t);\n}\nfunction Gt() {\n return yt(window.location.href);\n}\nfunction Ft() {\n const r = ut();\n if (!r)\n throw new Error(\"Unable to get first navigation entry.\");\n return yt(r.name);\n}\nfunction zt() {\n try {\n return Ft();\n } catch {\n }\n try {\n return Gt();\n } catch {\n }\n return null;\n}\nfunction Jt(r) {\n const {\n initDataRaw: t,\n themeParams: e,\n platform: s,\n version: n,\n showSettings: i,\n botInline: a\n } = r, c = new URLSearchParams();\n return t && c.set(\"tgWebAppData\", t), c.set(\"tgWebAppPlatform\", s), c.set(\"tgWebAppThemeParams\", Ut(e)), c.set(\"tgWebAppVersion\", n), typeof i == \"boolean\" && c.set(\"tgWebAppShowSettings\", i ? \"1\" : \"0\"), typeof a == \"boolean\" && c.set(\"tgWebAppBotInline\", a ? \"1\" : \"0\"), c.toString();\n}\nconst Et = \"telegram-mini-apps-launch-params\";\nfunction Qt() {\n const r = sessionStorage.getItem(Et);\n return r ? mt().parse(r) : null;\n}\nfunction Zt(r) {\n sessionStorage.setItem(Et, Jt(r));\n}\nfunction Kt() {\n try {\n return window.self !== window.top;\n } catch {\n return !0;\n }\n}\nfunction Yt() {\n const r = Qt(), t = zt(), e = Lt();\n if (r) {\n if (t)\n return {\n launchParams: t,\n isPageReload: Kt() ? e || r.initDataRaw === t.initDataRaw : !0\n };\n if (e)\n return {\n launchParams: r,\n isPageReload: e\n };\n throw new Error(\"Unable to retrieve current launch parameters, which must exist.\");\n }\n if (t)\n return {\n launchParams: t,\n isPageReload: !1\n };\n throw new Error(\"Unable to retrieve any launch parameters.\");\n}\nconst st = \"tmajsLaunchData\";\nfunction Ct() {\n const r = window[st];\n if (r)\n return r;\n const t = Yt();\n return window[st] = t, Zt(t.launchParams), t;\n}\nfunction rr() {\n try {\n return Ct(), !0;\n } catch {\n return !1;\n }\n}\nfunction Xt(r) {\n return \"external\" in r && H(r.external) && \"notify\" in r.external && typeof r.external.notify == \"function\";\n}\nfunction te(r) {\n return \"TelegramWebviewProxy\" in r && H(r.TelegramWebviewProxy) && \"postEvent\" in r.TelegramWebviewProxy && typeof r.TelegramWebviewProxy.postEvent == \"function\";\n}\nfunction vt() {\n try {\n return window.self !== window.top;\n } catch {\n return !0;\n }\n}\nclass tt extends Error {\n constructor(t, e) {\n super(`Method \"${t}\" is unsupported in the Mini Apps version ${e}.`), Object.setPrototypeOf(this, tt.prototype);\n }\n}\nclass et extends Error {\n constructor(t, e, s) {\n super(`Parameter \"${e}\" in method \"${t}\" is unsupported in the Mini Apps version ${s}.`), Object.setPrototypeOf(this, et.prototype);\n }\n}\nclass Pt {\n constructor(t, e) {\n this.prefix = t, this.enabled = e;\n }\n /**\n * Prints message into a console in case, logger is currently enabled.\n * @param level - log level.\n * @param args - arguments.\n */\n print(t, ...e) {\n if (!this.enabled)\n return;\n const s = /* @__PURE__ */ new Date(), n = Intl.DateTimeFormat(\"en-GB\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n fractionalSecondDigits: 3,\n timeZone: \"UTC\"\n }).format(s);\n console[t](`[${n}]`, this.prefix, ...e);\n }\n /**\n * Disables the logger.\n */\n disable() {\n this.enabled = !1;\n }\n /**\n * Prints error message into a console.\n * @param args\n */\n error(...t) {\n this.print(\"error\", ...t);\n }\n /**\n * Enables the logger.\n */\n enable() {\n this.enabled = !0;\n }\n /**\n * Prints log message into a console.\n * @param args\n */\n log(...t) {\n this.print(\"log\", ...t);\n }\n /**\n * Prints warning message into a console.\n * @param args\n */\n warn(...t) {\n this.print(\"warn\", ...t);\n }\n}\nlet kt = \"https://web.telegram.org\";\nconst V = new Pt(\"[SDK]\", !1);\nfunction sr(r) {\n if (r) {\n V.enable();\n return;\n }\n V.disable();\n}\nfunction nr(r) {\n kt = r;\n}\nfunction ee() {\n return kt;\n}\nconst re = f({\n eventType: u(),\n eventData: (r) => r\n});\nfunction se(r, t) {\n window.dispatchEvent(new MessageEvent(\"message\", {\n data: JSON.stringify({ eventType: r, eventData: t })\n }));\n}\nfunction ne() {\n const r = window;\n \"TelegramGameProxy_receiveEvent\" in r || [\n [\"TelegramGameProxy_receiveEvent\"],\n // Windows Phone.\n [\"TelegramGameProxy\", \"receiveEvent\"],\n // Desktop.\n [\"Telegram\", \"WebView\", \"receiveEvent\"]\n // Android and iOS.\n ].forEach((t) => {\n let e = r;\n t.forEach((s, n, i) => {\n if (n === i.length - 1) {\n e[s] = se;\n return;\n }\n s in e || (e[s] = {}), e = e[s];\n });\n });\n}\nfunction ie(r) {\n ne(), window.addEventListener(\"message\", (t) => {\n try {\n const { eventType: e, eventData: s } = re.parse(t.data);\n r(e, s);\n } catch {\n }\n });\n}\nfunction oe() {\n return f({\n req_id: u(),\n data: (r) => r === null ? r : u().optional().parse(r)\n });\n}\nfunction ae() {\n return f({\n req_id: u(),\n result: (r) => r,\n error: u().optional()\n });\n}\nfunction ce() {\n return f({\n slug: u(),\n status: u()\n });\n}\nfunction ue() {\n return f({ status: u() });\n}\nfunction he() {\n return f({\n button_id: (r) => r == null ? void 0 : u().parse(r)\n });\n}\nfunction pe() {\n return f({\n data: u().optional()\n });\n}\nfunction le() {\n return f({\n theme_params: (r) => {\n const t = gt().optional();\n return Object.entries(Y(r)).reduce((e, [s, n]) => (e[s] = t.parse(n), e), {});\n }\n });\n}\nfunction de() {\n return f({\n height: q(),\n width: (r) => r == null ? window.innerWidth : q().parse(r),\n is_state_stable: k(),\n is_expanded: k()\n });\n}\nfunction fe() {\n return f({ status: u() });\n}\nfunction ge() {\n const r = new w(), t = (e, ...s) => {\n V.log(\"Emitting processed event:\", e, ...s), r.emit(e, ...s);\n };\n return window.addEventListener(\"resize\", () => {\n t(\"viewport_changed\", {\n width: window.innerWidth,\n height: window.innerHeight,\n is_state_stable: !0,\n is_expanded: !0\n });\n }), ie((e, s) => {\n V.log(\"Received raw event:\", e, s);\n try {\n switch (e) {\n case \"viewport_changed\":\n return t(e, de().parse(s));\n case \"theme_changed\":\n return t(e, le().parse(s));\n case \"popup_closed\":\n return (\n // Sent on desktop.\n s == null ? t(e, {}) : t(e, he().parse(s))\n );\n case \"set_custom_style\":\n return t(e, u().parse(s));\n case \"qr_text_received\":\n return t(e, pe().parse(s));\n case \"clipboard_text_received\":\n return t(e, oe().parse(s));\n case \"invoice_closed\":\n return t(e, ce().parse(s));\n case \"phone_requested\":\n return t(\"phone_requested\", ue().parse(s));\n case \"custom_method_invoked\":\n return t(\"custom_method_invoked\", ae().parse(s));\n case \"write_access_requested\":\n return t(\"write_access_requested\", fe().parse(s));\n case \"main_button_pressed\":\n case \"back_button_pressed\":\n case \"settings_button_pressed\":\n case \"scan_qr_popup_closed\":\n case \"reload_iframe\":\n return t(e);\n default:\n return t(e, s);\n }\n } catch (n) {\n V.error(\"Error processing event:\", n);\n }\n }), r;\n}\nconst Q = \"telegram-mini-apps-cached-emitter\";\nfunction U() {\n const r = window;\n return r[Q] === void 0 && (r[Q] = ge()), r[Q];\n}\nfunction $(r, t) {\n U().off(r, t);\n}\nfunction y(r, t) {\n return U().on(r, t), () => $(r, t);\n}\nfunction ir(r, t) {\n return U().once(r, t), () => $(r, t);\n}\nfunction we(r) {\n U().unsubscribe(r);\n}\nfunction or(r) {\n return U().subscribe(r), () => we(r);\n}\nfunction _e(r, t) {\n const e = r.split(\".\"), s = t.split(\".\"), n = Math.max(e.length, s.length);\n for (let i = 0; i < n; i += 1) {\n const a = parseInt(e[i] || \"0\", 10), c = parseInt(s[i] || \"0\", 10);\n if (a !== c)\n return a > c ? 1 : -1;\n }\n return 0;\n}\nfunction P(r, t) {\n return _e(r, t) <= 0;\n}\nfunction R(r, t, e) {\n if (typeof e == \"string\") {\n if (r === \"web_app_open_link\" && t === \"try_instant_view\")\n return P(\"6.4\", e);\n if (r === \"web_app_set_header_color\" && t === \"color\")\n return P(\"6.9\", e);\n }\n switch (r) {\n case \"web_app_open_tg_link\":\n case \"web_app_open_invoice\":\n case \"web_app_setup_back_button\":\n case \"web_app_set_background_color\":\n case \"web_app_set_header_color\":\n case \"web_app_trigger_haptic_feedback\":\n return P(\"6.1\", t);\n case \"web_app_open_popup\":\n return P(\"6.2\", t);\n case \"web_app_close_scan_qr_popup\":\n case \"web_app_open_scan_qr_popup\":\n case \"web_app_read_text_from_clipboard\":\n return P(\"6.4\", t);\n case \"web_app_switch_inline_query\":\n return P(\"6.7\", t);\n case \"web_app_invoke_custom_method\":\n case \"web_app_request_write_access\":\n case \"web_app_request_phone\":\n return P(\"6.9\", t);\n case \"web_app_setup_settings_button\":\n return P(\"6.10\", t);\n default:\n return !0;\n }\n}\nfunction E(r, t) {\n return (e) => R(t[e], r);\n}\nfunction St(r, t) {\n return (e) => {\n const [s, n] = t[e];\n return R(s, n, r);\n };\n}\nfunction d(r, t, e) {\n let s = {}, n;\n t === void 0 && e === void 0 ? s = {} : t !== void 0 && e !== void 0 ? (s = e, n = t) : t !== void 0 && (\"targetOrigin\" in t ? s = t : n = t);\n const { targetOrigin: i = ee() } = s;\n if (V.log(`Calling method \"${r}\"`, n), vt()) {\n window.parent.postMessage(JSON.stringify({\n eventType: r,\n eventData: n\n }), i);\n return;\n }\n if (Xt(window)) {\n window.external.notify(JSON.stringify({ eventType: r, eventData: n }));\n return;\n }\n if (te(window)) {\n window.TelegramWebviewProxy.postEvent(r, JSON.stringify(n));\n return;\n }\n throw new Error(\n \"Unable to determine current environment and possible way to send event.\"\n );\n}\nfunction be(r) {\n return (t, e) => {\n if (!R(t, r))\n throw new tt(t, r);\n if (H(e)) {\n let s;\n if (t === \"web_app_open_link\" && \"try_instant_view\" in e ? s = \"try_instant_view\" : t === \"web_app_set_header_color\" && \"color\" in e && (s = \"color\"), s && !R(t, s, r))\n throw new et(t, s, r);\n }\n return d(t, e);\n };\n}\nclass J extends Error {\n constructor(t) {\n super(`Async call timeout exceeded. Timeout: ${t}`), Object.setPrototypeOf(this, J.prototype);\n }\n}\nfunction ar(r) {\n return r instanceof J;\n}\nfunction me(r) {\n return new Promise((t) => {\n setTimeout(t, r);\n });\n}\nfunction ye(r) {\n return new Promise((t, e) => {\n setTimeout(e, r, new J(r));\n });\n}\nfunction xt(r, t) {\n return Promise.race([\n r(),\n ye(t)\n ]);\n}\nfunction m(r, t, e, s) {\n let n, i, a, c;\n typeof t == \"string\" || Array.isArray(t) ? (a = Array.isArray(t) ? t : [t], n = e) : (i = t, a = Array.isArray(e) ? e : [e], n = s), H(i) && typeof i.req_id == \"string\" && (c = i.req_id);\n const { postEvent: p = d, timeout: h } = n || {}, g = n && \"capture\" in n ? n.capture : null, _ = () => new Promise((A, l) => {\n const C = a.map((v) => y(v, (M) => {\n c && (!H(M) || M.req_id !== c) || typeof g == \"function\" && !g(M) || (x(), A(M));\n })), x = () => C.forEach((v) => v());\n try {\n p(r, i);\n } catch (v) {\n x(), l(v);\n }\n });\n return typeof h == \"number\" ? xt(_, h) : _();\n}\nasync function O(r, t, e, s = {}) {\n const { result: n, error: i } = await m(\n \"web_app_invoke_custom_method\",\n {\n method: r,\n params: t,\n req_id: e\n },\n \"custom_method_invoked\",\n s\n );\n if (i)\n throw new Error(i);\n return n;\n}\nclass Ee {\n constructor(t, e, s = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"on\", (t, e) => t === \"click\" ? y(\"back_button_pressed\", e) : this.ee.on(t, e));\n /**\n * Removes event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"off\", (t, e) => t === \"click\" ? $(\"back_button_pressed\", e) : this.ee.off(t, e));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = s, this.state = new b({ isVisible: t }, this.ee), this.supports = E(e, {\n show: \"web_app_setup_back_button\",\n hide: \"web_app_setup_back_button\"\n });\n }\n set isVisible(t) {\n this.state.set(\"isVisible\", t), this.postEvent(\"web_app_setup_back_button\", { is_visible: t });\n }\n /**\n * True if BackButton is currently visible.\n */\n get isVisible() {\n return this.state.get(\"isVisible\");\n }\n /**\n * Hides the BackButton.\n */\n hide() {\n this.isVisible = !1;\n }\n /**\n * Shows the BackButton.\n */\n show() {\n this.isVisible = !0;\n }\n}\nfunction nt(r, t) {\n return r + (r.length > 0 && t.length > 0 ? ` ${t}` : t);\n}\nfunction Ce(...r) {\n return r.reduce((t, e) => {\n let s = \"\";\n return typeof e == \"string\" ? s = e : typeof e == \"object\" && e !== null && (s = Object.entries(e).reduce((n, [i, a]) => a ? nt(n, i) : n, \"\")), nt(t, s);\n }, \"\");\n}\nfunction ve(r) {\n return typeof r == \"object\" && r !== null && !Array.isArray(null);\n}\nfunction cr(...r) {\n return r.reduce((t, e) => (ve(e) && Object.entries(e).forEach(([s, n]) => {\n const i = Ce(t[s], n);\n i.length > 0 && (t[s] = i);\n }), t), {});\n}\nclass Pe {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n this.postEvent = e, this.state = new b({ isConfirmationNeeded: t }, this.ee);\n }\n set isConfirmationNeeded(t) {\n this.state.set(\"isConfirmationNeeded\", t), this.postEvent(\"web_app_setup_closing_behavior\", { need_confirmation: t });\n }\n /**\n * Returns true, if the confirmation dialog enabled while the user is trying\n * to close the Mini App.\n */\n get isConfirmationNeeded() {\n return this.state.get(\"isConfirmationNeeded\");\n }\n /**\n * Disables the confirmation dialog while the user is trying to close the\n * Mini App.\n */\n disableConfirmation() {\n this.isConfirmationNeeded = !1;\n }\n /**\n * Enables the confirmation dialog while the user is trying to close the\n * Mini App.\n */\n enableConfirmation() {\n this.isConfirmationNeeded = !0;\n }\n}\nfunction it(r, t) {\n return r.reduce((e, s) => (e[s] = t, e), {});\n}\nclass ke {\n constructor(t, e, s = d) {\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.createRequestId = e, this.postEvent = s, this.supports = E(t, {\n delete: \"web_app_invoke_custom_method\",\n get: \"web_app_invoke_custom_method\",\n getKeys: \"web_app_invoke_custom_method\",\n set: \"web_app_invoke_custom_method\"\n });\n }\n /**\n * Deletes specified key or keys from the cloud storage.\n * @param keyOrKeys - key or keys to delete.\n * @param options - request execution options.\n */\n async delete(t, e = {}) {\n const s = Array.isArray(t) ? t : [t];\n s.length !== 0 && await O(\n \"deleteStorageValues\",\n { keys: s },\n this.createRequestId(),\n { ...e, postEvent: this.postEvent }\n );\n }\n /**\n * Returns list of all keys presented in the cloud storage.\n * @param options - request execution options.\n */\n async getKeys(t = {}) {\n const e = await O(\n \"getStorageKeys\",\n {},\n this.createRequestId(),\n { ...t, postEvent: this.postEvent }\n );\n return Bt().of(u()).parse(e);\n }\n async get(t, e = {}) {\n const s = Array.isArray(t) ? t : [t];\n if (s.length === 0)\n return it(s, \"\");\n const n = f(\n it(s, u())\n ), i = await O(\n \"getStorageValues\",\n { keys: s },\n this.createRequestId(),\n { ...e, postEvent: this.postEvent }\n ).then((a) => n.parse(a));\n return Array.isArray(t) ? i : i[t];\n }\n /**\n * Saves specified value by key.\n * @param key - storage key.\n * @param value - storage value.\n * @param options - request execution options.\n */\n async set(t, e, s = {}) {\n await O(\n \"saveStorageValue\",\n { key: t, value: e },\n this.createRequestId(),\n { ...s, postEvent: this.postEvent }\n );\n }\n}\nclass Se {\n constructor(t, e = d) {\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.supports = E(t, {\n impactOccurred: \"web_app_trigger_haptic_feedback\",\n notificationOccurred: \"web_app_trigger_haptic_feedback\",\n selectionChanged: \"web_app_trigger_haptic_feedback\"\n });\n }\n /**\n * A method tells that an impact occurred. The Telegram app may play the\n * appropriate haptics based on style value passed.\n * @param style - impact style.\n */\n impactOccurred(t) {\n this.postEvent(\"web_app_trigger_haptic_feedback\", {\n type: \"impact\",\n impact_style: t\n });\n }\n /**\n * A method tells that a task or action has succeeded, failed, or produced\n * a warning. The Telegram app may play the appropriate haptics based on\n * type value passed.\n * @param type - notification type.\n */\n notificationOccurred(t) {\n this.postEvent(\"web_app_trigger_haptic_feedback\", {\n type: \"notification\",\n notification_type: t\n });\n }\n /**\n * A method tells that the user has changed a selection. The Telegram app\n * may play the appropriate haptics.\n *\n * Do not use this feedback when the user makes or confirms a selection;\n * use it only when the selection changes.\n */\n selectionChanged() {\n this.postEvent(\"web_app_trigger_haptic_feedback\", { type: \"selection_change\" });\n }\n}\nfunction xe() {\n const r = document.createElement(\"style\");\n r.id = \"telegram-custom-styles\", document.head.appendChild(r), y(\"set_custom_style\", (t) => {\n r.innerHTML = t;\n });\n}\nfunction qt(r) {\n return `telegram-mini-apps-${r}`;\n}\nfunction T(r, t) {\n sessionStorage.setItem(qt(r), JSON.stringify(t));\n}\nfunction B(r) {\n const t = sessionStorage.getItem(qt(r));\n return t ? JSON.parse(t) : null;\n}\nfunction qe(r, t, e) {\n const { isVisible: s = !1 } = r ? B(\"back-button\") || {} : {}, n = new Ee(s, t, e);\n return n.on(\"change\", () => {\n T(\"back-button\", { isVisible: n.isVisible });\n }), n;\n}\nfunction Ae(r, t) {\n const { isConfirmationNeeded: e = !1 } = r ? B(\"closing-behavior\") || {} : {}, s = new Pe(e, t);\n return s.on(\"change\", () => T(\"closing-behavior\", {\n isConfirmationNeeded: s.isConfirmationNeeded\n })), s;\n}\nclass Ve {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n o(this, \"postEvent\");\n /**\n * Adds new event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"on\", (t, e) => (\n // FIXME: Event 'main_button_pressed' is still being received on Android\n // even if the main button is disabled.\n // Issue: https://github.com/Telegram-Mini-Apps/tma.js/issues/3\n t === \"click\" ? y(\"main_button_pressed\", e) : this.ee.on(t, e)\n ));\n /**\n * Removes event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"off\", (t, e) => t === \"click\" ? $(\"main_button_pressed\", e) : this.ee.off(t, e));\n const {\n postEvent: e = d,\n text: s,\n textColor: n,\n backgroundColor: i,\n isEnabled: a,\n isVisible: c,\n isLoaderVisible: p\n } = t;\n this.postEvent = e, this.state = new b({\n backgroundColor: i,\n isEnabled: a,\n isVisible: c,\n isLoaderVisible: p,\n text: s,\n textColor: n\n }, this.ee);\n }\n /**\n * Sends current local state to Telegram application.\n */\n commit() {\n this.text !== \"\" && this.postEvent(\"web_app_setup_main_button\", {\n is_visible: this.isVisible,\n is_active: this.isEnabled,\n is_progress_visible: this.isLoaderVisible,\n text: this.text,\n color: this.backgroundColor,\n text_color: this.textColor\n });\n }\n set isEnabled(t) {\n this.setParams({ isEnabled: t });\n }\n /**\n * True if the Main Button is currently enabled.\n */\n get isEnabled() {\n return this.state.get(\"isEnabled\");\n }\n set isLoaderVisible(t) {\n this.setParams({ isLoaderVisible: t });\n }\n /**\n * True if the Main Button loader is currently visible.\n */\n get isLoaderVisible() {\n return this.state.get(\"isLoaderVisible\");\n }\n set isVisible(t) {\n this.setParams({ isVisible: t });\n }\n /**\n * True if the Main Button is currently visible.\n */\n get isVisible() {\n return this.state.get(\"isVisible\");\n }\n /**\n * The Main Button background color.\n */\n get backgroundColor() {\n return this.state.get(\"backgroundColor\");\n }\n /**\n * The Main Button text.\n */\n get text() {\n return this.state.get(\"text\");\n }\n /**\n * The Main Button text color.\n */\n get textColor() {\n return this.state.get(\"textColor\");\n }\n /**\n * Disables the Main Button.\n */\n disable() {\n return this.isEnabled = !1, this;\n }\n /**\n * Enables the Main Button.\n */\n enable() {\n return this.isEnabled = !0, this;\n }\n /**\n * Hides the Main Button.\n */\n hide() {\n return this.isVisible = !1, this;\n }\n /**\n * Hides the Main Button loader.\n */\n hideLoader() {\n return this.isLoaderVisible = !1, this;\n }\n /**\n * Shows the Main Button. Note that opening the Mini App from the attachment menu hides the\n * main button until the user interacts with the Mini App interface.\n */\n show() {\n return this.isVisible = !0, this;\n }\n /**\n * A method to show a loading indicator on the Main Button. It is recommended to display\n * loader if the action tied to the button may take a long time.\n */\n showLoader() {\n return this.isLoaderVisible = !0, this;\n }\n /**\n * Sets new Main Button text. Minimal length for text is 1 symbol, and maximum is 64 symbols.\n * @param text - new text.\n */\n setText(t) {\n return this.setParams({ text: t });\n }\n /**\n * Sets new Main Button text color.\n * @param textColor - new text color.\n */\n setTextColor(t) {\n return this.setParams({ textColor: t });\n }\n /**\n * Updates current Main Button color.\n * @param backgroundColor - color to set.\n */\n setBackgroundColor(t) {\n return this.setParams({ backgroundColor: t });\n }\n /**\n * Allows setting multiple Main Button parameters.\n * @param params - Main Button parameters.\n */\n setParams(t) {\n return this.state.set(t), this.commit(), this;\n }\n}\nfunction Re(r, t, e, s) {\n const {\n backgroundColor: n = t,\n isEnabled: i = !1,\n isVisible: a = !1,\n isLoaderVisible: c = !1,\n textColor: p = e,\n text: h = \"\"\n } = r ? B(\"main-button\") || {} : {}, g = new Ve({\n backgroundColor: n,\n isEnabled: i,\n isLoaderVisible: c,\n isVisible: a,\n postEvent: s,\n text: h,\n textColor: p\n }), _ = () => T(\"main-button\", {\n backgroundColor: g.backgroundColor,\n isEnabled: g.isEnabled,\n isLoaderVisible: g.isLoaderVisible,\n isVisible: g.isVisible,\n text: g.text,\n textColor: g.textColor\n });\n return g.on(\"change\", _), g;\n}\nconst Ie = X({\n contact: f({\n userId: {\n type: q(),\n from: \"user_id\"\n },\n phoneNumber: {\n type: u(),\n from: \"phone_number\"\n },\n firstName: {\n type: u(),\n from: \"first_name\"\n },\n lastName: {\n type: u().optional(),\n from: \"last_name\"\n }\n }),\n authDate: {\n type: pt(),\n from: \"auth_date\"\n },\n hash: u()\n});\nclass Le {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n o(this, \"botInline\");\n o(this, \"postEvent\");\n o(this, \"createRequestId\");\n o(this, \"requestingPhoneAccess\", !1);\n o(this, \"requestingWriteAccess\", !1);\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n /**\n * Checks if specified method parameter is supported by current component.\n */\n o(this, \"supportsParam\");\n const {\n postEvent: e = d,\n headerColor: s,\n backgroundColor: n,\n version: i,\n botInline: a,\n createRequestId: c\n } = t, p = E(i, {\n requestPhoneAccess: \"web_app_request_phone\",\n requestWriteAccess: \"web_app_request_write_access\",\n switchInlineQuery: \"web_app_switch_inline_query\",\n setHeaderColor: \"web_app_set_header_color\",\n setBackgroundColor: \"web_app_set_background_color\"\n });\n this.postEvent = e, this.botInline = a, this.createRequestId = c, this.supports = (h) => !(!p(h) || h === \"switchInlineQuery\" && !a), this.state = new b({ backgroundColor: n, headerColor: s }, this.ee), this.supportsParam = St(i, {\n \"setHeaderColor.color\": [\"web_app_set_header_color\", \"color\"]\n });\n }\n /**\n * Attempts to get requested contact.\n */\n async getRequestedContact() {\n return O(\n \"getRequestedContact\",\n {},\n this.createRequestId(),\n {\n postEvent: this.postEvent,\n timeout: 1e4\n }\n ).then((t) => Ie.parse(t));\n }\n /**\n * The Mini App background color.\n */\n get backgroundColor() {\n return this.state.get(\"backgroundColor\");\n }\n /**\n * Closes the Mini App.\n */\n close() {\n this.postEvent(\"web_app_close\");\n }\n /**\n * The Mini App header color. Could either be a header color key or RGB color.\n */\n get headerColor() {\n return this.state.get(\"headerColor\");\n }\n /**\n * True if Mini App is currently launched in bot inline mode.\n */\n get isBotInline() {\n return this.botInline;\n }\n /**\n * True if current Mini App background color recognized as dark.\n */\n get isDark() {\n return ft(this.backgroundColor);\n }\n /**\n * True if phone access is currently being requested.\n */\n get isRequestingPhoneAccess() {\n return this.requestingPhoneAccess;\n }\n /**\n * True if write access is currently being requested.\n */\n get isRequestingWriteAccess() {\n return this.requestingWriteAccess;\n }\n /**\n * Informs the Telegram app that the Mini App is ready to be displayed.\n *\n * It is recommended to call this method as early as possible, as soon as all essential\n * interface elements loaded. Once this method called, the loading placeholder is hidden\n * and the Mini App shown.\n *\n * If the method not called, the placeholder will be hidden only when the page fully loaded.\n */\n ready() {\n this.postEvent(\"web_app_ready\");\n }\n /**\n * Requests current user contact information. In contrary to requestPhoneAccess, this method\n * returns promise with contact information that rejects in case, user denied access, or request\n * failed.\n * @param options - additional options.\n */\n async requestContact({ timeout: t = 5e3 } = {}) {\n try {\n return await this.getRequestedContact();\n } catch {\n }\n if (await this.requestPhoneAccess() !== \"sent\")\n throw new Error(\"Access denied.\");\n const s = Date.now() + t;\n let n = 50;\n return xt(async () => {\n for (; Date.now() < s; ) {\n try {\n return await this.getRequestedContact();\n } catch {\n }\n await me(n), n += 50;\n }\n throw new Error(\"Unable to retrieve requested contact.\");\n }, t);\n }\n /**\n * Requests current user phone access. Method returns promise, which resolves\n * status of the request. In case, user accepted the request, Mini App bot will receive\n * the according notification.\n *\n * To obtain the retrieved information instead, utilize the requestContact method.\n * @param options - additional options.\n * @see requestContact\n */\n requestPhoneAccess(t = {}) {\n if (this.requestingPhoneAccess)\n throw new Error(\"Phone access is already being requested.\");\n return this.requestingPhoneAccess = !0, m(\"web_app_request_phone\", \"phone_requested\", {\n ...t,\n postEvent: this.postEvent\n }).then((e) => e.status).finally(() => {\n this.requestingPhoneAccess = !1;\n });\n }\n /**\n * Requests write message access to current user.\n * @param options - additional options.\n */\n requestWriteAccess(t = {}) {\n if (this.requestingWriteAccess)\n throw new Error(\"Write access is already being requested.\");\n return this.requestingWriteAccess = !0, m(\"web_app_request_write_access\", \"write_access_requested\", {\n ...t,\n postEvent: this.postEvent\n }).then((e) => e.status).finally(() => {\n this.requestingWriteAccess = !1;\n });\n }\n /**\n * A method used to send data to the bot. When this method called, a service message sent to\n * the bot containing the data of the length up to 4096 bytes, and the Mini App closed. See the\n * field `web_app_data` in the class [Message](https://core.telegram.org/bots/api#message).\n *\n * This method is only available for Mini Apps launched via a Keyboard button.\n * @param data - data to send to bot.\n * @throws {Error} data has incorrect size.\n */\n sendData(t) {\n const { size: e } = new Blob([t]);\n if (e === 0 || e > 4096)\n throw new Error(`Passed data has incorrect size: ${e}`);\n this.postEvent(\"web_app_data_send\", { data: t });\n }\n /**\n * Updates current Mini App header color.\n * @param color - color key or RGB color.\n */\n setHeaderColor(t) {\n this.postEvent(\"web_app_set_header_color\", lt(t) ? { color: t } : { color_key: t }), this.state.set(\"headerColor\", t);\n }\n /**\n * Updates current Mini App background color.\n * @param color - RGB color.\n */\n setBackgroundColor(t) {\n this.postEvent(\"web_app_set_background_color\", { color: t }), this.state.set(\"backgroundColor\", t);\n }\n /**\n * Inserts the bot's username and the specified inline query in the current chat's input field.\n * Query may be empty, in which case only the bot's username will be inserted. The client prompts\n * the user to choose a specific chat, then opens that chat and inserts the bot's username and\n * the specified inline query in the input field.\n * @param text - text which should be inserted in the input after the current bot name. Max\n * length is 256 symbols.\n * @param chatTypes - List of chat types which could be chosen to send the message. Could be\n * empty list.\n */\n switchInlineQuery(t, e = []) {\n if (!this.supports(\"switchInlineQuery\") && !this.isBotInline)\n throw new Error(\"Method is unsupported because Mini App should be launched in inline mode.\");\n this.postEvent(\"web_app_switch_inline_query\", {\n query: t,\n chat_types: e\n });\n }\n}\nfunction $e(r, t, e, s, n, i) {\n const {\n backgroundColor: a = t,\n headerColor: c = \"bg_color\"\n } = r ? B(\"mini-app\") || {} : {}, p = new Le({\n headerColor: c,\n backgroundColor: a,\n version: e,\n botInline: s,\n createRequestId: n,\n postEvent: i\n }), h = () => T(\"mini-app\", {\n backgroundColor: p.backgroundColor,\n headerColor: p.headerColor\n });\n return p.on(\"change\", h), p;\n}\nfunction Te() {\n let r = 0;\n return () => (r += 1, r.toString());\n}\nclass Be {\n constructor(t, e, s = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"on\", (t, e) => t === \"click\" ? y(\"settings_button_pressed\", e) : this.ee.on(t, e));\n /**\n * Removes event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"off\", (t, e) => t === \"click\" ? $(\"settings_button_pressed\", e) : this.ee.off(t, e));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = s, this.state = new b({ isVisible: t }, this.ee), this.supports = E(e, {\n show: \"web_app_setup_settings_button\",\n hide: \"web_app_setup_settings_button\"\n });\n }\n set isVisible(t) {\n this.state.set(\"isVisible\", t), this.postEvent(\"web_app_setup_settings_button\", { is_visible: t });\n }\n /**\n * True if SettingsButton is currently visible.\n */\n get isVisible() {\n return this.state.get(\"isVisible\");\n }\n /**\n * Hides the SettingsButton.\n */\n hide() {\n this.isVisible = !1;\n }\n /**\n * Shows the SettingsButton.\n */\n show() {\n this.isVisible = !0;\n }\n}\nfunction De(r, t, e) {\n const { isVisible: s = !1 } = r ? B(\"settings-button\") || {} : {}, n = new Be(s, t, e);\n return n.on(\"change\", () => {\n T(\"settings-button\", { isVisible: n.isVisible });\n }), n;\n}\nfunction We(r) {\n const t = new Mt(r);\n return t.listen(), t;\n}\nfunction Oe(r) {\n return [\"macos\", \"tdesktop\", \"unigram\", \"web\", \"weba\"].includes(r);\n}\nasync function At(r) {\n const t = await m(\"web_app_request_viewport\", \"viewport_changed\", r);\n return {\n height: t.height,\n width: t.width,\n isExpanded: t.is_expanded,\n isStateStable: t.is_state_stable\n };\n}\nfunction D(r) {\n return r < 0 ? 0 : r;\n}\nclass Ne {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n o(this, \"postEvent\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n const {\n height: e,\n isExpanded: s,\n width: n,\n stableHeight: i,\n postEvent: a = d\n } = t;\n this.postEvent = a, this.state = new b({\n height: D(e),\n isExpanded: s,\n stableHeight: D(i),\n width: D(n)\n }, this.ee);\n }\n /**\n * Request viewport information from the Telegram application and updates current Viewport\n * instance.\n * @param options - options to request fresh data.\n */\n sync(t) {\n return At(t).then(({ height: e, isExpanded: s, width: n, isStateStable: i }) => {\n this.state.set({\n height: e,\n width: n,\n isExpanded: s,\n stableHeight: i ? e : this.state.get(\"stableHeight\")\n });\n });\n }\n /**\n * The current height of the visible area of the Mini App.\n *\n * The application can display just the top part of the Mini App, with its\n * lower part remaining outside the screen area. From this position, the\n * user can \"pull\" the Mini App to its maximum height, while the bot can do\n * the same by calling `expand` method. As the position of the Mini App\n * changes, the current height value of the visible area will be updated\n * in real time.\n *\n * Please note that the refresh rate of this value is not sufficient\n * to smoothly follow the lower border of the window. It should not be\n * used to pin interface elements to the bottom of the visible area. It's\n * more appropriate to use the value of the `stableHeight`\n * field for this purpose.\n */\n get height() {\n return this.state.get(\"height\");\n }\n /**\n * The height of the visible area of the Mini App in its last stable state.\n *\n * The application can display just the top part of the Mini App, with its\n * lower part remaining outside the screen area. From this position,\n * the user can \"pull\" the Mini App to its maximum height, while the bot can\n * do the same by calling `expand` method.\n *\n * Unlike the value of `height`, the value of `stableHeight`\n * does not change as the position of the Mini App changes with user\n * gestures or during animations. The value of `stableHeight`\n * will be updated after all gestures and animations are completed and\n * the Mini App reaches its final size.\n */\n get stableHeight() {\n return this.state.get(\"stableHeight\");\n }\n /**\n * Starts listening to viewport changes and applies them.\n * @returns Function to stop listening.\n */\n listen() {\n return y(\"viewport_changed\", (t) => {\n const {\n height: e,\n width: s,\n is_expanded: n,\n is_state_stable: i\n } = t, a = {\n height: D(e),\n isExpanded: n,\n width: D(s)\n };\n i && (a.stableHeight = a.height), this.state.set(a);\n });\n }\n /**\n * Returns true if the Mini App is expanded to the maximum available height.\n * Otherwise, if the Mini App occupies part of the screen and can be expanded\n * to the full height using `expand` method.\n * @see expand\n */\n get isExpanded() {\n return this.state.get(\"isExpanded\");\n }\n /**\n * Current viewport width.\n */\n get width() {\n return this.state.get(\"width\");\n }\n /**\n * A method that expands the Mini App to the maximum available height. To\n * find out if the Mini App is expanded to the maximum height, refer to the\n * value of the `isExpanded`.\n * @see isExpanded\n */\n expand() {\n this.postEvent(\"web_app_expand\"), this.state.set(\"isExpanded\", !0);\n }\n /**\n * Returns true in case current viewport height is stable and is not going to\n * change in the next moment.\n */\n get isStable() {\n return this.stableHeight === this.height;\n }\n}\nfunction j(r) {\n const t = new Ne(r);\n return t.on(\"change\", () => T(\"viewport\", {\n height: t.height,\n isExpanded: t.isExpanded,\n stableHeight: t.stableHeight,\n width: t.width\n })), t.listen(), t;\n}\nfunction He(r, t, e, s) {\n const n = r ? B(\"viewport\") : null;\n if (n)\n return j({ ...n, postEvent: e });\n if (Oe(t))\n return j({\n height: window.innerHeight,\n isExpanded: !0,\n postEvent: e,\n stableHeight: window.innerHeight,\n width: window.innerWidth\n });\n if (s)\n return At({\n postEvent: e,\n timeout: 5e3\n }).then(({ height: a, isStateStable: c, ...p }) => j({\n ...p,\n height: a,\n stableHeight: c ? a : 0\n }));\n const i = j({\n width: 0,\n height: 0,\n isExpanded: !1,\n postEvent: e,\n stableHeight: 0\n });\n return i.sync({ postEvent: e, timeout: 5e3 }).catch((a) => {\n console.error(\"Unable to actualize viewport state\", a);\n }), i;\n}\nfunction S(r, t) {\n document.documentElement.style.setProperty(r, t);\n}\nfunction Ue(r, t) {\n const e = () => {\n S(\"--tg-background-color\", r.backgroundColor);\n }, s = () => {\n const {\n backgroundColor: n,\n secondaryBackgroundColor: i\n } = t;\n r.headerColor === \"bg_color\" ? n && S(\"--tg-header-color\", n) : r.headerColor === \"secondary_bg_color\" ? i && S(\"--tg-header-color\", i) : S(\"--tg-header-color\", r.headerColor);\n };\n t.on(\"change\", s), r.on(\"change:backgroundColor\", e), r.on(\"change:headerColor\", s), e(), s();\n}\nfunction Me(r) {\n const t = () => {\n const e = r.getState();\n Object.entries(e).forEach(([s, n]) => {\n if (n) {\n const i = s.replace(/[A-Z]/g, (a) => `-${a.toLowerCase()}`);\n S(`--tg-theme-${i}`, n);\n }\n });\n };\n r.on(\"change\", t), t();\n}\nfunction ot(r) {\n const t = () => S(\"--tg-viewport-height\", `${r.height}px`), e = () => S(\"--tg-viewport-width\", `${r.width}px`), s = () => S(\"--tg-viewport-height\", `${r.stableHeight}px`);\n r.on(\"change:height\", t), r.on(\"change:width\", e), r.on(\"change:stableHeight\", s), t(), e(), s();\n}\nfunction je(r) {\n return typeof r == \"object\" ? r : r ? {\n themeParams: !0,\n viewport: !0,\n miniApp: !0\n } : {};\n}\nfunction at(r, t, e, s) {\n const n = je(r);\n n.miniApp && Ue(t, e), n.themeParams && Me(e), n.viewport && (s instanceof Promise ? s.then(ot) : ot(s));\n}\nfunction Ge(r) {\n const { hostname: t, pathname: e } = new URL(r, window.location.href);\n if (t !== \"t.me\")\n throw new Error(`Incorrect hostname: ${t}`);\n const s = e.match(/^\\/(\\$|invoice\\/)([A-Za-z0-9\\-_=]+)$/);\n if (s === null)\n throw new Error('Link pathname has incorrect format. Expected to receive \"/invoice/{slug}\" or \"/${slug}\"');\n return s[2];\n}\nclass Fe {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.state = new b({ isOpened: !1 }, this.ee), this.supports = E(t, { open: \"web_app_open_invoice\" });\n }\n set isOpened(t) {\n this.state.set(\"isOpened\", t);\n }\n /**\n * True if invoice is currently opened.\n */\n get isOpened() {\n return this.state.get(\"isOpened\");\n }\n async open(t, e) {\n if (this.isOpened)\n throw new Error(\"Invoice is already opened\");\n const s = e ? Ge(t) : t;\n this.isOpened = !0;\n try {\n return (await m(\n \"web_app_open_invoice\",\n { slug: s },\n \"invoice_closed\",\n {\n postEvent: this.postEvent,\n capture(i) {\n return s === i.slug;\n }\n }\n )).status;\n } finally {\n this.isOpened = !1;\n }\n }\n}\nfunction ze(r) {\n const t = r.message.trim(), e = (r.title || \"\").trim(), s = r.buttons || [];\n let n;\n if (e.length > 64)\n throw new Error(`Title has incorrect size: ${e.length}`);\n if (t.length === 0 || t.length > 256)\n throw new Error(`Message has incorrect size: ${t.length}`);\n if (s.length > 3)\n throw new Error(`Buttons have incorrect size: ${s.length}`);\n return s.length === 0 ? n = [{ type: \"close\", id: \"\" }] : n = s.map((i) => {\n const { id: a = \"\" } = i;\n if (a.length > 64)\n throw new Error(`Button ID has incorrect size: ${a}`);\n if (i.type === void 0 || i.type === \"default\" || i.type === \"destructive\") {\n const c = i.text.trim();\n if (c.length === 0 || c.length > 64) {\n const p = i.type || \"default\";\n throw new Error(`Button text with type \"${p}\" has incorrect size: ${i.text.length}`);\n }\n return { ...i, text: c, id: a };\n }\n return { ...i, id: a };\n }), { title: e, message: t, buttons: n };\n}\nclass Je {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.state = new b({ isOpened: !1 }, this.ee), this.supports = E(t, { open: \"web_app_open_popup\" });\n }\n set isOpened(t) {\n this.state.set(\"isOpened\", t);\n }\n /**\n * True if popup is currently opened.\n */\n get isOpened() {\n return this.state.get(\"isOpened\");\n }\n /**\n * A method that shows a native popup described by the `params` argument.\n * Promise will be resolved when popup is closed. Resolved value will have\n * an identifier of pressed button.\n *\n * In case, user clicked outside the popup or clicked top right popup close\n * button, null will be returned.\n *\n * FIXME: In desktop, this function may work incorrectly.\n * Issue: https://github.com/Telegram-Mini-Apps/tma.js/issues/7\n * @param options - popup parameters.\n * @throws {Error} Popup is already opened.\n */\n open(t) {\n if (this.isOpened)\n throw new Error(\"Popup is already opened.\");\n return this.isOpened = !0, m(\n \"web_app_open_popup\",\n ze(t),\n \"popup_closed\",\n { postEvent: this.postEvent }\n ).then(({ button_id: e = null }) => e).finally(() => {\n this.isOpened = !1;\n });\n }\n}\nclass Qe {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.state = new b({ isOpened: !1 }, this.ee), this.supports = E(t, {\n close: \"web_app_close_scan_qr_popup\",\n open: \"web_app_open_scan_qr_popup\"\n });\n }\n /**\n * Closes scanner.\n */\n close() {\n this.postEvent(\"web_app_close_scan_qr_popup\"), this.isOpened = !1;\n }\n set isOpened(t) {\n this.state.set(\"isOpened\", t);\n }\n /**\n * Returns true in case, QR scanner is currently opened.\n */\n get isOpened() {\n return this.state.get(\"isOpened\");\n }\n /**\n * Opens scanner with specified title shown to user. Method returns promise\n * with scanned QR content in case, it was scanned. It will contain null in\n * case, scanner was closed.\n * @param text - title to display.\n */\n async open(t) {\n if (this.isOpened)\n throw new Error(\"QR scanner is already opened.\");\n this.isOpened = !0;\n try {\n const e = await m(\n \"web_app_open_scan_qr_popup\",\n { text: t },\n [\"qr_text_received\", \"scan_qr_popup_closed\"],\n { postEvent: this.postEvent }\n );\n return typeof e == \"object\" && typeof e.data == \"string\" ? e.data : null;\n } finally {\n this.isOpened = !1;\n }\n }\n}\nclass Ze {\n constructor(t, e, s = d) {\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n /**\n * Checks if specified method parameter is supported by current component.\n */\n o(this, \"supportsParam\");\n this.version = t, this.createRequestId = e, this.postEvent = s, this.supports = E(t, {\n readTextFromClipboard: \"web_app_read_text_from_clipboard\"\n }), this.supportsParam = St(t, {\n \"openLink.tryInstantView\": [\"web_app_open_link\", \"try_instant_view\"]\n });\n }\n /**\n * Opens a link in an external browser. The Mini App will not be closed.\n *\n * Note that this method can be called only in response to the user\n * interaction with the Mini App interface (e.g. click inside the Mini App\n * or on the main button).\n * @param url - URL to be opened.\n * @param tryInstantView\n */\n openLink(t, e) {\n const s = new URL(t, window.location.href).toString();\n if (!R(\"web_app_open_link\", this.version)) {\n window.open(s, \"_blank\");\n return;\n }\n this.postEvent(\"web_app_open_link\", {\n url: s,\n ...typeof e == \"boolean\" ? { try_instant_view: e } : {}\n });\n }\n /**\n * Opens a Telegram link inside Telegram app. The Mini App will be closed. It expects passing\n * link in full format, with hostname \"t.me\".\n * @param url - URL to be opened.\n * @throws {Error} URL has not allowed hostname.\n */\n openTelegramLink(t) {\n const {\n hostname: e,\n pathname: s,\n search: n\n } = new URL(t, window.location.href);\n if (e !== \"t.me\")\n throw new Error(`URL has not allowed hostname: ${e}. Only \"t.me\" is allowed`);\n if (!R(\"web_app_open_tg_link\", this.version)) {\n window.location.href = t;\n return;\n }\n this.postEvent(\"web_app_open_tg_link\", { path_full: s + n });\n }\n /**\n * Reads text from clipboard and returns string or null. null is returned\n * in cases:\n * - Value in clipboard is not text\n * - Access to clipboard is not allowed\n */\n readTextFromClipboard() {\n return m(\n \"web_app_read_text_from_clipboard\",\n { req_id: this.createRequestId() },\n \"clipboard_text_received\",\n { postEvent: this.postEvent }\n ).then(({ data: t = null }) => t);\n }\n}\nfunction ur(r = {}) {\n const {\n async: t = !1,\n complete: e = t,\n cssVars: s = !1,\n acceptCustomStyles: n = !1\n } = r;\n try {\n const {\n launchParams: {\n initData: i,\n initDataRaw: a,\n version: c,\n platform: p,\n themeParams: h,\n botInline: g = !1\n },\n isPageReload: _\n } = Ct(), A = Te(), l = be(c);\n vt() && (n && xe(), l(\"iframe_ready\", { reload_supported: !0 }), y(\"reload_iframe\", () => window.location.reload()));\n const C = {\n backButton: qe(_, c, l),\n closingBehavior: Ae(_, l),\n cloudStorage: new ke(c, A, l),\n createRequestId: A,\n hapticFeedback: new Se(c, l),\n invoice: new Fe(c, l),\n mainButton: Re(\n _,\n h.buttonColor || \"#000000\",\n h.buttonTextColor || \"#ffffff\",\n l\n ),\n miniApp: $e(\n _,\n h.backgroundColor || \"#ffffff\",\n c,\n g,\n A,\n l\n ),\n popup: new Je(c, l),\n postEvent: l,\n qrScanner: new Qe(c, l),\n settingsButton: De(_, c, l),\n themeParams: We(h),\n utils: new Ze(c, A, l),\n ...i ? {\n initData: new Ot(i),\n initDataRaw: a\n } : {}\n }, x = He(_, p, l, e);\n return x instanceof Promise || e ? Promise.resolve(x).then((v) => (at(\n s,\n C.miniApp,\n C.themeParams,\n v\n ), { ...C, viewport: v })) : (at(\n s,\n C.miniApp,\n C.themeParams,\n x\n ), { ...C, viewport: x });\n } catch (i) {\n if (e)\n return Promise.reject(i);\n throw i;\n }\n}\nfunction W(r, t) {\n return r.startsWith(t) ? r : `${t}${r}`;\n}\nfunction hr(r) {\n const t = r.match(/#(.+)/);\n return t ? t[1] : null;\n}\nasync function N(r) {\n return r === 0 ? !0 : Promise.race([\n new Promise((t) => {\n window.addEventListener(\"popstate\", function e() {\n window.removeEventListener(\"popstate\", e), t(!0);\n }), window.history.go(r);\n }),\n // Usually, it takes about 1ms to emit this event, but we use some buffer.\n new Promise((t) => {\n setTimeout(t, 50, !1);\n })\n ]);\n}\nasync function Ke() {\n if (window.history.length <= 1 || (window.history.pushState(null, \"\"), await N(1 - window.history.length)))\n return;\n let t = await N(-1);\n for (; t; )\n t = await N(-1);\n}\nclass Ye {\n constructor(t, e, {\n debug: s = !1,\n loggerPrefix: n = \"Navigator\"\n }) {\n o(this, \"logger\");\n o(this, \"entries\");\n if (this.entriesCursor = e, t.length === 0)\n throw new Error(\"Entries list should not be empty.\");\n if (e >= t.length)\n throw new Error(\"Cursor should be less than entries count.\");\n this.entries = t.map(({ pathname: i = \"\", search: a, hash: c }) => {\n if (!i.startsWith(\"/\") && i.length > 0)\n throw new Error('Pathname should start with \"/\"');\n return {\n pathname: W(i, \"/\"),\n search: a ? W(a, \"?\") : \"\",\n hash: c ? W(c, \"#\") : \"\"\n };\n }), this.logger = new Pt(`[${n}]`, s);\n }\n /**\n * Converts entry to the navigation entry.\n * @param entry - entry data\n */\n formatEntry(t) {\n let e;\n if (typeof t == \"string\")\n e = t;\n else {\n const {\n pathname: a = \"\",\n search: c,\n hash: p\n } = t;\n e = a + (c ? W(c, \"?\") : \"\") + (p ? W(p, \"#\") : \"\");\n }\n const {\n pathname: s,\n search: n,\n hash: i\n } = new URL(e, `https://localhost${this.path}`);\n return {\n pathname: s,\n search: n,\n hash: i\n };\n }\n /**\n * Current entry.\n */\n get entry() {\n return this.entries[this.entriesCursor];\n }\n /**\n * Goes back in history.\n */\n back() {\n return this.go(-1);\n }\n /**\n * Current entries cursor.\n */\n get cursor() {\n return this.entriesCursor;\n }\n /**\n * True if navigator can go back.\n */\n get canGoBack() {\n return this.entriesCursor > 0;\n }\n /**\n * True if navigator can go forward.\n */\n get canGoForward() {\n return this.entriesCursor !== this.entries.length - 1;\n }\n /**\n * Goes forward in history.\n */\n forward() {\n return this.go(1);\n }\n /**\n * Moves entries cursor by specified delta.\n * @param delta - cursor delta.\n */\n go(t) {\n this.logger.log(`called go(${t})`);\n const e = Math.min(\n this.entries.length - 1,\n Math.max(this.entriesCursor + t, 0)\n );\n if (this.entriesCursor === e)\n return this.performGo({\n updated: !1,\n delta: t\n });\n const s = this.entry;\n this.entriesCursor = e;\n const n = this.entry;\n return this.logger.log(\"State changed\", { before: s, after: n }), this.performGo({\n updated: !0,\n delta: t,\n before: s,\n after: n\n });\n }\n /**\n * Returns copy of navigator entries.\n */\n getEntries() {\n return this.entries.map((t) => ({ ...t }));\n }\n /**\n * Current hash.\n * @example\n * \"\", \"#\", \"#hash\"\n */\n get hash() {\n return this.entry.hash;\n }\n /**\n * Pushes new entry. Method replaces all entries after the current one with the inserted.\n * @param entry - entry data.\n *\n * @example Pushing absolute pathname.\n * push(\"/absolute-path\"); // \"/absolute-path\"\n *\n * @example Pushing relative pathname.\n * // Pushing relative path replaces N last path parts, where N is pushed pathname parts count.\n * // Pushing empty path is recognized as relative, but not replacing the last pathname part.\n * push(\"relative\"); // \"/home/root\" -> \"/home/relative\"\n *\n * @example Pushing query parameters.\n * push(\"/absolute?my-param=1\"); // \"/home\" -> \"/absolute?my-param=1\"\n * push(\"relative?my-param=1\"); // \"/home/root\" -> \"/home/relative?my-param=1\"\n * push(\"?my-param=1\"); // \"/home\" -> \"/home?my-param=1\"\n *\n * @example Pushing hash.\n * push(\"#my-hash\"); // \"/home\" -> \"/home#my-hash\"\n * push(\"johny#my-hash\"); // \"/home/root\" -> \"/home/johny#my-hash\"\n */\n push(t) {\n this.entriesCursor !== this.entries.length - 1 && this.entries.splice(this.entriesCursor + 1);\n const e = this.formatEntry(t), s = this.entry;\n this.entriesCursor += 1, this.entries[this.entriesCursor] = e;\n const n = this.entry;\n return this.logger.log(\"State changed\", { before: s, after: n }), this.performPush({\n before: s,\n after: n\n });\n }\n /**\n * Current full path including pathname, query parameters and hash.\n */\n get path() {\n return `${this.pathname}${this.search}${this.hash}`;\n }\n /**\n * Current pathname.\n * @example\n * \"/\", \"/abc\"\n */\n get pathname() {\n return this.entry.pathname;\n }\n /**\n * Replaces current entry. Has the same logic as `push` method.\n * @param entry - entry data.\n * @see push\n * @returns True if changes were done.\n */\n replace(t) {\n const e = this.formatEntry(t);\n if (this.search === e.search && this.pathname === e.pathname && this.hash === e.hash)\n return this.performReplace({\n updated: !1,\n entry: e\n });\n const s = this.entry;\n this.entries[this.entriesCursor] = e;\n const n = this.entry;\n return this.logger.log(\"State changed\", { before: s, after: n }), this.performReplace({\n updated: !0,\n before: s,\n after: n\n });\n }\n /**\n * Current query parameters.\n * @example\n * \"\", \"?\", \"?a=1\"\n */\n get search() {\n return this.entry.search;\n }\n}\nconst ct = 0, Z = 1, K = 2;\nclass Vt extends Ye {\n constructor(e, s, n = {}) {\n super(e, s, {\n ...n,\n loggerPrefix: \"HashNavigator\"\n });\n o(this, \"ee\", new w());\n o(this, \"attached\", !1);\n /**\n * Handles window \"popstate\" event.\n * @param state - event state.\n */\n o(this, \"onPopState\", async ({ state: e }) => {\n if (this.logger.log('\"popstate\" event received. State:', e), e === null)\n return this.push(window.location.hash.slice(1));\n if (e === ct) {\n this.logger.log(\"Void reached. Moving history forward\"), window.history.forward();\n return;\n }\n if (e === Z)\n return this.back();\n if (e === K)\n return this.forward();\n });\n o(this, \"back\", () => super.back());\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n }\n /**\n * Creates navigator from current window location hash.\n * @param options - options passed to constructor.\n */\n static fromLocation(e) {\n const {\n search: s,\n pathname: n,\n hash: i\n } = new URL(\n window.location.hash.slice(1),\n window.location.href\n );\n return new Vt([{ search: s, pathname: n, hash: i }], 0, e);\n }\n async performGo(e) {\n e.updated && (this.attached && await this.syncHistory(), this.emitChanged(e.before, e.after));\n }\n async performPush({ before: e, after: s }) {\n this.attached && await this.syncHistory(), this.emitChanged(e, s);\n }\n async performReplace(e) {\n e.updated && (this.attached && window.history.replaceState(null, \"\", `#${this.path}`), this.emitChanged(e.before, e.after));\n }\n /**\n * Synchronizes current navigator state with browser history.\n */\n async syncHistory() {\n window.removeEventListener(\"popstate\", this.onPopState);\n const e = `#${this.path}`;\n await Ke(), d(\"web_app_setup_back_button\", { is_visible: this.canGoBack }), this.canGoBack && this.canGoForward ? (this.logger.log(\"Setting up history: [<-, *, ->]\"), window.history.replaceState(Z, \"\"), window.history.pushState(null, \"\", e), window.history.pushState(K, \"\"), await N(-1)) : this.canGoBack ? (this.logger.log(\"Setting up history: [<-, *]\"), window.history.replaceState(Z, \"\"), window.history.pushState(null, \"\", e)) : this.canGoForward ? (this.logger.log(\"Setting up history: [*, ->]\"), window.history.replaceState(null, e), window.history.pushState(K, \"\"), await N(-1)) : (this.logger.log(\"Setting up history: [~, *]\"), window.history.replaceState(ct, \"\"), window.history.pushState(null, \"\", e)), window.addEventListener(\"popstate\", this.onPopState);\n }\n emitChanged(e, s) {\n this.ee.emit(\"change\", {\n navigator: this,\n from: e,\n to: s\n });\n }\n /**\n * Attaches current navigator to the browser history allowing navigator to manipulate it.\n */\n async attach() {\n if (!this.attached)\n return this.logger.log(\"Attaching\", this), this.attached = !0, y(\"back_button_pressed\", this.back), this.syncHistory();\n }\n /**\n * Detaches current navigator from the browser history.\n */\n detach() {\n this.attached && (this.logger.log(\"Detaching\", this), this.attached = !1, window.removeEventListener(\"popstate\", this.onPopState), $(\"back_button_pressed\", this.back));\n }\n}\nexport {\n Ee as BackButton,\n Pe as ClosingBehavior,\n ke as CloudStorage,\n Se as HapticFeedback,\n Vt as HashNavigator,\n Ot as InitData,\n Fe as Invoice,\n Ve as MainButton,\n tt as MethodUnsupportedError,\n Le as MiniApp,\n Ye as Navigator,\n et as ParameterUnsupportedError,\n Je as Popup,\n Qe as QRScanner,\n Be as SettingsButton,\n Mt as ThemeParams,\n J as TimeoutError,\n Ze as Utils,\n Ne as Viewport,\n Wt as chatParser,\n Ce as classNames,\n _e as compareVersions,\n be as createPostEvent,\n hr as getHash,\n ur as init,\n wt as initDataParser,\n O as invokeCustomMethod,\n ft as isColorDark,\n vt as isIframe,\n lt as isRGB,\n Dt as isRGBShort,\n H as isRecord,\n Oe as isStableViewportPlatform,\n rr as isTMA,\n ar as isTimeoutError,\n mt as launchParamsParser,\n cr as mergeClassNames,\n $ as off,\n y as on,\n ir as once,\n tr as parseInitData,\n jt as parseLaunchParams,\n bt as parseThemeParams,\n d as postEvent,\n m as request,\n er as requestThemeParams,\n At as requestViewport,\n Ct as retrieveLaunchData,\n Jt as serializeLaunchParams,\n Ut as serializeThemeParams,\n sr as setDebug,\n nr as setTargetOrigin,\n or as subscribe,\n R as supports,\n _t as themeParamsParser,\n dt as toRGB,\n we as unsubscribe,\n rt as userParser,\n xt as withTimeout\n};\n//# sourceMappingURL=index.mjs.map\n","import { createHmac } from 'node:crypto';\nimport { URLSearchParams } from 'node:url';\n\nexport interface ValidateOptions {\n /**\n * Time in seconds which states, how long from creation time is init data\n * considered valid.\n *\n * In other words, in case, when authDate + expiresIn is before current\n * time, init data recognized as expired.\n *\n * In case, this value is equal to 0, function does not check init data\n * expiration.\n * @default 86400 (1 day)\n */\n expiresIn?: number;\n}\n\n/**\n * Validates passed init data presented as search params converted to string,\n * or its object presentation.\n *\n * @param sp - search parameters.\n * @param token - Telegram bot secret token.\n * @param options - validation options.\n * @see toSearchParams\n * @throws {TypeError} \"hash\" should be string.\n * @throws {Error} \"hash\" is empty or not found.\n * @throws {TypeError} \"auth_date\" should be string.\n * @throws {TypeError} \"auth_date\" does not represent integer.\n * @throws {Error} \"auth_date\" is empty or not found.\n * @throws {Error} Init data expired.\n * @throws {Error} Sign invalid.\n */\nexport function validate(\n sp: string | URLSearchParams,\n token: string,\n options: ValidateOptions = {},\n): void {\n const searchParams = typeof sp === 'string' ? new URLSearchParams(sp) : sp;\n\n // Init data creation time.\n let authDate = new Date(0);\n\n // Init data sign.\n let hash = '';\n\n // All search params pairs presented as `k=v`.\n const pairs: string[] = [];\n\n // Iterate over all key-value pairs of parsed parameters and find required\n // parameters.\n searchParams.forEach((value, key) => {\n if (key === 'hash') {\n hash = value;\n return;\n }\n\n if (key === 'auth_date') {\n const authDateNum = parseInt(value, 10);\n\n if (Number.isNaN(authDateNum)) {\n throw new TypeError('\"auth_date\" should present integer');\n }\n authDate = new Date(authDateNum * 1000);\n }\n\n // Append new pair.\n pairs.push(`${key}=${value}`);\n });\n\n // Hash and auth date always required.\n if (hash.length === 0) {\n throw new Error('\"hash\" is empty or not found');\n }\n\n if (authDate.getTime() === 0) {\n throw new Error('\"auth_date\" is empty or not found');\n }\n\n // In case, expiration time passed, we do additional parameters check.\n const { expiresIn = 86400 } = options;\n\n if (expiresIn > 0) {\n // Check if init data expired.\n if (authDate.getTime() + expiresIn * 1000 < new Date().getTime()) {\n throw new Error('Init data expired');\n }\n }\n\n // According to docs, we sort all the pairs in alphabetical order.\n pairs.sort();\n\n // Compute sign.\n const computedHash = createHmac(\n 'sha256',\n createHmac('sha256', 'WebAppData').update(token).digest(),\n )\n .update(pairs.join('\\n'))\n .digest()\n .toString('hex');\n\n // In case, our sign is not equal to found one, we should throw an error.\n if (computedHash !== hash) {\n throw new Error('Signature is invalid');\n }\n}\n"],"names":["Rt","It","r","e","o","I","F","s","n","z","L","G","ht","i","a","h","c","p","k","q","pt","Y","f","u","X","Wt","rt","wt","tr","validate","sp","token","options","searchParams","URLSearchParams","authDate","hash","pairs","value","key","authDateNum","expiresIn","createHmac"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../sdk/dist/index.mjs","../src/validate.ts"],"sourcesContent":["var Rt = Object.defineProperty;\nvar It = (r, t, e) => t in r ? Rt(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;\nvar o = (r, t, e) => (It(r, typeof t != \"symbol\" ? t + \"\" : t, e), e);\nfunction H(r) {\n return typeof r == \"object\" && r !== null && !Array.isArray(r);\n}\nfunction ut() {\n return performance.getEntriesByType(\"navigation\")[0] || null;\n}\nfunction Lt() {\n const r = ut();\n return r ? r.type === \"reload\" : null;\n}\nfunction I() {\n return new TypeError(\"Value has unexpected type\");\n}\nclass F extends Error {\n constructor(e, { cause: s, type: n } = {}) {\n super(`Unable to parse value${n ? ` as ${n}` : \"\"}`, { cause: s });\n /**\n * Parser name.\n */\n o(this, \"type\");\n this.value = e, Object.setPrototypeOf(this, F.prototype), this.type = n;\n }\n}\nclass z {\n constructor(t, e, s) {\n this.parser = t, this.isOptional = e, this.type = s;\n }\n parse(t) {\n if (!(this.isOptional && t === void 0))\n try {\n return this.parser(t);\n } catch (e) {\n throw new F(t, { type: this.type, cause: e });\n }\n }\n optional() {\n return this.isOptional = !0, this;\n }\n}\nfunction $t(r) {\n if (Array.isArray(r))\n return r;\n if (typeof r == \"string\")\n try {\n const t = JSON.parse(r);\n if (Array.isArray(t))\n return t;\n } catch {\n }\n throw I();\n}\nclass Tt extends z {\n constructor(e, s, n) {\n super($t, s, n);\n o(this, \"itemParser\");\n this.itemParser = typeof e == \"function\" ? e : e.parse.bind(e);\n }\n parse(e) {\n const s = super.parse(e);\n return s === void 0 ? s : s.map(this.itemParser);\n }\n of(e) {\n return this.itemParser = typeof e == \"function\" ? e : e.parse.bind(e), this;\n }\n}\nfunction L(r, t) {\n return () => new z(r, !1, t);\n}\nclass G extends Error {\n constructor(t, { cause: e, type: s } = {}) {\n super(`Unable to parse field \"${t}\"${s ? ` as ${s}` : \"\"}`, { cause: e }), Object.setPrototypeOf(this, G.prototype);\n }\n}\nfunction ht(r, t) {\n const e = {};\n for (const s in r) {\n const n = r[s];\n if (!n)\n continue;\n let i, a;\n if (typeof n == \"function\" || \"parse\" in n)\n i = s, a = typeof n == \"function\" ? n : n.parse.bind(n);\n else {\n const { type: h } = n;\n i = n.from || s, a = typeof h == \"function\" ? h : h.parse.bind(h);\n }\n let c;\n const p = t(i);\n try {\n c = a(p);\n } catch (h) {\n throw h instanceof F ? new G(i, {\n type: h.type,\n cause: h\n }) : new G(i, { cause: h });\n }\n c !== void 0 && (e[s] = c);\n }\n return e;\n}\nfunction Bt(r) {\n return new Tt((t) => t, !1, r);\n}\nconst k = L((r) => {\n if (typeof r == \"boolean\")\n return r;\n const t = String(r);\n if (t === \"1\" || t === \"true\")\n return !0;\n if (t === \"0\" || t === \"false\")\n return !1;\n throw I();\n}, \"boolean\"), q = L((r) => {\n if (typeof r == \"number\")\n return r;\n if (typeof r == \"string\") {\n const t = Number(r);\n if (!Number.isNaN(t))\n return t;\n }\n throw I();\n}, \"number\"), pt = L((r) => r instanceof Date ? r : new Date(q().parse(r) * 1e3), \"Date\");\nfunction Y(r) {\n let t = r;\n if (typeof t == \"string\" && (t = JSON.parse(t)), typeof t != \"object\" || t === null || Array.isArray(t))\n throw I();\n return t;\n}\nfunction f(r, t) {\n return new z((e) => {\n const s = Y(e);\n return ht(r, (n) => s[n]);\n }, !1, t);\n}\nfunction lt(r) {\n return /^#[\\da-f]{6}$/i.test(r);\n}\nfunction Dt(r) {\n return /^#[\\da-f]{3}$/i.test(r);\n}\nfunction dt(r) {\n const t = r.replace(/\\s/g, \"\").toLowerCase();\n if (lt(t))\n return t;\n if (Dt(t)) {\n let s = \"#\";\n for (let n = 0; n < 3; n += 1)\n s += t[1 + n].repeat(2);\n return s;\n }\n const e = t.match(/^rgb\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)$/) || t.match(/^rgba\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3}),\\d{1,3}\\)$/);\n if (e === null)\n throw new Error(`Value \"${r}\" does not satisfy any of known RGB formats.`);\n return e.slice(1).reduce((s, n) => {\n const i = parseInt(n, 10).toString(16);\n return s + (i.length === 1 ? \"0\" : \"\") + i;\n }, \"#\");\n}\nfunction ft(r) {\n const t = dt(r);\n return Math.sqrt(\n [0.299, 0.587, 0.114].reduce((s, n, i) => {\n const a = parseInt(t.slice(1 + i * 2, 1 + (i + 1) * 2), 16);\n return s + a * a * n;\n }, 0)\n ) < 120;\n}\nconst u = L((r) => {\n if (typeof r == \"string\" || typeof r == \"number\")\n return r.toString();\n throw I();\n}, \"string\"), gt = L((r) => dt(u().parse(r)), \"rgb\");\nfunction X(r, t) {\n return new z((e) => {\n if (typeof e != \"string\" && !(e instanceof URLSearchParams))\n throw I();\n const s = typeof e == \"string\" ? new URLSearchParams(e) : e;\n return ht(r, (n) => {\n const i = s.get(n);\n return i === null ? void 0 : i;\n });\n }, !1, t);\n}\nfunction Wt() {\n return f({\n id: q(),\n type: u(),\n title: u(),\n photoUrl: {\n type: u().optional(),\n from: \"photo_url\"\n },\n username: u().optional()\n }, \"Chat\");\n}\nclass Ot {\n constructor(t) {\n this.initData = t;\n }\n /**\n * @see InitDataParsed.authDate\n */\n get authDate() {\n return this.initData.authDate;\n }\n /**\n * @see InitDataParsed.canSendAfter\n */\n get canSendAfter() {\n return this.initData.canSendAfter;\n }\n /**\n * Date after which it is allowed to call\n * the [answerWebAppQuery](https://core.telegram.org/bots/api#answerwebappquery) method.\n */\n get canSendAfterDate() {\n const { canSendAfter: t } = this;\n return t === void 0 ? void 0 : new Date(this.authDate.getTime() + t * 1e3);\n }\n /**\n * @see InitDataParsed.chat\n */\n get chat() {\n return this.initData.chat;\n }\n /**\n * @see InitDataParsed.chatType\n */\n get chatType() {\n return this.initData.chatType;\n }\n /**\n * @see InitDataParsed.chatInstance\n */\n get chatInstance() {\n return this.initData.chatInstance;\n }\n /**\n * @see InitDataParsed.hash\n */\n get hash() {\n return this.initData.hash;\n }\n /**\n * @see InitDataParsed.queryId\n */\n get queryId() {\n return this.initData.queryId;\n }\n /**\n * @see InitDataParsed.receiver\n */\n get receiver() {\n return this.initData.receiver;\n }\n /**\n * @see InitDataParsed.startParam\n */\n get startParam() {\n return this.initData.startParam;\n }\n /**\n * @see InitDataParsed.user\n */\n get user() {\n return this.initData.user;\n }\n}\nfunction rt() {\n return f({\n addedToAttachmentMenu: {\n type: k().optional(),\n from: \"added_to_attachment_menu\"\n },\n allowsWriteToPm: {\n type: k().optional(),\n from: \"allows_write_to_pm\"\n },\n firstName: {\n type: u(),\n from: \"first_name\"\n },\n id: q(),\n isBot: {\n type: k().optional(),\n from: \"is_bot\"\n },\n isPremium: {\n type: k().optional(),\n from: \"is_premium\"\n },\n languageCode: {\n type: u().optional(),\n from: \"language_code\"\n },\n lastName: {\n type: u().optional(),\n from: \"last_name\"\n },\n photoUrl: {\n type: u().optional(),\n from: \"photo_url\"\n },\n username: u().optional()\n }, \"User\");\n}\nfunction wt() {\n return X({\n authDate: {\n type: pt(),\n from: \"auth_date\"\n },\n canSendAfter: {\n type: q().optional(),\n from: \"can_send_after\"\n },\n chat: Wt().optional(),\n chatInstance: {\n type: u().optional(),\n from: \"chat_instance\"\n },\n chatType: {\n type: u().optional(),\n from: \"chat_type\"\n },\n hash: u(),\n queryId: {\n type: u().optional(),\n from: \"query_id\"\n },\n receiver: rt().optional(),\n startParam: {\n type: u().optional(),\n from: \"start_param\"\n },\n user: rt().optional()\n }, \"InitData\");\n}\nfunction er(r) {\n return wt().parse(r);\n}\nfunction Nt(r) {\n return r.replace(/(^|_)bg/, (t, e) => `${e}background`).replace(/_([a-z])/g, (t, e) => e.toUpperCase());\n}\nfunction Ht(r) {\n return r.replace(/[A-Z]/g, (t) => `_${t.toLowerCase()}`).replace(/(^|_)background/, (t, e) => `${e}bg`);\n}\nconst _t = L(\n (r) => {\n const t = gt().optional();\n return Object.entries(Y(r)).reduce((e, [s, n]) => (e[Nt(s)] = t.parse(n), e), {});\n },\n \"ThemeParams\"\n);\nfunction bt(r) {\n return _t().parse(r);\n}\nfunction rr(r = {}) {\n return m(\"web_app_request_theme\", \"theme_changed\", r).then(bt);\n}\nfunction Ut(r) {\n return JSON.stringify(\n Object.entries(r).reduce((t, [e, s]) => (s && (t[Ht(e)] = s), t), {})\n );\n}\nclass w {\n constructor() {\n o(this, \"listeners\", /* @__PURE__ */ new Map());\n o(this, \"subscribeListeners\", []);\n }\n /**\n * Adds specified event listener.\n * @param event - event name.\n * @param listener - event listener.\n * @param once - should listener called only once.\n */\n addListener(t, e, s) {\n let n = this.listeners.get(t);\n return n || (n = [], this.listeners.set(t, n)), n.push([e, s]), () => this.off(t, e);\n }\n emit(t, ...e) {\n this.subscribeListeners.forEach((n) => n(t, ...e));\n const s = this.listeners.get(t);\n s && s.forEach(([n, i], a) => {\n n(...e), i && s.splice(a, 1);\n });\n }\n /**\n * Adds event listener.\n * @param event - event name.\n * @param listener - event listener.\n * @returns Function to remove event listener.\n */\n on(t, e) {\n return this.addListener(t, e, !1);\n }\n /**\n * Adds event listener following the logic, described in `on` method, but calls specified\n * listener only once, removing it after.\n * @param event - event name.\n * @param listener - event listener.\n * @returns Function to remove event listener.\n * @see on\n */\n once(t, e) {\n return this.addListener(t, e, !0);\n }\n /**\n * Removes event listener. In case, specified listener was bound several times, it removes\n * only a single one.\n * @param event - event name.\n * @param listener - event listener.\n */\n off(t, e) {\n const s = this.listeners.get(t);\n if (s) {\n for (let n = 0; n < s.length; n += 1)\n if (e === s[n][0]) {\n s.splice(n, 1);\n return;\n }\n }\n }\n /**\n * Adds event listener to all events.\n * @param listener - events listener.\n * @returns Function to remove event listener.\n * @see on\n * @see once\n */\n subscribe(t) {\n return this.subscribeListeners.push(t), () => this.unsubscribe(t);\n }\n /**\n * Removes global event listener. In case, specified listener was bound several times, it removes\n * only a single one.\n * @param listener - events listener.\n * @returns Function to remove event listener.\n */\n unsubscribe(t) {\n for (let e = 0; e < this.subscribeListeners.length; e += 1)\n if (this.subscribeListeners[e] === t) {\n this.subscribeListeners.splice(e, 1);\n return;\n }\n }\n}\nclass b {\n constructor(t, e) {\n this.state = t, this.ee = e;\n }\n internalSet(t, e) {\n return this.state[t] === e || e === void 0 ? !1 : (this.state[t] = e, this.ee.emit(`change:${t}`, e), !0);\n }\n /**\n * Returns copy of current state.\n */\n clone() {\n return { ...this.state };\n }\n set(t, e) {\n let s = !1;\n if (typeof t == \"string\")\n s = this.internalSet(t, e);\n else\n for (const n in t)\n this.internalSet(n, t[n]) && (s = !0);\n s && this.ee.emit(\"change\");\n }\n /**\n * Returns value by specified key.\n * @param key - state key.\n */\n get(t) {\n return this.state[t];\n }\n}\nclass Mt {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n this.state = new b(t, this.ee);\n }\n /**\n * @since v6.10\n */\n get accentTextColor() {\n return this.get(\"accentTextColor\");\n }\n get backgroundColor() {\n return this.get(\"backgroundColor\");\n }\n get buttonColor() {\n return this.get(\"buttonColor\");\n }\n get buttonTextColor() {\n return this.get(\"buttonTextColor\");\n }\n get destructiveTextColor() {\n return this.get(\"destructiveTextColor\");\n }\n /**\n * Retrieves palette color value by its name.\n * @param key - palette key name.\n */\n get(t) {\n return this.state.get(t);\n }\n /**\n * Returns the copy of the internal state of the current component instance.\n */\n getState() {\n return this.state.clone();\n }\n /**\n * @since v6.10\n */\n get headerBackgroundColor() {\n return this.get(\"headerBackgroundColor\");\n }\n get hintColor() {\n return this.get(\"hintColor\");\n }\n /**\n * Returns true in case, current color scheme is recognized as dark. This\n * value is calculated according to theme background color.\n */\n get isDark() {\n return !this.backgroundColor || ft(this.backgroundColor);\n }\n get linkColor() {\n return this.get(\"linkColor\");\n }\n get secondaryBackgroundColor() {\n return this.get(\"secondaryBackgroundColor\");\n }\n /**\n * @since v6.10\n */\n get sectionBackgroundColor() {\n return this.get(\"sectionBackgroundColor\");\n }\n /**\n * @since v6.10\n */\n get sectionHeaderTextColor() {\n return this.get(\"sectionHeaderTextColor\");\n }\n /**\n * Starts listening to theme changes and applies them.\n * @returns Function to stop listening.\n */\n listen() {\n return y(\"theme_changed\", (t) => {\n this.state.set(bt(t.theme_params));\n });\n }\n /**\n * @since v6.10\n */\n get subtitleTextColor() {\n return this.get(\"subtitleTextColor\");\n }\n get textColor() {\n return this.get(\"textColor\");\n }\n}\nfunction mt() {\n return X({\n botInline: {\n type: k().optional(),\n from: \"tgWebAppBotInline\"\n },\n initData: {\n type: wt().optional(),\n from: \"tgWebAppData\"\n },\n initDataRaw: {\n type: u().optional(),\n from: \"tgWebAppData\"\n },\n platform: {\n type: u(),\n from: \"tgWebAppPlatform\"\n },\n showSettings: {\n type: k().optional(),\n from: \"tgWebAppShowSettings\"\n },\n startParam: {\n type: u().optional(),\n from: \"tgWebAppStartParam\"\n },\n themeParams: {\n type: _t(),\n from: \"tgWebAppThemeParams\"\n },\n version: {\n type: u(),\n from: \"tgWebAppVersion\"\n }\n }, \"LaunchParams\");\n}\nfunction jt(r) {\n return mt().parse(r);\n}\nfunction yt(r) {\n const t = r.includes(\"?\") ? r.replace(\"#\", \"&\").slice(r.indexOf(\"?\") + 1) : r.slice(r.indexOf(\"#\") + 1);\n return jt(t);\n}\nfunction Gt() {\n return yt(window.location.href);\n}\nfunction Ft() {\n const r = ut();\n if (!r)\n throw new Error(\"Unable to get first navigation entry.\");\n return yt(r.name);\n}\nfunction zt() {\n try {\n return Ft();\n } catch {\n }\n try {\n return Gt();\n } catch {\n }\n return null;\n}\nfunction Jt(r) {\n const {\n initDataRaw: t,\n themeParams: e,\n platform: s,\n version: n,\n showSettings: i,\n botInline: a\n } = r, c = new URLSearchParams();\n return t && c.set(\"tgWebAppData\", t), c.set(\"tgWebAppPlatform\", s), c.set(\"tgWebAppThemeParams\", Ut(e)), c.set(\"tgWebAppVersion\", n), typeof i == \"boolean\" && c.set(\"tgWebAppShowSettings\", i ? \"1\" : \"0\"), typeof a == \"boolean\" && c.set(\"tgWebAppBotInline\", a ? \"1\" : \"0\"), c.toString();\n}\nconst Et = \"telegram-mini-apps-launch-params\";\nfunction Qt() {\n const r = sessionStorage.getItem(Et);\n return r ? mt().parse(r) : null;\n}\nfunction Zt(r) {\n sessionStorage.setItem(Et, Jt(r));\n}\nfunction Kt() {\n try {\n return window.self !== window.top;\n } catch {\n return !0;\n }\n}\nfunction Yt() {\n const r = Qt(), t = zt(), e = Lt();\n if (r) {\n if (t)\n return {\n launchParams: t,\n isPageReload: Kt() ? e || r.initDataRaw === t.initDataRaw : !0\n };\n if (e)\n return {\n launchParams: r,\n isPageReload: e\n };\n throw new Error(\"Unable to retrieve current launch parameters, which must exist.\");\n }\n if (t)\n return {\n launchParams: t,\n isPageReload: !1\n };\n throw new Error(\"Unable to retrieve any launch parameters.\");\n}\nconst st = \"tmajsLaunchData\";\nfunction Ct() {\n const r = window[st];\n if (r)\n return r;\n const t = Yt();\n return window[st] = t, Zt(t.launchParams), t;\n}\nfunction sr() {\n try {\n return Ct(), !0;\n } catch {\n return !1;\n }\n}\nfunction Xt(r) {\n return \"external\" in r && H(r.external) && \"notify\" in r.external && typeof r.external.notify == \"function\";\n}\nfunction te(r) {\n return \"TelegramWebviewProxy\" in r && H(r.TelegramWebviewProxy) && \"postEvent\" in r.TelegramWebviewProxy && typeof r.TelegramWebviewProxy.postEvent == \"function\";\n}\nfunction vt() {\n try {\n return window.self !== window.top;\n } catch {\n return !0;\n }\n}\nclass tt extends Error {\n constructor(t, e) {\n super(`Method \"${t}\" is unsupported in the Mini Apps version ${e}.`), Object.setPrototypeOf(this, tt.prototype);\n }\n}\nclass et extends Error {\n constructor(t, e, s) {\n super(`Parameter \"${e}\" in method \"${t}\" is unsupported in the Mini Apps version ${s}.`), Object.setPrototypeOf(this, et.prototype);\n }\n}\nclass Pt {\n constructor(t, e) {\n this.prefix = t, this.enabled = e;\n }\n /**\n * Prints message into a console in case, logger is currently enabled.\n * @param level - log level.\n * @param args - arguments.\n */\n print(t, ...e) {\n if (!this.enabled)\n return;\n const s = /* @__PURE__ */ new Date(), n = Intl.DateTimeFormat(\"en-GB\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n fractionalSecondDigits: 3,\n timeZone: \"UTC\"\n }).format(s);\n console[t](`[${n}]`, this.prefix, ...e);\n }\n /**\n * Disables the logger.\n */\n disable() {\n this.enabled = !1;\n }\n /**\n * Prints error message into a console.\n * @param args\n */\n error(...t) {\n this.print(\"error\", ...t);\n }\n /**\n * Enables the logger.\n */\n enable() {\n this.enabled = !0;\n }\n /**\n * Prints log message into a console.\n * @param args\n */\n log(...t) {\n this.print(\"log\", ...t);\n }\n /**\n * Prints warning message into a console.\n * @param args\n */\n warn(...t) {\n this.print(\"warn\", ...t);\n }\n}\nlet kt = \"https://web.telegram.org\";\nconst V = new Pt(\"[SDK]\", !1);\nfunction nr(r) {\n if (r) {\n V.enable();\n return;\n }\n V.disable();\n}\nfunction ir(r) {\n kt = r;\n}\nfunction ee() {\n return kt;\n}\nconst re = f({\n eventType: u(),\n eventData: (r) => r\n});\nfunction se(r) {\n return re.parse(r);\n}\nfunction ne(r, t) {\n window.dispatchEvent(new MessageEvent(\"message\", {\n data: JSON.stringify({ eventType: r, eventData: t })\n }));\n}\nfunction ie() {\n const r = window;\n \"TelegramGameProxy_receiveEvent\" in r || [\n [\"TelegramGameProxy_receiveEvent\"],\n // Windows Phone.\n [\"TelegramGameProxy\", \"receiveEvent\"],\n // Desktop.\n [\"Telegram\", \"WebView\", \"receiveEvent\"]\n // Android and iOS.\n ].forEach((t) => {\n let e = r;\n t.forEach((s, n, i) => {\n if (n === i.length - 1) {\n e[s] = ne;\n return;\n }\n s in e || (e[s] = {}), e = e[s];\n });\n });\n}\nfunction oe(r) {\n ie(), window.addEventListener(\"message\", (t) => {\n try {\n const { eventType: e, eventData: s } = se(t.data);\n r(e, s);\n } catch {\n }\n });\n}\nfunction ae() {\n return f({\n req_id: u(),\n data: (r) => r === null ? r : u().optional().parse(r)\n });\n}\nfunction ce() {\n return f({\n req_id: u(),\n result: (r) => r,\n error: u().optional()\n });\n}\nfunction ue() {\n return f({\n slug: u(),\n status: u()\n });\n}\nfunction he() {\n return f({ status: u() });\n}\nfunction pe() {\n return f({\n button_id: (r) => r == null ? void 0 : u().parse(r)\n });\n}\nfunction le() {\n return f({\n data: u().optional()\n });\n}\nfunction de() {\n return f({\n theme_params: (r) => {\n const t = gt().optional();\n return Object.entries(Y(r)).reduce((e, [s, n]) => (e[s] = t.parse(n), e), {});\n }\n });\n}\nfunction fe() {\n return f({\n height: q(),\n width: (r) => r == null ? window.innerWidth : q().parse(r),\n is_state_stable: k(),\n is_expanded: k()\n });\n}\nfunction ge() {\n return f({ status: u() });\n}\nfunction we() {\n const r = new w(), t = (e, ...s) => {\n V.log(\"Emitting processed event:\", e, ...s), r.emit(e, ...s);\n };\n return window.addEventListener(\"resize\", () => {\n t(\"viewport_changed\", {\n width: window.innerWidth,\n height: window.innerHeight,\n is_state_stable: !0,\n is_expanded: !0\n });\n }), oe((e, s) => {\n V.log(\"Received raw event:\", e, s);\n try {\n switch (e) {\n case \"viewport_changed\":\n return t(e, fe().parse(s));\n case \"theme_changed\":\n return t(e, de().parse(s));\n case \"popup_closed\":\n return (\n // Sent on desktop.\n s == null ? t(e, {}) : t(e, pe().parse(s))\n );\n case \"set_custom_style\":\n return t(e, u().parse(s));\n case \"qr_text_received\":\n return t(e, le().parse(s));\n case \"clipboard_text_received\":\n return t(e, ae().parse(s));\n case \"invoice_closed\":\n return t(e, ue().parse(s));\n case \"phone_requested\":\n return t(\"phone_requested\", he().parse(s));\n case \"custom_method_invoked\":\n return t(\"custom_method_invoked\", ce().parse(s));\n case \"write_access_requested\":\n return t(\"write_access_requested\", ge().parse(s));\n case \"main_button_pressed\":\n case \"back_button_pressed\":\n case \"settings_button_pressed\":\n case \"scan_qr_popup_closed\":\n case \"reload_iframe\":\n return t(e);\n default:\n return t(e, s);\n }\n } catch (n) {\n V.error(\"Error processing event:\", n);\n }\n }), r;\n}\nconst Q = \"telegram-mini-apps-cached-emitter\";\nfunction U() {\n const r = window;\n return r[Q] === void 0 && (r[Q] = we()), r[Q];\n}\nfunction $(r, t) {\n U().off(r, t);\n}\nfunction y(r, t) {\n return U().on(r, t), () => $(r, t);\n}\nfunction or(r, t) {\n return U().once(r, t), () => $(r, t);\n}\nfunction _e(r) {\n U().unsubscribe(r);\n}\nfunction ar(r) {\n return U().subscribe(r), () => _e(r);\n}\nfunction be(r, t) {\n const e = r.split(\".\"), s = t.split(\".\"), n = Math.max(e.length, s.length);\n for (let i = 0; i < n; i += 1) {\n const a = parseInt(e[i] || \"0\", 10), c = parseInt(s[i] || \"0\", 10);\n if (a !== c)\n return a > c ? 1 : -1;\n }\n return 0;\n}\nfunction P(r, t) {\n return be(r, t) <= 0;\n}\nfunction R(r, t, e) {\n if (typeof e == \"string\") {\n if (r === \"web_app_open_link\" && t === \"try_instant_view\")\n return P(\"6.4\", e);\n if (r === \"web_app_set_header_color\" && t === \"color\")\n return P(\"6.9\", e);\n }\n switch (r) {\n case \"web_app_open_tg_link\":\n case \"web_app_open_invoice\":\n case \"web_app_setup_back_button\":\n case \"web_app_set_background_color\":\n case \"web_app_set_header_color\":\n case \"web_app_trigger_haptic_feedback\":\n return P(\"6.1\", t);\n case \"web_app_open_popup\":\n return P(\"6.2\", t);\n case \"web_app_close_scan_qr_popup\":\n case \"web_app_open_scan_qr_popup\":\n case \"web_app_read_text_from_clipboard\":\n return P(\"6.4\", t);\n case \"web_app_switch_inline_query\":\n return P(\"6.7\", t);\n case \"web_app_invoke_custom_method\":\n case \"web_app_request_write_access\":\n case \"web_app_request_phone\":\n return P(\"6.9\", t);\n case \"web_app_setup_settings_button\":\n return P(\"6.10\", t);\n default:\n return !0;\n }\n}\nfunction E(r, t) {\n return (e) => R(t[e], r);\n}\nfunction St(r, t) {\n return (e) => {\n const [s, n] = t[e];\n return R(s, n, r);\n };\n}\nfunction d(r, t, e) {\n let s = {}, n;\n t === void 0 && e === void 0 ? s = {} : t !== void 0 && e !== void 0 ? (s = e, n = t) : t !== void 0 && (\"targetOrigin\" in t ? s = t : n = t);\n const { targetOrigin: i = ee() } = s;\n if (V.log(`Calling method \"${r}\"`, n), vt()) {\n window.parent.postMessage(JSON.stringify({\n eventType: r,\n eventData: n\n }), i);\n return;\n }\n if (Xt(window)) {\n window.external.notify(JSON.stringify({ eventType: r, eventData: n }));\n return;\n }\n if (te(window)) {\n window.TelegramWebviewProxy.postEvent(r, JSON.stringify(n));\n return;\n }\n throw new Error(\n \"Unable to determine current environment and possible way to send event.\"\n );\n}\nfunction me(r) {\n return (t, e) => {\n if (!R(t, r))\n throw new tt(t, r);\n if (H(e)) {\n let s;\n if (t === \"web_app_open_link\" && \"try_instant_view\" in e ? s = \"try_instant_view\" : t === \"web_app_set_header_color\" && \"color\" in e && (s = \"color\"), s && !R(t, s, r))\n throw new et(t, s, r);\n }\n return d(t, e);\n };\n}\nclass J extends Error {\n constructor(t) {\n super(`Async call timeout exceeded. Timeout: ${t}`), Object.setPrototypeOf(this, J.prototype);\n }\n}\nfunction cr(r) {\n return r instanceof J;\n}\nfunction ye(r) {\n return new Promise((t) => {\n setTimeout(t, r);\n });\n}\nfunction Ee(r) {\n return new Promise((t, e) => {\n setTimeout(e, r, new J(r));\n });\n}\nfunction xt(r, t) {\n return Promise.race([\n r(),\n Ee(t)\n ]);\n}\nfunction m(r, t, e, s) {\n let n, i, a, c;\n typeof t == \"string\" || Array.isArray(t) ? (a = Array.isArray(t) ? t : [t], n = e) : (i = t, a = Array.isArray(e) ? e : [e], n = s), H(i) && typeof i.req_id == \"string\" && (c = i.req_id);\n const { postEvent: p = d, timeout: h } = n || {}, g = n && \"capture\" in n ? n.capture : null, _ = () => new Promise((A, l) => {\n const C = a.map((v) => y(v, (M) => {\n c && (!H(M) || M.req_id !== c) || typeof g == \"function\" && !g(M) || (x(), A(M));\n })), x = () => C.forEach((v) => v());\n try {\n p(r, i);\n } catch (v) {\n x(), l(v);\n }\n });\n return typeof h == \"number\" ? xt(_, h) : _();\n}\nasync function O(r, t, e, s = {}) {\n const { result: n, error: i } = await m(\n \"web_app_invoke_custom_method\",\n {\n method: r,\n params: t,\n req_id: e\n },\n \"custom_method_invoked\",\n s\n );\n if (i)\n throw new Error(i);\n return n;\n}\nclass Ce {\n constructor(t, e, s = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"on\", (t, e) => t === \"click\" ? y(\"back_button_pressed\", e) : this.ee.on(t, e));\n /**\n * Removes event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"off\", (t, e) => t === \"click\" ? $(\"back_button_pressed\", e) : this.ee.off(t, e));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = s, this.state = new b({ isVisible: t }, this.ee), this.supports = E(e, {\n show: \"web_app_setup_back_button\",\n hide: \"web_app_setup_back_button\"\n });\n }\n set isVisible(t) {\n this.state.set(\"isVisible\", t), this.postEvent(\"web_app_setup_back_button\", { is_visible: t });\n }\n /**\n * True if BackButton is currently visible.\n */\n get isVisible() {\n return this.state.get(\"isVisible\");\n }\n /**\n * Hides the BackButton.\n */\n hide() {\n this.isVisible = !1;\n }\n /**\n * Shows the BackButton.\n */\n show() {\n this.isVisible = !0;\n }\n}\nfunction nt(r, t) {\n return r + (r.length > 0 && t.length > 0 ? ` ${t}` : t);\n}\nfunction ve(...r) {\n return r.reduce((t, e) => {\n let s = \"\";\n return typeof e == \"string\" ? s = e : typeof e == \"object\" && e !== null && (s = Object.entries(e).reduce((n, [i, a]) => a ? nt(n, i) : n, \"\")), nt(t, s);\n }, \"\");\n}\nfunction Pe(r) {\n return typeof r == \"object\" && r !== null && !Array.isArray(null);\n}\nfunction ur(...r) {\n return r.reduce((t, e) => (Pe(e) && Object.entries(e).forEach(([s, n]) => {\n const i = ve(t[s], n);\n i.length > 0 && (t[s] = i);\n }), t), {});\n}\nclass ke {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n this.postEvent = e, this.state = new b({ isConfirmationNeeded: t }, this.ee);\n }\n set isConfirmationNeeded(t) {\n this.state.set(\"isConfirmationNeeded\", t), this.postEvent(\"web_app_setup_closing_behavior\", { need_confirmation: t });\n }\n /**\n * Returns true, if the confirmation dialog enabled while the user is trying\n * to close the Mini App.\n */\n get isConfirmationNeeded() {\n return this.state.get(\"isConfirmationNeeded\");\n }\n /**\n * Disables the confirmation dialog while the user is trying to close the\n * Mini App.\n */\n disableConfirmation() {\n this.isConfirmationNeeded = !1;\n }\n /**\n * Enables the confirmation dialog while the user is trying to close the\n * Mini App.\n */\n enableConfirmation() {\n this.isConfirmationNeeded = !0;\n }\n}\nfunction it(r, t) {\n return r.reduce((e, s) => (e[s] = t, e), {});\n}\nclass Se {\n constructor(t, e, s = d) {\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.createRequestId = e, this.postEvent = s, this.supports = E(t, {\n delete: \"web_app_invoke_custom_method\",\n get: \"web_app_invoke_custom_method\",\n getKeys: \"web_app_invoke_custom_method\",\n set: \"web_app_invoke_custom_method\"\n });\n }\n /**\n * Deletes specified key or keys from the cloud storage.\n * @param keyOrKeys - key or keys to delete.\n * @param options - request execution options.\n */\n async delete(t, e = {}) {\n const s = Array.isArray(t) ? t : [t];\n s.length !== 0 && await O(\n \"deleteStorageValues\",\n { keys: s },\n this.createRequestId(),\n { ...e, postEvent: this.postEvent }\n );\n }\n /**\n * Returns list of all keys presented in the cloud storage.\n * @param options - request execution options.\n */\n async getKeys(t = {}) {\n const e = await O(\n \"getStorageKeys\",\n {},\n this.createRequestId(),\n { ...t, postEvent: this.postEvent }\n );\n return Bt().of(u()).parse(e);\n }\n async get(t, e = {}) {\n const s = Array.isArray(t) ? t : [t];\n if (s.length === 0)\n return it(s, \"\");\n const n = f(\n it(s, u())\n ), i = await O(\n \"getStorageValues\",\n { keys: s },\n this.createRequestId(),\n { ...e, postEvent: this.postEvent }\n ).then((a) => n.parse(a));\n return Array.isArray(t) ? i : i[t];\n }\n /**\n * Saves specified value by key.\n * @param key - storage key.\n * @param value - storage value.\n * @param options - request execution options.\n */\n async set(t, e, s = {}) {\n await O(\n \"saveStorageValue\",\n { key: t, value: e },\n this.createRequestId(),\n { ...s, postEvent: this.postEvent }\n );\n }\n}\nclass xe {\n constructor(t, e = d) {\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.supports = E(t, {\n impactOccurred: \"web_app_trigger_haptic_feedback\",\n notificationOccurred: \"web_app_trigger_haptic_feedback\",\n selectionChanged: \"web_app_trigger_haptic_feedback\"\n });\n }\n /**\n * A method tells that an impact occurred. The Telegram app may play the\n * appropriate haptics based on style value passed.\n * @param style - impact style.\n */\n impactOccurred(t) {\n this.postEvent(\"web_app_trigger_haptic_feedback\", {\n type: \"impact\",\n impact_style: t\n });\n }\n /**\n * A method tells that a task or action has succeeded, failed, or produced\n * a warning. The Telegram app may play the appropriate haptics based on\n * type value passed.\n * @param type - notification type.\n */\n notificationOccurred(t) {\n this.postEvent(\"web_app_trigger_haptic_feedback\", {\n type: \"notification\",\n notification_type: t\n });\n }\n /**\n * A method tells that the user has changed a selection. The Telegram app\n * may play the appropriate haptics.\n *\n * Do not use this feedback when the user makes or confirms a selection;\n * use it only when the selection changes.\n */\n selectionChanged() {\n this.postEvent(\"web_app_trigger_haptic_feedback\", { type: \"selection_change\" });\n }\n}\nfunction qe() {\n const r = document.createElement(\"style\");\n r.id = \"telegram-custom-styles\", document.head.appendChild(r), y(\"set_custom_style\", (t) => {\n r.innerHTML = t;\n });\n}\nfunction qt(r) {\n return `telegram-mini-apps-${r}`;\n}\nfunction T(r, t) {\n sessionStorage.setItem(qt(r), JSON.stringify(t));\n}\nfunction B(r) {\n const t = sessionStorage.getItem(qt(r));\n return t ? JSON.parse(t) : null;\n}\nfunction Ae(r, t, e) {\n const { isVisible: s = !1 } = r ? B(\"back-button\") || {} : {}, n = new Ce(s, t, e);\n return n.on(\"change\", () => {\n T(\"back-button\", { isVisible: n.isVisible });\n }), n;\n}\nfunction Ve(r, t) {\n const { isConfirmationNeeded: e = !1 } = r ? B(\"closing-behavior\") || {} : {}, s = new ke(e, t);\n return s.on(\"change\", () => T(\"closing-behavior\", {\n isConfirmationNeeded: s.isConfirmationNeeded\n })), s;\n}\nclass Re {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n o(this, \"postEvent\");\n /**\n * Adds new event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"on\", (t, e) => (\n // FIXME: Event 'main_button_pressed' is still being received on Android\n // even if the main button is disabled.\n // Issue: https://github.com/Telegram-Mini-Apps/tma.js/issues/3\n t === \"click\" ? y(\"main_button_pressed\", e) : this.ee.on(t, e)\n ));\n /**\n * Removes event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"off\", (t, e) => t === \"click\" ? $(\"main_button_pressed\", e) : this.ee.off(t, e));\n const {\n postEvent: e = d,\n text: s,\n textColor: n,\n backgroundColor: i,\n isEnabled: a,\n isVisible: c,\n isLoaderVisible: p\n } = t;\n this.postEvent = e, this.state = new b({\n backgroundColor: i,\n isEnabled: a,\n isVisible: c,\n isLoaderVisible: p,\n text: s,\n textColor: n\n }, this.ee);\n }\n /**\n * Sends current local state to Telegram application.\n */\n commit() {\n this.text !== \"\" && this.postEvent(\"web_app_setup_main_button\", {\n is_visible: this.isVisible,\n is_active: this.isEnabled,\n is_progress_visible: this.isLoaderVisible,\n text: this.text,\n color: this.backgroundColor,\n text_color: this.textColor\n });\n }\n set isEnabled(t) {\n this.setParams({ isEnabled: t });\n }\n /**\n * True if the Main Button is currently enabled.\n */\n get isEnabled() {\n return this.state.get(\"isEnabled\");\n }\n set isLoaderVisible(t) {\n this.setParams({ isLoaderVisible: t });\n }\n /**\n * True if the Main Button loader is currently visible.\n */\n get isLoaderVisible() {\n return this.state.get(\"isLoaderVisible\");\n }\n set isVisible(t) {\n this.setParams({ isVisible: t });\n }\n /**\n * True if the Main Button is currently visible.\n */\n get isVisible() {\n return this.state.get(\"isVisible\");\n }\n /**\n * The Main Button background color.\n */\n get backgroundColor() {\n return this.state.get(\"backgroundColor\");\n }\n /**\n * The Main Button text.\n */\n get text() {\n return this.state.get(\"text\");\n }\n /**\n * The Main Button text color.\n */\n get textColor() {\n return this.state.get(\"textColor\");\n }\n /**\n * Disables the Main Button.\n */\n disable() {\n return this.isEnabled = !1, this;\n }\n /**\n * Enables the Main Button.\n */\n enable() {\n return this.isEnabled = !0, this;\n }\n /**\n * Hides the Main Button.\n */\n hide() {\n return this.isVisible = !1, this;\n }\n /**\n * Hides the Main Button loader.\n */\n hideLoader() {\n return this.isLoaderVisible = !1, this;\n }\n /**\n * Shows the Main Button. Note that opening the Mini App from the attachment menu hides the\n * main button until the user interacts with the Mini App interface.\n */\n show() {\n return this.isVisible = !0, this;\n }\n /**\n * A method to show a loading indicator on the Main Button. It is recommended to display\n * loader if the action tied to the button may take a long time.\n */\n showLoader() {\n return this.isLoaderVisible = !0, this;\n }\n /**\n * Sets new Main Button text. Minimal length for text is 1 symbol, and maximum is 64 symbols.\n * @param text - new text.\n */\n setText(t) {\n return this.setParams({ text: t });\n }\n /**\n * Sets new Main Button text color.\n * @param textColor - new text color.\n */\n setTextColor(t) {\n return this.setParams({ textColor: t });\n }\n /**\n * Updates current Main Button color.\n * @param backgroundColor - color to set.\n */\n setBackgroundColor(t) {\n return this.setParams({ backgroundColor: t });\n }\n /**\n * Allows setting multiple Main Button parameters.\n * @param params - Main Button parameters.\n */\n setParams(t) {\n return this.state.set(t), this.commit(), this;\n }\n}\nfunction Ie(r, t, e, s) {\n const {\n backgroundColor: n = t,\n isEnabled: i = !1,\n isVisible: a = !1,\n isLoaderVisible: c = !1,\n textColor: p = e,\n text: h = \"\"\n } = r ? B(\"main-button\") || {} : {}, g = new Re({\n backgroundColor: n,\n isEnabled: i,\n isLoaderVisible: c,\n isVisible: a,\n postEvent: s,\n text: h,\n textColor: p\n }), _ = () => T(\"main-button\", {\n backgroundColor: g.backgroundColor,\n isEnabled: g.isEnabled,\n isLoaderVisible: g.isLoaderVisible,\n isVisible: g.isVisible,\n text: g.text,\n textColor: g.textColor\n });\n return g.on(\"change\", _), g;\n}\nconst Le = X({\n contact: f({\n userId: {\n type: q(),\n from: \"user_id\"\n },\n phoneNumber: {\n type: u(),\n from: \"phone_number\"\n },\n firstName: {\n type: u(),\n from: \"first_name\"\n },\n lastName: {\n type: u().optional(),\n from: \"last_name\"\n }\n }),\n authDate: {\n type: pt(),\n from: \"auth_date\"\n },\n hash: u()\n});\nclass $e {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n o(this, \"botInline\");\n o(this, \"postEvent\");\n o(this, \"createRequestId\");\n o(this, \"requestingPhoneAccess\", !1);\n o(this, \"requestingWriteAccess\", !1);\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n /**\n * Checks if specified method parameter is supported by current component.\n */\n o(this, \"supportsParam\");\n const {\n postEvent: e = d,\n headerColor: s,\n backgroundColor: n,\n version: i,\n botInline: a,\n createRequestId: c\n } = t, p = E(i, {\n requestPhoneAccess: \"web_app_request_phone\",\n requestWriteAccess: \"web_app_request_write_access\",\n switchInlineQuery: \"web_app_switch_inline_query\",\n setHeaderColor: \"web_app_set_header_color\",\n setBackgroundColor: \"web_app_set_background_color\"\n });\n this.postEvent = e, this.botInline = a, this.createRequestId = c, this.supports = (h) => !(!p(h) || h === \"switchInlineQuery\" && !a), this.state = new b({ backgroundColor: n, headerColor: s }, this.ee), this.supportsParam = St(i, {\n \"setHeaderColor.color\": [\"web_app_set_header_color\", \"color\"]\n });\n }\n /**\n * Attempts to get requested contact.\n */\n async getRequestedContact() {\n return O(\n \"getRequestedContact\",\n {},\n this.createRequestId(),\n {\n postEvent: this.postEvent,\n timeout: 1e4\n }\n ).then((t) => Le.parse(t));\n }\n /**\n * The Mini App background color.\n */\n get backgroundColor() {\n return this.state.get(\"backgroundColor\");\n }\n /**\n * Closes the Mini App.\n */\n close() {\n this.postEvent(\"web_app_close\");\n }\n /**\n * The Mini App header color. Could either be a header color key or RGB color.\n */\n get headerColor() {\n return this.state.get(\"headerColor\");\n }\n /**\n * True if Mini App is currently launched in bot inline mode.\n */\n get isBotInline() {\n return this.botInline;\n }\n /**\n * True if current Mini App background color recognized as dark.\n */\n get isDark() {\n return ft(this.backgroundColor);\n }\n /**\n * True if phone access is currently being requested.\n */\n get isRequestingPhoneAccess() {\n return this.requestingPhoneAccess;\n }\n /**\n * True if write access is currently being requested.\n */\n get isRequestingWriteAccess() {\n return this.requestingWriteAccess;\n }\n /**\n * Informs the Telegram app that the Mini App is ready to be displayed.\n *\n * It is recommended to call this method as early as possible, as soon as all essential\n * interface elements loaded. Once this method called, the loading placeholder is hidden\n * and the Mini App shown.\n *\n * If the method not called, the placeholder will be hidden only when the page fully loaded.\n */\n ready() {\n this.postEvent(\"web_app_ready\");\n }\n /**\n * Requests current user contact information. In contrary to requestPhoneAccess, this method\n * returns promise with contact information that rejects in case, user denied access, or request\n * failed.\n * @param options - additional options.\n */\n async requestContact({ timeout: t = 5e3 } = {}) {\n try {\n return await this.getRequestedContact();\n } catch {\n }\n if (await this.requestPhoneAccess() !== \"sent\")\n throw new Error(\"Access denied.\");\n const s = Date.now() + t;\n let n = 50;\n return xt(async () => {\n for (; Date.now() < s; ) {\n try {\n return await this.getRequestedContact();\n } catch {\n }\n await ye(n), n += 50;\n }\n throw new Error(\"Unable to retrieve requested contact.\");\n }, t);\n }\n /**\n * Requests current user phone access. Method returns promise, which resolves\n * status of the request. In case, user accepted the request, Mini App bot will receive\n * the according notification.\n *\n * To obtain the retrieved information instead, utilize the requestContact method.\n * @param options - additional options.\n * @see requestContact\n */\n requestPhoneAccess(t = {}) {\n if (this.requestingPhoneAccess)\n throw new Error(\"Phone access is already being requested.\");\n return this.requestingPhoneAccess = !0, m(\"web_app_request_phone\", \"phone_requested\", {\n ...t,\n postEvent: this.postEvent\n }).then((e) => e.status).finally(() => {\n this.requestingPhoneAccess = !1;\n });\n }\n /**\n * Requests write message access to current user.\n * @param options - additional options.\n */\n requestWriteAccess(t = {}) {\n if (this.requestingWriteAccess)\n throw new Error(\"Write access is already being requested.\");\n return this.requestingWriteAccess = !0, m(\"web_app_request_write_access\", \"write_access_requested\", {\n ...t,\n postEvent: this.postEvent\n }).then((e) => e.status).finally(() => {\n this.requestingWriteAccess = !1;\n });\n }\n /**\n * A method used to send data to the bot. When this method called, a service message sent to\n * the bot containing the data of the length up to 4096 bytes, and the Mini App closed. See the\n * field `web_app_data` in the class [Message](https://core.telegram.org/bots/api#message).\n *\n * This method is only available for Mini Apps launched via a Keyboard button.\n * @param data - data to send to bot.\n * @throws {Error} data has incorrect size.\n */\n sendData(t) {\n const { size: e } = new Blob([t]);\n if (e === 0 || e > 4096)\n throw new Error(`Passed data has incorrect size: ${e}`);\n this.postEvent(\"web_app_data_send\", { data: t });\n }\n /**\n * Updates current Mini App header color.\n * @param color - color key or RGB color.\n */\n setHeaderColor(t) {\n this.postEvent(\"web_app_set_header_color\", lt(t) ? { color: t } : { color_key: t }), this.state.set(\"headerColor\", t);\n }\n /**\n * Updates current Mini App background color.\n * @param color - RGB color.\n */\n setBackgroundColor(t) {\n this.postEvent(\"web_app_set_background_color\", { color: t }), this.state.set(\"backgroundColor\", t);\n }\n /**\n * Inserts the bot's username and the specified inline query in the current chat's input field.\n * Query may be empty, in which case only the bot's username will be inserted. The client prompts\n * the user to choose a specific chat, then opens that chat and inserts the bot's username and\n * the specified inline query in the input field.\n * @param text - text which should be inserted in the input after the current bot name. Max\n * length is 256 symbols.\n * @param chatTypes - List of chat types which could be chosen to send the message. Could be\n * empty list.\n */\n switchInlineQuery(t, e = []) {\n if (!this.supports(\"switchInlineQuery\") && !this.isBotInline)\n throw new Error(\"Method is unsupported because Mini App should be launched in inline mode.\");\n this.postEvent(\"web_app_switch_inline_query\", {\n query: t,\n chat_types: e\n });\n }\n}\nfunction Te(r, t, e, s, n, i) {\n const {\n backgroundColor: a = t,\n headerColor: c = \"bg_color\"\n } = r ? B(\"mini-app\") || {} : {}, p = new $e({\n headerColor: c,\n backgroundColor: a,\n version: e,\n botInline: s,\n createRequestId: n,\n postEvent: i\n }), h = () => T(\"mini-app\", {\n backgroundColor: p.backgroundColor,\n headerColor: p.headerColor\n });\n return p.on(\"change\", h), p;\n}\nfunction Be() {\n let r = 0;\n return () => (r += 1, r.toString());\n}\nclass De {\n constructor(t, e, s = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"on\", (t, e) => t === \"click\" ? y(\"settings_button_pressed\", e) : this.ee.on(t, e));\n /**\n * Removes event listener.\n * @param event - event name.\n * @param listener - event listener.\n */\n o(this, \"off\", (t, e) => t === \"click\" ? $(\"settings_button_pressed\", e) : this.ee.off(t, e));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = s, this.state = new b({ isVisible: t }, this.ee), this.supports = E(e, {\n show: \"web_app_setup_settings_button\",\n hide: \"web_app_setup_settings_button\"\n });\n }\n set isVisible(t) {\n this.state.set(\"isVisible\", t), this.postEvent(\"web_app_setup_settings_button\", { is_visible: t });\n }\n /**\n * True if SettingsButton is currently visible.\n */\n get isVisible() {\n return this.state.get(\"isVisible\");\n }\n /**\n * Hides the SettingsButton.\n */\n hide() {\n this.isVisible = !1;\n }\n /**\n * Shows the SettingsButton.\n */\n show() {\n this.isVisible = !0;\n }\n}\nfunction We(r, t, e) {\n const { isVisible: s = !1 } = r ? B(\"settings-button\") || {} : {}, n = new De(s, t, e);\n return n.on(\"change\", () => {\n T(\"settings-button\", { isVisible: n.isVisible });\n }), n;\n}\nfunction Oe(r) {\n const t = new Mt(r);\n return t.listen(), t;\n}\nfunction Ne(r) {\n return [\"macos\", \"tdesktop\", \"unigram\", \"web\", \"weba\"].includes(r);\n}\nasync function At(r) {\n const t = await m(\"web_app_request_viewport\", \"viewport_changed\", r);\n return {\n height: t.height,\n width: t.width,\n isExpanded: t.is_expanded,\n isStateStable: t.is_state_stable\n };\n}\nfunction D(r) {\n return r < 0 ? 0 : r;\n}\nclass He {\n constructor(t) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n o(this, \"postEvent\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n const {\n height: e,\n isExpanded: s,\n width: n,\n stableHeight: i,\n postEvent: a = d\n } = t;\n this.postEvent = a, this.state = new b({\n height: D(e),\n isExpanded: s,\n stableHeight: D(i),\n width: D(n)\n }, this.ee);\n }\n /**\n * Request viewport information from the Telegram application and updates current Viewport\n * instance.\n * @param options - options to request fresh data.\n */\n sync(t) {\n return At(t).then(({ height: e, isExpanded: s, width: n, isStateStable: i }) => {\n this.state.set({\n height: e,\n width: n,\n isExpanded: s,\n stableHeight: i ? e : this.state.get(\"stableHeight\")\n });\n });\n }\n /**\n * The current height of the visible area of the Mini App.\n *\n * The application can display just the top part of the Mini App, with its\n * lower part remaining outside the screen area. From this position, the\n * user can \"pull\" the Mini App to its maximum height, while the bot can do\n * the same by calling `expand` method. As the position of the Mini App\n * changes, the current height value of the visible area will be updated\n * in real time.\n *\n * Please note that the refresh rate of this value is not sufficient\n * to smoothly follow the lower border of the window. It should not be\n * used to pin interface elements to the bottom of the visible area. It's\n * more appropriate to use the value of the `stableHeight`\n * field for this purpose.\n */\n get height() {\n return this.state.get(\"height\");\n }\n /**\n * The height of the visible area of the Mini App in its last stable state.\n *\n * The application can display just the top part of the Mini App, with its\n * lower part remaining outside the screen area. From this position,\n * the user can \"pull\" the Mini App to its maximum height, while the bot can\n * do the same by calling `expand` method.\n *\n * Unlike the value of `height`, the value of `stableHeight`\n * does not change as the position of the Mini App changes with user\n * gestures or during animations. The value of `stableHeight`\n * will be updated after all gestures and animations are completed and\n * the Mini App reaches its final size.\n */\n get stableHeight() {\n return this.state.get(\"stableHeight\");\n }\n /**\n * Starts listening to viewport changes and applies them.\n * @returns Function to stop listening.\n */\n listen() {\n return y(\"viewport_changed\", (t) => {\n const {\n height: e,\n width: s,\n is_expanded: n,\n is_state_stable: i\n } = t, a = {\n height: D(e),\n isExpanded: n,\n width: D(s)\n };\n i && (a.stableHeight = a.height), this.state.set(a);\n });\n }\n /**\n * Returns true if the Mini App is expanded to the maximum available height.\n * Otherwise, if the Mini App occupies part of the screen and can be expanded\n * to the full height using `expand` method.\n * @see expand\n */\n get isExpanded() {\n return this.state.get(\"isExpanded\");\n }\n /**\n * Current viewport width.\n */\n get width() {\n return this.state.get(\"width\");\n }\n /**\n * A method that expands the Mini App to the maximum available height. To\n * find out if the Mini App is expanded to the maximum height, refer to the\n * value of the `isExpanded`.\n * @see isExpanded\n */\n expand() {\n this.postEvent(\"web_app_expand\"), this.state.set(\"isExpanded\", !0);\n }\n /**\n * Returns true in case current viewport height is stable and is not going to\n * change in the next moment.\n */\n get isStable() {\n return this.stableHeight === this.height;\n }\n}\nfunction j(r) {\n const t = new He(r);\n return t.on(\"change\", () => T(\"viewport\", {\n height: t.height,\n isExpanded: t.isExpanded,\n stableHeight: t.stableHeight,\n width: t.width\n })), t.listen(), t;\n}\nfunction Ue(r, t, e, s) {\n const n = r ? B(\"viewport\") : null;\n if (n)\n return j({ ...n, postEvent: e });\n if (Ne(t))\n return j({\n height: window.innerHeight,\n isExpanded: !0,\n postEvent: e,\n stableHeight: window.innerHeight,\n width: window.innerWidth\n });\n if (s)\n return At({\n postEvent: e,\n timeout: 5e3\n }).then(({ height: a, isStateStable: c, ...p }) => j({\n ...p,\n height: a,\n stableHeight: c ? a : 0\n }));\n const i = j({\n width: 0,\n height: 0,\n isExpanded: !1,\n postEvent: e,\n stableHeight: 0\n });\n return i.sync({ postEvent: e, timeout: 5e3 }).catch((a) => {\n console.error(\"Unable to actualize viewport state\", a);\n }), i;\n}\nfunction S(r, t) {\n document.documentElement.style.setProperty(r, t);\n}\nfunction Me(r, t) {\n const e = () => {\n S(\"--tg-background-color\", r.backgroundColor);\n }, s = () => {\n const {\n backgroundColor: n,\n secondaryBackgroundColor: i\n } = t;\n r.headerColor === \"bg_color\" ? n && S(\"--tg-header-color\", n) : r.headerColor === \"secondary_bg_color\" ? i && S(\"--tg-header-color\", i) : S(\"--tg-header-color\", r.headerColor);\n };\n t.on(\"change\", s), r.on(\"change:backgroundColor\", e), r.on(\"change:headerColor\", s), e(), s();\n}\nfunction je(r) {\n const t = () => {\n const e = r.getState();\n Object.entries(e).forEach(([s, n]) => {\n if (n) {\n const i = s.replace(/[A-Z]/g, (a) => `-${a.toLowerCase()}`);\n S(`--tg-theme-${i}`, n);\n }\n });\n };\n r.on(\"change\", t), t();\n}\nfunction ot(r) {\n const t = () => S(\"--tg-viewport-height\", `${r.height}px`), e = () => S(\"--tg-viewport-width\", `${r.width}px`), s = () => S(\"--tg-viewport-height\", `${r.stableHeight}px`);\n r.on(\"change:height\", t), r.on(\"change:width\", e), r.on(\"change:stableHeight\", s), t(), e(), s();\n}\nfunction Ge(r) {\n return typeof r == \"object\" ? r : r ? {\n themeParams: !0,\n viewport: !0,\n miniApp: !0\n } : {};\n}\nfunction at(r, t, e, s) {\n const n = Ge(r);\n n.miniApp && Me(t, e), n.themeParams && je(e), n.viewport && (s instanceof Promise ? s.then(ot) : ot(s));\n}\nfunction Fe(r) {\n const { hostname: t, pathname: e } = new URL(r, window.location.href);\n if (t !== \"t.me\")\n throw new Error(`Incorrect hostname: ${t}`);\n const s = e.match(/^\\/(\\$|invoice\\/)([A-Za-z0-9\\-_=]+)$/);\n if (s === null)\n throw new Error('Link pathname has incorrect format. Expected to receive \"/invoice/{slug}\" or \"/${slug}\"');\n return s[2];\n}\nclass ze {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.state = new b({ isOpened: !1 }, this.ee), this.supports = E(t, { open: \"web_app_open_invoice\" });\n }\n set isOpened(t) {\n this.state.set(\"isOpened\", t);\n }\n /**\n * True if invoice is currently opened.\n */\n get isOpened() {\n return this.state.get(\"isOpened\");\n }\n async open(t, e) {\n if (this.isOpened)\n throw new Error(\"Invoice is already opened\");\n const s = e ? Fe(t) : t;\n this.isOpened = !0;\n try {\n return (await m(\n \"web_app_open_invoice\",\n { slug: s },\n \"invoice_closed\",\n {\n postEvent: this.postEvent,\n capture(i) {\n return s === i.slug;\n }\n }\n )).status;\n } finally {\n this.isOpened = !1;\n }\n }\n}\nfunction Je(r) {\n const t = r.message.trim(), e = (r.title || \"\").trim(), s = r.buttons || [];\n let n;\n if (e.length > 64)\n throw new Error(`Title has incorrect size: ${e.length}`);\n if (t.length === 0 || t.length > 256)\n throw new Error(`Message has incorrect size: ${t.length}`);\n if (s.length > 3)\n throw new Error(`Buttons have incorrect size: ${s.length}`);\n return s.length === 0 ? n = [{ type: \"close\", id: \"\" }] : n = s.map((i) => {\n const { id: a = \"\" } = i;\n if (a.length > 64)\n throw new Error(`Button ID has incorrect size: ${a}`);\n if (i.type === void 0 || i.type === \"default\" || i.type === \"destructive\") {\n const c = i.text.trim();\n if (c.length === 0 || c.length > 64) {\n const p = i.type || \"default\";\n throw new Error(`Button text with type \"${p}\" has incorrect size: ${i.text.length}`);\n }\n return { ...i, text: c, id: a };\n }\n return { ...i, id: a };\n }), { title: e, message: t, buttons: n };\n}\nclass Qe {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.state = new b({ isOpened: !1 }, this.ee), this.supports = E(t, { open: \"web_app_open_popup\" });\n }\n set isOpened(t) {\n this.state.set(\"isOpened\", t);\n }\n /**\n * True if popup is currently opened.\n */\n get isOpened() {\n return this.state.get(\"isOpened\");\n }\n /**\n * A method that shows a native popup described by the `params` argument.\n * Promise will be resolved when popup is closed. Resolved value will have\n * an identifier of pressed button.\n *\n * In case, user clicked outside the popup or clicked top right popup close\n * button, null will be returned.\n *\n * FIXME: In desktop, this function may work incorrectly.\n * Issue: https://github.com/Telegram-Mini-Apps/tma.js/issues/7\n * @param options - popup parameters.\n * @throws {Error} Popup is already opened.\n */\n open(t) {\n if (this.isOpened)\n throw new Error(\"Popup is already opened.\");\n return this.isOpened = !0, m(\n \"web_app_open_popup\",\n Je(t),\n \"popup_closed\",\n { postEvent: this.postEvent }\n ).then(({ button_id: e = null }) => e).finally(() => {\n this.isOpened = !1;\n });\n }\n}\nclass Ze {\n constructor(t, e = d) {\n o(this, \"ee\", new w());\n o(this, \"state\");\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n this.postEvent = e, this.state = new b({ isOpened: !1 }, this.ee), this.supports = E(t, {\n close: \"web_app_close_scan_qr_popup\",\n open: \"web_app_open_scan_qr_popup\"\n });\n }\n /**\n * Closes scanner.\n */\n close() {\n this.postEvent(\"web_app_close_scan_qr_popup\"), this.isOpened = !1;\n }\n set isOpened(t) {\n this.state.set(\"isOpened\", t);\n }\n /**\n * Returns true in case, QR scanner is currently opened.\n */\n get isOpened() {\n return this.state.get(\"isOpened\");\n }\n /**\n * Opens scanner with specified title shown to user. Method returns promise\n * with scanned QR content in case, it was scanned. It will contain null in\n * case, scanner was closed.\n * @param text - title to display.\n */\n async open(t) {\n if (this.isOpened)\n throw new Error(\"QR scanner is already opened.\");\n this.isOpened = !0;\n try {\n const e = await m(\n \"web_app_open_scan_qr_popup\",\n { text: t },\n [\"qr_text_received\", \"scan_qr_popup_closed\"],\n { postEvent: this.postEvent }\n );\n return typeof e == \"object\" && typeof e.data == \"string\" ? e.data : null;\n } finally {\n this.isOpened = !1;\n }\n }\n}\nclass Ke {\n constructor(t, e, s = d) {\n /**\n * Checks if specified method is supported by current component.\n */\n o(this, \"supports\");\n /**\n * Checks if specified method parameter is supported by current component.\n */\n o(this, \"supportsParam\");\n this.version = t, this.createRequestId = e, this.postEvent = s, this.supports = E(t, {\n readTextFromClipboard: \"web_app_read_text_from_clipboard\"\n }), this.supportsParam = St(t, {\n \"openLink.tryInstantView\": [\"web_app_open_link\", \"try_instant_view\"]\n });\n }\n /**\n * Opens a link in an external browser. The Mini App will not be closed.\n *\n * Note that this method can be called only in response to the user\n * interaction with the Mini App interface (e.g. click inside the Mini App\n * or on the main button).\n * @param url - URL to be opened.\n * @param tryInstantView\n */\n openLink(t, e) {\n const s = new URL(t, window.location.href).toString();\n if (!R(\"web_app_open_link\", this.version)) {\n window.open(s, \"_blank\");\n return;\n }\n this.postEvent(\"web_app_open_link\", {\n url: s,\n ...typeof e == \"boolean\" ? { try_instant_view: e } : {}\n });\n }\n /**\n * Opens a Telegram link inside Telegram app. The Mini App will be closed. It expects passing\n * link in full format, with hostname \"t.me\".\n * @param url - URL to be opened.\n * @throws {Error} URL has not allowed hostname.\n */\n openTelegramLink(t) {\n const {\n hostname: e,\n pathname: s,\n search: n\n } = new URL(t, window.location.href);\n if (e !== \"t.me\")\n throw new Error(`URL has not allowed hostname: ${e}. Only \"t.me\" is allowed`);\n if (!R(\"web_app_open_tg_link\", this.version)) {\n window.location.href = t;\n return;\n }\n this.postEvent(\"web_app_open_tg_link\", { path_full: s + n });\n }\n /**\n * Reads text from clipboard and returns string or null. null is returned\n * in cases:\n * - Value in clipboard is not text\n * - Access to clipboard is not allowed\n */\n readTextFromClipboard() {\n return m(\n \"web_app_read_text_from_clipboard\",\n { req_id: this.createRequestId() },\n \"clipboard_text_received\",\n { postEvent: this.postEvent }\n ).then(({ data: t = null }) => t);\n }\n}\nfunction hr(r = {}) {\n const {\n async: t = !1,\n complete: e = t,\n cssVars: s = !1,\n acceptCustomStyles: n = !1\n } = r;\n try {\n const {\n launchParams: {\n initData: i,\n initDataRaw: a,\n version: c,\n platform: p,\n themeParams: h,\n botInline: g = !1\n },\n isPageReload: _\n } = Ct(), A = Be(), l = me(c);\n vt() && (n && qe(), l(\"iframe_ready\", { reload_supported: !0 }), y(\"reload_iframe\", () => window.location.reload()));\n const C = {\n backButton: Ae(_, c, l),\n closingBehavior: Ve(_, l),\n cloudStorage: new Se(c, A, l),\n createRequestId: A,\n hapticFeedback: new xe(c, l),\n invoice: new ze(c, l),\n mainButton: Ie(\n _,\n h.buttonColor || \"#000000\",\n h.buttonTextColor || \"#ffffff\",\n l\n ),\n miniApp: Te(\n _,\n h.backgroundColor || \"#ffffff\",\n c,\n g,\n A,\n l\n ),\n popup: new Qe(c, l),\n postEvent: l,\n qrScanner: new Ze(c, l),\n settingsButton: We(_, c, l),\n themeParams: Oe(h),\n utils: new Ke(c, A, l),\n ...i ? {\n initData: new Ot(i),\n initDataRaw: a\n } : {}\n }, x = Ue(_, p, l, e);\n return x instanceof Promise || e ? Promise.resolve(x).then((v) => (at(\n s,\n C.miniApp,\n C.themeParams,\n v\n ), { ...C, viewport: v })) : (at(\n s,\n C.miniApp,\n C.themeParams,\n x\n ), { ...C, viewport: x });\n } catch (i) {\n if (e)\n return Promise.reject(i);\n throw i;\n }\n}\nfunction W(r, t) {\n return r.startsWith(t) ? r : `${t}${r}`;\n}\nfunction pr(r) {\n const t = r.match(/#(.+)/);\n return t ? t[1] : null;\n}\nasync function N(r) {\n return r === 0 ? !0 : Promise.race([\n new Promise((t) => {\n window.addEventListener(\"popstate\", function e() {\n window.removeEventListener(\"popstate\", e), t(!0);\n }), window.history.go(r);\n }),\n // Usually, it takes about 1ms to emit this event, but we use some buffer.\n new Promise((t) => {\n setTimeout(t, 50, !1);\n })\n ]);\n}\nasync function Ye() {\n if (window.history.length <= 1 || (window.history.pushState(null, \"\"), await N(1 - window.history.length)))\n return;\n let t = await N(-1);\n for (; t; )\n t = await N(-1);\n}\nclass Xe {\n constructor(t, e, {\n debug: s = !1,\n loggerPrefix: n = \"Navigator\"\n }) {\n o(this, \"logger\");\n o(this, \"entries\");\n if (this.entriesCursor = e, t.length === 0)\n throw new Error(\"Entries list should not be empty.\");\n if (e >= t.length)\n throw new Error(\"Cursor should be less than entries count.\");\n this.entries = t.map(({ pathname: i = \"\", search: a, hash: c }) => {\n if (!i.startsWith(\"/\") && i.length > 0)\n throw new Error('Pathname should start with \"/\"');\n return {\n pathname: W(i, \"/\"),\n search: a ? W(a, \"?\") : \"\",\n hash: c ? W(c, \"#\") : \"\"\n };\n }), this.logger = new Pt(`[${n}]`, s);\n }\n /**\n * Converts entry to the navigation entry.\n * @param entry - entry data\n */\n formatEntry(t) {\n let e;\n if (typeof t == \"string\")\n e = t;\n else {\n const {\n pathname: a = \"\",\n search: c,\n hash: p\n } = t;\n e = a + (c ? W(c, \"?\") : \"\") + (p ? W(p, \"#\") : \"\");\n }\n const {\n pathname: s,\n search: n,\n hash: i\n } = new URL(e, `https://localhost${this.path}`);\n return {\n pathname: s,\n search: n,\n hash: i\n };\n }\n /**\n * Current entry.\n */\n get entry() {\n return this.entries[this.entriesCursor];\n }\n /**\n * Goes back in history.\n */\n back() {\n return this.go(-1);\n }\n /**\n * Current entries cursor.\n */\n get cursor() {\n return this.entriesCursor;\n }\n /**\n * True if navigator can go back.\n */\n get canGoBack() {\n return this.entriesCursor > 0;\n }\n /**\n * True if navigator can go forward.\n */\n get canGoForward() {\n return this.entriesCursor !== this.entries.length - 1;\n }\n /**\n * Goes forward in history.\n */\n forward() {\n return this.go(1);\n }\n /**\n * Moves entries cursor by specified delta.\n * @param delta - cursor delta.\n */\n go(t) {\n this.logger.log(`called go(${t})`);\n const e = Math.min(\n this.entries.length - 1,\n Math.max(this.entriesCursor + t, 0)\n );\n if (this.entriesCursor === e)\n return this.performGo({\n updated: !1,\n delta: t\n });\n const s = this.entry;\n this.entriesCursor = e;\n const n = this.entry;\n return this.logger.log(\"State changed\", { before: s, after: n }), this.performGo({\n updated: !0,\n delta: t,\n before: s,\n after: n\n });\n }\n /**\n * Returns copy of navigator entries.\n */\n getEntries() {\n return this.entries.map((t) => ({ ...t }));\n }\n /**\n * Current hash.\n * @example\n * \"\", \"#\", \"#hash\"\n */\n get hash() {\n return this.entry.hash;\n }\n /**\n * Pushes new entry. Method replaces all entries after the current one with the inserted.\n * @param entry - entry data.\n *\n * @example Pushing absolute pathname.\n * push(\"/absolute-path\"); // \"/absolute-path\"\n *\n * @example Pushing relative pathname.\n * // Pushing relative path replaces N last path parts, where N is pushed pathname parts count.\n * // Pushing empty path is recognized as relative, but not replacing the last pathname part.\n * push(\"relative\"); // \"/home/root\" -> \"/home/relative\"\n *\n * @example Pushing query parameters.\n * push(\"/absolute?my-param=1\"); // \"/home\" -> \"/absolute?my-param=1\"\n * push(\"relative?my-param=1\"); // \"/home/root\" -> \"/home/relative?my-param=1\"\n * push(\"?my-param=1\"); // \"/home\" -> \"/home?my-param=1\"\n *\n * @example Pushing hash.\n * push(\"#my-hash\"); // \"/home\" -> \"/home#my-hash\"\n * push(\"johny#my-hash\"); // \"/home/root\" -> \"/home/johny#my-hash\"\n */\n push(t) {\n this.entriesCursor !== this.entries.length - 1 && this.entries.splice(this.entriesCursor + 1);\n const e = this.formatEntry(t), s = this.entry;\n this.entriesCursor += 1, this.entries[this.entriesCursor] = e;\n const n = this.entry;\n return this.logger.log(\"State changed\", { before: s, after: n }), this.performPush({\n before: s,\n after: n\n });\n }\n /**\n * Current full path including pathname, query parameters and hash.\n */\n get path() {\n return `${this.pathname}${this.search}${this.hash}`;\n }\n /**\n * Current pathname.\n * @example\n * \"/\", \"/abc\"\n */\n get pathname() {\n return this.entry.pathname;\n }\n /**\n * Replaces current entry. Has the same logic as `push` method.\n * @param entry - entry data.\n * @see push\n * @returns True if changes were done.\n */\n replace(t) {\n const e = this.formatEntry(t);\n if (this.search === e.search && this.pathname === e.pathname && this.hash === e.hash)\n return this.performReplace({\n updated: !1,\n entry: e\n });\n const s = this.entry;\n this.entries[this.entriesCursor] = e;\n const n = this.entry;\n return this.logger.log(\"State changed\", { before: s, after: n }), this.performReplace({\n updated: !0,\n before: s,\n after: n\n });\n }\n /**\n * Current query parameters.\n * @example\n * \"\", \"?\", \"?a=1\"\n */\n get search() {\n return this.entry.search;\n }\n}\nconst ct = 0, Z = 1, K = 2;\nclass Vt extends Xe {\n constructor(e, s, n = {}) {\n super(e, s, {\n ...n,\n loggerPrefix: \"HashNavigator\"\n });\n o(this, \"ee\", new w());\n o(this, \"attached\", !1);\n /**\n * Handles window \"popstate\" event.\n * @param state - event state.\n */\n o(this, \"onPopState\", async ({ state: e }) => {\n if (this.logger.log('\"popstate\" event received. State:', e), e === null)\n return this.push(window.location.hash.slice(1));\n if (e === ct) {\n this.logger.log(\"Void reached. Moving history forward\"), window.history.forward();\n return;\n }\n if (e === Z)\n return this.back();\n if (e === K)\n return this.forward();\n });\n o(this, \"back\", () => super.back());\n /**\n * Adds new event listener.\n */\n o(this, \"on\", this.ee.on.bind(this.ee));\n /**\n * Removes event listener.\n */\n o(this, \"off\", this.ee.off.bind(this.ee));\n }\n /**\n * Creates navigator from current window location hash.\n * @param options - options passed to constructor.\n */\n static fromLocation(e) {\n const {\n search: s,\n pathname: n,\n hash: i\n } = new URL(\n window.location.hash.slice(1),\n window.location.href\n );\n return new Vt([{ search: s, pathname: n, hash: i }], 0, e);\n }\n async performGo(e) {\n e.updated && (this.attached && await this.syncHistory(), this.emitChanged(e.before, e.after));\n }\n async performPush({ before: e, after: s }) {\n this.attached && await this.syncHistory(), this.emitChanged(e, s);\n }\n async performReplace(e) {\n e.updated && (this.attached && window.history.replaceState(null, \"\", `#${this.path}`), this.emitChanged(e.before, e.after));\n }\n /**\n * Synchronizes current navigator state with browser history.\n */\n async syncHistory() {\n window.removeEventListener(\"popstate\", this.onPopState);\n const e = `#${this.path}`;\n await Ye(), d(\"web_app_setup_back_button\", { is_visible: this.canGoBack }), this.canGoBack && this.canGoForward ? (this.logger.log(\"Setting up history: [<-, *, ->]\"), window.history.replaceState(Z, \"\"), window.history.pushState(null, \"\", e), window.history.pushState(K, \"\"), await N(-1)) : this.canGoBack ? (this.logger.log(\"Setting up history: [<-, *]\"), window.history.replaceState(Z, \"\"), window.history.pushState(null, \"\", e)) : this.canGoForward ? (this.logger.log(\"Setting up history: [*, ->]\"), window.history.replaceState(null, e), window.history.pushState(K, \"\"), await N(-1)) : (this.logger.log(\"Setting up history: [~, *]\"), window.history.replaceState(ct, \"\"), window.history.pushState(null, \"\", e)), window.addEventListener(\"popstate\", this.onPopState);\n }\n emitChanged(e, s) {\n this.ee.emit(\"change\", {\n navigator: this,\n from: e,\n to: s\n });\n }\n /**\n * Attaches current navigator to the browser history allowing navigator to manipulate it.\n */\n async attach() {\n if (!this.attached)\n return this.logger.log(\"Attaching\", this), this.attached = !0, y(\"back_button_pressed\", this.back), this.syncHistory();\n }\n /**\n * Detaches current navigator from the browser history.\n */\n detach() {\n this.attached && (this.logger.log(\"Detaching\", this), this.attached = !1, window.removeEventListener(\"popstate\", this.onPopState), $(\"back_button_pressed\", this.back));\n }\n}\nexport {\n Ce as BackButton,\n ke as ClosingBehavior,\n Se as CloudStorage,\n xe as HapticFeedback,\n Vt as HashNavigator,\n Ot as InitData,\n ze as Invoice,\n Re as MainButton,\n tt as MethodUnsupportedError,\n $e as MiniApp,\n Xe as Navigator,\n et as ParameterUnsupportedError,\n F as ParseError,\n G as ParseSchemaFieldError,\n Qe as Popup,\n Ze as QRScanner,\n De as SettingsButton,\n Mt as ThemeParams,\n J as TimeoutError,\n Ke as Utils,\n He as Viewport,\n Bt as array,\n k as boolean,\n Wt as chatParser,\n ve as classNames,\n be as compareVersions,\n me as createPostEvent,\n pt as date,\n pr as getHash,\n hr as init,\n wt as initDataParser,\n O as invokeCustomMethod,\n ft as isColorDark,\n vt as isIframe,\n lt as isRGB,\n Dt as isRGBShort,\n H as isRecord,\n Ne as isStableViewportPlatform,\n sr as isTMA,\n cr as isTimeoutError,\n f as json,\n mt as launchParamsParser,\n ur as mergeClassNames,\n q as number,\n $ as off,\n y as on,\n or as once,\n er as parseInitData,\n jt as parseLaunchParams,\n se as parseMessage,\n bt as parseThemeParams,\n d as postEvent,\n m as request,\n rr as requestThemeParams,\n At as requestViewport,\n Ct as retrieveLaunchData,\n gt as rgb,\n X as searchParams,\n Jt as serializeLaunchParams,\n Ut as serializeThemeParams,\n nr as setDebug,\n ir as setTargetOrigin,\n u as string,\n ar as subscribe,\n R as supports,\n _t as themeParamsParser,\n dt as toRGB,\n _e as unsubscribe,\n rt as userParser,\n xt as withTimeout\n};\n//# sourceMappingURL=index.mjs.map\n","import { createHmac } from 'node:crypto';\nimport { URLSearchParams } from 'node:url';\n\nexport interface ValidateOptions {\n /**\n * Time in seconds which states, how long from creation time is init data\n * considered valid.\n *\n * In other words, in case, when authDate + expiresIn is before current\n * time, init data recognized as expired.\n *\n * In case, this value is equal to 0, function does not check init data\n * expiration.\n * @default 86400 (1 day)\n */\n expiresIn?: number;\n}\n\n/**\n * Validates passed init data presented as search params converted to string,\n * or its object presentation.\n *\n * @param sp - search parameters.\n * @param token - Telegram bot secret token.\n * @param options - validation options.\n * @see toSearchParams\n * @throws {TypeError} \"hash\" should be string.\n * @throws {Error} \"hash\" is empty or not found.\n * @throws {TypeError} \"auth_date\" should be string.\n * @throws {TypeError} \"auth_date\" does not represent integer.\n * @throws {Error} \"auth_date\" is empty or not found.\n * @throws {Error} Init data expired.\n * @throws {Error} Sign invalid.\n */\nexport function validate(\n sp: string | URLSearchParams,\n token: string,\n options: ValidateOptions = {},\n): void {\n const searchParams = typeof sp === 'string' ? new URLSearchParams(sp) : sp;\n\n // Init data creation time.\n let authDate = new Date(0);\n\n // Init data sign.\n let hash = '';\n\n // All search params pairs presented as `k=v`.\n const pairs: string[] = [];\n\n // Iterate over all key-value pairs of parsed parameters and find required\n // parameters.\n searchParams.forEach((value, key) => {\n if (key === 'hash') {\n hash = value;\n return;\n }\n\n if (key === 'auth_date') {\n const authDateNum = parseInt(value, 10);\n\n if (Number.isNaN(authDateNum)) {\n throw new TypeError('\"auth_date\" should present integer');\n }\n authDate = new Date(authDateNum * 1000);\n }\n\n // Append new pair.\n pairs.push(`${key}=${value}`);\n });\n\n // Hash and auth date always required.\n if (hash.length === 0) {\n throw new Error('\"hash\" is empty or not found');\n }\n\n if (authDate.getTime() === 0) {\n throw new Error('\"auth_date\" is empty or not found');\n }\n\n // In case, expiration time passed, we do additional parameters check.\n const { expiresIn = 86400 } = options;\n\n if (expiresIn > 0) {\n // Check if init data expired.\n if (authDate.getTime() + expiresIn * 1000 < new Date().getTime()) {\n throw new Error('Init data expired');\n }\n }\n\n // According to docs, we sort all the pairs in alphabetical order.\n pairs.sort();\n\n // Compute sign.\n const computedHash = createHmac(\n 'sha256',\n createHmac('sha256', 'WebAppData').update(token).digest(),\n )\n .update(pairs.join('\\n'))\n .digest()\n .toString('hex');\n\n // In case, our sign is not equal to found one, we should throw an error.\n if (computedHash !== hash) {\n throw new Error('Signature is invalid');\n }\n}\n"],"names":["Rt","It","r","e","o","I","F","s","n","z","L","G","ht","i","a","h","c","p","k","q","pt","Y","f","u","X","Wt","rt","wt","er","validate","sp","token","options","searchParams","URLSearchParams","authDate","hash","pairs","value","key","authDateNum","expiresIn","createHmac"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tma.js/init-data-node",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "TypeScript Node library to operate with Telegram init data.",
|
|
5
5
|
"author": "Vladislav Kibenko <wolfram.deus@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/Telegram-Mini-Apps/tma.js#readme",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@tma.js/sdk": "^1.4.
|
|
49
|
+
"@tma.js/sdk": "^1.4.2"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"test": "vitest --run",
|