Разработка системы лимитов и верификации обменника

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка системы лимитов и верификации обменника
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • 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

Разработка системы лимитов и верификации обменника

Система лимитов — не просто цифры в базе данных. Это compliance инструмент, который балансирует между usability (пользователь хочет обменять сразу) и regulatory требованиями (AML требует знать клиента при суммах выше threshold). Правильная архитектура лимитов снижает KYC abandonment и остаётся compliant.

Структура лимитов по уровням верификации

interface LimitTier {
  daily: number;      // USD эквивалент
  monthly: number;
  perTransaction: number;
  fiatsAllowed: boolean;
  cryptoWithdrawalLimit: number;
  requiresKYC: KYCLevel;
}

const LIMIT_TIERS: Record<string, LimitTier> = {
  ANONYMOUS: {
    daily: 500,
    monthly: 1000,
    perTransaction: 500,
    fiatsAllowed: false,
    cryptoWithdrawalLimit: 500,
    requiresKYC: KYCLevel.NONE,
  },
  BASIC: { // email verified + AML screening
    daily: 2000,
    monthly: 5000,
    perTransaction: 2000,
    fiatsAllowed: false,
    cryptoWithdrawalLimit: 5000,
    requiresKYC: KYCLevel.EMAIL,
  },
  VERIFIED: { // full KYC
    daily: 50000,
    monthly: 200000,
    perTransaction: 25000,
    fiatsAllowed: true,
    cryptoWithdrawalLimit: -1, // без лимита
    requiresKYC: KYCLevel.FULL,
  },
};

Rolling window лимиты

Фиксированные дневные окна (00:00-23:59) создают bad UX: пользователь не может обменять в 23:50 то что планировал, потому что лимит обнулится через 10 минут. Rolling window лучше:

class LimitChecker {
  async checkAndConsumeLimits(
    userId: string,
    amount: number,
    currency: string
  ): Promise<LimitCheckResult> {
    const tier = await this.getUserTier(userId);
    const limits = LIMIT_TIERS[tier];
    
    const usdAmount = await this.toUSD(amount, currency);
    
    // Single transaction check
    if (usdAmount > limits.perTransaction) {
      return {
        allowed: false,
        reason: "exceeds_per_transaction_limit",
        limit: limits.perTransaction,
        upgradeRequired: tier !== "VERIFIED",
      };
    }
    
    // Rolling 24h window
    const usage24h = await this.getUsage(userId, 24 * 60 * 60 * 1000);
    if (usage24h + usdAmount > limits.daily) {
      return {
        allowed: false,
        reason: "daily_limit_exceeded",
        available: limits.daily - usage24h,
        resetsIn: await this.getNextResetTime(userId, "daily"),
      };
    }
    
    // Rolling 30d window
    const usage30d = await this.getUsage(userId, 30 * 24 * 60 * 60 * 1000);
    if (usage30d + usdAmount > limits.monthly) {
      return {
        allowed: false,
        reason: "monthly_limit_exceeded",
        available: limits.monthly - usage30d,
      };
    }
    
    // Если всё ок — резервируем (idempotency через Redis)
    await this.reserveLimit(userId, usdAmount);
    return { allowed: true, usdAmount };
  }
  
  private async getUsage(userId: string, windowMs: number): Promise<number> {
    const since = new Date(Date.now() - windowMs);
    return this.db.sumTransactions(userId, since);
  }
}

AML пороговые суммы и автоматические проверки

const AML_THRESHOLDS = {
  ENHANCED_SCREENING: 1000,    // USD — дополнительный AML скрининг
  KYC_REQUIRED: 1000,          // требуется базовый KYC
  FULL_KYC_REQUIRED: 3000,     // требуется полный KYC
  SAR_REVIEW: 10000,           // ручная review compliance офицером
  CTR_REPORT: 10000,           // Currency Transaction Report (в некоторых юрисдикциях)
};

async function preTransactionChecks(tx: ExchangeTransaction): Promise<CheckResult> {
  // Автоматическое повышение требований при достижении порогов
  if (tx.usdAmount >= AML_THRESHOLDS.FULL_KYC_REQUIRED) {
    const kycStatus = await getKYCStatus(tx.userId);
    if (kycStatus < KYCLevel.FULL) {
      return {
        action: "REQUIRE_KYC",
        requiredLevel: KYCLevel.FULL,
        message: "Для суммы свыше $3,000 требуется верификация",
      };
    }
  }
  
  // Скрининг при суммах выше $1,000
  if (tx.usdAmount >= AML_THRESHOLDS.ENHANCED_SCREENING) {
    const screenResult = await screenWallet(tx.destinationAddress, tx.asset);
    if (screenResult.blocked) {
      return { action: "BLOCK", reason: screenResult.reason };
    }
  }
  
  return { action: "ALLOW" };
}

Верификация по источнику средств

Для сумм выше enhanced due diligence threshold — форма Source of Funds:

interface SourceOfFunds {
  source: "employment" | "business" | "investments" | "inheritance" | "other";
  description: string;
  estimatedMonthlyVolume: number;
  supportingDocuments: string[]; // IPFS hashes или S3 URLs
}

async function collectSourceOfFunds(userId: string, amount: number): Promise<boolean> {
  if (amount < SOF_THRESHOLD) return true;
  
  const existingSOF = await db.getSourceOfFunds(userId);
  
  // SOF valid если заполнен и не истёк (пересбор раз в год)
  if (existingSOF && !isExpired(existingSOF, 365)) return true;
  
  // Запрашиваем SOF через UI
  await triggerSOFCollection(userId, { requiredFor: "transaction", amount });
  return false;
}

Система лимитов с rolling windows, AML порогами и SOF collection — 2-3 недели разработки.