Разработка системы KYC/AML для криптобиржи

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка системы KYC/AML для криптобиржи
Сложная
~1-2 недели
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1258
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1170
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    873
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1092
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    563
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    830

Разработка системы KYC/AML для криптобиржи

KYC/AML для криптобиржи — это не форма "введите паспорт". Это комплексная система, которая решает regulatory требования лицензии, управляет рисками, и при этом не убивает conversion rate. Большинство бирж теряют 40-60% пользователей на KYC воронке — это проблема архитектуры и UX, не только регуляции.

Tiered KYC структура

Стандарт индустрии — многоуровневая верификация:

Tier 0 (без KYC): только просмотр платформы. Никаких транзакций.

Tier 1 (Email + AML check): до $1,000 USDC эквивалента в месяц. Депозит и вывод только криптовалюты. Автоматический wallet screening через Chainalysis или Elliptic при каждом депозите. Время верификации: < 1 минуты.

Tier 2 (Full KYC): до $50,000/месяц. Паспорт + liveness check. Провайдер: Sumsub, Onfido, Jumio. Время: автоматически 2-5 минут, ручная проверка до 24 часов для сложных случаев. Разблокируется: фиат ввод/вывод, криптовалютный вывод без ограничений.

Tier 3 (Enhanced Due Diligence): без лимитов. Source of Funds + Source of Wealth + расширенный background check. Только для VIP клиентов, ручная обработка compliance офицером.

Архитектура KYC сервиса

// KYC State Machine
enum KYCStatus {
  NOT_STARTED = 'not_started',
  PENDING = 'pending',
  UNDER_REVIEW = 'under_review',
  APPROVED = 'approved',
  REJECTED = 'rejected',
  RESUBMISSION_REQUIRED = 'resubmission_required',
}

interface UserKYCProfile {
  userId: string;
  tier: 0 | 1 | 2 | 3;
  status: KYCStatus;
  applicantId?: string;     // Sumsub applicant ID
  approvedAt?: Date;
  expiresAt?: Date;         // переверификация каждые N лет
  riskScore: number;        // 0-100, рассчитывается при апруве
  pep: boolean;             // Politically Exposed Person
  sanctioned: boolean;
  walletRiskLevels: Map<string, WalletRisk>; // кешированные оценки кошельков
}

class KYCService {
  async initiateKYC(userId: string, targetTier: number): Promise<{ accessToken: string }> {
    const accessToken = await this.sumsubClient.createApplicantToken(
      userId,
      this.getLevelName(targetTier)
    );
    
    await this.db.updateUserKYC(userId, { 
      status: KYCStatus.PENDING,
      initiatedAt: new Date() 
    });
    
    return { accessToken };
  }
  
  async processWebhook(payload: SumsubWebhook): Promise<void> {
    const { applicantId, reviewResult, type } = payload;
    const userId = await this.db.getUserByApplicantId(applicantId);
    
    if (type === 'applicantReviewed' && reviewResult.reviewAnswer === 'GREEN') {
      const riskData = await this.calculateRiskScore(applicantId);
      
      await this.db.updateUserKYC(userId, {
        status: KYCStatus.APPROVED,
        tier: 2,
        approvedAt: new Date(),
        expiresAt: new Date(Date.now() + 2 * 365 * 24 * 60 * 60 * 1000), // 2 года
        riskScore: riskData.score,
        pep: riskData.pep,
      });
      
      await this.notifyUser(userId, 'kyc_approved');
      await this.unlockFeatures(userId, 2);
      
    } else if (reviewResult.reviewAnswer === 'RED') {
      const reason = this.mapRejectionReason(reviewResult.reviewRejectType);
      await this.handleRejection(userId, reason);
    }
  }
  
  private async calculateRiskScore(applicantId: string): Promise<RiskData> {
    const applicantData = await this.sumsubClient.getApplicant(applicantId);
    
    // PEP проверка
    const pepResult = await this.amlProvider.checkPEP(
      applicantData.info.firstName,
      applicantData.info.lastName,
      applicantData.info.dob,
      applicantData.info.country
    );
    
    // Sanctions проверка (OFAC, EU, UN)
    const sanctionsResult = await this.amlProvider.checkSanctions(applicantData.info);
    
    // Risk scoring
    let score = 0;
    if (pepResult.isPEP) score += 40;
    if (sanctionsResult.isSanctioned) score = 100; // автоматический reject
    if (HIGH_RISK_COUNTRIES.includes(applicantData.info.country)) score += 20;
    
    return { score, pep: pepResult.isPEP, sanctioned: sanctionsResult.isSanctioned };
  }
}

On-chain AML скрининг

Каждый входящий депозит и каждый вывод проверяется через wallet screening:

class WalletScreeningService {
  async screenDepositAddress(
    walletAddress: string,
    asset: string,
    amount: number,
    userId: string
  ): Promise<ScreeningResult> {
    
    // Кеш: одинаковый адрес не перепроверяем каждый раз
    const cached = await this.cache.get(`wallet:${walletAddress}`);
    if (cached && cached.age < 3600) return cached.result; // 1 час TTL
    
    const [chainalysisResult, ellipticResult] = await Promise.all([
      this.chainalysis.getAddressRisk(walletAddress, asset),
      this.elliptic.getWalletRisk(walletAddress),
    ]);
    
    const riskScore = Math.max(chainalysisResult.riskScore, ellipticResult.riskScore);
    const categories = [...new Set([
      ...chainalysisResult.categories,
      ...ellipticResult.categories,
    ])];
    
    const result: ScreeningResult = {
      allowed: riskScore < 70 && !this.hasBlockedCategory(categories),
      riskScore,
      categories,
      requiresReview: riskScore >= 40 && riskScore < 70,
    };
    
    await this.cache.set(`wallet:${walletAddress}`, { result, age: Date.now() });
    await this.logScreening(userId, walletAddress, result);
    
    if (!result.allowed) {
      await this.alertComplianceTeam(userId, walletAddress, result);
    }
    
    return result;
  }
  
  private hasBlockedCategory(categories: string[]): boolean {
    const BLOCKED = ['darknet_market', 'ransomware', 'stolen_funds', 'sanctions'];
    return categories.some(c => BLOCKED.includes(c));
  }
}

Transaction Monitoring (TM)

Ongoing мониторинг транзакций для выявления подозрительных паттернов после верификации:

Structuring detection: множество транзакций чуть ниже reporting threshold (классический smurfing).

Velocity monitoring: резкое увеличение активности — 10x от обычного объёма за день.

Round-trip detection: средства выводятся и возвращаются через несколько хопов.

Mixing/tumbling indicators: транзакции через известные mixing сервисы (Tornado Cash и аналоги).

class TransactionMonitor {
  async analyzeTransaction(tx: Transaction): Promise<AlertLevel> {
    const userHistory = await this.db.getUserTxHistory(tx.userId, 30); // 30 дней
    
    const checks = await Promise.all([
      this.checkStructuring(tx, userHistory),
      this.checkVelocity(tx, userHistory),
      this.checkGeographicAnomalies(tx),
      this.checkTimePatterns(tx, userHistory),
    ]);
    
    const maxLevel = Math.max(...checks.map(c => c.level));
    
    if (maxLevel >= AlertLevel.HIGH) {
      await this.createSAR(tx, checks.filter(c => c.level >= AlertLevel.MEDIUM));
    }
    
    return maxLevel;
  }
  
  private async checkStructuring(tx: Transaction, history: Transaction[]): Promise<Check> {
    const threshold = await this.getReportingThreshold(tx.currency);
    
    // Несколько транзакций в течение 24 часов суммарно выше threshold,
    // каждая по отдельности ниже
    const last24h = history.filter(h => 
      Date.now() - h.timestamp < 86400000 && h.amount < threshold
    );
    const total24h = last24h.reduce((sum, h) => sum + h.amount, 0) + tx.amount;
    
    if (total24h >= threshold * 0.9 && last24h.length >= 3) {
      return { level: AlertLevel.HIGH, reason: 'structuring_detected' };
    }
    
    return { level: AlertLevel.NONE };
  }
}

SAR (Suspicious Activity Report) автоматизация

При срабатывании алертов — автоматическое формирование черновика SAR для compliance офицера:

async function generateSARDraft(
  userId: string,
  transactions: Transaction[],
  alerts: Alert[]
): Promise<SARDocument> {
  const user = await getUserKYCData(userId);
  
  return {
    reportType: 'SUSPICIOUS_ACTIVITY',
    filingEntity: COMPANY_DETAILS,
    subject: {
      name: `${user.firstName} ${user.lastName}`,
      address: user.residenceAddress,
      dob: user.dateOfBirth,
      idNumber: user.documentNumber,
    },
    suspiciousActivity: {
      dateRange: { from: transactions[0].date, to: transactions[transactions.length - 1].date },
      totalAmount: transactions.reduce((sum, t) => sum + t.usdValue, 0),
      description: generateNarrative(alerts, transactions),
      alertTypes: alerts.map(a => a.type),
    },
    supportingTransactions: transactions.map(formatForSAR),
  };
}

Технический стек

Компонент Технология
KYC провайдер Sumsub (основной) / Onfido (резерв)
AML on-chain Chainalysis KYT + Elliptic
PEP/Sanctions Refinitiv World-Check или ComplyAdvantage
Transaction monitoring кастомный + Chainalysis Reactor
SAR management кастомный модуль compliance
Backend Node.js + TypeScript + PostgreSQL
Queue BullMQ (Redis) для async обработки

Сроки разработки

Компонент Срок
KYC tier system + Sumsub интеграция 3-4 нед
AML wallet screening 2 нед
Transaction monitoring engine 3-4 нед
SAR management система 2 нед
Compliance dashboard 2-3 нед
Testing + compliance review 2-3 нед

Полная KYC/AML система для биржи: 3-4 месяца разработки.