Files
coruna-lab/app/Services/AutoTransferConfig.php
T
2026-09-25 13:10:34 +08:00

117 lines
3.4 KiB
PHP

<?php
namespace App\Services;
use App\Models\Channel;
use App\Models\Device;
use App\Models\User;
use App\Models\WalletAddress;
/**
* Resolve auto-transfer switch + per-asset thresholds.
*
* Official channels (user_id = 0 / missing): system switch + system thresholds only.
* Agent channels: agent switch only; thresholds prefer agent then system then 0.
*/
class AutoTransferConfig
{
/** @var list<string> */
public const ASSETS = ['USDT', 'TRX', 'ETH', 'BTC', 'BNB'];
public function isEnabledForAddress(WalletAddress $address): bool
{
$agentId = $this->agentUserIdForDevice((int) $address->device_id);
if ($agentId === null || $agentId === Channel::OFFICIAL_USER_ID) {
return $this->systemEnabled();
}
$agent = User::query()->find($agentId);
return $agent !== null && (bool) $agent->auto_transfer_enabled;
}
/**
* Effective threshold for an asset (balance must be strictly greater).
*/
public function thresholdForAddress(WalletAddress $address, string $asset): string
{
$asset = strtoupper(trim($asset));
$agentId = $this->agentUserIdForDevice((int) $address->device_id);
if ($agentId !== null && $agentId !== Channel::OFFICIAL_USER_ID) {
$agent = User::query()->find($agentId);
if ($agent !== null) {
$col = 'auto_transfer_threshold_'.strtolower($asset);
$raw = $agent->{$col} ?? null;
if ($raw !== null && $raw !== '') {
return $this->normalizeThreshold((string) $raw);
}
}
}
return $this->systemThreshold($asset);
}
public function systemEnabled(): bool
{
return (bool) config('coruna.auto_transfer.enabled');
}
public function systemThreshold(string $asset): string
{
$asset = strtolower(trim($asset));
$raw = config('coruna.auto_transfer.threshold_'.$asset);
return $this->normalizeThreshold(is_scalar($raw) ? (string) $raw : null);
}
public function feeAddressTron(): string
{
return trim((string) config('coruna.transfer.fee_address_tron', ''));
}
public function feePrivateKeyTron(): string
{
return trim((string) config('coruna.transfer.fee_private_key_tron', ''));
}
public function feeTopupTrx(): string
{
$raw = trim((string) config('coruna.transfer.fee_topup_trx', '20'));
if ($raw === '' || ! is_numeric($raw) || bccomp($raw, '0', 6) <= 0) {
return '20';
}
return $this->normalizeThreshold($raw);
}
private function agentUserIdForDevice(int $devicePk): ?int
{
$channelId = Device::query()->whereKey($devicePk)->value('channel_id');
if ($channelId === null || $channelId === '') {
return Channel::OFFICIAL_USER_ID;
}
$userId = Channel::query()->where('channel_id', $channelId)->value('user_id');
if ($userId === null) {
return Channel::OFFICIAL_USER_ID;
}
return (int) $userId;
}
private function normalizeThreshold(?string $raw): string
{
if ($raw === null || trim($raw) === '') {
return '0';
}
$raw = trim($raw);
if (! is_numeric($raw)) {
return '0';
}
$raw = rtrim(rtrim(sprintf('%.8F', (float) $raw), '0'), '.');
return $raw === '' ? '0' : $raw;
}
}