trading-platform/docs/02-definicion-modulos/OQI-005-payments-stripe/requerimientos/RF-PAY-009-p2p.md
rckrdmrd a7cca885f0 feat: Major platform documentation and architecture updates
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>
2026-01-07 05:33:35 -06:00

20 KiB

id title type status priority epic project version created_date updated_date
RF-PAY-009 Sistema de Transferencias P2P Requirement Draft Media OQI-005 trading-platform 1.0.0 2026-01-04 2026-01-04

RF-PAY-009: Sistema de Transferencias P2P

Version: 1.0.0 Fecha: 2026-01-04 Estado: Draft Prioridad: P2 (Media) Story Points: 5 Epica: OQI-005


Descripcion

El sistema debe permitir a los usuarios realizar transferencias de fondos peer-to-peer (P2P) entre wallets internos de la plataforma, de manera instantanea y sin comisiones. Los usuarios podran enviar dinero a otros usuarios identificandolos por email, username o wallet ID.


Objetivo de Negocio

  • Fomentar comunidad activa y engagement entre usuarios
  • Facilitar pagos entre traders (apuestas amistosas, compartir senales)
  • Reducir friccion para onboarding de nuevos usuarios (amigos invitan)
  • Retener fondos dentro del ecosistema (no salen a bancos)
  • Habilitar futuros marketplaces internos (venta de cursos, senales)

Casos de Uso

  1. Envio por Email: Usuario A envia $50 USD a usuario B usando su email
  2. Envio por Username: Usuario A envia $100 USD a @trader_pro
  3. Envio por Wallet ID: Usuario A pega wallet ID y envia $25 USD
  4. Con Mensaje: Usuario A envia $10 USD con nota "Para el cafe de ayer"
  5. Recepcion: Usuario B recibe notificacion y ve fondos en wallet
  6. Historial: Usuario revisa todas las transferencias enviadas/recibidas

Requisitos Funcionales

RF-PAY-009.1: Identificacion de Destinatario

DEBE:

  1. Buscar usuario por email exacto
  2. Buscar usuario por username (con o sin @)
  3. Buscar usuario por wallet ID (UUID corto de 8 caracteres)
  4. Mostrar preview del destinatario antes de confirmar
  5. Validar que destinatario tiene cuenta activa

Preview de destinatario:

Enviar a:
+---------------------------+
| @trader_pro               |
| Juan P****z               |  (nombre parcialmente oculto)
| Miembro desde 2024        |
| [x] Cuenta verificada     |
+---------------------------+

RF-PAY-009.2: Creacion de Transferencia

DEBE:

  1. Validar saldo suficiente en wallet del remitente
  2. Validar monto dentro de limites ($1 - $5,000)
  3. Validar limite diario acumulado ($10,000)
  4. Permitir mensaje opcional (max 140 caracteres)
  5. Requerir 2FA para montos > $500 USD

Modelo de datos:

@Entity({ name: 'p2p_transfers', schema: 'billing' })
class P2PTransfer {
  id: string;                    // UUID
  shortId: string;               // ID corto 8 chars para referencia
  senderId: string;              // FK a users
  senderWalletId: string;        // FK a wallets
  receiverId: string;            // FK a users
  receiverWalletId: string;      // FK a wallets
  amount: Decimal;               // Monto en USD
  message?: string;              // Mensaje opcional (140 chars max)
  status: P2PTransferStatus;     // pending, completed, failed, reversed
  requires2FA: boolean;          // true si amount > 500
  verified2FA: boolean;          // true si 2FA completado
  createdAt: Date;
  completedAt?: Date;
  updatedAt: Date;
}

enum P2PTransferStatus {
  PENDING = 'pending',       // Esperando 2FA
  COMPLETED = 'completed',   // Transferido exitosamente
  FAILED = 'failed',         // Error en proceso
  REVERSED = 'reversed'      // Revertido por admin
}

RF-PAY-009.3: Procesamiento de Transferencia

DEBE:

  1. Debitar wallet del remitente atomicamente
  2. Acreditar wallet del destinatario atomicamente
  3. Crear registros en wallet_transactions para ambos
  4. Marcar transferencia como completed
  5. Emitir eventos para notificaciones

Transaccion atomica:

await db.transaction(async (tx) => {
  // 1. Lock wallets en orden consistente (evitar deadlock)
  const [senderWallet, receiverWallet] = await Promise.all([
    tx.wallet.findOne({ id: senderWalletId }, { lock: true }),
    tx.wallet.findOne({ id: receiverWalletId }, { lock: true })
  ]);

  // 2. Validar saldo
  if (senderWallet.balance < amount) {
    throw new InsufficientFundsError();
  }

  // 3. Debitar remitente
  await tx.walletTransaction.create({
    walletId: senderWallet.id,
    type: 'debit',
    amount: -amount,
    reference: transferId,
    description: `Transferencia P2P a ${receiverUsername}`
  });
  await tx.wallet.decrement(senderWallet.id, 'balance', amount);

  // 4. Acreditar destinatario
  await tx.walletTransaction.create({
    walletId: receiverWallet.id,
    type: 'credit',
    amount: amount,
    reference: transferId,
    description: `Transferencia P2P de ${senderUsername}`
  });
  await tx.wallet.increment(receiverWallet.id, 'balance', amount);

  // 5. Actualizar estado
  await tx.p2pTransfer.update(transferId, {
    status: 'completed',
    completedAt: new Date()
  });
});

RF-PAY-009.4: Verificacion 2FA

DEBE:

  1. Requerir 2FA para transferencias > $500 USD
  2. Soportar TOTP (Google Authenticator)
  3. Soportar SMS como fallback
  4. Codigo valido por 5 minutos
  5. Maximo 3 intentos fallidos

Flujo 2FA:

1. Usuario crea transferencia de $600
2. Backend crea transfer con status: PENDING, requires2FA: true
3. Frontend muestra modal de 2FA
4. Usuario ingresa codigo
5. Backend valida codigo
6. Si valido: procesar transferencia
7. Si invalido: incrementar intentos, bloquear si > 3

RF-PAY-009.5: Notificaciones

DEBE:

  1. Push notification instantanea al destinatario
  2. Email de confirmacion a ambas partes
  3. In-app notification en historial
  4. Mostrar mensaje del remitente si existe

Contenido de notificacion (destinatario):

@juan_trader te envio $50.00 USD

"Para el cafe de ayer"

Tu nuevo saldo: $150.00 USD

Contenido de notificacion (remitente):

Transferencia exitosa

Enviaste $50.00 USD a @trader_pro
Referencia: ABC12345
Tu nuevo saldo: $200.00 USD

RF-PAY-009.6: Historial de Transferencias

DEBE:

  1. Mostrar transferencias enviadas y recibidas
  2. Filtrar por tipo (enviadas/recibidas/todas)
  3. Filtrar por rango de fechas
  4. Buscar por destinatario/remitente
  5. Mostrar mensaje asociado

Vista de historial:

+--------------------------------------------+
| Transferencias P2P                         |
+--------------------------------------------+
| [Todas] [Enviadas] [Recibidas]             |
+--------------------------------------------+
| 04 Ene 2026  @trader_pro                   |
| Enviado     -$50.00 USD    "Para el cafe"  |
+--------------------------------------------+
| 03 Ene 2026  @maria_fx                     |
| Recibido    +$100.00 USD   "Gracias!"      |
+--------------------------------------------+
| 02 Ene 2026  @carlos_btc                   |
| Enviado     -$25.00 USD                    |
+--------------------------------------------+

Flujo de Transferencia P2P

+-------------+     +-------------+     +-------------+     +-------------+
|  Remitente  |     |  Frontend   |     |   Backend   |     | Destinatario|
+------+------+     +------+------+     +------+------+     +------+------+
       |                   |                   |                   |
       | Click "Enviar     |                   |                   |
       | Dinero"           |                   |                   |
       |------------------>|                   |                   |
       |                   |                   |                   |
       | Ingresa:          |                   |                   |
       | - @trader_pro     |                   |                   |
       | - $50 USD         |                   |                   |
       | - "Para el cafe"  |                   |                   |
       |------------------>|                   |                   |
       |                   |                   |                   |
       |                   | GET /users/lookup |                   |
       |                   | ?q=@trader_pro    |                   |
       |                   |------------------>|                   |
       |                   |<------------------|                   |
       |                   | { username,       |                   |
       |                   |   displayName,    |                   |
       |                   |   walletId }      |                   |
       |                   |                   |                   |
       |<------------------|                   |                   |
       | Preview:          |                   |                   |
       | "Juan P****z"     |                   |                   |
       |                   |                   |                   |
       | Confirma          |                   |                   |
       |------------------>|                   |                   |
       |                   |                   |                   |
       |                   | POST /p2p/transfer|                   |
       |                   | { receiverId,     |                   |
       |                   |   amount: 50,     |                   |
       |                   |   message }       |                   |
       |                   |------------------>|                   |
       |                   |                   |                   |
       |                   |                   | 1. Validate user  |
       |                   |                   | 2. Validate       |
       |                   |                   |    balance        |
       |                   |                   | 3. Validate       |
       |                   |                   |    limits         |
       |                   |                   | 4. Check 2FA req  |
       |                   |                   |    ($50 < $500)   |
       |                   |                   |    NO 2FA needed  |
       |                   |                   |                   |
       |                   |                   | BEGIN TX          |
       |                   |                   | - Debit sender    |
       |                   |                   | - Credit receiver |
       |                   |                   | - Create records  |
       |                   |                   | COMMIT TX         |
       |                   |                   |                   |
       |                   |<------------------|                   |
       |                   | { status:         |                   |
       |                   |   "completed",    |                   |
       |                   |   transferId }    |                   |
       |                   |                   |                   |
       |<------------------|                   |------------------>|
       | "Enviado!"        |                   | Push: "Recibiste  |
       |                   |                   | $50 de @juan"     |
       |                   |                   |                   |
       |<------------------|                   |------------------>|
       | Email:            |                   | Email:            |
       | Confirmacion      |                   | Confirmacion      |
       |                   |                   |                   |

Flujo con 2FA (Monto > $500)

+-------------+     +-------------+     +-------------+
|  Remitente  |     |  Frontend   |     |   Backend   |
+------+------+     +------+------+     +------+------+
       |                   |                   |
       | Enviar $600 a     |                   |
       | @trader_pro       |                   |
       |------------------>|                   |
       |                   |                   |
       |                   | POST /p2p/transfer|
       |                   | { amount: 600 }   |
       |                   |------------------>|
       |                   |                   |
       |                   |                   | Detecta: amount >
       |                   |                   | $500, requiere 2FA
       |                   |                   |
       |                   |                   | Crear transfer:
       |                   |                   | status: PENDING
       |                   |                   | requires2FA: true
       |                   |                   |
       |                   |<------------------|
       |                   | { transferId,     |
       |                   |   requires2FA:    |
       |                   |   true }          |
       |                   |                   |
       |<------------------|                   |
       | Modal: "Ingresa   |                   |
       | codigo 2FA"       |                   |
       |                   |                   |
       | Ingresa: 123456   |                   |
       |------------------>|                   |
       |                   |                   |
       |                   | POST /p2p/transfer|
       |                   | /{id}/verify      |
       |                   | { code: 123456 }  |
       |                   |------------------>|
       |                   |                   |
       |                   |                   | Validar TOTP
       |                   |                   | Procesar transfer
       |                   |                   |
       |                   |<------------------|
       |                   | { status:         |
       |                   |   "completed" }   |
       |                   |                   |
       |<------------------|                   |
       | "Enviado!"        |                   |
       |                   |                   |

Reglas de Negocio

RN-001: Limites de Transferencia

Limite Valor
Monto minimo $1.00 USD
Monto maximo por transferencia $5,000.00 USD
Limite diario acumulado $10,000.00 USD
Limite mensual Sin limite

RN-002: Comisiones

Concepto Fee
Transferencia P2P 0% (gratis)
Sin fees ocultos -

RN-003: Seguridad 2FA

Monto Requiere 2FA
$0 - $500 No
$500.01+ Si

RN-004: Restricciones

  • No se puede enviar a si mismo
  • Ambas cuentas deben estar activas
  • No se permite enviar a cuentas suspendidas
  • Wallet del remitente debe tener saldo suficiente
  • No se pueden revertir transferencias (excepto admin)

RN-005: Mensajes

  • Mensaje opcional
  • Maximo 140 caracteres
  • No se permiten URLs
  • Filtro de palabras prohibidas
  • Mensaje visible para ambas partes

API Endpoints

Buscar Usuario

GET /api/v1/users/lookup:
  description: Buscar usuario para transferencia P2P
  query:
    q: string (email, username o walletId)
  response:
    id: string
    username: string
    displayName: string (parcialmente oculto)
    walletId: string
    verified: boolean
    memberSince: string

Crear Transferencia

POST /api/v1/p2p/transfers:
  description: Crear transferencia P2P
  body:
    receiverId: string
    amount: number
    message?: string
  response:
    transferId: string
    shortId: string
    status: string
    requires2FA: boolean
    amount: number
    receiver:
      username: string
      displayName: string

Verificar 2FA

POST /api/v1/p2p/transfers/{id}/verify:
  description: Verificar 2FA para transferencia pendiente
  body:
    code: string (6 digitos)
  response:
    transferId: string
    status: "completed"
    completedAt: string

Historial de Transferencias

GET /api/v1/p2p/transfers:
  description: Listar transferencias P2P del usuario
  query:
    type: string (sent | received | all)
    page: number
    limit: number
    dateFrom: string
    dateTo: string
  response:
    data:
      - id: string
        shortId: string
        type: string (sent | received)
        amount: number
        otherUser:
          username: string
          displayName: string
        message: string
        status: string
        createdAt: string
    pagination:
      total: number
      page: number
      pages: number

Detalle de Transferencia

GET /api/v1/p2p/transfers/{id}:
  description: Obtener detalle de una transferencia
  response:
    id: string
    shortId: string
    type: string
    amount: number
    message: string
    status: string
    sender:
      username: string
      displayName: string
    receiver:
      username: string
      displayName: string
    createdAt: string
    completedAt: string

Seguridad

Prevencion de Fraude

  • Rate limit: maximo 10 transferencias por hora
  • Alerta si multiples transferencias al mismo destinatario
  • Bloqueo temporal si patron sospechoso
  • Monitoreo de transferencias circulares (A→B→A)
  • Limite diario reduce riesgo de robo de cuenta

Validaciones

async function validateP2PTransfer(
  senderId: string,
  receiverId: string,
  amount: number
): Promise<ValidationResult> {
  // 1. No enviar a si mismo
  if (senderId === receiverId) {
    throw new Error('No puedes enviarte dinero a ti mismo');
  }

  // 2. Destinatario existe y activo
  const receiver = await userRepo.findOne({ id: receiverId });
  if (!receiver || receiver.status !== 'active') {
    throw new Error('Usuario no encontrado o inactivo');
  }

  // 3. Saldo suficiente
  const wallet = await walletRepo.findOne({ userId: senderId });
  if (wallet.balance < amount) {
    throw new Error(`Saldo insuficiente. Disponible: $${wallet.balance}`);
  }

  // 4. Dentro de limites
  if (amount < 1 || amount > 5000) {
    throw new Error('Monto debe ser entre $1 y $5,000 USD');
  }

  // 5. Limite diario
  const todayTotal = await getDailyTransferTotal(senderId);
  if (todayTotal + amount > 10000) {
    throw new Error(`Excedes limite diario. Disponible hoy: $${10000 - todayTotal}`);
  }

  return { valid: true, requires2FA: amount > 500 };
}

Auditoria

  • Log de todas las transferencias
  • Guardar IP y User-Agent del remitente
  • Registro de intentos fallidos de 2FA
  • Alertas a seguridad por patrones anomalos

Manejo de Errores

Error Codigo Mensaje Usuario
Usuario no encontrado 404 No encontramos un usuario con ese email/username
Cuenta inactiva 403 Este usuario no puede recibir transferencias
Saldo insuficiente 400 Saldo insuficiente. Tienes $X disponible
Monto muy bajo 400 El monto minimo es $1 USD
Monto muy alto 400 El monto maximo por transferencia es $5,000 USD
Limite diario 400 Has alcanzado tu limite diario de $10,000
Auto-transferencia 400 No puedes enviarte dinero a ti mismo
2FA invalido 401 Codigo 2FA incorrecto. Te quedan X intentos
2FA expirado 401 Codigo expirado. Solicita uno nuevo
Rate limit 429 Demasiadas transferencias. Espera 1 hora

Configuracion Requerida

# Limites P2P
P2P_TRANSFER_MIN_USD=1
P2P_TRANSFER_MAX_USD=5000
P2P_TRANSFER_DAILY_LIMIT_USD=10000
P2P_2FA_THRESHOLD_USD=500

# Rate Limits
P2P_MAX_TRANSFERS_PER_HOUR=10
P2P_MAX_TRANSFERS_PER_DAY=50

# 2FA
P2P_2FA_CODE_EXPIRY_MINUTES=5
P2P_2FA_MAX_ATTEMPTS=3

# Mensajes
P2P_MESSAGE_MAX_LENGTH=140

Metricas de Negocio

KPIs a Rastrear

  • Transferencias P2P/dia: Numero de transferencias completadas
  • Volumen P2P/dia: Total transferido en USD
  • Usuarios activos P2P: Usuarios unicos que envian/reciben
  • Ticket promedio: Monto promedio por transferencia
  • Ratio envio/recepcion: Balance de actividad
  • Tasa de conversion 2FA: % de transferencias >$500 completadas

Criterios de Aceptacion

  • Usuario puede buscar destinatario por email
  • Usuario puede buscar destinatario por username
  • Usuario puede buscar destinatario por wallet ID
  • Preview muestra nombre parcialmente oculto
  • Transferencia de $50 se procesa sin 2FA
  • Transferencia de $600 requiere 2FA
  • Saldo se actualiza instantaneamente en ambos wallets
  • Mensaje opcional se muestra a destinatario
  • Push notification llega al destinatario
  • Email de confirmacion llega a ambas partes
  • Historial muestra transferencias enviadas y recibidas
  • Limites de monto se validan correctamente
  • Limite diario se calcula correctamente
  • No se permite enviar a si mismo
  • No se permite enviar a cuenta suspendida

Especificacion Tecnica Relacionada

Historias de Usuario Relacionadas