Some checks failed
deploy / deploy (push) Failing after 40s
Proof: targeted pair-native strategy, preflight, outcome, dashboard, and ops tests pass; full npm test passes 237/237; operator dashboard production bundle builds; ops watcher Python test passes. Assumptions: DB asset, pair, strategy config, and price route rows remain canonical; legacy EURe fields stay only for old-row/API compatibility; local shell has no Kubernetes context for direct live namespace recheck. Still fake: venue-native terminal fill ids and realized fee/PnL attribution remain unavailable; live deployment verification must happen through the repo workflow because manual cluster repair is out of scope.
176 lines
6.1 KiB
Python
176 lines
6.1 KiB
Python
from __future__ import annotations
|
|
|
|
import sys
|
|
import unittest
|
|
from decimal import Decimal
|
|
from pathlib import Path
|
|
from unittest import mock
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
|
|
import watch_live_mm
|
|
|
|
|
|
ASSETS = {
|
|
"nep141:btc.omft.near": watch_live_mm.AssetMeta(
|
|
asset_id="nep141:btc.omft.near",
|
|
symbol="BTC",
|
|
decimals=8,
|
|
),
|
|
"nep141:eure": watch_live_mm.AssetMeta(
|
|
asset_id="nep141:eure",
|
|
symbol="EURe",
|
|
decimals=18,
|
|
),
|
|
"nep141:usdc.omft.near": watch_live_mm.AssetMeta(
|
|
asset_id="nep141:usdc.omft.near",
|
|
symbol="USDC",
|
|
decimals=6,
|
|
),
|
|
}
|
|
|
|
|
|
class WatchLiveMmTests(unittest.TestCase):
|
|
def test_format_amount_humanizes_btc(self) -> None:
|
|
self.assertEqual(
|
|
watch_live_mm.format_amount("100000", ASSETS["nep141:btc.omft.near"]),
|
|
"0.001 BTC",
|
|
)
|
|
|
|
def test_format_amount_humanizes_eure(self) -> None:
|
|
self.assertEqual(
|
|
watch_live_mm.format_amount("122753877246000000000", ASSETS["nep141:eure"]),
|
|
"122.75387725 EURe",
|
|
)
|
|
|
|
def test_format_decimal_trims_trailing_zeroes(self) -> None:
|
|
self.assertEqual(watch_live_mm.format_decimal(Decimal("60.00000000")), "60")
|
|
|
|
def test_render_quote_row_formats_assets(self) -> None:
|
|
row = {
|
|
"ingested_at": "2026-04-02 14:00:00+00",
|
|
"quote_id": "quote-1",
|
|
"asset_in": "nep141:eure",
|
|
"asset_out": "nep141:btc.omft.near",
|
|
"request_kind": "exact_in",
|
|
"amount_in": "122753877246000000000",
|
|
"amount_out": "",
|
|
"min_deadline_ms": "15000",
|
|
}
|
|
rendered = watch_live_mm.render_quote_row(row, ASSETS)
|
|
self.assertIn("QUOTE", rendered)
|
|
self.assertIn("EURe->BTC", rendered)
|
|
self.assertIn("122.75387725 EURe", rendered)
|
|
|
|
def test_render_decision_row_formats_inventory(self) -> None:
|
|
row = {
|
|
"ingested_at": "2026-04-02 14:00:01+00",
|
|
"quote_id": "quote-2",
|
|
"direction": "eure_to_btc",
|
|
"decision": "rejected",
|
|
"decision_reason": "insufficient_inventory",
|
|
"gross_edge_pct": "2.000000",
|
|
"eure_notional": "16.246379",
|
|
"inventory_asset": "nep141:btc.omft.near",
|
|
"inventory_available": "100000",
|
|
"inventory_required": "1592145",
|
|
}
|
|
rendered = watch_live_mm.render_decision_row(row, ASSETS)
|
|
self.assertIn("DECISION", rendered)
|
|
self.assertIn("insufficient_inventory", rendered)
|
|
self.assertIn("0.001 BTC", rendered)
|
|
|
|
def test_select_new_rows_returns_oldest_first_and_marks_seen(self) -> None:
|
|
seen = {"existing"}
|
|
rows = [
|
|
{"event_id": "newer"},
|
|
{"event_id": "middle"},
|
|
{"event_id": "existing"},
|
|
]
|
|
fresh = watch_live_mm.select_new_rows(rows, seen)
|
|
self.assertEqual([row["event_id"] for row in fresh], ["middle", "newer"])
|
|
self.assertEqual(seen, {"existing", "middle", "newer"})
|
|
|
|
def test_current_state_fingerprint_includes_portfolio_metrics(self) -> None:
|
|
responses = {
|
|
"near-intents-ingest": {
|
|
"ingest": {
|
|
"last_matching_quote_at": "2026-04-02T20:17:44.623Z",
|
|
"published_count": 7,
|
|
}
|
|
},
|
|
"inventory-sync": {
|
|
"last_snapshot": {
|
|
"spendable": {
|
|
"nep141:btc.omft.near": "137014",
|
|
"nep141:eure": "38999978799978799978",
|
|
"nep141:usdc.omft.near": "1234567",
|
|
}
|
|
}
|
|
},
|
|
"history-writer": {
|
|
"latest_portfolio_metrics": {
|
|
"trade_pnl_eure": "0.391183707978799978",
|
|
"mark_to_market_pnl_eure": "0.497413887978799978",
|
|
}
|
|
},
|
|
"strategy-engine": {
|
|
"armed": False,
|
|
"latest_decision": {
|
|
"decision_reason": "actionable",
|
|
"quote_id": "quote-1",
|
|
},
|
|
},
|
|
"trade-executor": {
|
|
"armed": False,
|
|
"signer_registered": True,
|
|
},
|
|
}
|
|
|
|
with mock.patch.object(
|
|
watch_live_mm,
|
|
"fetch_service_state",
|
|
side_effect=lambda *, namespace, deployment: responses[deployment],
|
|
):
|
|
state = watch_live_mm.current_state_fingerprint(namespace="unrip", assets=ASSETS)
|
|
|
|
self.assertEqual(state["trade_pnl_eure"], "0.391183707978799978")
|
|
self.assertEqual(state["mark_to_market_pnl_eure"], "0.497413887978799978")
|
|
self.assertEqual(state["btc_spendable"], "0.00137014 BTC")
|
|
self.assertEqual(state["eure_spendable"], "38.9999788 EURe")
|
|
self.assertIn("1.234567 USDC", state["spendable_assets"])
|
|
|
|
def test_current_state_fingerprint_does_not_require_eure_asset(self) -> None:
|
|
assets = {
|
|
key: value
|
|
for key, value in ASSETS.items()
|
|
if value.symbol != "EURe"
|
|
}
|
|
responses = {
|
|
"near-intents-ingest": {"ingest": {"published_count": 1}},
|
|
"inventory-sync": {
|
|
"last_snapshot": {
|
|
"spendable": {
|
|
"nep141:btc.omft.near": "100000",
|
|
"nep141:usdc.omft.near": "5000000",
|
|
}
|
|
}
|
|
},
|
|
"history-writer": {"latest_portfolio_metrics": {}},
|
|
"strategy-engine": {"armed": False, "latest_decision": {}},
|
|
"trade-executor": {"armed": False, "signer_registered": True},
|
|
}
|
|
|
|
with mock.patch.object(
|
|
watch_live_mm,
|
|
"fetch_service_state",
|
|
side_effect=lambda *, namespace, deployment: responses[deployment],
|
|
):
|
|
state = watch_live_mm.current_state_fingerprint(namespace="unrip", assets=assets)
|
|
|
|
self.assertEqual(state["eure_spendable"], "untracked")
|
|
self.assertIn("5 USDC", state["spendable_assets"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|