golem-vm-provider 0.1.50__tar.gz → 0.1.51__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.
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/PKG-INFO +29 -1
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/README.md +28 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/main.py +178 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/pyproject.toml +1 -1
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/__init__.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/api/__init__.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/api/models.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/api/routes.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/config.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/container.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/data/deployments/l2.json +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/discovery/__init__.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/discovery/advertiser.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/discovery/golem_base_advertiser.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/discovery/golem_base_utils.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/discovery/multi_advertiser.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/discovery/resource_monitor.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/discovery/resource_tracker.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/discovery/service.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/network/port_verifier.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/payments/blockchain_service.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/payments/monitor.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/payments/stream_map.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/security/ethereum.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/security/faucet.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/service.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/utils/__init__.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/utils/ascii_art.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/utils/logging.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/utils/port_display.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/utils/pricing.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/utils/retry.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/utils/setup.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/vm/__init__.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/vm/cloud_init.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/vm/models.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/vm/multipass.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/vm/multipass_adapter.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/vm/name_mapper.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/vm/port_manager.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/vm/provider.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/vm/proxy_manager.py +0 -0
- {golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/vm/service.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: golem-vm-provider
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.51
|
4
4
|
Summary: VM on Golem Provider Node - Run your own provider node to offer VMs on the Golem Network
|
5
5
|
Keywords: golem,vm,provider,cloud,decentralized
|
6
6
|
Author: Phillip Jensen
|
@@ -436,6 +436,34 @@ poetry run golem-provider streams list --json
|
|
436
436
|
poetry run golem-provider streams show <vm_id>
|
437
437
|
```
|
438
438
|
|
439
|
+
- Summarize earnings and withdrawable amounts:
|
440
|
+
|
441
|
+
```bash
|
442
|
+
poetry run golem-provider streams earnings
|
443
|
+
# or JSON
|
444
|
+
poetry run golem-provider streams earnings --json
|
445
|
+
```
|
446
|
+
|
447
|
+
- Withdraw vested funds:
|
448
|
+
|
449
|
+
```bash
|
450
|
+
# One VM by id
|
451
|
+
poetry run golem-provider streams withdraw --vm-id <vm_id>
|
452
|
+
|
453
|
+
# All mapped streams
|
454
|
+
poetry run golem-provider streams withdraw --all
|
455
|
+
```
|
456
|
+
|
457
|
+
Configure monitor and withdraw via CLI:
|
458
|
+
|
459
|
+
```bash
|
460
|
+
# Set monitor to require 1h remaining, check every 30s
|
461
|
+
poetry run golem-provider config monitor --enable true --interval 30 --min-remaining 3600
|
462
|
+
|
463
|
+
# Enable auto-withdraw every 15 minutes when >= 1e15 wei
|
464
|
+
poetry run golem-provider config withdraw --enable true --interval 900 --min-wei 1000000000000000
|
465
|
+
```
|
466
|
+
|
439
467
|
### Resource Advertisement Flow
|
440
468
|
|
441
469
|
```mermaid
|
@@ -391,6 +391,34 @@ poetry run golem-provider streams list --json
|
|
391
391
|
poetry run golem-provider streams show <vm_id>
|
392
392
|
```
|
393
393
|
|
394
|
+
- Summarize earnings and withdrawable amounts:
|
395
|
+
|
396
|
+
```bash
|
397
|
+
poetry run golem-provider streams earnings
|
398
|
+
# or JSON
|
399
|
+
poetry run golem-provider streams earnings --json
|
400
|
+
```
|
401
|
+
|
402
|
+
- Withdraw vested funds:
|
403
|
+
|
404
|
+
```bash
|
405
|
+
# One VM by id
|
406
|
+
poetry run golem-provider streams withdraw --vm-id <vm_id>
|
407
|
+
|
408
|
+
# All mapped streams
|
409
|
+
poetry run golem-provider streams withdraw --all
|
410
|
+
```
|
411
|
+
|
412
|
+
Configure monitor and withdraw via CLI:
|
413
|
+
|
414
|
+
```bash
|
415
|
+
# Set monitor to require 1h remaining, check every 30s
|
416
|
+
poetry run golem-provider config monitor --enable true --interval 30 --min-remaining 3600
|
417
|
+
|
418
|
+
# Enable auto-withdraw every 15 minutes when >= 1e15 wei
|
419
|
+
poetry run golem-provider config withdraw --enable true --interval 900 --min-wei 1000000000000000
|
420
|
+
```
|
421
|
+
|
394
422
|
### Resource Advertisement Flow
|
395
423
|
|
396
424
|
```mermaid
|
@@ -132,6 +132,8 @@ streams_app = typer.Typer(help="Inspect payment streams")
|
|
132
132
|
cli.add_typer(pricing_app, name="pricing")
|
133
133
|
cli.add_typer(wallet_app, name="wallet")
|
134
134
|
cli.add_typer(streams_app, name="streams")
|
135
|
+
config_app = typer.Typer(help="Configure stream monitoring and withdrawals")
|
136
|
+
cli.add_typer(config_app, name="config")
|
135
137
|
|
136
138
|
@cli.callback()
|
137
139
|
def main():
|
@@ -284,6 +286,108 @@ def streams_show(vm_id: str = typer.Argument(..., help="VM id (requestor_name)")
|
|
284
286
|
print(f"Error: {e}")
|
285
287
|
raise typer.Exit(code=1)
|
286
288
|
|
289
|
+
@streams_app.command("earnings")
|
290
|
+
def streams_earnings(json_out: bool = typer.Option(False, "--json", help="Output in JSON")):
|
291
|
+
"""Summarize provider earnings: vested, withdrawn, and withdrawable totals."""
|
292
|
+
from .container import Container
|
293
|
+
from .config import settings
|
294
|
+
from .payments.blockchain_service import StreamPaymentReader
|
295
|
+
import json as _json
|
296
|
+
try:
|
297
|
+
c = Container()
|
298
|
+
c.config.from_pydantic(settings)
|
299
|
+
stream_map = c.stream_map()
|
300
|
+
reader = StreamPaymentReader(settings.POLYGON_RPC_URL, settings.STREAM_PAYMENT_ADDRESS)
|
301
|
+
items = asyncio.run(stream_map.all_items())
|
302
|
+
now = int(reader.web3.eth.get_block("latest")["timestamp"]) if items else 0
|
303
|
+
rows = []
|
304
|
+
total_vested = 0
|
305
|
+
total_withdrawn = 0
|
306
|
+
total_withdrawable = 0
|
307
|
+
for vm_id, stream_id in items.items():
|
308
|
+
try:
|
309
|
+
s = reader.get_stream(int(stream_id))
|
310
|
+
vested = max(min(now, int(s["stopTime"])) - int(s["startTime"]), 0) * int(s["ratePerSecond"]) # type: ignore
|
311
|
+
withdrawable = max(int(vested) - int(s["withdrawn"]), 0)
|
312
|
+
total_vested += int(vested)
|
313
|
+
total_withdrawn += int(s["withdrawn"]) # type: ignore
|
314
|
+
total_withdrawable += int(withdrawable)
|
315
|
+
rows.append({
|
316
|
+
"vm_id": vm_id,
|
317
|
+
"stream_id": int(stream_id),
|
318
|
+
"vested": int(vested),
|
319
|
+
"withdrawn": int(s["withdrawn"]),
|
320
|
+
"withdrawable": int(withdrawable),
|
321
|
+
})
|
322
|
+
except Exception as e:
|
323
|
+
rows.append({"vm_id": vm_id, "stream_id": int(stream_id), "error": str(e)})
|
324
|
+
out = {
|
325
|
+
"streams": rows,
|
326
|
+
"totals": {
|
327
|
+
"vested": int(total_vested),
|
328
|
+
"withdrawn": int(total_withdrawn),
|
329
|
+
"withdrawable": int(total_withdrawable),
|
330
|
+
}
|
331
|
+
}
|
332
|
+
if json_out:
|
333
|
+
print(_json.dumps(out, indent=2))
|
334
|
+
return
|
335
|
+
print("\nEarnings summary (wei):")
|
336
|
+
print(f" Vested total : {total_vested}")
|
337
|
+
print(f" Withdrawn total : {total_withdrawn}")
|
338
|
+
print(f" Withdrawable total: {total_withdrawable}")
|
339
|
+
if rows:
|
340
|
+
print("\nPer-stream:")
|
341
|
+
for r in rows:
|
342
|
+
if "error" in r:
|
343
|
+
print(f"- {r['vm_id']} [{r['stream_id']}] ERROR: {r['error']}")
|
344
|
+
else:
|
345
|
+
print(f"- {r['vm_id']} [{r['stream_id']}]: vested={r['vested']} withdrawn={r['withdrawn']} withdrawable={r['withdrawable']}")
|
346
|
+
except Exception as e:
|
347
|
+
print(f"Error: {e}")
|
348
|
+
raise typer.Exit(code=1)
|
349
|
+
|
350
|
+
|
351
|
+
@streams_app.command("withdraw")
|
352
|
+
def streams_withdraw(
|
353
|
+
vm_id: str = typer.Option(None, "--vm-id", help="Withdraw for a single VM id"),
|
354
|
+
all_streams: bool = typer.Option(False, "--all", help="Withdraw for all mapped streams"),
|
355
|
+
):
|
356
|
+
"""Withdraw vested funds for one or all streams."""
|
357
|
+
from .container import Container
|
358
|
+
from .config import settings
|
359
|
+
try:
|
360
|
+
if not vm_id and not all_streams:
|
361
|
+
print("Specify --vm-id or --all")
|
362
|
+
raise typer.Exit(code=1)
|
363
|
+
c = Container()
|
364
|
+
c.config.from_pydantic(settings)
|
365
|
+
stream_map = c.stream_map()
|
366
|
+
client = c.stream_client()
|
367
|
+
targets = []
|
368
|
+
if all_streams:
|
369
|
+
items = asyncio.run(stream_map.all_items())
|
370
|
+
for vid, sid in items.items():
|
371
|
+
targets.append((vid, int(sid)))
|
372
|
+
else:
|
373
|
+
sid = asyncio.run(stream_map.get(vm_id))
|
374
|
+
if sid is None:
|
375
|
+
print("No stream mapped for this VM.")
|
376
|
+
raise typer.Exit(code=1)
|
377
|
+
targets.append((vm_id, int(sid)))
|
378
|
+
results = []
|
379
|
+
for vid, sid in targets:
|
380
|
+
try:
|
381
|
+
tx = client.withdraw(int(sid))
|
382
|
+
results.append((vid, sid, tx))
|
383
|
+
print(f"Withdrew stream {sid} for VM {vid}: tx={tx}")
|
384
|
+
except Exception as e:
|
385
|
+
print(f"Failed to withdraw stream {sid} for VM {vid}: {e}")
|
386
|
+
# no JSON aggregation here; use earnings for structured output
|
387
|
+
except Exception as e:
|
388
|
+
print(f"Error: {e}")
|
389
|
+
raise typer.Exit(code=1)
|
390
|
+
|
287
391
|
@cli.command()
|
288
392
|
def start(
|
289
393
|
no_verify_port: bool = typer.Option(False, "--no-verify-port", help="Skip provider port verification."),
|
@@ -331,6 +435,80 @@ def _write_env_vars(path: str, updates: dict):
|
|
331
435
|
with open(path, "w") as f:
|
332
436
|
f.writelines(out)
|
333
437
|
|
438
|
+
|
439
|
+
@config_app.command("withdraw")
|
440
|
+
def config_withdraw(
|
441
|
+
enable: bool = typer.Option(None, "--enable", help="Enable/disable auto-withdraw (true/false)"),
|
442
|
+
interval: int = typer.Option(None, "--interval", help="Withdraw interval in seconds (e.g., 1800)"),
|
443
|
+
min_wei: int = typer.Option(None, "--min-wei", help="Only withdraw when >= this wei amount"),
|
444
|
+
dev: bool = typer.Option(False, "--dev", help="Write to .env.dev instead of .env"),
|
445
|
+
):
|
446
|
+
"""Configure provider auto-withdraw settings and persist to .env(.dev)."""
|
447
|
+
from .config import settings
|
448
|
+
env_path = _env_path_for(dev)
|
449
|
+
updates = {}
|
450
|
+
if enable is not None:
|
451
|
+
updates["GOLEM_PROVIDER_STREAM_WITHDRAW_ENABLED"] = str(enable).lower()
|
452
|
+
settings.STREAM_WITHDRAW_ENABLED = bool(enable)
|
453
|
+
if interval is not None:
|
454
|
+
if interval < 0:
|
455
|
+
raise typer.BadParameter("--interval must be >= 0")
|
456
|
+
updates["GOLEM_PROVIDER_STREAM_WITHDRAW_INTERVAL_SECONDS"] = int(interval)
|
457
|
+
try:
|
458
|
+
settings.STREAM_WITHDRAW_INTERVAL_SECONDS = int(interval)
|
459
|
+
except Exception:
|
460
|
+
pass
|
461
|
+
if min_wei is not None:
|
462
|
+
if min_wei < 0:
|
463
|
+
raise typer.BadParameter("--min-wei must be >= 0")
|
464
|
+
updates["GOLEM_PROVIDER_STREAM_MIN_WITHDRAW_WEI"] = int(min_wei)
|
465
|
+
try:
|
466
|
+
settings.STREAM_MIN_WITHDRAW_WEI = int(min_wei)
|
467
|
+
except Exception:
|
468
|
+
pass
|
469
|
+
if not updates:
|
470
|
+
print("No changes (use --enable/--interval/--min-wei)")
|
471
|
+
raise typer.Exit(code=0)
|
472
|
+
_write_env_vars(env_path, updates)
|
473
|
+
print(f"Updated withdraw settings in {env_path}")
|
474
|
+
|
475
|
+
|
476
|
+
@config_app.command("monitor")
|
477
|
+
def config_monitor(
|
478
|
+
enable: bool = typer.Option(None, "--enable", help="Enable/disable stream monitor (true/false)"),
|
479
|
+
interval: int = typer.Option(None, "--interval", help="Monitor interval in seconds (e.g., 30)"),
|
480
|
+
min_remaining: int = typer.Option(None, "--min-remaining", help="Minimum remaining runway to keep VM running (seconds)"),
|
481
|
+
dev: bool = typer.Option(False, "--dev", help="Write to .env.dev instead of .env"),
|
482
|
+
):
|
483
|
+
"""Configure provider stream monitor and persist to .env(.dev)."""
|
484
|
+
from .config import settings
|
485
|
+
env_path = _env_path_for(dev)
|
486
|
+
updates = {}
|
487
|
+
if enable is not None:
|
488
|
+
updates["GOLEM_PROVIDER_STREAM_MONITOR_ENABLED"] = str(enable).lower()
|
489
|
+
settings.STREAM_MONITOR_ENABLED = bool(enable)
|
490
|
+
if interval is not None:
|
491
|
+
if interval < 0:
|
492
|
+
raise typer.BadParameter("--interval must be >= 0")
|
493
|
+
updates["GOLEM_PROVIDER_STREAM_MONITOR_INTERVAL_SECONDS"] = int(interval)
|
494
|
+
try:
|
495
|
+
settings.STREAM_MONITOR_INTERVAL_SECONDS = int(interval)
|
496
|
+
except Exception:
|
497
|
+
pass
|
498
|
+
if min_remaining is not None:
|
499
|
+
if min_remaining < 0:
|
500
|
+
raise typer.BadParameter("--min-remaining must be >= 0")
|
501
|
+
updates["GOLEM_PROVIDER_STREAM_MIN_REMAINING_SECONDS"] = int(min_remaining)
|
502
|
+
try:
|
503
|
+
settings.STREAM_MIN_REMAINING_SECONDS = int(min_remaining)
|
504
|
+
except Exception:
|
505
|
+
pass
|
506
|
+
if not updates:
|
507
|
+
print("No changes (use --enable/--interval/--min-remaining)")
|
508
|
+
raise typer.Exit(code=0)
|
509
|
+
_write_env_vars(env_path, updates)
|
510
|
+
print(f"Updated monitor settings in {env_path}")
|
511
|
+
|
334
512
|
def _print_pricing_examples(glm_usd):
|
335
513
|
from decimal import Decimal
|
336
514
|
from .utils.pricing import calculate_monthly_cost, calculate_monthly_cost_usd
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "golem-vm-provider"
|
3
|
-
version = "0.1.
|
3
|
+
version = "0.1.51"
|
4
4
|
description = "VM on Golem Provider Node - Run your own provider node to offer VMs on the Golem Network"
|
5
5
|
authors = ["Phillip Jensen <phillip+vm-on-golem@golemgrid.com>"]
|
6
6
|
readme = "README.md"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/discovery/golem_base_advertiser.py
RENAMED
File without changes
|
{golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/discovery/golem_base_utils.py
RENAMED
File without changes
|
{golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/discovery/multi_advertiser.py
RENAMED
File without changes
|
{golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/discovery/resource_monitor.py
RENAMED
File without changes
|
{golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/discovery/resource_tracker.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{golem_vm_provider-0.1.50 → golem_vm_provider-0.1.51}/provider/payments/blockchain_service.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|