/** * Execute the console command. * * @return mixed */ public function handle() { $intervals = [300, 900, 1800, 7200, 14400, 86400]; $base = Wallet::where('base', true)->get(); $all = Wallet::all(); foreach ($base as $base_wallet) { foreach ($all as $market_wallet) { if ($market_wallet->id == $base_wallet->id) { continue; } foreach ($intervals as $interval) { OrdersTransaction::selectRaw(' FLOOR(MIN(unix_timestamp(`created_at`))/' . $interval . ')*' . $interval . ' AS date, SUM(amount) AS volume, SUBSTRING_INDEX(MIN(CONCAT(unix_timestamp(`created_at`), \'_\', price)), \'_\', -1) AS `open`, MAX(price) AS high, MIN(price) AS low, SUBSTRING_INDEX(MAX(CONCAT(unix_timestamp(`created_at`), \'_\', price)), \'_\', -1) AS `close` ')->where(function (\Illuminate\Database\Eloquent\Builder $query) use($base_wallet, $market_wallet) { $query->where('wallet_id', $base_wallet->id)->where('want_wallet_id', $market_wallet->id); })->where('created_at', '>=', DB::raw('DATE_SUB(NOW(), INTERVAL 24 HOUR)'))->groupBy(DB::raw('FLOOR(unix_timestamp(`created_at`)/' . $interval . ')'))->orderBy('created_at', 'asc')->chunk(100000, function ($orders) use($base_wallet, $market_wallet, $interval) { foreach ($orders as $key => $order) { try { $cache = OrdersChart::firstOrNew(['wallet_id' => $base_wallet->id, 'want_wallet_id' => $market_wallet->id, 'date' => $order->date, 'interval' => $interval]); $cache->date = $order->date; $cache->open = $order->open; $cache->high = $order->high; $cache->low = $order->low; $cache->close = $order->close; $cache->volume = $order->volume; $cache->wallet_id = $base_wallet->id; $cache->want_wallet_id = $market_wallet->id; $cache->interval = $interval; $cache->save(); } catch (\Exception $e) { } } }); } } } }
/** * Find orders to fullfill request. * * @param float $amount * @param float $price * @param Wallet $base_wallet * @param Wallet $want_wallet * @param WalletsAddress $user_base_wallet * @param string $request_order_type [s - sell, b - buy] */ public static function fullfillSuitable(&$amount, $price, Wallet $base_wallet, Wallet $want_wallet, WalletsAddress $user_base_wallet, $request_order_type) { $suitable_orders_found = true; if ($request_order_type == 's') { $price_finder = '>='; $type_finder = 'buy'; } else { $price_finder = '<='; $type_finder = 'sell'; } while ($suitable_orders_found) { $order = self::where('wallet_id', $base_wallet->id)->where('want_wallet_id', $want_wallet->id)->where('price', $price_finder, $price)->where('status', 'open')->where('type', $type_finder)->first(); if ($order && $amount > 0) { Log::debug('Fullfilling order #' . $order->id); if ($order->amount >= $amount) { $process_amount = $amount; } else { $process_amount = $order->amount; } $order->decrement('amount', $process_amount); Log::debug('Process amount: ' . $process_amount); $amount -= $process_amount; if ($order->amount <= 0) { $order->status = 'closed'; } $order->save(); $order_user_deposit = $order->type == 'sell' ? $process_amount * $price : $process_amount; $user_deposit = $order->type == 'sell' ? $process_amount : $process_amount * $price; if ($request_order_type == 's') { $user_wallet_id = $want_wallet->generateUserAddress($order->user()->first()); } else { $user_wallet_id = $base_wallet->generateUserAddress($order->user()->first()); } $order_user_wallet = WalletsAddress::where('id', $user_wallet_id)->first(); $transaction = new OrdersTransaction(); $transaction->user_id = $order->user_id; $transaction->order_id = $order->id; $transaction->amount = $process_amount; $transaction->price = $price; $transaction->wallet_id = $base_wallet->id; $transaction->want_wallet_id = $want_wallet->id; $transaction->fee = $user_base_wallet->user_id == $order->user_id ? 0 : config('exchange.trading.fee'); $transaction->type = $order->type; $transaction->save(); $order_user_fee = $user_base_wallet->user_id == $order->user_id ? 0 : self::calcFee($order_user_deposit); $result_deposit = sprintf('%.8f', $order_user_deposit - $order_user_fee); $order_user_wallet->deposit($result_deposit); Log::debug('[order] Deposit amount ' . $order_user_deposit . '(fee ' . $order_user_fee . ') (Result: ' . $result_deposit . '): w' . $order_user_wallet->wallet_id . 'u' . $order_user_wallet->user_id); self::depositFee($order_user_fee, $order_user_wallet->wallet_id); if ($request_order_type == 's') { $user_wallet_id = $base_wallet->generateUserAddress(Auth::user()); } else { $user_wallet_id = $want_wallet->generateUserAddress(Auth::user()); } $user_wallet = WalletsAddress::where('id', $user_wallet_id)->first(); $transaction = new OrdersTransaction(); $transaction->user_id = $user_wallet->user_id; $transaction->order_id = $order->id; $transaction->amount = $process_amount; $transaction->price = $price; $transaction->wallet_id = $base_wallet->id; $transaction->want_wallet_id = $want_wallet->id; $transaction->fee = config('exchange.trading.fee'); $transaction->type = $order->type == 'sell' ? 'buy' : 'sell'; $transaction->save(); $user_fee = self::calcFee($user_deposit); $user_wallet->deposit($user_deposit - $user_fee); Log::debug('[user] Deposit amount ' . $user_deposit . '(fee ' . $user_fee . '): w' . $user_wallet->wallet_id . 'u' . $user_wallet->user_id); self::depositFee($user_fee, $user_wallet->wallet_id); $withdrawal_amount = $order->type == 'sell' ? round($process_amount * $price, 8) : $process_amount; $user_base_wallet->withdrawal($withdrawal_amount); Log::debug('Withdrawal amount ' . $withdrawal_amount . ': w' . $user_base_wallet->wallet_id . 'u' . $user_base_wallet->user_id); Cache::tags('user' . $order->user_id)->forget('wallets'); Cache::tags('user' . $user_wallet->user_id)->forget('wallets'); } else { $suitable_orders_found = false; } } }
/** * Get latest ticker data. */ public static function getTickers() { $pairs = self::generatePairs(); $tickers = []; foreach ($pairs as $name => $pair) { $base = $pair['base_id']; $market = $pair['id']; $tickers[$name] = ['high' => 0, 'low' => 0, 'avg' => 0, 'vol' => 0, 'vol_curr' => 0, 'buy' => 0, 'sell' => 0, 'updated' => time()]; $last_sell = Order::select('price')->where(function (\Illuminate\Database\Eloquent\Builder $query) use($base, $market) { $query->where('wallet_id', $base)->where('want_wallet_id', $market); })->where('type', 'sell')->orderBy('created_at', 'desc')->first(); if ($last_sell) { $tickers[$name]['sell'] = (double) $last_sell->price; } $last_buy = Order::select('price')->where(function (\Illuminate\Database\Eloquent\Builder $query) use($base, $market) { $query->where('wallet_id', $base)->where('want_wallet_id', $market); })->where('type', 'buy')->orderBy('created_at', 'desc')->first(); if ($last_buy) { $tickers[$name]['buy'] = (double) $last_buy->price; } $last_chart_prices = OrdersChart::where('wallet_id', $base)->where('want_wallet_id', $market)->where('interval', 86400)->orderBy('date', 'desc')->first(); if ($last_chart_prices) { $tickers[$name]['high'] = (double) $last_chart_prices->high; $tickers[$name]['low'] = (double) $last_chart_prices->low; } $last_chart_volume = OrdersChart::where('wallet_id', $base)->where('want_wallet_id', $market)->where('interval', 86400)->orderBy('date', 'desc')->first(); if ($last_chart_volume) { $tickers[$name]['vol_curr'] = (double) $last_chart_volume->volume; } $base_volume = OrdersTransaction::selectRaw(' SUM(amount*price) AS volume ')->where(function (\Illuminate\Database\Eloquent\Builder $query) use($base, $market) { $query->where('wallet_id', $base)->where('want_wallet_id', $market); })->where('type', 'sell')->where('created_at', '>=', DB::raw('DATE_SUB(NOW(), INTERVAL 24 HOUR)'))->first(); if ($base_volume) { $tickers[$name]['vol'] = (double) $base_volume->volume; } } return $tickers; }
public function getHistory() { $coins_list = function () { $data = ['' => 'All']; foreach (Cache::remember('coin_list', Config::get('cache.ttl'), function () { return Wallet::select('short as coin')->get(); }) as $wallet) { $data[$wallet->coin] = $wallet->coin; } return $data; }; $provider = new EloquentDataProvider(OrdersTransaction::selectRaw('0 as total, orders_transactions.fee as fee, orders_transactions.id as id, orders_transactions.order_id as order_id, orders_transactions.amount, orders_transactions.price, orders_transactions.created_at, orders_transactions.updated_at, orders_transactions.type, w1.short as coin1, w2.short as coin2')->where('user_id', Auth::user()->id)->leftJoin('wallets as w1', 'w1.id', '=', 'orders_transactions.wallet_id')->leftJoin('wallets as w2', 'w2.id', '=', 'orders_transactions.want_wallet_id')); Services::resourceManager()->ignoreCss(['bootstrap']); Services::resourceManager()->ignoreJs(['bootstrap']); $grid = new Grid($provider, [(new Column('orders_transactions.id', 'ID'))->setValueFormatter(function ($value, OrdersTransaction $row = null) { if (!empty($row->id)) { return $row->id; } else { return $value; } }), (new Column('orders_transactions.order_id', 'Order ID'))->setValueFormatter(function ($value, OrdersTransaction $row = null) { if (!empty($row->order_id)) { return $row->order_id; } else { return $value; } }), (new Column('coin1'))->setValueFormatter(function ($value, OrdersTransaction $row = null) { if (!empty($row)) { return $row->coin2 . '/' . $row->coin1; } else { return $value; } }), (new Column('type'))->setValueFormatter(function ($value, OrdersTransaction $row = null) { if (!empty($row)) { if ($value == 'buy') { return HTML::tag('span', $value, ['class' => 'label label-success']); } else { return HTML::tag('span', $value, ['class' => 'label label-danger']); } } else { return $value; } }), (new Column('amount'))->setValueFormatter(function ($value, OrdersTransaction $row = null) { if (!empty($row)) { return HTML::tag('span', sprintf('%.8f %s', $row->amount, $row->coin2)); } else { return $value; } }), (new Column('price'))->setValueFormatter(function ($value, OrdersTransaction $row = null) { if (!empty($row)) { return HTML::tag('span', sprintf('%.8f %s', $row->price, $row->coin1)); } else { return $value; } }), (new Column('fee'))->setValueFormatter(function ($value, OrdersTransaction $row = null) { if (!empty($row)) { if ($row->type == 'sell') { return HTML::tag('span', sprintf('%.8f %s (%.2f%%)', Order::calcFee($row->amount, $row->fee), $row->coin1, $row->fee)); } else { return HTML::tag('span', sprintf('%.8f %s (%.2f%%)', Order::calcFee($row->amount * $row->price, $row->fee), $row->coin2, $row->fee)); } } else { return $value; } }), (new Column('total'))->setValueFormatter(function ($value, OrdersTransaction $row = null) { if (!empty($row)) { if ($row->type == 'buy') { return HTML::tag('span', sprintf('%.8f %s', $row->amount - Order::calcFee($row->amount, $row->fee), $row->coin2)); } else { return HTML::tag('span', sprintf('%.8f %s', $row->amount * $row->price - Order::calcFee($row->amount * $row->price, $row->fee), $row->coin1)); } } else { return $value; } }), (new Column('orders_transactions.created_at', 'Created At'))->setValueFormatter(function ($value, OrdersTransaction $row = null) { if (!empty($row->created_at)) { return $row->created_at; } else { return $value; } }), new Column('updated_at'), (new FilterControl('wallets.short', FilterOperation::OPERATOR_EQ, new InputOption('coin', ['coin' => Input::get('coin')])))->setView(new TemplateView('select', ['options' => $coins_list(), 'label' => 'Coin', 'inputAttributes' => ['style' => 'width: 50px;']])), new PageSizeSelectControl(new InputOption('ps', ['ps' => Input::get('ps')], 10), [10, 50, 100, 500, 1000]), new CsvExport(new InputOption('csv', ['csv' => Input::get('csv')])), new ResetButton(), new PageTotalsRow(['amount' => PageTotalsRow::OPERATION_SUM]), new PaginationControl(new InputOption('page', ['page' => Input::get('page')], 1), 10, $provider), new ColumnSortingControl('orders_transactions.id', new InputOption('sort', ['sort' => Input::get('sort')], 'orders_transactions.id-dir-desc')), new ColumnSortingControl('amount', new InputOption('sort', ['sort' => Input::get('sort')])), new ColumnSortingControl('orders_transactions.created_at', new InputOption('sort', ['sort' => Input::get('sort')]))]); $customization = new BootstrapStyling(); $customization->apply($grid); $grid = $grid->render(); return view('user.orders.history', compact('grid')); }