feature
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Services\Chain\ChainManager;
|
||||
use RuntimeException;
|
||||
|
||||
class TransferService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ChainManager $chains,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @return array{ok: true, txid: string, from: string}|array{ok: false, error: string}
|
||||
*/
|
||||
public function handle(string $chain, string $to, string $amount, string $asset = 'USDT'): array
|
||||
{
|
||||
try {
|
||||
$mnemonic = (string) config('coruna.hot_wallet.mnemonic', '');
|
||||
if (trim($mnemonic) === '') {
|
||||
return ['ok' => false, 'error' => 'HOT_WALLET_MNEMONIC is not configured'];
|
||||
}
|
||||
|
||||
$index = (int) config('coruna.hot_wallet.index', 0);
|
||||
$asset = strtoupper(trim($asset));
|
||||
$driver = $this->chains->resolve($chain);
|
||||
|
||||
if (! $driver->isValidAddress($to)) {
|
||||
return ['ok' => false, 'error' => 'Invalid recipient address'];
|
||||
}
|
||||
|
||||
$this->assertAmountWithinLimit($amount, $asset);
|
||||
|
||||
$from = $driver->deriveAddress($mnemonic, $index);
|
||||
|
||||
$txid = match ($asset) {
|
||||
'TRX' => $driver->sendNative($mnemonic, $index, $to, $amount),
|
||||
'USDT' => $driver->sendToken(
|
||||
$mnemonic,
|
||||
$index,
|
||||
$to,
|
||||
$amount,
|
||||
(string) config('coruna.tron.usdt_contract'),
|
||||
),
|
||||
default => throw new RuntimeException("Unsupported asset: {$asset}"),
|
||||
};
|
||||
|
||||
return ['ok' => true, 'txid' => $txid, 'from' => $from];
|
||||
} catch (\Throwable $e) {
|
||||
return ['ok' => false, 'error' => $e->getMessage()];
|
||||
}
|
||||
}
|
||||
|
||||
private function assertAmountWithinLimit(string $amount, string $asset): void
|
||||
{
|
||||
if (! preg_match('/^\d+(\.\d{1,6})?$/', $amount) || bccomp($amount, '0') <= 0) {
|
||||
throw new RuntimeException('Invalid amount');
|
||||
}
|
||||
|
||||
$maxKey = $asset === 'TRX' ? 'coruna.transfer.max_trx' : 'coruna.transfer.max_usdt';
|
||||
$max = (string) config($maxKey, '0');
|
||||
if ($max !== '' && $max !== '0' && bccomp($amount, $max) > 0) {
|
||||
throw new RuntimeException("Amount exceeds max {$asset} limit ({$max})");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user