rspace-online/modules/rexchange/applets.ts

76 lines
2.8 KiB
TypeScript

/**
* rExchange applet definitions — Rate Card + Trade Status.
*/
import type { AppletDefinition, AppletLiveData } from "../../shared/applet-types";
const rateCard: AppletDefinition = {
id: "rate-card",
label: "Rate Card",
icon: "💱",
accentColor: "#047857",
ports: [
{ name: "pair-in", type: "string", direction: "input" },
{ name: "rate-out", type: "number", direction: "output" },
],
renderCompact(data: AppletLiveData): string {
const { snapshot } = data;
const pair = (snapshot.pair as string) || "—/—";
const rate = (snapshot.rate as number) || 0;
const change24h = (snapshot.change24h as number) || 0;
const changeColor = change24h >= 0 ? "#22c55e" : "#ef4444";
const arrow = change24h >= 0 ? "▲" : "▼";
return `
<div style="text-align:center">
<div style="font-size:11px;color:#94a3b8;margin-bottom:4px">${pair}</div>
<div style="font-size:22px;font-weight:700;color:#e2e8f0">${rate.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 6 })}</div>
<div style="font-size:11px;font-weight:500;color:${changeColor};margin-top:4px">${arrow} ${Math.abs(change24h).toFixed(2)}%</div>
</div>
`;
},
onInputReceived(portName, value, ctx) {
if (portName === "pair-in" && typeof value === "string") {
ctx.emitOutput("rate-out", 0);
}
},
};
const tradeStatus: AppletDefinition = {
id: "trade-status",
label: "Trade Status",
icon: "🔄",
accentColor: "#047857",
ports: [
{ name: "trade-in", type: "json", direction: "input" },
{ name: "status-out", type: "string", direction: "output" },
],
renderCompact(data: AppletLiveData): string {
const { snapshot } = data;
const type = (snapshot.type as string) || "trade";
const amount = (snapshot.amount as number) || 0;
const asset = (snapshot.asset as string) || "—";
const status = (snapshot.status as string) || "pending";
const statusColor = status === "filled" ? "#22c55e" : status === "cancelled" ? "#ef4444" : "#f59e0b";
return `
<div>
<div style="display:flex;justify-content:space-between;margin-bottom:6px">
<span style="font-size:11px;color:#94a3b8;text-transform:uppercase">${type}</span>
<span style="font-size:10px;font-weight:500;color:${statusColor};text-transform:uppercase">${status}</span>
</div>
<div style="font-size:18px;font-weight:700;color:#e2e8f0;margin-bottom:2px">${amount.toLocaleString()}</div>
<div style="font-size:11px;color:#94a3b8">${asset}</div>
</div>
`;
},
onInputReceived(portName, value, ctx) {
if (portName === "trade-in" && value && typeof value === "object") {
const trade = value as Record<string, unknown>;
ctx.emitOutput("status-out", (trade.status as string) || "pending");
}
},
};
export const exchangeApplets: AppletDefinition[] = [rateCard, tradeStatus];