---
title: "WalletConductor"
description: "SSOT-фасад для custodial native-token кошельков, fiat credit ledger, Token Desk, пополнения картой, confidential native onramp и покупок на NFT market. Денежный аналог PaymentConductor"
locale: "ru"
---
# WalletConductor

**WalletConductor** — оркестрационный фасад Ring Platform для денежных путей **custodial native-token web3** и **fiat credit**. Тонкие адаптеры (`app/_actions/wallet.ts`, `/api/wallet/token/*`, `/api/wallet/desk/*`, покупка на NFT market) вызывают conductor; он делегирует PSP в [PaymentConductor](/docs/features/payment-conductor.md), а математику ledger в `creditBalanceService`.

> **Info**
> Используйте вкладки **Основатель** / **Разработчик** в боковой панели документации для фильтрации этой страницы. UI продукта для участников: [Wallet](/docs/features/wallet.md). Инвентарь HTTP/actions: [Wallet API](/docs/api/wallet.md).

Один слой для денег кошелька: карта → **credit points**, desk → **native token**, gasless custodial переводы, ad-hoc списание кредитов и покупки на NFT market. Учёт fiat-списаний использует `credit.creditBalanceUnitToMainCurrency` (обычно `1`), никогда не desk oracle. Внешний EVM POL/USDT через `POST /api/wallet/transfer` остаётся **вне** этого conductor.

```mermaid
flowchart TB
  subgraph surfaces["Surfaces"]
    SA["Server Actions\napp/_actions/wallet.ts"]
    API["HTTP /api/wallet/*"]
    NFT["NFT market buy"]
    OAuth["OAuth / ensure"]
  end

  subgraph WC["WalletConductor"]
    TOP["initiateTopUp"]
    ONR["initiateNativeOnramp"]
    DESK["quoteDesk / executeDesk"]
    SEND["transferNative"]
    SPEND["spendCredits"]
    ENS["ensureNativeWallet"]
    NFTB["purchaseNftListing"]
  end

  subgraph deps["Dependencies"]
    PC["PaymentConductor\nwallet_topup / native_token_onramp"]
    CBS["creditBalanceService"]
    DS["desk-service + native-token-oracle"]
    XFER["native-token-transfer-service"]
    EW["ensure-wallet"]
    SOL["SolanaMarketClient"]
  end

  SA --> WC
  API --> WC
  NFT --> NFTB
  OAuth --> ENS
  TOP --> PC
  ONR --> PC
  DESK --> DS
  SPEND --> CBS
  SEND --> XFER
  ENS --> EW
  NFTB --> SOL
  DS --> CBS
```

## Чем владеет WalletConductor

| Возможность | Метод | Результат |
|------------|--------|--------|
| **Карта → credit points** | `initiateTopUp` | PaymentConductor `wallet_topup` → начисление в fiat ledger |
| **Карта/PayPal → treasury native** | `initiateNativeOnramp` | PaymentConductor `native_token_onramp` (confidential+) |
| **Token Desk** | `quoteDesk` / `executeDesk` | Credit points ↔ native по desk oracle (subscriber+) |
| **Custodial перевод** | `transferNative` | Gasless native перевод + строка `wallet_transactions` |
| **Native баланс** | `getNativeBalance` | Custodial баланс в native chain платформы |
| **Ad-hoc списание кредитов** | `spendCredits` | Списание из fiat ledger по `creditBalanceUnitToMainCurrency` |
| **Выдача кошелька** | `ensureNativeWallet` | Атомарные multi-chain кошельки (OAuth-safe, без сессии) |
| **Гейт минимального кредита** | `ensureFunded` | Выдача с проверкой сессии + минимальный порог кредита |
| **Покупка на NFT market** | `purchaseNftListing` | Идемпотентная покупка за RING через Solana market client |

**Не в WalletConductor:** списание при **checkout** store/membership (PaymentConductor `credit_balance` / SubscriptionConductor) и внешний EVM `POST /api/wallet/transfer`. Это намеренно отдельные SSOT-пути.

## Два курса: не смешивать

| Курс | SSOT | Где используется |
|------|------|---------|
| **Учёт fiat credit** | `ring-config.json` → `credit.creditBalanceUnitToMainCurrency` (обычно `1`) через `getMainCurrencyCreditAccountingRate()` | `spendCredits`, сторона списания desk, checkout `credit_balance` |
| **Token Desk oracle** | `platform_settings.web3.oracle.nativePerMainCurrency` через `native-token-oracle.ts` | Только `quoteDesk` / `executeDesk` points ↔ native |

### For founders

## Почему это важно для вашего клона

WalletConductor: денежный хребет для оператора за продуктом [Wallet](/docs/features/wallet.md). Участники видят UI пополнения, desk и переводов; ваш клон остаётся согласованным, потому что каждый путь идёт через один фасад, а не через разрозненные вызовы PSP и ledger.

  
- **[Пополнение кредита](/docs/features/wallet.md)** — Любой авторизованный участник покупает credit points картой. Points: единицы fiat ledger (1:1 с `mainCurrency` магазина, когда `creditBalanceUnitToMainCurrency` равен `1`).

  
- **[Token Desk](/docs/features/wallet.md)** — Subscriber+ конвертирует points ↔ native по desk oracle. Изменение `nativePerMainCurrency` никогда не меняет математику store или ad-hoc списания кредитов.

  
- **[Native onramp](/docs/features/payment-conductor.md)** — Confidential+ карта/PayPal → treasury native (за feature-флагом). **Не** начисляет credit points.

  
- **[Покупка на NFT market](/docs/features/nft-market.md)** — Подходящие покупатели платят RING из custodial кошелька через `purchaseNftListing` (идемпотентная строка продажи).

### Чеклист оператора

**Подтвердите SSOT единицы кредита**

Оставьте `credit.creditBalanceUnitToMainCurrency: 1` в `ring-config.json`, если вы намеренно не масштабируете points относительно fiat. Изменения desk oracle никогда не влияют на checkout магазина или `POST /api/wallet/credit/spend`.

**Отделите desk oracle от fiat**

Superadmin задаёт `nativePerMainCurrency` только для конвертации на desk. Не ожидайте этот курс при ad-hoc списании кредитов.

**Осторожно включайте native onramp**

Native onramp картой доступен для confidential+ и стоит за feature-флагом (`CONFIDENTIAL_TOKEN_ONRAMP` / desk `nativeTokenOnramp`). Держите его выключенным, пока не готовы treasury ops и compliance.

> **Tip**
> Из UI предпочитайте Server Actions. HTTP-маршруты кошелька оставьте для MCP и не-React клиентов. Предпочитайте `/api/wallet/token/*`: устаревшие алиасы `/api/wallet/ring/*` удалены.

### For developers

## Реализация

Фасад: `features/wallet/conductor/wallet-conductor.ts` (`server-only`).

{`import { WalletConductor } from '@/features/wallet/conductor/wallet-conductor'

// OAuth / events — no session required
const ensured = await WalletConductor.ensureNativeWallet({ id: userId, role })

// Card → credit points (amount 25–2000)
const topUp = await WalletConductor.initiateTopUp(null, formData)

// Ad-hoc fiat debit — rate defaults to creditBalanceUnitToMainCurrency
const spent = await WalletConductor.spendCredits({
  userId,
  amount: '10.00',
  description: 'API debit',
})

// Desk (subscriber+)
const quote = await WalletConductor.quoteDesk({ userId, role, side: 'buy', amount: '100' })
await WalletConductor.executeDesk({ userId, role, idempotencyKey, quoteToken })`}

### Подключение поверхности

**Вызывайте фасад, а не ledger**

UI и маршруты должны импортировать `WalletConductor` (или тонкие обёртки в `app/_actions/wallet.ts`). Не списывайте через `creditBalanceService` из UI фич для путей, которыми владеет conductor.

**Держите SSOT fiat-курса**

Для путей списания не передавайте `usdRate` или передавайте `getMainCurrencyCreditAccountingRate()`. Никогда не подавайте `nativePerMainCurrency` / desk oracle в списания fiat ledger.

**Соблюдайте границу EVM**

Custodial native перевод: `transferNative`. Внешний SupportedCrypto (POL/USDT) остаётся на `POST /api/wallet/transfer`; не встраивайте его в WalletConductor без явного редизайна.

### Карта модулей

| Слой | Путь |
|-------|------|
| Фасад | `features/wallet/conductor/wallet-conductor.ts` |
| Выдача | `features/wallet/services/ensure-wallet.ts` |
| Credit ledger | `features/wallet/services/credit-balance-service.ts` |
| Fiat-курс | `lib/ring-config-core.ts` → `getCreditUnitToMainCurrencyRate` / `lib/payments/credit-balance.ts` → `getMainCurrencyCreditAccountingRate` |
| Desk | `features/wallet/chains/solana/desk-service.ts` |
| Desk oracle | `features/wallet/services/native-token-oracle.ts` |
| Custodial перевод | `features/wallet/chains/native-token-transfer-service.ts` |
| PSP checkout | `lib/payments/conductor/payment-conductor.ts` |
| Store credit rail | `lib/payments/processors/credit-balance.processor.ts` (PaymentConductor, не WC) |
| Actions | `app/_actions/wallet.ts` |
| Покупка NFT | `features/nft-market/services/solana-market-client.ts` |

### Контракты методов

| Метод | Auth / гейты | Примечания |
|--------|--------------|-------|
| `ensureNativeWallet` | Вызывающий передаёт `id` | OAuth-safe; возвращает `{ ok, native, wallets }` |
| `ensureFunded` | Сессия | Выдача + опциональный минимум кредита |
| `initiateTopUp` | Сессия | Сумма 25–2000; purpose `wallet_topup` |
| `initiateNativeOnramp` | Сессия + confidential metadata | Опциональный `processor` paypal/stripe/wayforpay |
| `quoteDesk` / `executeDesk` | `assertTokenDeskSubscriberAccess` | Solana desk SSOT |
| `transferNative` | Вызывающий передаёт `userId` | Пишет `wallet_transactions`; обновляет контакты |
| `spendCredits` | Вызывающий передаёт `userId` | По умолчанию `usdRate` = `getMainCurrencyCreditAccountingRate()` |
| `purchaseNftListing` | Ключ идемпотентности | Статус: pending → submitted → confirmed / failed |
| `getNativeBalance` | Вызывающий передаёт `userId` | Тонкая обёртка над transfer service |

### Последовательность: пополнение кредита картой

```mermaid
sequenceDiagram
  participant UI as CreditAddFsModal
  participant WC as WalletConductor
  participant PC as PaymentConductor
  participant PSP as WayForPay_or_Stripe_or_PayPal
  participant WH as wallet_topup_webhook
  participant CBS as creditBalanceService
  UI->>WC: initiateTopUp formData
  WC->>PC: createCheckout purpose=wallet_topup
  PC-->>UI: redirect navigate_or_form_post
  UI->>PSP: followCheckoutResult
  Note over UI,PSP: returnUrl browser UX only
  PSP->>WH: webhook Approved_or_capture
  WH->>CBS: addFiatUsd fiat points
```

Вкладка Card не передаёт `processor` (SSOT в env). Вкладка PayPal задаёт `processor=paypal`. Клиент: `lib/payments/checkout-redirect.ts`.

### Последовательность: ad-hoc списание кредитов

```mermaid
sequenceDiagram
  participant API as POST /api/wallet/credit/spend
  participant WC as WalletConductor.spendCredits
  participant RATE as getMainCurrencyCreditAccountingRate
  participant CBS as creditBalanceService
  API->>WC: amount, description
  WC->>RATE: creditBalanceUnitToMainCurrency
  WC->>CBS: spendCredits(..., usdRate)
  CBS-->>API: newBalance, transactionId
```

### Окружение и конфигурация (проверено)

| Ключ | Роль |
|-----|------|
| `WALLET_ENCRYPTION_KEY` | Шифрование custodial ключей |
| `SOLANA_RPC_URL` / `SOLANA_TREASURY_PRIVATE_KEY` | Custodial Solana + спонсирование gas |
| `CONFIDENTIAL_TOKEN_ONRAMP` / desk `nativeTokenOnramp` | Гейт native onramp картой |
| `credit.creditBalanceUnitToMainCurrency` | Множитель учёта fiat ledger |
| `ORACLE_QUOTE_SECRET` / `RING_ORACLE_DEFAULT_RATE` | HMAC котировки desk + fallback |

## Связанная документация

  
- **[Generative Gallery](/docs/features/generative-media.md)** — Credit-first биллинг генерации через `spendCredits` + ledger `generative_usage`.

  
- **[Архитектура WalletConductor](/docs/architecture/wallet-conductor.md)** — Адаптеры, карта маршрутов, последовательности, SSOT env.

  
- **[Фича Wallet](/docs/features/wallet.md)** — Архитектура продукта и сценарии участников.

  
- **[Wallet API](/docs/api/wallet.md)** — Actions, HTTP-маршруты, таблицы SSOT курсов.

  
- **[PaymentConductor](/docs/features/payment-conductor.md)** — PSP rails для пополнения и onramp.
