<?php
// =============================================================
// Golden-векторы подписи Hyperliquid — порт tests/signing_test.py.
// =============================================================
// Запуск: php tests/hyperliquid_signing_test.php
// Самодостаточно, без composer. Проверяет, что PHP-подпись побайтово
// совпадает с официальным Python-SDK (msgpack + keccak + EIP-712 +
// secp256k1 ECDSA + RFC6979).

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

use HL\Signing;
use HL\Msgpack;

$PRIV = '0x0123456789012345678901234567890123456789012345678901234567890123';

$pass = 0;
$fail = 0;
function check(string $name, $got, $expect): void
{
    global $pass, $fail;
    if ($got === $expect) {
        $pass++;
        echo "  ✓ $name\n";
    } else {
        $fail++;
        echo "  ✗ $name\n      got:    " . var_export($got, true) . "\n      expect: " . var_export($expect, true) . "\n";
    }
}

function checkSig(string $name, array $sig, string $r, string $s, int $v): void
{
    check("$name r", $sig['r'], $r);
    check("$name s", $sig['s'], $s);
    check("$name v", $sig['v'], $v);
}

echo "== action_hash / phantom agent ==\n";
$wire = Signing::orderRequestToWire([
    'coin' => 'ETH', 'is_buy' => true, 'sz' => 0.0147, 'limit_px' => 1670.1,
    'reduce_only' => false, 'order_type' => ['limit' => ['tif' => 'Ioc']],
], 4);
$action = Signing::orderWiresToAction([$wire]);
$hash = Signing::actionHash($action, null, 1677777606040, null);
check('phantom connectionId', '0x' . bin2hex($hash),
    '0x0fcbeda5ae3c4950a548021552a4fea2226858c4453571bf3f24ba017eac2908');

echo "== float helpers ==\n";
// Прим.: кейс SDK floatToIntForHashing(123123123123)=12312312312300000000 опущен —
// результат (1.23e19) превышает PHP_INT_MAX (9.2e18) и непредставим в int64.
// Реальные размеры * 1e8 остаются глубоко внутри int64 (см. dummy num=1e11 ниже).
check('floatToIntForHashing(0.00001231)', Signing::floatToIntForHashing(0.00001231), 1231);
check('floatToIntForHashing(1.033)', Signing::floatToIntForHashing(1.033), 103300000);
check('floatToWire(100)', Signing::floatToWire(100.0), '100');
check('floatToWire(1670.1)', Signing::floatToWire(1670.1), '1670.1');

echo "== sign_l1_action: dummy ==\n";
$action = ['type' => 'dummy', 'num' => Signing::floatToIntForHashing(1000)];
checkSig('dummy mainnet', Signing::signL1Action($PRIV, $action, null, 0, null, true),
    '0x53749d5b30552aeb2fca34b530185976545bb22d0b3ce6f62e31be961a59298',
    '0x755c40ba9bf05223521753995abb2f73ab3229be8ec921f350cb447e384d8ed8', 27);
checkSig('dummy testnet', Signing::signL1Action($PRIV, $action, null, 0, null, false),
    '0x542af61ef1f429707e3c76c5293c80d01f74ef853e34b76efffcb57e574f9510',
    '0x17b8b32f086e8cdede991f1e2c529f5dd5297cbe8128500e00cbaf766204a613', 28);

echo "== sign_l1_action: order ==\n";
$wire = Signing::orderRequestToWire([
    'coin' => 'ETH', 'is_buy' => true, 'sz' => 100, 'limit_px' => 100,
    'reduce_only' => false, 'order_type' => ['limit' => ['tif' => 'Gtc']],
], 1);
$action = Signing::orderWiresToAction([$wire]);
checkSig('order mainnet', Signing::signL1Action($PRIV, $action, null, 0, null, true),
    '0xd65369825a9df5d80099e513cce430311d7d26ddf477f5b3a33d2806b100d78e',
    '0x2b54116ff64054968aa237c20ca9ff68000f977c93289157748a3162b6ea940e', 28);
checkSig('order testnet', Signing::signL1Action($PRIV, $action, null, 0, null, false),
    '0x82b2ba28e76b3d761093aaded1b1cdad4960b3af30212b343fb2e6cdfa4e3d54',
    '0x6b53878fc99d26047f4d7e8c90eb98955a109f44209163f52d8dc4278cbbd9f5', 27);

echo "== sign_l1_action: order with cloid ==\n";
$wire = Signing::orderRequestToWire([
    'coin' => 'ETH', 'is_buy' => true, 'sz' => 100, 'limit_px' => 100,
    'reduce_only' => false, 'order_type' => ['limit' => ['tif' => 'Gtc']],
    'cloid' => '0x00000000000000000000000000000001',
], 1);
$action = Signing::orderWiresToAction([$wire]);
checkSig('cloid mainnet', Signing::signL1Action($PRIV, $action, null, 0, null, true),
    '0x41ae18e8239a56cacbc5dad94d45d0b747e5da11ad564077fcac71277a946e3',
    '0x3c61f667e747404fe7eea8f90ab0e76cc12ce60270438b2058324681a00116da', 27);
checkSig('cloid testnet', Signing::signL1Action($PRIV, $action, null, 0, null, false),
    '0xeba0664bed2676fc4e5a743bf89e5c7501aa6d870bdb9446e122c9466c5cd16d',
    '0x7f3e74825c9114bc59086f1eebea2928c190fdfbfde144827cb02b85bbe90988', 28);

echo "== sign_l1_action: with vault ==\n";
$action = ['type' => 'dummy', 'num' => Signing::floatToIntForHashing(1000)];
checkSig('vault mainnet', Signing::signL1Action($PRIV, $action, '0x1719884eb866cb12b2287399b15f7db5e7d775ea', 0, null, true),
    '0x3c548db75e479f8012acf3000ca3a6b05606bc2ec0c29c50c515066a326239',
    '0x4d402be7396ce74fbba3795769cda45aec00dc3125a984f2a9f23177b190da2c', 28);
checkSig('vault testnet', Signing::signL1Action($PRIV, $action, '0x1719884eb866cb12b2287399b15f7db5e7d775ea', 0, null, false),
    '0xe281d2fb5c6e25ca01601f878e4d69c965bb598b88fac58e475dd1f5e56c362b',
    '0x7ddad27e9a238d045c035bc606349d075d5c5cd00a6cd1da23ab5c39d4ef0f60', 27);

echo "== sign_l1_action: tpsl trigger ==\n";
$wire = Signing::orderRequestToWire([
    'coin' => 'ETH', 'is_buy' => true, 'sz' => 100, 'limit_px' => 100,
    'reduce_only' => false,
    'order_type' => ['trigger' => ['triggerPx' => 103, 'isMarket' => true, 'tpsl' => 'sl']],
], 1);
$action = Signing::orderWiresToAction([$wire]);
checkSig('tpsl mainnet', Signing::signL1Action($PRIV, $action, null, 0, null, true),
    '0x98343f2b5ae8e26bb2587daad3863bc70d8792b09af1841b6fdd530a2065a3f9',
    '0x6b5bb6bb0633b710aa22b721dd9dee6d083646a5f8e581a20b545be6c1feb405', 27);
checkSig('tpsl testnet', Signing::signL1Action($PRIV, $action, null, 0, null, false),
    '0x971c554d917c44e0e1b6cc45d8f9404f32172a9d3b3566262347d0302896a2e4',
    '0x206257b104788f80450f8e786c329daa589aa0b32ba96948201ae556d5637eac', 28);

echo "== sign_l1_action: scheduleCancel ==\n";
checkSig('schedCancel mainnet', Signing::signL1Action($PRIV, ['type' => 'scheduleCancel'], null, 0, null, true),
    '0x6cdfb286702f5917e76cd9b3b8bf678fcc49aec194c02a73e6d4f16891195df9',
    '0x6557ac307fa05d25b8d61f21fb8a938e703b3d9bf575f6717ba21ec61261b2a0', 27);

echo "\n";
echo $fail === 0 ? "ВСЕ ТЕСТЫ ПРОШЛИ ($pass)\n" : "ПРОВАЛЕНО: $fail, прошло: $pass\n";
exit($fail === 0 ? 0 : 1);
