feat: add unified resale dashboard

This commit is contained in:
david
2026-08-28 09:45:51 +02:00
parent cd3ea734e3
commit 53607738f8
8 changed files with 949 additions and 22 deletions

View File

@@ -22,6 +22,20 @@ services:
- no-new-privileges:true - no-new-privileges:true
volumes: volumes:
- surplus-seller-state:/var/lib/surplus-manager - surplus-seller-state:/var/lib/surplus-manager
networks:
- traefik-net
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik-net"
- "traefik.http.routers.mp-openrouter-reseller-mainnet.entrypoints=web"
- "traefik.http.routers.mp-openrouter-reseller-mainnet.rule=Host(`mp-suppliers-openrouter-reseller.vector.apexfusion.org`)"
- "traefik.http.routers.mp-openrouter-reseller-mainnet.middlewares=mp-openrouter-reseller-mainnet-https"
- "traefik.http.middlewares.mp-openrouter-reseller-mainnet-https.redirectscheme.scheme=https"
- "traefik.http.middlewares.mp-openrouter-reseller-mainnet-https.redirectscheme.permanent=true"
- "traefik.http.routers.mp-openrouter-reseller-mainnet-tls.entrypoints=websecure"
- "traefik.http.routers.mp-openrouter-reseller-mainnet-tls.rule=Host(`mp-suppliers-openrouter-reseller.vector.apexfusion.org`)"
- "traefik.http.routers.mp-openrouter-reseller-mainnet-tls.tls.certresolver=letsencrypt"
- "traefik.http.services.mp-openrouter-reseller-mainnet.loadbalancer.server.port=8080"
healthcheck: healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8080/healthz >/dev/null || exit 1"] test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8080/healthz >/dev/null || exit 1"]
interval: 20s interval: 20s
@@ -37,3 +51,8 @@ services:
volumes: volumes:
surplus-seller-state: surplus-seller-state:
name: marketplace-mainnet-surplus-seller-state name: marketplace-mainnet-surplus-seller-state
networks:
traefik-net:
external: true
name: traefik-net

View File

@@ -1,4 +1,9 @@
import { createServer, type Server } from "node:http"; import {
createServer,
type IncomingMessage,
type Server,
type ServerResponse,
} from "node:http";
import { fileURLToPath } from "node:url"; import { fileURLToPath } from "node:url";
import { resolve } from "node:path"; import { resolve } from "node:path";
import { loadSurplusManagerConfig } from "../surplus/config.js"; import { loadSurplusManagerConfig } from "../surplus/config.js";
@@ -6,6 +11,11 @@ import { SurplusClient } from "../surplus/client.js";
import { SurplusSellerController } from "../surplus/controller.js"; import { SurplusSellerController } from "../surplus/controller.js";
import { OpenRouterKeyClient } from "../surplus/openRouterKey.js"; import { OpenRouterKeyClient } from "../surplus/openRouterKey.js";
import { FileSurplusStateStore } from "../surplus/state.js"; import { FileSurplusStateStore } from "../surplus/state.js";
import {
SurplusDashboardService,
type SurplusDashboardSnapshot,
} from "../surplus/dashboard.js";
import { renderSurplusDashboardPage } from "../surplus/dashboardPage.js";
export async function runSurplusSeller( export async function runSurplusSeller(
env: Record<string, string | undefined>, env: Record<string, string | undefined>,
@@ -29,7 +39,13 @@ export async function runSurplusSeller(
stateStore, stateStore,
log: (message) => console.log(message), log: (message) => console.log(message),
}); });
const server = createStatusServer(controller); const dashboard = new SurplusDashboardService({
controller,
client,
allowance,
config,
});
const server = createSurplusServer(controller, dashboard);
await new Promise<void>((resolveListen, rejectListen) => { await new Promise<void>((resolveListen, rejectListen) => {
server.once("error", rejectListen); server.once("error", rejectListen);
server.listen(config.port, "0.0.0.0", () => { server.listen(config.port, "0.0.0.0", () => {
@@ -41,26 +57,81 @@ export async function runSurplusSeller(
return { server, controller }; return { server, controller };
} }
function createStatusServer(controller: SurplusSellerController): Server { interface DashboardSource {
getSnapshot(): Promise<SurplusDashboardSnapshot>;
}
export function createSurplusServer(
controller: Pick<SurplusSellerController, "snapshot" | "healthy">,
dashboard: DashboardSource,
): Server {
return createServer((request, response) => { return createServer((request, response) => {
const status = controller.snapshot(); void handleRequest(controller, dashboard, request, response);
if (request.method === "GET" && request.url === "/healthz") { });
const healthy = controller.healthy(); }
response.statusCode = healthy ? 200 : 503;
response.setHeader("content-type", "application/json"); async function handleRequest(
response.end(JSON.stringify({ ok: healthy, phase: status.phase })); controller: Pick<SurplusSellerController, "snapshot" | "healthy">,
return; dashboard: DashboardSource,
} request: IncomingMessage,
if (request.method === "GET" && request.url === "/status") { response: ServerResponse,
): Promise<void> {
const path = request.url?.split("?")[0] ?? "/";
response.setHeader("cache-control", "no-store");
response.setHeader("x-content-type-options", "nosniff");
response.setHeader("x-frame-options", "DENY");
response.setHeader("referrer-policy", "no-referrer");
if (request.method === "GET" && path === "/") {
response.statusCode = 302;
response.setHeader("location", "/reseller");
response.end();
return;
}
if (
request.method === "GET" &&
(path === "/reseller" || path === "/reseller/")
) {
response.statusCode = 200;
response.setHeader("content-type", "text/html; charset=utf-8");
response.setHeader(
"content-security-policy",
"default-src 'self'; style-src 'self' 'unsafe-inline'; " +
"script-src 'self' 'unsafe-inline'; connect-src 'self'; " +
"img-src 'self' data:; frame-ancestors 'none'; base-uri 'none'",
);
response.end(renderSurplusDashboardPage());
return;
}
const status = controller.snapshot();
if (request.method === "GET" && path === "/healthz") {
const healthy = controller.healthy();
response.statusCode = healthy ? 200 : 503;
response.setHeader("content-type", "application/json");
response.end(JSON.stringify({ ok: healthy, phase: status.phase }));
return;
}
if (request.method === "GET" && path === "/status") {
response.statusCode = 200;
response.setHeader("content-type", "application/json");
response.end(JSON.stringify(status));
return;
}
if (request.method === "GET" && path === "/dashboard/api") {
try {
const snapshot = await dashboard.getSnapshot();
response.statusCode = 200; response.statusCode = 200;
response.setHeader("content-type", "application/json"); response.setHeader("content-type", "application/json");
response.end(JSON.stringify(status)); response.end(JSON.stringify(snapshot));
return; } catch {
response.statusCode = 503;
response.setHeader("content-type", "application/json");
response.end(JSON.stringify({ error: "dashboard_data_unavailable" }));
} }
response.statusCode = 404; return;
response.setHeader("content-type", "application/json"); }
response.end(JSON.stringify({ error: "not_found" })); response.statusCode = 404;
}); response.setHeader("content-type", "application/json");
response.end(JSON.stringify({ error: "not_found" }));
} }
export async function main( export async function main(

View File

@@ -40,6 +40,9 @@ export interface SurplusOrderBookOffer {
healthy: boolean; healthy: boolean;
trusted: boolean; trusted: boolean;
trades24h: number; trades24h: number;
rank: number;
capRemainingMicroUsd: number | null;
volume24hMicroUsd: number;
} }
export interface SurplusOrderBook { export interface SurplusOrderBook {
@@ -64,17 +67,48 @@ export interface SurplusOfferPatch {
} }
export interface SurplusSale { export interface SurplusSale {
id: string;
model: string; model: string;
offerId: string | null; offerId: string | null;
settlementStatus: string; settlementStatus: string;
createdAt: string | null; createdAt: string | null;
sellerCostMicroUsd: number; sellerCostMicroUsd: number;
inputTokens: number;
outputTokens: number;
cacheReadTokens: number;
effectiveInputUsdPer1m: number;
effectiveOutputUsdPer1m: number;
transactionHash: string | null;
}
export interface SurplusDailyEarnings {
day: string;
earnedUsd: number;
inputTokens: number;
outputTokens: number;
requests: number;
totalTokens: number;
}
export interface SurplusModelEarnings {
model: string;
earnedUsd: number;
requests: number;
totalTokens: number;
lastSaleAt: string | null;
} }
export interface SurplusEarnings { export interface SurplusEarnings {
totalEarnedMicroUsd: number; totalEarnedMicroUsd: number;
pendingMicroUsd: number; pendingMicroUsd: number;
paidMicroUsd: number; paidMicroUsd: number;
daily: SurplusDailyEarnings[];
byModel: SurplusModelEarnings[];
requestCount: number;
tokenCount: number;
topModel: string | null;
payoutHoldReason: string | null;
payoutHoldReleasesAt: string | null;
recentSales: SurplusSale[]; recentSales: SurplusSale[];
} }
@@ -263,15 +297,43 @@ export class SurplusClient {
async getEarnings(): Promise<SurplusEarnings> { async getEarnings(): Promise<SurplusEarnings> {
const body = await this.requestJson("/v1/seller/earnings?range=lifetime"); const body = await this.requestJson("/v1/seller/earnings?range=lifetime");
const root = record(body, "Surplus earnings response"); const root = record(body, "Surplus earnings response");
const rawSales = root.recent_sales; if (!Array.isArray(root.recent_sales)) {
if (!Array.isArray(rawSales)) {
throw new Error("Surplus earnings response.recent_sales must be an array"); throw new Error("Surplus earnings response.recent_sales must be an array");
} }
if (!Array.isArray(root.daily)) {
throw new Error("Surplus earnings response.daily must be an array");
}
if (!Array.isArray(root.by_model)) {
throw new Error("Surplus earnings response.by_model must be an array");
}
const share = record(root.share, "Surplus earnings response.share");
const payoutHold = optionalRecord(root.payout_hold);
return { return {
totalEarnedMicroUsd: microUsd(root.total_earned_usdc, "total_earned_usdc"), totalEarnedMicroUsd: microUsd(root.total_earned_usdc, "total_earned_usdc"),
pendingMicroUsd: microUsd(root.pending_usdc, "pending_usdc"), pendingMicroUsd: microUsd(root.pending_usdc, "pending_usdc"),
paidMicroUsd: microUsd(root.paid_usdc, "paid_usdc"), paidMicroUsd: microUsd(root.paid_usdc, "paid_usdc"),
recentSales: rawSales.map((sale, index) => parseSale(sale, index)), daily: root.daily.map((day, index) => parseDailyEarnings(day, index)),
byModel: root.by_model.map((model, index) =>
parseModelEarnings(model, index)
),
requestCount: nonNegativeSafeInteger(
share.requests,
"Surplus earnings share.requests",
),
tokenCount: nonNegativeSafeInteger(
share.tokens,
"Surplus earnings share.tokens",
),
topModel: optionalString(share.top_model),
payoutHoldReason: payoutHold
? optionalString(payoutHold.reason)
: null,
payoutHoldReleasesAt: payoutHold
? optionalTimestamp(payoutHold.releases_at, "payout_hold.releases_at")
: null,
recentSales: root.recent_sales.map((sale, index) =>
parseSale(sale, index)
),
}; };
} }
@@ -460,17 +522,98 @@ function parseOrderBookOffer(value: unknown, index: number): SurplusOrderBookOff
healthy: boolean(item.healthy, `Surplus order book offer ${index}.healthy`), healthy: boolean(item.healthy, `Surplus order book offer ${index}.healthy`),
trusted: boolean(item.trusted, `Surplus order book offer ${index}.trusted`), trusted: boolean(item.trusted, `Surplus order book offer ${index}.trusted`),
trades24h: nonNegativeSafeInteger(item.trades_24h, `Surplus order book offer ${index}.trades_24h`), trades24h: nonNegativeSafeInteger(item.trades_24h, `Surplus order book offer ${index}.trades_24h`),
rank: positiveSafeInteger(item.rank, `Surplus order book offer ${index}.rank`),
capRemainingMicroUsd: optionalMicroUsd(
item.cap_remaining,
`Surplus order book offer ${index}.cap_remaining`,
),
volume24hMicroUsd: microUsd(
item.volume_24h,
`Surplus order book offer ${index}.volume_24h`,
),
}; };
} }
function parseSale(value: unknown, index: number): SurplusSale { function parseSale(value: unknown, index: number): SurplusSale {
const item = record(value, `Surplus sale ${index}`); const item = record(value, `Surplus sale ${index}`);
return { return {
id: string(item.id, `Surplus sale ${index}.id`),
model: string(item.model, `Surplus sale ${index}.model`), model: string(item.model, `Surplus sale ${index}.model`),
offerId: optionalString(item.offer_id), offerId: optionalString(item.offer_id),
settlementStatus: string(item.settlement_status, `Surplus sale ${index}.settlement_status`), settlementStatus: string(item.settlement_status, `Surplus sale ${index}.settlement_status`),
createdAt: optionalString(item.created_at), createdAt: optionalTimestamp(item.created_at, `Surplus sale ${index}.created_at`),
sellerCostMicroUsd: microUsd(item.seller_cost_usdc, `Surplus sale ${index}.seller_cost_usdc`), sellerCostMicroUsd: microUsd(item.seller_cost_usdc, `Surplus sale ${index}.seller_cost_usdc`),
inputTokens: optionalSafeInteger(item.input_tokens, `Surplus sale ${index}.input_tokens`),
outputTokens: optionalSafeInteger(item.output_tokens, `Surplus sale ${index}.output_tokens`),
cacheReadTokens: optionalSafeInteger(
item.cache_read_tokens,
`Surplus sale ${index}.cache_read_tokens`,
),
effectiveInputUsdPer1m: nonNegativeNumber(
item.effective_input_per_1m,
`Surplus sale ${index}.effective_input_per_1m`,
),
effectiveOutputUsdPer1m: nonNegativeNumber(
item.effective_output_per_1m,
`Surplus sale ${index}.effective_output_per_1m`,
),
transactionHash: optionalString(item.tx_hash),
};
}
function parseDailyEarnings(
value: unknown,
index: number,
): SurplusDailyEarnings {
const item = record(value, `Surplus daily earnings ${index}`);
return {
day: string(item.day, `Surplus daily earnings ${index}.day`),
earnedUsd: nonNegativeNumber(
item.earned_usd,
`Surplus daily earnings ${index}.earned_usd`,
),
inputTokens: nonNegativeSafeInteger(
item.input_tokens,
`Surplus daily earnings ${index}.input_tokens`,
),
outputTokens: nonNegativeSafeInteger(
item.output_tokens,
`Surplus daily earnings ${index}.output_tokens`,
),
requests: nonNegativeSafeInteger(
item.requests,
`Surplus daily earnings ${index}.requests`,
),
totalTokens: nonNegativeSafeInteger(
item.total_tokens,
`Surplus daily earnings ${index}.total_tokens`,
),
};
}
function parseModelEarnings(
value: unknown,
index: number,
): SurplusModelEarnings {
const item = record(value, `Surplus model earnings ${index}`);
return {
model: string(item.model, `Surplus model earnings ${index}.model`),
earnedUsd: nonNegativeNumber(
item.earned_usd,
`Surplus model earnings ${index}.earned_usd`,
),
requests: nonNegativeSafeInteger(
item.requests,
`Surplus model earnings ${index}.requests`,
),
totalTokens: nonNegativeSafeInteger(
item.total_tokens,
`Surplus model earnings ${index}.total_tokens`,
),
lastSaleAt: optionalTimestamp(
item.last_sale_at,
`Surplus model earnings ${index}.last_sale_at`,
),
}; };
} }
@@ -503,6 +646,19 @@ function optionalString(value: unknown): string | null {
return typeof value === "string" && value !== "" ? value : null; return typeof value === "string" && value !== "" ? value : null;
} }
function optionalTimestamp(value: unknown, field: string): string | null {
if (value === null || value === undefined) return null;
const timestamp = typeof value === "number"
? value
: typeof value === "string"
? Date.parse(value)
: Number.NaN;
if (!Number.isFinite(timestamp) || timestamp < 0) {
throw new Error(`${field} must be a timestamp`);
}
return new Date(timestamp).toISOString();
}
function boolean(value: unknown, field: string): boolean { function boolean(value: unknown, field: string): boolean {
if (typeof value !== "boolean") throw new Error(`${field} must be a boolean`); if (typeof value !== "boolean") throw new Error(`${field} must be a boolean`);
return value; return value;
@@ -560,6 +716,11 @@ function nonNegativeSafeInteger(value: unknown, field: string): number {
return value; return value;
} }
function optionalSafeInteger(value: unknown, field: string): number {
if (value === null || value === undefined) return 0;
return nonNegativeSafeInteger(value, field);
}
function microUsd(value: unknown, field: string): number { function microUsd(value: unknown, field: string): number {
if (typeof value === "string" && /^(?:0|[1-9]\d*)$/.test(value)) { if (typeof value === "string" && /^(?:0|[1-9]\d*)$/.test(value)) {
const parsed = Number(value); const parsed = Number(value);

View File

@@ -0,0 +1,259 @@
import type { SurplusManagerConfig } from "./config.js";
import type {
SurplusClient,
SurplusDailyEarnings,
SurplusEarnings,
SurplusOffer,
SurplusOrderBook,
} from "./client.js";
import type {
SurplusControllerStatus,
SurplusSellerController,
} from "./controller.js";
import type { OpenRouterKeyClient } from "./openRouterKey.js";
import { formatUsdNanos } from "../reseller/money.js";
import { formatMicroUsd } from "./policy.js";
export interface VectorMigrationSummary {
status: "retired";
model: string;
supplierWallet: string;
advertRef: string;
retirementTransaction: string;
retiredOn: string;
historicalAp3xEarned: string;
historicalSettledJobs: number;
historicalUpstreamSpendUsd: string;
}
export interface SurplusDashboardSnapshot {
generatedAt: string;
controller: SurplusControllerStatus;
identity: {
sellerWallet: string;
payoutAddress: string;
};
provider: {
name: "OpenRouter";
hardLimitUsd: string;
remainingUsd: string;
usedUsd: string;
reserveUsd: string;
estimatedDailyExposureUsd: string;
};
surplus: {
offer: {
id: string | null;
model: string | null;
providerModel: string | null;
status: "active" | "inactive" | "missing";
dailyCapUsd: string | null;
costMultiplier: number | null;
inputUsdPer1m: string | null;
outputUsdPer1m: string | null;
rank: number | null;
available: boolean;
healthy: boolean;
trusted: boolean;
trades24h: number;
volume24hUsd: string;
capRemainingUsd: string | null;
};
earnings: {
totalUsd: string;
pendingUsd: string;
paidUsd: string;
requests: number;
tokens: number;
today: SurplusDailyEarnings | null;
topModel: string | null;
payoutHoldReason: string | null;
payoutHoldReleasesAt: string | null;
};
recentSales: Array<{
id: string;
model: string;
createdAt: string | null;
settlementStatus: string;
inputTokens: number;
outputTokens: number;
cacheReadTokens: number;
revenueUsd: string;
transactionHash: string | null;
}>;
};
vector: VectorMigrationSummary;
}
interface SurplusDashboardOptions {
controller: Pick<SurplusSellerController, "snapshot">;
client: Pick<SurplusClient, "listAllOffers" | "getEarnings" | "getOrderBook">;
allowance: Pick<OpenRouterKeyClient, "readAllowance">;
config: SurplusManagerConfig;
vector?: VectorMigrationSummary;
cacheMs?: number;
now?: () => number;
}
const DEFAULT_VECTOR_MIGRATION: VectorMigrationSummary = {
status: "retired",
model: "deepseek/deepseek-v4-flash",
supplierWallet: "addr1v8zy05zsugau8su0lqn8q37xlryh39cww9mw9t6g7vt207c9xfc9d",
advertRef:
"29bc9e7ec9f4a26f33e419436cfe95239b5d06b75db637e8dbb4cbc478d1a445#0",
retirementTransaction:
"d7fdae603e5744c98efc20c25d73a83ebfef0308806026a370d9f81c975c11fa",
retiredOn: "2026-08-27",
historicalAp3xEarned: "1.600000",
historicalSettledJobs: 8,
historicalUpstreamSpendUsd: "0.000093",
};
export class SurplusDashboardService {
private readonly controller: Pick<SurplusSellerController, "snapshot">;
private readonly client: Pick<
SurplusClient,
"listAllOffers" | "getEarnings" | "getOrderBook"
>;
private readonly allowance: Pick<OpenRouterKeyClient, "readAllowance">;
private readonly config: SurplusManagerConfig;
private readonly vector: VectorMigrationSummary;
private readonly cacheMs: number;
private readonly now: () => number;
private cache: { fetchedAt: number; value: SurplusDashboardSnapshot } | null = null;
private inFlight: Promise<SurplusDashboardSnapshot> | null = null;
constructor(options: SurplusDashboardOptions) {
this.controller = options.controller;
this.client = options.client;
this.allowance = options.allowance;
this.config = options.config;
this.vector = options.vector ?? DEFAULT_VECTOR_MIGRATION;
this.cacheMs = options.cacheMs ?? 15_000;
this.now = options.now ?? Date.now;
}
async getSnapshot(): Promise<SurplusDashboardSnapshot> {
const now = this.now();
if (this.cache && now - this.cache.fetchedAt < this.cacheMs) {
return this.cache.value;
}
if (this.inFlight) return this.inFlight;
const load = this.loadSnapshot();
this.inFlight = load;
try {
const value = await load;
this.cache = { fetchedAt: this.now(), value };
return value;
} finally {
this.inFlight = null;
}
}
private async loadSnapshot(): Promise<SurplusDashboardSnapshot> {
const controller = this.controller.snapshot();
const [offers, earnings, allowance, orderBook] = await Promise.all([
this.client.listAllOffers(),
this.client.getEarnings(),
this.allowance.readAllowance(),
controller.model ? this.client.getOrderBook(controller.model) : null,
]);
const offer = findOffer(offers, controller.offerId);
const marketOffer = findMarketOffer(orderBook, controller.offerId);
const usedUsdNanos = allowance.limitUsdNanos - allowance.remainingUsdNanos;
const estimatedDailyExposure =
Number(this.config.perOfferCapUsd) * 10_000 / this.config.recoveryBps;
const today = earnings.daily.find((day) =>
day.day === new Date(this.now()).toISOString().slice(0, 10)
) ?? null;
return {
generatedAt: new Date(this.now()).toISOString(),
controller,
identity: {
sellerWallet: this.config.sellerWallet,
payoutAddress: this.config.payoutAddress,
},
provider: {
name: "OpenRouter",
hardLimitUsd: formatUsdNanos(allowance.limitUsdNanos, 6),
remainingUsd: formatUsdNanos(allowance.remainingUsdNanos, 6),
usedUsd: formatUsdNanos(usedUsdNanos, 6),
reserveUsd: this.config.reserveUsd,
estimatedDailyExposureUsd: estimatedDailyExposure.toFixed(6),
},
surplus: {
offer: {
id: offer?.id ?? controller.offerId,
model: offer?.model ?? controller.model,
providerModel: controller.providerModelId,
status: offer?.status ?? "missing",
dailyCapUsd: offer?.capDailyUsd === null || offer === undefined
? null
: offer.capDailyUsd.toFixed(6),
costMultiplier: offer?.costMultiplierPpm === null || offer === undefined
? null
: offer.costMultiplierPpm / 1_000_000,
inputUsdPer1m: controller.inputUsdPer1m,
outputUsdPer1m: controller.outputUsdPer1m,
rank: marketOffer?.rank ?? null,
available: marketOffer?.available ?? false,
healthy: marketOffer?.healthy ?? false,
trusted: marketOffer?.trusted ?? false,
trades24h: marketOffer?.trades24h ?? 0,
volume24hUsd: formatMicroUsd(marketOffer?.volume24hMicroUsd ?? 0),
capRemainingUsd: marketOffer?.capRemainingMicroUsd === null ||
marketOffer === undefined
? null
: formatMicroUsd(marketOffer.capRemainingMicroUsd),
},
earnings: earningsSummary(earnings, today),
recentSales: earnings.recentSales.slice(0, 25).map((sale) => ({
id: sale.id,
model: sale.model,
createdAt: sale.createdAt,
settlementStatus: sale.settlementStatus,
inputTokens: sale.inputTokens,
outputTokens: sale.outputTokens,
cacheReadTokens: sale.cacheReadTokens,
revenueUsd: formatMicroUsd(sale.sellerCostMicroUsd),
transactionHash: sale.transactionHash,
})),
},
vector: this.vector,
};
}
}
function findOffer(
offers: SurplusOffer[],
offerId: string | null,
): SurplusOffer | undefined {
return offerId ? offers.find((offer) => offer.id === offerId) : undefined;
}
function findMarketOffer(
orderBook: SurplusOrderBook | null,
offerId: string | null,
) {
return offerId
? orderBook?.offers.find((offer) => offer.id === offerId)
: undefined;
}
function earningsSummary(
earnings: SurplusEarnings,
today: SurplusDailyEarnings | null,
): SurplusDashboardSnapshot["surplus"]["earnings"] {
return {
totalUsd: formatMicroUsd(earnings.totalEarnedMicroUsd),
pendingUsd: formatMicroUsd(earnings.pendingMicroUsd),
paidUsd: formatMicroUsd(earnings.paidMicroUsd),
requests: earnings.requestCount,
tokens: earnings.tokenCount,
today,
topModel: earnings.topModel,
payoutHoldReason: earnings.payoutHoldReason,
payoutHoldReleasesAt: earnings.payoutHoldReleasesAt,
};
}

View File

@@ -0,0 +1,62 @@
export function renderSurplusDashboardPage(): string {
return `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="color-scheme" content="dark">
<title>Inference Resale Control Plane</title>
<style>
:root{--bg:#07110f;--surface:#0c1916;--surface-2:#10231e;--line:#244039;--text:#eef8f3;--muted:#91aaa1;--green:#57e39b;--teal:#5fd8cd;--blue:#79b8ff;--amber:#f3c969;--red:#ff827c;--shadow:0 24px 80px #0007}
*{box-sizing:border-box}html{min-width:320px}body{margin:0;background:radial-gradient(circle at 8% -5%,#17493b 0,transparent 29rem),radial-gradient(circle at 95% 20%,#15344b 0,transparent 34rem),var(--bg);color:var(--text);font:14px/1.5 Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}
body:before{content:"";position:fixed;inset:0;pointer-events:none;background-image:linear-gradient(#fff008 1px,transparent 1px),linear-gradient(90deg,#fff008 1px,transparent 1px);background-size:42px 42px;mask-image:linear-gradient(to bottom,#0008,transparent 55%)}
a{color:var(--blue);text-decoration:none}a:hover,a:focus-visible{text-decoration:underline}.shell{width:min(1240px,calc(100% - 32px));margin:auto;padding:38px 0 72px}.top{display:flex;justify-content:space-between;align-items:flex-start;gap:32px;margin-bottom:26px}.eyebrow{color:var(--green);font:700 11px/1.2 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.16em;text-transform:uppercase}.top h1{margin:10px 0 8px;font-size:clamp(32px,5.5vw,58px);line-height:.98;letter-spacing:-.055em;max-width:780px}.top p{color:var(--muted);margin:0;max-width:660px;font-size:15px}.live-cluster{text-align:right;min-width:210px}.updated{color:var(--muted);font-variant-numeric:tabular-nums;margin-top:8px}.badge{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--line);border-radius:999px;padding:7px 11px;background:#081511cc;font-size:12px;font-weight:700}.badge:before{content:"";width:7px;height:7px;border-radius:50%;background:var(--muted);box-shadow:0 0 0 3px #fff1}.badge.live:before{background:var(--green);box-shadow:0 0 18px var(--green)}.badge.retired:before{background:var(--amber)}
.panel{border:1px solid var(--line);border-radius:18px;background:linear-gradient(145deg,#10231ee8,#0a1714f2);box-shadow:var(--shadow)}.flow{display:grid;grid-template-columns:1fr 42px 1.1fr 42px 1.15fr;align-items:stretch;padding:14px;margin-bottom:18px;overflow:hidden}.node{padding:18px;border-radius:13px;background:#091612;border:1px solid #24443a;min-width:0}.node strong{display:block;font-size:18px;margin:5px 0 3px}.node small{color:var(--muted);display:block}.node .sub{font:12px ui-monospace,SFMono-Regular,Menlo,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.arrow{display:grid;place-items:center;color:var(--teal);font-size:22px}.markets{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:18px}.market-card{padding:22px;position:relative;overflow:hidden}.market-card:after{content:"";position:absolute;width:180px;height:180px;border-radius:50%;right:-90px;top:-110px;background:#57e39b0b}.market-head{display:flex;justify-content:space-between;align-items:flex-start;gap:16px}.market-head h2{margin:3px 0 0;font-size:22px}.market-head p{margin:5px 0 0;color:var(--muted)}.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.truncate{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.metrics{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin:16px 0 0}.metric{padding:14px;border:1px solid #254039;border-radius:12px;background:#07130f9c;min-width:0}.label{display:block;color:var(--muted);text-transform:uppercase;letter-spacing:.11em;font-size:10px;font-weight:700}.metric strong{display:block;font-size:clamp(18px,2.2vw,27px);letter-spacing:-.035em;margin-top:5px;font-variant-numeric:tabular-nums}.metric small{color:var(--muted);display:block;margin-top:2px}.good{color:var(--green)}.warn{color:var(--amber)}.retired-copy{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:16px}.fact{padding:12px 14px;border-left:2px solid var(--amber);background:#f3c9690a}.fact strong{display:block;margin-top:3px}
.section-head{display:flex;justify-content:space-between;align-items:end;gap:20px;margin:28px 2px 12px}.section-head h2{margin:0;font-size:22px;letter-spacing:-.025em}.section-head p{margin:0;color:var(--muted)}.table-wrap{overflow:auto}.sales{width:100%;border-collapse:collapse;min-width:820px}.sales th,.sales td{text-align:left;padding:12px 15px;border-bottom:1px solid #213a33}.sales th{position:sticky;top:0;background:#0d1b17;color:var(--muted);font-size:10px;text-transform:uppercase;letter-spacing:.12em}.sales tbody tr:hover{background:#ffffff05}.sales tbody tr:last-child td{border-bottom:0}.status-pill{display:inline-flex;border-radius:999px;padding:3px 8px;background:#ffffff0b;border:1px solid #ffffff13;font-size:11px}.status-pill.confirmed{color:var(--green);border-color:#57e39b55}.status-pill.accrued{color:var(--amber);border-color:#f3c96955}.empty{padding:34px!important;text-align:center!important;color:var(--muted)}.alert{display:none;margin-top:14px;padding:12px 14px;border-radius:11px;background:#ff827c10;border:1px solid #ff827c44;color:#ffc4bf}.alert.visible{display:block}.foot{display:flex;justify-content:space-between;gap:24px;color:var(--muted);margin-top:24px;font-size:12px}.foot span:last-child{text-align:right}
@media(max-width:980px){.metrics{grid-template-columns:repeat(2,1fr)}.markets{grid-template-columns:1fr}.flow{grid-template-columns:1fr}.arrow{transform:rotate(90deg);height:34px}.top{flex-direction:column}.live-cluster{text-align:left}.retired-copy{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.shell{width:min(100% - 20px,1240px);padding-top:24px}.metrics,.retired-copy{grid-template-columns:1fr}.market-card{padding:17px}.top h1{font-size:38px}.foot{flex-direction:column}.foot span:last-child{text-align:left}}
</style>
</head>
<body>
<main class="shell">
<header class="top"><div><div class="eyebrow">Autonomous inference resale</div><h1>One capacity pool.<br>Two settlement markets.</h1><p>Live OpenRouter capacity sold through Surplus on Base, with the completed Vector AP3X proof preserved as the migration record.</p></div><div class="live-cluster"><span class="badge" id="controller-badge">Loading controller</span><div class="updated" id="updated">Waiting for current state</div></div></header>
<section class="panel flow" aria-label="Capacity routing flow">
<div class="node"><span class="label">Upstream capacity</span><strong>OpenRouter</strong><small id="flow-allowance">Allowance loading</small><small class="sub" id="flow-provider-model">provider model --</small></div><div class="arrow" aria-hidden="true">→</div>
<div class="node"><span class="label">Autonomous manager</span><strong>Seller agent</strong><small>Discovers · prices · caps · reconciles</small><small class="sub" id="flow-wallet">seller --</small></div><div class="arrow" aria-hidden="true">→</div>
<div class="node"><span class="label">Current settlement</span><strong>Surplus / Base USDC</strong><small id="flow-surplus">Offer loading</small><small class="sub" id="flow-offer">offer --</small></div>
</section>
<section class="markets">
<article class="panel market-card"><div class="market-head"><div><span class="label">Current market</span><h2>Surplus Intelligence</h2><p>Competitive model routing with USDC settlement on Base.</p></div><span class="badge" id="surplus-badge">Loading</span></div>
<div class="metrics"><div class="metric"><span class="label">Lifetime revenue</span><strong id="earned">--</strong><small id="earnings-state">--</small></div><div class="metric"><span class="label">Requests sold</span><strong id="requests">--</strong><small id="tokens">-- tokens</small></div><div class="metric"><span class="label">Market position</span><strong id="rank">--</strong><small id="market-state">--</small></div><div class="metric"><span class="label">Daily seller cap</span><strong id="daily-cap">--</strong><small id="cap-remaining">-- remaining</small></div></div>
<div class="alert" id="payout-hold"></div><div class="alert" id="controller-error"></div></article>
<article class="panel market-card"><div class="market-head"><div><span class="label">Migration record</span><h2>Vector marketplace</h2><p>AP3X escrow route retired after the cross-market proof.</p></div><span class="badge retired">Retired</span></div>
<div class="metrics"><div class="metric"><span class="label">AP3X earned</span><strong id="vector-earned">--</strong><small>historical</small></div><div class="metric"><span class="label">Settled jobs</span><strong id="vector-jobs">--</strong><small>Vector escrows</small></div><div class="metric"><span class="label">Upstream spend</span><strong id="vector-spend">--</strong><small>proof route</small></div><div class="metric"><span class="label">Retired on</span><strong id="vector-date">--</strong><small>advert closed</small></div></div>
<div class="retired-copy"><div class="fact"><span class="label">Retired advert</span><strong class="mono truncate" id="vector-advert">--</strong><a id="advert-link" target="_blank" rel="noopener noreferrer">Open creation transaction ↗</a></div><div class="fact"><span class="label">Retirement proof</span><strong class="mono truncate" id="vector-retirement">--</strong><a id="retirement-link" target="_blank" rel="noopener noreferrer">Open confirmed transaction ↗</a></div></div></article>
</section>
<section class="panel market-card"><div class="market-head"><div><span class="label">Economics</span><h2>Capacity and price controls</h2><p>The seller cap is discounted revenue. The agent converts it to estimated upstream exposure before it opens the route.</p></div><span class="badge live">Bounded</span></div>
<div class="metrics"><div class="metric"><span class="label">OpenRouter remaining</span><strong id="provider-remaining">--</strong><small id="provider-used">-- used</small></div><div class="metric"><span class="label">Protected reserve</span><strong id="provider-reserve">--</strong><small>fail-closed threshold</small></div><div class="metric"><span class="label">Daily upstream estimate</span><strong id="provider-exposure">--</strong><small>from recovery floor</small></div><div class="metric"><span class="label">Current multiplier</span><strong id="multiplier">--</strong><small id="prices">--</small></div></div></section>
<div class="section-head"><div><span class="label">Surplus activity</span><h2>Recent sales</h2></div><p id="sales-note">Loading settlement records</p></div>
<section class="panel table-wrap"><table class="sales"><thead><tr><th>Time</th><th>Status</th><th>Model</th><th>Input</th><th>Output</th><th>Cache read</th><th>Revenue</th><th>Base settlement</th></tr></thead><tbody id="sales-body"><tr><td colspan="8" class="empty">Loading sales</td></tr></tbody></table></section>
<footer class="foot"><span id="identity">Seller identity loading</span><span>Vector proves the agent-owned route. Surplus is the current USDC market.</span></footer>
</main>
<script>
(function(){'use strict';
var $=function(id){return document.getElementById(id)};
var set=function(id,value){$(id).textContent=value==null?'--':String(value)};
var usd=function(value){if(value==null||value==='')return'--';var n=Number(value);return Number.isFinite(n)?'$'+n.toFixed(n<.01?6:4):'--'};
var count=function(value){return new Intl.NumberFormat().format(Number(value)||0)};
var short=function(value){var s=String(value||'');return s.length>18?s.slice(0,10)+'…'+s.slice(-7):s||'--'};
var when=function(value){if(!value)return'--';var d=new Date(value);return Number.isNaN(d.getTime())?'--':d.toLocaleString()};
function statusBadge(id,label,live){var el=$(id);el.textContent=label;el.className='badge '+(live?'live':'');}
function link(id,href){var el=$(id);el.href=href;}
function txLink(row,hash){var td=document.createElement('td');if(typeof hash==='string'&&/^0x[0-9a-fA-F]{64}$/.test(hash)){var a=document.createElement('a');a.href='https://basescan.org/tx/'+hash;a.target='_blank';a.rel='noopener noreferrer';a.textContent=short(hash);td.appendChild(a)}else{td.textContent='Accruing'}row.appendChild(td)}
function cell(row,value,className){var td=document.createElement('td');if(className)td.className=className;td.textContent=value==null?'--':String(value);row.appendChild(td)}
function renderSales(sales){var body=$('sales-body');body.replaceChildren();if(!sales.length){var empty=document.createElement('tr');cell(empty,'No sales returned','empty');empty.firstChild.colSpan=8;body.appendChild(empty);return}sales.forEach(function(sale){var row=document.createElement('tr');cell(row,when(sale.createdAt));var status=document.createElement('td');var pill=document.createElement('span');pill.className='status-pill '+sale.settlementStatus;pill.textContent=sale.settlementStatus;status.appendChild(pill);row.appendChild(status);cell(row,sale.model,'mono');cell(row,count(sale.inputTokens));cell(row,count(sale.outputTokens));cell(row,count(sale.cacheReadTokens));cell(row,usd(sale.revenueUsd));txLink(row,sale.transactionHash);body.appendChild(row)})}
function render(data){var c=data.controller,o=data.surplus.offer,e=data.surplus.earnings,p=data.provider,v=data.vector;statusBadge('controller-badge',c.phase,c.ok);statusBadge('surplus-badge',o.status,o.available&&o.healthy);set('updated','Updated '+when(data.generatedAt));set('flow-allowance',usd(p.remainingUsd)+' of '+usd(p.hardLimitUsd)+' remaining');set('flow-provider-model',o.providerModel);set('flow-wallet',short(data.identity.sellerWallet));set('flow-surplus',(o.available?'Available':'Unavailable')+' · '+(o.healthy?'healthy':'not healthy'));set('flow-offer',o.id);set('earned',usd(e.totalUsd));set('earnings-state',usd(e.pendingUsd)+' pending · '+usd(e.paidUsd)+' paid');set('requests',count(e.requests));set('tokens',count(e.tokens)+' tokens');set('rank',o.rank==null?'--':'#'+o.rank);set('market-state',(o.trusted?'trusted':'untrusted')+' · '+count(o.trades24h)+' trades / 24h');set('daily-cap',usd(o.dailyCapUsd));set('cap-remaining',usd(o.capRemainingUsd)+' remaining');set('provider-remaining',usd(p.remainingUsd));set('provider-used',usd(p.usedUsd)+' used of '+usd(p.hardLimitUsd));set('provider-reserve',usd(p.reserveUsd));set('provider-exposure',usd(p.estimatedDailyExposureUsd));set('multiplier',o.costMultiplier==null?'--':(o.costMultiplier*100).toFixed(3)+'%');set('prices',usd(o.inputUsdPer1m)+' in · '+usd(o.outputUsdPer1m)+' out / 1M');set('vector-earned',v.historicalAp3xEarned+' AP3X');set('vector-jobs',count(v.historicalSettledJobs));set('vector-spend',usd(v.historicalUpstreamSpendUsd));set('vector-date',v.retiredOn);set('vector-advert',v.advertRef);set('vector-retirement',v.retirementTransaction);var advertHash=String(v.advertRef).split('#')[0];link('advert-link','https://vector.apexscan.org/en/transaction/'+advertHash+'/summary/');link('retirement-link','https://vector.apexscan.org/en/transaction/'+v.retirementTransaction+'/summary/');set('identity','Surplus '+short(data.identity.sellerWallet)+' · payout '+short(data.identity.payoutAddress));set('sales-note',count(e.requests)+' lifetime requests · '+count(e.tokens)+' tokens');var hold=$('payout-hold');if(e.payoutHoldReason){hold.className='alert visible';hold.textContent='Payout hold: '+e.payoutHoldReason+(e.payoutHoldReleasesAt?' · releases '+when(e.payoutHoldReleasesAt):'')}else{hold.className='alert'}var error=$('controller-error');if(c.lastError){error.className='alert visible';error.textContent='Controller: '+c.lastError}else{error.className='alert'}renderSales(data.surplus.recentSales)}
async function refresh(){try{var response=await fetch('/dashboard/api',{cache:'no-store'});if(!response.ok)throw new Error('Dashboard API returned '+response.status);render(await response.json())}catch(error){statusBadge('controller-badge','data unavailable',false);set('updated',error instanceof Error?error.message:'Dashboard data unavailable')}}
refresh();setInterval(refresh,15000);
})();
</script>
</body>
</html>`;
}

View File

@@ -201,6 +201,9 @@ describe("SurplusClient", () => {
healthy: true, healthy: true,
trusted: true, trusted: true,
trades_24h: 7, trades_24h: 7,
rank: 1,
cap_remaining: null,
volume_24h: 0,
}], }],
}); });
}); });
@@ -222,6 +225,79 @@ describe("SurplusClient", () => {
expect(String(fetchFn.mock.calls[1][0])).toContain("alpha%3Amodel"); expect(String(fetchFn.mock.calls[1][0])).toContain("alpha%3Amodel");
}); });
it("normalizes live earnings, payout hold, and settlement records", async () => {
const client = new SurplusClient({
apiBaseUrl: "https://api.surplusintelligence.ai",
sellerApiKey: SELLER_KEY,
timeoutMs: 1_000,
fetchFn: async () => Response.json({
total_earned_usdc: "186810",
pending_usdc: "176817",
paid_usdc: "9993",
daily: [{
day: "2026-08-27",
earned_usd: 0.18681,
input_tokens: 100,
output_tokens: 20,
requests: 3,
total_tokens: 120,
}],
by_model: [{
model: "alpha",
earned_usd: 0.18681,
requests: 3,
total_tokens: 120,
last_sale_at: 1787831146968,
}],
share: {
requests: 3,
tokens: 120,
top_model: "alpha",
},
recent_sales: [{
id: "sale-1",
model: "alpha",
offer_id: "offer-1",
settlement_status: "confirmed",
created_at: 1787831146968,
seller_cost_usdc: "83",
input_tokens: 10,
output_tokens: 2,
cache_read_tokens: 4,
effective_input_per_1m: 0.004,
effective_output_per_1m: 0.008,
tx_hash: "0x" + "a".repeat(64),
}],
payout_hold: {
reason: "new_seller",
releases_at: "2026-08-29T11:24:42.552Z",
},
}),
});
const earnings = await client.getEarnings();
expect(earnings).toMatchObject({
totalEarnedMicroUsd: 186_810,
pendingMicroUsd: 176_817,
paidMicroUsd: 9_993,
requestCount: 3,
tokenCount: 120,
topModel: "alpha",
payoutHoldReason: "new_seller",
});
expect(earnings.daily[0]).toMatchObject({ requests: 3, totalTokens: 120 });
expect(earnings.recentSales[0]).toMatchObject({
id: "sale-1",
settlementStatus: "confirmed",
cacheReadTokens: 4,
sellerCostMicroUsd: 83,
});
expect(earnings.recentSales[0].createdAt).toBe(
new Date(1787831146968).toISOString(),
);
});
it("sends one absolute cost-multiplier PATCH with the cap", async () => { it("sends one absolute cost-multiplier PATCH with the cap", async () => {
let request: RequestInit | undefined; let request: RequestInit | undefined;
const client = new SurplusClient({ const client = new SurplusClient({

View File

@@ -114,6 +114,9 @@ class FakeSurplusClient implements SurplusControllerClient {
healthy: true, healthy: true,
trusted: true, trusted: true,
trades24h: 0, trades24h: 0,
rank: 1,
capRemainingMicroUsd: null,
volume24hMicroUsd: 0,
}]; }];
if (this.offer) { if (this.offer) {
offers.push({ offers.push({
@@ -126,6 +129,9 @@ class FakeSurplusClient implements SurplusControllerClient {
healthy: true, healthy: true,
trusted: true, trusted: true,
trades24h: this.trades24h, trades24h: this.trades24h,
rank: 2,
capRemainingMicroUsd: 50_000,
volume24hMicroUsd: 0,
}); });
} }
return { model, offers }; return { model, offers };
@@ -187,12 +193,26 @@ class FakeSurplusClient implements SurplusControllerClient {
totalEarnedMicroUsd: this.settled ? 100 : 0, totalEarnedMicroUsd: this.settled ? 100 : 0,
pendingMicroUsd: 0, pendingMicroUsd: 0,
paidMicroUsd: this.settled ? 100 : 0, paidMicroUsd: this.settled ? 100 : 0,
daily: [],
byModel: [],
requestCount: this.settled ? 1 : 0,
tokenCount: this.settled ? 2 : 0,
topModel: this.settled ? "beta-model" : null,
payoutHoldReason: null,
payoutHoldReleasesAt: null,
recentSales: this.settled ? [{ recentSales: this.settled ? [{
id: "sale-1",
model: "beta-model", model: "beta-model",
offerId: "managed-offer", offerId: "managed-offer",
settlementStatus: "confirmed", settlementStatus: "confirmed",
createdAt: "2026-08-27T10:00:01.000Z", createdAt: "2026-08-27T10:00:01.000Z",
sellerCostMicroUsd: 100, sellerCostMicroUsd: 100,
inputTokens: 1,
outputTokens: 1,
cacheReadTokens: 0,
effectiveInputUsdPer1m: 0.003972,
effectiveOutputUsdPer1m: 0.007944,
transactionHash: "0x" + "a".repeat(64),
}] : [], }] : [],
}; };
} }

View File

@@ -0,0 +1,259 @@
import { describe, expect, it, vi } from "vitest";
import request from "supertest";
import type { SurplusManagerConfig } from "../../supplier/src/surplus/config.js";
import {
SurplusDashboardService,
type SurplusDashboardSnapshot,
} from "../../supplier/src/surplus/dashboard.js";
import { renderSurplusDashboardPage } from "../../supplier/src/surplus/dashboardPage.js";
import { createSurplusServer } from "../../supplier/src/cli/surplus-seller.js";
import type { SurplusControllerStatus } from "../../supplier/src/surplus/controller.js";
const STATUS: SurplusControllerStatus = {
ok: true,
phase: "active",
live: true,
model: "deepseek-v4-flash",
providerModelId: "deepseek/deepseek-v4-flash",
offerId: "offer-1",
inputUsdPer1m: "0.003972",
outputUsdPer1m: "0.007944",
competitorId: "external",
remainingAllowanceUsd: "16.313443",
reserveThresholdUsd: "1.00",
totalEarnedUsd: "0.186810",
lastCycleAt: "2026-08-28T12:00:00.000Z",
lastSuccessAt: "2026-08-28T12:00:00.000Z",
lastError: null,
};
function config(): SurplusManagerConfig {
return {
live: true,
apiBaseUrl: "https://api.surplusintelligence.ai",
sellerApiKey: "si_seller_test_secret",
providerApiKey: "sk-or-v1-test-secret",
providerBaseUrl: "https://openrouter.ai/api/v1",
capacityBaseUrl: "https://openrouter.ai/api",
perOfferCapUsd: "0.05",
aggregateCapUsd: "0.05",
sellerWallet: "0x1111111111111111111111111111111111111111",
payoutAddress: "0x1111111111111111111111111111111111111111",
maxCandidateOrderBooks: 10,
reserveUsd: "1.00",
maxProviderLimitUsd: "20.00",
recoveryBps: 490,
undercutBps: 10,
pollIntervalMs: 300_000,
requestTimeoutMs: 120_000,
stopAfterTrades: 0,
settledStatuses: ["confirmed"],
statePath: "/tmp/surplus-dashboard-test.json",
port: 8080,
};
}
function snapshot(): SurplusDashboardSnapshot {
return {
generatedAt: "2026-08-28T12:00:00.000Z",
controller: STATUS,
identity: {
sellerWallet: "0x1111111111111111111111111111111111111111",
payoutAddress: "0x1111111111111111111111111111111111111111",
},
provider: {
name: "OpenRouter",
hardLimitUsd: "20.000000",
remainingUsd: "16.313443",
usedUsd: "3.686557",
reserveUsd: "1.00",
estimatedDailyExposureUsd: "1.020408",
},
surplus: {
offer: {
id: "offer-1",
model: "deepseek-v4-flash",
providerModel: "deepseek/deepseek-v4-flash",
status: "active",
dailyCapUsd: "0.050000",
costMultiplier: 0.04995,
inputUsdPer1m: "0.003972",
outputUsdPer1m: "0.007944",
rank: 10,
available: true,
healthy: true,
trusted: true,
trades24h: 429,
volume24hUsd: "0.064030",
capRemainingUsd: "0.050000",
},
earnings: {
totalUsd: "0.186810",
pendingUsd: "0.176817",
paidUsd: "0.009993",
requests: 1_093,
tokens: 104_698_905,
today: null,
topModel: "deepseek-v4-flash",
payoutHoldReason: "new_seller",
payoutHoldReleasesAt: "2026-08-29T11:24:42.552Z",
},
recentSales: [],
},
vector: {
status: "retired",
model: "deepseek/deepseek-v4-flash",
supplierWallet: "addr1test",
advertRef: `${"a".repeat(64)}#0`,
retirementTransaction: "b".repeat(64),
retiredOn: "2026-08-27",
historicalAp3xEarned: "1.600000",
historicalSettledJobs: 8,
historicalUpstreamSpendUsd: "0.000093",
},
};
}
describe("SurplusDashboardService", () => {
it("combines safe live metrics with the Vector migration record", async () => {
const listAllOffers = vi.fn(async () => [{
id: "offer-1",
model: "deepseek-v4-flash",
sellerBaseUrl: "https://openrouter.ai/api/v1",
status: "active" as const,
capDailyUsd: 0.05,
costMultiplierPpm: 49_950,
inputMicroUsdPer1m: 3_972,
outputMicroUsdPer1m: 7_944,
}]);
const getEarnings = vi.fn(async () => ({
totalEarnedMicroUsd: 186_810,
pendingMicroUsd: 176_817,
paidMicroUsd: 9_993,
daily: [{
day: "2026-08-28",
earnedUsd: 0.01,
inputTokens: 10,
outputTokens: 2,
requests: 1,
totalTokens: 12,
}],
byModel: [],
requestCount: 1_093,
tokenCount: 104_698_905,
topModel: "deepseek-v4-flash",
payoutHoldReason: "new_seller",
payoutHoldReleasesAt: "2026-08-29T11:24:42.552Z",
recentSales: [{
id: "sale-1",
model: "deepseek-v4-flash",
offerId: "offer-1",
settlementStatus: "confirmed",
createdAt: "2026-08-28T11:00:00.000Z",
sellerCostMicroUsd: 83,
inputTokens: 10,
outputTokens: 2,
cacheReadTokens: 3,
effectiveInputUsdPer1m: 0.003972,
effectiveOutputUsdPer1m: 0.007944,
transactionHash: "0x" + "c".repeat(64),
}],
}));
const getOrderBook = vi.fn(async () => ({
model: "deepseek-v4-flash",
offers: [{
id: "offer-1",
seller: "0x1111111111111111111111111111111111111111",
sellerBaseUrl: "https://openrouter.ai/api/v1",
inputMicroUsdPer1m: 3_972,
outputMicroUsdPer1m: 7_944,
available: true,
healthy: true,
trusted: true,
trades24h: 429,
rank: 10,
capRemainingMicroUsd: 50_000,
volume24hMicroUsd: 64_030,
}],
}));
const service = new SurplusDashboardService({
controller: { snapshot: () => STATUS },
client: { listAllOffers, getEarnings, getOrderBook },
allowance: {
readAllowance: async () => ({
limitUsdNanos: 20_000_000_000n,
remainingUsdNanos: 16_313_443_131n,
reset: null,
checkedAtMs: Date.parse("2026-08-28T12:00:00.000Z"),
}),
},
config: config(),
now: () => Date.parse("2026-08-28T12:00:00.000Z"),
});
const first = await service.getSnapshot();
const second = await service.getSnapshot();
expect(first.surplus.offer).toMatchObject({
id: "offer-1",
rank: 10,
available: true,
dailyCapUsd: "0.050000",
});
expect(first.surplus.earnings).toMatchObject({
totalUsd: "0.186810",
requests: 1_093,
topModel: "deepseek-v4-flash",
});
expect(first.provider).toMatchObject({
usedUsd: "3.686556",
estimatedDailyExposureUsd: "1.020408",
});
expect(first.vector).toMatchObject({ status: "retired", historicalSettledJobs: 8 });
expect(first.surplus.recentSales[0]).toMatchObject({
settlementStatus: "confirmed",
revenueUsd: "0.000083",
});
expect(JSON.stringify(first)).not.toContain("si_seller_test_secret");
expect(JSON.stringify(first)).not.toContain("sk-or-v1-test-secret");
expect(second).toBe(first);
expect(listAllOffers).toHaveBeenCalledTimes(1);
expect(getEarnings).toHaveBeenCalledTimes(1);
expect(getOrderBook).toHaveBeenCalledTimes(1);
});
});
describe("unified dashboard HTTP surface", () => {
it("serves the dashboard, cached API data, and security headers", async () => {
const data = snapshot();
const server = createSurplusServer(
{ snapshot: () => STATUS, healthy: () => true },
{ getSnapshot: async () => data },
);
const page = await request(server).get("/reseller");
expect(page.status).toBe(200);
expect(page.text).toContain("One capacity pool.");
expect(page.text).toContain("Vector marketplace");
expect(page.headers["content-security-policy"]).toContain("frame-ancestors 'none'");
const api = await request(server).get("/dashboard/api");
expect(api.status).toBe(200);
expect(api.body).toEqual(data);
expect(JSON.stringify(api.body)).not.toContain("test-secret");
const root = await request(server).get("/");
expect(root.status).toBe(302);
expect(root.headers.location).toBe("/reseller");
server.close();
});
it("renders static HTML without embedding credentials", () => {
const html = renderSurplusDashboardPage();
expect(html).toContain("/dashboard/api");
expect(html).toContain("Surplus Intelligence");
expect(html).toContain("Vector marketplace");
expect(html).not.toContain("si_seller_");
expect(html).not.toContain("sk-or-v1-");
});
});