Skip to content

Commit aef6034

Browse files
Gii2000claude
andauthored
perf: [PR-1484] remove sf buy, sf sell, and sf orders (#247)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1699a7b commit aef6034

24 files changed

Lines changed: 140 additions & 2213 deletions

src/helpers/fetchers.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,3 @@ export async function getContract(contractId: string) {
1313
}
1414
return data;
1515
}
16-
17-
export async function getOrder(orderId: string) {
18-
const api = await apiClient();
19-
const { data, response, error } = await api.GET("/v0/orders/{id}", {
20-
params: {
21-
path: { id: orderId },
22-
},
23-
});
24-
if (!response.ok) {
25-
// @ts-expect-error -- TODO: FIXME: include error in OpenAPI schema output
26-
if (error?.code === "order.not_found") {
27-
return null;
28-
}
29-
return logAndQuit(`Failed to get order: ${response.statusText}`);
30-
}
31-
return data;
32-
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import {
66
startOfDay,
77
} from "date-fns";
88
import dayjs, { type Dayjs } from "dayjs";
9+
import duration from "dayjs/plugin/duration";
910
import utc from "dayjs/plugin/utc";
1011
import { formatDateRange } from "little-date";
1112

1213
dayjs.extend(utc);
14+
dayjs.extend(duration);
1315

1416
const shortenAmPm = (text: string): string => {
1517
const shortened = (text || "").replace(/ AM/g, "am").replace(/ PM/g, "pm");
@@ -133,3 +135,30 @@ export const formatDateAsUTC = (date: Dayjs): string => {
133135

134136
return `${utcDate.format("MMM D")}, ${timeStr} UTC`;
135137
};
138+
139+
/**
140+
* Formats a duration in milliseconds to a compact string like "1d2h30m".
141+
*/
142+
export function formatDuration(ms: number) {
143+
const d = dayjs.duration(ms);
144+
145+
const years = Math.floor(d.asYears());
146+
const weeks = Math.floor(d.asWeeks()) % 52;
147+
const days = d.days();
148+
const hours = d.hours();
149+
const minutes = d.minutes();
150+
const seconds = d.seconds();
151+
const milliseconds = d.milliseconds();
152+
153+
let result = "";
154+
155+
if (years > 0) result += `${years}y`;
156+
if (weeks > 0) result += `${weeks}w`;
157+
if (days > 0) result += `${days}d`;
158+
if (hours > 0) result += `${hours}h`;
159+
if (minutes > 0) result += `${minutes}m`;
160+
if (seconds > 0) result += `${seconds}s`;
161+
if (milliseconds > 0) result += `${milliseconds}ms`;
162+
163+
return result || "0ms";
164+
}

src/helpers/quote.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import dayjs from "dayjs";
2+
import { apiClient } from "../apiClient.ts";
3+
import { GPUS_PER_NODE } from "../lib/constants.ts";
4+
import type { components } from "../schema.ts";
5+
import { logAndQuit, logSessionTokenExpiredAndQuit } from "./errors.ts";
6+
import { parseStartDateOrNow, roundDateUpToNextMinute } from "./units.ts";
7+
8+
export function getPricePerGpuHourFromQuote(
9+
quote: Pick<NonNullable<Quote>, "start_at" | "end_at" | "price" | "quantity">,
10+
) {
11+
const startTimeOrNow = parseStartDateOrNow(quote.start_at);
12+
13+
// from the market's perspective, "NOW" means at the beginning of the next minute.
14+
// when the order duration is very short, this can cause the rate to be computed incorrectly
15+
// if we implicitly assume it to mean `new Date()`.
16+
const coercedStartTime =
17+
startTimeOrNow === "NOW"
18+
? roundDateUpToNextMinute(new Date())
19+
: startTimeOrNow;
20+
const durationSeconds = dayjs(quote.end_at).diff(dayjs(coercedStartTime));
21+
const durationHours = durationSeconds / 3600 / 1000;
22+
23+
return quote.price / GPUS_PER_NODE / quote.quantity / durationHours;
24+
}
25+
26+
export async function getQuote(options: {
27+
instanceType?: string;
28+
quantity: number;
29+
minStartTime: Date | "NOW";
30+
maxStartTime: Date | "NOW";
31+
minDurationSeconds: number;
32+
maxDurationSeconds: number;
33+
cluster?: string;
34+
colocateWith?: string;
35+
}) {
36+
const api = await apiClient();
37+
38+
const params = {
39+
query: {
40+
side: "buy",
41+
instance_type: options.instanceType,
42+
quantity: options.quantity,
43+
min_start_date:
44+
options.minStartTime === "NOW"
45+
? ("NOW" as const)
46+
: options.minStartTime.toISOString(),
47+
max_start_date:
48+
options.maxStartTime === "NOW"
49+
? ("NOW" as const)
50+
: options.maxStartTime.toISOString(),
51+
min_duration: options.minDurationSeconds,
52+
max_duration: options.maxDurationSeconds,
53+
cluster: options.cluster,
54+
colocate_with: options.colocateWith,
55+
},
56+
} as const;
57+
58+
const { data, error, response } = await api.GET("/v0/quote", {
59+
params,
60+
// timeout after 600 seconds
61+
signal: AbortSignal.timeout(600 * 1000),
62+
});
63+
64+
if (!response.ok) {
65+
switch (response.status) {
66+
case 400:
67+
return logAndQuit(`Bad Request: ${JSON.stringify(error, null, 2)}`);
68+
case 401:
69+
return await logSessionTokenExpiredAndQuit();
70+
case 500:
71+
return logAndQuit(
72+
`Failed to get quote: ${JSON.stringify(error, null, 2)}`,
73+
);
74+
default:
75+
return logAndQuit(`Failed to get quote: ${response.statusText}`);
76+
}
77+
}
78+
79+
if (!data) {
80+
return logAndQuit(
81+
`Failed to get quote: Unexpected response from server: ${response}`,
82+
);
83+
}
84+
85+
if (!data.quote) {
86+
return null;
87+
}
88+
89+
return {
90+
...data.quote,
91+
price: Number(data.quote.price),
92+
quantity: Number(data.quote.quantity),
93+
start_at: data.quote.start_at,
94+
end_at: data.quote.end_at,
95+
};
96+
}
97+
98+
export type Quote = components["schemas"]["quoter_ApiQuoteDetails"] | null;

src/helpers/units.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import dayjs from "dayjs";
55
import timezone from "dayjs/plugin/timezone";
66
import utc from "dayjs/plugin/utc";
77
import type { Nullable } from "../types/empty.ts";
8-
import { formatDate, formatDateAsUTC } from "./format-date.ts";
8+
import { formatDate, formatDateAsUTC } from "./format-time.ts";
99

1010
dayjs.extend(utc);
1111
dayjs.extend(timezone);

src/helpers/urls.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ const apiPaths: Record<string, Path<IdParams | never>> = {
2222
me: "/v0/me",
2323
ping: "/v0/ping",
2424

25-
orders_list: "/v0/orders",
26-
orders_get: ({ id }: IdParams): string => `/v0/orders/${id}`,
27-
orders_cancel: ({ id }: IdParams): string => `/v0/orders/${id}`,
28-
2925
quote_get: "/v0/quote",
3026

3127
instances_list: "/v0/instances",

src/index.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,13 @@ import { checkVersion } from "./checkVersion.ts";
1717
import { loadConfig, saveConfig } from "./helpers/config.ts";
1818
import { getAppBanner } from "./lib/app-banner.ts";
1919
import { registerBalance } from "./lib/balance.ts";
20-
import { registerBuy } from "./lib/buy/index.tsx";
2120
import { registerContracts } from "./lib/contracts/index.tsx";
2221
import { registerDev } from "./lib/dev.ts";
23-
import { registerExtend } from "./lib/extend/index.tsx";
2422
import { registerLogin } from "./lib/login.ts";
2523
import { registerMe } from "./lib/me.ts";
2624
import { registerNodes } from "./lib/nodes/index.ts";
27-
import { registerOrders } from "./lib/orders/index.tsx";
2825
import { analytics, IS_TRACKING_DISABLED } from "./lib/posthog.ts";
2926
import { registerScale } from "./lib/scale/index.tsx";
30-
import { registerSell } from "./lib/sell.ts";
3127
import { registerTokens } from "./lib/tokens.ts";
3228
import { registerUpgrade } from "./lib/upgrade.ts";
3329
import { registerVM } from "./lib/vm/index.ts";
@@ -47,11 +43,7 @@ async function main() {
4743

4844
// commands
4945
registerLogin(program);
50-
registerBuy(program);
51-
registerExtend(program);
52-
registerOrders(program);
5346
registerContracts(program);
54-
registerSell(program);
5547
registerBalance(program);
5648
registerTokens(program);
5749
registerUpgrade(program);

src/lib/Quote.tsx

Lines changed: 0 additions & 55 deletions
This file was deleted.

0 commit comments

Comments
 (0)