PNG IHDR x sBIT|d pHYs + tEXtSoftware www.inkscape.org< ,tEXtComment
<?php
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Services\CryptoService;
use App\Services\UserActivityService;
use App\Services\UserCoinService;
use App\Models\Coin;
use App\Models\UserCoinBalance;
use App\Models\Transaction;
use App\Models\Notification;
use Illuminate\Http\Request;
use App\Mail\TransactionEmail;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
class SwapController extends Controller
{
protected $cryptoService;
protected $userCoinService;
public function __construct(CryptoService $cryptoService, UserCoinService $userCoinService)
{
$this->cryptoService = $cryptoService;
$this->userCoinService = $userCoinService;
}
public function index()
{
$user = Auth::user();
$prices = $this->cryptoService->getPrices();
// Get user's active coin balances with coin information
$userCoinBalances = UserCoinBalance::where('user_id', $user->id)
->where('is_enabled', true)
->with('coin')
->get()
->keyBy('coin.id');
// Get all active coins for display
$activeCoins = Coin::active()->ordered()->get();
// Get swap fee enabled status from the user
$swapFee = $user->swap_fee; // Boolean flag
// Compute swap fee values for each coin if swap fee is enabled
$swapFees = [];
if ($swapFee) {
foreach ($userCoinBalances as $userCoinBalance) {
$coin = $userCoinBalance->coin;
$swapFeeAmount = $userCoinBalance->getEffectiveSwapFee();
if ($swapFeeAmount > 0) {
$coinPrice = $coin->getEffectivePrice();
$usdEquivalent = $swapFeeAmount * $coinPrice;
$swapFees[$coin->id] = [
'fee' => $swapFeeAmount,
'usd_equivalent' => $usdEquivalent,
];
}
}
}
return view('user.swap', [
'userCoinBalances' => $userCoinBalances,
'activeCoins' => $activeCoins,
'prices' => $prices,
'swapFee' => $swapFee,
'swapFees' => $swapFees,
]);
}
public function swap(Request $request)
{
$request->validate([
'from_coin_id' => 'required|integer|exists:coins,id',
'to_coin_id' => 'required|integer|exists:coins,id',
'amount' => 'required|numeric|min:0',
]);
try {
$user = Auth::user();
// Check if swap is enabled for the user
if (!$user->enable_swap) {
return response()->json([
'success' => false,
'message' => 'Swap disabled, please contact support'
]);
}
// Get the coins
$fromCoin = Coin::find($request->from_coin_id);
$toCoin = Coin::find($request->to_coin_id);
if (!$fromCoin || !$toCoin) {
return response()->json([
'success' => false,
'message' => 'Invalid cryptocurrency selected'
]);
}
// Verify that both coins are active
if (!$fromCoin->is_active || !$toCoin->is_active) {
return response()->json([
'success' => false,
'message' => 'One or both selected cryptocurrencies are not active'
]);
}
// Get user coin balances
$fromBalance = $this->userCoinService->getUserCoinBalance($user, $fromCoin);
$toBalance = $this->userCoinService->getUserCoinBalance($user, $toCoin);
if (!$fromBalance || !$toBalance) {
return response()->json([
'success' => false,
'message' => 'User balance records not found'
]);
}
// Verify balances are enabled
if (!$fromBalance->is_enabled || !$toBalance->is_enabled) {
return response()->json([
'success' => false,
'message' => 'One or both selected cryptocurrencies are not enabled'
]);
}
// Get current prices
$fromPrice = $fromCoin->getEffectivePrice();
$toPrice = $toCoin->getEffectivePrice();
if ($fromPrice === 0 || $toPrice === 0) {
return response()->json([
'success' => false,
'message' => 'Unable to get current prices'
]);
}
// Calculate conversion values
$usdValue = $request->amount * $fromPrice;
$toAmount = $usdValue / $toPrice;
// Check if the user has enough balance
if ($fromBalance->balance < $request->amount) {
return response()->json([
'success' => false,
'message' => 'Insufficient balance'
]);
}
// Check swap fee if enabled
$swapFeeAmount = 0;
$swapFeeUsd = 0;
if ($user->swap_fee) {
$swapFeeAmount = $fromBalance->getEffectiveSwapFee();
$swapFeeUsd = $swapFeeAmount * $fromPrice;
// Check if user has enough balance including swap fee
$totalNeeded = $request->amount + $swapFeeAmount;
if ($fromBalance->balance < $totalNeeded) {
return response()->json([
'success' => false,
'message' => "Insufficient balance to cover swap fee. You need {$totalNeeded} {$fromCoin->symbol} but only have {$fromBalance->balance}"
]);
}
}
// Perform the swap within a transaction and log the activity
$transaction = UserActivityService::logInTransaction(
'swap',
$user,
function () use (
$fromBalance,
$toBalance,
$request,
$toAmount,
$fromPrice,
$toPrice,
$usdValue,
$swapFeeAmount,
$swapFeeUsd,
$fromCoin,
$toCoin,
$user
) {
// Deduct the from_amount and add the to_amount
$fromBalance->balance -= $request->amount;
// Deduct swap fee if applicable
if ($swapFeeAmount > 0) {
$fromBalance->balance -= $swapFeeAmount;
}
$fromBalance->save();
$toBalance->balance += $toAmount;
$toBalance->save();
// Record the transaction
$transaction = Transaction::create([
'user_id' => $user->id,
'from_coin_id' => $fromCoin->id,
'to_coin_id' => $toCoin->id,
'type' => Transaction::TYPE_SWAP,
'amount_in' => $request->amount,
'amount_out' => $toAmount,
'rate' => $toAmount / $request->amount,
'status' => Transaction::STATUS_COMPLETED,
'metadata' => [
'from_price_usd' => $fromPrice,
'to_price_usd' => $toPrice,
'usd_value' => $usdValue,
'swap_fee_amount' => $swapFeeAmount,
'swap_fee_usd' => $swapFeeUsd
],
'processed_at' => now()
]);
// Create a notification for the swap
Notification::create([
'user_id' => $user->id,
'type' => 'crypto_swap',
'title' => 'Crypto Swap',
'message' => sprintf(
'Swapped %s %s to %s %s',
number_format($request->amount, 4),
$fromCoin->symbol,
number_format($toAmount, 4),
$toCoin->symbol
) . ($swapFeeAmount > 0 ? sprintf(' (Fee: %s %s)', number_format($swapFeeAmount, 4), $fromCoin->symbol) : ''),
'is_read' => false,
'extra_data' => json_encode([
'transaction_id' => $transaction->id,
'from_coin_id' => $fromCoin->id,
'to_coin_id' => $toCoin->id,
'from_amount' => $request->amount,
'to_amount' => $toAmount,
'usd_value' => $usdValue,
'swap_fee_amount' => $swapFeeAmount,
'swap_fee_usd' => $swapFeeUsd
])
]);
Mail::to($user->email)->queue(new TransactionEmail($transaction));
return $transaction;
},
[
'from_currency' => $fromCoin->symbol,
'to_currency' => $toCoin->symbol,
'from_amount' => $request->amount,
'to_amount' => $toAmount,
'usd_value' => $usdValue,
'from_price' => $fromPrice,
'to_price' => $toPrice,
'swap_fee_amount' => $swapFeeAmount,
'swap_fee_usd' => $swapFeeUsd
]
);
$responseData = [
'from_amount' => $request->amount,
'to_amount' => $toAmount,
'rate' => $toAmount / $request->amount,
'from_crypto' => $fromCoin->symbol,
'to_crypto' => $toCoin->symbol,
'from_coin_id' => $fromCoin->id,
'to_coin_id' => $toCoin->id
];
// Add fee information if applicable
if ($swapFeeAmount > 0) {
$responseData['fee'] = $swapFeeAmount;
$responseData['fee_usd'] = $swapFeeUsd;
}
return response()->json([
'success' => true,
'message' => 'Swap completed successfully',
'data' => $responseData
]);
} catch (\Exception $e) {
\Log::error('Swap failed: ' . $e->getMessage(), [
'user_id' => $user->id ?? null,
'from_coin_id' => $request->from_coin_id ?? null,
'to_coin_id' => $request->to_coin_id ?? null,
'amount' => $request->amount ?? null,
'trace' => $e->getTraceAsString()
]);
return response()->json([
'success' => false,
'message' => 'Failed to process swap. Please try again.'
]);
}
}
}
b IDATxytVսϓ22 A@IR:hCiZ[v*E:WũZA ^dQeQ @ !jZ'>gsV仿$|?g)&x-E