---
title: "Кредитні винагороди"
description: "Винагороди з кредитного балансу на основі конфігурації за внесок subscriber+ — ідемпотентні, з множником ролі та добовим лімітом за UTC"
locale: "uk"
---
# Кредитні винагороди

Ring нараховує одиниці **кредитного балансу** (`credit.creditUnitLabel`, наприклад `points` на ring-platform.org), коли користувач здійснює реальний внесок. Кредити — це утиліта платформи (їх можна витрачати в магазині, на членство та генеративні медіа), а не спекулятивна криптовалюта. Правила отримання детерміновані, обмежені та придатні для аудиту.

## SSOT конфігурації

Шлях запису: `ring-config.json` → `credit.rewards`

```json
{
  "credit": {
    "creditUnitLabel": "points",
    "creditBalanceUnitToMainCurrency": 1,
    "rewards": {
      "minRole": "subscriber",
      "multipliers": { "subscriber": 1, "member": 1.5, "confidential": 2 },
      "dailyEarnCap": { "subscriber": 50, "member": 100, "confidential": 150 },
      "events": {
        "adminVerify": { "amount": "50", "enabled": true, "idempotencyMode": "once_per_user" },
        "commentCreated": { "amount": "2", "idempotencyMode": "once_per_object" }
      }
    }
  }
}
```

Порядок резервного читання (міграція): `credit.rewards.events` → `credit.creditAddEvents` → `credits.rewards.events`.

## Ідемпотентність

| Режим | Ключ | Використання |
|------|-----|-----|
| `once_per_user` | `credit_add_event:{trigger}:{userId}` | Поля профілю, KYC, бонус за завершення |
| `once_per_object` | `…:{objectType}:{objectId}` | Коментарі, відгуки, схвалені новини |

Унікальний індекс на `credit_add_events.idempotency_key` запобігає перегонам.

## Множники ролей і добові ліміти

Фінальна винагорода = `floor(base × multiplier)` (мінімум 1, якщо base ≥ 1). Добовий ліміт — **календарний день UTC**; якщо винагорода перевищила б залишок бюджету, всю винагороду **пропущено** (`skip_reason: daily_cap`) — часткове карбування ніколи не виконується.

Відвідувачі нічого не отримують (`minRole: subscriber`).

## Рушій

`enqueueRewardCreditAddEvent` у `lib/wallet/reward-credit-service.ts`:

1. Завантажити правило → enabled / minRole / username / verified gates  
2. Побудувати ключ ідемпотентності → existing completed → `existing`  
3. Множник + добовий ліміт UTC  
4. `creditBalanceService.addCredits(..., 'reward_credit_add', getFiatCreditAccountingRate())`  
5. Рядок аудиту + `appendEvent('reward_credit_add')`

Помилки ledger → статус `failed` (не `skipped`).

## Підключені дії (Фаза 1)

| Тригер | Коли |
|---------|------|
| Поля профілю / `profileCompleted` | Після переходу `updateProfile` від порожнього до заповненого / досягнення повноти |
| `adminVerify` | Верифікація KYC адміністратором |
| `newsStoryApproved` | Схвалення на головній сторінці **статей, написаних користувачами** |
| `commentCreated` / `reviewCreated` / `requestCreated` | Після створення (один раз для кожного object id) |

`profileCompleted` — це **бонус за завершення** на додачу до винагород за окремі поля.

## Моніторинг адміністратором

- `/admin/rewards` — графіки (добове карбування, за тригером, за роллю, лідери за заробітком)
- Вкладка активності користувачів **Rewards**
- API у `/api/admin/rewards/*`

## Етика

Жодних механік випадковості, сумам із клієнта не довіряємо, правила опубліковано, рейка партнерського токена залишається окремою. Див. lens LegioX `ua_non_speculative_reputation_wealth_designer`.
