392 lines
12 KiB
Markdown
392 lines
12 KiB
Markdown
# Документ совместимости API для web2-client
|
||
|
||
## Обзор
|
||
|
||
Данный документ описывает спецификацию API эндпоинтов, необходимых для полной совместимости с web2-client. Это критически важно для миграции с Sanic на FastAPI без нарушения функциональности клиента.
|
||
|
||
## Критические эндпоинты для web2-client
|
||
|
||
### 1. Аутентификация через Telegram WebApp
|
||
|
||
#### `POST /api/v1/auth.twa`
|
||
|
||
**Текущая реализация:** [`s_api_v1_auth_twa()`](../app/api/routes/auth.py:16-121)
|
||
|
||
**Запрос:**
|
||
```json
|
||
{
|
||
"twa_data": "string", // Telegram WebApp initData
|
||
"ton_proof": { // Опционально
|
||
"account": {
|
||
"address": "string",
|
||
"chain": "string",
|
||
"publicKey": "string"
|
||
},
|
||
"ton_proof": {
|
||
"timestamp": "number",
|
||
"domain": "string",
|
||
"signature": "string",
|
||
"payload": "string"
|
||
}
|
||
},
|
||
"ref_id": "string" // Опционально
|
||
}
|
||
```
|
||
|
||
**Ответ:**
|
||
```json
|
||
{
|
||
"user": {
|
||
"id": "number",
|
||
"telegram_id": "number",
|
||
"username": "string",
|
||
"meta": {
|
||
"first_name": "string",
|
||
"last_name": "string",
|
||
"photo_url": "string"
|
||
}
|
||
},
|
||
"connected_wallet": {
|
||
"version": "string",
|
||
"address": "string",
|
||
"ton_balance": "string" // nanoTON bignum
|
||
} | null,
|
||
"auth_v1_token": "string"
|
||
}
|
||
```
|
||
|
||
**Критические требования:**
|
||
- Валидация TWA данных через TELEGRAM_API_KEY и CLIENT_TELEGRAM_API_KEY
|
||
- Поддержка TON Proof для кошельков
|
||
- Генерация JWT токена для последующих запросов
|
||
- Сохранение wallet connections в БД
|
||
|
||
#### `POST /api/v1/auth.selectWallet`
|
||
|
||
**Текущая реализация:** [`s_api_v1_auth_select_wallet()`](../app/api/routes/auth.py:142-190)
|
||
|
||
**Запрос:**
|
||
```json
|
||
{
|
||
"wallet_address": "string" // Raw или canonical адрес
|
||
}
|
||
```
|
||
|
||
**Ответ:**
|
||
```http
|
||
HTTP 200 OK
|
||
```
|
||
|
||
**Критические требования:**
|
||
- Конвертация адреса в canonical формат через `Address.to_string(1, 1, 1)`
|
||
- Создание новой WalletConnection записи
|
||
- Проверка существования кошелька у пользователя
|
||
|
||
### 2. Загрузка файлов (Chunked Upload)
|
||
|
||
#### `POST /api/v1/storage`
|
||
|
||
**Текущая реализация:** [`s_api_v1_storage_post()`](../app/api/routes/node_storage.py:31-101)
|
||
|
||
**Особенности web2-client:**
|
||
|
||
**Обычная загрузка (файл <= 80MB):**
|
||
```http
|
||
POST /api/v1/storage
|
||
Content-Type: application/octet-stream
|
||
Authorization: <auth_v1_token>
|
||
X-File-Name: <base64_encoded_filename>
|
||
X-Chunk-Start: 0
|
||
X-Last-Chunk: 1
|
||
|
||
<binary_file_data>
|
||
```
|
||
|
||
**Chunked загрузка (файл > 80MB):**
|
||
```http
|
||
POST /api/v1/storage
|
||
Content-Type: application/octet-stream
|
||
Authorization: <auth_v1_token>
|
||
X-File-Name: <base64_encoded_filename>
|
||
X-Chunk-Start: <byte_offset>
|
||
X-Upload-ID: <upload_id> // Начиная с 2-го чанка
|
||
X-Last-Chunk: 1 // Только для последнего чанка
|
||
|
||
<binary_chunk_data>
|
||
```
|
||
|
||
**Ответ для промежуточных чанков:**
|
||
```json
|
||
{
|
||
"upload_id": "string",
|
||
"current_size": "number"
|
||
}
|
||
```
|
||
|
||
**Ответ для финального чанка:**
|
||
```json
|
||
{
|
||
"content_sha256": "string",
|
||
"content_id": "string", // v2 формат
|
||
"content_id_v1": "string", // v1 формат для совместимости
|
||
"content_url": "string" // dmy://storage?cid=...
|
||
}
|
||
```
|
||
|
||
**Критические требования:**
|
||
- Поддержка заголовков `X-File-Name`, `X-Chunk-Start`, `X-Last-Chunk`, `X-Upload-ID`
|
||
- Декодирование base64 имени файла
|
||
- Chunked upload логика с промежуточным состоянием
|
||
- Генерация SHA256 хэша и CID v1/v2
|
||
- Сохранение в StoredContent с типом "local/content_bin"
|
||
|
||
### 3. Скачивание файлов
|
||
|
||
#### `GET /api/v1/storage/:content_id`
|
||
|
||
**Текущая реализация:** [`s_api_v1_storage_get()`](../app/api/routes/node_storage.py:106-273)
|
||
|
||
**Параметры запроса:**
|
||
- `seconds_limit` (опционально) - ограничение длительности для аудио/видео
|
||
|
||
**Ответ:**
|
||
```http
|
||
Content-Type: <определяется автоматически>
|
||
|
||
<binary_file_data>
|
||
```
|
||
|
||
**Критические требования:**
|
||
- Разрешение CID через `resolve_content()`
|
||
- Конвертация аудио в MP3 с обложкой (через pydub/AudioSegment)
|
||
- Конвертация изображений в JPEG с компрессией до 200KB
|
||
- Конвертация видео в MP4 с ffmpeg (с поддержкой seconds_limit)
|
||
- Потоковая отдача файлов
|
||
|
||
### 4. Создание контента
|
||
|
||
#### `POST /api/v1/blockchain.sendNewContentMessage`
|
||
|
||
**Текущая реализация:** [`s_api_v1_blockchain_send_new_content_message()`](../app/api/routes/_blockchain.py:38-248)
|
||
|
||
**Запрос:**
|
||
```json
|
||
{
|
||
"title": "string",
|
||
"authors": ["string"],
|
||
"content": "string", // CID контента
|
||
"image": "string", // CID обложки
|
||
"description": "string",
|
||
"hashtags": ["string"],
|
||
"price": "string", // nanoTON в строке
|
||
"resaleLicensePrice": "string", // nanoTON (default = 0)
|
||
"allowResale": "boolean",
|
||
"royaltyParams": [{
|
||
"address": "string",
|
||
"value": "number" // 10000 = 100%
|
||
}],
|
||
"downloadable": "boolean" // Опционально
|
||
}
|
||
```
|
||
|
||
**Ответ для бесплатной загрузки (промо):**
|
||
```json
|
||
{
|
||
"address": "free",
|
||
"amount": "30000000", // 0.03 TON в nanoTON
|
||
"payload": ""
|
||
}
|
||
```
|
||
|
||
**Ответ для обычной загрузки:**
|
||
```json
|
||
{
|
||
"address": "string", // Адрес platform
|
||
"amount": "30000000", // 0.03 TON в nanoTON
|
||
"payload": "string" // base64 BOC payload
|
||
}
|
||
```
|
||
|
||
**Критические требования:**
|
||
- Валидация royaltyParams (сумма = 10000)
|
||
- Создание encrypted_content и metadata
|
||
- Проверка PromoAction для бесплатных загрузок
|
||
- Генерация BOC payload для транзакций
|
||
- Интеграция с BlockchainTask
|
||
|
||
### 5. Покупка контента
|
||
|
||
#### `POST /api/v1/blockchain.sendPurchaseContentMessage`
|
||
|
||
**Текущая реализация:** [`s_api_v1_blockchain_send_purchase_content_message()`](../app/api/routes/_blockchain.py:251-295)
|
||
|
||
**Запрос:**
|
||
```json
|
||
{
|
||
"content_address": "string",
|
||
"license_type": "resale" // Только resale поддерживается
|
||
}
|
||
```
|
||
|
||
**Ответ:**
|
||
```json
|
||
{
|
||
"address": "string", // Адрес контракта контента
|
||
"amount": "string", // Цена в nanoTON
|
||
"payload": "string" // base64 BOC payload
|
||
}
|
||
```
|
||
|
||
### 6. Просмотр контента
|
||
|
||
#### `GET /api/v1/content.view/:content_id`
|
||
|
||
**Требуется реализация** - отсутствует в текущем коде
|
||
|
||
**Ожидаемый ответ:**
|
||
```json
|
||
{
|
||
"content": {
|
||
"id": "string",
|
||
"title": "string",
|
||
"authors": ["string"],
|
||
"description": "string",
|
||
"price": "string",
|
||
"metadata": "object"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 7. Декодирование CID
|
||
|
||
#### `GET /api/v1/storage.decodeContentId/:content_id`
|
||
|
||
**Текущая реализация:** [`s_api_v1_storage_decode_cid()`](../app/api/routes/node_storage.py:275-280)
|
||
|
||
**Ответ:**
|
||
```json
|
||
{
|
||
"content_hash": "string",
|
||
"accept_type": "string",
|
||
// ... другие поля CID
|
||
}
|
||
```
|
||
|
||
## Аутентификация и заголовки
|
||
|
||
### Authorization Header
|
||
```http
|
||
Authorization: <auth_v1_token>
|
||
```
|
||
|
||
**Критические требования:**
|
||
- JWT токен из localStorage
|
||
- Middleware проверка токена
|
||
- Установка `request.ctx.user` для авторизованных запросов
|
||
|
||
### Chunked Upload Headers
|
||
```http
|
||
X-File-Name: <base64_encoded_name>
|
||
X-Chunk-Start: <byte_offset>
|
||
X-Upload-ID: <upload_session_id>
|
||
X-Last-Chunk: 1 // Только для последнего чанка
|
||
```
|
||
|
||
## Middleware Requirements
|
||
|
||
### 1. Authentication Middleware
|
||
- Проверка `Authorization` заголовка
|
||
- Валидация JWT токенов
|
||
- Установка `request.ctx.user`
|
||
|
||
### 2. Database Session Middleware
|
||
- Создание `request.ctx.db_session`
|
||
- Автоматический commit/rollback
|
||
|
||
### 3. CORS Middleware
|
||
- Поддержка preflight запросов
|
||
- Разрешение всех необходимых заголовков
|
||
|
||
## Форматы данных
|
||
|
||
### CID (Content Identifier)
|
||
- **v1 формат**: для обратной совместимости
|
||
- **v2 формат**: текущий стандарт
|
||
- **Resolve функция**: `resolve_content()` для преобразования
|
||
|
||
### Wallet Addresses
|
||
- **Raw формат**: принимается в запросах
|
||
- **Canonical формат**: `Address.to_string(1, 1, 1)` для хранения
|
||
|
||
### File Hashes
|
||
- **SHA256**: base58 encoding
|
||
- **Storage path**: `UPLOADS_DIR/sha256_hash`
|
||
|
||
## Критические несовместимости
|
||
|
||
### 1. Missing Endpoints
|
||
- `GET /api/v1/content.view/:content_id` - **ТРЕБУЕТ РЕАЛИЗАЦИИ**
|
||
|
||
### 2. Chunked Upload Protocol
|
||
- Web2-client использует специфичные заголовки
|
||
- Требует поддержки upload_id сессий
|
||
- Необходима обработка `X-Last-Chunk`
|
||
|
||
### 3. File Processing
|
||
- Автоматическая конвертация аудио/видео/изображений
|
||
- Поддержка ffmpeg для видео
|
||
- Генерация preview с обложками
|
||
|
||
### 4. Blockchain Integration
|
||
- TON BOC payload генерация
|
||
- PromoAction логика для бесплатных загрузок
|
||
- BlockchainTask для отслеживания транзакций
|
||
|
||
## Рекомендации для FastAPI миграции
|
||
|
||
### 1. Точное сохранение API
|
||
```python
|
||
@app.post("/api/v1/auth.twa")
|
||
async def auth_twa(request: TelegramAuthRequest):
|
||
# Точная реплика логики s_api_v1_auth_twa()
|
||
```
|
||
|
||
### 2. Middleware Stack
|
||
```python
|
||
app.add_middleware(CORSMiddleware)
|
||
app.add_middleware(AuthenticationMiddleware)
|
||
app.add_middleware(DatabaseSessionMiddleware)
|
||
```
|
||
|
||
### 3. File Handling
|
||
```python
|
||
from fastapi import UploadFile, Header
|
||
from typing import Optional
|
||
|
||
@app.post("/api/v1/storage")
|
||
async def upload_file(
|
||
file: bytes = Body(...),
|
||
x_file_name: str = Header(..., alias="X-File-Name"),
|
||
x_chunk_start: int = Header(0, alias="X-Chunk-Start"),
|
||
x_upload_id: Optional[str] = Header(None, alias="X-Upload-ID"),
|
||
x_last_chunk: Optional[int] = Header(None, alias="X-Last-Chunk")
|
||
):
|
||
# Chunked upload логика
|
||
```
|
||
|
||
### 4. Response Formats
|
||
- Точное сохранение JSON структур
|
||
- Обработка ошибок в том же формате
|
||
- HTTP статус коды как в Sanic версии
|
||
|
||
## Заключение
|
||
|
||
Для обеспечения 100% совместимости с web2-client необходимо:
|
||
|
||
1. **Сохранить все форматы запросов/ответов**
|
||
2. **Реализовать недостающие эндпоинты**
|
||
3. **Точно скопировать chunked upload протокол**
|
||
4. **Поддержать все middleware требования**
|
||
5. **Сохранить обработку файлов и конвертацию**
|
||
|
||
**КРИТИЧЕСКИ ВАЖНО**: Любое изменение в API может сломать web2-client, поэтому миграция должна быть byte-perfect совместимой. |