rmi-backend/app/_archive/legacy_2026_07/sweep_now.py
cryptorugmunch 628c1d2a10
Some checks failed
CI / build (push) Failing after 3s
refactor(rmi-backend,audit): mount Wave 3 + archive 136 dead-code files (P2.3)
PHASE 2.3 (AUDIT-2026-Q3.md):

Task 1 — Wire-in Wave 3 (1 router mounted, 2 deferred):
  - app.routers.unified_scanner_router mounted at /api/v2/scanner/* (2 routes:
    POST /api/v2/scanner/token/scan, POST /api/v2/scanner/wallet/scan).
    Refactored prefix from /api/v2 -> /api/v2/scanner to avoid future conflicts
    with the v1 /api/v1/scanner/ stub.
  - app.routers.unified_wallet_scanner DEFERRED (no router APIRouter attribute;
    library module consumed by unified_scanner_router via get_wallet_scanner()).
  - app.routers.admin_extensions DEFERRED (DORMANT per audit; 25 routes at
    /api/v1/admin/* would shadow /api/v1/admin/alerts_webhook).

Task 2 — Archive 136 dead-code files to app/_archive/legacy_2026_07/:
  - 73 routers in app/routers/ (reach graph showed zero reach into mount.py).
  - 63 flat app/*.py (domain modules never imported by live code).
  - 1 file RESTORED post-archive: app/routers/x402_bridge_health.py (caught by
    tests/unit/test_bridge_health.py which directly imports it; reach graph
    considered tests/ only as transitive reach — to be patched in next cycle).

Forced-LIVE (NOT archived per user directive):
  - app/ai_pipeline_v3.py  (3 importers in audit window, importers themselves DEAD)
  - app/splade_bm25.py       (LIVE via app.rag_service)
  - app/wallet_manager_v2.py (LIVE via x402_enforcement, x402_tools, sweep_all, sweep_now)
  - app/crypto_embeddings.py (NOT in audit ARCHIVE list; heavy import graph)

Verification (forward-import closure from mount.py + main.py + factory.py + lifespan.py):
  - imports = 348 app.* modules
  - reached = 194 files reachable from roots
  - archive set = audit_dead (186) - reached - forced_live (4) - test_live (1) = 136
  - Net delta: 136 files moved, 44,932 LOC reduction, 293->295 active routes (+2 from Wave 3)

pyproject.toml updates:
  - setuptools.packages.find: added exclude for app._archive*
  - ruff.extend-exclude: added "app/_archive/"
  - mypy.exclude: added "app/_archive/"

Smoke test: pytest tests/ — 817 passed, 3 pre-existing failures unchanged
(0 new failures; 0 routes lost; all 4 forced-LIVE files still importable).

Restoration: git mv app/_archive/legacy_2026_07/<name>.py <original-path>
and add the import to app/mount.py ROUTER_MODULES.

Refs: AUDIT-2026-Q3.md /home/dev/pry/rmi-final-deadcode-2026-07-06.md
2026-07-06 20:52:31 +02:00

118 lines
4.2 KiB
Python

#!/usr/bin/env python3
"""One-shot sweep - no interactive prompt. For cron/automation.
Usage: docker exec rmi_backend python3 /app/app/sweep_now.py [--chain sol|eth] [--to ADDR] [--min 1.00]
"""
import argparse
import asyncio
import os
import sys
sys.path.insert(0, "/app")
parser = argparse.ArgumentParser()
parser.add_argument("--chain", default="")
parser.add_argument("--to", default="")
parser.add_argument("--min", type=float, default=1.0)
args = parser.parse_args()
from app.wallet_manager_v2 import get_wallet_manager_v2 # noqa: E402
mgr = get_wallet_manager_v2(os.environ["WALLET_VAULT_PASSWORD"])
evm_chains = {
"eth",
"base",
"polygon",
"arbitrum",
"optimism",
"avalanche",
"bsc",
"fantom",
"gnosis",
}
swept = 0
errors = 0
for w in mgr._wallets.values():
if not w.x402_enabled:
continue
if args.chain and w.chain != args.chain:
continue
if (w.balance_usd or 0) < args.min:
continue
if w.chain not in evm_chains and w.chain != "sol":
continue
mnemonic = mgr.get_mnemonic(w.wallet_id)
if not mnemonic:
continue
try:
if w.chain in evm_chains:
from eth_account import Account
from web3 import Web3
owner = args.to or "0x1E3AC01d0fdb976179790BDD02823196A92705C9"
rpc = os.getenv("ETH_RPC_URL", "https://eth.llamarpc.com")
acct = Account.from_mnemonic(mnemonic)
w3 = Web3(Web3.HTTPProvider(rpc))
bal = w3.eth.get_balance(w.address)
if bal <= w3.to_wei(0.0002, "ether"):
continue
sweep = bal - w3.to_wei(0.0001, "ether")
nonce = w3.eth.get_transaction_count(w.address)
tx = {
"nonce": nonce,
"to": Web3.to_checksum_address(owner),
"value": sweep,
"gas": 21000,
"gasPrice": w3.eth.gas_price,
"chainId": w3.eth.chain_id,
}
signed = w3.eth.account.sign_transaction(tx, acct.key)
h = w3.eth.send_raw_transaction(signed.rawTransaction).hex()
print(f"SWEPT eth {w.address[:12]} -> {owner[:12]} tx={h[:16]}")
swept += 1
elif w.chain == "sol":
from bip_utils import Bip39SeedGenerator, Bip44, Bip44Coins
from solana.rpc.async_api import AsyncClient
from solana.rpc.commitment import Confirmed
from solana.transaction import Transaction
from solders.keypair import Keypair
from solders.pubkey import Pubkey
from solders.system_program import TransferParams, transfer
owner = args.to or "Gix4P9AmwcZRGzr2hCEME5m2QAvY86dBfm8c7e7MpFzv"
rpc = os.getenv("SOLANA_RPC_URL", "https://api.mainnet-beta.solana.com")
seed = Bip39SeedGenerator(mnemonic).Generate()
ctx = Bip44.FromSeed(seed, Bip44Coins.SOLANA).Purpose().Coin().Account(0).Change(0).AddressIndex(0)
kp = Keypair.from_bytes(ctx.PrivateKey().Raw().ToBytes())
async def _do():
async with AsyncClient(rpc) as c: # noqa: B023
resp = await c.get_balance(kp.pubkey(), commitment=Confirmed) # noqa: B023
if resp.value <= 2_000_000:
return
sweep = resp.value - 1_000_000
ix = transfer(
TransferParams(
from_pubkey=kp.pubkey(), # noqa: B023
to_pubkey=Pubkey.from_string(owner), # noqa: B023
lamports=sweep,
)
)
tx = Transaction().add(ix)
tx.sign(kp) # noqa: B023
r = await c.send_transaction(tx, kp) # noqa: B023
return str(r.value)
sig = asyncio.run(_do())
if sig:
print(f"SWEPT sol {w.address[:12]} -> {owner[:12]} tx={sig[:16]}")
swept += 1
except Exception as e:
print(f"ERR {w.chain}: {str(e)[:80]}")
errors += 1
mgr._save_vault()
print("Done: %d swept, %d errors" % (swept, errors)) # noqa: UP031