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
18 changes: 9 additions & 9 deletions src/routes/hyperliquid/markets.sql
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ WITH
FROM {db_hypercore:Identifier}.state_ohlcv_fills
WHERE interval_min = 60
AND timestamp >= now() - INTERVAL 24 HOUR
AND (isNull({coin:Nullable(String)}) OR coin = {coin:Nullable(String)})
AND (isNull({dex:Nullable(String)}) OR dex_from_coin(coin) = {dex:Nullable(String)})
AND (empty({coin:Array(String)}) OR coin IN {coin:Array(String)})
AND (empty({dex:Array(String)}) OR dex_from_coin(coin) IN {dex:Array(String)})
GROUP BY coin
),
uu_24h AS (
Expand All @@ -22,8 +22,8 @@ WITH
FROM {db_hypercore:Identifier}.state_ohlcv_fills_uniq_user FINAL
WHERE interval_min = 1440
AND timestamp >= now() - INTERVAL 48 HOUR
AND (isNull({coin:Nullable(String)}) OR coin = {coin:Nullable(String)})
AND (isNull({dex:Nullable(String)}) OR dex_from_coin(coin) = {dex:Nullable(String)})
AND (empty({coin:Array(String)}) OR coin IN {coin:Array(String)})
AND (empty({dex:Array(String)}) OR dex_from_coin(coin) IN {dex:Array(String)})
GROUP BY coin
),
day_prev AS (
Expand All @@ -34,8 +34,8 @@ WITH
WHERE interval_min = 60
AND timestamp >= now() - INTERVAL 48 HOUR
AND timestamp < now() - INTERVAL 24 HOUR
AND (isNull({coin:Nullable(String)}) OR coin = {coin:Nullable(String)})
AND (isNull({dex:Nullable(String)}) OR dex_from_coin(coin) = {dex:Nullable(String)})
AND (empty({coin:Array(String)}) OR coin IN {coin:Array(String)})
AND (empty({dex:Array(String)}) OR dex_from_coin(coin) IN {dex:Array(String)})
GROUP BY coin
),
oi_latest AS (
Expand All @@ -47,7 +47,7 @@ WITH
FROM {db_hypercore:Identifier}.open_interest
WHERE interval_min = 60
AND timestamp >= now() - INTERVAL 6 HOUR
AND (isNull({coin:Nullable(String)}) OR coin = {coin:Nullable(String)})
AND (empty({coin:Array(String)}) OR coin IN {coin:Array(String)})
GROUP BY coin
)
SELECT
Expand All @@ -72,8 +72,8 @@ LEFT JOIN day_prev prev ON prev.coin = cur.coin
LEFT JOIN oi_latest oi ON oi.coin = cur.coin
LEFT JOIN uu_24h uu ON uu.coin = cur.coin
LEFT JOIN {db_hypercore:Identifier}.state_spot_pair_names AS n FINAL ON n.coin = cur.coin
WHERE (isNull({base_token:Nullable(String)}) OR n.base_token = {base_token:Nullable(String)})
AND (isNull({quote_token:Nullable(String)}) OR n.quote_token = {quote_token:Nullable(String)})
WHERE (empty({base_token:Array(String)}) OR n.base_token IN {base_token:Array(String)})
AND (empty({quote_token:Array(String)}) OR n.quote_token IN {quote_token:Array(String)})
ORDER BY cur.volume_24h DESC
LIMIT {limit:UInt64}
OFFSET {offset:UInt64}
8 changes: 4 additions & 4 deletions src/routes/hyperliquid/markets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ import { validatorHook, withErrorResponses } from '../../utils.js';
import baseQuery from './markets.sql' with { type: 'text' };

const querySchema = createQuerySchema({
coin: { schema: hyperliquidCoinSchema, optional: true },
dex: { schema: hyperliquidDexIdSchema, optional: true },
base_token: { schema: hyperliquidTokenSchema, optional: true },
quote_token: { schema: hyperliquidTokenSchema, optional: true },
coin: { schema: hyperliquidCoinSchema, batched: true, optional: true },
dex: { schema: hyperliquidDexIdSchema, batched: true, optional: true },
base_token: { schema: hyperliquidTokenSchema, batched: true, optional: true },
quote_token: { schema: hyperliquidTokenSchema, batched: true, optional: true },
});

const responseSchema = apiUsageResponseSchema.extend({
Expand Down
6 changes: 3 additions & 3 deletions src/routes/hyperliquid/markets_activity.sql
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ FROM (
FROM {db_hypercore:Identifier}.fills
WHERE timestamp >= (SELECT t FROM start_ts)
AND timestamp < (SELECT t FROM end_ts)
AND (isNull({user:Nullable(String)}) OR user = {user:Nullable(String)})
AND (isNull({coin:Nullable(String)}) OR coin = {coin:Nullable(String)})
AND (isNull({dex:Nullable(String)}) OR dex = {dex:Nullable(String)})
AND (empty({user:Array(String)}) OR user IN {user:Array(String)})
AND (empty({coin:Array(String)}) OR coin IN {coin:Array(String)})
AND (empty({dex:Array(String)}) OR dex IN {dex:Array(String)})
ORDER BY timestamp DESC, block_num DESC, event_index DESC
LIMIT {limit:UInt64}
OFFSET {offset:UInt64}
Expand Down
8 changes: 4 additions & 4 deletions src/routes/hyperliquid/markets_activity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import { validatorHook, withErrorResponses } from '../../utils.js';
import query from './markets_activity.sql' with { type: 'text' };

const querySchema = createQuerySchema({
coin: { schema: hyperliquidCoinSchema, optional: true },
dex: { schema: hyperliquidDexIdSchema, optional: true },
user: { schema: evmAddressSchema, optional: true },
coin: { schema: hyperliquidCoinSchema, batched: true, optional: true },
dex: { schema: hyperliquidDexIdSchema, batched: true, optional: true },
user: { schema: evmAddressSchema, batched: true, optional: true },
start_time: { schema: timestampSchema, optional: true },
end_time: { schema: timestampSchema, optional: true },
});
Expand Down Expand Up @@ -110,7 +110,7 @@ const route = new Hono<{ Variables: { validatedData: z.infer<typeof querySchema>
route.get('/', openapi, zValidator('query', querySchema, validatorHook), validator('query', querySchema), async (c) => {
const params = c.req.valid('query');

if (!params.coin && !params.dex && !params.user) {
if (!params.coin.length && !params.dex.length && !params.user.length) {
return c.json(
{ status: 400, code: 'bad_query_input', message: 'Provide at least one of coin, dex, or user' },
400
Expand Down
6 changes: 3 additions & 3 deletions src/routes/hyperliquid/markets_liquidations.sql
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ SELECT
FROM {db_hypercore:Identifier}.fills_liquidation AS f
LEFT JOIN {db_hypercore:Identifier}.state_spot_pair_names AS n FINAL ON n.coin = f.coin
WHERE f.user = f.liquidated_user
AND (isNull({coin:Nullable(String)}) OR f.coin = {coin:Nullable(String)})
AND (isNull({dex:Nullable(String)}) OR dex_from_coin(f.coin) = {dex:Nullable(String)})
AND (isNull({liquidated_user:Nullable(String)}) OR f.liquidated_user = {liquidated_user:Nullable(String)})
AND (empty({coin:Array(String)}) OR f.coin IN {coin:Array(String)})
AND (empty({dex:Array(String)}) OR dex_from_coin(f.coin) IN {dex:Array(String)})
AND (empty({liquidated_user:Array(String)}) OR f.liquidated_user IN {liquidated_user:Array(String)})
AND (isNull({start_time:Nullable(UInt64)}) OR f.timestamp >= toDateTime({start_time:Nullable(UInt64)}))
AND (isNull({end_time:Nullable(UInt64)}) OR f.timestamp < toDateTime({end_time:Nullable(UInt64)}))
GROUP BY f.event_hash, f.liquidated_user, f.coin, f.direction
Expand Down
6 changes: 3 additions & 3 deletions src/routes/hyperliquid/markets_liquidations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import { validatorHook, withErrorResponses } from '../../utils.js';
import baseQuery from './markets_liquidations.sql' with { type: 'text' };

const querySchema = createQuerySchema({
coin: { schema: hyperliquidCoinSchema, optional: true },
dex: { schema: hyperliquidDexIdSchema, optional: true },
liquidated_user: { schema: evmAddressSchema, optional: true },
coin: { schema: hyperliquidCoinSchema, batched: true, optional: true },
dex: { schema: hyperliquidDexIdSchema, batched: true, optional: true },
liquidated_user: { schema: evmAddressSchema, batched: true, optional: true },
sort_by: { schema: hyperliquidLiquidationSortBySchema, prefault: 'notional' },
start_time: { schema: timestampSchema, optional: true },
end_time: { schema: timestampSchema, optional: true },
Expand Down
4 changes: 2 additions & 2 deletions src/routes/hyperliquid/markets_oi.sql
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ SELECT
sum(oi.funding_events) AS funding_events
FROM {db_hypercore:Identifier}.state_open_interest AS oi
LEFT JOIN {db_hypercore:Identifier}.state_spot_pair_names AS n FINAL ON n.coin = oi.coin
WHERE oi.coin = {coin:String}
WHERE oi.coin IN {coin:Array(String)}
AND oi.interval_min = {interval:UInt32}
AND (isNull({dex:Nullable(String)}) OR dex_from_coin(oi.coin) = {dex:Nullable(String)})
AND (empty({dex:Array(String)}) OR dex_from_coin(oi.coin) IN {dex:Array(String)})
AND (isNull({start_time:Nullable(UInt64)}) OR oi.timestamp >= toDateTime({start_time:Nullable(UInt64)}))
AND (isNull({end_time:Nullable(UInt64)}) OR oi.timestamp < toDateTime({end_time:Nullable(UInt64)}))
GROUP BY oi.interval_min, oi.coin, oi.timestamp
Expand Down
4 changes: 2 additions & 2 deletions src/routes/hyperliquid/markets_oi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import { validatorHook, withErrorResponses } from '../../utils.js';
import query from './markets_oi.sql' with { type: 'text' };

const querySchema = createQuerySchema({
coin: { schema: hyperliquidCoinSchema },
dex: { schema: hyperliquidDexIdSchema, optional: true },
coin: { schema: hyperliquidCoinSchema, batched: true },
dex: { schema: hyperliquidDexIdSchema, batched: true, optional: true },
interval: { schema: evmIntervalSchema, prefault: '1h' },
start_time: { schema: timestampSchema, optional: true },
end_time: { schema: timestampSchema, optional: true },
Expand Down
42 changes: 21 additions & 21 deletions src/routes/hyperliquid/users.sql
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
SELECT
user,
{coin:Nullable(String)} AS coin,
{dex:Nullable(String)} AS dex,
u.user AS user,
if(length({coin:Array(String)}) = 1, {coin:Array(String)}[1], NULL) AS coin,
if(length({dex:Array(String)}) = 1, {dex:Array(String)}[1], NULL) AS dex,
{interval:Nullable(String)} AS interval,
sum(transactions) AS transactions,
sum(buys) AS buys,
sum(sells) AS sells,
sum(volume_bought) AS volume_bought,
sum(volume_sold) AS volume_sold,
sum(total_volume) AS total_volume,
sum(total_fees) AS total_fees,
sum(realized_pnl) AS realized_pnl,
sum(total_funding) AS total_funding,
sum(liquidation_fills) AS liquidation_fills,
sum(u.transactions) AS transactions,
sum(u.buys) AS buys,
sum(u.sells) AS sells,
sum(u.volume_bought) AS volume_bought,
sum(u.volume_sold) AS volume_sold,
sum(u.total_volume) AS total_volume,
sum(u.total_fees) AS total_fees,
sum(u.realized_pnl) AS realized_pnl,
sum(u.total_funding) AS total_funding,
sum(u.liquidation_fills) AS liquidation_fills,
count() AS coins_traded,
min(first_trade) AS first_trade,
max(last_trade) AS last_trade
FROM {db_hypercore:Identifier}.state_user_by_coin FINAL
WHERE interval_min = {interval_min:UInt32}
AND (isNull({user:Nullable(String)}) OR user = {user:Nullable(String)})
AND (isNull({coin:Nullable(String)}) OR coin = {coin:Nullable(String)})
AND (isNull({dex:Nullable(String)}) OR dex = {dex:Nullable(String)})
GROUP BY user
min(u.first_trade) AS first_trade,
max(u.last_trade) AS last_trade
FROM {db_hypercore:Identifier}.state_user_by_coin AS u FINAL
WHERE u.interval_min = {interval_min:UInt32}
AND (empty({user:Array(String)}) OR u.user IN {user:Array(String)})
AND (empty({coin:Array(String)}) OR u.coin IN {coin:Array(String)})
AND (empty({dex:Array(String)}) OR u.dex IN {dex:Array(String)})
GROUP BY u.user
ORDER BY total_volume DESC
LIMIT {limit:UInt64}
OFFSET {offset:UInt64}
8 changes: 4 additions & 4 deletions src/routes/hyperliquid/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import byCoinQuery from './users.sql' with { type: 'text' };
import leaderboardQuery from './users_leaderboard.sql' with { type: 'text' };

const querySchema = createQuerySchema({
user: { schema: evmAddressSchema, optional: true },
user: { schema: evmAddressSchema, batched: true, optional: true },
interval: { schema: userLookbackIntervalSchema, optional: true },
sort_by: { schema: hyperliquidUserSortBySchema, prefault: 'total_volume' },
coin: { schema: hyperliquidCoinSchema, optional: true },
dex: { schema: hyperliquidDexIdSchema, optional: true },
coin: { schema: hyperliquidCoinSchema, batched: true, optional: true },
dex: { schema: hyperliquidDexIdSchema, batched: true, optional: true },
});

const responseSchema = apiUsageResponseSchema.extend({
Expand Down Expand Up @@ -148,7 +148,7 @@ route.get('/', openapi, zValidator('query', querySchema, validatorHook), validat
// state_user_leaderboard is pre-aggregated across coins/dexes and keyed by
// (interval_min, user) — use it whenever the request doesn't scope to a
// specific coin or dex. Falls back to state_user_by_coin FINAL otherwise.
const usesLeaderboard = !params.coin && !params.dex;
const usesLeaderboard = !params.coin.length && !params.dex.length;
const baseSql = usesLeaderboard ? leaderboardQuery : byCoinQuery;
const sql = baseSql.replace('ORDER BY total_volume DESC', `ORDER BY ${sortColumn} DESC`);

Expand Down
38 changes: 19 additions & 19 deletions src/routes/hyperliquid/users_leaderboard.sql
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
SELECT
user,
{coin:Nullable(String)} AS coin,
{dex:Nullable(String)} AS dex,
u.user AS user,
if(length({coin:Array(String)}) = 1, {coin:Array(String)}[1], NULL) AS coin,
if(length({dex:Array(String)}) = 1, {dex:Array(String)}[1], NULL) AS dex,
{interval:Nullable(String)} AS interval,
transactions,
buys,
sells,
volume_bought,
volume_sold,
total_volume,
total_fees,
realized_pnl,
total_funding,
liquidation_fills,
coins_traded,
first_trade,
last_trade
FROM {db_hypercore:Identifier}.state_user_leaderboard FINAL
WHERE interval_min = {interval_min:UInt32}
AND (isNull({user:Nullable(String)}) OR user = {user:Nullable(String)})
u.transactions AS transactions,
u.buys AS buys,
u.sells AS sells,
u.volume_bought AS volume_bought,
u.volume_sold AS volume_sold,
u.total_volume AS total_volume,
u.total_fees AS total_fees,
u.realized_pnl AS realized_pnl,
u.total_funding AS total_funding,
u.liquidation_fills AS liquidation_fills,
u.coins_traded AS coins_traded,
u.first_trade AS first_trade,
u.last_trade AS last_trade
FROM {db_hypercore:Identifier}.state_user_leaderboard AS u FINAL
WHERE u.interval_min = {interval_min:UInt32}
AND (empty({user:Array(String)}) OR u.user IN {user:Array(String)})
ORDER BY total_volume DESC
LIMIT {limit:UInt64}
OFFSET {offset:UInt64}
6 changes: 3 additions & 3 deletions src/routes/hyperliquid/users_positions.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ SELECT
FROM {db_hypercore:Identifier}.funding_deltas AS f
LEFT JOIN {db_hypercore:Identifier}.state_spot_pair_names AS n FINAL ON n.coin = f.coin
WHERE f.timestamp >= now() - INTERVAL 2 DAY
AND f.user = {user:String}
AND (isNull({coin:Nullable(String)}) OR f.coin = {coin:Nullable(String)})
AND (isNull({dex:Nullable(String)}) OR f.dex = {dex:Nullable(String)})
AND f.user IN {user:Array(String)}
AND (empty({coin:Array(String)}) OR f.coin IN {coin:Array(String)})
AND (empty({dex:Array(String)}) OR f.dex IN {dex:Array(String)})
GROUP BY f.user, f.coin
HAVING position_size != 0
ORDER BY abs(position_size) DESC
Expand Down
6 changes: 3 additions & 3 deletions src/routes/hyperliquid/users_positions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import { validatorHook, withErrorResponses } from '../../utils.js';
import query from './users_positions.sql' with { type: 'text' };

const querySchema = createQuerySchema({
user: { schema: evmAddressSchema },
coin: { schema: hyperliquidCoinSchema, optional: true },
dex: { schema: hyperliquidDexIdSchema, optional: true },
user: { schema: evmAddressSchema, batched: true },
coin: { schema: hyperliquidCoinSchema, batched: true, optional: true },
dex: { schema: hyperliquidDexIdSchema, batched: true, optional: true },
});

const responseSchema = apiUsageResponseSchema.extend({
Expand Down
8 changes: 4 additions & 4 deletions src/routes/hyperliquid/vaults.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ WITH
uniqExact(splitByChar(',', users)[1]) AS depositor_count,
max(timestamp) AS last_deposit_at
FROM {db_hypercore:Identifier}.ledger_vault_deposits
WHERE (isNull({vault:Nullable(String)}) OR vault = {vault:Nullable(String)})
WHERE (empty({vault:Array(String)}) OR vault IN {vault:Array(String)})
GROUP BY vault
),
withdrawals AS (
Expand All @@ -18,15 +18,15 @@ WITH
count() AS withdrawal_count,
max(timestamp) AS last_withdrawal_at
FROM {db_hypercore:Identifier}.ledger_vault_withdrawals
WHERE (isNull({vault:Nullable(String)}) OR vault = {vault:Nullable(String)})
WHERE (empty({vault:Array(String)}) OR vault IN {vault:Array(String)})
GROUP BY vault
),
distributions AS (
SELECT
vault,
sum(usdc_num) AS lifetime_distributions
FROM {db_hypercore:Identifier}.ledger_vault_distributions
WHERE (isNull({vault:Nullable(String)}) OR vault = {vault:Nullable(String)})
WHERE (empty({vault:Array(String)}) OR vault IN {vault:Array(String)})
GROUP BY vault
),
creates AS (
Expand All @@ -37,7 +37,7 @@ WITH
argMin(usdc_num, timestamp) AS initial_deposit,
argMin(fee_num, timestamp) AS create_fee
FROM {db_hypercore:Identifier}.ledger_vault_creates
WHERE (isNull({vault:Nullable(String)}) OR vault = {vault:Nullable(String)})
WHERE (empty({vault:Array(String)}) OR vault IN {vault:Array(String)})
GROUP BY vault
)
SELECT
Expand Down
2 changes: 1 addition & 1 deletion src/routes/hyperliquid/vaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { validatorHook, withErrorResponses } from '../../utils.js';
import baseQuery from './vaults.sql' with { type: 'text' };

const querySchema = createQuerySchema({
vault: { schema: evmAddressSchema, optional: true },
vault: { schema: evmAddressSchema, batched: true, optional: true },
sort_by: { schema: hyperliquidVaultSortBySchema, prefault: 'lifetime_deposits' },
});

Expand Down
21 changes: 12 additions & 9 deletions src/routes/hyperliquid/vaults_depositors.sql
Original file line number Diff line number Diff line change
@@ -1,44 +1,47 @@
WITH
deposits AS (
SELECT
vault,
splitByChar(',', users)[1] AS user,
sum(usdc_num) AS deposits,
count() AS deposit_count,
max(timestamp) AS last_deposit_at
FROM {db_hypercore:Identifier}.ledger_vault_deposits
WHERE vault = {vault:String}
GROUP BY user
WHERE vault IN {vault:Array(String)}
GROUP BY vault, user
),
withdrawals AS (
SELECT
vault,
user,
sum(net_withdrawn_usd_num) AS withdrawals,
count() AS withdrawal_count,
max(timestamp) AS last_withdrawal_at
FROM {db_hypercore:Identifier}.ledger_vault_withdrawals
WHERE vault = {vault:String}
GROUP BY user
WHERE vault IN {vault:Array(String)}
GROUP BY vault, user
),
distributions AS (
SELECT
vault,
splitByChar(',', users)[1] AS user,
sum(usdc_num) AS distributions_received
FROM {db_hypercore:Identifier}.ledger_vault_distributions
WHERE vault = {vault:String}
GROUP BY user
WHERE vault IN {vault:Array(String)}
GROUP BY vault, user
)
SELECT
deposits.user AS user,
{vault:String} AS vault,
deposits.vault AS vault,
deposits.deposits AS deposits,
deposits.deposit_count AS deposit_count,
coalesce(withdrawals.withdrawals, 0) AS withdrawals,
coalesce(withdrawals.withdrawal_count, 0) AS withdrawal_count,
coalesce(distributions.distributions_received, 0) AS distributions_received,
greatest(deposits.last_deposit_at, withdrawals.last_withdrawal_at) AS last_activity_at
FROM deposits
LEFT JOIN withdrawals USING (user)
LEFT JOIN distributions USING (user)
LEFT JOIN withdrawals USING (vault, user)
LEFT JOIN distributions USING (vault, user)
ORDER BY deposits DESC
LIMIT {limit:UInt64}
OFFSET {offset:UInt64}
Loading
Loading