git / moonbite-network / tests/test_sweep_to_vault.py · raw
"""ADR-015 sweep tool: only founder coins, vault verified, batches fit, dry run sends nothing."""import importlib.utilimport osfrom decimal import Decimalimport pytest_spec = importlib.util.spec_from_file_location( "sweep_to_vault", os.path.join(os.path.dirname(__file__), "..", "tools", "vault", "sweep_to_vault.py"))sweep = importlib.util.module_from_spec(_spec)_spec.loader.exec_module(sweep)def coins(n, addr=sweep.FOUNDER_ADDRESSES[0]): return [{"txid": f"{i:064x}", "vout": 0, "amount": Decimal("10"), "address": addr} for i in range(n)]class FakeCli: def __init__(self, utxos, vault=sweep.VAULT): self.utxos, self.vault, self.calls = utxos, vault, [] def __call__(self, method, *params): self.calls.append((method, params)) if method == "decodescript": return {"asm": "1886907600 OP_CHECKLOCKTIMEVERIFY OP_DROP ...", "segwit": {"address": self.vault}} if method == "listunspent": assert params[0] == 100 and params[2] == sweep.FOUNDER_ADDRESSES # mature, founder-only return self.utxos if method == "createrawtransaction": return "raw" if method == "signrawtransactionwithwallet": return {"complete": True, "hex": "signed"} if method == "testmempoolaccept": return [{"allowed": True}] if method == "sendrawtransaction": return "txid%d" % len([c for c in self.calls if c[0] == "sendrawtransaction"]) raise AssertionError(method)def run(monkeypatch, fake, *extra, tmp_path=None): monkeypatch.setattr(sweep, "Cli", lambda cmd: fake) args = ["--cli", "moonbite-cli", *extra] if tmp_path is not None: args += ["--log", str(tmp_path / "log.txt")] return sweep.main(args)def test_batches_stay_under_the_size_limit_and_fees_are_small(): b = sweep.plan(coins(2673), 400, 2) assert len(b) == 7 and sum(len(x["inputs"]) for x in b) == 2673 assert all(sweep.vbytes(len(x["inputs"])) < 100_000 for x in b) assert sum(x["send"] + x["fee"] for x in b) == Decimal("26730") assert sum(x["fee"] for x in b) < Decimal("0.01")def test_dry_run_sends_nothing(monkeypatch): fake = FakeCli(coins(5)) assert run(monkeypatch, fake) == 0 assert not any(m == "sendrawtransaction" for m, _ in fake.calls)def test_wrong_vault_refuses(monkeypatch): fake = FakeCli(coins(5), vault="moon1qsomethingelse") with pytest.raises(SystemExit, match="Vault check FAILED"): run(monkeypatch, fake, "--send") assert not any(m == "sendrawtransaction" for m, _ in fake.calls)def test_send_pays_only_the_vault_and_logs_txids(monkeypatch, tmp_path): fake = FakeCli(coins(900)) assert run(monkeypatch, fake, "--send", "--batch", "400", tmp_path=tmp_path) == 0 outs = [p[1] for m, p in fake.calls if m == "createrawtransaction"] assert len(outs) == 3 and all(list(o.keys()) == [sweep.VAULT] for o in outs) assert (tmp_path / "log.txt").read_text().count("txid") == 3