$ErrorActionPreference = "Stop" $ConfigPath = "C:\MinerOpsAgent\agent-config.json" $Config = Get-Content -Raw $ConfigPath | ConvertFrom-Json $HubUrl = ($Config.hub_url + "").TrimEnd("/") $AgentId = $Config.agent_id $AgentSecret = $Config.agent_secret $Headers = @{ "X-MinerOps-Agent-Secret" = $AgentSecret } function Normalize-MinerOpsIp { param([string] $Ip) if (-not $Ip) { return "" } return ($Ip -replace "/32$", "").Trim() } function Invoke-MinerOps4028PoolsSimple { param( [Parameter(Mandatory=$true)] [string] $Ip, [int] $Port = 4028, [int] $TimeoutMs = 5000 ) $client = $null $stream = $null try { $json = '{"command":"pools"}' $client = New-Object System.Net.Sockets.TcpClient $client.ReceiveTimeout = $TimeoutMs $client.SendTimeout = $TimeoutMs $client.Connect($Ip, $Port) $stream = $client.GetStream() $stream.ReadTimeout = $TimeoutMs $stream.WriteTimeout = $TimeoutMs $bytes = [System.Text.Encoding]::ASCII.GetBytes($json) $stream.Write($bytes, 0, $bytes.Length) $stream.Flush() Start-Sleep -Milliseconds 500 $buffer = New-Object byte[] 131072 $read = $stream.Read($buffer, 0, $buffer.Length) if ($read -le 0) { return $null } $raw = [System.Text.Encoding]::ASCII.GetString($buffer, 0, $read).Trim([char]0).Trim() if (-not $raw) { return $null } $parsed = $raw | ConvertFrom-Json if (-not $parsed.POOLS) { return $null } return @($parsed.POOLS) } catch { return $null } finally { if ($stream) { try { $stream.Close() } catch {} } if ($client) { try { $client.Close() } catch {} } } } $response = Invoke-RestMethod -Method Get -Uri "$HubUrl/api/agent/known-miners" -Headers $Headers -TimeoutSec 60 $knownMiners = @() if ($response.miners) { $knownMiners = @($response.miners) } elseif ($response.data -and $response.data.miners) { $knownMiners = @($response.data.miners) } elseif ($response.data -and $response.data.known_miners) { $knownMiners = @($response.data.known_miners) } Write-Host "Known miners: $($knownMiners.Count)" $poolSnapshots = New-Object System.Collections.Generic.List[object] $count = 0 foreach ($miner in $knownMiners) { $count++ $ip = Normalize-MinerOpsIp -Ip $miner.ip_address if (-not $ip) { continue } if (($count % 25) -eq 0) { Write-Host "Checked $count / $($knownMiners.Count). Collected $($poolSnapshots.Count)." } $pools = @(Invoke-MinerOps4028PoolsSimple -Ip $ip) if ($pools.Count -gt 0) { $poolSnapshots.Add([pscustomobject]@{ miner_id = $miner.miner_id ip_address = $ip mac_address = $miner.mac_address model = $miner.model pools = @($pools) }) } } Write-Host "Pool snapshots collected: $($poolSnapshots.Count)" $body = @{ agent_id = $AgentId pool_snapshots = $poolSnapshots } | ConvertTo-Json -Depth 20 $result = Invoke-RestMethod ` -Method Post ` -Uri "$HubUrl/api/agent/pool-snapshots" ` -Headers $Headers ` -Body $body ` -ContentType "application/json" ` -TimeoutSec 180 $result | ConvertTo-Json -Depth 10