{"openapi":"3.1.0","info":{"title":"HALOWERK defiwerk","version":"1.0.0","description":"HALOWERK defiwerk — bezahlte Endpunkte nach x402. Preise in USDC auf Base Mainnet.","contact":{"url":"https://defi.halowerk.com/"}},"servers":[{"url":"https://defi.halowerk.com"}],"paths":{"/dex/quote":{"post":{"operationId":"dex_quote","summary":"Collects swap quotes for one token pair from every DEX connected on that chain, direct and via one intermediate token, and ranks them by amount received after gas — not by the headline number, which for small trades is regularly the worse route.","description":"For a given chain, token pair and input amount, every connected DEX is queried through its own contracts: Uniswap V3 through the Quoter via eth_call across all fee tiers, constant-product pools through the pool maths on live reserves, Solidly-style pools through their own getAmountOut. Two-hop routes through the wrapped native token and the chain USDC are included, priced by chaining the hops exactly as a real swap would traverse them. Nothing is executed, submitted or handed to a router — every number is a read. price_impact_bps and slippage are reported as the two different things they are: price impact is how far this trade size moves the pool away from its own mid price, slippage_bps is the tolerance the caller supplied and from which amount_out_min is derived. amount_out_min is arithmetic on the caller tolerance, not a promise about execution. Both rankings are given: best_by_gross for the largest raw output and best_by_net after subtracting gas at the current gas price, with the assumed gas overhead printed so the calculation can be repeated. DEXes that fail or hold no pool for the pair are listed with the reason rather than silently dropped. No recommendation, no execution, no route forwarding.","tags":["defiwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["chain","token_in","token_out","amount_in"],"additionalProperties":false,"properties":{"chain":{"type":"string","enum":["base","ethereum","arbitrum","optimism","polygon"]},"token_in":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$"},"token_out":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$"},"amount_in":{"type":"string","pattern":"^[0-9]+(\\.[0-9]+)?$","description":"Input amount in whole token units, as a decimal string, e.g. \"1.5\"."},"slippage_bps":{"type":"integer","minimum":0,"maximum":5000,"default":50,"description":"Caller slippage tolerance in basis points; only used to derive amount_out_min."},"include_multihop":{"type":"boolean","default":true,"description":"Also price routes through one intermediate token."}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/pool/liquidity":{"post":{"operationId":"pool_liquidity","summary":"Reads one DEX pool directly from the chain and answers the question TVL cannot: how much price impact an exit of 1k, 10k, 100k and 1M USD actually costs, in both directions, simulated against the live pool state.","description":"Resolves a pool either by address or by chain, token pair and DEX, then reads token0, token1, fee tier, reserves, in-range liquidity and the current tick straight from the contract. Exit impact is not estimated from a formula but simulated: for Uniswap V3 through the official Quoter contract via eth_call, which walks the same ticks a real swap would and reports how many it crossed; for constant-product and Solidly pools through the pool maths or the pool own getAmountOut. Nothing is ever executed, routed or signed. For concentrated liquidity the answer separates total TVL from the capital actually sitting within one, two and five percent of the current price, so that idle out-of-range liquidity cannot be mistaken for depth. 24h and 7d volume come from a public yield directory and are marked as a foreign derivation with their own age; where the pool cannot be matched there unambiguously, volume stays null instead of being guessed. LP holder count and top LP share require an indexer and are always null with the reason stated. Delivers no recommendation and no verdict on whether a pool is good.","tags":["defiwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["chain"],"additionalProperties":false,"properties":{"chain":{"type":"string","enum":["base","ethereum","arbitrum","optimism","polygon"]},"pool":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Pool address. Either this or token_a plus token_b plus dex."},"token_a":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$"},"token_b":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$"},"dex":{"type":"string","description":"DEX id, required together with token_a and token_b."},"fee_tier_ppm":{"type":"integer","enum":[100,500,3000,10000],"description":"Optional fee tier in parts per million for Uniswap V3. Omitted means the deepest tier."}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/yield/normalize":{"post":{"operationId":"yield_normalize","summary":"Takes an advertised pool APY apart: base yield against reward emissions, compounding assumption made explicit, an impermanent loss estimate from the actual 30-day price path, and the net yield after gas for stakes from 200 to 100000 USD — which is regularly negative at the small end.","description":"Resolves a pool in a public yield directory by chain, protocol and pool id or symbol, then rebuilds the number a buyer actually needs. Advertised total APY and a conservative APY are reported separately: the conservative figure uses the trailing seven-day realised base yield and deliberately excludes token emissions, because emissions are only worth what the reward token is worth. Every reward token is priced at the moment of the call and that price is stated as the assumption it is; the end of an emission schedule is not published by the directory and stays null rather than being guessed. For AMM pools the fee APR is additionally recomputed from 24h volume, the fee tier and TVL so the arithmetic behind the advertised base yield is visible and can be repeated; since the directory derives its base yield from the same inputs, a deviation of zero means the numbers are consistent, not that a second independent source confirmed them, and the answer says so. Impermanent loss is an estimate and labelled as one: it is computed from the real price path of both underlying tokens over the last 31 days with the constant-product formula, plus a scenario table. net_apy_after_gas subtracts entry, exit and harvest gas at the current gas price and native token price for each stake size, with the assumed gas units printed in the answer so the calculation can be repeated. Contains no recommendation and no forecast — a calculation with its assumptions open.","tags":["defiwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["chain","protocol","pool"],"additionalProperties":false,"properties":{"chain":{"type":"string","enum":["base","ethereum","arbitrum","optimism","polygon"]},"protocol":{"type":"string","description":"Protocol id as the directory names it, for example \"aave-v3\", \"uniswap-v3\", \"aerodrome-v1\"."},"pool":{"type":"string","description":"Directory pool id (uuid) or the pool symbol, for example \"WETH-USDC\"."},"stake_sizes_usd":{"type":"array","items":{"type":"number","minimum":1,"maximum":100000000},"maxItems":8,"description":"Stake sizes for net_apy_after_gas. Default 200, 1000, 10000, 100000."}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/oracle/crosscheck":{"post":{"operationId":"oracle_crosscheck","summary":"Cross-checks one asset price across Chainlink, Pyth, RedStone, centralised exchanges and on-chain DEX spot and TWAP, and reports the age of every single source, the spread between them and which sources sit in pools thin enough to be pushed.","description":"Reads a Chainlink aggregator directly from the chain, pulls Pyth and RedStone, queries public exchange tickers and derives spot plus a 30-minute TWAP from the deepest Uniswap V3 pool of the asset against USDC on the requested chain. Every source carries its own age in seconds, its own price and a link to verify it. Nothing is smoothed into an average: the median is stated alongside the full list and the maximum deviation in basis points, because disagreement between sources is the finding, not a defect to hide. Sources quoted against USDT rather than USD are named and excluded from the median. DEX spot prices out of pools below the disclosed depth threshold are flagged as thin and therefore pushable. Chainlink heartbeat and deviation threshold are configuration that does not live on the aggregator contract — they stay null rather than being asserted, and an observed update interval derived from the last two rounds is given instead. Delivers no recommendation, no trading signal and no protection promise; every threshold used for the risk wording is listed in the answer.","tags":["defiwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["chain","asset"],"additionalProperties":false,"properties":{"chain":{"type":"string","enum":["base","ethereum","arbitrum","optimism","polygon"],"description":"Chain the on-chain sources are read from. Off-chain sources are chain independent."},"asset":{"type":"string","enum":["ETH","BTC","USDC","USDT","DAI","LINK","CBETH","AERO"],"description":"Asset symbol. Only assets whose sources were individually verified against the chain are available."},"oracles":{"type":"array","items":{"type":"string","enum":["chainlink","pyth","redstone","cex","dex_spot","dex_twap"]},"description":"Optional filter for source types. Omitted means all available types."}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/lending/health":{"post":{"operationId":"lending_health","summary":"Reads a wallet lending position straight from the protocol contracts and answers the question that actually matters: at which price per collateral asset it gets liquidated, how far prices may fall first, and what the health factor becomes at minus ten, twenty, thirty and fifty percent.","description":"Resolves pool, price oracle and data provider through the protocol address provider rather than hard-coded addresses, then reads every reserve the wallet touches: collateral amounts, variable and stable debt, LTV, liquidation threshold, liquidation bonus and the borrow rate, all at one block. Values are computed with the price the protocol oracle reports, not with a market price from an exchange — a liquidation follows the oracle, and the oracle source contract per asset is named in the answer so it can be cross-checked with the oracle endpoint of this hub. liquidation_price is given per collateral asset as the oracle price at which the health factor reaches one while all other prices hold; where a single asset cannot trigger it even at price zero, the field says so instead of showing a number. Scenarios apply a uniform fall to all collateral while debt stays nominal, and that assumption is printed with them. Reads only: no transaction, no signature, no advice on whether to add collateral or close. Positions on protocols other than the ones listed are rejected rather than approximated.","tags":["defiwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["chain","protocol","wallet"],"additionalProperties":false,"properties":{"chain":{"type":"string","enum":["base","ethereum","arbitrum","optimism","polygon"]},"protocol":{"type":"string","enum":["aave-v3"]},"wallet":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Address whose position is read. Public on-chain data only."},"scenarios_pct":{"type":"array","items":{"type":"number","minimum":-99,"maximum":100},"maxItems":8,"description":"Price moves of the collateral in percent. Default -10, -20, -30, -50."}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}},"/mev/risk":{"post":{"operationId":"mev_risk","summary":"Estimates what a sandwich attack on one specific swap would earn an attacker, compares it against the gas that attack costs, counts sandwiches that actually happened on that pool from on-chain events, and lists concrete mitigations with their effect and their price.","description":"Takes chain, token pair, input amount and slippage tolerance, finds the pool the trade would most likely use and reads its live state. The maximum the caller can lose is arithmetic and exact: the gap between the quoted output and the minimum output their own tolerance permits. The attacker profit is an estimate and labelled as one — the profit-maximising front-run size is searched for inside a constant-liquidity pool model, bounded by the largest front-run the caller own tolerance still permits, and the same model is checked against the official Quoter for the unattacked swap so that model_error_bps is visible rather than hidden. That profit is then set against the gas two attacker transactions cost: below it, the attack does not pay for itself, and the answer says so instead of warning about a danger that does not add up. Whether the chain even has a public pending pool is stated with its reason, because on a single-sequencer chain a third party cannot see the trade before the block. recent_sandwiches_on_pool is not estimated but counted from Swap events in the scanned block window, with the window length and the detection pattern disclosed. Mitigations come with numbers: what a tighter tolerance caps the loss at, what splitting the order costs in extra gas and saves in impact. Nothing is executed, forwarded, signed or submitted, and no protection is promised.","tags":["defiwerk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["chain","token_in","token_out","amount_in"],"additionalProperties":false,"properties":{"chain":{"type":"string","enum":["base","ethereum","arbitrum","optimism","polygon"]},"token_in":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$"},"token_out":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$"},"amount_in":{"type":"string","pattern":"^[0-9]+(\\.[0-9]+)?$","description":"Input amount in whole token units as a decimal string."},"slippage_bps":{"type":"integer","minimum":1,"maximum":5000,"default":50},"route":{"type":"string","pattern":"^0x[a-fA-F0-9]{40}$","description":"Optional pool address to assess instead of the automatically chosen one."},"scan_history":{"type":"boolean","default":true,"description":"Scan past Swap events for actual sandwiches. Costs time; switch off for a faster answer."}}}}}},"responses":{"200":{"description":"Ergebnis","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Eingabe ungültig, charged=false"},"402":{"description":"Zahlung erforderlich. Die Antwort trägt accepts, description und inputSchema.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentRequired"}}}},"429":{"description":"Zu viele unbezahlte Anfragen, charged=false"},"502":{"description":"Gegenstelle nicht erreichbar, charged=false"},"504":{"description":"Zeitbudget überschritten, charged=false"}}}}},"components":{"schemas":{"PaymentRequired":{"type":"object","properties":{"x402Version":{"type":"integer"},"error":{"type":"string"},"description":{"type":"string"},"inputSchema":{"type":"object"},"accepts":{"type":"array","items":{"type":"object"}}}}},"securitySchemes":{"x402":{"type":"apiKey","in":"header","name":"PAYMENT-SIGNATURE","description":"x402 Zahlungsnachweis"}}}}