Changes include: - Updated architecture documentation - Enhanced module definitions (OQI-001 to OQI-008) - ML integration documentation updates - Trading strategies documentation - Orchestration and inventory updates - Docker configuration updates 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
645 lines
24 KiB
Markdown
645 lines
24 KiB
Markdown
---
|
|
id: "RF-PAY-007"
|
|
title: "Sistema de Depositos y Retiros en Criptomonedas"
|
|
type: "Requirement"
|
|
status: "Draft"
|
|
priority: "Alta"
|
|
epic: "OQI-005"
|
|
project: "trading-platform"
|
|
version: "1.0.0"
|
|
created_date: "2026-01-04"
|
|
updated_date: "2026-01-04"
|
|
---
|
|
|
|
# RF-PAY-007: Sistema de Depositos y Retiros en Criptomonedas
|
|
|
|
**Version:** 1.0.0
|
|
**Fecha:** 2026-01-04
|
|
**Estado:** Draft
|
|
**Prioridad:** P1 (Alta)
|
|
**Story Points:** 13
|
|
**Epica:** [OQI-005](../_MAP.md)
|
|
|
|
---
|
|
|
|
## Descripcion
|
|
|
|
El sistema debe permitir a los usuarios realizar depositos y retiros utilizando criptomonedas, integrando con proveedores de pago crypto como Coinbase Commerce o BitPay, soportando multiples monedas y redes blockchain, con conversion automatica a USD para mantener el balance del wallet interno.
|
|
|
|
---
|
|
|
|
## Objetivo de Negocio
|
|
|
|
- Expandir opciones de pago para usuarios globales sin acceso bancario tradicional
|
|
- Atraer segmento crypto-nativo con preferencia por pagos descentralizados
|
|
- Reducir costos de transaccion en mercados internacionales
|
|
- Ofrecer alternativa a usuarios con restricciones bancarias
|
|
- Habilitar depositos anonimos (hasta limite KYC)
|
|
|
|
---
|
|
|
|
## Casos de Uso
|
|
|
|
1. **Deposito BTC:** Usuario envia 0.01 BTC a direccion unica y recibe $450 USD en wallet
|
|
2. **Deposito USDT:** Usuario envia 100 USDT (TRC-20) y recibe $100 USD en wallet
|
|
3. **Retiro ETH:** Usuario solicita retiro de $200 USD y recibe 0.08 ETH en su wallet externo
|
|
4. **Verificacion KYC:** Usuario completa KYC para habilitar retiros crypto
|
|
5. **Monitoreo de Confirmaciones:** Sistema muestra progreso de confirmaciones on-chain
|
|
|
|
---
|
|
|
|
## Monedas y Redes Soportadas
|
|
|
|
| Moneda | Simbolo | Redes Soportadas | Confirmaciones Requeridas |
|
|
|--------|---------|------------------|---------------------------|
|
|
| Bitcoin | BTC | Bitcoin Network | 3 confirmaciones |
|
|
| Ethereum | ETH | Ethereum Mainnet | 12 confirmaciones |
|
|
| Tether | USDT | ERC-20, TRC-20 | 12 (ERC-20), 20 (TRC-20) |
|
|
| USD Coin | USDC | ERC-20, Polygon | 12 (ERC-20), 30 (Polygon) |
|
|
|
|
---
|
|
|
|
## Requisitos Funcionales
|
|
|
|
### RF-PAY-007.1: Generacion de Direcciones Unicas
|
|
|
|
**DEBE:**
|
|
1. Generar direccion unica de deposito por usuario por moneda/red
|
|
2. Asociar direccion a `userId` en tabla `crypto_addresses`
|
|
3. Mostrar QR code y direccion copiable en UI
|
|
4. Detectar red correcta segun direccion (ERC-20 vs TRC-20)
|
|
5. Reutilizar direccion para depositos futuros del mismo usuario
|
|
|
|
**Modelo de datos:**
|
|
```typescript
|
|
@Entity({ name: 'crypto_addresses', schema: 'billing' })
|
|
class CryptoAddress {
|
|
id: string; // UUID
|
|
userId: string; // FK a users
|
|
currency: string; // BTC, ETH, USDT
|
|
network: string; // bitcoin, ethereum, tron, polygon
|
|
address: string; // Direccion de deposito unica
|
|
derivationPath?: string; // Para HD wallets
|
|
isActive: boolean; // true
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
}
|
|
```
|
|
|
|
### RF-PAY-007.2: Deteccion y Procesamiento de Depositos
|
|
|
|
**DEBE:**
|
|
1. Monitorear direcciones via webhooks del proveedor (Coinbase/BitPay)
|
|
2. Detectar transacciones entrantes en tiempo real
|
|
3. Mostrar estado "Pendiente" con contador de confirmaciones
|
|
4. Convertir a USD al alcanzar confirmaciones requeridas
|
|
5. Acreditar al wallet interno del usuario
|
|
|
|
**Flujo de Confirmaciones:**
|
|
```
|
|
0 confirmaciones → Estado: DETECTED (detectado)
|
|
1 confirmacion → Estado: PENDING (pendiente)
|
|
3+ confirmaciones → Estado: CONFIRMED (BTC)
|
|
12+ confirmaciones → Estado: CONFIRMED (ETH/ERC-20)
|
|
20+ confirmaciones → Estado: CONFIRMED (TRC-20)
|
|
```
|
|
|
|
### RF-PAY-007.3: Conversion Automatica a USD
|
|
|
|
**DEBE:**
|
|
1. Obtener tasa de cambio en tiempo real al momento de confirmacion
|
|
2. Aplicar spread de 0.5% sobre tasa de mercado
|
|
3. Convertir monto crypto a USD equivalente
|
|
4. Acreditar USD al wallet interno
|
|
5. Registrar tasa de cambio usada en transaccion
|
|
|
|
**Calculo:**
|
|
```
|
|
USD_Amount = Crypto_Amount * Market_Rate * (1 - 0.005)
|
|
|
|
Ejemplo:
|
|
0.01 BTC * $45,000/BTC * 0.995 = $447.75 USD
|
|
```
|
|
|
|
### RF-PAY-007.4: Sistema de Retiros Crypto
|
|
|
|
**DEBE:**
|
|
1. Permitir retiros a wallet externo del usuario
|
|
2. Solicitar direccion de destino y red
|
|
3. Validar formato de direccion segun red
|
|
4. Calcular monto crypto segun tasa actual
|
|
5. Procesar retiro via API del proveedor
|
|
6. Enviar notificacion con TX hash
|
|
|
|
**Validaciones:**
|
|
- KYC aprobado obligatorio para retiros
|
|
- Monto minimo: $50 USD equivalente
|
|
- Monto maximo: $10,000 USD por transaccion
|
|
- Limite diario: $50,000 USD
|
|
- Cooldown: 24h para nuevas direcciones
|
|
|
|
### RF-PAY-007.5: Verificacion KYC para Retiros
|
|
|
|
**DEBE:**
|
|
1. Bloquear retiros crypto hasta completar KYC
|
|
2. Solicitar documentos: ID gubernamental + selfie + comprobante domicilio
|
|
3. Verificar via proveedor KYC (Jumio, Onfido)
|
|
4. Aprobar/rechazar en maximo 24 horas
|
|
5. Permitir retiros una vez aprobado
|
|
|
|
**Niveles KYC:**
|
|
| Nivel | Requisitos | Limite Retiro |
|
|
|-------|------------|---------------|
|
|
| Ninguno | Solo email | $0 (sin retiros) |
|
|
| Basico | ID + Selfie | $1,000/dia |
|
|
| Verificado | ID + Selfie + Domicilio | $50,000/dia |
|
|
|
|
### RF-PAY-007.6: Webhooks de Confirmaciones
|
|
|
|
**DEBE:**
|
|
1. Recibir webhooks de Coinbase Commerce/BitPay
|
|
2. Validar firma HMAC del webhook
|
|
3. Actualizar estado de transaccion en BD
|
|
4. Emitir evento interno para procesamiento
|
|
5. Responder 200 OK inmediatamente (procesamiento async)
|
|
|
|
**Eventos a manejar:**
|
|
- `charge:created` - Transaccion detectada
|
|
- `charge:pending` - Esperando confirmaciones
|
|
- `charge:confirmed` - Confirmaciones completas
|
|
- `charge:failed` - Transaccion fallida/expirada
|
|
|
|
---
|
|
|
|
## Modelo de Datos
|
|
|
|
### Tabla: crypto_transactions
|
|
|
|
```typescript
|
|
@Entity({ name: 'crypto_transactions', schema: 'billing' })
|
|
class CryptoTransaction {
|
|
id: string; // UUID
|
|
userId: string; // FK a users
|
|
walletId: string; // FK a wallets
|
|
type: 'deposit' | 'withdrawal';
|
|
status: CryptoTxStatus; // detected, pending, confirmed, failed, expired
|
|
currency: string; // BTC, ETH, USDT
|
|
network: string; // bitcoin, ethereum, tron, polygon
|
|
cryptoAmount: Decimal; // Monto en crypto
|
|
usdAmount: Decimal; // Monto en USD (convertido)
|
|
exchangeRate: Decimal; // Tasa de cambio usada
|
|
fromAddress?: string; // Direccion origen (depositos)
|
|
toAddress: string; // Direccion destino
|
|
txHash?: string; // Hash de transaccion on-chain
|
|
confirmations: number; // Confirmaciones actuales
|
|
requiredConfirmations: number; // Confirmaciones requeridas
|
|
providerRef: string; // ID en Coinbase/BitPay
|
|
fee?: Decimal; // Fee de red
|
|
metadata?: object;
|
|
createdAt: Date;
|
|
confirmedAt?: Date;
|
|
updatedAt: Date;
|
|
}
|
|
|
|
enum CryptoTxStatus {
|
|
DETECTED = 'detected',
|
|
PENDING = 'pending',
|
|
CONFIRMED = 'confirmed',
|
|
FAILED = 'failed',
|
|
EXPIRED = 'expired'
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Flujo de Deposito Crypto
|
|
|
|
```
|
|
+-------------+ +-------------+ +-------------+ +-------------+ +-------------+
|
|
| Usuario | | Frontend | | Backend | | Coinbase | | Blockchain |
|
|
+------+------+ +------+------+ +------+------+ +------+------+ +------+------+
|
|
| | | | |
|
|
| Selecciona | | | |
|
|
| "Depositar BTC" | | | |
|
|
|------------------>| | | |
|
|
| | | | |
|
|
| | GET /crypto/ | | |
|
|
| | address?currency= | | |
|
|
| | BTC&network=bitcoin| | |
|
|
| |------------------>| | |
|
|
| | | | |
|
|
| | | Get/Create | |
|
|
| | | unique address | |
|
|
| | |------------------>| |
|
|
| | |<------------------| |
|
|
| | | | |
|
|
| |<------------------| | |
|
|
| | { address, qrCode } | |
|
|
| | | | |
|
|
|<------------------| | | |
|
|
| Muestra QR + | | | |
|
|
| direccion | | | |
|
|
| | | | |
|
|
| Usuario envia | | | |
|
|
| 0.01 BTC desde | | | |
|
|
| su wallet externo | | | |
|
|
|---------------------------------------------------------->|----------------->|
|
|
| | | | |
|
|
| | | | TX broadcast |
|
|
| | | |<-----------------|
|
|
| | | | |
|
|
| | |<------------------| |
|
|
| | | Webhook: | |
|
|
| | | charge:created | |
|
|
| | | | |
|
|
| | | Create | |
|
|
| | | crypto_transaction| |
|
|
| | | status: DETECTED | |
|
|
| | | | |
|
|
|<------------------|-------------------| | |
|
|
| Push: "Deposito | | | |
|
|
| detectado, 0/3 | | | |
|
|
| confirmaciones" | | | |
|
|
| | | | |
|
|
| | |<------------------| |
|
|
| | | Webhook: | |
|
|
| | | charge:confirmed | |
|
|
| | | (3 confirmations) | |
|
|
| | | | |
|
|
| | | BEGIN TX | |
|
|
| | | 1. Get exchange | |
|
|
| | | rate | |
|
|
| | | 2. Convert to USD | |
|
|
| | | 3. Credit wallet | |
|
|
| | | 4. Update status | |
|
|
| | | COMMIT TX | |
|
|
| | | | |
|
|
|<------------------|-------------------| | |
|
|
| Push: "Deposito | | | |
|
|
| confirmado! | | | |
|
|
| +$447.75 USD" | | | |
|
|
| | | | |
|
|
```
|
|
|
|
---
|
|
|
|
## Flujo de Retiro Crypto
|
|
|
|
```
|
|
+-------------+ +-------------+ +-------------+ +-------------+
|
|
| Usuario | | Frontend | | Backend | | Coinbase |
|
|
+------+------+ +------+------+ +------+------+ +------+------+
|
|
| | | |
|
|
| Click "Retirar | | |
|
|
| a Crypto" | | |
|
|
|------------------>| | |
|
|
| | | |
|
|
| | GET /user/kyc | |
|
|
| |------------------>| |
|
|
| |<------------------| |
|
|
| | { status: | |
|
|
| | "verified" } | |
|
|
| | | |
|
|
| Ingresa: | | |
|
|
| - $200 USD | | |
|
|
| - BTC | | |
|
|
| - bc1q...xyz | | |
|
|
|------------------>| | |
|
|
| | | |
|
|
| | POST /crypto/ | |
|
|
| | withdraw | |
|
|
| | { amount: 200, | |
|
|
| | currency: "BTC",| |
|
|
| | address: "bc1q..| |
|
|
| | network: "bitcoin"} |
|
|
| |------------------>| |
|
|
| | | |
|
|
| | | 1. Validate KYC |
|
|
| | | 2. Validate addr |
|
|
| | | 3. Check limits |
|
|
| | | 4. Get rate |
|
|
| | | 5. Calculate BTC |
|
|
| | | ($200 = 0.0044)|
|
|
| | | |
|
|
| | | 6. Debit wallet |
|
|
| | | 7. Create pending |
|
|
| | | withdrawal |
|
|
| | | |
|
|
| | | 8. Request payout |
|
|
| | |------------------>|
|
|
| | |<------------------|
|
|
| | | { payoutId } |
|
|
| | | |
|
|
| |<------------------| |
|
|
| | { status: "pending", |
|
|
| | cryptoAmount: 0.0044, |
|
|
| | estimatedTime: "30min" } |
|
|
| | | |
|
|
|<------------------| | |
|
|
| "Retiro procesando| | |
|
|
| 0.0044 BTC a | | |
|
|
| bc1q...xyz" | | |
|
|
| | | |
|
|
| | |<------------------|
|
|
| | | Webhook: |
|
|
| | | payout:completed |
|
|
| | | txHash: 0xabc... |
|
|
| | | |
|
|
|<------------------|-------------------| |
|
|
| Email: "Retiro | | |
|
|
| completado! | | |
|
|
| TX: 0xabc..." | | |
|
|
| | | |
|
|
```
|
|
|
|
---
|
|
|
|
## Reglas de Negocio
|
|
|
|
### RN-001: Limites de Deposito
|
|
|
|
| Limite | Valor |
|
|
|--------|-------|
|
|
| Deposito minimo | $10 USD equivalente |
|
|
| Deposito maximo por transaccion | $50,000 USD equivalente |
|
|
| Deposito maximo diario | $100,000 USD equivalente |
|
|
| Sin limite mensual | - |
|
|
|
|
### RN-002: Limites de Retiro
|
|
|
|
| Limite | Sin KYC | KYC Basico | KYC Verificado |
|
|
|--------|---------|------------|----------------|
|
|
| Por transaccion | $0 | $1,000 | $10,000 |
|
|
| Diario | $0 | $1,000 | $50,000 |
|
|
| Mensual | $0 | $5,000 | $200,000 |
|
|
|
|
### RN-003: Fees y Spreads
|
|
|
|
| Concepto | Valor |
|
|
|----------|-------|
|
|
| Deposito | GRATIS (usuario paga fee de red) |
|
|
| Spread conversion | 0.5% |
|
|
| Retiro fee fijo | $5 USD |
|
|
| Retiro fee red | Variable (estimado mostrado) |
|
|
|
|
### RN-004: Expiracion de Transacciones
|
|
|
|
- Depositos no confirmados expiran en **72 horas**
|
|
- Retiros pendientes expiran en **24 horas**
|
|
- Transacciones expiradas se marcan como `EXPIRED`
|
|
- Fondos de retiros expirados se devuelven al wallet
|
|
|
|
### RN-005: Direcciones de Retiro
|
|
|
|
- Primera vez: direccion debe esperar 24h antes de usar
|
|
- Direcciones usadas previamente: retiro inmediato
|
|
- Maximo 5 direcciones guardadas por moneda
|
|
- Cambio de direccion requiere 2FA
|
|
|
|
---
|
|
|
|
## Integracion con Proveedores
|
|
|
|
### Coinbase Commerce (Recomendado)
|
|
|
|
```typescript
|
|
// Configuracion
|
|
const coinbase = new CoinbaseCommerce({
|
|
apiKey: process.env.COINBASE_API_KEY,
|
|
webhookSecret: process.env.COINBASE_WEBHOOK_SECRET
|
|
});
|
|
|
|
// Crear charge para deposito
|
|
const charge = await coinbase.charges.create({
|
|
name: `Deposito ${userId}`,
|
|
description: 'Deposito a wallet trading-platform',
|
|
pricing_type: 'no_price', // Usuario decide monto
|
|
metadata: {
|
|
userId,
|
|
walletId,
|
|
type: 'deposit'
|
|
}
|
|
});
|
|
```
|
|
|
|
### BitPay (Alternativa)
|
|
|
|
```typescript
|
|
// Configuracion
|
|
const bitpay = new BitPayClient({
|
|
token: process.env.BITPAY_TOKEN,
|
|
environment: 'prod'
|
|
});
|
|
|
|
// Crear invoice para deposito
|
|
const invoice = await bitpay.createInvoice({
|
|
price: 0, // Variable
|
|
currency: 'USD',
|
|
buyer: { email: user.email },
|
|
posData: JSON.stringify({ userId, walletId })
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
## API Endpoints
|
|
|
|
### Depositos
|
|
|
|
```yaml
|
|
GET /api/v1/crypto/deposit/address:
|
|
description: Obtener direccion de deposito
|
|
query:
|
|
currency: string (BTC, ETH, USDT)
|
|
network: string (bitcoin, ethereum, tron, polygon)
|
|
response:
|
|
address: string
|
|
qrCode: string (base64)
|
|
currency: string
|
|
network: string
|
|
minDeposit: number
|
|
|
|
GET /api/v1/crypto/deposit/status/{txId}:
|
|
description: Estado de deposito
|
|
response:
|
|
status: string
|
|
confirmations: number
|
|
requiredConfirmations: number
|
|
cryptoAmount: number
|
|
usdAmount: number
|
|
txHash: string
|
|
```
|
|
|
|
### Retiros
|
|
|
|
```yaml
|
|
POST /api/v1/crypto/withdraw:
|
|
description: Solicitar retiro crypto
|
|
body:
|
|
amount: number (USD)
|
|
currency: string
|
|
network: string
|
|
address: string
|
|
response:
|
|
withdrawalId: string
|
|
cryptoAmount: number
|
|
exchangeRate: number
|
|
fee: number
|
|
estimatedTime: string
|
|
|
|
GET /api/v1/crypto/withdraw/{id}:
|
|
description: Estado de retiro
|
|
response:
|
|
status: string
|
|
txHash: string
|
|
cryptoAmount: number
|
|
address: string
|
|
```
|
|
|
|
### Direcciones Guardadas
|
|
|
|
```yaml
|
|
GET /api/v1/crypto/addresses:
|
|
description: Listar direcciones de retiro guardadas
|
|
|
|
POST /api/v1/crypto/addresses:
|
|
description: Agregar direccion de retiro
|
|
body:
|
|
currency: string
|
|
network: string
|
|
address: string
|
|
label: string
|
|
|
|
DELETE /api/v1/crypto/addresses/{id}:
|
|
description: Eliminar direccion guardada
|
|
```
|
|
|
|
---
|
|
|
|
## Seguridad
|
|
|
|
### Validacion de Direcciones
|
|
|
|
```typescript
|
|
function validateCryptoAddress(address: string, network: string): boolean {
|
|
switch (network) {
|
|
case 'bitcoin':
|
|
// Legacy (1...), SegWit (3...), Native SegWit (bc1...)
|
|
return /^(1|3)[a-zA-Z0-9]{25,34}$|^bc1[a-z0-9]{39,59}$/.test(address);
|
|
case 'ethereum':
|
|
case 'polygon':
|
|
// ERC-20 format
|
|
return /^0x[a-fA-F0-9]{40}$/.test(address);
|
|
case 'tron':
|
|
// TRC-20 format
|
|
return /^T[a-zA-Z0-9]{33}$/.test(address);
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
```
|
|
|
|
### Prevencion de Fraude
|
|
|
|
- Monitorear patrones de deposito/retiro inusuales
|
|
- Bloquear retiros inmediatos post-deposito (1h cooldown)
|
|
- Verificar consistencia de direcciones (no reutilizar entre usuarios)
|
|
- Alerta si retiro > 50% del deposito reciente
|
|
- Require 2FA para retiros > $1,000
|
|
|
|
### Hot/Cold Wallet
|
|
|
|
- Hot wallet: maximo 10% de fondos totales
|
|
- Cold wallet: 90% de fondos en almacenamiento offline
|
|
- Rebalanceo automatico diario
|
|
- Multi-sig para cold wallet (3 de 5 firmas)
|
|
|
|
---
|
|
|
|
## Manejo de Errores
|
|
|
|
| Error | Codigo | Mensaje Usuario |
|
|
|-------|--------|-----------------|
|
|
| KYC no verificado | 403 | Completa la verificacion de identidad para retirar |
|
|
| Direccion invalida | 400 | La direccion ingresada no es valida para {network} |
|
|
| Limite excedido | 400 | Excedes el limite de ${limit}/dia. Intenta manana. |
|
|
| Saldo insuficiente | 400 | Saldo insuficiente. Disponible: ${balance} |
|
|
| Red no soportada | 400 | La red {network} no esta soportada para {currency} |
|
|
| Direccion muy nueva | 400 | Nueva direccion. Espera 24h antes de usarla. |
|
|
| Proveedor no disponible | 503 | Servicio temporalmente no disponible. Intenta mas tarde. |
|
|
|
|
---
|
|
|
|
## Webhooks Recibidos
|
|
|
|
| Evento | Accion |
|
|
|--------|--------|
|
|
| `charge:created` | Crear crypto_transaction con status DETECTED |
|
|
| `charge:pending` | Actualizar confirmaciones |
|
|
| `charge:confirmed` | Convertir a USD, acreditar wallet |
|
|
| `charge:failed` | Marcar como FAILED |
|
|
| `payout:completed` | Actualizar retiro con txHash |
|
|
| `payout:failed` | Revertir debito de wallet |
|
|
|
|
---
|
|
|
|
## Configuracion Requerida
|
|
|
|
```env
|
|
# Coinbase Commerce
|
|
COINBASE_API_KEY=xxx
|
|
COINBASE_WEBHOOK_SECRET=xxx
|
|
|
|
# BitPay (alternativo)
|
|
BITPAY_TOKEN=xxx
|
|
BITPAY_WEBHOOK_SECRET=xxx
|
|
|
|
# Limites
|
|
CRYPTO_DEPOSIT_MIN_USD=10
|
|
CRYPTO_DEPOSIT_MAX_USD=50000
|
|
CRYPTO_DEPOSIT_MAX_DAILY_USD=100000
|
|
CRYPTO_WITHDRAWAL_MIN_USD=50
|
|
CRYPTO_WITHDRAWAL_FEE_USD=5
|
|
CRYPTO_CONVERSION_SPREAD=0.005
|
|
|
|
# Confirmaciones
|
|
CRYPTO_CONFIRMATIONS_BTC=3
|
|
CRYPTO_CONFIRMATIONS_ETH=12
|
|
CRYPTO_CONFIRMATIONS_TRC20=20
|
|
CRYPTO_CONFIRMATIONS_POLYGON=30
|
|
|
|
# Seguridad
|
|
CRYPTO_NEW_ADDRESS_COOLDOWN_HOURS=24
|
|
CRYPTO_POST_DEPOSIT_COOLDOWN_HOURS=1
|
|
```
|
|
|
|
---
|
|
|
|
## Criterios de Aceptacion
|
|
|
|
- [ ] Usuario puede obtener direccion unica de deposito por moneda/red
|
|
- [ ] QR code se genera correctamente para cada direccion
|
|
- [ ] Depositos se detectan via webhook en tiempo real
|
|
- [ ] Contador de confirmaciones se actualiza correctamente
|
|
- [ ] Conversion a USD aplica spread de 0.5%
|
|
- [ ] Wallet se acredita automaticamente al confirmar deposito
|
|
- [ ] Usuario sin KYC no puede retirar
|
|
- [ ] Usuario con KYC puede retirar hasta su limite
|
|
- [ ] Validacion de direcciones funciona para todas las redes
|
|
- [ ] Retiros se procesan y notifican con TX hash
|
|
- [ ] Limites diarios se aplican correctamente
|
|
- [ ] Cooldown de 24h para nuevas direcciones funciona
|
|
- [ ] Transacciones no confirmadas expiran en 72h
|
|
|
|
---
|
|
|
|
## Especificacion Tecnica Relacionada
|
|
|
|
- [ET-PAY-007: Crypto Integration](../especificaciones/ET-PAY-007-crypto.md)
|
|
|
|
## Historias de Usuario Relacionadas
|
|
|
|
- [US-PAY-020: Depositar Crypto](../historias-usuario/US-PAY-020-depositar-crypto.md)
|
|
- [US-PAY-021: Retirar Crypto](../historias-usuario/US-PAY-021-retirar-crypto.md)
|
|
- [US-PAY-022: Ver Estado Deposito](../historias-usuario/US-PAY-022-estado-deposito.md)
|