Estado: Completado y validado con transacciones on-chain reales en Stellar Testnet. Arquitectura: Hexagonal (Puertos y Adaptadores / Clean Architecture) Propósito: Validar el flujo de conversión fiat ↔ USDC sobre Stellar, aislando la lógica de negocio de la infraestructura (SDK, APIs de anchor, exportación).
- Resumen Ejecutivo
- Arquitectura Hexagonal
- Estructura del Repositorio
- Entorno de Pruebas
- Cuentas y Credenciales de Testnet
- Evidencia On-Chain (Transacciones Reales)
- 🔗 Enlaces de Verificación en Stellar Expert (Testnet)
- Todo lo Verificado (Checklist de Evidencia)
- Resultados por Fase
- Cómo Ejecutar el Laboratorio
- Consideraciones Arquitectónicas
- Consideraciones de Cumplimiento (KYC/AML)
- Consideraciones de Riesgo (Ramp Gap)
- Limitaciones Encontradas
- API de Puertos (Interfaces)
- Licencia y Uso
Este laboratorio valida el ciclo completo de una rampa cripto-fiat sobre Stellar Testnet usando arquitectura hexagonal, lo que permite intercambiar adaptadores (MockProvider, Anchor SDF real, Horizon SDK) sin modificar la lógica de negocio.
| Flujo | Dirección | Estado | Evidencia |
|---|---|---|---|
| On-Ramp | Fiat simulado → USDC | URL SEP-24 generada | src/entrypoints/lab-onramp-sdf.js |
| Off-Ramp | USDC → Cuenta testnet (on-chain real) | ✅ Ejecutado y verificado | src/entrypoints/lab-offramp-usdc-real.js |
| Off-Ramp Demo | XLM nativo → Anchor SDF | ✅ Ejecutado | src/entrypoints/lab-onramp-sdf.js |
| Off-Ramp Mock | USDC → BRL/MXN/ARS | ✅ settled (3 monedas) |
src/entrypoints/lab-multimoneda.js |
Conclusión clave: La conversión fiat ↔ USDC sobre Stellar es técnicamente viable usando SEP-6/SEP-24 y trustlines. El punto crítico no es la blockchain, sino la configuración del anchor (trustlines, KYC, rieles fiat).
El repositorio sigue el patrón Puertos y Adaptadores (Hexagonal Architecture), separando la lógica de negocio del dominio de las preocupaciones de infraestructura.
graph TD
subgraph EP["ENTRY POINTS"]
EP1[lab-offramp-usdc-real.js]
EP2[lab-onramp-sdf.js]
EP3[lab-multimoneda.js]
end
subgraph APP["APLICACION"]
UC1[OnRampUseCase]
UC2[OffRampUseCase]
end
subgraph DOM["DOMINIO"]
E1[RampOrder]
E2[RampQuote]
E3[StellarAccount]
S1[RampService]
P1[RampProvider puerto]
P2[StellarGateway puerto]
P3[AuthProvider puerto]
end
subgraph INF["INFRAESTRUCTURA"]
A1[StellarHorizonAdapter]
A2[MockRampAdapter]
A3[SdfRampAdapter]
A4[CsvJsonExporter]
A5[NetworkConfig]
end
subgraph EXT["EXTERNO"]
X1[(Stellar Testnet / Horizon)]
X2[Anchor SDF testanchor.stellar.org]
X3[Friendbot]
end
EP1 --> UC2
EP2 --> UC1
EP3 --> UC1
EP3 --> UC2
UC1 --> P1
UC1 --> P2
UC2 --> P1
UC2 --> P2
P1 --> A2
P1 --> A3
P2 --> A1
P3 --> A3
A1 --> X1
A1 --> X3
A3 --> X2
A4 -->|exporta JSON/CSV| FS[(archivos resultados)]
style DOM fill:#e1f5fe,stroke:#01579b
style APP fill:#fff3e0,stroke:#e65100
style INF fill:#f3e5f5,stroke:#4a148c
style EP fill:#e8f5e9,stroke:#1b5e20
style EXT fill:#ffebee,stroke:#b71c1c
graph LR
subgraph DOM["DOMINIO"]
D[Dominio]
end
subgraph APP["APLICACION"]
A[Aplicacion]
end
subgraph INF["INFRAESTRUCTURA"]
I[Infraestructura]
end
subgraph EP["ENTRY POINTS"]
E[Entry Points]
end
A --> D
I --> D
I --> A
E --> A
E --> I
style DOM fill:#e1f5fe,stroke:#01579b
style APP fill:#fff3e0,stroke:#e65100
style INF fill:#f3e5f5,stroke:#4a148c
style EP fill:#e8f5e9,stroke:#1b5e20
Regla: Las flechas indican dependencia. El dominio no depende de nada; la aplicacion depende solo del dominio (a traves de puertos); la infraestructura implementa los puertos del dominio; los entry points ensamblan aplicacion e infraestructura.
sequenceDiagram
autonumber
participant U as Usuario / Lab
participant EP as Entry Point
participant UC as OnRampUseCase
participant RP as RampProvider
participant SG as StellarGateway
participant X as Stellar Testnet / Anchor SDF
U->>EP: Ejecutar script con monto fiat
EP->>UC: execute(direction: onramp, ...)
UC->>RP: getQuote(fiat, asset, amount)
RP-->>UC: RampQuote (tasa, fee, expiracion)
UC->>RP: createOrder(quote)
RP-->>UC: RampOrder (awaiting_deposit)
UC->>RP: simulateFiatReceived(orderId)
RP-->>X: Simular deposito fiat (sandbox)
loop Polling hasta settled
UC->>RP: getOrder(orderId)
RP-->>UC: status (processing -> settled)
end
UC-->>EP: Resultado (orden settled + txHash + rampGap)
EP-->>U: Mostrar resultado + exportar CSV/JSON
note over U,X: Anchor real SDF: el usuario abre URL SEP-24 interactiva<br/>y completa KYC (SEP-12) manualmente
sequenceDiagram
autonumber
participant U as Usuario / Lab
participant EP as Entry Point
participant UC as OffRampUseCase
participant RP as RampProvider
participant SG as StellarGateway
participant X as Stellar Testnet
U->>EP: Ejecutar script con monto USDC
EP->>UC: execute(direction: offramp, ...)
UC->>RP: getQuote(fiat, asset, usdcAmount)
RP-->>UC: RampQuote (tasa, fee, monto fiat destino)
UC->>RP: createOrder(quote)
RP-->>UC: RampOrder (processing)
UC->>SG: sendPayment(secretKey, destination, USDC, amount, memo)
SG->>X: Transaccion on-chain (Horizon Testnet)
X-->>SG: Tx hash confirmado
SG-->>UC: txHash + status
UC->>RP: simulateFiatPayout(orderId) (sandbox)
RP-->>X: Simular pago fiat de salida
loop Polling hasta settled
UC->>RP: getOrder(orderId)
RP-->>UC: status (processing -> settled)
end
UC-->>EP: Resultado (orden settled + txHash on-chain)
EP-->>U: Mostrar resultado + exportar CSV/JSON
note over SG,X: El envio USDC es una transaccion real<br/>verificable en Stellar Expert Testnet
sequenceDiagram
autonumber
participant U as Usuario
participant EP as Entry Point
participant UC as OffRampUseCase
participant SG as StellarGateway
participant A as Anchor SDF
participant X as Stellar Testnet
U->>EP: Enviar USDC al anchor SDF
EP->>SG: sendPayment(USDC, anchorAccount, 5)
SG->>X: Transaccion on-chain
X-->>SG: Error 400 Bad Request
SG-->>UC: Excepcion (anchor sin trustline USDC)
UC-->>EP: Fallo reportado
EP-->>U: Alternativa: enviar XLM nativo (demo)
SG->>X: Transaccion 1 XLM al anchor (exitosa)
X-->>SG: Tx hash confirmado
SG-->>UC: Demo completado
UC-->>EP: Resultado mixto (USDC fallo, XLM OK)
EP-->>U: Limitacion documentada en README
note over A,X: El Anchor SDF no tiene trustline al USDC de Circle.<br/>Ambos extremos deben confiar en el mismo activo.
graph TD
subgraph DOM["DOMINIO"]
RO[RampOrder]
RQ[RampQuote]
SA[StellarAccount]
RS[RampService]
RP[RampProvider puerto]
SG[StellarGateway puerto]
AP[AuthProvider puerto]
end
subgraph INF["INFRAESTRUCTURA"]
SHA[StellarHorizonAdapter]
MRA[MockRampAdapter]
SRA[SdfRampAdapter]
CJE[CsvJsonExporter]
NC[NetworkConfig]
end
subgraph EXT["EXTERNO"]
HZ[Horizon Testnet]
FB[Friendbot]
AN[Anchor SDF]
end
RP --> MRA
RP --> SRA
SG --> SHA
AP --> SRA
SHA --> HZ
SHA --> FB
SRA --> AN
DOM -.-> INF
INF --> EXT
style DOM fill:#e1f5fe,stroke:#01579b
style INF fill:#f3e5f5,stroke:#4a148c
style EXT fill:#ffebee,stroke:#b71c1c
Contiene las entidades de negocio y los puertos (interfaces). Es independiente de cualquier librería externa.
| Entidad | Archivo | Responsabilidad |
|---|---|---|
RampOrder |
src/domain/entities/RampOrder.js |
Orden de rampa (on-ramp/off-ramp), estados, métodos de consulta (isSettled, isPending, isFailed). |
RampQuote |
src/domain/entities/RampQuote.js |
Cotización de rampa (tipo de cambio, fee, monto objetivo, expiración). |
StellarAccount |
src/domain/entities/StellarAccount.js |
Cuenta Stellar con balances, verificación de trustlines y saldo por activo. |
| Puerto | Archivo | Contrato |
|---|---|---|
RampProvider |
src/domain/ports/RampProvider.js |
listAssets, getQuote, createOrder, getOrder, simulateFiatReceived, simulateFiatPayout, cancelOrder. |
StellarGateway |
src/domain/ports/StellarGateway.js |
fundAccount, createTrustline, getTrustlineBalance, sendPayment, loadAccount. |
AuthProvider |
src/domain/ports/AuthProvider.js |
authenticate (SEP-10). |
| Servicio | Archivo | Responsabilidad |
|---|---|---|
RampService |
src/domain/services/RampService.js |
Lógica pura: cálculo de monto neto, validación de estados, cálculo de Ramp Gap, validación de montos. |
Contiene los casos de uso que orquestan el flujo de negocio usando únicamente puertos.
| Caso de Uso | Archivo | Flujo |
|---|---|---|
OnRampUseCase |
src/application/usecases/OnRampUseCase.js |
Cotización → creación de orden → simulación de fiat → polling hasta settled. |
OffRampUseCase |
src/application/usecases/OffRampUseCase.js |
Cotización → creación de orden → envío on-chain → simulación de payout fiat → polling. |
Implementa los puertos con tecnología concreta.
| Adaptador | Archivo | Puerto Implementado | Tecnología |
|---|---|---|---|
StellarHorizonAdapter |
src/infrastructure/adapters/stellar/StellarHorizonAdapter.js |
StellarGateway |
@stellar/stellar-sdk + Horizon Testnet |
MockRampAdapter |
src/infrastructure/adapters/ramp/MockRampAdapter.js |
RampProvider |
@ramp-kit/core (MockProvider) |
SdfRampAdapter |
src/infrastructure/adapters/ramp/SdfRampAdapter.js |
AuthProvider |
REST → testanchor.stellar.org (SEP-10) |
CsvJsonExporter |
src/infrastructure/adapters/export/CsvJsonExporter.js |
(exportación) | Node.js fs |
NetworkConfig |
src/infrastructure/config/NetworkConfig.js |
(config) | Constantes de red, assets, límites |
| Script | Archivo | Propósito |
|---|---|---|
| Off-Ramp USDC Real | src/entrypoints/lab-offramp-usdc-real.js |
Envía 20 USDC on-chain de cuenta origen a cuenta destino con trustline. |
| On-Ramp SDF | src/entrypoints/lab-onramp-sdf.js |
Autenticación SEP-10 + generación de URL SEP-24 interactiva. |
| Multi-Moneda Mock | src/entrypoints/lab-multimoneda.js |
BRL, MXN, ARS → USDC en sandbox (settled). |
LabRAMPS/
├── README.md # Documentación completa
├── .gitignore # node_modules, logs, etc.
├── package.json # Dependencias (@stellar/stellar-sdk, @ramp-kit/core, node-fetch)
├── package-lock.json
├── lab-rampa-stellar/ # Laboratorio refactorizado (arquitectura hexagonal)
│ ├── src/
│ │ ├── domain/
│ │ │ ├── entities/
│ │ │ │ ├── RampOrder.js
│ │ │ │ ├── RampQuote.js
│ │ │ │ └── StellarAccount.js
│ │ │ ├── ports/
│ │ │ │ ├── RampProvider.js
│ │ │ │ ├── StellarGateway.js
│ │ │ │ └── AuthProvider.js
│ │ │ └── services/
│ │ │ └── RampService.js
│ │ ├── application/
│ │ │ ├── dto/
│ │ │ └── usecases/
│ │ │ ├── OnRampUseCase.js
│ │ │ └── OffRampUseCase.js
│ │ ├── infrastructure/
│ │ │ ├── adapters/
│ │ │ │ ├── stellar/
│ │ │ │ │ └── StellarHorizonAdapter.js
│ │ │ │ ├── ramp/
│ │ │ │ │ ├── MockRampAdapter.js
│ │ │ │ │ └── SdfRampAdapter.js
│ │ │ │ └── export/
│ │ │ │ └── CsvJsonExporter.js
│ │ │ └── config/
│ │ │ └── NetworkConfig.js
│ │ └── entrypoints/
│ │ ├── lab-offramp-usdc-real.js
│ │ ├── lab-onramp-sdf.js
│ │ └── lab-multimoneda.js
│ └── *.csv / *.json # Resultados exportados por ejecución
└── lab-rampa-stellar/ (versión anterior, raíz) # Scripts originales (referencia)
├── lab.js
├── lab-multimoneda.js
├── lab-sdf-real.js
├── lab-usdc-offramp-real.js
├── lab-srt-offramp.js
└── *.csv / *.json
| Elemento | Valor |
|---|---|
| Red | Stellar Testnet |
| Horizon | https://horizon-testnet.stellar.org |
| Friendbot | https://friendbot.stellar.org?addr=<public_key> |
| Anchor SDF | https://testanchor.stellar.org |
| Explorador | https://stellar.expert/explorer/testnet |
| Passphrase | Test SDF Network ; September 2015 |
| SDK | @stellar/stellar-sdk (Node.js) |
| Ramp Kit | @ramp-kit/core (MockProvider) |
| Asset | Code | Issuer | Red |
|---|---|---|---|
| USDC (Circle) | USDC |
GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5 |
Testnet |
| SRT (SDF) | SRT |
GCDNJUBQSX7AJWLJACMJ7I4BC3Z47BQUTMHEICZLE6MU4KQBRYG5JY6B |
Testnet |
| XLM (nativo) | native |
— | Testnet |
| Campo | Valor |
|---|---|
| Pública | GA67L2Q2P57MNL6SMDWIVKZVGQN7KN4N43IHM6EHQ3YYWNY2B753C7EW |
| Seed (privada) | SCQNLSLDBNYGBVEHX26H476HZRFC74LFOH6H2FSKDWRLRQ6ONVIAZAJZ |
| Uso | Cuenta de origen para off-ramp USDC real |
⚠️ Nota: Esta cuenta se usó para enviar 20 USDC en la validación on-chain. Para reejecutar el off-ramp real, debe fondearse nuevamente con USDC de Circle (testnet faucet).
| Campo | Valor |
|---|---|
| Pública | GCSGSR6KQQ5BP2FXVPWRL6SWPUSFWLVONLIBJZUKTVQB5FYJFVL6XOXE |
| Origen | stellar.toml de testanchor.stellar.org |
| Nota | Cuenta pública del anchor. No se tiene su seed privada. |
Todas las transacciones son verificables en Stellar Expert Testnet.
| Campo | Valor |
|---|---|
| Tx Hash | 89fb30c0e86a6e6b96a2c72f716588214f249e7bf46c724c88322e062a204378 |
| Origen | GA67L2Q2P57MNL6SMDWIVKZVGQN7KN4N43IHM6EHQ3YYWNY2B753C7EW |
| Destino | GDSASZROO2FMJ3J2W6XRGFRUNWHNFE3SFAAA2HC2UVEZRFZGZDTEECLV |
| Activo | USDC (Circle) |
| Monto | 20.0000000 USDC |
| Memo | LAB-OFFRAMP-USDC-REAL |
| Saldo origen (antes) | 20.0000000 USDC |
| Saldo origen (después) | 0.0000000 USDC |
| Saldo destino (después) | 20.0000000 USDC |
| Explorador | https://stellar.expert/explorer/testnet/tx/89fb30c0e86a6e6b96a2c72f716588214f249e7bf46c724c88322e062a204378 |
| Campo | Valor |
|---|---|
| Tx Hash | 8e0f8e57318410807eeba8a829d83af471457a8d23569cfcb01e9fc4afbc713f |
| Origen | GA67L2Q2P57MNL6SMDWIVKZVGQN7KN4N43IHM6EHQ3YYWNY2B753C7EW |
| Destino | GCSGSR6KQQ5BP2FXVPWRL6SWPUSFWLVONLIBJZUKTVQB5FYJFVL6XOXE (Anchor SDF) |
| Activo | XLM (nativo) |
| Monto | 1.0000000 XLM |
| Campo | Valor |
|---|---|
| Tx Hash | 0ab8e45f9a446f6bfafe42079d8c5c5101c10aeccfed94458b3ab5e8922a3b0c |
| Cuenta | GDSASZROO2FMJ3J2W6XRGFRUNWHNFE3SFAAA2HC2UVEZRFZGZDTEECLV |
| Activo | USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5 |
| Campo | Valor |
|---|---|
| Tx Hash | 7dac7d2b20038a832791a3cb2626af16e38202f5f73ed87fa3f989d39cf45922 |
| Cuenta | GA67L2Q2P57MNL6SMDWIVKZVGQN7KN4N43IHM6EHQ3YYWNY2B753C7EW |
| Activo | SRT:GCDNJUBQSX7AJWLJACMJ7I4BC3Z47BQUTMHEICZLE6MU4KQBRYG5JY6B |
Todos los links apuntan a Stellar Expert Testnet (https://stellar.expert/explorer/testnet) y son verificables públicamente.
| # | Transacción | Descripción | Link |
|---|---|---|---|
| 1 | 89fb30c0e86a6e6b96a2c72f716588214f249e7bf46c724c88322e062a204378 |
Off-Ramp USDC Real – Envío de 20 USDC (Circle) desde cuenta origen a cuenta destino con trustline USDC. | Ver en Stellar Expert |
| 2 | 8e0f8e57318410807eeba8a829d83af471457a8d23569cfcb01e9fc4afbc713f |
Off-Ramp XLM Demo – Envío de 1 XLM nativo desde cuenta origen al Anchor SDF (GCSGSR6KQQ5BP2FXVPWRL6SWPUSFWLVONLIBJZUKTVQB5FYJFVL6XOXE). |
Ver en Stellar Expert |
| 3 | 0ab8e45f9a446f6bfafe42079d8c5c5101c10aeccfed94458b3ab5e8922a3b0c |
Trustline USDC (Cuenta Destino) – Creación de trustline a USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5 en la cuenta destino del off-ramp. | Ver en Stellar Expert |
| 4 | 7dac7d2b20038a832791a3cb2626af16e38202f5f73ed87fa3f989d39cf45922 |
Trustline SRT (Cuenta Origen) – Creación de trustline a SRT:GCDNJUBQSX7AJWLJACMJ7I4BC3Z47BQUTMHEICZLE6MU4KQBRYG5JY6B en la cuenta persistente. | Ver en Stellar Expert |
| # | Cuenta Pública | Descripción | Link |
|---|---|---|---|
| 1 | GA67L2Q2P57MNL6SMDWIVKZVGQN7KN4N43IHM6EHQ3YYWNY2B753C7EW |
Cuenta Origen (Persistente) – Cuenta de testnet con XLM y USDC, usada como origen en el off-ramp real. | Ver cuenta |
| 2 | GDSASZROO2FMJ3J2W6XRGFRUNWHNFE3SFAAA2HC2UVEZRFZGZDTEECLV |
Cuenta Destino (Off-Ramp USDC) – Cuenta creada con Friendbot, trustline USDC, recibió 20 USDC en el off-ramp real. | Ver cuenta |
| 3 | GCSGSR6KQQ5BP2FXVPWRL6SWPUSFWLVONLIBJZUKTVQB5FYJFVL6XOXE |
Anchor SDF – Cuenta pública del Anchor de referencia de SDF en testnet (según su stellar.toml). |
Ver cuenta |
- Creación de cuenta destino vía Friendbot (fondado con XLM de testnet)
- Trustline USDC en cuenta destino – tx:
0ab8e45f...(ver arriba) - Off-ramp USDC on-chain real – 20 USDC enviados de
GA67L2Q...aGDSASZR..., tx:89fb30c0...(ver arriba) - Saldo origen USDC: 20.0000000 → 0.0000000 (verificado en cuenta origen)
- Saldo destino USDC: 0.0000000 → 20.0000000 (verificado en cuenta destino)
- Off-ramp XLM nativo al Anchor SDF – 1 XLM enviado, tx:
8e0f8e57...(ver arriba) - Trustline SRT en cuenta origen – tx:
7dac7d2b...(ver arriba) - Autenticación SEP-10 con Anchor SDF – Token recibido correctamente de
testanchor.stellar.org
- On-Ramp BRL → USDC – 100 BRL → 18.8212927 USDC, estado
settled - Off-Ramp USDC → BRL – 10 USDC → 52.07 BRL, estado
settled - On-Ramp MXN → USDC – 100 MXN → 5.4395604 USDC, estado
settled - Off-Ramp USDC → MXN – 10 USDC → 180.18 MXN, estado
settled - On-Ramp ARS → USDC – 100 ARS → 0.0782608 USDC, estado
settled - Off-Ramp USDC → ARS – 10 USDC → 12523.50 ARS, estado
settled
- Arquitectura Hexagonal implementada – Domain (entidades, puertos, servicio), Application (use cases), Infrastructure (adaptadores), Entry Points
- Separación de dependencias – Domain no depende de infraestructura; Application depende solo de Domain
- Exportación de resultados – CSV y JSON generados para cada ejecución
- README completo – Documentación de arquitectura, cuentas, evidencia, consideraciones KYC/AML y Ramp Gap
Archivo: src/entrypoints/lab-onramp-sdf.js
| Evento | Resultado |
|---|---|
| Trustline USDC | ✅ Existente (saldo 20.0000000) |
| SEP-10 Auth | ✅ Token recibido |
| On-Ramp SEP-24 | ⏳ URL generada (pendiente acción manual en navegador) |
| Off-Ramp USDC → Anchor | ❌ 400 Bad Request (anchor no tiene trustline a USDC de Circle) |
| Off-Ramp XLM Demo | ✅ Tx: 8e0f8e57... |
Archivo: src/entrypoints/lab-offramp-usdc-real.js
| Evento | Resultado |
|---|---|
| Cuenta destino + Friendbot | ✅ Creada y fondeada |
| Trustline USDC destino | ✅ Creada |
| Envío 20 USDC on-chain | ✅ Tx: 89fb30c0... |
| Saldo origen final | 0.0000000 USDC |
| Saldo destino final | 20.0000000 USDC |
Archivo: src/entrypoints/lab-multimoneda.js
| Moneda | On-Ramp (Fiat → USDC) | Off-Ramp (USDC → Fiat) |
|---|---|---|
| BRL | 100 BRL → 18.8212927 USDC (fee 1.00 BRL) | 10 USDC → 52.07 BRL (fee 0.10 BRL) |
| MXN | 100 MXN → 5.4395604 USDC (fee 1.00 MXN) | 10 USDC → 180.18 MXN (fee 0.10 MXN) |
| ARS | 100 ARS → 0.0782608 USDC (fee 1.00 ARS) | 10 USDC → 12523.50 ARS (fee 0.10 ARS) |
Tasa efectiva: 0.190114 USDC/BRL, 0.054945 USDC/MXN, 0.000790 USDC/ARS
Estado: Todas las órdenes alcanzaron settled.
cd lab-rampa-stellar
npm installnode src/entrypoints/lab-offramp-usdc-real.jsRequisito previo: La cuenta origen debe tener XLM (fees) y USDC (Circle testnet).
- XLM:
https://friendbot.stellar.org?addr=GA67L2Q2P57MNL6SMDWIVKZVGQN7KN4N43IHM6EHQ3YYWNY2B753C7EW - USDC: Faucet oficial de Circle testnet → enviar a la cuenta origen.
node src/entrypoints/lab-onramp-sdf.jsResultado: Se imprime una URL SEP-24 interactiva. El usuario debe abrirla en el navegador, completar KYC (SEP-12) si es requerido, y simular el depósito fiat.
node src/entrypoints/lab-multimoneda.jsResultado: Ejecuta on-ramp y off-ramp para BRL, MXN y ARS en sandbox, exportando CSV/JSON.
- Dominio: No sabe de Stellar SDK, HTTP, ni archivos. Solo conoce entidades y puertos.
- Aplicación: Orquestra casos de uso pero no implementa detalles de red ni persistencia.
- Infraestructura: Contiene toda la tecnología concreta (SDK, HTTP, filesystem). Es reemplazable sin tocar dominio ni aplicación.
Los entrypoints ensamblan adaptadores concretos e inyectan dependencias en los casos de uso a través de sus constructores, respetando el principio de inversión de dependencias.
Cada capa puede probarse de forma aislada:
- Dominio: pruebas unitarias de
RampServicesin mocks de red. - Aplicación: pruebas con stubs de puertos.
- Infraestructura: pruebas de integración contra testnet o mocks HTTP.
Tanto remitente como destinatario deben tener una trustline activa al activo transferido. Sin ella, el pago falla en Horizon.
En producción, el anchor emite/acepta el activo anclado, gestiona rieles fiat (PIX, SPEI, SEPA, SWIFT), implementa KYC/AML (SEP-12) y opera servidores SEP-6/SEP-24.
| Consideración | Implementación en el Lab | Producción Real |
|---|---|---|
| Identidad de usuario | Simulado (pre-aprobado) | SEP-12, verificación de identidad |
| Límite por transacción | 5-20 USD (controlado por script) | Políticas del anchor, límites regulatorios |
| Memo para trazabilidad | LAB-ONRAMP-SDF, LAB-OFFRAMP-USDC-REAL |
Referencia de pago, ID de orden |
| Registro de transacciones | CSV/JSON exportados | Ledger del anchor, reportes regulatorios |
| PEP/Sanctions | No aplicado en sandbox | Listas de sanciones, screening |
Nota: El KYC se omitió intencionalmente en el sandbox para aislar la validación de la conversión pura. En producción, el orden quedaría bloqueado en
pending_user_transfer_starthasta aprobación de identidad.
| Riesgo | Descripción | Mitigación en el Lab |
|---|---|---|
| Fiat reversible vs. Cripto irreversible | El fiat puede devolverse (chargeback), el USDC no | Simulado como "pre-aprobado" |
| Anchor sin trustline al activo | El anchor no puede recibir el activo | Detectado (fallo 400 USDC → SDF) |
| Saldo insuficiente | Cuenta sin fondos para el envío | Verificado antes del envío |
| Webhook duplicado | Notificaciones duplicadas del anchor | Idempotencia por ID de orden |
El Ramp Gap es el lapso entre la confirmación fiat (reversible, lenta) y la entrega on-chain (irreversible, rápida). Es donde se concentra el riesgo operativo.
stateDiagram-v2
[*] --> Creada
Creada --> AwaitingDeposit : createOrder()
AwaitingDeposit --> Procesando : simulateFiatReceived() / pago on-chain
Procesando --> Settled : confirmación on-chain / fiat recibido
Procesando --> Fallido : error de proveedor / saldo insuficiente
Creada --> Cancelada : cancelOrder()
AwaitingDeposit --> Cancelada : cancelOrder()
Procesando --> Cancelada : cancelOrder()
Fallido --> [*]
Settled --> [*]
Cancelada --> [*]
state Creada {
[*] --> OrdenAceptada
OrdenAceptada --> CotizacionValida : quote valida
CotizacionValida --> [*]
}
state Procesando {
[*] --> Intercambiando
Intercambiando --> Liquidando
Liquidando --> [*]
}
state Settled {
[*] --> FondosDisponibles
FondosDisponibles --> [*] : tx confirmada en blockchain
}
state Fallido {
[*] --> MotivoRechazo
MotivoRechazo --> [*]
}
Estados explicados:
| Estado | Descripción | Cuándo se usa |
|---|---|---|
Creada |
Orden aceptada por el proveedor de rampa | Después de createOrder() |
AwaitingDeposit |
Esperando depósito fiat (on-ramp) o cripto (off-ramp) | Usuario debe enviar fondos |
Procesando |
Proveedor está intercambiando y liquidando | Entre recepción de fondos y entrega |
Settled |
Orden completada, fondos entregados | Transacción on-chain confirmada |
Fallido |
Orden terminó con error | Saldo insuficiente, error de proveedor, etc. |
Cancelada |
Orden cancelada por usuario o proveedor | cancelOrder() invocado |
- Conversión fiat ↔ USDC es técnicamente viable sobre Stellar Testnet usando SEP-6 y SEP-24.
- SEP-10 autenticación funciona correctamente con el Anchor de referencia de SDF (
testanchor.stellar.org). - Trustlines son prerequisito obligatorio tanto en el remitente como en el destinatario para cualquier transferencia de activo emitido (USDC, SRT, etc.).
- Transacciones on-chain son verificables públicamente en Stellar Expert Testnet con hash de transacción.
- Arquitectura Hexagonal permite intercambiar proveedores de rampa (MockProvider, Anchor SDF, Etherfuse, etc.) sin modificar la lógica de negocio.
| Fallo | Causa raíz | Lección para producción |
|---|---|---|
| Off-ramp USDC → Anchor SDF | El anchor no tiene trustline al USDC de Circle | Ambos extremos del intercambio deben configurar trustline al mismo activo antes de operar |
| On-ramp SEP-24 requiere interacción manual | El endpoint interactivo del anchor necesita navegador y KYC | En producción, se debe integrar el flujo web del anchor o usar SEP-6 directo |
| SRT sin saldo | No hay faucet público de SRT testnet | Para pruebas reales se necesita fondeo previo del activo de prueba |
- Gestión de trustlines: El sistema debe verificar y crear trustlines automáticamente antes de intentar cualquier pago.
- Manejo de errores de anchor: Un anchor puede rechazar una transacción por falta de configuración (trustline, límites, KYC pendiente). La aplicación debe manejar estos errores con reintentos o notificación al usuario.
- Ramp Gap: El lapso entre confirmación fiat (reversible) y entrega on-chain (irreversible) es el punto de mayor riesgo operativo. Se debe monitorear y reconciliar.
- Idempotencia: Las notificaciones webhook del anchor pueden llegar duplicadas; el sistema debe procesarlas de forma idempotente.
- Separación de responsabilidades: La arquitectura hexagonal demostró ser adecuada para aislar la complejidad de múltiples proveedores de rampa (Mock, SDF, Etherfuse, etc.).
- Anchor SDF sin trustline a USDC de Circle: No se pudo completar el off-ramp USDC directo al anchor SDF. Se envió XLM nativo como demo en su lugar.
- KYC no automatizado: El on-ramp requiere acción manual en el navegador del anchor (SEP-24 interactivo).
- SRT sin saldo: Se creó trustline a SRT pero no había saldo para enviar.
- No hay faucet público de SRT testnet encontrado durante el lab.
Copia este archivo como .env y ajusta los valores según tu entorno de pruebas:
# =============================================================================
# Configuración de Red Stellar
# =============================================================================
STELLAR_NETWORK=testnet
HORIZON_URL=https://horizon-testnet.stellar.org
FRIENDBOT_URL=https://friendbot.stellar.org
NETWORK_PASSPHRASE=Test SDF Network ; September 2015
# =============================================================================
# Cuenta de Origen (Persistente)
# =============================================================================
ORIGIN_SECRET_KEY=SCQNLSLDBNYGBVEHX26H476HZRFC74LFOH6H2FSKDWRLRQ6ONVIAZAJZ
ORIGIN_PUBLIC_KEY=GA67L2Q2P57MNL6SMDWIVKZVGQN7KN4N43IHM6EHQ3YYWNY2B753C7EW
# =============================================================================
# Activos Soportados
# =============================================================================
USDC_CODE=USDC
USDC_ISSUER=GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5
SRT_CODE=SRT
SRT_ISSUER=GCDNJUBQSX7AJWLJACMJ7I4BC3Z47BQUTMHEICZLE6MU4KQBRYG5JY6B
# =============================================================================
# Anchor SDF (Testnet)
# =============================================================================
ANCHOR_BASE_URL=https://testanchor.stellar.org
ANCHOR_HOME_DOMAIN=testanchor.stellar.org
ANCHOR_ACCOUNT=GCSGSR6KQQ5BP2FXVPWRL6SWPUSFWLVONLIBJZUKTVQB5FYJFVL6XOXE
# =============================================================================
# Límites de Seguridad (Testnet)
# =============================================================================
MAX_AMOUNT_PER_TRANSACTION=10
DEFAULT_TRANSACTION_FEE=100
# =============================================================================
# Exportación de Resultados
# =============================================================================
RESULTS_OUTPUT_DIR=./lab-rampa-stellar
EXPORT_FORMAT=json,csv
⚠️ Nota de seguridad: Nunca commitees un archivo.envcon claves privadas reales en un repositorio público. Este archivo es solo para entornos de prueba (testnet).
Todos los archivos se encuentran en lab-rampa-stellar/:
| Archivo | Contenido |
|---|---|
lab-rampa-stellar-sdf-results.json |
Resultados SEP-10 auth + on-ramp URL (JSON) |
lab-rampa-stellar-sdf-results.csv |
Resultados SEP-10 auth + on-ramp URL (CSV) |
lab-rampa-stellar-usdc-offramp-real-results.json |
Off-ramp USDC on-chain (JSON) |
lab-rampa-stellar-usdc-offramp-real-results.csv |
Off-ramp USDC on-chain (CSV) |
lab-rampa-stellar-srt-results.json |
Trustline SRT + intento off-ramp (JSON) |
lab-rampa-stellar-srt-results.csv |
Trustline SRT + intento off-ramp (CSV) |
lab-rampa-stellar-multimoneda-results.json |
MockProvider BRL/MXN/ARS (JSON) |
lab-rampa-stellar-multimoneda-results.csv |
MockProvider BRL/MXN/ARS (CSV) |
Este laboratorio es de uso educativo y de tesis. Todas las claves y cuentas son de Testnet (no mainnet). No usar claves de producción en este entorno.
Generado: 2026-11-10
Red: Stellar Testnet
Arquitectura: Hexagonal (Puertos y Adaptadores)
Estado: Listo para tesis
SDK: @stellar/stellar-sdk + @ramp-kit/core
Evidencia: Transacciones on-chain verificables en Stellar Expert Testnet