Skip to content

Ecossistema

Esta pagina documenta o fluxo de ponta a ponta da plataforma ProCases: desde o momento em que o usuario deposita dinheiro real ate a entrega de uma skin CS2 real na conta Steam do usuario.


Visao Macro: De Dinheiro Real a Skin Real

O Ciclo Completo

EtapaAcaoDeParaComunicacao
1Usuario paga via PIXBancoHorsePayPIX (instantaneo)
2HorsePay confirma pagamentoHorsePayBackendWebhook HTTP
3Usuario aposta (caixa, batalha, upgrade)SaldoMotor PFInterno (Redlock + Double-Entry)
4Resultado provably fair gera itemMotor PFInventarioInterno (Prisma Transaction)
5Usuario solicita saque de itemInventarioWaxpeerREST API
6Vendedor envia trade offer no SteamWaxpeerSteamWebSocket + Polling

O dinheiro real entra (HorsePay), transforma-se em saldo digital, o saldo gera items virtuais via sistema provably fair, e os items virtuais sao convertidos em skins reais via Waxpeer.


Etapa 1: Deposito (HorsePay PIX)

Como funciona

  1. Iniciacao: Usuario escolhe valor e metodo PIX. Backend cria pedido na HorsePay via OAuth e recebe codigo PIX + QR code.

  2. Pagamento: Usuario paga no app do banco. HorsePay processa instantaneamente.

  3. Confirmacao: HorsePay envia webhook para nosso endpoint publico (POST /payment/deposit/webhook/horsepay). Backend valida o payload, encontra o deposito pelo client_reference_id, e confirma.

  4. Creditacao: Dentro de uma transacao atomica com distributed lock:

    • Cria double-entry (CREDIT para usuario, DEBIT para sistema)
    • Aplica bonus de cupom quando aplicavel (valor x bonusPercentage)
    • Distribui tickets de sorteio (1 por R$ 30)
    • Distribui tickets de evento (250 por ticket de sorteio)
    • Atualiza cache de saldo
  5. Notificacao: WebSocket emite saldo atualizado e confirmacao para o frontend em tempo real.

Integridade garantida por

  • Distributed Lock: Previne processamento duplo do mesmo webhook
  • Double-Entry: Credito ao usuario = Debito ao sistema (soma zero)
  • Status PENDING → CONFIRMED: Deposito so e processado uma vez
  • Unique constraint: Deposit.externalId previne duplicatas do HorsePay

Etapa 2: Aposta (Motor Provably Fair)

Modos de aposta

ModoFluxoProvably Fair
Abertura de CaixaPaga preco → Roll → Item1 roll por abertura
Sistema FLIPRoll ≥ flipThreshold da caixa → tier raro (roleta dupla é visual)1 roll único (threshold por caixa)
Batalha PvPN jogadores abrem mesmas caixas → Time com maior valor vence1 roll por jogador por round
UpgradeInveste item/saldo → Roll determina sucesso1 roll, threshold baseado na chance
SorteioCompra tickets → Draw provably fair1 roll por premio

O que torna provably fair

  1. Antes do jogo: Backend gera serverSeed e envia o commitment HMAC-SHA256(serverSeed, '') ao usuario
  2. Usuario define: clientSeed (qualquer texto)
  3. Roll: HMAC-SHA256(serverSeed, clientSeed:nonce) → numero de 1 a 10.000.000
  4. Apos o jogo: serverSeed e revelado. Qualquer pessoa pode recalcular e verificar

Ninguem pode manipular: Backend nao conhece o clientSeed antes de gerar o serverSeed. Usuario nao conhece o serverSeed antes de definir o clientSeed.

Integridade garantida por

  • Distributed Lock: Uma operacao de saldo por usuario por vez
  • Double-Entry: Debito do preco da caixa e atomico com o resultado
  • BIGINT centavos: Zero erro de ponto flutuante nos calculos
  • Hash ranges: Cada item tem range fixo (1 a 10.000.000), probabilidades verificaveis
  • Seeds salvos no banco: Auditoria completa de cada resultado

Etapa 3: Item no Inventario Virtual

O inventario virtual e o elo entre o sistema de apostas e o mundo real. Cada item tem um marketHashName que corresponde exatamente ao nome do item no marketplace da Steam/Waxpeer.

O que o usuario pode fazer com um item

AcaoResultadoReversivel
VenderRecebe saldo em BRLNao
SacarRecebe skin real no SteamNao (apos trade aceita)
Usar em UpgradeCombina com saldo para item melhorNao
Usar em BatalhaCompete com outros jogadoresNao
Oferecer em SwapTroca por item do siteSim (ate aceitar)

Integridade garantida por

  • 7 status via Enum: Transicoes de estado controladas pelo banco
  • Locks distribuidos: Previne uso simultaneo do mesmo item
  • Unique constraints: Mesmo item nao pode estar em dois lugares
  • Cascade deletes: Integridade referencial automatica

Etapa 4: Saque - De Item Virtual a Skin Real (Waxpeer)

Esta e a etapa mais complexa do sistema. O item virtual precisa ser convertido em uma skin CS2 real e entregue na conta Steam do usuario.

Comunicacao bidirecional com Waxpeer

O sistema usa dois canais simultaneos para rastrear o status do saque:

Canal 1: WebSocket (tempo real)

Backend ←→ wss://waxpeer.com (Socket.io)

Evento: 'steamTrade'
Payload: {
  type: 'create' | 'update',
  data: {
    id: string,          // waxpeerId
    stage: 0-9,          // estagio do trade
    done: boolean,       // trade concluida
    is_released: boolean // item liberado
  }
}

O WebSocket recebe atualizacoes em tempo real assim que o status muda no Waxpeer. Conecta automaticamente ao iniciar o servico e reconecta em caso de desconexao (ate 10 tentativas com backoff exponencial).

Canal 2: Polling (fallback)

A cada 30 segundos:
  1. Busca withdrawals pendentes no banco (max 100)
  2. GET /v1/check-many-steam?id=123&id=456...
  3. Compara status atual com status salvo
  4. Atualiza se mudou

O polling garante que nenhum saque fique "perdido" mesmo se o WebSocket desconectar ou perder um evento.

Mapeamento de status Waxpeer → Sistema

Codigo WaxpeerSignificadoStatus no Sistema
0CriadoWAITING_SELLER
1Aguardando vendedorWAITING_SELLER
2Trade offer enviadaTRADE_SENT
3Trade aceitaTRADE_SENT
4Trade concluida no SteamCOMPLETED
5Liberado (confirmado)COMPLETED
6Falha/CancelamentoFAILED ou CANCELLED
done: trueConcluidoCOMPLETED
is_released: trueItem liberadoCOMPLETED

Protecao de preco

Antes de comprar no Waxpeer, o sistema verifica:

1. Nome exato do item (marketHashName) bate com o Waxpeer
2. Item tem estoque disponivel (count >= 1)
3. Preco no Waxpeer <= nosso preco original de compra

Se o preco subiu significativamente desde a compra original, o saque e bloqueado para proteger a casa de prejuizo.

Fluxo de estados do saque

PENDING          → Item locked, compra iniciada
WAITING_SELLER   → Compra OK, aguardando vendedor enviar trade
TRADE_SENT       → Trade offer enviada ao usuario no Steam
COMPLETED        → Trade aceita, item entregue ✓

FAILED           → Compra falhou (sem estoque, preco invalido)
CANCELLED        → Vendedor cancelou trade

Em caso de falha/cancelamento: Item retorna automaticamente ao inventario do usuario com status AVAILABLE.

Integridade garantida por

  • Distributed Lock (30s TTL): Previne saque duplicado do mesmo item
  • Status LOCKED: Item nao pode ser vendido/usado enquanto saque em andamento
  • Dual tracking: WebSocket + Polling garante que nenhum status e perdido
  • Protecao de preco: Verifica preco antes de comprar
  • Rollback automatico: Falha → item volta ao inventario

Por que Zero Gaps

O sistema e projetado para que nenhum dado se perca em nenhuma etapa:

Deposito

Cenario de falhaProtecao
Webhook recebido 2xDeposit.externalId unique constraint
Crash durante creditacaoPrisma transaction faz rollback automatico
Redis cai durante lockOperacao nao inicia (seguro por design)
HorsePay fora do arDeposito fica PENDING ate webhook chegar

Aposta

Cenario de falhaProtecao
Saldo insuficienteVerificado dentro da transacao atomica
Dois cliques simultaneosDistributed lock por usuario
Crash apos debitoTransacao atomica: debito + resultado sao uma unica operacao
Roll manipuladoHMAC-SHA256 com seeds publicos verificaveis

Saque

Cenario de falhaProtecao
Waxpeer fora do arItem permanece AVAILABLE, usuario tenta depois
Compra falhaItem volta de LOCKED para AVAILABLE
WebSocket desconectaPolling a cada 30s como fallback
Trade cancelada pelo vendedorStatus atualizado, item volta ao inventario
Trade expira (sendUntil)Waxpeer cancela automaticamente, polling detecta

Integridade financeira

Cenario de falhaProtecao
Saldo negativoImpossivel: verificacao atomica dentro da transacao
Dinheiro "sumiu"Impossivel: double-entry garante soma zero no sistema
Saldo divergenteSource of truth = SUM de transacoes (recalculavel)
Cache desatualizadoCache e complementar, saldo real sempre verificavel

Fluxo de Dados Completo


Tecnologias por Etapa

EtapaTecnologiasProtecoes
DepositoHorsePay REST + Webhook, Redis Lock, Prisma TXDouble-entry, unique constraint, lock
ApostaHMAC-SHA256, BigInt, Prisma TX, Redis LockProvably fair, range 1-10M, seeds verificaveis
InventarioPostgreSQL Enums, Partial Indexes7 status, locks distribuidos, cascade deletes
SaqueWaxpeer REST + WebSocket + PollingLock 30s, dual tracking, protecao de preco
AuditoriaSHA-256 hash chainingCadeia imutavel, verificacao automatica
ComunicacaoSocket.io + Redis AdapterBroadcast multi-instancia, reconexao automatica

Arquivos Fonte

Deposito

  • src/application/services/deposit.service.ts
  • src/infrastructure/payment/horsepay.provider.ts
  • src/presentation/controllers/payment.controller.ts

Motor de Apostas

  • src/application/services/provably-fair.service.ts
  • src/application/use-cases/case-opening/open-case.use-case.ts
  • src/application/use-cases/battle/execute-battle.use-case.ts
  • src/application/use-cases/upgrade/perform-upgrade.use-case.ts

Saque (Waxpeer)

  • src/application/use-cases/inventory/request-withdraw-item.use-case.ts
  • src/application/services/waxpeer-withdrawal-tracker.service.ts
  • src/infrastructure/external-apis/waxpeer.service.ts
  • src/infrastructure/external-apis/waxpeer-websocket.service.ts

Integridade

  • src/application/services/transaction.service.ts
  • src/infrastructure/locks/lock.service.ts
  • src/infrastructure/audit/audit.service.ts

Documentação Técnica - ProCases