<?php
// =============================================================
// approve_agent.php — одобрение API agent wallet для прямой торговли.
// =============================================================
// Генерирует новую пару ключей агента и подписывает действие approveAgent
// ОСНОВНЫМ приватным ключом, разрешая агенту торговать от имени аккаунта
// (но НЕ выводить средства). После этого основной ключ больше не нужен на
// сервере — в config.php кладётся только приватный ключ агента.
//
// Запуск (CLI):
//     php approve_agent.php [--testnet] [--name copybot]
// Основной приватный ключ читается из STDIN (не из argv — чтобы не попасть
// в список процессов/историю shell).
//
// БЕЗОПАСНОСТЬ: запускай локально или по защищённому каналу. Скрипт не
// логирует основной ключ и обнуляет его в памяти после использования.

if (PHP_SAPI !== 'cli') {
    http_response_code(403);
    exit("Только из командной строки.\n");
}

require_once __DIR__ . '/hyperliquid/Signing.php';
require_once __DIR__ . '/hyperliquid/crypto/Secp256k1.php';

use HL\Signing;
use HL\Crypto\Secp256k1;
use HL\HyperliquidClient;

require_once __DIR__ . '/hyperliquid/HyperliquidClient.php';

// --- аргументы ---
$isMainnet = !in_array('--testnet', $argv, true);
$name = 'copybot';
foreach ($argv as $i => $a) {
    if ($a === '--name' && isset($argv[$i + 1])) {
        $name = $argv[$i + 1];
    }
}

$net = $isMainnet ? 'MAINNET' : 'TESTNET';
fwrite(STDERR, "== Одобрение agent wallet ($net), имя: '$name' ==\n");
fwrite(STDERR, "Вставь ОСНОВНОЙ приватный ключ (0x..., ввод скрыт) и нажми Enter:\n");

// читаем ключ из STDIN без эха
$echoOff = @shell_exec('stty -echo 2>/dev/null');
$mainPriv = trim((string) fgets(STDIN));
@shell_exec('stty echo 2>/dev/null');
fwrite(STDERR, "\n");

if (!preg_match('/^0x[0-9a-fA-F]{64}$/', $mainPriv)) {
    exit("Ошибка: ожидался приватный ключ вида 0x + 64 hex.\n");
}

// --- генерируем агента ---
$agentKey = '0x' . bin2hex(random_bytes(32));
$agentAddr = Secp256k1::privateToAddress($agentKey);
$mainAddr = Secp256k1::privateToAddress($mainPriv);

$action = [
    'type'         => 'approveAgent',
    'agentAddress' => $agentAddr,
    'agentName'    => $name,
    'nonce'        => Signing::getTimestampMs(),
];
$types = [
    ['name' => 'hyperliquidChain', 'type' => 'string'],
    ['name' => 'agentAddress', 'type' => 'address'],
    ['name' => 'agentName', 'type' => 'string'],
    ['name' => 'nonce', 'type' => 'uint64'],
];

$sig = Signing::signUserSignedAction($mainPriv, $action, $types, 'HyperliquidTransaction:ApproveAgent', $isMainnet);

// обнуляем основной ключ в памяти
$mainPriv = str_repeat("\0", strlen($mainPriv));
unset($mainPriv);

// --- отправляем ---
$payload = ['action' => $action, 'nonce' => $action['nonce'], 'signature' => $sig];
$url = $isMainnet ? HyperliquidClient::MAINNET_EXCHANGE : HyperliquidClient::TESTNET_EXCHANGE;

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_SLASHES),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 15,
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
]);
$resp = curl_exec($ch);
$err = curl_error($ch);
curl_close($ch);

if ($err) {
    exit("Сетевая ошибка: $err\n");
}
$decoded = json_decode($resp, true);

echo "\n";
if (is_array($decoded) && ($decoded['status'] ?? null) === 'ok') {
    echo "✅ Агент одобрен.\n\n";
    echo "Добавь в config.php (или переменные окружения):\n\n";
    echo "  HL_ACCOUNT_ADDRESS   = {$mainAddr}\n";
    echo "  HL_AGENT_PRIVATE_KEY = {$agentKey}\n";
    echo "  HL_IS_MAINNET        = " . ($isMainnet ? 'true' : 'false') . "\n\n";
    echo "Агентский адрес: {$agentAddr}\n";
    echo "⚠️  Сохрани HL_AGENT_PRIVATE_KEY надёжно — повторно его не покажут.\n";
} else {
    echo "❌ Не удалось одобрить агента. Ответ биржи:\n";
    echo $resp . "\n";
    echo "\nАгентский ключ НЕ сохраняй (одобрение не прошло). Проверь сеть/баланс/ключ.\n";
}
