Referencia general: Stellar Ecosystem Proposals (SEPs).
- SEP-0010 (Stellar Authentication): Autenticación recomendada. El usuario firma un challenge con su wallet; el backend verifica. No se piden claves ni frases en la web.
- SEP-0002, SEP-0004, SEP-0006: Federation, Tx Status y Deposit/Withdrawal — usados en backend o desde el front contra tu anchor (con JWT de SEP-0010).
- SEP-0005 (Key Derivation): Estándar para wallets que derivan claves desde mnemónico. Faro no pide frase de recuperación en la UI; la entrada es Entrar / Comenzar con el Stellar Wallet Kit (Freighter, xBull, etc.). Ver WALLET-SEP-0005.md.
- Qué hace: Resuelve direcciones tipo
nombre*dominio.comaaccount_id(y al revés, o portxid). - En Faro: Útil para mostrar “pagado a María*banco.com” en lugar de una cuenta G... y para validar destinatarios.
- Configuración: En tu backend/anchor debes tener un Federation Server (o usar uno existente). En
.envdel front:
NEXT_PUBLIC_FEDERATION_SERVER_URL=https://tu-federation-server.com- Uso en código:
import { resolveStellarAddress, resolveAccountId } from "@/lib/stellarsep"
const record = await resolveStellarAddress("bob*stellar.org")
// record.account_id, record.memo_type, record.memo- Qué hace: El receptor del pago expone
AUTH_SERVER/tx_status?id=tx_idy devuelve el estado del pago (pending, delivered, failed, refunded, etc.). - En Faro: Para que el usuario que envía vea si el pago ya fue recibido/entregado por la contraparte.
- Configuración: El receptor debe definir
AUTH_SERVERen sustellar.toml. En tu app (si tú eres el receptor o consultas a otro):
NEXT_PUBLIC_AUTH_SERVER_URL=https://auth.tu-anchor.com- Uso:
import { getTxStatus } from "@/lib/stellarsep"
const status = await getTxStatus("stellar_tx_hash...")
// status.status => "pending" | "delivered" | "failed" | ...- Qué hace: API estándar de depósitos y retiros (anchor). Endpoints:
/info,/deposit,/withdraw,/transaction,/transactions. - En Faro: Para flujos “depositar fiat → recibir token” y “enviar token → retirar fiat” desde tu anchor.
- Configuración: Tu anchor debe tener
TRANSFER_SERVERenstellar.tomle implementar los endpoints. En el front:
NEXT_PUBLIC_TRANSFER_SERVER_URL=https://transfer.tu-anchor.com- Uso:
import {
getTransferInfo,
getDeposit,
getWithdraw,
getTransaction,
getTransactions,
} from "@/lib/stellarsep"
const info = await getTransferInfo()
const deposit = await getDeposit(
{ asset_code: "USDC", account: "G...", funding_method: "WIRE" },
jwt
)
const tx = await getTransaction(deposit.id!, jwt)Nota: La autenticación JWT suele obtenerse con SEP-10. Implementa el flujo SEP-10 en tu backend y pasa el JWT a estas funciones.
- Qué es: Escrow sin custodia con hitos (milestones), aprobaciones y disputas. Contratos en Stellar Soroban, USDC.
- En Faro: Puedes usarlo para pagos entre inversor y PyME con liberación por hitos (por ejemplo: factura verificada → hito 1; factura cobrada → hito 2).
NEXT_PUBLIC_TRUSTLESS_WORK_API_URL=https://api.trustlesswork.com
TRUSTLESS_WORK_API_KEY=tu_api_key_si_la_api_lo_requiere
# Cuenta Stellar con USDC (trustline) para el rol platformAddress del escrow. En test puede ser tu wallet.
NEXT_PUBLIC_TRUSTLESS_WORK_PLATFORM_ADDRESS=- Las llamadas que modifican estado (crear escrow, aprobar milestone) deberían hacerse desde tu backend con
TRUSTLESS_WORK_API_KEYpara no exponer la clave. - Requisito USDC: La API exige que la cuenta usada como platformAddress (y disputeResolver) tenga USDC (trustline). Si no defines
NEXT_PUBLIC_TRUSTLESS_WORK_PLATFORM_ADDRESS, Faro usa la dirección del inversionista al crear el escrow, de modo que la misma wallet que financia tenga USDC.
Cuando un inversionista financia una factura (POST /api/invoices/[id]/invest), el backend crea un escrow en Trustless Work si:
- La factura tiene dirección Stellar del deudor (
debtorAddress): es la cuenta del negocio que pagará el nominal al vencimiento. - Están configuradas
NEXT_PUBLIC_TRUSTLESS_WORK_API_URLyTRUSTLESS_WORK_API_KEY.
El escrow se crea con: client_account = deudor (negocio), provider_account = inversionista, amount = nominal en unidades mínimas (6 decimales). Así, cuando el negocio pague en Trustless Work, el inversionista recibe el nominal. Si no hay debtorAddress o falla la API, la inversión se registra igual en Faro pero sin escrowId. En el formulario de tokenizar hay un campo opcional “Dirección Stellar del deudor” para que el proveedor lo indique cuando el negocio tenga cuenta Stellar.
import { createEscrow, getEscrow, approveMilestone } from "@/lib/trustless-work"
const escrow = await createEscrow({
amount: "1000000000", // 1000 USDC (6 decimals)
client_account: "G...", // inversor
provider_account: "G...", // PyME
description: "Financiación factura FAC-001",
milestones: [
{ amount: "500000000", description: "Hito 1: Factura verificada" },
{ amount: "500000000", description: "Hito 2: Factura cobrada" },
],
})
await approveMilestone(escrow.id, milestoneId)- La API real de Trustless Work puede usar rutas o cuerpos distintos; ajusta
lib/trustless-work/client.tssegún su documentación o Swagger cuando esté disponible.
-
Configuración
- En
.env:NEXT_PUBLIC_API_KEYoNEXT_PUBLIC_TRUSTLESS_WORK_API_KEY(front, flujo on-chain);TRUSTLESS_WORK_API_KEY(backend, fallback REST). Con testnet el provider usadevelopment(dev.api.trustlesswork.com). NEXT_PUBLIC_STELLAR_NETWORK=testnet(o mainnet) debe coincidir con la red de la wallet y con el entorno de tu API key.
- En
-
Código
- Provider:
TrustlessWorkProviderencomponents/providers/client-providers.tsxenvuelve la app y usa@trustless-work/escrow(development/mainNetsegún red). - Invertir (on-chain): en
app/app/market/[id]/page.tsxse usanuseInitializeEscrow,useSendTransaction,useFundEscrow; se envíacontractIden el body aPOST /api/invoices/[id]/invest. - Pagar (on-chain): en
app/app/pay/[id]/page.tsxse usanuseChangeMilestoneStatus,useApproveMilestone,useReleaseFunds; luegoPOST /api/invoices/[id]/payconreleasedOnChain: true. - Backend:
app/api/invoices/[id]/investaceptacontractIdy lo guarda comoescrowId;app/api/invoices/[id]/payno llama a la API REST si recibereleasedOnChainoreleaseTxHash.
- Provider:
-
Prueba en la app
- Crea una factura con Dirección Stellar del deudor (tokenizar).
- Como inversionista: Mercado → factura → Invertir. Debe pedir firmar en la wallet (Initialize y luego Fund). Tras éxito, la pantalla debe indicar "Se creó un escrow en USDC".
- Como deudor: Dashboard → "Pagar nominal (USDC)" en esa factura. Debe pedir firmar 3 veces (Mark as done, Approve, Release). Tras éxito, "Pago registrado" y el inversionista recibe USDC.
- Si no hay API key o no hay deudor, la inversión se registra sin escrow on-chain (sin mensaje de escrow creado).
-
Verificación externa
- En la respuesta de Initialize, Trustless Work devuelve
contractId(C...). Puedes buscar ese contrato en Stellar Expert (testnet/public según red). - Si Trustless Work ofrece dashboard o API de listado por cuenta, comprueba que aparezca el escrow con el
contractIdguardado en la factura (escrowId).
- En la respuesta de Initialize, Trustless Work devuelve
-
Errores frecuentes
- "Error al invertir" genérico: abre la consola del navegador (F12); el mensaje real suele indicar API key, red o falta de USDC en la wallet.
- Wallet en otra red: la app y la wallet deben estar en la misma red (testnet/mainnet).
- USDC: para que Fund y Release muevan valor real, las wallets deben tener USDC en esa red (en testnet suele hacer falta un faucet o dApp de Trustless Work).
- "The wallet for role 'platformAddress' does not have the required asset": la cuenta usada como plataforma no tiene USDC. Configura
NEXT_PUBLIC_TRUSTLESS_WORK_PLATFORM_ADDRESScon una cuenta que tenga USDC o deja la variable sin definir para que se use la del inversionista.
Para invertir en facturas con escrow necesitas USDC en la red (p. ej. Stellar Testnet):
-
Circle Testnet Faucet
https://faucet.circle.com/ — elige Stellar Testnet, introduce tu dirección y solicita USDC (hasta 20 USDC de prueba). -
Swap XLM → USDC por terminal
Con la Stellar CLI puedes hacer un path payment. Los montos van en stroops (1 XLM = 10⁷ stroops; USDC tiene 6 decimales). En testnet, el emisor USDC suele serGBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5. Ejemplo (reemplazaTU_CUENTAy montos según tu red):stellar tx new path-payment-strict-send \ --source TU_CUENTA \ --send-asset native \ --send-amount 10000000 \ --destination TU_CUENTA \ --dest-asset USDC:GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5 \ --dest-min 1
Consulta el Stellar CLI Manual para
path-payment-strict-send/path-payment-strict-receivey el emisor USDC correcto de tu red (testnet/mainnet).
| Variable | Uso |
|---|---|
NEXT_PUBLIC_FEDERATION_SERVER_URL |
SEP-0002 Federation |
NEXT_PUBLIC_AUTH_SERVER_URL |
SEP-0004 Tx Status |
NEXT_PUBLIC_TRANSFER_SERVER_URL |
SEP-0006 Deposit/Withdrawal |
NEXT_PUBLIC_TRUSTLESS_WORK_API_URL |
Trustless Work API |
TRUSTLESS_WORK_API_KEY |
Trustless Work (server-side) |
NEXT_PUBLIC_TRUSTLESS_WORK_PLATFORM_ADDRESS |
Cuenta Stellar con USDC para el rol plataforma del escrow; en test puede ser tu wallet. Si no se define, se usa la del inversionista. |
NEXT_PUBLIC_STELLAR_NETWORK |
testnet | mainnet (opcional) |
Tu backend/anchor debe implementar los endpoints indicados en cada SEP y publicar stellar.toml con FEDERATION_SERVER, AUTH_SERVER y TRANSFER_SERVER según corresponda.