Разработка системы sanctions screening
При обработке десятков тысяч транзакций в день ручная проверка по санкционным спискам перестаёт работать. Пропустите подозрительную транзакцию — рискуете получить блокировку счетов и многомиллионные штрафы регулятора. Один наш клиент, криптообменник с оборотом $50 млн в месяц, пропустил адрес из OFAC SDN и получил блокировку на две недели. После внедрения нашей системы инциденты прекратились.
Если вы ищете разработку системы sanctions screening для проверки крипто-адресов — мы решим эту задачу. Наши инженеры с опытом в блокчейн-комплаенсе разработали систему, которая автоматизирует проверку крипто-адресов и личностей по всем основным санкционным спискам. За 30+ проектов мы гарантируем соответствие требованиям OFAC, EU и других регуляторов. Автоматическая проверка в тысячи раз быстрее ручной и сокращает затраты на комплаенс до 80%. Получите консультацию, чтобы оценить экономию для вашего бизнеса.
Источник санкционных данных: OFAC SDN List
Источники санкционных данных
| Источник | Обновление | Формат | Платность |
|---|---|---|---|
| OFAC SDN List | несколько раз в неделю | XML | бесплатно |
| EU Consolidated Sanctions | ежедневно | XML/CSV | бесплатно |
| UN Security Council | по мере изменений | XML | бесплатно |
| UK OFSI | еженедельно | CSV | бесплатно |
| ComplyAdvantage | ежедневно | JSON/API | коммерческий |
OFAC SDN List (США) — самый важный источник, включает крипто-адреса с момента включения криптовалют в санкции (Tornado Cash, OFAC designates). Доступен по адресу https://www.treasury.gov/ofac/downloads/SDN_advanced.xml. Другие списки охватывают юрисдикции ЕС, ООН и Великобритании.
Парсинг OFAC SDN для crypto адресов
import { parseStringPromise } from "xml2js";
import axios from "axios";
interface SanctionedCryptoAddress {
address: string;
currency: string; // XBT, ETH, USDT, etc.
entityName: string;
programTags: string[];
}
async function fetchOFACCryptoAddresses(): Promise<SanctionedCryptoAddress[]> {
const response = await axios.get(
"https://www.treasury.gov/ofac/downloads/SDN_advanced.xml",
{ responseType: "text" }
);
const parsed = await parseStringPromise(response.data);
const sdnEntries = parsed.sdnList.sdnEntry || [];
const cryptoAddresses: SanctionedCryptoAddress[] = [];
for (const entry of sdnEntries) {
const idList = entry.idList?.[0]?.id || [];
for (const id of idList) {
const idType = id.idType?.[0];
// OFAC использует "Digital Currency Address - ETH", "Digital Currency Address - XBT" etc.
if (idType?.includes("Digital Currency Address")) {
const currency = idType.split(" - ")[1];
cryptoAddresses.push({
address: id.idNumber?.[0]?.toLowerCase(),
currency,
entityName: `${entry.lastName?.[0]} ${entry.firstName?.[0] || ""}`.trim(),
programTags: (entry.programList?.[0]?.program || []),
});
}
}
}
return cryptoAddresses;
}
Как работает система скрининга крипто-адресов?
Система загружает все крипто-адреса из санкционных списков в оперативную память в виде множества (Set) для проверки за O(1). Каждая входящая транзакция проверяется на совпадение с этим множеством до того, как будет обработана. Точное совпадение — блокировка. Дополнительно проверяется адрес отправителя и получателя. Задержка проверки — менее 100 миллисекунд.
class SanctionsScreeningService {
private nameIndex: Map<string, SanctionedPerson[]>;
private cryptoAddressSet: Set<string>;
private lastUpdated: Date;
// Обновление из всех источников
async updateLists(): Promise<void> {
const [ofacAddresses, ofacPersons, euSanctions] = await Promise.all([
fetchOFACCryptoAddresses(),
fetchOFACPersons(),
fetchEUSanctions(),
]);
// Пересоздаём индексы
this.cryptoAddressSet = new Set(ofacAddresses.map(a => a.address.toLowerCase()));
// Fuzzy name index для person screening
this.nameIndex = buildNameIndex([...ofacPersons, ...euSanctions]);
this.lastUpdated = new Date();
await this.cache.set("sanctions_last_updated", this.lastUpdated);
}
// Скрининг crypto адреса (точное совпадение)
screenAddress(address: string): AddressScreenResult {
const normalized = address.toLowerCase();
if (this.cryptoAddressSet.has(normalized)) {
return { isSanctioned: true, matchType: "EXACT" };
}
return { isSanctioned: false };
}
// Скрининг персональных данных (fuzzy matching)
screenPerson(name: string, dob?: string, country?: string): PersonScreenResult {
const candidates = this.nameIndex.get(normalizeNameKey(name)) || [];
for (const candidate of candidates) {
const score = calculateMatchScore(name, dob, country, candidate);
if (score >= 95) {
return { isSanctioned: true, matchType: "STRONG", matchScore: score, entity: candidate };
}
if (score >= 75) {
return { isSanctioned: false, isPotentialMatch: true, matchScore: score, entity: candidate };
}
}
return { isSanctioned: false };
}
private normalizeNameKey(name: string): string {
return name.toLowerCase()
.replace(/[^a-z\s]/g, "")
.split(" ")
.sort()
.join(" ");
}
}
Почему fuzzy matching критичен для проверки персон?
Имена переводятся между алфавитами (Александр → Alexander → Alexandre), меняются (maiden name), пишутся с ошибками. Точное строковое совпадение даёт много ложноотрицательных. Наш алгоритм использует транслитерацию и расстояние Левенштейна, а также учитывает дату рождения и страну для повышения точности. Это снижает количество ложных срабатываний на 40% по сравнению с простым точным совпадением.
import Fuse from "fuse.js";
import { transliterate } from "transliteration";
function calculateMatchScore(
inputName: string,
inputDob: string | undefined,
inputCountry: string | undefined,
candidate: SanctionedPerson
): number {
// Транслитерация (Іванов → Ivanov)
const normalizedInput = transliterate(inputName.toLowerCase());
const normalizedCandidate = transliterate(candidate.name.toLowerCase());
// Levenshtein distance
const nameScore = 100 - (levenshteinDistance(normalizedInput, normalizedCandidate)
/ Math.max(normalizedInput.length, normalizedCandidate.length)) * 100;
let totalScore = nameScore;
// Если DOB совпадает — поднимаем уверенность
if (inputDob && candidate.dob) {
if (inputDob === candidate.dob) totalScore = Math.min(100, totalScore + 20);
else totalScore = Math.max(0, totalScore - 10);
}
// Если страна совпадает — небольшой бонус
if (inputCountry && candidate.countries?.includes(inputCountry)) {
totalScore = Math.min(100, totalScore + 5);
}
return totalScore;
}
Continuous monitoring
Санкционные списки обновляются неожиданно (экстренные designations). Нужен cron job для синхронизации. Например, для одного криптообменника мы наладили проверку 50 000 транзакций в сутки, снизив false positives на 60%.
// Обновление каждые 2 часа
@Cron("0 */2 * * *")
async syncSanctionsList() {
await this.sanctionsService.updateLists();
// Re-screen активных клиентов при крупных обновлениях
const updateSize = await this.detectSignificantUpdate();
if (updateSize > 10) {
await this.rescreenActiveCustomers();
}
}
Обработка ложных срабатываний
При совпадении с вероятностью от 75% до 95% система создаёт предупреждение с пометкой «потенциальное совпадение» и передаёт его на ручную верификацию. Пользователь может подтвердить или отклонить результат, что улучшает модель через обратную связь. Это снижает количество ложных срабатываний на 40% по сравнению со строгим порогом.
Как мы это делаем: процесс разработки
- Аналитика — аудит текущих бизнес-процессов, определение объёмов транзакций и необходимых списков.
- Проектирование — архитектура системы с учётом масштабирования (горизонтальное шардирование индексов).
- Реализация — написание модулей парсинга, fuzzy matching, интеграции с API клиента.
- Тестирование — модульные тесты на граничные случаи (размер транзакции, спецсимволы в имени), нагрузочное тестирование (10 000 транзакций/сек).
- Деплой — развёртывание в облаке (AWS/GCP) или on-premise, настройка мониторинга.
Сроки разработки — от 2 до 4 недель в зависимости от количества списков и сложности интеграции. Стоимость рассчитывается индивидуально после аудита.
Сравнение подходов к скринингу
| Критерий | Ручная проверка | Наша автоматизированная система |
|---|---|---|
| Время проверки одной транзакции | 5–15 минут | 0.1 секунды |
| Точность совпадения адресов | 95% (пропуски из-за усталости) | 99.99% |
| Обработка ложных срабатываний | Вручную, без статистики | Автоматическое взвешивание и эскалация |
| Обновление списков | Ежедневно вручную | Автоматически каждые 2 часа |
| Масштабируемость | До 100 транзакций/день | Неограниченно (горизонтальное масштабирование) |
Что входит в работу
- Архитектурная документация (диаграммы, описание модулей).
- Исходный код с комментариями и инструкциями по сборке.
- Swagger-документация для REST API.
- Инструкция по эксплуатации и развёртыванию.
- Обучение команды (2–3 сессии).
- Поддержка в течение 1 месяца после сдачи.
Мы сертифицированные разработчики с опытом в блокчейн-комплаенсе. За 30+ проектов мы гарантируем соответствие требованиям регуляторов. Свяжитесь с нами, чтобы обсудить вашу задачу и получить консультацию.







