# `shine_payments`

## Кратко

`shine_payments` — третья программа Solana-модуля SHiNE. Она отвечает за vault входящих средств, DAO-казну, покупку тикетов, менеджерские лимиты, очереди выплат и пошаговое исполнение выплат.

Папка программы: `shine-solana/shine/programs/shine_payments/`.

## Текущие функции

1. `init`
   - Создает основные PDA: `config_pda`, `coef_limit_pda`, `queues_pda`, `inflow_vault_pda`.
   - Записывает `dao_wallet` и стартовые параметры выплат.

2. `update_coef_limit`
   - Обновляет коэффициент выплаты, лимит очереди и награду вызвавшему `step_payout`.
   - Требует подпись DAO-кошелька из `ConfigState`.

3. `grant_manager_limits`
   - DAO выдает менеджеру лимиты на создание тикетов в очередях Q1/Q2.
   - Создает или обновляет `manager_allowance_pda`.

4. `buy_ticket`
   - Покупка тикета с суммой в lamports, пересчетом через Pyth SOL/USD.

5. `buy_ticket_usd`
   - Покупка тикета от USD-центов с защитой по максимальному платежу в lamports.

6. `buy_ticket_sol`
   - Покупка тикета в lamports с проверкой минимального ожидаемого USD-эквивалента.

7. `manager_add_ticket`
   - Менеджер создает тикет за счет выданного ему DAO-лимита.

8. `step_payout`
   - Любой подписант может вызвать шаг выплат.
   - Программа выплачивает следующий тикет, DAO-часть и награду вызывающему.

9. `change_ticket_recipient`
   - Текущий получатель тикета может поменять адрес получателя, если тикет еще не следующий на выплату.

## Аргументы инструкций

`init` аргументов не принимает.

`update_coef_limit`:

- `coef_ppm: u64`
- `limit_usd_cents: u64`
- `call_reward_lamports: u64`

`grant_manager_limits`:

- `manager_wallet: Pubkey`
- `add_q1_usd_cents: u64`
- `add_q2_usd_cents: u64`

`buy_ticket`:

- `amount_lamports: u64`
- `recipient_wallet: Pubkey`

`buy_ticket_usd`:

- `amount_usd_cents: u64`
- `max_pay_lamports: u64`
- `recipient_wallet: Pubkey`

`buy_ticket_sol`:

- `amount_lamports: u64`
- `min_expected_usd_cents: u64`
- `recipient_wallet: Pubkey`

`manager_add_ticket`:

- `queue_id: u8` — только `1` или `2`
- `recipient_wallet: Pubkey`
- `payout_usd_cents: u64`

`change_ticket_recipient`:

- `new_recipient_wallet: Pubkey`

## Главные PDA

1. `config_pda`
   - Seed: `shine_payments_config`.
   - Хранит `dao_wallet` и `inflow_vault`.
   - Размер PDA: `8 + 160` байт.

2. `coef_limit_pda`
   - Seed: `shine_payments_coef_limit`.
   - Хранит коэффициент выплат, лимит и награду `step_payout`.
   - Размер PDA: `8 + 96` байт.

3. `queues_pda`
   - Seed: `shine_payments_queues`.
   - Хранит агрегаты очередей Q1/Q2.
   - Размер PDA: `8 + 192` байт.

4. `inflow_vault_pda`
   - Seed: `shine_payments_inflow_vault`.
   - Принимает деньги от `shine_users`.
   - Из него выполняются выплаты тикетам, DAO и вызывающему `step_payout`.
   - Размер PDA: `8 + 32` байт.

5. `ticket_pda`
   - Seed зависит от очереди и индекса тикета.
   - Отдельная PDA-запись на каждый тикет.
   - Q1 seed: `shine_payments_q1_ticket` + `ticket_index`.
   - Q2 seed: `shine_payments_q2_ticket` + `ticket_index`.
   - Размер PDA: `8 + 160` байт.

6. `manager_allowance_pda`
   - Seed: `shine_p_manager_allow` + адрес менеджера.
   - Хранит доступный лимит менеджера по Q1/Q2.
   - Размер PDA: `8 + 128` байт.

## Текущие параметры

Параметры initial config из `programs/shine_payments/src/settings.rs`:

| Поле | Значение | Смысл |
| --- | --- | --- |
| `START_COEF_PPM` | `5_000_000` | коэффициент 5.0x в ppm-масштабе |
| `START_LIMIT_USD_CENTS` | `1_000_000` | стартовый лимит Q1: 10_000 USD |
| `START_CALL_REWARD_LAMPORTS` | `8_000_000` | награда вызвавшему `step_payout`, 0.008 SOL |
| `MAX_CALL_REWARD_LAMPORTS` | `10_000_000` | максимум награды, 0.01 SOL |
| `ORACLE_MAX_AGE_SECS` | `120` | максимальный возраст цены Pyth |

Для расчетов используется Pyth SOL/USD:

- feed id: `0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d`
- price update account: `7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE`

## Деньги

Входы:

- из `shine_users` в `inflow_vault_pda` при регистрации и увеличении лимита;
- от покупателя тикета сразу в `dao_wallet` при `buy_ticket*`.

Выходы:

- из `inflow_vault_pda` получателю тикета;
- из `inflow_vault_pda` в `dao_wallet`;
- из `inflow_vault_pda` вызвавшему `step_payout`;
- если очереди пустые, весь доступный остаток `inflow_vault_pda` переводится в DAO.

## Очереди и выплаты

Выплаты идут строго пошагово:

- если есть невыплаченные Q1-тикеты, `step_payout` берет следующий Q1;
- если Q1 пустая, берется следующий Q2;
- для Q1 DAO-часть равна сумме тикета в USD;
- для Q2 DAO-часть равна двойной сумме тикета в USD;
- перед выплатой суммы пересчитываются из USD-центов в lamports по Pyth SOL/USD;
- если в `inflow_vault_pda` не хватает средств на тикет, DAO-часть и награду вызвавшему, шаг отклоняется.

`change_ticket_recipient` запрещает менять получателя у тикета, который является следующим на выплату.

## Ключи и управление

На старте удобно считать, что у программы есть отдельный управляющий ключ `key_3`.

Целевая модель:

- `update_coef_limit` вызывает DAO;
- `grant_manager_limits` вызывает DAO;
- upgrade-authority программы после проверки передается DAO;
- `step_payout` остается открытым для любого подписанта, чтобы выплаты не зависели от одного оператора.
