blockmachine 0.22.0__tar.gz → 0.23.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {blockmachine-0.22.0 → blockmachine-0.23.0}/PKG-INFO +2 -2
- {blockmachine-0.22.0 → blockmachine-0.23.0}/blockmachine.egg-info/PKG-INFO +2 -2
- {blockmachine-0.22.0 → blockmachine-0.23.0}/blockmachine.egg-info/SOURCES.txt +4 -2
- {blockmachine-0.22.0 → blockmachine-0.23.0}/blockmachine.egg-info/requires.txt +1 -1
- {blockmachine-0.22.0 → blockmachine-0.23.0}/commands/epoch.py +53 -7
- {blockmachine-0.22.0 → blockmachine-0.23.0}/commands/leaderboard.py +10 -11
- {blockmachine-0.22.0 → blockmachine-0.23.0}/commands/miner.py +43 -544
- {blockmachine-0.22.0 → blockmachine-0.23.0}/main.py +0 -11
- {blockmachine-0.22.0 → blockmachine-0.23.0}/pyproject.toml +2 -2
- {blockmachine-0.22.0 → blockmachine-0.23.0}/settings.py +7 -25
- {blockmachine-0.22.0 → blockmachine-0.23.0}/tests/test_cli_config.py +4 -43
- blockmachine-0.23.0/tests/test_cli_help.py +42 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/tests/test_epoch_payout_cli.py +101 -3
- {blockmachine-0.22.0 → blockmachine-0.23.0}/tests/test_leaderboard_cli.py +14 -4
- {blockmachine-0.22.0 → blockmachine-0.23.0}/tests/test_miner_add_class.py +0 -1
- {blockmachine-0.22.0 → blockmachine-0.23.0}/tests/test_miner_eligibility.py +24 -0
- blockmachine-0.23.0/tests/test_miner_eth_tier.py +61 -0
- blockmachine-0.23.0/tests/test_miner_metrics.py +20 -0
- blockmachine-0.23.0/tests/test_miner_pricing.py +41 -0
- blockmachine-0.22.0/tests/test_miner_capacity.py +0 -451
- blockmachine-0.22.0/tests/test_miner_eth_tier.py +0 -195
- {blockmachine-0.22.0 → blockmachine-0.23.0}/__init__.py +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/auth_config.py +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/blockmachine.egg-info/dependency_links.txt +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/blockmachine.egg-info/entry_points.txt +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/blockmachine.egg-info/top_level.txt +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/client.py +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/commands/__init__.py +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/commands/auth.py +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/commands/validator.py +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/config.py +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/endpoints.py +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/setup.cfg +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/testing.py +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/tests/test_cli_endpoints_and_testing.py +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/tests/test_miner_ban_line.py +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/tests/test_miner_compat_reason.py +0 -0
- {blockmachine-0.22.0 → blockmachine-0.23.0}/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: blockmachine
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.23.0
|
|
4
4
|
Summary: Blockmachine CLI - Miner and validator operator interface
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/taostat/blockmachine
|
|
@@ -8,7 +8,7 @@ Classifier: Development Status :: 3 - Alpha
|
|
|
8
8
|
Classifier: Environment :: Console
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
10
|
Requires-Python: >=3.10
|
|
11
|
-
Requires-Dist: typer
|
|
11
|
+
Requires-Dist: typer<0.26.0,>=0.9.0
|
|
12
12
|
Requires-Dist: rich>=13.7.0
|
|
13
13
|
Requires-Dist: httpx>=0.27.0
|
|
14
14
|
Requires-Dist: websockets>=13.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: blockmachine
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.23.0
|
|
4
4
|
Summary: Blockmachine CLI - Miner and validator operator interface
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/taostat/blockmachine
|
|
@@ -8,7 +8,7 @@ Classifier: Development Status :: 3 - Alpha
|
|
|
8
8
|
Classifier: Environment :: Console
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
10
|
Requires-Python: >=3.10
|
|
11
|
-
Requires-Dist: typer
|
|
11
|
+
Requires-Dist: typer<0.26.0,>=0.9.0
|
|
12
12
|
Requires-Dist: rich>=13.7.0
|
|
13
13
|
Requires-Dist: httpx>=0.27.0
|
|
14
14
|
Requires-Dist: websockets>=13.0
|
|
@@ -31,11 +31,13 @@ commands/miner.py
|
|
|
31
31
|
commands/validator.py
|
|
32
32
|
tests/test_cli_config.py
|
|
33
33
|
tests/test_cli_endpoints_and_testing.py
|
|
34
|
+
tests/test_cli_help.py
|
|
34
35
|
tests/test_epoch_payout_cli.py
|
|
35
36
|
tests/test_leaderboard_cli.py
|
|
36
37
|
tests/test_miner_add_class.py
|
|
37
38
|
tests/test_miner_ban_line.py
|
|
38
|
-
tests/test_miner_capacity.py
|
|
39
39
|
tests/test_miner_compat_reason.py
|
|
40
40
|
tests/test_miner_eligibility.py
|
|
41
|
-
tests/test_miner_eth_tier.py
|
|
41
|
+
tests/test_miner_eth_tier.py
|
|
42
|
+
tests/test_miner_metrics.py
|
|
43
|
+
tests/test_miner_pricing.py
|
|
@@ -84,7 +84,7 @@ def render_payout(body: dict, top: int = TOP_MINERS) -> list[str]:
|
|
|
84
84
|
|
|
85
85
|
lines.append(
|
|
86
86
|
f" {'UID':<4} {'alpha':>9} {'USD':>9} {'share':>5} "
|
|
87
|
-
"breakdown (chain/class → α)"
|
|
87
|
+
"breakdown (chain/request class → α)"
|
|
88
88
|
)
|
|
89
89
|
for m in miners[:top]:
|
|
90
90
|
lines.append(
|
|
@@ -103,27 +103,69 @@ def render_payout(body: dict, top: int = TOP_MINERS) -> list[str]:
|
|
|
103
103
|
return lines
|
|
104
104
|
|
|
105
105
|
|
|
106
|
+
def _has_cu_split(miner: dict) -> bool:
|
|
107
|
+
"""Does this body separate served CU from the base-incentive subsidy?
|
|
108
|
+
|
|
109
|
+
Registries built before taostat/blockmachine_playground#1529 send one
|
|
110
|
+
unqualified ``cu`` and nothing else. Printing zero served CU against
|
|
111
|
+
those would be a new lie, so the old single column is kept for them.
|
|
112
|
+
"""
|
|
113
|
+
return "cu_served" in miner and "cu_base_incentive" in miner
|
|
114
|
+
|
|
115
|
+
|
|
106
116
|
def render_miner(body: dict, miner: dict) -> list[str]:
|
|
107
|
-
"""One miner with every
|
|
117
|
+
"""One miner with every chain and request-class line."""
|
|
108
118
|
header = render_payout(body)
|
|
109
119
|
lines = header[: header.index("")]
|
|
120
|
+
split = _has_cu_split(miner)
|
|
121
|
+
cu_total = int(miner.get("cu_total") or 0)
|
|
110
122
|
lines.append("")
|
|
111
123
|
lines.append(
|
|
112
124
|
f"UID {miner.get('uid')} {miner.get('hotkey')}\n"
|
|
113
125
|
f" {float(miner.get('alpha') or 0):.1f} α "
|
|
114
126
|
f"(${_fmt_usd(miner.get('usd'))}, "
|
|
115
|
-
f"{float(miner.get('share') or 0) * 100:.1f}% of the pool
|
|
116
|
-
f"{
|
|
127
|
+
f"{float(miner.get('share') or 0) * 100:.1f}% of the pool"
|
|
128
|
+
+ (")" if split else f", {cu_total:,} CU)")
|
|
117
129
|
)
|
|
130
|
+
if split:
|
|
131
|
+
lines.append(
|
|
132
|
+
f" {cu_total:,} CU: {int(miner.get('cu_served') or 0):,} served "
|
|
133
|
+
f"+ {int(miner.get('cu_base_incentive') or 0):,} base incentive"
|
|
134
|
+
)
|
|
118
135
|
lines.append("")
|
|
119
|
-
|
|
136
|
+
if split:
|
|
137
|
+
lines.append(
|
|
138
|
+
f" {'chain/request class':<22} {'served CU':>15} "
|
|
139
|
+
f"{'base incentive CU':>19} {'alpha':>9} {'USD':>9}"
|
|
140
|
+
)
|
|
141
|
+
else:
|
|
142
|
+
lines.append(
|
|
143
|
+
f" {'chain/request class':<22} {'CU':>15} {'alpha':>9} {'USD':>9}"
|
|
144
|
+
)
|
|
120
145
|
for e in miner.get("breakdown") or []:
|
|
121
146
|
node = f"{e.get('chain')}/{e.get('node_class')}"
|
|
147
|
+
cu_col = (
|
|
148
|
+
f"{int(e.get('cu_served') or 0):>15,} "
|
|
149
|
+
f"{int(e.get('cu_base_incentive') or 0):>19,}"
|
|
150
|
+
if split
|
|
151
|
+
else f"{int(e.get('cu') or 0):>15,}"
|
|
152
|
+
)
|
|
122
153
|
lines.append(
|
|
123
|
-
f" {node:<18} {
|
|
154
|
+
f" {node:<18} {cu_col} "
|
|
124
155
|
f"{float(e.get('alpha') or 0):>9.1f} {_fmt_usd(e.get('usd')):>9}"
|
|
125
156
|
)
|
|
126
157
|
lines.append("")
|
|
158
|
+
if split:
|
|
159
|
+
lines.append(
|
|
160
|
+
"Served CU is the customer traffic this miner answered. Base incentive "
|
|
161
|
+
"CU is the"
|
|
162
|
+
)
|
|
163
|
+
lines.append(
|
|
164
|
+
"subnet's own top-up, injected as CU — nobody sent those requests. "
|
|
165
|
+
"Both count"
|
|
166
|
+
)
|
|
167
|
+
lines.append("toward the payout, and together they are the CU total above.")
|
|
168
|
+
lines.append("")
|
|
127
169
|
lines.append(
|
|
128
170
|
"USD is an estimate at the α price the finalizer recorded; the chain pays in α."
|
|
129
171
|
)
|
|
@@ -144,8 +186,12 @@ def payout(
|
|
|
144
186
|
|
|
145
187
|
Per UID: alpha, USD (an estimate at the price recorded when the epoch
|
|
146
188
|
was finalized), share of the miner pool, and the alpha split by chain
|
|
147
|
-
and
|
|
189
|
+
and request class. Available the moment an epoch finalizes; the chain pays
|
|
148
190
|
it out over the following epoch.
|
|
191
|
+
|
|
192
|
+
With --uid, CU is shown as two columns: the customer traffic the miner
|
|
193
|
+
answered, and the base-incentive subsidy injected as synthetic CU. Both
|
|
194
|
+
count toward the payout; only the first is traffic.
|
|
149
195
|
"""
|
|
150
196
|
path = "/epochs/latest/payout" if epoch is None else f"/epochs/{epoch}/payout"
|
|
151
197
|
with RegistryClient(load_config()) as client:
|
|
@@ -238,9 +238,8 @@ def _render_default(
|
|
|
238
238
|
) -> None:
|
|
239
239
|
"""Render the default leaderboard view (Option B).
|
|
240
240
|
|
|
241
|
-
When ``verbose`` is True, ETH node sub-rows include the
|
|
242
|
-
|
|
243
|
-
operators can inspect what the gateway actually probed.
|
|
241
|
+
When ``verbose`` is True, ETH node sub-rows include the three
|
|
242
|
+
capability flags (``A P X``) after the tier label.
|
|
244
243
|
"""
|
|
245
244
|
miners = data.get("miners", [])
|
|
246
245
|
epoch = data.get("epoch")
|
|
@@ -363,8 +362,8 @@ def _render_default(
|
|
|
363
362
|
def _recompute_shares(miners: list[dict], archive: bool) -> list[dict]:
|
|
364
363
|
"""Recompute routing scores and traffic shares for the selected dimension.
|
|
365
364
|
|
|
366
|
-
When archive=True, filters to
|
|
367
|
-
routing_score_archive / price_factor_archive.
|
|
365
|
+
When archive=True, filters to nodes marked ``is_archive`` or
|
|
366
|
+
``serves_proofs`` and uses routing_score_archive / price_factor_archive.
|
|
368
367
|
Adds _score, _share, _price_factor to each miner and _share to each node.
|
|
369
368
|
"""
|
|
370
369
|
results = []
|
|
@@ -373,7 +372,7 @@ def _recompute_shares(miners: list[dict], archive: bool) -> list[dict]:
|
|
|
373
372
|
for miner in miners:
|
|
374
373
|
nodes = miner.get("nodes", [])
|
|
375
374
|
if archive:
|
|
376
|
-
nodes = [n for n in nodes if n.get("is_archive"
|
|
375
|
+
nodes = [n for n in nodes if n.get("is_archive") or n.get("serves_proofs")]
|
|
377
376
|
miner_score = 0.0
|
|
378
377
|
for node in nodes:
|
|
379
378
|
ns = _node_score_field(node, "routing_score", archive) or 0.0
|
|
@@ -503,10 +502,10 @@ def _render_detail(
|
|
|
503
502
|
f"{p95_label}{_bottleneck_label(lat)}"
|
|
504
503
|
)
|
|
505
504
|
|
|
506
|
-
# Reliability saturates at
|
|
505
|
+
# Reliability saturates at 3 good epochs (gateway cap);
|
|
507
506
|
# more history exists but no longer buys score.
|
|
508
507
|
ep_label = (
|
|
509
|
-
f" ({epochs_good} good epochs; score saturates at
|
|
508
|
+
f" ({epochs_good} good epochs; score saturates at 3)"
|
|
510
509
|
if epochs_good is not None
|
|
511
510
|
else ""
|
|
512
511
|
)
|
|
@@ -560,15 +559,15 @@ def show(
|
|
|
560
559
|
None,
|
|
561
560
|
"--chain",
|
|
562
561
|
"-c",
|
|
563
|
-
help="Filter to a single chain (e.g. eth, tao, bsc, base, polygon, optimism, arbitrum, avalanche, scroll, mantle, robinhood, tron). Default: all chains.",
|
|
562
|
+
help="Filter to a single chain (e.g. eth, tao, bsc, base, polygon, optimism, arbitrum, avalanche, arc, scroll, mantle, robinhood, tron). Default: all chains.",
|
|
564
563
|
),
|
|
565
564
|
verbose: bool = typer.Option(
|
|
566
565
|
False,
|
|
567
566
|
"--verbose",
|
|
568
567
|
"-v",
|
|
569
568
|
help=(
|
|
570
|
-
"For ETH nodes, show raw capability flags (A P
|
|
571
|
-
"archive, proof,
|
|
569
|
+
"For ETH nodes, show raw capability flags (A P X = "
|
|
570
|
+
"archive, proof, audit-compatible) alongside "
|
|
572
571
|
"the tier label."
|
|
573
572
|
),
|
|
574
573
|
),
|