Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a15f5c9
launch list, detail, stats and swaps endpoints (EKU-827)
moodysalem Oct 6, 2026
da96bb2
add frozen zero-seed API schemas and local policy guards
Paperclip-Paperclip Oct 11, 2026
1af28a8
replace staged launch API with frozen zero-seed indexed reads
Paperclip-Paperclip Oct 11, 2026
bd06ee3
update route parameter census for cursor-based launch reads
Paperclip-Paperclip Oct 11, 2026
faf0316
Accept any integer form of launch path parameters
moodysalem Oct 19, 2026
661351c
Pass the formatter and linter, and follow the refreshed indexer harness
moodysalem Oct 19, 2026
35c22bd
Serve the draft exponential creator-fee decay in launch reads
moodysalem Oct 19, 2026
2429547
Serve native-ETH zero-seed launches with periphery owners (schema v3)
moodysalem Oct 20, 2026
4b1e5b1
Serve requested, installed and sink supply and per-launch quotes (lau…
moodysalem Oct 21, 2026
8f18246
Document launch schema v4 and the per-launch quote policy
moodysalem Oct 21, 2026
cf05546
Serve zero-seed launches of evm-contracts 550afc4: full uint64 creato…
moodysalem Oct 22, 2026
620aa11
Serve zero-seed launches of evm-contracts 43d6628: exact token0 insta…
moodysalem Oct 22, 2026
f96998a
Merge main into the zero-seed launch endpoints branch
moodysalem Oct 22, 2026
5e261c7
Pin the launch replay to indexer 03e95fd, where the launch migration …
moodysalem Oct 22, 2026
86af4e7
Merge main (oxfmt, oxlint and wrangler bumps) into the zero-seed laun…
moodysalem Oct 24, 2026
06fc548
Serve the tick-rate launch fee model as response contract v5
moodysalem Oct 24, 2026
dd4481f
Serve only the final zero-seed launch as response contract v6
moodysalem Oct 25, 2026
c05481a
Replay the indexer's final launch chain through the launch routes
moodysalem Oct 25, 2026
a0738c4
Pin the launch replay to the indexer's documented final launch commit
moodysalem Oct 25, 2026
90d13a6
Serve launch volume, list orders and market aggregates as contract v7
moodysalem Oct 26, 2026
75ee5be
Replay launch-token logs through the indexer's discovered-address fil…
moodysalem Oct 26, 2026
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
2 changes: 1 addition & 1 deletion .oxfmtrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
"trailingComma": "all",
"printWidth": 80,
"sortPackageJson": false,
"ignorePatterns": ["openapi.json"]
"ignorePatterns": ["openapi.json", "src/routes/launches/vectors/**"]
}
2,454 changes: 2,454 additions & 0 deletions openapi.json

Large diffs are not rendered by default.

220 changes: 220 additions & 0 deletions src/contract/cases/launches.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
import { ContractCase, stubQuery } from "../harness";
import { LOCAL_INSTANCES } from "../../routes/launches/policy";

const NATIVE = "0x0000000000000000000000000000000000000000" as const;
const VERSION = "zero-seed-launch-api/v7" as const;

const pin = LOCAL_INSTANCES[0];
const owner = `0x${"2".repeat(40)}`;
const zero = `0x${"0".repeat(64)}`;
const as_of = { block_number: "1", block_hash: zero, block_time: 1000 };
const summary = {
schema_version: VERSION,
chain_id: "31337",
pool_id: zero,
pool_key: {
core_address: pin.core,
token0: NATIVE,
token1: `0x${"1".repeat(40)}`,
config: zero,
fee: "0" as const,
tick_spacing: 17990,
extension: pin.address,
},
token: {
address: `0x${"1".repeat(40)}`,
name: "Zero Seed",
symbol: "ZERO",
decimals: 18 as const,
},
quote_token: {
address: NATIVE,
name: null,
symbol: null,
decimals: 18,
kind: "native" as const,
},
launch_token_is_token1: true,
controller: pin.periphery,
creator: owner,
owner,
logo_url: null,
parameters: {
name: "0x095a65726f205365656400000000000000000000000000000000000000000000",
symbol:
"0x045a45524f000000000000000000000000000000000000000000000000000000",
supply: "1000000000000000000000000000",
quote_token: NATIVE,
ask_tick: "-13815500",
upper_tick: "-9210300",
trading_start: "1000",
decay_rate_x32: "68913100933",
initial_fee: "9223372036854775808",
final_fee: "55340232221128654",
salt: zero,
},
range: {
tick_spacing: 17990,
aligned_ask_tick: -13798330,
aligned_upper_tick: -9210880,
pool_tick_lower: 9210880,
pool_tick_upper: 13798330,
},
supply: {
requested: "1000000000000000000000000000",
installed: "999999999999999999999999508",
sink: "492",
sink_holder: NATIVE,
},
trading_start: 1000,
status: "trading" as const,
fee_schedule: {
trading_start: 1000,
initial_fee: "9223372036854775808",
final_fee: "55340232221128654",
decay_rate_x32: "68913100933",
half_life_seconds: "86400.000001",
saturation_elapsed_seconds: "5529597",
phase: "decaying" as const,
fee_rate: "9223372036854775808",
evaluated_at: 1000,
},
market: {
price_tick: -13798330,
price_x128: "340282366920938463463374607431768",
market_cap: "1000000000000000000000",
market_cap_usd: null,
raised: "0",
sold: "0",
sold_share: "0.000000000000000000",
trade_count: 0,
volume: "0",
volume_usd: null,
},
created: {
...as_of,
event_id: "-1",
transaction_index: 0,
event_index: 0,
transaction_hash: zero,
},
as_of,
};
const ledger = { accrued: "0", claimed: "0", unclaimed: "0" };
const identity = {
schema_version: VERSION,
chain_id: "31337",
pool_id: zero,
as_of,
next_cursor: null,
};
const path = `/launches/31337/${zero}`;
export const launchesCases: ContractCase[] = [
{
operation: "/launches",
request: "/launches?status=trading",
stub: () =>
stubQuery("readZeroSeedList", {
schema_version: VERSION,
data: [
summary,
{
...summary,
logo_url: "https://example.invalid/logo.svg",
status: "upcoming",
},
],
total: 2,
totals: { all: 2, trading: 1, upcoming: 1 },
aggregates: {
launch_count: 2,
trade_count: 0,
by_quote: [
{
chain_id: "31337",
quote_token: NATIVE,
launch_count: 2,
trade_count: 0,
volume: "0",
market_cap: "2000000000000000000000",
usd_priced: false,
volume_usd: null,
market_cap_usd: null,
},
],
usd: {
volume: null,
market_cap: null,
priced_launch_count: 0,
excluded_launch_count: 2,
},
},
next_offset: null,
evaluated_at: 1000,
heads: [{ chain_id: "31337", ...as_of }],
}),
},
{
operation: "/launches/{chainId}/{poolId}",
request: path,
stub: () =>
stubQuery("readZeroSeedDetail", {
...summary,
principal: {
position_id: zero,
liquidity: "100",
locked: true,
withdrawable: false,
pool_reserves: { launch_token: "1000", quote_token: "0" },
},
fee_ledger: {
holder: owner,
launch_token: ledger,
quote_token: ledger,
swap_count: 0,
claim_count: 0,
owner_change_count: 1,
last_event_id: "-1",
},
}),
},
{
operation: "/launches/{chainId}/{poolId}/swaps",
request: `${path}/swaps`,
stub: () => stubQuery("readZeroSeedSwaps", { ...identity, data: [] }),
},
{
operation: "/launches/{chainId}/{poolId}/claims",
request: `${path}/claims`,
stub: () =>
stubQuery("readZeroSeedClaims", {
...identity,
data: [
{
event: summary.created,
payout_event_id: "1",
owner,
recipient: owner,
launch_token_amount: "0",
quote_token_amount: "5",
},
],
totals: { launch_token: "0", quote_token: "5" },
}),
},
{
operation: "/launches/{chainId}/{poolId}/owners",
request: `${path}/owners`,
stub: () =>
stubQuery("readZeroSeedOwners", {
...identity,
data: [
{
event: summary.created,
previous_owner: null,
new_owner: owner,
},
],
}),
},
];
25 changes: 25 additions & 0 deletions src/queries.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import postgres, { type Sql } from "postgres";
import { Env } from "./env";
import {
LaunchQueries,
type LaunchListOptions,
type LaunchReadOptions,
} from "./routes/launches/queries";

export type StateFilter = "opened" | "closed";

Expand Down Expand Up @@ -197,6 +202,26 @@ export class Queries {
this.sql = sql;
}

public readZeroSeedList(input: LaunchListOptions) {
return new LaunchQueries(this.sql).list(input);
}

public readZeroSeedDetail(chainId: bigint, poolId: bigint) {
return new LaunchQueries(this.sql).detail(chainId, poolId);
}

public readZeroSeedSwaps(input: LaunchReadOptions & { poolId: bigint }) {
return new LaunchQueries(this.sql).swaps(input);
}

public readZeroSeedClaims(input: LaunchReadOptions & { poolId: bigint }) {
return new LaunchQueries(this.sql).claims(input);
}

public readZeroSeedOwners(input: LaunchReadOptions & { poolId: bigint }) {
return new LaunchQueries(this.sql).owners(input);
}

public async listErc20Tokens({
minVisibilityPriority,
pageSize,
Expand Down
2 changes: 2 additions & 0 deletions src/responseSchemas.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { stateCases } from "./contract/cases/state";
import { statsCases } from "./contract/cases/stats";
import { twammCases } from "./contract/cases/twamm";
import { ve33Cases } from "./contract/cases/ve33";
import { launchesCases } from "./contract/cases/launches";

const cases: ContractCase[] = [
...metaCases,
Expand All @@ -30,6 +31,7 @@ const cases: ContractCase[] = [
...auctionsCases,
...governanceCases,
...ve33Cases,
...launchesCases,
...incentivesCases,
];

Expand Down
6 changes: 3 additions & 3 deletions src/router.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ describe("Hono app integration", () => {
),
);

expect(Object.keys(schema.paths ?? {})).toHaveLength(59);
expect(operations).toHaveLength(59);
expect(Object.keys(schema.paths ?? {})).toHaveLength(64);
expect(operations).toHaveLength(64);
expect(
operations.reduce(
(count, operation) => count + (operation.parameters?.length ?? 0),
0,
),
).toBe(198);
).toBe(219);

const getToken = operations.find(
(operation) =>
Expand Down
12 changes: 12 additions & 0 deletions src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ import {
GetAuctionNftState,
ListAuctions,
} from "./routes/auctions";
import {
GetLaunch,
ListLaunchClaims,
ListLaunches,
ListLaunchOwners,
ListLaunchSwaps,
} from "./routes/launches";
import {
ListVe33Pools,
ListVe33TokensByAddress,
Expand Down Expand Up @@ -123,6 +130,11 @@ const routes: readonly ApiRoute[] = [
GetAuctionNftMetadata,
GetAuctionNftState,
GetAuctionNftImage,
ListLaunches,
ListLaunchClaims,
ListLaunchOwners,
ListLaunchSwaps,
GetLaunch,
ListProposals,
ListTopDelegates,
ListVotesOnProposal,
Expand Down
Loading
Loading