Skip to main content
This guide covers how to integrate ChainStream KYT/KYA compliance capabilities into your application, including complete scenarios for CEX deposit/withdrawal risk control, wallet risk alerts, and batch screening.

Prerequisites

API Configuration

ConfigValue
Base URLhttps://api-dex.chainstream.io/
Auth Domaindex.asia.auth.chainstream.io
Audiencehttps://api.dex.chainstream.io
ScopeDescription
kyt.readKYT API read permission (query transaction risk)
kyt.writeKYT API write permission (register transaction analysis)

Generate Access Token

import { AuthenticationClient } from 'auth0';

const auth0Client = new AuthenticationClient({
  domain: 'dex.asia.auth.chainstream.io',
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret'
});

// Get Token with full KYT permissions
const response = await auth0Client.oauth.clientCredentialsGrant({
  audience: 'https://api.dex.chainstream.io',
  scope: 'kyt.read kyt.write'
});

const accessToken = response.data.access_token;

API Calls

All requests must include the Token in the Header:
const response = await fetch('https://api-dex.chainstream.io/v1/kyt/transfer', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ /* request body */ })
});

CEX Deposit Risk Control

Exchange deposit scenarios are the core use case for KYT, requiring risk assessment before funds are credited.

Business Flow

Integration Steps

1

Initialize Client

import { AuthenticationClient } from 'auth0';

// Generate Token (recommend caching, refresh before expiry)
async function getAccessToken() {
  const auth0Client = new AuthenticationClient({
    domain: 'dex.asia.auth.chainstream.io',
    clientId: process.env.CHAINSTREAM_CLIENT_ID,
    clientSecret: process.env.CHAINSTREAM_CLIENT_SECRET
  });

  const { data } = await auth0Client.oauth.clientCredentialsGrant({
    audience: 'https://api.dex.chainstream.io',
    scope: 'kyt.read kyt.write'
  });

  return data.access_token;
}
2

Transaction Detection

Monitor incoming transactions to user deposit addresses:
async function onDepositDetected(tx) {
  const deposit = {
    network: 'ethereum',           // Network: bitcoin, ethereum, Solana
    asset: tx.asset,               // Asset type: ETH, SOL, etc.
    transferReference: tx.hash,    // Transaction hash
    direction: 'received'          // Direction: sent or received
  };
  
  // Call KYT analysis
  const result = await registerTransfer(deposit);
  
  // Get risk assessment
  const risk = await getTransferSummary(result.externalId);
  
  // Execute decision
  await executeDecision(tx, risk);
}
3

Register Transaction

Call KYT API to register transaction:
async function registerTransfer(deposit) {
  const response = await fetch('https://api-dex.chainstream.io/v1/kyt/transfer', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      network: deposit.network,
      asset: deposit.asset,
      transferReference: deposit.transferReference,
      direction: deposit.direction
    })
  });
  
  return await response.json();
}
4

Get Risk Assessment

Query transaction risk summary:
async function getTransferSummary(transferId) {
  const response = await fetch(
    `https://api-dex.chainstream.io/v1/kyt/transfers/${transferId}/summary`,
    {
      headers: {
        'Authorization': `Bearer ${accessToken}`
      }
    }
  );
  
  return await response.json();
}
5

Auto Decision

Execute appropriate actions based on risk level:
async function executeDecision(tx, risk) {
  const riskLevel = risk.rating; // SEVERE, HIGH, MEDIUM, LOW
  
  switch (riskLevel) {
    case 'SEVERE':
      await freezeDeposit(tx);
      await createSARReport(tx, risk);
      await notifyCompliance(tx, risk);
      break;
      
    case 'HIGH':
      await holdDeposit(tx, { hours: 24 });
      await createManualReview(tx, risk);
      break;
      
    case 'MEDIUM':
      await creditDeposit(tx);
      await flagForMonitoring(tx, risk);
      break;
      
    case 'LOW':
      await creditDeposit(tx);
      break;
  }
  
  // Record audit log
  await auditLog.record({
    action: 'DEPOSIT_RISK_DECISION',
    txHash: tx.hash,
    riskLevel,
    timestamp: new Date()
  });
}

Complete Flow Details

The end-to-end compliance integration flow covers: Detect → Register → Poll → Risk Judgment → Release/Freeze

1. Detection Phase

Trigger SourceDescriptionLatency
On-chain MonitoringMonitor deposit addressesBlock confirmation time
User SubmissionWithdrawal requestInstant
Scheduled ScanCatch-up mechanismConfigurable

2. Registration Phase

POST https://api-dex.chainstream.io/v1/kyt/transfer
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "network": "ethereum",
  "asset": "ETH",
  "transferReference": "0x1234567890abcdef...",
  "direction": "received"
}
Response:
{
  "externalId": "123e4567-e89b-12d3-a456-426614174000",
  "asset": "ETH",
  "network": "ethereum",
  "transferReference": "0x1234567890abcdef...",
  "direction": "received",
  "updatedAt": "2024-01-15T10:30:00.000Z"
}

3. Query Phase

async function pollForResult(transferId, maxAttempts = 10) {
  for (let i = 0; i < maxAttempts; i++) {
    const response = await fetch(
      `https://api-dex.chainstream.io/v1/kyt/transfers/${transferId}/summary`,
      {
        headers: { 'Authorization': `Bearer ${accessToken}` }
      }
    );
    const data = await response.json();
    
    if (data.rating) {
      return data;
    }
    
    await new Promise(r => setTimeout(r, 3000)); // 3 second interval
  }
  
  throw new Error('Analysis timeout');
}

4. Judgment Phase

Risk judgment rule configuration:
risk_rules:
  severe:
    action: FREEZE
    auto_execute: true
    notify:
      - [email protected]
      - [email protected]
    
  high:
    action: MANUAL_REVIEW
    auto_execute: false
    hold_period: 24h
    escalation: 4h
    
  medium:
    action: FLAG
    auto_execute: true
    monitoring_period: 30d
    
  low:
    action: PASS
    auto_execute: true

5. Execution Phase

ActionTrigger ConditionFollow-up
ReleaseLOW riskNormal credit/payment
FlagMEDIUM riskCredit but continue monitoring
HoldHIGH riskEnter manual review queue
FreezeSEVERE riskFreeze + Compliance report

Complete Service Implementation

import { AuthenticationClient } from 'auth0';

class ComplianceService {
  constructor() {
    this.accessToken = null;
    this.tokenExpiry = null;
  }

  // Get or refresh Token
  async getAccessToken() {
    if (this.accessToken && this.tokenExpiry > Date.now()) {
      return this.accessToken;
    }

    const auth0Client = new AuthenticationClient({
      domain: 'dex.asia.auth.chainstream.io',
      clientId: process.env.CHAINSTREAM_CLIENT_ID,
      clientSecret: process.env.CHAINSTREAM_CLIENT_SECRET
    });

    const { data } = await auth0Client.oauth.clientCredentialsGrant({
      audience: 'https://api.dex.chainstream.io',
      scope: 'kyt.read kyt.write'
    });

    this.accessToken = data.access_token;
    // Token usually valid 24 hours, refresh 1 hour early
    this.tokenExpiry = Date.now() + (23 * 60 * 60 * 1000);
    
    return this.accessToken;
  }

  // Deposit compliance check
  async checkDeposit(deposit) {
    const token = await this.getAccessToken();
    
    // 1. Register transaction
    const registerResponse = await fetch('https://api-dex.chainstream.io/v1/kyt/transfer', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        network: deposit.network,
        asset: deposit.asset,
        transferReference: deposit.txHash,
        direction: 'received'
      })
    });
    const registered = await registerResponse.json();

    // 2. Wait and get risk assessment
    const risk = await this.waitForAnalysis(token, registered.externalId);
    
    // 3. Generate decision
    const decision = this.makeDecision(risk);
    
    // 4. Record audit
    await this.auditLog(deposit, risk, decision);
    
    return decision;
  }

  async waitForAnalysis(token, transferId, maxAttempts = 10) {
    for (let i = 0; i < maxAttempts; i++) {
      const response = await fetch(
        `https://api-dex.chainstream.io/v1/kyt/transfers/${transferId}/summary`,
        { headers: { 'Authorization': `Bearer ${token}` } }
      );
      const result = await response.json();
      
      if (result.rating) {
        return result;
      }
      await new Promise(r => setTimeout(r, 3000));
    }
    throw new Error('Analysis timeout');
  }

  makeDecision(risk) {
    const decisions = {
      'SEVERE': {
        action: 'FREEZE',
        requireSAR: true,
        notify: ['[email protected]', '[email protected]']
      },
      'HIGH': {
        action: 'HOLD',
        requireReview: true,
        holdHours: 24
      },
      'MEDIUM': {
        action: 'PASS',
        flagMonitoring: true
      },
      'LOW': {
        action: 'PASS'
      }
    };
    return decisions[risk.rating] || decisions['LOW'];
  }

  async auditLog(deposit, risk, decision) {
    console.log({
      timestamp: new Date().toISOString(),
      type: 'COMPLIANCE_CHECK',
      deposit,
      risk,
      decision
    });
  }
}

// Usage example
const compliance = new ComplianceService();

app.post('/deposit/process', async (req, res) => {
  const deposit = req.body;
  const decision = await compliance.checkDeposit(deposit);
  res.json(decision);
});

CEX Withdrawal Risk Control

Withdrawal scenarios require checking the risk of the destination address when users initiate withdrawals.

Business Flow

Implementation Example

async function handleWithdrawal(request) {
  const { toAddress } = request;
  const token = await complianceService.getAccessToken();
  
  // 1. Register address
  const registerResponse = await fetch('https://api-dex.chainstream.io/v1/kyt/address', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ address: toAddress })
  });
  await registerResponse.json();
  
  // 2. Get address risk
  const riskResponse = await fetch(
    `https://api-dex.chainstream.io/v1/kyt/addresses/${toAddress}/risk`,
    { headers: { 'Authorization': `Bearer ${token}` } }
  );
  const addressRisk = await riskResponse.json();
  
  // 3. Risk handling
  switch (addressRisk.rating) {
    case 'SEVERE':
      return {
        status: 'REJECTED',
        reason: 'Target address is associated with known criminal activity',
        riskLevel: 'SEVERE'
      };
      
    case 'HIGH':
      return {
        status: 'PENDING_CONFIRMATION',
        warning: 'This address has been flagged as high risk',
        riskDetails: addressRisk,
        requiresConfirmation: true
      };
      
    default:
      return {
        status: 'APPROVED',
        riskLevel: addressRisk.rating
      };
  }
}

// Express route example
app.post('/withdraw/request', async (req, res) => {
  const result = await handleWithdrawal(req.body);
  res.json(result);
});

Wallet Risk Alerts

In wallet applications, provide risk alerts before users initiate transfers.

User Experience Flow

Frontend/Backend Integration

Frontend should never expose clientSecret directly. Use backend API proxy to call ChainStream.
// Trigger on address input change
async function onAddressChange(address) {
  if (!isValidAddress(address)) return;
  
  setLoading(true);
  
  try {
    // Call backend proxy API
    const response = await fetch('/api/risk/check-address', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ address })
    });
    const risk = await response.json();
    
    setRiskInfo({
      level: risk.rating,
      labels: risk.labels,
      warnings: risk.warnings
    });
  } finally {
    setLoading(false);
  }
}

Batch Address Screening

Enterprise-level compliance screening for existing addresses.

Use Cases

  • Regular compliance audits
  • New regulatory requirement implementation
  • M&A due diligence
  • Risk screening

Batch Screening Implementation

async function batchScreenAddresses(addresses) {
  const token = await complianceService.getAccessToken();
  const results = [];
  
  for (const address of addresses) {
    try {
      // Register address
      await fetch('https://api-dex.chainstream.io/v1/kyt/address', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ address })
      });
      
      // Get risk
      const riskResponse = await fetch(
        `https://api-dex.chainstream.io/v1/kyt/addresses/${address}/risk`,
        { headers: { 'Authorization': `Bearer ${token}` } }
      );
      const risk = await riskResponse.json();
      
      results.push({
        address,
        rating: risk.rating,
        riskScore: risk.riskScore
      });
    } catch (error) {
      results.push({
        address,
        error: error.message
      });
    }
  }
  
  // Process high-risk addresses
  const highRiskAddresses = results.filter(
    r => r.rating === 'SEVERE' || r.rating === 'HIGH'
  );
  
  return { all: results, highRisk: highRiskAddresses };
}

Best Practices

Threshold Setting Recommendations

Adjust risk thresholds based on business type:
Business TypeSEVERE HandlingHIGH HandlingMEDIUM Handling
Licensed CEXAuto freezeManual reviewFlag monitoring
Wallet AppStrong warningWarningNotice
DeFi ProtocolReject interactionWarningNormal
OTC PlatformReject tradeAdditional KYCNormal

Audit Log Requirements

Ensure complete audit trail:
{
  "eventId": "evt_123456",
  "timestamp": "2024-01-15T10:30:00Z",
  "eventType": "RISK_DECISION",
  "subject": {
    "transferId": "123e4567-e89b-12d3-a456-426614174000",
    "txHash": "0x...",
    "userId": "user_789"
  },
  "riskAssessment": {
    "rating": "HIGH",
    "riskScore": 72
  },
  "decision": {
    "action": "HOLD",
    "decidedBy": "SYSTEM",
    "reason": "Auto-hold per risk policy"
  },
  "metadata": {
    "policyVersion": "1.2.0",
    "engineVersion": "2024.01"
  }
}

Next Steps