Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/api/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export const config = {

// MVP flags
mockStellar: process.env.MOCK_STELLAR === "true",
enableInvestments: process.env.ENABLE_INVESTMENTS === "true" || process.env.DEMO_MODE === "true",

// Demo mode — forced false in production (see deriveDemoMode)
demoMode: deriveDemoMode(process.env.DEMO_MODE, process.env.NODE_ENV),
Expand Down
8 changes: 7 additions & 1 deletion apps/api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { cetesRoutes } from "./routes/cetes.js";
import { merchantRoutes } from "./routes/merchants.js";
import { tradeMessagesRoutes } from "./routes/trade-messages.js";
import { initAuthChallengesTable } from "./db/auth.js";
import { config } from "./config.js";

const PORT = parseInt(process.env.PORT ?? "3000", 10);
const NODE_ENV = process.env.NODE_ENV ?? "development";
Expand All @@ -37,7 +38,12 @@ app.register(reputationRoutes);
app.register(fundRoutes);
app.register(serviceRoutes);
app.register(demoRoutes);
app.register(cetesRoutes);

if (config.enableInvestments) {
app.register(cetesRoutes);
app.register(blendRoutes);
}

app.register(merchantRoutes);
app.register(tradeMessagesRoutes);

Expand Down
63 changes: 63 additions & 0 deletions apps/api/src/routes/blend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import type { FastifyInstance } from "fastify";
import { authMiddleware } from "../middleware/auth.middleware.js";

export async function blendRoutes(fastify: FastifyInstance): Promise<void> {
/**
* GET /defi/blend/status
* Authenticated. Returns user's Blend position status.
*/
fastify.get(
"/defi/blend/status",
{ preHandler: [authMiddleware] },
async (request, reply) => {
const userId = (request as any).user.id;

// In productized demo, we return a simulated position
return reply.send({
available_liquidity_usdc: 500.0,
borrow_limit_usdc: 1200.0,
current_borrowed_usdc: 0.0,
health_factor: 1.0,
collateral_assets: [
{ symbol: "XLM", amount: "1500", value_usdc: "250.0" },
{ symbol: "USDC", amount: "250", value_usdc: "250.0" }
],
note: "Data simulated for MicoPay Demo"
});
}
);

/**
* POST /defi/blend/borrow
* Authenticated. Initiates a borrow request on Blend.
*/
fastify.post(
"/defi/blend/borrow",
{
preHandler: [authMiddleware],
schema: {
body: {
type: "object",
required: ["amount", "asset"],
properties: {
amount: { type: "number" },
asset: { type: "string", enum: ["USDC", "XLM"] }
}
}
}
},
async (request, reply) => {
const { amount, asset } = request.body as { amount: number; asset: string };

// Simulate on-chain transaction
return reply.send({
hash: `sim_blend_borrow_${Date.now()}`,
status: "success",
amount,
asset,
explorer_url: `https://stellar.expert/explorer/testnet/tx/sim_blend_borrow_${Date.now()}`,
message: `Successfully borrowed ${amount} ${asset} from Blend`
});
}
);
}
13 changes: 11 additions & 2 deletions apps/api/src/routes/health.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { FastifyInstance } from "fastify";
import { checkHealth } from "../services/health.js";
import { config } from "../config.js";

export async function healthRoutes(fastify: FastifyInstance): Promise<void> {
fastify.get<{ Querystring: { detailed?: string } }>(
Expand All @@ -17,7 +18,12 @@ export async function healthRoutes(fastify: FastifyInstance): Promise<void> {

if (isDetailed) {
const health = await checkHealth();
const statusCode = health.status === "healthy" ? 200 : health.status === "degraded" ? 200 : 503;
const statusCode =
health.status === "healthy"
? 200
: health.status === "degraded"
? 200
: 503;
return reply.status(statusCode).send(health);
}

Expand All @@ -29,8 +35,11 @@ export async function healthRoutes(fastify: FastifyInstance): Promise<void> {
payment_method: "x402",
network: process.env.STELLAR_NETWORK ?? "testnet",
detailed: "/health?detailed=true",
features: {
investments: config.enableInvestments,
},
});
}
},
);

fastify.get("/health/live", async () => ({
Expand Down
36 changes: 23 additions & 13 deletions micopay/frontend/src/pages/Explore.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Logo } from '../components/Logo';
import { useState, useEffect } from "react";
import { Logo } from "../components/Logo";
import { getHealth } from "../services/api";

interface ExploreProps {
onBack?: () => void;
onNavigate?: (page: string) => void;
onBack?: () => void;
onNavigate?: (page: string) => void;
}

const Explore = ({ onBack, onNavigate }: ExploreProps) => {
Expand All @@ -20,15 +22,14 @@ const Explore = ({ onBack, onNavigate }: ExploreProps) => {
</div>
</header>

<main className="flex-1 mt-20 px-6">
<section className="mb-10 pt-4">
<h1 className="font-headline font-extrabold text-3xl text-on-surface leading-tight mb-2">
Explorar
</h1>
<p className="text-on-surface-variant font-medium opacity-70 italic">
Descubre nuevas formas de usar tu dinero
</p>
</section>
useEffect(() => {
getHealth()
.then((data) => {
if (data.features) setFeatures(data.features);
})
.catch(() => {})
.finally(() => setLoading(false));
}, []);

<div className="space-y-6">
{/* Etherfuse Cetes */}
Expand Down Expand Up @@ -102,7 +103,16 @@ const Explore = ({ onBack, onNavigate }: ExploreProps) => {
</footer>
</main>
</div>
);

{/* Footer Section */}
<footer className="mt-12 text-center">
<p className="text-xs text-outline font-medium">
Powered by Stellar, Etherfuse & Blend
</p>
</footer>
</main>
</div>
);
};

export default Explore;