v1.0.0-dev: slim to the real product — merchant state machine only
This commit is contained in:
parent
c31518309d
commit
b4a81e0ab8
15 changed files with 286 additions and 2503 deletions
|
|
@ -53,23 +53,31 @@ def _utxo(lovelace: int, tx_hash: str = "aa" * 32) -> dict:
|
|||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _patch_koios_and_oracle(monkeypatch):
|
||||
"""Default: no UTxOs, oracle returns $0.45/ADA. Individual tests override."""
|
||||
def _patch_koios(monkeypatch):
|
||||
"""Default: Koios returns no UTxOs. Individual tests override."""
|
||||
|
||||
async def fake_utxos(address, koios_url=None, timeout=None):
|
||||
return []
|
||||
|
||||
async def fake_price():
|
||||
return 0.45
|
||||
monkeypatch.setattr(monitor, "check_address_utxos", fake_utxos)
|
||||
|
||||
async def fake_convert(usd):
|
||||
|
||||
@pytest.fixture
|
||||
def price_fn_at_45c():
|
||||
"""A deterministic price_fn for tests — USD priced at $0.45/ADA."""
|
||||
async def _convert(usd: float) -> int:
|
||||
if usd <= 0:
|
||||
return 0
|
||||
return int((usd / 0.45) * 1_000_000)
|
||||
return _convert
|
||||
|
||||
monkeypatch.setattr(monitor, "check_address_utxos", fake_utxos)
|
||||
monkeypatch.setattr(monitor, "get_ada_usd_price", fake_price)
|
||||
monkeypatch.setattr(monitor, "convert_usd_to_lovelace", fake_convert)
|
||||
|
||||
@pytest.fixture
|
||||
def price_fn_zero():
|
||||
"""A price_fn that returns 0 — stand-in for oracle unavailability."""
|
||||
async def _zero(usd: float) -> int:
|
||||
return 0
|
||||
return _zero
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
@ -184,14 +192,14 @@ async def test_already_expired_invoices_are_skipped(monkeypatch) -> None:
|
|||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
async def test_reprice_updates_expected_lovelace_and_extends_expiry() -> None:
|
||||
async def test_reprice_updates_expected_lovelace_and_extends_expiry(price_fn_at_45c) -> None:
|
||||
store = InMemoryStore()
|
||||
inv = _make(expected_lovelace=5_000_000)
|
||||
inv.expires_at = datetime.now(timezone.utc) - timedelta(minutes=1)
|
||||
await store.create(inv)
|
||||
|
||||
updated = await monitor.reprice_expired_invoices(
|
||||
store, window_minutes=15, max_repricings=3
|
||||
store, price_fn=price_fn_at_45c, window_minutes=15, max_repricings=3
|
||||
)
|
||||
assert updated == 1
|
||||
|
||||
|
|
@ -205,14 +213,14 @@ async def test_reprice_updates_expected_lovelace_and_extends_expiry() -> None:
|
|||
assert fetched.metadata["repriced_count"] == 1
|
||||
|
||||
|
||||
async def test_reprice_gives_up_after_max_repricings() -> None:
|
||||
async def test_reprice_gives_up_after_max_repricings(price_fn_at_45c) -> None:
|
||||
store = InMemoryStore()
|
||||
inv = _make(expected_lovelace=5_000_000, repriced_count=3)
|
||||
inv.expires_at = datetime.now(timezone.utc) - timedelta(minutes=1)
|
||||
await store.create(inv)
|
||||
|
||||
await monitor.reprice_expired_invoices(
|
||||
store, window_minutes=15, max_repricings=3
|
||||
store, price_fn=price_fn_at_45c, window_minutes=15, max_repricings=3
|
||||
)
|
||||
|
||||
fetched = await store.get("inv")
|
||||
|
|
@ -220,26 +228,21 @@ async def test_reprice_gives_up_after_max_repricings() -> None:
|
|||
assert fetched.status == InvoiceStatus.EXPIRED
|
||||
|
||||
|
||||
async def test_reprice_noop_when_nothing_expired() -> None:
|
||||
async def test_reprice_noop_when_nothing_expired(price_fn_at_45c) -> None:
|
||||
store = InMemoryStore()
|
||||
await store.create(_make(expired_in_minutes=15) if False else _make())
|
||||
await store.create(_make())
|
||||
|
||||
updated = await monitor.reprice_expired_invoices(store)
|
||||
updated = await monitor.reprice_expired_invoices(store, price_fn=price_fn_at_45c)
|
||||
assert updated == 0
|
||||
|
||||
|
||||
async def test_reprice_skips_when_oracle_unavailable(monkeypatch) -> None:
|
||||
async def test_reprice_skips_when_oracle_returns_zero(price_fn_zero) -> None:
|
||||
store = InMemoryStore()
|
||||
inv = _make(expected_lovelace=5_000_000)
|
||||
inv.expires_at = datetime.now(timezone.utc) - timedelta(minutes=1)
|
||||
await store.create(inv)
|
||||
|
||||
async def zero_price():
|
||||
return 0.0
|
||||
|
||||
monkeypatch.setattr(monitor, "get_ada_usd_price", zero_price)
|
||||
|
||||
updated = await monitor.reprice_expired_invoices(store)
|
||||
updated = await monitor.reprice_expired_invoices(store, price_fn=price_fn_zero)
|
||||
assert updated == 0
|
||||
|
||||
fetched = await store.get("inv")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue