@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,188 @@
1
+ # GitHub Releases Automation Plan (Final)
2
+
3
+ This document defines the production plan for release detection, deduped GitHub Release publishing, and near-instant app update signaling.
4
+
5
+ ## Goals
6
+
7
+ - Build the Windows installer on GitHub Actions (`windows-latest`) with `npm run build:win` (no `.exe` committed to git).
8
+ - Publish the installer to a GitHub Release only when that release tag does not already exist.
9
+ - Notify an app-update service immediately after a new release is published.
10
+ - Keep app-side update detection near-instant using push notification plus fallback polling.
11
+
12
+ ## Source of Truth
13
+
14
+ - The **GitHub Release tag** is the release identity (`release_id`), for example `build_03252026_1929`.
15
+ - Locally and in CI, `windows/cleanup.cjs` places the installer under `releases/builder/build_MMDDYYYY_HHMM/HyperlinksSpaceProgramInstaller_<stamp>.exe` (other files under `dev/`). In CI, set `RELEASE_BUILD_ID` to pin the folder/tag, or omit it to use the timestamp from build time.
16
+
17
+ ## When You Must Make a New Installer Release
18
+
19
+ Create a new installer/GitHub Release when a change is native/runtime-level and cannot be delivered safely by OTA update alone.
20
+
21
+ Native/runtime changes include:
22
+
23
+ - Adding, removing, or upgrading native libraries/modules (anything requiring a new Android/iOS/desktop binary).
24
+ - Changing app permissions or OS capabilities (camera, notifications, background modes, file access, etc.).
25
+ - Changing Expo config plugins or native project settings that affect the compiled binary.
26
+ - Upgrading Expo SDK/React Native/runtime where binary compatibility changes.
27
+ - Changing `runtimeVersion` strategy/value, or bumping app version when `runtimeVersion.policy` depends on it.
28
+ - Changing signing/notarization/install packaging behavior for distributed installers.
29
+ - Any fix that touches native code or build-time platform configuration.
30
+
31
+ Do not make a new installer release for:
32
+
33
+ - Pure JavaScript/TypeScript logic changes.
34
+ - UI changes in React components.
35
+ - Asset/text/content updates that are OTA-compatible.
36
+ - API integration changes that do not alter native dependencies.
37
+
38
+ Practical decision checklist:
39
+
40
+ 1. Does this change require rebuilding a platform binary to work? If yes, make installer release.
41
+ 2. Does this change alter native modules, permissions, SDK/runtime, or build config? If yes, make installer release.
42
+ 3. If both answers are no, publish OTA update only and skip installer release.
43
+
44
+ ## Workflow Trigger
45
+
46
+ - **Manual only:** `workflow_dispatch` (workflow “Windows release (CI build)”).
47
+ - Optional input **release_id** (`build_MMDDYYYY_HHMM`). If empty, the tag is taken from the build output after `cleanup.cjs`.
48
+
49
+ Example trigger:
50
+
51
+ ```yaml
52
+ on:
53
+ workflow_dispatch:
54
+ inputs:
55
+ release_id:
56
+ description: "Optional tag, e.g. build_03252026_1929"
57
+ required: false
58
+ default: ""
59
+ ```
60
+
61
+ ## Dedupe Rules (No Duplicate Releases)
62
+
63
+ 1. Run `npm run build:win` (optionally with `RELEASE_BUILD_ID` so the output folder matches the intended tag).
64
+ 2. Resolve `release_id` from the workflow input or from `releases/builder/build_*/HyperlinksSpaceProgramInstaller_*.exe`.
65
+ 3. Check whether GitHub Release/tag already exists for that `release_id`.
66
+ 4. If it exists:
67
+ - Exit successfully (`0`)
68
+ - Do not upload assets
69
+ - Do not send webhook notification
70
+ 5. If it does not exist:
71
+ - Create GitHub Release/tag
72
+ - Upload `HyperlinksSpaceProgramInstaller.exe` as the release asset
73
+ - Continue to webhook notification
74
+
75
+ Recommended extra safety:
76
+
77
+ - Use workflow `concurrency` keyed by `release_id` to avoid race conditions.
78
+
79
+ ## Endpoint Contract
80
+
81
+ - Webhook endpoint path: `api/releases.ts`
82
+ - Route URL: `POST /api/releases`
83
+ - Purpose: accept release-published events from GitHub Actions and fan out update notifications to app clients.
84
+
85
+ ## Security
86
+
87
+ - GitHub Actions sends auth header:
88
+ - `x-release-token: <secret>`
89
+ - Endpoint validates against:
90
+ - `process.env.RELEASE_WEBHOOK_TOKEN`
91
+ - Optional hardening:
92
+ - Add HMAC signature verification for request body.
93
+
94
+ If auth fails:
95
+
96
+ - Return `401` and do not process payload.
97
+
98
+ ## Payload Shape
99
+
100
+ `POST /api/releases` expects JSON:
101
+
102
+ ```json
103
+ {
104
+ "release_id": "build_03252026_1929",
105
+ "version": "1.0.0",
106
+ "published_at": "2026-03-25T19:29:00Z",
107
+ "platform": "windows",
108
+ "assets": [
109
+ {
110
+ "name": "HyperlinksSpaceProgramInstaller.exe",
111
+ "url": "https://github.com/<org>/<repo>/releases/download/build_03252026_1929/HyperlinksSpaceProgramInstaller.exe",
112
+ "sha256": "<optional>"
113
+ }
114
+ ],
115
+ "github_release_url": "https://github.com/<org>/<repo>/releases/tag/build_03252026_1929"
116
+ }
117
+ ```
118
+
119
+ ## Endpoint Behavior (`api/releases.ts`)
120
+
121
+ 1. Accept only `POST`.
122
+ 2. Validate auth token/signature.
123
+ 3. Parse and validate required fields:
124
+ - `release_id`, `published_at`, `assets`.
125
+ 4. Enforce idempotency by `release_id`:
126
+ - If already processed, return `200 { ok: true, duplicate: true }`.
127
+ 5. Store/update latest release metadata in persistent storage.
128
+ 6. Push update signal to clients (WebSocket/SSE/Firebase/Expo push).
129
+ 7. Return quickly with `200 { ok: true }`.
130
+
131
+ ## GitHub Actions Notification Step
132
+
133
+ After successful release creation and asset upload:
134
+
135
+ 1. Read webhook URL and token from repository secrets:
136
+ - `RELEASE_WEBHOOK_URL`
137
+ - `RELEASE_WEBHOOK_TOKEN`
138
+ 2. Send `POST` to `/api/releases` with release payload.
139
+ 3. Retry webhook call with backoff on transient failures.
140
+
141
+ Important:
142
+
143
+ - Do not send webhook if release already existed (dedupe branch).
144
+
145
+ ## App Update Strategy
146
+
147
+ Primary strategy:
148
+
149
+ - Real-time push signal from backend triggered by `/api/releases`.
150
+
151
+ Fallback strategy:
152
+
153
+ - App checks latest release on:
154
+ - app foreground/resume
155
+ - periodic interval (for example every 5-15 minutes)
156
+
157
+ Client behavior:
158
+
159
+ 1. Compare local build/version with latest server metadata.
160
+ 2. If newer exists:
161
+ - Show "Update available" prompt or trigger controlled update flow.
162
+
163
+ ## Reliability and Observability
164
+
165
+ - Idempotent handling on `release_id`.
166
+ - Structured logs for each stage:
167
+ - detected -> published/skipped -> webhook sent -> app signal broadcast
168
+ - Alert on partial failure:
169
+ - release created but webhook failed
170
+ - Keep webhook processing fast and non-blocking for external calls.
171
+
172
+ ## Rollout Plan
173
+
174
+ 1. Deploy `api/releases.ts` in staging.
175
+ 2. Run workflow in dry-run mode to validate folder parsing and dedupe checks.
176
+ 3. Enable real release creation for test folder.
177
+ 4. Enable webhook call to staging endpoint.
178
+ 5. Verify end-to-end with one client device.
179
+ 6. Promote to production after stable validation.
180
+
181
+ ## Acceptance Criteria
182
+
183
+ - A new `releases/builder/build_.../` folder produces exactly one GitHub Release.
184
+ - Re-running workflow for the same `release_id` does not create duplicates.
185
+ - Webhook is called only for newly created releases.
186
+ - `POST /api/releases` rejects unauthorized requests.
187
+ - Connected app receives update signal near-instantly in normal conditions.
188
+ - Fallback polling still discovers updates if push delivery fails.
@@ -0,0 +1,34 @@
1
+ # Scalability overview and challenges
2
+
3
+ **Stack:** Vercel serverless (webhook, API), Neon Postgres, Telegram bot (Grammy), OpenAI, single `messages` table for bot + TMA.
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ - **Webhook:** Stateless. Returns 200 immediately; update is processed in `waitUntil`. No in-memory state between requests. Vercel scales out with traffic (more concurrent requests → more instances).
10
+ - **Bot:** One bot instance per serverless instance (module-level in webhook). No global singleton; fits serverless.
11
+ - **Dedupe / “only latest wins”:** Done in the DB (`telegram_update_id` unique constraint + `getMaxTelegramUpdateIdForThread`). Works across instances; no reliance on in-process state.
12
+ - **Messages:** One table, indexed by `(user_telegram, thread_id, type, created_at)` and unique on `(..., telegram_update_id)` for bot. Per-request load is small (insert user, get history, insert assistant, optional max-update-id read).
13
+ - **Database:** Neon with **connection pooling** already on (supports up to 10,000 concurrent connections). Use the pooled `DATABASE_URL` in Vercel so serverless invocations go through the pooler.
14
+
15
+ The design is horizontally scalable: more users → more invocations → more instances; no single bottleneck in the app logic.
16
+
17
+ ---
18
+
19
+ ## Challenges and what to do
20
+
21
+ | Area | Challenge | What to do |
22
+ |------|-----------|------------|
23
+ | **DB connections** | Pooling is already on (up to 10,000 concurrent connections). | Ensure `DATABASE_URL` in Vercel is the **pooled** connection string from Neon. |
24
+ | **OpenAI** | Limits are per key (RPM/TPM). One key can scale. | Raise **usage tier** (limits increase with spend/account age—e.g. Tier 4: 10k RPM, 2M TPM). Enterprise: **Scale Tier** for dedicated capacity. Optionally multiple keys or queue only if you need beyond tier limits. |
25
+ | **Vercel** | Hobby has invocation/duration limits; long AI flows need enough timeout. | Use Pro (or Enterprise) for production at scale; set function timeout to cover longest flow (e.g. streaming + DB). |
26
+ | **Messages table** | Grows with users and time; very large tables can slow queries and increase cost. | Retention (delete or archive old threads); optional partitioning by time or user; keep `getThreadHistory` with a small `limit`. |
27
+ | **Observability** | At scale, bottlenecks and errors are hard to see without metrics. | Logging, metrics, and alerts (errors, latency, DB pool usage, OpenAI rate limits) in Vercel/Neon or a third-party tool. |
28
+
29
+ ---
30
+
31
+ ## Summary
32
+
33
+ - **Scalable:** Stateless webhook, 200-first response, DB-backed dedupe and history, Neon connection pooling.
34
+ - **To scale to very high traffic:** Neon pooling is already on (10k connections); keep using the pooled `DATABASE_URL`. For OpenAI, extend plan/usage to reach a higher tier (or Scale Tier for enterprise); one key is enough. Plan for Vercel limits/timeouts; add message retention and monitoring.
@@ -0,0 +1,244 @@
1
+ # Security Implementation Plan (Telegram-First Wallet)
2
+
3
+ This file describes a practical implementation plan for the security model defined in `security.md`, focused on the repository-root Expo/Vercel codebase and a serverless backend.
4
+
5
+ ---
6
+
7
+ ## Phase 0 – Prerequisites & Plumbing
8
+
9
+ - **0.1. Bot & Mini App configuration**
10
+ - Ensure main Mini App is configured in @BotFather with:
11
+ - `https://hsbexpo.vercel.app` (or new URL) as base.
12
+ - `startapp` support enabled.
13
+ - Confirm `telegram-web-app.js` is loaded in the Mini App shell.
14
+
15
+ - **0.2. Serverless backend basics**
16
+ - Use existing Vercel project (repository root) API routes:
17
+ - Create a shared util for **Telegram initData validation** (WebApp) in `api/_lib/telegram.ts`:
18
+ - `validateInitData(initData: string): { username: string }`.
19
+ - Create a shared util for **Telegram Login widget validation** (web/native) in `api/_lib/telegram_login.ts`:
20
+ - `validateLoginPayload(payload): { username: string }`.
21
+
22
+ - **0.3. Database**
23
+ - Choose a serverless DB (e.g. Neon, Supabase, PlanetScale, Vercel Postgres).
24
+ - Define tables (supporting **multiple wallets per user**, including app-created and TonConnect-linked):
25
+ - `users`:
26
+ - `telegram_username` (PK or unique, text).
27
+ - `created_at`, `updated_at`.
28
+ - `last_login_at` – last successful Telegram login (any platform).
29
+ - `last_tma_seen_at` – last time user opened the Mini App.
30
+ - `locale` – preferred language (derived from Telegram).
31
+ - `time_zone` (optional, from app settings).
32
+ - `number_of_wallets` – cached count for quick UI/query.
33
+ - `default_wallet` – optional reference/key to the user’s default wallet (e.g. `wallet_address` + `wallet_blockchain` + `wallet_net` tuple or UI identifier).
34
+ - `security_flags` (JSON) – e.g. `{ "high_value_user": true, "require_extra_confirm": false }`.
35
+ - `marketing_opt_in` (bool) – whether user agreed to non-transactional notifications.
36
+ - `wallets`:
37
+ - `telegram_username` (FK to `users`).
38
+ - `address` (text).
39
+ - `blockchain` (text, e.g. `'ton'`).
40
+ - `net` (text, e.g. `'mainnet'`, `'testnet'`).
41
+ - `type` (`'internal' | 'tonconnect' | 'other'`) – app-created vs external/connected.
42
+ - `label` (optional user-friendly name, e.g. “Main wallet”, “Tonkeeper”).
43
+ - `is_default` (bool) – which wallet to show first in UI.
44
+ - Composite PK/unique: (`telegram_username`, `wallet_address`, `wallet_blockchain`, `wallet_net`).
45
+ - `created_at` – when this wallet record was created (first seen / added).
46
+ - `updated_at` – when this wallet record was created (first seen / added).
47
+ - `last_used_at` – last time a transaction was initiated or confirmed with this wallet.
48
+ - `last_seen_balance_at` – last time we refreshed its on-chain balance
49
+ - `source` – 'miniapp', 'tonconnect', 'imported' (how it was added)
50
+ - `notes` – (optional text): free-form user note about this wallet.
51
+ - Timestamps / metadata (last_used_at, etc.).
52
+ - `pending_transactions`:
53
+ - `id` (UUID / text, PK).
54
+ - `telegram_username` (FK to `users`).
55
+ - `wallet_address` (text).
56
+ - `wallet_blockchain` (text).
57
+ - `wallet_net` (text).
58
+ - `payload` (JSONB / text).
59
+ - `status` (`pending | confirmed | rejected | failed`).
60
+ - `created_at`, `updated_at`.
61
+ - Add minimal DB client in `api/_lib/db.ts`.
62
+
63
+ ---
64
+
65
+ ## Phase 1 – Telegram Mini App: Wallet Creation & Device Auth
66
+
67
+ - **1.1. Mini App bootstrap**
68
+ - Create a dedicated Mini App entry screen in Expo web (`app/app/index.tsx` or a nested route) that:
69
+ - Accesses `window.Telegram.WebApp.initData`.
70
+ - Calls a backend endpoint `POST /api/tg/init` to:
71
+ - Validate `initData`.
72
+ - Upsert a bare `users` row if needed (without wallet).
73
+
74
+ - **1.2. Wallet creation flow (TMA)**
75
+ - Implement a React flow in the Mini App:
76
+ - Step 1: Intro + explanation (self-custody, seed phrase).
77
+ - Step 2: Generate mnemonic (client-side) with a TON/crypto library.
78
+ - Step 3: Show mnemonic & confirmation quiz.
79
+ - Step 4:
80
+ - Derive wallet master key from mnemonic.
81
+ - Store it via `SecureStorage.setItem('wallet_master_key', …)` when supported; if that fails (e.g. Desktop `UNSUPPORTED`), fall back to `DeviceStorage` and warn the user (see `docs/security_raw.md`).
82
+ - Derive/encode wallet seed or root key, encrypt with master key → `seed_cipher`.
83
+ - Store `seed_cipher` via `Telegram.WebApp.CloudStorage.setItem('wallet_seed_cipher', <cipher>)`.
84
+ - Derive `wallet_address` from mnemonic/root key.
85
+ - Call `POST /api/wallet/register` with `{ telegram_username, wallet_address }` (initData-validated).
86
+ - Step 5: Success screen explaining:
87
+ - “Wallet created in Telegram; keep your mnemonic safe.”
88
+ - “Use Android/iOS/web to view wallet after logging in with Telegram.”
89
+
90
+ - **1.3. New Telegram device authorization**
91
+ - At Mini App start:
92
+ - Check `SecureStorage.getItem('wallet_master_key')`.
93
+ - If present → user can operate without extra input.
94
+ - If absent but `CloudStorage.getItem('wallet_seed_cipher')` exists:
95
+ - Show “Authorize this device” screen:
96
+ - Prompt for mnemonic once.
97
+ - Derive new master key, store in `SecureStorage`.
98
+ - Optionally re-encrypt `seed_cipher` (or just reuse old one).
99
+
100
+ ---
101
+
102
+ ## Phase 2 – iOS/Android App Flow (Single App)
103
+
104
+ (All implemented in the repository root app using Expo Router / React Native.)
105
+
106
+ - **2.1. Local state**
107
+ - Add a simple secure storage wrapper (e.g. `expo-secure-store`):
108
+ - Keys:
109
+ - `telegram_username`
110
+ - `wallet_address`
111
+ - Add a React context or hook `useCurrentUser()` that:
112
+ - On app start, reads these keys.
113
+ - Exposes `state: 'anonymous' | 'linked'`, `telegram_username`, `wallet_address`.
114
+
115
+ - **2.2. “Log in with Telegram” screen**
116
+ - Create a route (e.g. `app/app/login/telegram.tsx`) used on mobile startup when `state === 'anonymous'`:
117
+ - Copy text from `security.md`:
118
+ - Explain benefits of Telegram-based wallet creation and storage.
119
+ - Buttons:
120
+ - **Open Telegram to create wallet**:
121
+ - Use `Linking.openURL('https://t.me/<bot_username>?startapp=wallet_onboarding')`.
122
+ - **I already created my wallet in Telegram / Log in with Telegram**:
123
+ - Opens a WebView or browser to hosted login page (e.g. `/login/telegram`).
124
+
125
+ - **2.3. Telegram Login for Websites (web page + API)**
126
+ - Create a web page (static route in repository root or separate) that:
127
+ - Embeds the Telegram Login widget configured for your bot & domain.
128
+ - On success, posts the payload (via `data-onauth` callback) to `POST /api/login/telegram`.
129
+ - `POST /api/login/telegram`:
130
+ - Validates login payload (`hash` + `auth_date`) per [Telegram widget docs](https://core.telegram.org/widgets/login).
131
+ - Extracts `username`.
132
+ - Looks up `users` by `telegram_username`.
133
+ - Responds with:
134
+ - On success: `{ telegram_username, wallet_address }`.
135
+ - On missing wallet: `{ error: 'NO_WALLET' }`.
136
+ - In the mobile WebView:
137
+ - When login completes, post a message back to the React Native layer with the above payload.
138
+ - Native side saves `telegram_username` + `wallet_address` via secure storage and updates `useCurrentUser()` state.
139
+
140
+ - **2.4. Main wallet UI on mobile**
141
+ - When `useCurrentUser()` reports `state === 'linked'`:
142
+ - Show wallet balances / positions (read-only) via:
143
+ - Direct chain APIs or your own serverless `GET /api/wallet/state?address=...`.
144
+ - For any **sensitive action** (swap, send, etc.) use the serverless + bot confirmation flow (Phase 3).
145
+
146
+ ---
147
+
148
+ ## Phase 3 – Serverless Transaction Flow & Bot Confirmation
149
+
150
+ - **3.1. Create transaction (serverless route)**
151
+ - Add `POST /api/tx/create`:
152
+ - Auth:
153
+ - From Mini App: validate `initData`, resolve `telegram_username`.
154
+ - From web/mobile: require a session or signed JWT containing `telegram_username` from Telegram login.
155
+ - Validate payload (action, amount, destination).
156
+ - Insert into `pending_transactions` with status `pending`.
157
+ - Use bot token to call `sendMessage` with:
158
+ - Text summary.
159
+ - Inline `web_app` button pointing to `https://t.me/<bot_username>?startapp=tx_<id>`.
160
+ - Return `{ id }` to caller for polling.
161
+
162
+ - **3.2. Confirmation page in Mini App**
163
+ - Implement a `tx/[id]`-like route in the Mini App (or use `start_param` parsing on the main screen) that:
164
+ - Reads `start_param` → extracts `<id>`.
165
+ - Calls `GET /api/tx/<id>`:
166
+ - Validates `initData`, ensures tx belongs to `telegram_username`.
167
+ - Returns tx summary (read-only).
168
+ - UI:
169
+ - Shows:
170
+ - Asset, amount, from / to addresses, network, estimated fee.
171
+ - A big, unambiguous **“Confirm”** button and a **“Reject”** button.
172
+
173
+ - **3.3. Local signing & completion**
174
+ - On **Confirm**:
175
+ - Mini App:
176
+ - Reconstructs the on-chain transaction from the payload and `wallet_address`.
177
+ - Signs it with the wallet key derived from mnemonic / master key in `SecureStorage`.
178
+ - Sends `POST /api/tx/<id>/complete` with:
179
+ - `id`
180
+ - `signedTx` (or `txHash` if client broadcasts).
181
+ - `decision: 'confirmed'`.
182
+ - `POST /api/tx/<id>/complete`:
183
+ - Validates `initData` and ownership.
184
+ - Verifies tx is still `pending`.
185
+ - Option A (backend broadcasting):
186
+ - Broadcast `signedTx` to RPC endpoint.
187
+ - On success/failure, update `status` accordingly and store `tx_hash`.
188
+ - Option B (client broadcasting):
189
+ - Trust `txHash` and mark as `confirmed`, or perform lightweight verification.
190
+ - Returns final status to Mini App.
191
+
192
+ - **3.4. Rejection path**
193
+ - On **Reject**:
194
+ - Mini App calls `POST /api/tx/<id>/complete` with `decision: 'rejected'`.
195
+ - Backend sets status `rejected`.
196
+
197
+ - **3.5. Client status updating**
198
+ - Any client that initiated the tx (Mini App, web, mobile app):
199
+ - Polls `GET /api/tx/<id>` until `status !== 'pending'`.
200
+ - Or uses lightweight WebSocket/SSE if desired.
201
+
202
+ ---
203
+
204
+ ## Phase 4 – Hardening & Observability
205
+
206
+ - **4.1. Logging & audit**
207
+ - Add structured logging in all API routes:
208
+ - User identity (`telegram_username`), tx id, IP, user agent.
209
+ - Consider a `tx_history` view for user self-audits.
210
+
211
+ - **4.2. Rate limiting & abuse protection**
212
+ - Add rate limiting (IP + username) on:
213
+ - `/api/tx/create`
214
+ - `/api/login/telegram`
215
+ - Consider CAPTCHA or additional friction on spammy accounts.
216
+
217
+ - **4.3. Secrets & config**
218
+ - Store:
219
+ - Bot token, DB URL, RPC URLs, etc. in Vercel environment variables.
220
+ - Never log full mnemonics or keys; ensure any debug logging never prints sensitive values.
221
+
222
+ - **4.4. UX safety rails**
223
+ - On confirmation pages (Mini App & web):
224
+ - Highlight destination address and allow user to copy it.
225
+ - Show human-readable asset names & verify network.
226
+ - For large amounts, add extra confirmation step or warning.
227
+
228
+ ---
229
+
230
+ ## Phase 5 – Optional Enhancements
231
+
232
+ - **5.1. Advanced local wallets (non-default)**
233
+ - In the mobile app and/or web app, optionally add:
234
+ - “Import mnemonic to this device” flow (explicit, with big warnings).
235
+ - Keep Telegram-first as the recommended path in docs and UI.
236
+
237
+ - **5.2. Multi-device / guardian support (future)**
238
+ - Extend smart contract / wallet to support multiple keys or social recovery.
239
+ - Use Telegram as one guardian channel among others.
240
+
241
+ ---
242
+
243
+ This plan should be implemented iteratively: Phase 1 (Mini App wallet), Phase 2 (mobile login shell), Phase 3 (serverless tx + confirmations), then hardening and enhancements. Each step can be validated independently (unit tests on API routes, manual testing in TMA, Expo mobile, and web).
244
+