Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a27d01f12 |
@@ -127,3 +127,7 @@ color-coded (green up, red down). Reconnection is handled by HTMX.
|
|||||||
Python · FastAPI · Uvicorn · websockets · HTMX · Tailwind CSS v4
|
Python · FastAPI · Uvicorn · websockets · HTMX · Tailwind CSS v4
|
||||||
|
|
||||||
The Clojure implementation this replaced is on the `clojure` branch.
|
The Clojure implementation this replaced is on the `clojure` branch.
|
||||||
|
|
||||||
|
The 24-hour chart uses 48 half-hour candles from rustbtcdata’s
|
||||||
|
`/api/kraken-half-hour` endpoint, aggregated from minute OHLC data. It refreshes
|
||||||
|
every five minutes and includes the current partial half-hour candle.
|
||||||
|
|||||||
+7
-2
@@ -73,7 +73,7 @@ HOME_HTML = """\
|
|||||||
</div>
|
</div>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 p-6">
|
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 p-6">
|
||||||
<p class="text-sm text-gray-500 mb-3">24h Candles (1h)</p>
|
<p class="text-sm text-gray-500 mb-3">24h Candles (30m)</p>
|
||||||
<div id="chart-hour" style="height:300px"></div>
|
<div id="chart-hour" style="height:300px"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -170,7 +170,7 @@ HOME_HTML = """\
|
|||||||
}
|
}
|
||||||
|
|
||||||
initChart('chart-minute', '/api/kraken-minute', 60 * 1000);
|
initChart('chart-minute', '/api/kraken-minute', 60 * 1000);
|
||||||
initChart('chart-hour', '/api/kraken-hour', 5 * 60 * 1000, updateMidnightPrice);
|
initChart('chart-hour', '/api/kraken-half-hour', 5 * 60 * 1000, updateMidnightPrice);
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
@@ -233,6 +233,11 @@ async def _proxy_btcdata_json(path: str) -> JSONResponse:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/api/kraken-half-hour")
|
||||||
|
async def kraken_half_hour():
|
||||||
|
return await _proxy_btcdata_json("/api/kraken-half-hour")
|
||||||
|
|
||||||
|
|
||||||
@app.get("/api/kraken-hour")
|
@app.get("/api/kraken-hour")
|
||||||
async def kraken_hour():
|
async def kraken_hour():
|
||||||
return await _proxy_btcdata_json("/api/kraken-hour")
|
return await _proxy_btcdata_json("/api/kraken-hour")
|
||||||
|
|||||||
@@ -107,3 +107,22 @@ def test_version_endpoint(monkeypatch):
|
|||||||
|
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response.json() == {"version": "abc1234"}
|
assert response.json() == {"version": "abc1234"}
|
||||||
|
|
||||||
|
|
||||||
|
def test_24_hour_chart_uses_half_hour_candles():
|
||||||
|
response = TestClient(main.app).get("/")
|
||||||
|
assert "24h Candles (30m)" in response.text
|
||||||
|
assert "initChart('chart-hour', '/api/kraken-half-hour', 5 * 60 * 1000, updateMidnightPrice)" in response.text
|
||||||
|
assert "initChart('chart-minute', '/api/kraken-minute', 60 * 1000)" in response.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_half_hour_proxy_preserves_candles_and_upstream_errors(monkeypatch):
|
||||||
|
for status, payload in [(200, [{"ts": 1800, "open": "10", "high": "12", "low": "9", "close": "11"}]), (503, {"error": "database unavailable"})]:
|
||||||
|
request = httpx.Request("GET", "http://btcdata.test/api/kraken-half-hour")
|
||||||
|
client = StubAsyncClient(response=httpx.Response(status, json=payload, request=request))
|
||||||
|
monkeypatch.setattr(main, "BTCDATA_URL", "http://btcdata.test")
|
||||||
|
monkeypatch.setattr(main.httpx, "AsyncClient", lambda: client)
|
||||||
|
response = TestClient(main.app).get("/api/kraken-half-hour")
|
||||||
|
assert response.status_code == status
|
||||||
|
assert response.json() == payload
|
||||||
|
assert client.requested_url == "http://btcdata.test/api/kraken-half-hour"
|
||||||
|
|||||||
Reference in New Issue
Block a user