*/ 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; } }