Розробка instant-exchange сервісу

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка instant-exchange сервісу
Середній
~1-2 тижні
Часті запитання

Напрямки блокчейн-розробки

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1285
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1198
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    902
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1122
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    589
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    859

Розробка KYC/AML для крипто-обменника

KYC (Know Your Customer) та AML (Anti-Money Laundering) — регуляторні вимоги, які стають обов'язковими для крипто-обменників у більшості юрисдикцій. FATF (Financial Action Task Force) та ЄС вимагають верифікацію для транзакцій вище певних порогів. Без KYC/AML обменник ризикує блокування платіжних провайдерів та юридичні проблеми.

Архітектура KYC/AML системи

Рівні верифікації (KYC Tiers)

type KYCTier int

const (
    TierUnverified  KYCTier = 0  // без верифікації
    TierBasic       KYCTier = 1  // email + телефон
    TierStandard    KYCTier = 2  // ID документ + selfie
    TierEnhanced    KYCTier = 3  // + джерело коштів
)

type TierLimits struct {
    DailyLimitUSD   decimal.Decimal
    TxLimitUSD      decimal.Decimal
    RequiredKYC     KYCTier
}

var DefaultLimits = map[KYCTier]TierLimits{
    TierUnverified: {DailyLimitUSD: decimal.New(1000, 0),  TxLimitUSD: decimal.New(500, 0)},
    TierBasic:      {DailyLimitUSD: decimal.New(3000, 0),  TxLimitUSD: decimal.New(1500, 0)},
    TierStandard:   {DailyLimitUSD: decimal.New(15000, 0), TxLimitUSD: decimal.New(5000, 0)},
    TierEnhanced:   {DailyLimitUSD: decimal.New(100000, 0), TxLimitUSD: decimal.New(50000, 0)},
}

Інтеграція з KYC провайдерами

Розроблювати OCR документів та liveness detection самостійно — нецілісійне. Використовуємо KYC-as-a-Service:

Sumsub — популярний вибір для крипто. Перевірка документів 80+ країн, liveness detection, база даних Watchlist:

import axios from 'axios';
import crypto from 'crypto';

class SumsubKYC {
  private appToken: string;
  private secretKey: string;
  
  private signRequest(method: string, url: string, body?: string): string {
    const ts = Math.floor(Date.now() / 1000).toString();
    const payload = ts + method.toUpperCase() + url + (body || '');
    const hmac = crypto.createHmac('sha256', this.secretKey).update(payload).digest('hex');
    return `${ts}:${hmac}`;
  }
  
  async createApplicant(externalUserId: string, levelName: string = 'basic-kyc-level') {
    const url = '/resources/applicants';
    const body = JSON.stringify({ externalUserId, levelName });
    
    const response = await axios.post(`https://api.sumsub.com${url}`, body, {
      headers: {
        'X-App-Token': this.appToken,
        'X-App-Access-Sig': this.signRequest('POST', url, body),
        'Content-Type': 'application/json',
      },
    });
    
    return response.data;  // applicantId
  }
  
  async generateAccessToken(applicantId: string): Promise<string> {
    const url = `/resources/accessTokens?userId=${applicantId}`;
    const response = await axios.post(`https://api.sumsub.com${url}`, '', {
      headers: {
        'X-App-Token': this.appToken,
        'X-App-Access-Sig': this.signRequest('POST', url),
      },
    });
    return response.data.token;
  }
  
  // Webhook від Sumsub при зміні статусу верифікації
  async handleWebhook(payload: SumsubWebhook) {
    const { applicantId, reviewResult } = payload;
    
    switch (reviewResult.reviewAnswer) {
      case 'GREEN':  // верифіковано
        await this.updateUserKYCStatus(applicantId, 'verified');
        break;
      case 'RED':    // відхилено
        const reasons = reviewResult.rejectLabels;
        await this.updateUserKYCStatus(applicantId, 'rejected', reasons);
        break;
    }
  }
}

Frontend інтеграція — Sumsub WebSDK вбудовується в сторінку верифікації:

// React компонент верифікації
import SumsubWebSdk from '@sumsub/websdk-react';

function KYCVerification({ userId }: { userId: string }) {
  const [accessToken, setAccessToken] = useState<string | null>(null);
  
  useEffect(() => {
    api.getKYCToken(userId).then(setAccessToken);
  }, [userId]);
  
  if (!accessToken) return <Loading />;
  
  return (
    <SumsubWebSdk
      accessToken={accessToken}
      expirationHandler={() => api.getKYCToken(userId)}
      onMessage={(type, payload) => {
        if (type === 'idCheck.applicantReviewComplete') {
          router.push('/kyc/pending');
        }
      }}
      onError={(error) => console.error('KYC error:', error)}
    />
  );
}

AML: мониторинг транзакцій

Blockchain аналітика

Для крипто-транзакцій потрібно перевіряти походження коштів. Відправка з міксера, darknet marketplace або санкціонованої адреси — червоний прапорець.

Провайдери blockchain analytics:

class ChainAnalysisAML {
  async checkAddress(address: string, currency: string): Promise<RiskScore> {
    const response = await this.client.post('/v2/users', {
      userId: `check-${Date.now()}`,
      currency,
      address,
    });
    
    return {
      risk: response.data.risk,          // "low" | "medium" | "high" | "severe"
      riskScore: response.data.riskScore, // 0-10
      exposures: response.data.exposures, // [{category, value}]
      flags: response.data.flags,         // конкретні причини ризику
    };
  }
}

// Приклад інтеграції у процес обміну
async function checkIncomingDeposit(txHash: string, fromAddress: string, currency: string) {
  const riskScore = await chainAnalysis.checkAddress(fromAddress, currency);
  
  if (riskScore.risk === 'severe') {
    await freezeTransaction(txHash, 'HIGH_RISK_ADDRESS');
    await notifyCompliance(txHash, riskScore);
    return false;
  }
  
  if (riskScore.risk === 'high') {
    await flagForReview(txHash, riskScore);
    // Продовжуємо, але помічаємо для ручної перевірки
  }
  
  return true;
}

Elliptic та TRM Labs — альтернативи Chainalysis, з різним охопленням та ціновою політикою.

Правила AML

type AMLRule struct {
    Name      string
    Check     func(tx Transaction, user User) AMLResult
    Action    AMLAction  // ALLOW, FLAG, BLOCK
}

var AMLRules = []AMLRule{
    {
        Name: "structuring_detection",
        Check: func(tx Transaction, user User) AMLResult {
            // Підозрюємо: кілька транзакцій чуть нижче порога KYC
            recentTxs := db.GetUserTransactions(user.ID, 24*time.Hour)
            totalValue := sum(recentTxs)
            
            // Кілька транзакцій ~$990 поспіль — спроба обійти KYC лімит
            if len(recentTxs) > 3 && totalValue > KYCThreshold*0.8 {
                return AMLResult{Risk: "high", Reason: "potential_structuring"}
            }
            return AMLResult{Risk: "low"}
        },
        Action: FLAG,
    },
    {
        Name: "high_risk_country",
        Check: func(tx Transaction, user User) AMLResult {
            highRiskCountries := []string{"KP", "IR", "SY", "CU"}
            if contains(highRiskCountries, user.Country) {
                return AMLResult{Risk: "severe", Reason: "sanctioned_jurisdiction"}
            }
            return AMLResult{Risk: "low"}
        },
        Action: BLOCK,
    },
    {
        Name: "pep_screening",
        Check: func(tx Transaction, user User) AMLResult {
            // PEP = Politically Exposed Person
            isPEP := pepDatabase.CheckName(user.FullName, user.DateOfBirth)
            if isPEP {
                return AMLResult{Risk: "medium", Reason: "pep_detected"}
            }
            return AMLResult{Risk: "low"}
        },
        Action: FLAG,
    },
}

Watchlist screening

Перевірка за санкціонними списками (OFAC SDN, EU Consolidated List, UN Sanctions):

type WatchlistScreener struct {
    ofacList   []SanctionEntry
    euList     []SanctionEntry
    updateFreq time.Duration
}

func (ws *WatchlistScreener) ScreenName(name, dob string) []SanctionMatch {
    // Fuzzy matching — імена можуть бути транслітеровані по-різному
    var matches []SanctionMatch
    
    for _, entry := range append(ws.ofacList, ws.euList...) {
        similarity := fuzzy.MatchScore(name, entry.Name)
        if similarity > 0.85 {  // 85% схожість
            matches = append(matches, SanctionMatch{
                Entry:      entry,
                Similarity: similarity,
                ListSource: entry.ListSource,
            })
        }
    }
    return matches
}

SAR (Suspicious Activity Report)

При обнаруженні підозрілої активності — обов'язкова подача SAR у регулятора (FinCEN у США, Росфінмониторинг у Росії):

type SAR struct {
    UserID          int64
    TransactionID   string
    Amount          decimal.Decimal
    Currency        string
    SuspiciousType  string   // structuring, layering, unusual_pattern, etc.
    Description     string
    SupportingDocs  []string
    FiledAt         time.Time
}

// Автоматична генерація чернетки SAR при алерті
func (c *ComplianceEngine) GenerateSARDraft(alert AMLAlert) *SAR {
    user := c.db.GetUser(alert.UserID)
    txHistory := c.db.GetTransactionHistory(alert.UserID, 90*24*time.Hour)
    
    return &SAR{
        UserID:         alert.UserID,
        TransactionID:  alert.TxID,
        SuspiciousType: alert.RuleTriggered,
        Description: fmt.Sprintf(
            "Користувач %s (KYC: %s) здійснив транзакцію на %s %s "+
            "з адреси з високим ризиком (score: %.1f). "+
            "Історія транзакцій за 90 днів: %d операцій на суму %s",
            user.FullName, user.KYCTier, alert.Amount, alert.Currency,
            alert.RiskScore, len(txHistory), totalVolume(txHistory),
        ),
    }
}

Compliance Dashboard

Для команди compliance — окремий інтерфейс:

  • Очередь на ручну перевірку (high/medium risk транзакції)
  • Історія всіх AML алертів з деталізацією
  • Статистика: скільки транзакцій заблоковано, скільки SAR подано
  • Управління AML правилами та порогами

Сроки і інтеграції

Компонент Срок
KYC тиры + Sumsub інтеграція 2–3 тижні
AML правила + монітринг транзакцій 2–3 тижні
Blockchain analytics (Chainalysis/Elliptic) 1–2 тижні
Watchlist screening 1–2 тижні
Compliance dashboard 2–3 тижні

Повна KYC/AML система для обменника: 2–3 місяці. Вимагає юридичної консультації по цільовим юрисдикціям для налаштування порогів та вимог.