Uyumluluk çözümlerini kripto borsanıza entegre etmek karmaşık olmak zorunda değil. Bu kapsamlı rehber, gerçek kod örnekleri, en iyi uygulamalar ve kaçınılması gereken yaygın hatalarla birlikte Defy'in Vera AI, Live AML ve Travel Rule API'lerini nasıl uygulayacağınızı adım adım göstermektedir.
## Başlarken
### Ön Koşullar
Entegrasyondan önce:
- Aktif Defy hesabı
- API kimlik bilgileri (API key + secret)
- Geliştirme ortamı
- Test sandbox erişimi
- REST API'ler hakkında temel bilgi
### API Kimlik Doğrulama
Tüm Defy API'leri, HMAC imzalarıyla API key kimlik doğrulaması kullanır:
```javascript
const crypto = require('crypto');
function generateSignature(apiSecret, method, path, timestamp, body = '') {
const message = `${method}${path}${timestamp}${body}`;
return crypto
.createHmac('sha256', apiSecret)
.update(message)
.digest('hex');
}
// Example usage
const apiKey = process.env.DEFY_API_KEY;
const apiSecret = process.env.DEFY_API_SECRET;
const timestamp = Date.now().toString();
const method = 'POST';
const path = '/v1/verify';
const body = JSON.stringify({ userId: '12345' });
const signature = generateSignature(apiSecret, method, path, timestamp, body);
// Add to request headers
const headers = {
'X-Defy-API-Key': apiKey,
'X-Defy-Timestamp': timestamp,
'X-Defy-Signature': signature,
'Content-Type': 'application/json'
};
```
### SDK Kurulumu
**Node.js:**
```bash
npm install @defy/compliance-sdk
```
**Python:**
```bash
pip install defy-compliance
```
**Go:**
```bash
go get github.com/defy/compliance-go
```
**PHP:**
```bash
composer require defy/compliance-sdk
```
## Vera AI Entegrasyonu (Uyumluluk/KYB)
### Bireysel Uyumluluk Akışı
**Adım 1: Doğrulama Oturumu Başlatma**
```javascript
const { VeraAI } = require('@defy/compliance-sdk');
const vera = new VeraAI({
apiKey: process.env.DEFY_API_KEY,
apiSecret: process.env.DEFY_API_SECRET,
environment: 'production', // or 'sandbox'
webhookUrl: 'https://your-platform.com/webhooks/vera'
});
// Create verification session
async function startVerification(userId, userInfo) {
try {
const session = await vera.createSession({
userId: userId,
verificationType: 'individual',
requiredChecks: [
'identity_document',
'proof_of_address',
'biometric',
'sanctions_screening',
'pep_screening'
],
userInfo: {
firstName: userInfo.firstName,
lastName: userInfo.lastName,
dateOfBirth: userInfo.dateOfBirth,
nationality: userInfo.nationality,
email: userInfo.email,
phone: userInfo.phone
},
metadata: {
ipAddress: userInfo.ipAddress,
userAgent: userInfo.userAgent,
signupDate: userInfo.signupDate
}
});
return {
sessionId: session.id,
redirectUrl: session.redirectUrl,
expiresAt: session.expiresAt
};
} catch (error) {
console.error('verification session creation failed:', error);
throw error;
}
}
```
**Adım 2: Doğrulama Sonuçlarını İşleme**
```javascript
// Webhook endpoint
app.post('/webhooks/vera', async (req, res) => {
// Verify webhook signature
const isValid = vera.verifyWebhookSignature(
req.headers['x-defy-signature'],
req.body
);
if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = req.body;
switch (event.type) {
case 'verification.completed':
await handleVerificationCompleted(event.data);
break;
case 'verification.failed':
await handleVerificationFailed(event.data);
break;
case 'verification.pending_review':
await handleVerificationPendingReview(event.data);
break;
}
res.sendStatus(200);
});
async function handleVerificationCompleted(data) {
const {
userId,
sessionId,
riskScore,
verificationLevel,
checks
} = data;
// Update user in database
await db.users.update(userId, {
verificationStatus: 'completed',
verificationLevel: verificationLevel,
riskScore: riskScore,
verificationCompletedAt: new Date(),
verificationChecks: checks
});
// Enable trading
await enableUserTrading(userId);
// Notify user
await sendEmail(userId, 'Identity Verification Successful');
}
```
**Adım 3: Risk Tabanlı Karar Verme**
```javascript
async function makeVerificationDecision(userId, verificationData) {
const { riskScore, checks, flags } = verificationData;
// Auto-approve low risk
if (riskScore < 30 && allChecksPassed(checks)) {
return {
decision: 'approved',
level: 'standard',
limits: {
dailyDeposit: 50000,
dailyWithdrawal: 50000,
monthlyVolume: 1000000
}
};
}
// Manual review for medium risk
if (riskScore >= 30 && riskScore < 70) {
await queueForManualReview(userId, verificationData);
return {
decision: 'pending_review',
estimatedTime: '24 hours'
};
}
// Reject high risk
if (riskScore >= 70 || hasCriticalFlags(flags)) {
await logRejection(userId, flags);
return {
decision: 'rejected',
reason: determineRejectionReason(flags)
};
}
}
function allChecksPassed(checks) {
return checks.every(check => check.status === 'passed');
}
function hasCriticalFlags(flags) {
const criticalFlags = [
'sanctions_hit',
'pep_high_risk',
'fraudulent_document',
'stolen_identity'
];
return flags.some(flag => criticalFlags.includes(flag.type));
}
```
### Kurumsal KYB Akışı
```javascript
async function startKYB(companyId, companyInfo) {
const session = await vera.createSession({
companyId: companyId,
verificationType: 'business',
requiredChecks: [
'company_registry',
'tax_verification',
'ubo_identification',
'authorized_signatories',
'business_license'
],
companyInfo: {
legalName: companyInfo.legalName,
registrationNumber: companyInfo.registrationNumber,
taxId: companyInfo.taxId,
incorporationCountry: companyInfo.country,
businessType: companyInfo.businessType,
website: companyInfo.website
},
ubos: companyInfo.ubos.map(ubo => ({
firstName: ubo.firstName,
lastName: ubo.lastName,
ownership: ubo.ownershipPercentage,
dateOfBirth: ubo.dateOfBirth,
nationality: ubo.nationality
}))
});
return session;
}
```
## Live AML Entegrasyonu
### İşlem İzleme
**İşlem Öncesi Tarama:**
```javascript
const { LiveAML } = require('@defy/compliance-sdk');
const liveAML = new LiveAML({
apiKey: process.env.DEFY_API_KEY,
apiSecret: process.env.DEFY_API_SECRET
});
async function screenTransaction(transaction) {
try {
const result = await liveAML.screenTransaction({
transactionId: transaction.id,
userId: transaction.userId,
type: transaction.type, // 'deposit', 'withdrawal', 'trade'
amount: transaction.amount,
currency: transaction.currency,
blockchain: transaction.blockchain,
addresses: {
from: transaction.fromAddress,
to: transaction.toAddress
},
metadata: {
timestamp: transaction.timestamp,
ipAddress: transaction.ipAddress,
deviceId: transaction.deviceId
}
});
return {
allowed: result.decision === 'approved',
riskScore: result.riskScore,
riskLevel: result.riskLevel,
flags: result.flags,
requiresReview: result.decision === 'manual_review'
};
} catch (error) {
// On error, default to manual review for safety
console.error('AML screening error:', error);
return {
allowed: false,
requiresReview: true,
error: error.message
};
}
}
// Usage in withdrawal flow
app.post('/api/withdraw', async (req, res) => {
const { userId, amount, currency, toAddress } = req.body;
// Create pending transaction
const transaction = await db.transactions.create({
userId,
type: 'withdrawal',
amount,
currency,
toAddress,
status: 'pending_aml_check'
});
// Screen transaction
const amlResult = await screenTransaction(transaction);
if (amlResult.allowed) {
// Approve and process
await db.transactions.update(transaction.id, {
status: 'approved',
riskScore: amlResult.riskScore
});
await processWithdrawal(transaction.id);
res.json({ success: true, transactionId: transaction.id });
} else if (amlResult.requiresReview) {
// Queue for manual review
await db.transactions.update(transaction.id, {
status: 'pending_review',
riskScore: amlResult.riskScore,
flags: amlResult.flags
});
res.json({
success: false,
status: 'pending_review',
message: 'Transaction queued for compliance review'
});
} else {
// Reject
await db.transactions.update(transaction.id, {
status: 'rejected',
rejectionReason: amlResult.flags
});
res.json({
success: false,
status: 'rejected',
message: 'Transaction rejected due to compliance reasons'
});
}
});
```
**Davranış Analizi:**
```javascript
async function analyzeUserBehavior(userId) {
const behavior = await liveAML.analyzeBehavior({
userId: userId,
timeframe: '30d', // Last 30 days
includeMetrics: [
'transaction_frequency',
'amount_patterns',
'time_patterns',
'address_diversity',
'counterparty_risk'
]
});
return {
riskScore: behavior.overallRiskScore,
insights: {
transactionFrequency: behavior.metrics.transaction_frequency,
averageAmount: behavior.metrics.average_amount,
peakTradingHours: behavior.metrics.peak_hours,
suspiciousPatterns: behavior.flags
},
recommendations: behavior.recommendations
};
}
```
**Yaptırım Taraması:**
```javascript
async function screenAddress(address, blockchain) {
const result = await liveAML.screenAddress({
address: address,
blockchain: blockchain,
includeIndirectExposure: true, // Check 2-3 hops
lists: ['OFAC', 'UN', 'EU', 'MASAK'] // Which lists to check
});
if (result.hit) {
// Log sanctions hit
await logSanctionsHit({
address: address,
blockchain: blockchain,
matchedLists: result.matches,
severity: result.severity
});
// Block transaction
return {
allowed: false,
reason: 'sanctions_hit',
details: result.matches
};
}
return { allowed: true };
}
```
## Travel Rule Entegrasyonu
### VASP'tan VASP'a İletişim
**Giden Transfer:**
```javascript
const { TravelRule } = require('@defy/compliance-sdk');
const travelRule = new TravelRule({
apiKey: process.env.DEFY_API_KEY,
apiSecret: process.env.DEFY_API_SECRET,
vaspInfo: {
name: 'Your Exchange Name',
did: 'did:web:your-exchange.com',
jurisdiction: 'TR',
license: 'MASAK-2024-001'
}
});
async function handleOutgoingTransfer(transfer) {
// Check if amount exceeds Travel Rule threshold
const requiresTravelRule = await travelRule.checkThreshold({
amount: transfer.amount,
currency: transfer.currency,
jurisdiction: transfer.jurisdiction
});
if (!requiresTravelRule) {
// Process normally
return await processTransfer(transfer);
}
// Discover beneficiary VASP
const beneficiaryVASP = await travelRule.discoverVASP({
address: transfer.beneficiaryAddress,
blockchain: transfer.blockchain
});
if (!beneficiaryVASP) {
// Unhosted wallet - collect beneficiary info from user
const beneficiaryInfo = await requestBeneficiaryInfo(transfer.userId);
// Process with enhanced due diligence
return await processWithEDD(transfer, beneficiaryInfo);
}
// Send Travel Rule data
const trSession = await travelRule.sendData({
originator: {
name: transfer.originatorName,
address: transfer.originatorAddress,
accountNumber: transfer.userId,
vasp: {
name: 'Your Exchange',
did: 'did:web:your-exchange.com'
}
},
beneficiary: {
name: beneficiaryVASP.name,
did: beneficiaryVASP.did,
accountNumber: transfer.beneficiaryAccountId
},
transaction: {
amount: transfer.amount,
currency: transfer.currency,
blockchain: transfer.blockchain
}
});
// Wait for acceptance (with timeout)
const response = await trSession.waitForResponse({
timeout: 300000 // 5 minutes
});
if (response.status === 'accepted') {
// Link TR data to transaction
await db.transactions.update(transfer.id, {
travelRuleSessionId: trSession.id,
travelRuleStatus: 'completed'
});
// Process transaction
return await processTransfer(transfer);
} else {
// Rejected by beneficiary VASP
await db.transactions.update(transfer.id, {
status: 'rejected',
rejectionReason: response.rejectionReason
});
throw new Error(`Travel Rule rejected: ${response.rejectionReason}`);
}
}
```
**Gelen Transfer:**
```javascript
// Webhook handler for incoming Travel Rule data
app.post('/webhooks/travel-rule', async (req, res) => {
const incomingData = req.body;
// Verify originator VASP
const vaspValid = await travelRule.verifyVASP(incomingData.originator.vasp);
if (!vaspValid) {
await travelRule.rejectTransfer(incomingData.sessionId, {
reason: 'invalid_vasp',
message: 'Originator VASP could not be verified'
});
return res.sendStatus(200);
}
// Sanctions screening
const sanctionsResult = await liveAML.screenEntity({
name: incomingData.originator.name,
address: incomingData.originator.address
});
if (sanctionsResult.hit) {
await travelRule.rejectTransfer(incomingData.sessionId, {
reason: 'sanctions_hit',
message: 'Originator appears on sanctions list'
});
await fileSAR(incomingData, sanctionsResult);
return res.sendStatus(200);
}
// Risk assessment
const riskScore = await calculateIncomingRisk(incomingData);
if (riskScore < 70) {
// Auto-accept
await travelRule.acceptTransfer(incomingData.sessionId);
} else {
// Queue for manual review
await queueTransferReview(incomingData, riskScore);
}
res.sendStatus(200);
});
```
## Hata Yönetimi
### Yeniden Deneme Mantığı
```javascript
async function callAPIWithRetry(apiCall, maxRetries = 3) {
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await apiCall();
} catch (error) {
lastError = error;
// Don't retry on client errors (4xx)
if (error.statusCode >= 400 && error.statusCode < 500) {
throw error;
}
// Exponential backoff
if (attempt < maxRetries) {
const delay = Math.min(1000 * Math.pow(2, attempt), 10000);
await sleep(delay);
}
}
}
throw lastError;
}
// Usage
const result = await callAPIWithRetry(() =>
vera.createSession(sessionData)
);
```
### Hız Sınırlandırma
```javascript
const rateLimit = require('express-rate-limit');
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per windowMs
message: 'Too many requests, please try again later',
standardHeaders: true,
legacyHeaders: false,
});
app.use('/api/', apiLimiter);
```
## Test
### Sandbox Ortamı
```javascript
// Use sandbox for development
const vera = new VeraAI({
apiKey: process.env.DEFY_SANDBOX_API_KEY,
apiSecret: process.env.DEFY_SANDBOX_API_SECRET,
environment: 'sandbox'
});
// Test with mock data
const testSession = await vera.createSession({
userId: 'test_user_123',
verificationType: 'individual',
testMode: true,
testScenario: 'approved_low_risk' // or 'rejected_sanctions', 'pending_review'
});
```
### Entegrasyon Testleri
```javascript
describe('Vera AI Integration', () => {
it('should create verification session successfully', async () => {
const session = await vera.createSession({
userId: 'test_123',
verificationType: 'individual'
});
expect(session).toHaveProperty('id');
expect(session).toHaveProperty('redirectUrl');
expect(session.status).toBe('pending');
});
it('should handle webhook correctly', async () => {
const webhookPayload = {
type: 'verification.completed',
data: {
userId: 'test_123',
riskScore: 25,
verificationLevel: 'standard'
}
};
const response = await request(app)
.post('/webhooks/vera')
.send(webhookPayload)
.set('X-Defy-Signature', generateTestSignature(webhookPayload));
expect(response.status).toBe(200);
});
});
```
## En İyi Uygulamalar
### Performans Optimizasyonu
**1. API Yanıtlarını Önbelleğe Alma:**
```javascript
const redis = require('redis');
const client = redis.createClient();
async function getCachedRiskScore(userId) {
const cached = await client.get(`risk:${userId}`);
if (cached) return JSON.parse(cached);
const riskScore = await liveAML.getRiskScore(userId);
await client.setex(`risk:${userId}`, 3600, JSON.stringify(riskScore));
return riskScore;
}
```
**2. Toplu İşleme:**
```javascript
// Screen multiple addresses in one request
const results = await liveAML.batchScreenAddresses({
addresses: [
{ address: '0x123...', blockchain: 'ethereum' },
{ address: '0x456...', blockchain: 'ethereum' },
{ address: 'bc1q789...', blockchain: 'bitcoin' }
]
});
```
**3. Asenkron İşleme:**
```javascript
// Don't block on non-critical checks
async function processDeposit(deposit) {
// Critical: Sanctions screening (block)
const sanctionsResult = await liveAML.screenAddress(deposit.fromAddress);
if (sanctionsResult.hit) {
throw new Error('Sanctions violation');
}
// Credit user account
await creditUserBalance(deposit);
// Non-critical: Behavioral analysis (async)
analyzeBehavior(deposit.userId).catch(err => {
console.error('Behavior analysis failed:', err);
});
return { success: true };
}
```
## İzleme ve Loglama
### Loglama
```javascript
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'compliance.log' })
]
});
// Log all API calls
async function loggedAPICall(apiCall, context) {
const startTime = Date.now();
try {
const result = await apiCall();
logger.info('API call successful', {
...context,
duration: Date.now() - startTime,
result: result
});
return result;
} catch (error) {
logger.error('API call failed', {
...context,
duration: Date.now() - startTime,
error: error.message,
stack: error.stack
});
throw error;
}
}
```
### Metrikler
```javascript
const prometheus = require('prom-client');
// Define metrics
const verificationSessionCounter = new prometheus.Counter({
name: 'verification_sessions_total',
help: 'Total number of verification sessions created',
labelNames: ['status']
});
const amlScreeningDuration = new prometheus.Histogram({
name: 'aml_screening_duration_seconds',
help: 'AML screening duration',
buckets: [0.1, 0.5, 1, 2, 5]
});
// Record metrics
verificationSessionCounter.inc({ status: 'approved' });
const timer = amlScreeningDuration.startTimer();
await screenTransaction(tx);
timer();
```
## Sonuç
Defy'in uyumluluk API'lerinin başarılı entegrasyonu şu unsurları gerektirir:
1. Doğru kimlik doğrulama ve güvenlik
2. Sağlam hata yönetimi
3. Kapsamlı test
4. Performans optimizasyonu
5. İzleme ve loglama
**Defy Destek:**
- Teknik dokümantasyon: https://docs.getdefy.co
- API referansı: https://api.getdefy.co/docs
- SDK örnekleri: https://github.com/defy/examples
- Destek: info@getdefy.co
- Slack topluluğu: https://defy-dev.slack.com
Defy ile uyumlu kripto platformları oluşturmaya bugün başlayın!