@www.hyperlinks.space/program-kit 1.2.181818 → 7.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) 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/.env.example +19 -0
  5. package/.gitattributes +48 -0
  6. package/.gitignore +52 -0
  7. package/.nvmrc +1 -0
  8. package/.vercelignore +6 -0
  9. package/README.md +7 -2
  10. package/ai/openai.ts +202 -0
  11. package/ai/transmitter.ts +367 -0
  12. package/api/{base.ts → _base.ts} +1 -1
  13. package/api/wallet/_auth.ts +143 -0
  14. package/api/wallet/register.ts +151 -0
  15. package/api/wallet/status.ts +89 -0
  16. package/app/index.tsx +319 -5
  17. package/assets/images/PreviewImage.png +0 -0
  18. package/backlogs/medium_term_backlog.md +26 -0
  19. package/backlogs/short_term_backlog.md +42 -0
  20. package/database/start.ts +0 -1
  21. package/database/wallets.ts +266 -0
  22. package/eslint.config.cjs +10 -0
  23. package/fullREADME.md +142 -71
  24. package/index.js +3 -0
  25. package/npmReadMe.md +7 -2
  26. package/npmrc.example +1 -0
  27. package/package.json +7 -27
  28. package/polyfills/buffer.ts +9 -0
  29. package/research & docs/auth-and-centralized-encrypted-keys-plan.md +440 -0
  30. package/research & docs/github-gitlab-bidirectional-mirroring.md +154 -0
  31. package/research & docs/keys-retrieval-console-scripts.js +131 -0
  32. package/{docs/security_plan_raw.md → research & docs/security_plan_raw.md } +1 -1
  33. package/{docs/security_raw.md → research & docs/security_raw.md } +22 -13
  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/{docs/wallets_hosting_architecture.md → research & docs/wallets_hosting_architecture.md } +147 -1
  38. package/scripts/test-api-base.ts +2 -2
  39. package/services/wallet/tonWallet.ts +73 -0
  40. package/telegram/post.ts +44 -8
  41. package/ui/components/GlobalBottomBar.tsx +447 -0
  42. package/ui/components/GlobalBottomBarWeb.tsx +362 -0
  43. package/ui/components/GlobalLogoBar.tsx +108 -0
  44. package/ui/components/GlobalLogoBarFallback.tsx +66 -0
  45. package/ui/components/GlobalLogoBarWithFallback.tsx +24 -0
  46. package/ui/components/HyperlinksSpaceLogo.tsx +29 -0
  47. package/ui/components/Telegram.tsx +677 -0
  48. package/ui/components/telegramWebApp.ts +359 -0
  49. package/ui/fonts.ts +12 -0
  50. package/ui/theme.ts +117 -0
  51. /package/{docs → research & docs}/ai_and_search_bar_input.md +0 -0
  52. /package/{docs → research & docs}/ai_bot_messages.md +0 -0
  53. /package/{docs → research & docs}/blue_bar_tackling.md +0 -0
  54. /package/{docs → research & docs}/bot_async_streaming.md +0 -0
  55. /package/{docs → research & docs}/build_and_install.md +0 -0
  56. /package/{docs → research & docs}/database_messages.md +0 -0
  57. /package/{docs → research & docs}/fonts.md +0 -0
  58. /package/{docs → research & docs}/npm-release.md +0 -0
  59. /package/{docs → research & docs}/releases.md +0 -0
  60. /package/{docs → research & docs}/releases_github_actions.md +0 -0
  61. /package/{docs → research & docs}/scalability.md +0 -0
  62. /package/{docs → research & docs}/timing_raw.md +0 -0
  63. /package/{docs → research & docs}/tma_logo_bar_jump_investigation.md +0 -0
  64. /package/{docs → research & docs}/update.md +0 -0
  65. /package/{docs → research & docs}/wallet_telegram_standalone_multichain_proposal.md +0 -0
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Wallet helpers for the wallets table.
3
+ * Shared by API routes and bot-side services.
4
+ */
5
+ import { sql } from './start.js';
6
+ import { normalizeUsername } from './users.js';
7
+
8
+ export type WalletRow = {
9
+ id: number;
10
+ telegram_username: string;
11
+ wallet_address: string;
12
+ wallet_blockchain: string;
13
+ wallet_net: string;
14
+ type: string;
15
+ label: string | null;
16
+ is_default: boolean;
17
+ source: string | null;
18
+ notes: string | null;
19
+ created_at: string;
20
+ updated_at: string;
21
+ last_used_at: string | null;
22
+ last_seen_balance_at: string | null;
23
+ };
24
+
25
+ export type RegisterWalletInput = {
26
+ telegramUsername: string;
27
+ walletAddress: string;
28
+ walletBlockchain: string;
29
+ walletNet: string;
30
+ type: string;
31
+ label?: string | null;
32
+ source?: string | null;
33
+ notes?: string | null;
34
+ isDefault?: boolean;
35
+ };
36
+
37
+ function normalizeText(raw: unknown): string {
38
+ if (typeof raw !== 'string') return '';
39
+ return raw.trim();
40
+ }
41
+
42
+ function normalizeLower(raw: unknown): string {
43
+ return normalizeText(raw).toLowerCase();
44
+ }
45
+
46
+ function normalizeAddress(raw: unknown): string {
47
+ return normalizeText(raw);
48
+ }
49
+
50
+ export async function listWalletsByUsername(
51
+ telegramUsername: string,
52
+ ): Promise<WalletRow[]> {
53
+ const username = normalizeUsername(telegramUsername);
54
+ if (!username) return [];
55
+
56
+ const rows = await sql<WalletRow[]>`
57
+ SELECT
58
+ id,
59
+ telegram_username,
60
+ wallet_address,
61
+ wallet_blockchain,
62
+ wallet_net,
63
+ type,
64
+ label,
65
+ is_default,
66
+ source,
67
+ notes,
68
+ created_at,
69
+ updated_at,
70
+ last_used_at,
71
+ last_seen_balance_at
72
+ FROM wallets
73
+ WHERE telegram_username = ${username}
74
+ ORDER BY is_default DESC, created_at ASC;
75
+ `;
76
+ return rows;
77
+ }
78
+
79
+ export async function getDefaultWalletByUsername(
80
+ telegramUsername: string,
81
+ ): Promise<WalletRow | null> {
82
+ const username = normalizeUsername(telegramUsername);
83
+ if (!username) return null;
84
+
85
+ const rows = await sql<WalletRow[]>`
86
+ SELECT
87
+ id,
88
+ telegram_username,
89
+ wallet_address,
90
+ wallet_blockchain,
91
+ wallet_net,
92
+ type,
93
+ label,
94
+ is_default,
95
+ source,
96
+ notes,
97
+ created_at,
98
+ updated_at,
99
+ last_used_at,
100
+ last_seen_balance_at
101
+ FROM wallets
102
+ WHERE telegram_username = ${username}
103
+ ORDER BY is_default DESC, created_at ASC
104
+ LIMIT 1;
105
+ `;
106
+
107
+ return rows[0] ?? null;
108
+ }
109
+
110
+ export async function setDefaultWallet(opts: {
111
+ telegramUsername: string;
112
+ walletAddress: string;
113
+ walletBlockchain: string;
114
+ walletNet: string;
115
+ }): Promise<WalletRow | null> {
116
+ const username = normalizeUsername(opts.telegramUsername);
117
+ const walletAddress = normalizeAddress(opts.walletAddress);
118
+ const walletBlockchain = normalizeLower(opts.walletBlockchain);
119
+ const walletNet = normalizeLower(opts.walletNet);
120
+
121
+ if (!username || !walletAddress || !walletBlockchain || !walletNet) {
122
+ return null;
123
+ }
124
+
125
+ await sql`
126
+ UPDATE wallets
127
+ SET is_default = FALSE,
128
+ updated_at = NOW()
129
+ WHERE telegram_username = ${username};
130
+ `;
131
+
132
+ const rows = await sql<WalletRow[]>`
133
+ UPDATE wallets
134
+ SET is_default = TRUE,
135
+ updated_at = NOW()
136
+ WHERE telegram_username = ${username}
137
+ AND wallet_address = ${walletAddress}
138
+ AND wallet_blockchain = ${walletBlockchain}
139
+ AND wallet_net = ${walletNet}
140
+ RETURNING
141
+ id,
142
+ telegram_username,
143
+ wallet_address,
144
+ wallet_blockchain,
145
+ wallet_net,
146
+ type,
147
+ label,
148
+ is_default,
149
+ source,
150
+ notes,
151
+ created_at,
152
+ updated_at,
153
+ last_used_at,
154
+ last_seen_balance_at;
155
+ `;
156
+
157
+ const selected = rows[0] ?? null;
158
+ if (!selected) return null;
159
+
160
+ await sql`
161
+ UPDATE users
162
+ SET default_wallet = ${selected.id},
163
+ updated_at = NOW()
164
+ WHERE telegram_username = ${username};
165
+ `;
166
+
167
+ return selected;
168
+ }
169
+
170
+ export async function registerWallet(
171
+ input: RegisterWalletInput,
172
+ ): Promise<WalletRow | null> {
173
+ const telegramUsername = normalizeUsername(input.telegramUsername);
174
+ const walletAddress = normalizeAddress(input.walletAddress);
175
+ const walletBlockchain = normalizeLower(input.walletBlockchain);
176
+ const walletNet = normalizeLower(input.walletNet);
177
+ const walletType = normalizeLower(input.type);
178
+ const label = normalizeText(input.label ?? '');
179
+ const source = normalizeText(input.source ?? '');
180
+ const notes = normalizeText(input.notes ?? '');
181
+
182
+ if (
183
+ !telegramUsername ||
184
+ !walletAddress ||
185
+ !walletBlockchain ||
186
+ !walletNet ||
187
+ !walletType
188
+ ) {
189
+ return null;
190
+ }
191
+
192
+ const rows = await sql<WalletRow[]>`
193
+ INSERT INTO wallets (
194
+ telegram_username,
195
+ wallet_address,
196
+ wallet_blockchain,
197
+ wallet_net,
198
+ type,
199
+ label,
200
+ source,
201
+ notes,
202
+ is_default,
203
+ created_at,
204
+ updated_at
205
+ )
206
+ VALUES (
207
+ ${telegramUsername},
208
+ ${walletAddress},
209
+ ${walletBlockchain},
210
+ ${walletNet},
211
+ ${walletType},
212
+ ${label || null},
213
+ ${source || null},
214
+ ${notes || null},
215
+ FALSE,
216
+ NOW(),
217
+ NOW()
218
+ )
219
+ ON CONFLICT (telegram_username, wallet_address, wallet_blockchain, wallet_net)
220
+ DO UPDATE SET
221
+ type = EXCLUDED.type,
222
+ label = EXCLUDED.label,
223
+ source = EXCLUDED.source,
224
+ notes = EXCLUDED.notes,
225
+ updated_at = NOW()
226
+ RETURNING
227
+ id,
228
+ telegram_username,
229
+ wallet_address,
230
+ wallet_blockchain,
231
+ wallet_net,
232
+ type,
233
+ label,
234
+ is_default,
235
+ source,
236
+ notes,
237
+ created_at,
238
+ updated_at,
239
+ last_used_at,
240
+ last_seen_balance_at;
241
+ `;
242
+
243
+ const wallet = rows[0] ?? null;
244
+ if (!wallet) return null;
245
+
246
+ if (input.isDefault) {
247
+ return setDefaultWallet({
248
+ telegramUsername,
249
+ walletAddress,
250
+ walletBlockchain,
251
+ walletNet,
252
+ });
253
+ }
254
+
255
+ const currentDefault = await getDefaultWalletByUsername(telegramUsername);
256
+ if (!currentDefault) {
257
+ return setDefaultWallet({
258
+ telegramUsername,
259
+ walletAddress,
260
+ walletBlockchain,
261
+ walletNet,
262
+ });
263
+ }
264
+
265
+ return wallet;
266
+ }
@@ -0,0 +1,10 @@
1
+ // https://docs.expo.dev/guides/using-eslint/
2
+ const { defineConfig } = require('eslint/config');
3
+ const expoConfig = require('eslint-config-expo/flat');
4
+
5
+ module.exports = defineConfig([
6
+ expoConfig,
7
+ {
8
+ ignores: ['dist/*'],
9
+ },
10
+ ]);
package/fullREADME.md CHANGED
@@ -4,23 +4,31 @@
4
4
 
5
5
  <u>**In progress, contribute!**</u>
6
6
 
7
- This program is built upon [React Native](https://reactnative.dev/) by Meta and [Expo](https://expo.dev) multiplatform technologies, Windows build and executable creation achieved with [Electron Builder](https://www.electron.build/) and [Electron Forge](https://www.electronforge.io/), working in Telegram with help of [Telegram Mini Apps React SDK](http://telegram-mini-apps.com/) and [Bot API](https://core.telegram.org/bots). AI is backed by [OpenAI API](https://openai.com/ru-RU/api/), blockchain data is processed from [Swap.Coffee API](https://docs.swap.coffee/eng/user-guides/welcome).
8
-
9
- ## Program Kit
10
-
11
- To give value for other developers we decided to launch an npm package that provides a ready starter for creating a multiplatform program in one command.
12
-
13
- ```bash
14
- npx @www.hyperlinks.space/program-kit ./new-program
15
- ```
16
-
17
- Link to the package: https://www.npmjs.com/package/@www.hyperlinks.space/program-kit
7
+ This program is built upon [React Native](https://reactnative.dev/) by Meta and [Expo](https://expo.dev) multiplatform technologies, Windows build and executable creation achieved with [Electron Builder](https://www.electron.build/) and [Electron Forge](https://www.electronforge.io/), working in Telegram with help of [Telegram Mini Apps React SDK](http://telegram-mini-apps.com/), [Bot API](https://core.telegram.org/bots) and [Grammy](https://grammy.dev/). AI is backed by [OpenAI API](https://openai.com/ru-RU/api/), blockchain info is processed from [Swap.Coffee API](https://docs.swap.coffee/eng/user-guides/welcome). DB for the best user's experience we host on [Neon](https://neon.tech/).
18
8
 
19
9
  ## Program design
20
10
 
21
11
  Access [Figma](https://www.figma.com/design/53lDKAD6pRv3e0uef1DP18/TECHSYMBAL-Inc.?node-id=754-71&t=v3tmAlywNgXkTWMd-1) in real time for contributing. Contact [Seva](t.me/sevaaignatyev) in Telegram to discuss and implement.
22
12
 
23
- Copying fully or partially, usage as an inspiration for other developments are unpleasant, participation in our projects is appreciated. All core materials are available publicly for instant access worldwide and our project availability for newcomers.
13
+ All core materials are available publicly for сгккуте hyperlinks.space team members' instant and easy access worldwide and our project's availability for newcomers' research only.
14
+
15
+ ## Structure
16
+
17
+ - [`app`](./app) - Expo/React Telegram Mini App client (web/mobile screens, navigation, UI logic).
18
+ - [`ui`](./ui) - shared UI layer (components, theme tokens, and font configuration used by the app).
19
+ - [`bot`](./bot) - TypeScript Telegram bot service and runtime entrypoints.
20
+ - [`database`](./database) - database startup/migration/service scripts.
21
+ - [`ai`](./ai) - AI assistant service logic and model integration points.
22
+ - [`api`](./api) - backend API handlers and server-side endpoints.
23
+ - [`blockchain`](./blockchain) - TON/blockchain interaction logic and related helpers.
24
+ - [`telegram`](./telegram) - Telegram-specific integration utilities and adapters.
25
+ - [`windows`](./windows) - Electron desktop shell, NSIS installer config, and auto-update flow.
26
+ - [`scripts`](./scripts) - developer/ops scripts (local run, migration, release helpers).
27
+ - [`docs`](./docs) - project and operational documentation (architecture, releases, security reference, tooling).
28
+ - [`research`](./research) - exploratory notes, investigations, and proposals not yet promoted to `docs/`.
29
+ - [`backlogs`](./backlogs) - short-term planning notes and prioritized work items.
30
+ - [`assets`](./assets) - static assets used by app, installer, and branding.
31
+ - [`dist`](./dist) - generated web build output (export artifacts).
24
32
 
25
33
  ## How to fork and contribute?
26
34
 
@@ -64,15 +72,36 @@ git switch -c new-branch-for-next-update # Create and switch to a new feature br
64
72
 
65
73
  **Move in loops starting from the step 3.**
66
74
 
67
- ## Pull requests and commits requirements
75
+ ## Local deploy
68
76
 
69
- - Give pull requests and commits a proper name and description
70
- - Dedicate each pull request to an understandable area or field, each commit to a focused logical change
71
- - Check file changes in every commit pulled, no arbitrary files modifications should persist such as LF/CRLF line-ending conversion, broken/garbled text diffs, BOM added or removed, accidental "invisible" corruption from text filters
72
- - Add dependecies and packages step by step for security
73
- - An issue creation or following an existing before a pull request would be a good practice
77
+ `npm` package note: `.env.example` is included in the published package so you can use it as a reference for establishing your testing environment with `.env` file.
78
+
79
+ Before local deploy / cloud deploy, prepare these env-backed services:
80
+
81
+ 1. **Neon PostgreSQL (`DATABASE_URL`)**
82
+ - Create an account/project at [Neon](https://neon.tech/).
83
+ - Create a database and copy the connection string.
84
+ - Put it into `.env` as `DATABASE_URL=...`.
85
+ 2. **OpenAI API (`OPENAI_API_KEY`)**
86
+ - Create an account at [OpenAI Platform](https://platform.openai.com/).
87
+ - Create an API key in the API Keys page.
88
+ - Put it into `.env` as `OPENAI_API_KEY=...`.
89
+ 3. **Telegram bot token (`BOT_TOKEN`)**
90
+ - In Telegram, open [@BotFather](https://t.me/BotFather), create a test bot with `/newbot`.
91
+ - Copy the bot token and put it into `.env` as `BOT_TOKEN=...`.
92
+ 4. **Vercel project envs (for comfortable deploy/testing)**
93
+ - Create a [Vercel](https://vercel.com/) account and import this repository as a project.
94
+ - In Project Settings -> Environment Variables, set at least:
95
+ - `DATABASE_URL`
96
+ - `OPENAI_API_KEY`
97
+ - `BOT_TOKEN` (or `TELEGRAM_BOT_TOKEN`)
98
+ - Pull envs locally when needed with `vercel env pull .env.local`.
99
+
100
+ Copy env template locally:
74
101
 
75
- ## Local deploy
102
+ ```bash
103
+ cp .env.example .env
104
+ ```
76
105
 
77
106
  To start the full local stack, run:
78
107
 
@@ -82,67 +111,31 @@ npm run start
82
111
 
83
112
  This runs Expo dev server, the Telegram bot (polling mode), and local Vercel API (`vercel dev`).
84
113
 
114
+ After `npm run start`, you can test the app on real phones with Expo Go:
115
+
116
+ - Install **Expo Go** from Google Play (Android) or App Store (iOS).
117
+ - Make sure your phone and development machine are on the same network.
118
+ - Open Expo Go and scan the QR code shown in the terminal/Expo UI.
119
+ - The app will launch on the device and hot-reload on code changes.
120
+
85
121
  Isolated/local run options:
86
122
 
87
123
  - Expo only (no bot, no Vercel): `npm run start:expo`
88
124
  - Bot only (polling mode): `npm run bot:local`
89
125
  - Vercel API only: `npm run dev:vercel`
90
126
 
91
- ## Milestone snapshot package (npm)
92
-
93
- NPM release and snapshot details were moved to `docs/npm-release.md`.
94
-
95
- ### Local env setup
96
-
97
- 1. **Copy the example file** (from the repository root):
98
- ```bash
99
- cp .env.example .env
100
- ```
101
- 2. **Edit `.env`** and set at least:
102
- - **`BOT_TOKEN`** – if you run the Telegram bot locally (`npm run bot:local`).
103
- 3. **Expo app** – `npx expo start` reads env from the environment; for app-only env vars you can also put them in `.env` and use an Expo-compatible loader if you add one, or set them in the shell before running:
104
- ```bash
105
- export BOT_TOKEN=your_token
106
- npx expo start
107
- ```
108
- 4. **Bot local** – `npm run bot:local` loads `.env` from the project root (optional; you can also set `BOT_TOKEN` in the shell).
109
-
110
- The `.env` file is gitignored; do not commit it.
111
-
112
127
  ## GitHub Actions
113
128
 
114
129
  Current Actions workflows include:
115
130
 
116
- - `Vercel Deploy Test` (`.github/workflows/vercel-deploy-test-envs.yml`) - manual web deploy to Vercel.
117
- - `NPM Package Release` (`.github/workflows/npm-package-release.yml`) - npm/GitHub Packages release workflow.
118
- - `Electron EXE Release` and `Electron Forge EXE Release` - manual Windows release pipelines.
119
- - `EXPO Publish` (`.github/workflows/expo-publish.yml`) - manual OTA publish with EAS CLI.
120
- - `Lint errors check` (`.github/workflows/lint-errors-check.yml`) - manual lint check.
121
-
122
- ## Expo Workflows
123
-
124
- This project uses two automation layers:
125
-
126
- - [EAS Workflows](https://docs.expo.dev/eas/workflows/get-started/) for Expo update/build/deploy flows (triggered via npm scripts from [`package.json`](./package.json)).
127
- - GitHub Actions for CI/CD tasks stored in `.github/workflows` (manual release/deploy jobs and checks).
128
-
129
- ### Previews
131
+ - [`Vercel Deploy Test`](./.github/workflows/vercel-deploy-test-envs.yml) - manual web deploy to Vercel.
132
+ - [`Electron Forge EXE Release`](./.github/workflows/electron-forge-exe-release.yml) - manual Windows release pipeline.
133
+ - [`Electron EXE Release`](./.github/workflows/electron-exe-release.yml) - manual Windows release pipeline.
134
+ - [`Lint errors check`](./.github/workflows/lint-errors-check.yml) - manual lint check.
135
+ - [`EXPO Publish`](./.github/workflows/expo-publish.yml) - manual OTA publish with EAS CLI.
136
+ - [`NPM Package Release`](./.github/workflows/npm-package-release.yml) - npm/GitHub Packages release workflow.
130
137
 
131
- Run `npm run draft` to [publish a preview update](https://docs.expo.dev/eas/workflows/examples/publish-preview-update/) of your project, which can be viewed in Expo Go or in a development build.
132
-
133
- ### Development Builds
134
-
135
- Run `npm run development-builds` to [create a development build](https://docs.expo.dev/eas/workflows/examples/create-development-builds/). Note - you'll need to follow the [Prerequisites](https://docs.expo.dev/eas/workflows/examples/create-development-builds/#prerequisites) to ensure you have the correct emulator setup on your machine.
136
-
137
- ### Production Deployments
138
-
139
- Run `npm run deploy` to [deploy to production](https://docs.expo.dev/eas/workflows/examples/deploy-to-production/). Note - you'll need to follow the [Prerequisites](https://docs.expo.dev/eas/workflows/examples/deploy-to-production/#prerequisites) to ensure you're set up to submit to the Apple and Google stores.
140
-
141
- ## Hosting
142
-
143
- Expo offers hosting for websites and API functions via EAS Hosting. See the [Getting Started](https://docs.expo.dev/eas/hosting/get-started/) guide to learn more.
144
-
145
- ### Deploy web build to Vercel
138
+ ## Deploy to Vercel
146
139
 
147
140
  From the repository root, deploy the static web build to Vercel production:
148
141
 
@@ -152,7 +145,7 @@ vercel --prod
152
145
 
153
146
  Deploying from repository root makes this folder the project root, so `api/bot` is deployed and no Root Directory setting is needed. The project is configured so Vercel runs `npx expo export -p web` and serves the `dist/` output. Link the project first with `vercel` if needed.
154
147
 
155
- ## Telegram bot (Grammy)
148
+ ## Telegram bot
156
149
 
157
150
  The bot is extended beyond a basic "Hello" and "Start program" responder and now supports AI streaming and threads.
158
151
 
@@ -174,6 +167,84 @@ The bot is extended beyond a basic "Hello" and "Start program" responder and now
174
167
  - Run full local stack (Expo + bot + Vercel): `npm run start`
175
168
  - Keep production and local bot tokens separate when possible to avoid webhook/polling conflicts.
176
169
 
177
- ## Where to discuss the project?
170
+ ## Pull requests and commits requirements
171
+
172
+ - Give pull requests and commits a proper name and description
173
+ - Dedicate each pull request to an understandable area or field, each commit to a focused logical change
174
+ - Check file changes in every commit pulled, no arbitrary files modifications should persist such as LF/CRLF line-ending conversion, broken/garbled text diffs, BOM added or removed, accidental "invisible" corruption from text filters
175
+ - Add dependecies and packages step by step for security
176
+ - An issue creation or following an existing before a pull request would be a good practice
177
+
178
+ ## Expo Workflows
179
+
180
+ [EAS Workflows](https://docs.expo.dev/eas/workflows/get-started/) are here for Expo update/build/deploy flows (triggered via npm scripts from [`package.json`](./package.json)).
181
+
182
+ ## Previews
183
+
184
+ Run `npm run draft` to [publish a preview update](https://docs.expo.dev/eas/workflows/examples/publish-preview-update/) of your project, which can be viewed in Expo Go or in a development build.
185
+
186
+ ## Development Builds
187
+
188
+ Run `npm run development-builds` to [create a development build](https://docs.expo.dev/eas/workflows/examples/create-development-builds/). Note - you'll need to follow the [Prerequisites](https://docs.expo.dev/eas/workflows/examples/create-development-builds/#prerequisites) to ensure you have the correct emulator setup on your machine.
189
+
190
+ ## Expo envs setup
191
+
192
+ **Expo app** – `npx expo start` reads env from the environment; for app-only env vars you can also put them in `.env` and use an Expo-compatible loader if you add one, or set them in the shell before running:
193
+ ```bash
194
+ export BOT_TOKEN=your_token
195
+ npx expo start
196
+ ```
197
+
198
+ ## GitLab access
199
+
200
+ GitHub and GitLab repositories are identical. If you want to contribute through GitLab, get access from [@staindart](https://github.com/staindart).
201
+
202
+ If you can push to **both** [GitHub](https://github.com/HyperlinksSpace/HyperlinksSpaceProgram) and [GitLab](https://gitlab.com/hyperlinks.space/HyperlinksSpaceProgram) directly, we ask you to configure Git so pushes keep **both** hosts in sync: the repositories are the same; avoid updating only one side.
203
+
204
+ 1. **Keep `origin` on GitHub for fetch and the first push URL.** If you cloned from GitHub, this is already true: `origin` is where `git pull` / `git fetch origin` get updates. We standardize on GitHub for **incoming** history from `origin` so your local `main` tracks `origin/main` on GitHub.
205
+
206
+ 2. **Register GitLab as a second push URL on `origin`.** Git allows multiple **push** URLs per remote name, but only one **fetch** URL. Adding GitLab here means a single `git push origin <branch>` (or the IDE **Sync** push step) sends the same commits to **both** GitHub and GitLab without a second command.
207
+
208
+ ```bash
209
+ git remote set-url --add --push origin https://gitlab.com/hyperlinks.space/HyperlinksSpaceProgram.git
210
+ ```
211
+
212
+ Run this once per clone; it does not change where you fetch from.
213
+
214
+ 3. **Add a separate remote named `gitlab`.** Because `origin`’s fetch URL stays on GitHub, `git fetch origin` never downloads refs from GitLab. The extra remote lets you run `git fetch gitlab` when you need to compare or merge with the GitLab copy (for example if CI or another contributor updated GitLab only).
215
+
216
+ ```bash
217
+ git remote add gitlab https://gitlab.com/hyperlinks.space/HyperlinksSpaceProgram.git
218
+ ```
219
+
220
+ Note, that GitHub and GitLab URL's are a little different :)
221
+
222
+ If `gitlab` already exists with a wrong URL, use `git remote set-url gitlab https://gitlab.com/hyperlinks.space/HyperlinksSpaceProgram.git` instead.
223
+
224
+ 4. **Verify** with `git remote -v`. You should see GitHub on fetch/push for `origin`, GitLab as the second `origin` push line, and `gitlab` for fetch/push to GitLab:
225
+
226
+ ```text
227
+ gitlab https://gitlab.com/hyperlinks.space/HyperlinksSpaceProgram.git (fetch)
228
+ gitlab https://gitlab.com/hyperlinks.space/HyperlinksSpaceProgram.git (push)
229
+ origin https://github.com/HyperlinksSpace/HyperlinksSpaceProgram.git (fetch)
230
+ origin https://github.com/HyperlinksSpace/HyperlinksSpaceProgram.git (push)
231
+ origin https://gitlab.com/hyperlinks.space/HyperlinksSpaceProgram.git (push)
232
+ ```
233
+
234
+ **GitLab HTTPS access:** GitLab.com does not use **fine-grained** personal access tokens for Git-over-HTTPS (`git push` / `git fetch`). Create a **legacy** personal access token under GitLab → **Edit profile** → **Access tokens** with scopes **`read_repository`** and **`write_repository`**, as described in the official guide: [Personal access tokens](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html). Use your GitLab username and the token as the password when Git prompts. GitHub authentication stays separate (for example `gh auth login` or your existing GitHub credential).
235
+
236
+ ## Program Kit
237
+
238
+ To make it easier for developers to create multiplatform programs with us, we decided to launch an npm package that provides a ready starter for creating such a program basis in one command.
239
+
240
+ ```bash
241
+ npx @www.hyperlinks.space/program-kit ./new-program
242
+ ```
243
+
244
+ Link to the package: https://www.npmjs.com/package/@www.hyperlinks.space/program-kit
245
+
246
+ The **npm registry page** shows a separate package-oriented description: [`npmReadMe.md`](./npmReadMe.md) in the repo root. At publish time the [NPM Package Release](.github/workflows/npm-package-release.yml) workflow copies the main [`README.md`](./README.md) to `fullREADME.md`, then replaces `README.md` with the contents of `npmReadMe.md` so `npm pack` / `npm publish` ship the shorter readme as the package readme (npm always surfaces `README.md` from the tarball). Snapshot channels, tags, and local `npm pack` checks are in [`docs/npm-release.md`](./docs/npm-release.md).
247
+
248
+ ## Project discussions
178
249
 
179
250
  This repository has [GitHub Discussions](https://github.com/HyperlinksSpace/HyperlinksSpaceProgram/discussions) opened, as well you can join our [Telegram Chat](https://t.me/HyperlinksSpaceChat) and [Channel](https://t.me/HyperlinksSpace).
package/index.js ADDED
@@ -0,0 +1,3 @@
1
+ // Earliest bundle entry: polyfill Node `Buffer` before expo-router loads route modules (@ton/* uses it at load time).
2
+ import "./polyfills/buffer";
3
+ import "expo-router/entry";
package/npmReadMe.md CHANGED
@@ -33,12 +33,17 @@ registry and token.
33
33
 
34
34
  ## After Scaffold
35
35
 
36
+ Copy `npmrc.example` to `.npmrc` so installs match this repo (`legacy-peer-deps`; npm does not ship a real `.npmrc` in the tarball for security):
37
+
36
38
  ```bash
37
39
  cd new-program
40
+ cp npmrc.example .npmrc
38
41
  npm install
39
42
  npm run start
40
43
  ```
41
44
 
45
+ If you prefer not to use a `.npmrc`, you can run **`npm install --legacy-peer-deps`** instead of the copy step.
46
+
42
47
  Then open the project **`fullREADME.md`** for details (env vars, bot setup, build
43
48
  and release commands).
44
49
 
@@ -49,5 +54,5 @@ and release commands).
49
54
 
50
55
  ## Notes
51
56
 
52
- - Published directly from the `app/` folder.
53
- - Package tarball is filtered to include only required project files.
57
+ - Published from the repository root; the pack includes everything except patterns in [`.npmignore`](./.npmignore) (no `files` whitelist in `package.json`).
58
+ - `.npmrc` cannot be published on npm; `npmrc.example` is included so you can copy it locally.
package/npmrc.example ADDED
@@ -0,0 +1 @@
1
+ legacy-peer-deps=true
package/package.json CHANGED
@@ -8,39 +8,15 @@
8
8
  "bin": {
9
9
  "program-kit": "scripts/program-kit-init.cjs"
10
10
  },
11
- "files": [
12
- "README.md",
13
- "fullREADME.md",
14
- "npmReadMe.md",
15
- "app",
16
- "api",
17
- "app.json",
18
- "assets",
19
- "blockchain",
20
- "bot",
21
- "database",
22
- "docs",
23
- "!docs/debug.log",
24
- "!docs/issue.md",
25
- "eas.json",
26
- "eslint.config.js",
27
- "global.css",
28
- "package-lock.json",
29
- "scripts",
30
- "telegram",
31
- "tsconfig.json",
32
- "vercel.json",
33
- "windows"
34
- ],
35
11
  "publishConfig": {
36
12
  "access": "public"
37
13
  },
38
14
  "repository": {
39
15
  "type": "git",
40
- "url": "https://github.com/HyperlinksSpace/HyperlinksSpaceBot.git"
16
+ "url": "https://github.com/HyperlinksSpace/HyperlinksSpaceProgram.git"
41
17
  },
42
- "main": "expo-router/entry",
43
- "version": "1.2.181818",
18
+ "main": "index.js",
19
+ "version": "7.8.3",
44
20
  "type": "module",
45
21
  "engines": {
46
22
  "node": ">=18 <=22"
@@ -161,6 +137,10 @@
161
137
  "@react-navigation/native": "^7.1.6",
162
138
  "@swap-coffee/sdk": "^1.5.4",
163
139
  "@tma.js/sdk-react": "^3.0.16",
140
+ "@ton/core": "^0.63.1",
141
+ "@ton/crypto": "^3.3.0",
142
+ "@ton/ton": "^16.2.3",
143
+ "buffer": "^6.0.3",
164
144
  "electron-updater": "^6.8.3",
165
145
  "expo": "~54.0.0",
166
146
  "expo-blur": "~15.0.8",
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Load before any module that touches Node's `Buffer` at evaluation time (e.g. @ton/*).
3
+ * Browsers and Telegram WebView do not define `globalThis.Buffer`.
4
+ */
5
+ import { Buffer } from "buffer";
6
+
7
+ if (typeof globalThis !== "undefined" && !(globalThis as { Buffer?: unknown }).Buffer) {
8
+ (globalThis as { Buffer: typeof Buffer }).Buffer = Buffer;
9
+ }