Files
coinhunter-cli/tests/test_account_market_services.py
Tacit Lab 3855477155 refactor: flatten account command to a single balances view
Remove overview/balances/positions subcommands in favor of one
`account` command that returns all balances with an `is_dust` flag.
Add descriptions to every parser and expose -a/--agent and --doc
on all leaf commands for better help discoverability.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-17 18:19:19 +08:00

96 lines
3.2 KiB
Python

"""Account and market service tests."""
from __future__ import annotations
import unittest
from coinhunter.services import account_service, market_service
class FakeSpotClient:
def account_info(self):
return {
"balances": [
{"asset": "USDT", "free": "120.0", "locked": "0"},
{"asset": "BTC", "free": "0.01", "locked": "0"},
{"asset": "DOGE", "free": "1", "locked": "0"},
]
}
def ticker_price(self, symbols=None):
prices = {
"BTCUSDT": {"symbol": "BTCUSDT", "price": "60000"},
"DOGEUSDT": {"symbol": "DOGEUSDT", "price": "0.1"},
}
if not symbols:
return list(prices.values())
return [prices[symbol] for symbol in symbols]
def ticker_24h(self, symbols=None):
rows = [
{
"symbol": "BTCUSDT",
"lastPrice": "60000",
"priceChangePercent": "4.5",
"quoteVolume": "10000000",
"highPrice": "61000",
"lowPrice": "58000",
},
{
"symbol": "ETHUSDT",
"lastPrice": "3000",
"priceChangePercent": "3.0",
"quoteVolume": "8000000",
"highPrice": "3050",
"lowPrice": "2900",
},
{
"symbol": "DOGEUSDT",
"lastPrice": "0.1",
"priceChangePercent": "1.0",
"quoteVolume": "200",
"highPrice": "0.11",
"lowPrice": "0.09",
},
]
if not symbols:
return rows
wanted = set(symbols)
return [row for row in rows if row["symbol"] in wanted]
def exchange_info(self):
return {
"symbols": [
{"symbol": "BTCUSDT", "status": "TRADING"},
{"symbol": "ETHUSDT", "status": "TRADING"},
{"symbol": "DOGEUSDT", "status": "BREAK"},
]
}
class AccountMarketServicesTestCase(unittest.TestCase):
def test_get_balances_with_dust_flag(self):
config = {
"market": {"default_quote": "USDT"},
"trading": {"dust_usdt_threshold": 10.0},
}
payload = account_service.get_balances(
config,
spot_client=FakeSpotClient(),
)
balances = {item["asset"]: item for item in payload["balances"]}
self.assertFalse(balances["USDT"]["is_dust"])
self.assertFalse(balances["BTC"]["is_dust"])
self.assertTrue(balances["DOGE"]["is_dust"])
def test_market_tickers_and_scan_universe(self):
config = {
"market": {"default_quote": "USDT", "universe_allowlist": [], "universe_denylist": []},
"opportunity": {"min_quote_volume": 1000},
}
tickers = market_service.get_tickers(config, ["btc/usdt", "ETH-USDT"], spot_client=FakeSpotClient())
self.assertEqual([item["symbol"] for item in tickers["tickers"]], ["BTCUSDT", "ETHUSDT"])
universe = market_service.get_scan_universe(config, spot_client=FakeSpotClient())
self.assertEqual([item["symbol"] for item in universe], ["BTCUSDT", "ETHUSDT"])