@www.hyperlinks.space/program-kit 18.18.18 → 123.123.123

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.
Files changed (52) hide show
  1. package/.eas/workflows/create-development-builds.yml +21 -0
  2. package/.eas/workflows/create-draft.yml +15 -0
  3. package/.eas/workflows/deploy-to-production.yml +68 -0
  4. package/.gitattributes +48 -0
  5. package/.gitignore +52 -0
  6. package/.nvmrc +1 -0
  7. package/.vercelignore +6 -0
  8. package/README.md +17 -2
  9. package/ai/openai.ts +202 -0
  10. package/ai/transmitter.ts +367 -0
  11. package/backlogs/medium_term_backlog.md +26 -0
  12. package/backlogs/short_term_backlog.md +42 -0
  13. package/eslint.config.cjs +10 -0
  14. package/npmReadMe.md +17 -2
  15. package/npmrc.example +1 -0
  16. package/package.json +3 -28
  17. package/polyfills/buffer.ts +9 -0
  18. package/research & docs/ai_and_search_bar_input.md +94 -0
  19. package/research & docs/ai_bot_messages.md +124 -0
  20. package/research & docs/auth-and-centralized-encrypted-keys-plan.md +440 -0
  21. package/research & docs/blue_bar_tackling.md +143 -0
  22. package/research & docs/bot_async_streaming.md +174 -0
  23. package/research & docs/build_and_install.md +129 -0
  24. package/research & docs/database_messages.md +34 -0
  25. package/research & docs/fonts.md +18 -0
  26. package/research & docs/github-gitlab-bidirectional-mirroring.md +154 -0
  27. package/research & docs/keys-retrieval-console-scripts.js +131 -0
  28. package/research & docs/npm-release.md +46 -0
  29. package/research & docs/releases.md +201 -0
  30. package/research & docs/releases_github_actions.md +188 -0
  31. package/research & docs/scalability.md +34 -0
  32. package/research & docs/security_plan_raw.md +244 -0
  33. package/research & docs/security_raw.md +354 -0
  34. package/research & docs/storage-availability-console-script.js +152 -0
  35. package/research & docs/storage-lifetime.md +33 -0
  36. package/research & docs/telegram-raw-keys-cloud-storage-risks.md +31 -0
  37. package/research & docs/timing_raw.md +63 -0
  38. package/research & docs/tma_logo_bar_jump_investigation.md +69 -0
  39. package/research & docs/update.md +205 -0
  40. package/research & docs/wallet_telegram_standalone_multichain_proposal.md +192 -0
  41. package/research & docs/wallets_hosting_architecture.md +403 -0
  42. package/services/wallet/tonWallet.ts +73 -0
  43. package/ui/components/GlobalBottomBar.tsx +447 -0
  44. package/ui/components/GlobalBottomBarWeb.tsx +362 -0
  45. package/ui/components/GlobalLogoBar.tsx +108 -0
  46. package/ui/components/GlobalLogoBarFallback.tsx +66 -0
  47. package/ui/components/GlobalLogoBarWithFallback.tsx +24 -0
  48. package/ui/components/HyperlinksSpaceLogo.tsx +29 -0
  49. package/ui/components/Telegram.tsx +677 -0
  50. package/ui/components/telegramWebApp.ts +359 -0
  51. package/ui/fonts.ts +12 -0
  52. package/ui/theme.ts +117 -0
@@ -0,0 +1,354 @@
1
+ # Security Model: Telegram-First Wallet
2
+
3
+ ## Goals
4
+
5
+ - Create wallets inside the Telegram Mini App.
6
+ - Let users access the **same wallet** from:
7
+ - Telegram on any device.
8
+ - Other platforms (web / desktop / native) via **Login with Telegram**.
9
+ - Keep custody with the **user** (mnemonic as ultimate root of trust), while using Telegram features to improve UX.
10
+
11
+ This document describes the current high-level design; it is not a formal audit.
12
+
13
+ ---
14
+
15
+ ## Key Concepts & Storage
16
+
17
+ **Key terms**
18
+
19
+ - **Mnemonic (seed phrase)**: Ultimate secret that controls the wallet. If lost, funds are lost; if leaked, funds are at risk.
20
+ - **Wallet master key**: Device-specific key derived from the mnemonic and stored only on that device.
21
+ - **Wallet seed cipher**: Encrypted blob that contains the wallet seed (or a seed-derived secret), usable only together with the wallet master key.
22
+ - **Telegram CloudStorage**: Per-user, per-bot key–value store synced via Telegram servers. Suitable for non-secret data or ciphertext.
23
+ - **Telegram SecureStorage**: Per-device secure storage, backed by iOS Keychain / Android Keystore, intended for small sensitive values like tokens and keys (see [Mini Apps docs](https://core.telegram.org/bots/webapps#securestorage)).
24
+ - **Telegram DeviceStorage**: Persistent **local** key–value storage inside the Telegram client for the bot (up to 5 MB per user). Telegram documents it as conceptually similar to browser `localStorage`, **not** as Keychain/Keystore-backed secure storage (see [DeviceStorage](https://core.telegram.org/bots/webapps#devicestorage)).
25
+
26
+ We **never store raw mnemonics** on our backend or in Telegram CloudStorage.
27
+
28
+ ### SecureStorage vs DeviceStorage (product stance)
29
+
30
+ - **SecureStorage** is the preferred place for the wallet master key: encrypted at rest and isolated using OS secure hardware where Telegram implements it.
31
+ - Some clients (notably **Telegram Desktop** in common builds) report `secure_storage_failed` with errors such as **`UNSUPPORTED`**, meaning there is no SecureStorage bridge for that Mini App session.
32
+ - **DeviceStorage fallback** (used only when SecureStorage fails) keeps the same split as the design (master key local, seed as ciphertext in CloudStorage), but the master key is **not** under the same hardware-backed guarantees. It is **stricter than random website `localStorage`** (scoped to the Telegram client and bot), yet **strictly weaker than SecureStorage** against threats that can read Mini App storage (e.g. XSS, compromised WebView, malware with access to Telegram’s local storage).
33
+
34
+ **Alternative architectures** (not the default in this repo) include: **require** SecureStorage and **block** signing until the user opens the Mini App on a supported client, or a **Tonkeeper-style** model (password-encrypted secrets with persistence via CloudStorage only, with security bounded by password strength and KDF choice).
35
+
36
+ The Mini App implementation tries **SecureStorage first**, then **DeviceStorage** for `wallet_master_key`, and surfaces a short in-app notice when the weaker path is used.
37
+
38
+ ---
39
+
40
+ ## I. Wallet Creation in Telegram
41
+
42
+ Flow when a user creates a wallet for the first time in the Telegram Mini App on a device:
43
+
44
+ 1. **Generate mnemonic on the device**
45
+ - The Mini App generates a new mnemonic locally (client-side).
46
+ - The user is shown the mnemonic once and asked to write it down for lifelong backup.
47
+
48
+ 2. **Derive wallet master key (device-local)**
49
+ - From the mnemonic, the app derives a **wallet master key** (e.g. via a BIP-style KDF / HKDF).
50
+ - This master key is stored in Telegram **`SecureStorage` when available** (Keychain / Keystore on mobile).
51
+ - If SecureStorage is unavailable (`UNSUPPORTED` or failure), the app **falls back to `DeviceStorage`** and explains the weaker guarantee in the UI (see “SecureStorage vs DeviceStorage” above).
52
+
53
+ 3. **Create and store wallet seed cipher (cloud)**
54
+ - The app creates a **wallet seed cipher**:
55
+ - `seed_cipher = Encrypt(wallet_seed_or_root, wallet_master_key)`.
56
+ - `seed_cipher` is stored in Telegram `CloudStorage` under this bot for this user.
57
+ - CloudStorage contains **only ciphertext**, never raw seed or keys.
58
+
59
+ 4. **Persist wallet mapping in our backend**
60
+ - Our backend stores a record like:
61
+ - `telegram_username` (Telegram username, treated as unique in our system),
62
+ - `wallet_address` (public address),
63
+ - metadata (creation time, network, etc.).
64
+ - No mnemonics or master keys are saved server-side.
65
+
66
+ **Properties**
67
+
68
+ - The **first Telegram device** has everything needed to use the wallet:
69
+ - Master key in `SecureStorage` or, on some clients, `DeviceStorage`.
70
+ - Seed cipher in `CloudStorage`.
71
+ - If the app is reinstalled on the **same device**, we can:
72
+ - Recover the master key from the same Telegram local store (if Telegram restores it).
73
+ - Decrypt the seed cipher for a smooth UX without re-entering the mnemonic.
74
+ - If local storage is wiped, the user must re-enter the mnemonic.
75
+
76
+ ---
77
+
78
+ ## II. New Telegram Device Authorization
79
+
80
+ When the same user opens the Mini App on **another Telegram client** (new phone/tablet):
81
+
82
+ 1. **Detect existing wallet**
83
+ - Using `initData` / backend lookup, we see that this `telegram_username` already owns at least one `wallet_address`.
84
+
85
+ 2. **Check device SecureStorage**
86
+ - On this **new device**, `SecureStorage` is empty for our bot (no wallet master key yet).
87
+ - We may still see the `seed_cipher` in `CloudStorage` (it is synced across user devices), but without a master key it is useless.
88
+
89
+ 3. **Ask user for mnemonic to authorize this device**
90
+ - The Mini App prompts the user to enter their mnemonic.
91
+ - From the mnemonic we derive a **new device-specific wallet master key** and store it in this device’s `SecureStorage`.
92
+ - Optionally, we re-encrypt and update the `seed_cipher` for this device; but the canonical root of trust remains the mnemonic.
93
+
94
+ **Result**
95
+
96
+ - Each Telegram device gains access only after the user proves knowledge of the mnemonic once.
97
+ - Loss of a device does **not** affect other devices, as long as the mnemonic is safe.
98
+
99
+ ---
100
+
101
+ ## III. Other Platforms (Outside Telegram)
102
+
103
+ For platforms outside Telegram (web, desktop app, native mobile app not running inside Telegram), we:
104
+
105
+ 1. **Authenticate via Telegram**
106
+ - Use **Telegram Login for Websites** (see [login widget docs](https://core.telegram.org/widgets/login)) in a browser or embedded WebView.
107
+ - The login widget:
108
+ - Shows a Telegram-branded authorization UI where the user confirms sharing their Telegram identity with our site.
109
+ - After success, returns a signed payload containing `id`, `first_name`, `last_name`, `username`, `photo_url`, `auth_date`, and `hash`.
110
+ - On our backend we verify the `hash` using HMAC-SHA-256 with the SHA-256 of the bot’s token as a key, as described in the official docs.
111
+ - This works on:
112
+ - **Desktop browsers** (Chrome, Firefox, Safari, Edge, …),
113
+ - **Mobile browsers** on **iOS and Android**,
114
+ - In-app WebViews (e.g. inside a native app’s web login screen).
115
+
116
+ > For pure native iOS/Android apps, we typically embed a small web login page (with the widget) or open the system browser, then pass the verified Telegram identity back into the app.
117
+
118
+ 2. **Lookup existing wallet**
119
+ - Once Telegram login succeeds, we resolve `telegram_username` in our DB.
120
+ - If there is an associated `wallet_address`, we know this user already owns a wallet.
121
+
122
+ 3. **Authorize the device with the mnemonic**
123
+ - Because we are **outside Telegram**, we do not have Telegram’s `SecureStorage`.
124
+ - We therefore ask the user to **enter the mnemonic** to authorize this new platform.
125
+ - The app derives a **local wallet master key** from the mnemonic and stores it using the platform’s secure storage:
126
+ - iOS: Keychain
127
+ - Android: Keystore
128
+ - Desktop: DPAPI / Keychain / Keyring, depending on OS
129
+ - Web: WebCrypto + IndexedDB (with the usual caveats around user clearing storage).
130
+
131
+ **Result**
132
+
133
+ - Telegram login is used purely as an **identity layer** (“who is this user?”).
134
+ - The **mnemonic** is still required to authorize a completely new platform.
135
+ - Our backend never receives the raw mnemonic; only derived public keys / addresses.
136
+
137
+ ---
138
+
139
+ ## IV. Android / iOS (Single App, Telegram‑Centric Flow)
140
+
141
+ We ship **one app** (the current Expo app at repository root) to iOS/Android stores. On mobile, the app acts as a shell that:
142
+
143
+ - Explains why wallet creation happens in Telegram.
144
+ - Sends the user into the Telegram Mini App to actually create the wallet.
145
+ - Then uses **Telegram Login for Websites** + our backend to recognize the user and their wallet.
146
+
147
+ ### Database: user identification (Telegram username–centric)
148
+
149
+ In the backend we maintain a `users` table (or equivalent) with at least:
150
+
151
+ - `telegram_username` – Telegram username, treated as unique in our system.
152
+ - `wallet_address` – current wallet address owned by this username.
153
+
154
+ The mobile app never needs to store the mnemonic or keys; it only needs the `telegram_username` and `wallet_address` retrieved from the backend after Telegram login.
155
+
156
+ ### A. New user on iOS/Android (no wallet yet)
157
+
158
+ 1. **App start → “Log in with Telegram” screen**
159
+ - Shown when there is no linked `telegram_username` in local app storage.
160
+ - Content:
161
+ - Title: “Create your wallet in Telegram”.
162
+ - Short text summarizing benefits:
163
+ - “Wallets are created **inside Telegram**, we never see your seed phrase.”
164
+ - “Your keys are stored using Telegram **SecureStorage + CloudStorage** on your devices.”
165
+ - “You can access the same wallet from Telegram, web, and this app.”
166
+ - UI:
167
+ - Primary button: **“Open Telegram to create wallet”**.
168
+ - Secondary button (dimmed / smaller): **“I already created my wallet in Telegram”** (goes to login widget, see flow B).
169
+ - Action on primary:
170
+ - Deep link to Mini App, e.g. `https://t.me/<bot_username>?startapp=wallet_onboarding`.
171
+
172
+ 2. **Telegram Mini App: wallet creation (same as section I)**
173
+ - Generate mnemonic, show/confirm it.
174
+ - Derive wallet master key → store in `SecureStorage`.
175
+ - Encrypt wallet seed → store cipher in `CloudStorage`.
176
+ - Call backend `register_wallet(telegram_username, wallet_address)` which:
177
+ - Creates a new `users` row.
178
+ - Stores `telegram_username`, `wallet_address`.
179
+ - Show a completion screen:
180
+ - “Your wallet is ready in Telegram.”
181
+ - Instruction: “Return to the app and tap ‘I already created my wallet’ to connect.”
182
+
183
+ 3. **Back in iOS/Android app → “Log in with Telegram” (Telegram login widget)**
184
+ - User returns to the app and taps **“I already created my wallet in Telegram”** (or simply “Log in with Telegram”).
185
+ - App opens an embedded WebView or browser page with **Telegram Login for Websites**:
186
+ - Widget asks the user to confirm sharing their Telegram identity.
187
+ - After success, backend receives a signed payload and validates it as in section III.
188
+ - Backend extracts `username` from the payload and looks up `telegram_username` in `users`:
189
+ - If found, returns `{ telegram_username, wallet_address, ... }` to the app.
190
+ - If not found (edge case: user logged in before creating wallet), the app can:
191
+ - Show “No wallet yet, please create it in Telegram first” and show the **Open Telegram** button again.
192
+
193
+ 4. **App state after linking**
194
+ - The app stores `telegram_username` and `wallet_address` in its local storage.
195
+ - It can now:
196
+ - Display balances / history via backend or blockchain APIs.
197
+ - For signing, either:
198
+ - Redirect back to Telegram Mini App on an action (“Sign in Telegram”), or
199
+ - In a future advanced flow, allow the user to import mnemonic locally (explicit, non‑default).
200
+
201
+ ### B. Existing Telegram wallet user installing iOS/Android app
202
+
203
+ For a user who already has a Telegram wallet (created earlier in the Mini App):
204
+
205
+ 1. **App start → same “Log in with Telegram” screen**
206
+ - The screen is identical, but the text emphasizes:
207
+ - “If you already created your wallet in Telegram, just log in below.”
208
+ - Action:
209
+ - User taps **“I already created my wallet in Telegram”** / **“Log in with Telegram”**.
210
+
211
+ 2. **Telegram Login for Websites**
212
+ - Same widget flow as in A.3.
213
+ - Backend verifies the payload and looks up `telegram_username` in `users`:
214
+ - If a row exists → return `{ telegram_username, wallet_address }` to the app.
215
+ - If no row exists → the app suggests:
216
+ - “We don’t see a wallet yet. Please open Telegram to create one.” and shows the **Open Telegram to create wallet** button.
217
+
218
+ 3. **After login**
219
+ - The app saves `telegram_username` + `wallet_address` locally and shows the wallet UI.
220
+ - No mnemonic is ever handled by the app in this default flow.
221
+
222
+ **Key points of this model**
223
+
224
+ - There is **one app** (repository root), not a separate companion; mobile just has a Telegram-centric onboarding path.
225
+ - All wallet creation and key material remain in the Telegram Mini App and its SecureStorage/CloudStorage environment.
226
+ - The iOS/Android app uses:
227
+ - **Telegram Login for Websites** to learn “who is this user?” (via `username`),
228
+ - The backend’s `users` table (`telegram_username`, `wallet_address`) to link that identity to a wallet.
229
+ - Users who don’t want to connect Telegram can only use future “local‑only” features if we add them explicitly; the default path is Telegram‑first.
230
+
231
+ ---
232
+
233
+ ## V. Serverless Transaction Flow & Bot‑Based Confirmation
234
+
235
+ We assume a **serverless backend** (e.g. Vercel / Cloudflare / Lambda functions) with:
236
+
237
+ - Stateless HTTP handlers (API routes).
238
+ - A persistent datastore (serverless Postgres / KV / Dynamo, etc.) for:
239
+ - `users` (`telegram_username`, `wallet_address`, …).
240
+ - `pending_transactions` (id, telegram_username, payload, status, timestamps).
241
+
242
+ All **signing** happens on the client side (Telegram Mini App or other wallet environment); serverless functions never hold private keys.
243
+
244
+ ### 1. Initiating a transaction (any client)
245
+
246
+ From any frontend (Telegram Mini App, web, iOS/Android app):
247
+
248
+ 1. Client sends a request to a serverless endpoint, e.g. `POST /api/tx/create`:
249
+ - Body includes:
250
+ - `telegram_username` (or derived from Telegram auth),
251
+ - transaction intent (action type, amount, asset, destination, etc.).
252
+ 2. Serverless handler:
253
+ - Validates the request and user identity.
254
+ - Creates a `pending_transactions` row with:
255
+ - `id` (e.g. UUID or short code),
256
+ - `telegram_username`,
257
+ - serialized transaction payload (what needs to be signed),
258
+ - status = `pending`.
259
+ - Uses the **Telegram Bot API** to send a push message to the user:
260
+ - “New action requires confirmation: <summary>”.
261
+ - Inline button: **“Review & confirm”** linking to:
262
+ - Recommended: Mini App deep link, e.g.\
263
+ `https://t.me/<bot_username>?startapp=tx_<id>`
264
+ - Optionally, a web URL, e.g.\
265
+ `https://app.hyperlinks.space/tx/<id>`.
266
+
267
+ ### 2. Confirmation page (Telegram Mini App)
268
+
269
+ When the user taps the button in the bot message and opens the Mini App:
270
+
271
+ 1. The Mini App receives `start_param = tx_<id>` via `initData`.
272
+ 2. It calls a serverless endpoint, e.g. `GET /api/tx/<id>`:
273
+ - Backend verifies the request using `initData`/`hash` and checks that:
274
+ - `pending_transactions.id` exists,
275
+ - `telegram_username` from DB matches the Mini App user,
276
+ - status is `pending`.
277
+ - Backend returns the transaction details (read‑only).
278
+ 3. Mini App shows a **confirmation UI**:
279
+ - Clear summary: amounts, assets, destination, fees, network.
280
+ - Buttons: **Confirm** / **Reject**.
281
+
282
+ ### 3. Signing & broadcasting (inside Telegram)
283
+
284
+ On **Confirm** from the Mini App:
285
+
286
+ 1. Mini App reconstructs/derives the transaction to be signed using:
287
+ - The locally available wallet (seed/master key in Telegram `SecureStorage` or `DeviceStorage` fallback).
288
+ - The payload from `pending_transactions`.
289
+ 2. Mini App signs the transaction **locally** using the wallet key.
290
+ 3. Mini App sends a request to a serverless endpoint, e.g. `POST /api/tx/<id>/complete` with:
291
+ - `id`,
292
+ - signed transaction payload (or only the resulting transaction hash if the client broadcasts itself),
293
+ - confirmation that user accepted.
294
+ 4. Serverless handler:
295
+ - Verifies that the caller is the right `telegram_username` and that tx is still `pending`.
296
+ - Either:
297
+ - Broadcasts the signed transaction to the chain (if backend has RPC access and broadcasting doesn’t leak secrets), **or**
298
+ - Simply records the fact that this transaction was confirmed and uses a separate service / worker to broadcast.
299
+ - Updates `pending_transactions.status` to `confirmed` (or `failed` with reason).
300
+
301
+ The originating client (web / mobile app) can poll or subscribe for status changes on `pending_transactions` to reflect completion.
302
+
303
+ ### 4. Optional: web‑only confirmation page
304
+
305
+ For users who click a **web URL** from the bot instead of the Mini App:
306
+
307
+ - The confirmation page:
308
+ - Uses **Telegram Login for Websites** to authenticate the user (retrieve `username`).
309
+ - Loads the `pending_transactions` row by `id` + `telegram_username`.
310
+ - Shows the same confirmation UI.
311
+ - For signing, we recommend **redirecting back to Telegram** for actual key usage:
312
+ - On **Confirm**, the web page can:
313
+ - Either deep‑link into the Mini App with the same `tx_<id>`, or
314
+ - Ask the user to enter the mnemonic or connect an external wallet (advanced, non‑default).
315
+ - This keeps the **self‑custodial key** anchored in the Mini App by default, while still allowing purely web‑based flows where the user explicitly opts into entering their mnemonic or linking another wallet.
316
+
317
+ ### Serverless guarantees
318
+
319
+ - All backend logic is stateless across requests; long‑lived data lives in `users` and `pending_transactions`.
320
+ - No private keys or mnemonics are ever stored or derived in serverless functions.
321
+ - Bot pushes and confirmation flows are coordinated exclusively via:
322
+ - Telegram Bot API (for notifications),
323
+ - Telegram Mini App (for signing with local master key in SecureStorage or DeviceStorage fallback),
324
+ - Telegram Login (for identity on web / mobile).
325
+
326
+ This model keeps transaction approvals **user‑driven and key‑local** (inside Telegram or another explicit wallet) while still fitting neatly into a serverless architecture.
327
+
328
+ ---
329
+
330
+ ## Security Properties
331
+
332
+ - **Self-custody:**
333
+ - The mnemonic is the **only ultimate key**; if the user keeps it offline and safe, they retain full control over funds.
334
+ - Neither our backend nor Telegram can unilaterally move funds without the mnemonic / keys.
335
+
336
+ - **Device-local keys:**
337
+ - Each device has its own **wallet master key** stored in Telegram **SecureStorage** when supported, else **DeviceStorage** (weaker).
338
+ - Compromise of one device does **not** automatically compromise others.
339
+
340
+ - **Cloud data is ciphertext only:**
341
+ - `Wallet Seed Cipher` in CloudStorage is encrypted with the wallet master key, which should exist only on the user’s Telegram client for that device.
342
+ - An attacker with only CloudStorage access cannot derive the mnemonic without the master key.
343
+
344
+ - **Cross-platform restore requires mnemonic:**
345
+ - Any **new environment** (new Telegram device with empty SecureStorage or any non-Telegram platform) requires the mnemonic once.
346
+
347
+ ---
348
+
349
+ ## Limitations & Notes
350
+
351
+ - If the **mnemonic is lost**, there is no recovery (by design) – it is the self-custodial root.
352
+ - If a device with a master key is compromised, an attacker can act as the owner from that device until the user moves funds to a new wallet.
353
+ - Telegram `SecureStorage` is documented for **iOS and Android**; **Desktop and some builds may not support it**, triggering fallback to `DeviceStorage` or leaving the key unsaved until the user uses a supported client or restores with the mnemonic.
354
+ - Telegram Login for Websites is an **authentication mechanism only** – it does not give access to keys or the mnemonic itself, and cannot replace the mnemonic for wallet authorization.
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Telegram Mini App storage availability probe (paste into DevTools console).
3
+ *
4
+ * What this script does:
5
+ * 1) Checks whether Telegram WebApp bridge exists.
6
+ * 2) Probes SecureStorage by real write+read+remove roundtrip.
7
+ * 3) Probes DeviceStorage by real write+read+remove roundtrip.
8
+ * 4) Probes CloudStorage by real write+read+remove roundtrip.
9
+ * 5) Prints a single QA verdict:
10
+ * - "secure" => SecureStorage works.
11
+ * - "device" => SecureStorage fails, but DeviceStorage works.
12
+ * - "none" => neither SecureStorage nor DeviceStorage works.
13
+ *
14
+ * Notes:
15
+ * - "API object exists" does NOT mean storage is supported. Telegram Desktop may expose methods
16
+ * but return UNSUPPORTED at runtime. This script verifies runtime behavior.
17
+ * - Probe keys are deleted at the end.
18
+ */
19
+ (async () => {
20
+ const wa = window.Telegram?.WebApp;
21
+ if (!wa) {
22
+ const result = {
23
+ verdict: "none",
24
+ webApp: null,
25
+ error: "Telegram.WebApp not found (not running in TMA context).",
26
+ };
27
+ console.log("[storage-probe]", result);
28
+ return result;
29
+ }
30
+
31
+ const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
32
+
33
+ const probeSecureOrDevice = async (storage, eventPrefix, includeCanRestore) => {
34
+ const key = `probe_${eventPrefix}_${Date.now()}`;
35
+ const value = "ok";
36
+ let eventFailed = null;
37
+
38
+ const failedEventName = `${eventPrefix}_failed`;
39
+ const savedEventName = `${eventPrefix}_key_saved`;
40
+
41
+ const onFailed = (payload) => { eventFailed = payload; };
42
+ const onSaved = () => {};
43
+
44
+ try {
45
+ wa.onEvent?.(failedEventName, onFailed);
46
+ wa.onEvent?.(savedEventName, onSaved);
47
+ } catch {}
48
+
49
+ const cleanup = () => {
50
+ try { wa.offEvent?.(failedEventName, onFailed); } catch {}
51
+ try { wa.offEvent?.(savedEventName, onSaved); } catch {}
52
+ };
53
+
54
+ if (!storage || typeof storage.setItem !== "function" || typeof storage.getItem !== "function") {
55
+ cleanup();
56
+ return {
57
+ present: false,
58
+ supported: false,
59
+ set: null,
60
+ get: null,
61
+ remove: null,
62
+ eventFailed: null,
63
+ };
64
+ }
65
+
66
+ return new Promise((resolve) => {
67
+ storage.setItem(key, value, (setErr, stored) => {
68
+ storage.getItem(key, async (getErr, gotValue, canRestore) => {
69
+ await wait(50);
70
+
71
+ const base = {
72
+ present: true,
73
+ supported: setErr == null && getErr == null && gotValue === value,
74
+ set: { err: setErr ?? null, stored: stored ?? null },
75
+ get: includeCanRestore
76
+ ? { err: getErr ?? null, value: gotValue ?? null, canRestore: canRestore ?? null }
77
+ : { err: getErr ?? null, value: gotValue ?? null },
78
+ remove: null,
79
+ eventFailed,
80
+ };
81
+
82
+ if (typeof storage.removeItem === "function") {
83
+ storage.removeItem(key, (rmErr, removed) => {
84
+ base.remove = { err: rmErr ?? null, removed: removed ?? null };
85
+ cleanup();
86
+ resolve(base);
87
+ });
88
+ } else {
89
+ cleanup();
90
+ resolve(base);
91
+ }
92
+ });
93
+ });
94
+ });
95
+ };
96
+
97
+ const probeCloudStorage = async () => {
98
+ const cs = wa.CloudStorage;
99
+ const key = `probe_cloud_${Date.now()}`;
100
+ const value = "ok";
101
+
102
+ if (!cs || typeof cs.setItem !== "function" || typeof cs.getItem !== "function") {
103
+ return {
104
+ present: false,
105
+ supported: false,
106
+ set: null,
107
+ get: null,
108
+ remove: null,
109
+ };
110
+ }
111
+
112
+ return new Promise((resolve) => {
113
+ cs.setItem(key, value, (setErr, stored) => {
114
+ cs.getItem(key, (getErr, gotValue) => {
115
+ const out = {
116
+ present: true,
117
+ supported: setErr == null && getErr == null && gotValue === value,
118
+ set: { err: setErr ?? null, stored: stored ?? null },
119
+ get: { err: getErr ?? null, value: gotValue ?? null },
120
+ remove: null,
121
+ };
122
+
123
+ if (typeof cs.removeItem === "function") {
124
+ cs.removeItem(key, (rmErr, removed) => {
125
+ out.remove = { err: rmErr ?? null, removed: removed ?? null };
126
+ resolve(out);
127
+ });
128
+ } else {
129
+ resolve(out);
130
+ }
131
+ });
132
+ });
133
+ });
134
+ };
135
+
136
+ const secureStorage = await probeSecureOrDevice(wa.SecureStorage, "secure_storage", true);
137
+ const deviceStorage = await probeSecureOrDevice(wa.DeviceStorage, "device_storage", false);
138
+ const cloudStorage = await probeCloudStorage();
139
+
140
+ const verdict = secureStorage.supported ? "secure" : deviceStorage.supported ? "device" : "none";
141
+
142
+ const result = {
143
+ verdict,
144
+ webApp: { platform: wa.platform ?? null, version: wa.version ?? null },
145
+ secureStorage,
146
+ deviceStorage,
147
+ cloudStorage,
148
+ };
149
+
150
+ console.log(`[storage-probe] verdict=${verdict}`, result);
151
+ return result;
152
+ })();
@@ -0,0 +1,33 @@
1
+ # Storage Lifetime for Wallet Keys
2
+
3
+ This document summarizes practical storage lifetime expectations for wallet-related secrets.
4
+
5
+ Important: "lifetime" is never absolute. Every layer can be lost due to account loss, uninstall, reset, policy changes, corruption, or compromise.
6
+
7
+ ## Quick Matrix
8
+
9
+ | Storage type | Typical lifetime | Main limiting factor | Cross-device | Notes for wallet keys |
10
+ |---|---|---|---|---|
11
+ | Telegram CloudStorage | Potentially long-lived | Telegram account/app availability and platform behavior | Yes (inside Telegram ecosystem) | Use for ciphertext/public metadata, not raw mnemonic |
12
+ | Telegram SecureStorage | Device-scoped durable | Device/app reinstall/reset and client support | No | Best TMA local tier when supported |
13
+ | Telegram DeviceStorage | Device-scoped durable | Device/app reinstall/reset | No | Weaker than SecureStorage; fallback tier |
14
+ | Session Storage (`sessionStorage`) | Current tab/session only | Tab/window/browser session end | No | Not suitable for persistent keys |
15
+ | Browser Local Storage (`localStorage`) | Potentially long-lived on same browser profile | User clearing data, browser profile loss | No | Use only encrypted blobs if needed |
16
+ | IndexedDB (web) | Potentially long-lived on same browser profile | User/browser data clearing, profile loss | No | Better than localStorage for larger encrypted blobs |
17
+ | Expo Secure Store (iOS/Android) | Durable on device | Uninstall/reset/device change | No | Good native local secret store; still not "forever" |
18
+ | Electron OS secure storage (Windows/macOS) | Durable on device profile | OS profile/device lifetime, reinstall/migration | No | Suitable desktop local secret store |
19
+ | In-memory runtime only | Process/session only | App restart/crash/background termination | No | Best for temporary decrypted material |
20
+
21
+ ## Lifetime Statements (practical wording)
22
+
23
+ - **Telegram CloudStorage:** theoretically long-lived, practically bounded by **Telegram account lifetime and platform behavior**.
24
+ - **Device-local storage (SecureStorage/DeviceStorage/Secure Store/OS keychain):** bounded by **device/app/profile lifetime**.
25
+ - **Session storage:** bounded by **session lifetime** (tab/window/app session).
26
+
27
+ ## Recommended usage pattern
28
+
29
+ 1. Keep **mnemonic as offline backup** (user-controlled, not in backend/cloud plaintext).
30
+ 2. Store day-to-day local unlock material in the strongest available **device-local secure store**.
31
+ 3. Store only **ciphertext** in cloud/sync layers.
32
+ 4. Treat all lifetimes as "best effort durability", not guaranteed permanence.
33
+
@@ -0,0 +1,31 @@
1
+ # Telegram CloudStorage Raw Keys Risks
2
+
3
+ This note clarifies a common misunderstanding:
4
+
5
+ - It is true that Telegram Mini App `CloudStorage` is scoped per bot/per user.
6
+ - It is true that each Telegram user session is strongly protected by Telegram account security controls (session management, device authorization, transport security, etc.).
7
+ - It is also true that endpoint compromise exists in both models (Bitcoin Core local storage and TMA/web clients).
8
+
9
+ The key security difference is not "cross-user direct reads". The key difference is how compromise can scale through the app runtime.
10
+
11
+ In other words: Telegram session protection is a strong baseline and should be acknowledged. The residual risk discussed here is about compromised Mini App code/runtime on an already authenticated user session, not about bypassing Telegram account/session controls.
12
+
13
+ ## Corrected comparison
14
+
15
+ Exactly: a PC can be hacked in both cases.
16
+
17
+ - **Bitcoin Core local storage:** an attacker usually needs to compromise that specific machine (or steal wallet backups) to get that user's keys.
18
+ - **Raw mnemonic in Telegram CloudStorage:** per-user storage still applies, but if the Mini App runtime/supply chain is compromised, malicious code can read each currently logged-in user's own CloudStorage during their session and exfiltrate it. This can impact many users over time without a "read all users" API.
19
+
20
+ So both models are vulnerable to endpoint compromise, but web/TMA delivery can add centralized distribution/supply-chain risk that increases aggregate exposure.
21
+
22
+ ## Practical differences vs local desktop wallet model
23
+
24
+ - **Runtime surface:**
25
+ - Local desktop wallet (Bitcoin Core style): narrower app distribution/runtime model.
26
+ - Web/TMA app: JavaScript/runtime/supply-chain surface is broader.
27
+
28
+ - **Secret impact on read:**
29
+ - **Raw mnemonic in cloud:** one successful read is immediate takeover.
30
+ - **Encrypted cloud blob:** attacker still needs decrypt capability (password/device key), which adds a barrier.
31
+
@@ -0,0 +1,63 @@
1
+ # Raw timing estimate
2
+
3
+ **Purpose:** Rough “time till app finish” and **MVP launch** based on commit history, plans, and the front app.
4
+
5
+ **Important:** The app will not be sent to platforms (store/listing) before it is fully finished. So **MVP launch = full product launch**, and the realistic estimate is **3 months**.
6
+
7
+ ## Transfer layout to repository root (TypeScript) — build on new architecture
8
+
9
+ The goal is **not** to finish the Flutter app in `front/`. The **Flutter** app in `front/` is the **reference layout** (web pages, flows, structure). The work is to **transfer that layout and flows into the repository root app in TypeScript** and make everything work there, with **security plan compliance** (see `docs/security_plan.md`). The production Mini App is the TS app at repository root (Expo/React), backed by the same repo’s API and DB.
10
+
11
+ ### Pages to implement in repository root (TS) — from `front/` reference
12
+
13
+ - **Bootstrap** – initData auth, config from API, wallet warm-up.
14
+ - **Main** – home / hub after bootstrap.
15
+ - **Send** – send flow (security plan: pending tx, confirmations).
16
+ - **Swap** – swap flow (rate state, rotation, etc. from root plan).
17
+ - **Wallets** – list/create/manage; wallet creation and nickname (security plan: mnemonic flow, device auth, wallet registration).
18
+ - **Apps** – apps design, brand book alignment.
19
+ - **AI** – AI & search bar; response formatting; scrolling fix; wired to `app` AI routes.
20
+ - **Get** – get flow.
21
+ - **Trade** – trade page.
22
+ - **Creators** – creators content.
23
+ - **Mnemonics** – mnemonic display/backup (security plan).
24
+ - **Wallet panel** – wallet panel page.
25
+
26
+ ### Services / wiring in repository root (TS)
27
+
28
+ | Concern | Role | Backend / compliance |
29
+ |--------|------|-----------------------|
30
+ | **Auth** | Telegram initData auth (e.g. app’s telegram/init endpoint). | initData validation and user upsert (Phase 0–1). |
31
+ | **AI** | Chat with AI via same-origin `/api/ai` (or app’s AI route). | Already in `app`; ensure config, keys, and error handling in prod. |
32
+ | **Wallet** | Mnemonic generation, storage, key derivation (client-side). | Security plan: SecureStorage/CloudStorage, wallet registration (`POST /api/wallet/register`), device auth flow; optional TonConnect later. |
33
+
34
+ ### API surface (in repository root)
35
+
36
+ - **`/api/telegram`** (or init) – initData validation, user upsert.
37
+ - **`/api/ai`** – AI proxy; used by the TS app.
38
+
39
+ All of the above must work end-to-end in the TS app and stay within the security model (initData-only auth, no raw secrets to server, wallet registration and pending tx where applicable).
40
+
41
+ ---
42
+
43
+ ## Short and Medium term backlogs
44
+
45
+ - **`app/short_term_backlog.md`** (3 items): Response formatting, app theme, AI & search bar.
46
+ - **Root `medium_term_backlog.md`** (backlog): Header indent bug, rotation on swap, edit-interval healthcheck, ticker link, scrolling in AI widget, bot parts isolation, ld timeout, “AI bd”, hovers, languages, favicon, wallet creation & nickname, jetton lockup, theme in Chrome, “Bd”, wallet creation, apps design, plan users BD for search, brand book, fixes, starting rewards, feed item types, PAY BY QR, swap long rate state, swaps, tokens.
47
+
48
+ **Security:** All features above are delivered **with security plan compliance** (Phase 0–2: initData validation, wallet creation and registration, device auth, pending transactions, TonConnect if in scope, etc.). No “MVP without security”; the launch build is compliant.
49
+
50
+ ---
51
+
52
+ ## Time estimate
53
+
54
+ Completion order and stages:
55
+
56
+ | Stage | Scope | Estimate | Notes |
57
+ |-------|--------|----------|--------|
58
+ | **1** | **Security plan implementation** | **~3 weeks** | Phase 0 (validation, DB), Phase 1 (wallet creation, device auth, register), Phase 2 (pending tx, confirmations). |
59
+ | **2** | **App (TS) – pages & UX** | **~3 weeks** | Transfer layout from `front/` and implement all pages in repository root app (send, swap, wallets, apps, AI, get, trade, creators, mnemonics, wallet panel); layout and navigation solid. |
60
+ | **3** | **App (TS) – services & wiring** | **~3 weeks** | Auth, AI, and wallet flows in repository root app; backend alignment; errors and edge cases. |
61
+ | **4** | **Integration, testing, finishing** | **~3 weeks** | E2E, platform checks, store/listing readiness, app/plan and root plan items (formatting, theme, bugs, features). |
62
+
63
+ **MVP launch (full finish, platform-ready):** **~3 months** (12 weeks).