orderBy('weigh', 'desc')->get(); foreach ($pairs as $p) { $match = CurrencyMatch::find($p->currency_match_id); if ($match) { $currency = Currency::find($match->currency_id); $p->close = $currency ? $currency->price : 0; $p->price_change = $currency ? ($currency->change ?? 0) : 0; $p->high = $currency ? ($currency->high ?? $p->close) : 0; $p->low = $currency ? ($currency->low ?? $p->close) : 0; $p->match_legal_id = $match->legal_id; $p->match_currency_id = $match->currency_id; $p->volume_24h = $currency ? ($currency->vol ?? 0) : 0; } } return $this->success($pairs); } public function placeOrder(Request $request) { $user_id = Token::getUserIdByToken(Token::getToken()); $user = \App\Users::find($user_id); if (!$user) return $this->error('Please login'); $pair_id = $request->input('pair_id'); $direction = $request->input('direction'); $amount = floatval($request->input('amount')); $delivery_time = $request->input('delivery_time'); if (!in_array($direction, ['up', 'down'])) return $this->error('Invalid direction'); if ($amount <= 0) return $this->error('Invalid amount'); if (!$delivery_time) return $this->error('Select delivery time'); $pair = OptionPair::where('id', $pair_id)->where('status', 1)->first(); if (!$pair) return $this->error('Pair not available'); if ($amount < $pair->min_amount) return $this->error('Min: ' . $pair->min_amount . ' USDC'); if ($amount > $pair->max_amount) return $this->error('Max: ' . $pair->max_amount . ' USDC'); $delivery_ts = is_numeric($delivery_time) ? date('Y-m-d H:i:s', $delivery_time) : $delivery_time; if (strtotime($delivery_ts) <= time() + 10) return $this->error('Delivery time must be in the future'); $match = CurrencyMatch::find($pair->currency_match_id); $currency = $match ? Currency::find($match->currency_id) : null; $open_price = $currency ? floatval($currency->price) : 0; $fee = sprintf("%.6f", $amount * $pair->fee_rate / 100); DB::beginTransaction(); try { $wallet = UsersWallet::where('user_id', $user->id)->where('currency', 3)->lockForUpdate()->first(); if (!$wallet || $wallet->legal_balance < $amount) { DB::rollBack(); return $this->error('Insufficient balance'); } $before = $wallet->legal_balance; $wallet->legal_balance = bc_sub($wallet->legal_balance, $amount, 6); $wallet->save(); AccountLog::insertLog( ['user_id' => $user->id, 'value' => -$amount, 'info' => 'Option ' . strtoupper($direction) . ' - ' . $pair->coinname, 'type' => AccountLog::MICRO_TRADE_SUBMIT, 'currency' => 3], ['balance_type' => 1, 'wallet_id' => $wallet->id, 'lock_type' => 0, 'before' => $before, 'change' => -$amount, 'after' => $wallet->legal_balance] ); OptionOrder::create([ 'user_id' => $user->id, 'pair_id' => $pair_id, 'symbol' => $pair->symbol, 'direction' => $direction, 'amount' => $amount, 'fee' => $fee, 'open_price' => $open_price, 'profit_rate' => $pair->profit_rate, 'delivery_time' => $delivery_ts, 'status' => 0, ]); DB::commit(); return $this->success('Order placed'); } catch (\Exception $e) { DB::rollBack(); return $this->error($e->getMessage()); } } public function myOrders(Request $request) { $user_id = Token::getUserIdByToken(Token::getToken()); $user = \App\Users::find($user_id); if (!$user) return $this->error('Please login'); $status = $request->input('status', 'all'); $query = OptionOrder::where('user_id', $user->id)->with('pair:id,coinname'); if ($status !== 'all') $query->where('status', $status); $list = $query->orderBy('id', 'desc')->paginate(20); $statusMap = ['0'=>'Pending','1'=>'Win','2'=>'Lose','3'=>'Canceled']; foreach ($list as $item) { $item->status_text = $statusMap[$item->status] ?? ''; $item->direction_text = $item->direction == 'up' ? 'Buy Up' : 'Buy Down'; $item->coinname = $item->pair ? $item->pair->coinname : $item->symbol; } return $this->success($list); } }