@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,69 @@
1
+ # TMA logo bar jump on input focus – fix
2
+
3
+ ## Problem
4
+
5
+ When the user focuses the AI & Search input in the Telegram Mini App, the keyboard opens and the logo bar jumps (shifts down then up). The whole column (logo bar + main + bottom bar) was also scrollable.
6
+
7
+ **Cause:** Viewport height shrinks when the keyboard opens; if root/body height follows that, the layout reflows and the host may scroll the window → logo bar moves. Reacting on every browser resize (e.g. Visual Viewport) caused intermediate reflows before the final state.
8
+
9
+ ## What we tried (dismissed or replaced)
10
+
11
+ | Approach | Outcome |
12
+ |----------|--------|
13
+ | **Position fixed for logo bar** | Reverted. Did not fix the shift inside TMA. |
14
+ | **Root height from `viewport.stableHeight()`** (pin layout to stable height so it doesn’t change on keyboard) | Not used. We chose “single update when TMA reports” instead. |
15
+ | **Visual Viewport API** (`window.visualViewport` resize + `body.style.height` + `--vh` + `scrollTo(0,0)` on every resize) | Replaced. Caused intermediate reflows; keyboard open triggered multiple resize events before the final size. |
16
+ | **Scroll lock only** (prevent window scroll) | Necessary but not sufficient on its own; layout still shifted. |
17
+
18
+ ## Solution
19
+
20
+ Use **only the TMA viewport API**. When the keyboard opens, change nothing until TMA sends **viewport_changed**; then apply the new height and scroll reset in one turn.
21
+
22
+ ### 1. TMA viewport (Telegram.tsx)
23
+
24
+ - After `viewport.mount()`:
25
+ - **`viewport.bindCssVars()`** – SDK sets/updates `--tg-viewport-height`. Layout height is driven by this.
26
+ - **`on("viewport_changed", handler)`** – Run **`window.scrollTo(0, 0)` only when `payload.is_state_stable`** (or `payload.isStateStable`). Do not reset scroll during drag or animation.
27
+ - **Window scroll lock** – `window.addEventListener("scroll", …)` → if `scrollY > 0` then `scrollTo(0, 0)`.
28
+ - **viewport-fit=cover** on the viewport meta (iOS).
29
+
30
+ ### 2. CSS (global.css)
31
+
32
+ - **html**: `height: 100%`, `overflow: hidden`, `overscroll-behavior: none`.
33
+ - **body**, **#root** / **[data-expo-root]**: `height: var(--tg-viewport-height, 100%)`, `min-height: var(--tg-viewport-height, 100%)`, `overflow: hidden` (body also `overscroll-behavior: none`).
34
+
35
+ ### 3. Layout
36
+
37
+ - **Root View** (_layout.tsx): `overflow: "hidden"`, flex column.
38
+ - **Logo bar** (GlobalLogoBar): `flexShrink: 0`.
39
+ - **Main**: `flex: 1`, `minHeight: 0`.
40
+
41
+ ### 4. TMA (telegramWebApp.ts)
42
+
43
+ - **readyAndExpand()**: `expand()`, `setHeaderColor("#000000")`, `setupSwipeBehavior({ allow_vertical_swipe: false })`, `disableVerticalSwipes?.()`.
44
+
45
+ ## viewport_changed payload
46
+
47
+ | Field | Type | Description |
48
+ |-------|------|-------------|
49
+ | `height` | number | Viewport height. |
50
+ | `width` | number (optional) | Viewport width. |
51
+ | `is_expanded` | boolean | Viewport expanded. |
52
+ | `is_state_stable` | boolean | State stable (no change in the next moment). |
53
+
54
+ Only call `scrollTo(0, 0)` when **is_state_stable** is true. Support both `is_state_stable` and `isStateStable` (bridge payload shape).
55
+
56
+ ## Summary: keep vs dismiss
57
+
58
+ **Keep in the stack:**
59
+
60
+ - TMA-only viewport logic: `viewport.bindCssVars()`, `on("viewport_changed", …)` with **is_state_stable** check before `scrollTo(0, 0)`, window scroll lock, viewport-fit=cover.
61
+ - CSS: `--tg-viewport-height` for body and #root, overflow/overscroll locked on html/body and root.
62
+ - Root `overflow: "hidden"` and logo bar `flexShrink: 0`.
63
+ - readyAndExpand (expand, setHeaderColor, setupSwipeBehavior, disableVerticalSwipes).
64
+
65
+ **Dismiss as try-outs:**
66
+
67
+ - Any use of **Visual Viewport API** for TMA (resize/scroll listeners, `body.style.height`, `--vh`) — replaced by TMA viewport + bindCssVars + viewport_changed.
68
+ - **Position fixed** for the logo bar — reverted.
69
+ - **stableHeight**-based root height — not used; we use bindCssVars (current height) and rely on **is_state_stable** to avoid resetting scroll until the viewport is stable.
@@ -0,0 +1,205 @@
1
+ # Instant App Updates Plan
2
+
3
+ This plan defines how to deliver near-instant updates for the app with minimal user friction, while keeping binary releases for native-level changes.
4
+
5
+ ## 1) Update Strategy (Two Lanes)
6
+
7
+ - **Lane A: OTA updates (default, fast path)**
8
+ - Use Expo EAS Update to deliver JavaScript/TypeScript and asset changes.
9
+ - No reinstall required.
10
+ - Target latency: minutes or less after publish.
11
+ - **Lane B: Binary releases (slow path)**
12
+ - Use installer/store release only when native/runtime changes are required.
13
+ - Triggered through `releases/**` and GitHub Release workflow.
14
+
15
+ Decision rule:
16
+
17
+ - JS/UI/business logic/assets changes -> OTA
18
+ - Native dependency/plugin/permission/runtime changes -> binary release
19
+
20
+ ## 2) Current Project Baseline
21
+
22
+ Already configured:
23
+
24
+ - `app.json` has `updates.url`.
25
+ - `app.json` has `runtimeVersion.policy = appVersion`.
26
+ - `eas.json` has channels:
27
+ - preview profile -> `main`
28
+ - production profile -> `production`
29
+
30
+ Implication:
31
+
32
+ - Binaries built on a channel only receive updates from that same channel and compatible runtime version.
33
+
34
+ ## 3) Target Architecture for "Instant" Updates
35
+
36
+ 1. Developer merges code to branch.
37
+ 2. CI publishes OTA update to EAS (`main` or `production` branch/channel).
38
+ 3. App receives update check trigger (foreground/resume and optional push signal).
39
+ 4. App fetches update, then applies at safe point (next app restart or immediate reload based on policy).
40
+
41
+ For binary-only updates:
42
+
43
+ 1. `releases/builder/build_MMDDYYYY_HHMM/` (or Forge under `releases/forge/...`) changes.
44
+ 2. GitHub workflow dedupes and creates Release if new.
45
+ 3. Workflow calls `POST /api/releases` webhook.
46
+ 4. Backend notifies clients that binary update is available.
47
+
48
+ ## 4) Server and CI Setup
49
+
50
+ ### 4.1 GitHub Secrets
51
+
52
+ Add repository secrets:
53
+
54
+ - `EXPO_TOKEN` (required for EAS CLI in CI)
55
+ - `RELEASE_WEBHOOK_URL` (for binary-release notification)
56
+ - `RELEASE_WEBHOOK_TOKEN` (for endpoint auth)
57
+
58
+ ### 4.2 OTA Workflow (GitHub Actions)
59
+
60
+ Create workflow `.github/workflows/eas-update.yml`:
61
+
62
+ - Trigger:
63
+ - `push` to selected branches (`main`, optionally `release/*`)
64
+ - Optional `workflow_dispatch`
65
+ - Path filters to avoid unnecessary publishes (example):
66
+ - include app source and config paths
67
+ - exclude `releases/**`
68
+ - Steps:
69
+ 1. checkout
70
+ 2. setup node
71
+ 3. install deps (`npm ci` in repository root)
72
+ 4. publish OTA:
73
+ - branch `main` for preview/internal
74
+ - branch `production` for production
75
+ 5. output EAS update group id and URL
76
+
77
+ Recommended publish command:
78
+
79
+ - `npx eas update --branch <branch> --non-interactive --message "<commit message>"`
80
+
81
+ ### 4.3 Binary Workflow (Already Planned)
82
+
83
+ Keep `releases/**` workflow with dedupe:
84
+
85
+ - If release exists, skip.
86
+ - If new, create GitHub Release and upload assets.
87
+ - Call `POST /api/releases`.
88
+
89
+ ## 5) App Runtime Behavior
90
+
91
+ Implement client update behavior with `expo-updates`:
92
+
93
+ 1. On app start and on foreground:
94
+ - call `checkForUpdateAsync()`
95
+ 2. If update exists:
96
+ - call `fetchUpdateAsync()`
97
+ 3. Apply policy:
98
+ - silent + apply on next launch (default safe)
99
+ - or prompt user and reload now (`reloadAsync()`)
100
+
101
+ Suggested policy:
102
+
103
+ - **Critical fixes:** prompt and reload now
104
+ - **Normal updates:** fetch silently and apply next launch
105
+
106
+ Minimum checks:
107
+
108
+ - On cold start
109
+ - On foreground if last check older than threshold (for example 10 minutes)
110
+
111
+ ## 6) Push-Accelerated Detection (Optional but Preferred)
112
+
113
+ OTA itself is already fast, but to reduce time further:
114
+
115
+ - Add backend push trigger when CI publishes OTA.
116
+ - App receives push and immediately runs update check.
117
+
118
+ Channels you can use:
119
+
120
+ - Expo Push Notifications
121
+ - Firebase Cloud Messaging
122
+ - WebSocket/SSE (if app has persistent session)
123
+
124
+ Fallback remains foreground polling.
125
+
126
+ ## 7) Versioning and Compatibility Rules
127
+
128
+ With `runtimeVersion.policy = appVersion`:
129
+
130
+ - OTA is only delivered to binaries with matching `expo.version`.
131
+ - When native changes occur:
132
+ - bump app version
133
+ - ship new binary
134
+ - publish OTA for that new runtime afterward
135
+
136
+ Team rule:
137
+
138
+ - Do not bump app version for pure JS hotfixes unless intentionally creating a new runtime.
139
+
140
+ ## 8) Security and Reliability
141
+
142
+ - Protect `/api/releases` using token and optional HMAC.
143
+ - Make webhook handler idempotent by `release_id`.
144
+ - Retry webhook delivery in workflow with backoff.
145
+ - Log update lifecycle:
146
+ - CI publish success/failure
147
+ - release webhook accepted/rejected
148
+ - app check/fetch/apply events (client telemetry)
149
+
150
+ ## 9) Rollout Plan
151
+
152
+ Phase 1 - Staging:
153
+
154
+ 1. Implement OTA workflow for `main` channel only.
155
+ 2. Add app-side check/fetch on startup + foreground.
156
+ 3. Test with internal build on `main`.
157
+
158
+ Phase 2 - Production:
159
+
160
+ 1. Add production publish workflow/manual gate.
161
+ 2. Add push-accelerated trigger.
162
+ 3. Monitor crash-free sessions and update adoption rate.
163
+
164
+ Phase 3 - Hardening:
165
+
166
+ 1. Add kill switch/rollback procedure.
167
+ 2. Add release dashboard with latest OTA and binary status.
168
+
169
+ ## 10) Operational Playbook
170
+
171
+ ### Publish OTA update
172
+
173
+ From repository root:
174
+
175
+ - `npx eas update --branch main --message "fix: ..."`
176
+ - for production:
177
+ - `npx eas update --branch production --message "fix: ..."`
178
+
179
+ ### Publish binary update
180
+
181
+ 1. Create `releases/builder/build_MMDDYYYY_HHMM/` with installer at root and supporting files under `dev/`.
182
+ 2. Push changes.
183
+ 3. Workflow creates (or skips duplicate) GitHub Release and calls `/api/releases`.
184
+
185
+ ### Rollback OTA
186
+
187
+ - Republish a known-good commit to the same branch/channel with a new OTA message.
188
+ - If needed, temporarily disable update checks via remote config flag.
189
+
190
+ ## 11) Acceptance Criteria
191
+
192
+ - OTA updates reach active users without reinstall for JS/UI changes.
193
+ - Median time from CI publish to client fetch is within target SLA.
194
+ - Binary updates only occur for native/runtime changes.
195
+ - Duplicate `release_id` never creates duplicate GitHub Release.
196
+ - `/api/releases` accepts only authenticated requests.
197
+ - App always has fallback update detection even if push signal fails.
198
+
199
+ ## 12) Next Implementation Tasks
200
+
201
+ 1. Create `api/releases.ts` endpoint.
202
+ 2. Add `.github/workflows/eas-update.yml`.
203
+ 3. Add client update service wrapper (`check/fetch/apply` policy).
204
+ 4. Add docs section in `build_and_install.md` linking OTA vs binary rules.
205
+ 5. Add monitoring events for update checks and apply outcomes.
@@ -0,0 +1,192 @@
1
+ # Unified Wallet Model: Telegram, Standalone, Multi-Chain & DLLR (TON)
2
+
3
+ This document proposes a single coherent setup for the tensions between:
4
+
5
+ - A **Telegram-first** experience (Mini App, bot confirmations, CloudStorage-assisted UX).
6
+ - **Standalone operation** when Telegram is unavailable, blocked, or the user simply prefers not to use it.
7
+ - **Non-custodial** custody: keys and mnemonics never held by our servers.
8
+ - **DLLR** and core product flows anchored on **TON**, where issuance and program logic are expected to live.
9
+ - **Multiple chains** where users may hold assets or use bridges, without fragmenting identity or safety.
10
+
11
+ It complements `wallets_hosting_architecture.md`, `security_raw.md`, and `security_plan_raw.md` by resolving “which path wins when” and how they fit together.
12
+
13
+ ---
14
+
15
+ ## 1. Core idea: one logical wallet, three *surfaces*
16
+
17
+ Think in terms of **one user-owned root of trust** (mnemonic for the primary TON wallet, and optional additional key material for other chains), and **three ways to use it**:
18
+
19
+ | Surface | What it is | Best for |
20
+ |--------|------------|----------|
21
+ | **A. Telegram-hosted (TMA)** | Same non-custodial keys; encrypted material split between Telegram `SecureStorage` + `CloudStorage` (ciphertext only), identity via `initData`. | Smoothest UX inside Telegram, bot-driven tx confirmation, push-to-sign. |
22
+ | **B. Unhosted / standalone** | Keys only on device OS keystore / WebCrypto; no Telegram APIs required to open the app or sign. | Telegram outage, privacy preference, store-review-friendly “works without Telegram”. |
23
+ | **C. Connected** | External wallets via **TON Connect** (TON) and, later, analogous **WalletConnect** / chain-specific SDKs for other networks. | Power users, hardware wallets, assets already elsewhere. |
24
+
25
+ **Important:** Surfaces are **not** different custodial models. They differ only in **where keys live** and **which transport** is used for identity and sync. The backend stores **public** data (addresses, `telegram_username` ↔ address mapping when the user opts in), never mnemonics.
26
+
27
+ ---
28
+
29
+ ## 2. Why Telegram alone is not enough (and how we fix it)
30
+
31
+ Telegram can be unreachable (outage, censorship, user choice). A product that *only* creates or signs inside the Mini App forces a hard dependency on Telegram for custody and signing.
32
+
33
+ **Proposal:**
34
+
35
+ 1. **Default recommended path** remains: create primary **TON** wallet in TMA (best onboarding, aligns with bot + DLLR messaging).
36
+ 2. **Mandatory parallel capability:** the same app build supports **Create / Restore wallet locally** (standalone) with **no Telegram account** and **no bot call** for key generation.
37
+ 3. **Linking layer (optional):** if the user *has* Telegram, they can **link** `telegram_username` ↔ `wallet_address` so CloudStorage sync and bot confirmations work. If they never link, they remain fully standalone; DLLR/Ton features still work on-chain by address.
38
+ 4. **Degraded mode:** if Telegram is down but the user already has keys on device, the app runs **full local signing** for TON (and any chain we have implemented client-side). Features that *require* the bot (e.g. push approval via Telegram) show a clear “Unavailable while Telegram is unreachable” with fallback: open pending items in TMA later, or confirm via standalone signing if the flow allows.
39
+
40
+ This matches non-custodial rules: the server never becomes the signing authority.
41
+
42
+ ---
43
+
44
+ ## 3. DLLR on TON as the canonical product wallet
45
+
46
+ **Clarification to remove confusion:**
47
+
48
+ - **Primary app wallet** = **TON** address derived from the user’s main mnemonic (or from a TON Connect wallet they set as default).
49
+ - **DLLR** is treated as a **TON jetton / program** (or locked-state construct per your issuance design). Balances, locks, and allocations are **read and signed on TON**.
50
+ - “Multi-chain” does **not** mean DLLR exists on every chain. It means:
51
+ - **User may connect other addresses** for portfolio view, bridges, or future features.
52
+ - **Product-critical flows** (rewards, locks, compliance hooks tied to DLLR) stay **TON-first**.
53
+
54
+ **UI rule:** always show a clear **“Primary (TON + DLLR)”** section, then **“Other networks”** as secondary, so expectations stay aligned with issuance on TON.
55
+
56
+ ---
57
+
58
+ ## 4. Multi-chain matrix (recommended model)
59
+
60
+ Use a single **wallet registry** in the client and the `wallets` table (as in `security_plan_raw.md`), with explicit `blockchain`, `net`, and `type`:
61
+
62
+ | Type | Example | Custody |
63
+ |------|---------|--------|
64
+ | `internal` | App-generated TON keypair | Non-custodial; keys in device/TMA storage |
65
+ | `tonconnect` | Tonkeeper, MyTonWallet | User’s external wallet; we only hold address + session |
66
+ | `walletconnect` / `evm` / `solana` (future) | MetaMask, Phantom, … | Same: address + connection state |
67
+
68
+ **Telegram-hosted vs unhosted** applies only to **`internal`** wallets:
69
+
70
+ - In TMA, `internal` wallet uses SecureStorage + CloudStorage ciphertext split.
71
+ - In standalone app, `internal` wallet uses only OS secure storage (same cryptography, different storage adapters).
72
+
73
+ **Connected** wallets are **always** “hosted” by the third-party provider, not by Telegram and not by us.
74
+
75
+ ---
76
+
77
+ ## 5. Identity: Telegram as optional glue, not a single gate
78
+
79
+ Today’s docs lean **Telegram-first** for onboarding. The unified model adds:
80
+
81
+ | User state | Can use app? | DLLR / TON actions |
82
+ |------------|--------------|--------------------|
83
+ | Standalone, never linked Telegram | Yes (after local create/restore) | Yes, if keys on device |
84
+ | Telegram user, wallet only in TMA | Yes in TMA; on mobile/web after Telegram Login | Signing in TMA; read-only elsewhere unless mnemonic imported locally (optional advanced) |
85
+ | Linked Telegram + local keys | Yes everywhere | Full: bot confirmations where implemented + local signing fallback |
86
+
87
+ **Backend:**
88
+
89
+ - `users.telegram_username` is **nullable** for standalone-only users, or use a separate **account id** (emailless) keyed by device-chosen identifier only for analytics—not for custody.
90
+ - Linking Telegram is a **deliberate** step: “Connect Telegram for notifications and faster sync.”
91
+
92
+ ---
93
+
94
+ ## 6. First run and subsequent runs (program behavior)
95
+
96
+ This section describes what the **client program** does on **cold start** (first launch or fresh install) versus **later launches** on the same install, for each major surface. It aligns with the state machine in `wallets_hosting_architecture.md` (e.g. `awallet_v1`, deploy status).
97
+
98
+ ### 6.1 Shared startup sequence (all surfaces)
99
+
100
+ 1. **Bootstrap UI shell** — Router loads; global providers start (network, wallet context).
101
+ 2. **Detect environment** — `TMA` (Telegram WebApp present) vs **standalone** (Expo native / open web) vs **web + Telegram Login** (widget session).
102
+ 3. **Resolve wallet presence** — Read local secure storage keys (`awallet_v1` or equivalent): encrypted blob for `internal` wallet, plus any **connected** wallet session handles (TON Connect).
103
+ 4. **Branch:**
104
+ - **No wallet record** → onboarding (Section 6.2).
105
+ - **Wallet record present** → main app (Section 6.3).
106
+
107
+ Balances and DLLR/TON state are **always** refreshed asynchronously after UI is usable (do not block first paint on RPC unless product requires it).
108
+
109
+ ---
110
+
111
+ ### 6.2 First run (no wallet on this install)
112
+
113
+ | Entry | What the user sees | What the program does |
114
+ |--------|--------------------|------------------------|
115
+ | **Telegram Mini App** | Intro → **Create wallet** / **Restore wallet** (optional **Connect Tonkeeper** if offered). | Generates mnemonic locally; stores **wallet master key** in Telegram `SecureStorage`; stores **seed ciphertext** in `CloudStorage`; registers **public** `wallet_address` (+ `telegram_username` from `initData`) with backend. Shows address and QR immediately; may show **Deploying** for SMC/jetton setup; nudges **backup seed**. |
116
+ | **Standalone (native / web, no Telegram)** | Same choice: **Create** / **Restore** / **Connect** external wallet. | Generates or imports keys using **only** OS keystore / WebCrypto; **no** `initData`, **no** CloudStorage unless user later links Telegram. Optional backend call with a **non-Telegram** account id or anonymous mode until linked. |
117
+ | **Store mobile app (Telegram-centric onboarding)** | Per `security_raw.md`: “Create wallet in Telegram” vs “I already have a wallet” + **Log in with Telegram**. | First path deep-links to TMA; second uses **Telegram Login** to fetch **public** linkage (`username` → `wallet_address`) for **read-only** until user imports mnemonic on device (if you add that flow). |
118
+
119
+ **First run, new Telegram device (TMA):** `CloudStorage` may already hold **ciphertext** from another device, but **SecureStorage** is empty → program shows **Authorize this device** and asks for **mnemonic once**, then writes local master key and proceeds as normal.
120
+
121
+ **First run, connected wallet only (TON Connect):** No internal blob; program stores connection session + address; primary balance flows use that address until user adds an `internal` wallet.
122
+
123
+ ---
124
+
125
+ ### 6.3 Subsequent runs (wallet already on this device)
126
+
127
+ | Condition | Program behavior |
128
+ |-----------|------------------|
129
+ | **Encrypted blob + device key present** | **Silent load:** decrypt wallet, navigate to **home / wallet** without asking for seed. Poll `/wallet/status` or chain APIs for **deploy status**, **TON balance**, **DLLR** state. If deploy was **pending**, **retry deploy** in background (same as `wallets_hosting_architecture.md`). |
130
+ | **TMA + CloudStorage ciphertext + SecureStorage OK** | Same silent path; CloudStorage may sync updates from other Telegram clients. |
131
+ | **Standalone + keys in local secure storage** | Same as row 1; **no** Telegram dependency for open or sign. |
132
+ | **User opened “Log in with Telegram” on mobile** | After verified login, app loads **cached** `telegram_username` + **addresses** from API; UI is **read-first** until local signing is enabled (mnemonic import), matching your phased plan. |
133
+ | **Telegram unavailable (outage / blocked)** | If keys exist locally: **full app** for signing and reads that do not need the bot. If keys exist **only** in TMA on a device that cannot open Telegram: user must use **restore** on standalone build or wait for Telegram. Features that need the bot show **degraded / queue** messaging. |
134
+ | **App update** | Same storage keys (`awallet_v1` versioning); run **migration** if blob format bumps. Wallet survives update if paths are stable. |
135
+
136
+ **Subsequent run UX expectations:** back up seed remains **dismissible** until acknowledged; high-value actions may still route through **pending tx + bot confirmation** when Telegram is linked and the flow requires it.
137
+
138
+ ---
139
+
140
+ ### 6.4 Summary table
141
+
142
+ | | First run | Subsequent runs |
143
+ |---|-----------|-----------------|
144
+ | **Typical path** | Onboarding → create / restore / connect | Silent unlock → home → background balance/deploy sync |
145
+ | **Telegram required?** | Only for TMA path or Telegram-login shell | No, if standalone keys exist; yes for TMA-specific features |
146
+ | **Seed prompt** | At creation (show once) or restore; optional “authorize device” on new TMA device | Only if blob missing, storage wiped, or user hits **Restore** |
147
+
148
+ ---
149
+
150
+ ## 7. “Perfect setup” summary (one paragraph)
151
+
152
+ **Ship one Expo app** with three entry modes: (1) **Telegram Mini App** for best-in-class onboarding, CloudStorage-backed ciphertext sync, and bot-mediated confirmations; (2) **standalone** create/restore so the app **always launches** and can sign TON (and DLLR) without Telegram; (3) **TON Connect + future multi-chain connectors** for imported liquidity and power users. Treat **TON + DLLR** as the single source of truth for product economics; treat other chains as **attached accounts**. Keep **mnemonic / keys** only on the client, **ciphertext** in CloudStorage when Telegram is used, and **public addresses + optional Telegram link** on the server. When Telegram is down, **degrade gracefully**: local signing and read paths keep working; Telegram-only steps queue or hide with clear messaging.
153
+
154
+ ---
155
+
156
+ ## 8. Implementation phases (aligned with existing roadmap)
157
+
158
+ 1. **Phase A — Standalone parity (minimum viable resilience)**
159
+ - Unhosted TON create/restore in **Expo web + native** without Telegram.
160
+ - Same `WalletService` abstraction as in `wallets_hosting_architecture.md`; storage backend switches on environment (TMA vs native).
161
+ - Optional “Link Telegram” after the fact.
162
+
163
+ 2. **Phase B — Linking & DB**
164
+ - Nullable Telegram on `users`; `wallets` rows for `internal` + `tonconnect`.
165
+ - Telegram Login only for users who want cross-surface sync.
166
+
167
+ 3. **Phase C — Bot confirmations + queue**
168
+ - Pending tx from any client; confirmation in TMA when available; standalone users complete via **local sign** without bot where the protocol allows.
169
+
170
+ 4. **Phase D — Multi-chain read + selective write**
171
+ - Add connected chains for **display** first; add signing per chain as product requires.
172
+
173
+ ---
174
+
175
+ ## 9. Security notes (unchanged principles)
176
+
177
+ - No mnemonic on server; CloudStorage holds **ciphertext only**; device-bound keys decrypt.
178
+ - Telegram Login proves **identity**, not possession of keys.
179
+ - Standalone users rely on **seed backup** exactly as in self-custody best practice.
180
+ - DLLR issuance rules remain **on-chain** on TON; our app is a **client**, not an issuer.
181
+
182
+ ---
183
+
184
+ ## 10. Open decisions (to refine with product/legal)
185
+
186
+ - Whether standalone users get **full** DLLR program participation or **subset** until KYC/Telegram link (if required by issuance policy).
187
+ - Exact **jetton master** and **wallet v4/v5** choices for DLLR display and deploy flows.
188
+ - Whether **one mnemonic** derives only TON or also other chains (prefer **separate mnemonics** per chain unless using a documented multi-chain HD profile).
189
+
190
+ ---
191
+
192
+ *Proposal doc; iterate with team and adjust table/column names to match the actual migration from `security_plan_raw.md`.*