Example #1
0
 public static function executeOrder($buy, $price, $amount, $currency1, $fee, $market_price, $edit_id = 0, $this_user_id = 0, $external_transaction = false, $stop_price = false, $use_maker_fee = false, $verbose = false)
 {
     global $CFG;
     if (!$CFG->session_active) {
         return false;
     }
     if ($CFG->trading_status == 'suspended') {
         db_commit();
         return array('error' => array('message' => Lang::string('buy-trading-disabled'), 'code' => 'TRADING_SUSPENDED'));
     }
     $this_user_id = preg_replace("/[^0-9]/", "", $this_user_id);
     $this_user_id = $this_user_id > 0 ? $this_user_id : User::$info['id'];
     if (!($this_user_id > 0)) {
         db_commit();
         return array('error' => array('message' => 'Invalid authentication.', 'code' => 'AUTH_ERROR'));
     }
     $amount = preg_replace("/[^0-9\\.]/", "", $amount);
     $orig_amount = $amount;
     $price = preg_replace("/[^0-9\\.]/", "", $price);
     $stop_price = preg_replace("/[^0-9\\.]/", "", $stop_price);
     $currency1 = strtolower(preg_replace("/[^a-zA-Z]/", "", $currency1));
     $edit_id = preg_replace("/[^0-9]/", "", $edit_id);
     db_start_transaction();
     $orig_order = false;
     if ($edit_id > 0) {
         if (empty($CFG->session_api) || $external_transaction) {
             $orig_order = DB::getRecord('orders', $edit_id, 0, 1, false, false, false, 1);
         } else {
             $orig_order = self::getRecord(false, $edit_id, $this_user_id, true);
         }
         if ($orig_order['site_user'] != $this_user_id || !$orig_order) {
             db_commit();
             return array('error' => array('message' => 'Order not found.', 'code' => 'ORDER_NOT_FOUND'));
         }
         $buy = $orig_order['order_type'] == $CFG->order_type_bid;
         $currency_info = $CFG->currencies[$orig_order['currency']];
         $currency1 = strtolower($currency_info['currency']);
         $edit_id = $orig_order['id'];
         $use_maker_fee = $use_maker_fee && $orig_order['market_price'] != 'Y';
         if ($external_transaction) {
             $amount = $orig_order['btc'];
             $orig_amount = $amount;
         }
     } else {
         $currency_info = $CFG->currencies[strtoupper($currency1)];
     }
     $bid_ask = self::getBidAsk($currency1);
     $bid = $bid_ask['bid'];
     $ask = $bid_ask['ask'];
     $bid = $bid > $ask ? $ask : $bid;
     $price = $market_price ? $buy ? $ask : $bid : $price;
     $usd_info = $CFG->currencies['USD'];
     $user_balances = User::getBalances($this_user_id, array($currency_info['id'], $CFG->btc_currency_id), true);
     $user_fee = FeeSchedule::getUserFees($this_user_id);
     $on_hold = User::getOnHold(1, $this_user_id, $user_fee, array($currency_info['id'], $CFG->btc_currency_id));
     $this_btc_balance = !empty($user_balances['btc']) ? $user_balances['btc'] : 0;
     $this_fiat_balance = !empty($user_balances[$currency1]) ? $user_balances[$currency1] : 0;
     $this_triggered_stop = $stop_price > 0 && $market_price;
     $stop_price = $stop_price > 0 && $market_price ? false : $stop_price;
     $fee = !$use_maker_fee ? $user_fee['fee'] : $user_fee['fee1'];
     $insert_id = 0;
     $transactions = 0;
     $new_order = 0;
     $edit_order = 0;
     $comp_btc_balance = array();
     $comp_btc_on_hold = array();
     $comp_fiat_balance = array();
     $comp_fiat_on_hold = array();
     $currency_max = false;
     $currency_max_str = false;
     $currency_min = false;
     $currency_min_str = false;
     $compatible = false;
     $trans_total = 0;
     $this_funds_finished = false;
     $hidden_executions = array();
     $max_price = 0;
     $min_price = 0;
     $executed_orders = array();
     $executed_prices = array();
     $executed_orig_prices = false;
     $no_compatible = false;
     $triggered_rows = false;
     if (!empty($on_hold['BTC']['total'])) {
         $this_btc_on_hold = $edit_id > 0 && !$buy ? $on_hold['BTC']['total'] - $amount : $on_hold['BTC']['total'];
     } else {
         $this_btc_on_hold = 0;
     }
     if (!empty($on_hold[strtoupper($currency1)]['total'])) {
         $this_fiat_on_hold = $edit_id > 0 && $buy ? $on_hold[strtoupper($currency1)]['total'] - ($amount * $orig_order['btc_price'] + $amount * $orig_order['btc_price'] * ($fee * 0.01)) : $on_hold[strtoupper($currency1)]['total'];
     } else {
         $this_fiat_on_hold = 0;
     }
     $error = self::checkPreconditions($buy, $currency_info, $amount, $price, $stop_price, $fee, $buy ? $this_fiat_balance - $this_fiat_on_hold : $this_btc_balance - $this_btc_on_hold, $bid, $ask, $market_price, $this_user_id, $orig_order);
     if ($error) {
         db_commit();
         return $error;
     }
     if (!$market_price) {
         $error = self::checkUserOrders($buy, $currency_info, $this_user_id, $price, $stop_price, $fee);
         if ($error) {
             db_commit();
             return $error;
         }
     }
     if (!($edit_id > 0)) {
         $order_log_id = db_insert('order_log', array('date' => date('Y-m-d H:i:s'), 'order_type' => $buy ? $CFG->order_type_bid : $CFG->order_type_ask, 'site_user' => $this_user_id, 'btc' => $amount, 'fiat' => $amount * $price, 'currency' => $currency_info['id'], 'btc_price' => $price, 'market_price' => $market_price ? 'Y' : 'N', 'stop_price' => $stop_price, 'status' => 'ACTIVE'));
     } else {
         if (!$external_transaction || $this_triggered_stop) {
             $order_log_id = db_insert('order_log', array('date' => date('Y-m-d H:i:s'), 'order_type' => $buy ? $CFG->order_type_bid : $CFG->order_type_ask, 'site_user' => $this_user_id, 'btc' => $amount, 'fiat' => $amount * $price, 'currency' => $currency_info['id'], 'btc_price' => $price, 'market_price' => $market_price ? 'Y' : 'N', 'p_id' => $orig_order['log_id'], 'stop_price' => $stop_price, 'status' => 'ACTIVE'));
             db_update('order_log', $orig_order['log_id'], array('status' => 'REPLACED', 'btc_remaining' => $orig_order['btc']));
         } else {
             $order_log_id = $orig_order['log_id'];
         }
     }
     if ($buy) {
         if ($price != $stop_price) {
             $compatible = self::getCompatible($CFG->order_type_ask, $price, $currency1, $amount, 1, $market_price, false, $use_maker_fee, $this_user_id);
             $no_compatible = !$compatible;
             $compatible = is_array($compatible) ? new ArrayIterator($compatible) : false;
             $compatible[] = array('continue' => 1);
             //$btc_commision = 0;
             $fiat_commision = false;
             $c = count($compatible);
             $i = 1;
         }
         if ($compatible) {
             foreach ($compatible as $comp_order) {
                 if (!empty($comp_order['is_market']) && $comp_order['is_market'] == 'Y' && $price < $bid) {
                     $hidden_executions[] = $comp_order;
                     continue;
                 }
                 if (!empty($comp_order['real_market_price']) && round($comp_order['real_market_price'], 2, PHP_ROUND_HALF_UP) <= $price && round($comp_order['fiat_price'], 2, PHP_ROUND_HALF_UP) > $price && !$market_price) {
                     $hidden_executions[] = $comp_order;
                     continue;
                 }
                 if (!empty($comp_order['order_type']) && $comp_order['order_type'] == $CFG->order_type_bid) {
                     if ($comp_order['is_market'] == 'Y') {
                         $hidden_executions[] = $comp_order;
                     }
                     continue;
                 }
                 if (!($amount > 0) || !($this_fiat_balance - $this_fiat_on_hold > 0)) {
                     $triggered = self::triggerStops($max_price, $min_price, $currency1, 1, $bid, $ask, $currency_max, $currency_min);
                     $triggered_rows = self::getMarketOrders();
                     if ($triggered_rows) {
                         $hidden_executions = array_merge($triggered_rows, $hidden_executions);
                     }
                     break;
                 } elseif ($i == $c && $max_price > 0) {
                     $triggered = self::triggerStops($max_price, $min_price, $currency1, 1, $bid, $ask, $currency_max, $currency_min);
                     if ($triggered > 0) {
                         $triggered_rows = self::getCompatible($CFG->order_type_ask, $max_price, $currency1, $amount, 1, $market_price, $executed_orders, false, false, true);
                         if ($triggered_rows) {
                             foreach ($triggered_rows as $triggered_row) {
                                 $compatible->append($triggered_row);
                             }
                         }
                     }
                 }
                 if (!empty($comp_order['continue']) || $comp_order['site_user'] == $this_user_id) {
                     $i++;
                     continue;
                 }
                 $comp_user_info = self::lockOrder($comp_order['site_user'], $comp_order['id'], $comp_order['currency_id']);
                 if (!$comp_user_info) {
                     continue;
                 }
                 $comp_order = array_merge($comp_order, $comp_user_info);
                 $comp_order['btc_balance'] = array_key_exists($comp_order['site_user'], $comp_btc_balance) ? $comp_btc_balance[$comp_order['site_user']] : $comp_order['btc_balance'];
                 $comp_order['fiat_balance'] = array_key_exists($comp_order['site_user'], $comp_fiat_balance) ? $comp_fiat_balance[$comp_order['site_user']] : $comp_order['fiat_balance'];
                 $comp_btc_on_hold[$comp_order['site_user']] = array_key_exists($comp_order['site_user'], $comp_btc_on_hold) ? $comp_btc_on_hold[$comp_order['site_user']] : $comp_order['btc_on_hold'];
                 $max_amount = ($this_fiat_balance - $this_fiat_on_hold) / $comp_order['fiat_price'] > $amount + $fee * 0.01 * $amount ? $amount : ($this_fiat_balance - $this_fiat_on_hold) / $comp_order['fiat_price'] - $fee * 0.01 * (($this_fiat_balance - $this_fiat_on_hold) / $comp_order['fiat_price']);
                 $max_comp_amount = $comp_order['btc_balance'] - ($comp_btc_on_hold[$comp_order['site_user']] - $comp_order['btc_outstanding']) > $comp_order['btc_outstanding'] ? $comp_order['btc_outstanding'] : $comp_order['btc_balance'] - ($comp_btc_on_hold[$comp_order['site_user']] - $comp_order['btc_outstanding']);
                 $this_funds_finished = $max_amount < $amount;
                 $comp_funds_finished = $max_comp_amount < $comp_order['btc_outstanding'];
                 if (!($max_amount > 0) || !($max_comp_amount > 0)) {
                     if ($comp_funds_finished) {
                         self::cancelOrder($comp_order['id'], 0, $comp_order['site_user']);
                     }
                     $i++;
                     continue;
                 }
                 if ($max_comp_amount >= $max_amount) {
                     $trans_amount = $max_amount;
                     $comp_order_outstanding = $comp_order['btc_outstanding'] - $max_amount;
                     $amount = $amount - $max_amount;
                 } else {
                     $trans_amount = $max_comp_amount;
                     $amount = $amount - $trans_amount;
                     $comp_order_outstanding = $comp_order['btc_outstanding'] - $max_comp_amount;
                 }
                 $this_fee = $fee * 0.01 * $trans_amount;
                 $comp_order_fee = $comp_order['fee1'] * 0.01 * $trans_amount;
                 $this_conversion_fee = $currency_info['id'] != $comp_order['currency_id'] ? $comp_order['fiat_price'] * $trans_amount - $comp_order['orig_btc_price'] * $comp_order['orig_conversion_factor'] * $trans_amount : 0;
                 $this_trans_amount_net = $trans_amount + $this_fee;
                 $comp_order_trans_amount_net = $trans_amount - $comp_order_fee;
                 $comp_btc_balance[$comp_order['site_user']] = $comp_order['btc_balance'] - $trans_amount;
                 $comp_fiat_balance[$comp_order['site_user']] = round($comp_order['fiat_balance'] + $comp_order['orig_btc_price'] * $comp_order_trans_amount_net, 2, PHP_ROUND_HALF_UP);
                 $comp_btc_on_hold[$comp_order['site_user']] = $comp_btc_on_hold[$comp_order['site_user']] - $trans_amount;
                 //$btc_commision += $this_fee;
                 if (!empty($fiat_commision[strtolower($currency_info['currency'])])) {
                     $fiat_commision[strtolower($currency_info['currency'])] += $this_fee * $comp_order['fiat_price'];
                 } else {
                     $fiat_commision[strtolower($currency_info['currency'])] = $this_fee * $comp_order['fiat_price'];
                 }
                 if (!empty($fiat_commision[strtolower($comp_order['currency_abbr'])])) {
                     $fiat_commision[strtolower($comp_order['currency_abbr'])] += $comp_order_fee * $comp_order['orig_btc_price'];
                 } else {
                     $fiat_commision[strtolower($comp_order['currency_abbr'])] = $comp_order_fee * $comp_order['orig_btc_price'];
                 }
                 $this_prev_btc = $this_btc_balance;
                 $this_prev_fiat = $this_fiat_balance;
                 $this_btc_balance += $trans_amount;
                 $this_fiat_balance -= round($this_trans_amount_net * $comp_order['fiat_price'], 2, PHP_ROUND_HALF_UP);
                 $trans_total += $trans_amount;
                 $max_price = $comp_order['fiat_price'] > $max_price ? $comp_order['fiat_price'] : $max_price;
                 $min_price = $comp_order['fiat_price'] < $min_price || !($min_price > 0) ? $comp_order['fiat_price'] : $min_price;
                 if ($currency_info['id'] != $comp_order['currency_id']) {
                     $currency_max[$comp_order['currency_id']] = $comp_order['orig_btc_price'] > $currency_max[$comp_order['currency_id']] ? $comp_order['orig_btc_price'] : $currency_max[$comp_order['currency_id']];
                     $currency_min[$comp_order['currency_id']] = $comp_order['orig_btc_price'] < $currency_min[$comp_order['currency_id']] || !($currency_min[$comp_order['currency_id']] > 0) ? $comp_order['orig_btc_price'] : $currency_min[$comp_order['currency_id']];
                 }
                 $trans_info = array('date' => date('Y-m-d H:i:s'), 'site_user' => $this_user_id, 'transaction_type' => $CFG->transactions_buy_id, 'site_user1' => $comp_order['site_user'], 'transaction_type1' => $CFG->transactions_sell_id, 'btc' => $trans_amount, 'btc_price' => $comp_order['fiat_price'], 'fiat' => $comp_order['fiat_price'] * $trans_amount, 'currency' => $currency_info['id'], 'currency1' => $comp_order['currency_id'], 'fee' => $this_fee, 'fee1' => $comp_order_fee, 'btc_net' => $this_trans_amount_net, 'btc_net1' => $comp_order_trans_amount_net, 'btc_before' => $this_prev_btc, 'btc_after' => $this_btc_balance, 'fiat_before' => $this_prev_fiat, 'fiat_after' => $this_fiat_balance, 'btc_before1' => $comp_order['btc_balance'], 'btc_after1' => $comp_btc_balance[$comp_order['site_user']], 'fiat_before1' => $comp_order['fiat_balance'], 'fiat_after1' => $comp_fiat_balance[$comp_order['site_user']], 'log_id' => $order_log_id, 'log_id1' => $comp_order['log_id'], 'fee_level' => $fee, 'fee_level1' => $comp_order['fee'], 'conversion_fee' => $this_conversion_fee, 'orig_btc_price' => $comp_order['orig_btc_price'], 'bid_at_transaction' => $bid, 'ask_at_transaction' => $ask);
                 if ($currency_info['id'] != $comp_order['currency_id']) {
                     $trans_info = array_merge($trans_info, array('conversion' => 'Y', 'convert_amount' => $comp_order['fiat_price'] * $trans_amount, 'convert_rate_given' => $comp_order['conversion_factor'], 'convert_system_rate' => $comp_order['orig_conversion_factor'], 'convert_from_currency' => $currency_info['id'], 'convert_to_currency' => $comp_order['currency_id']));
                 }
                 $transaction_id = db_insert('transactions', $trans_info);
                 $executed_orders[] = $comp_order['id'];
                 $executed_prices[] = array('price' => $comp_order['fiat_price'], 'amount' => $trans_amount);
                 $executed_orig_prices[$comp_order['id']] = array('price' => $comp_order['orig_btc_price'], 'amount' => $trans_amount);
                 ++$transactions;
                 if (round($comp_order_outstanding, 8, PHP_ROUND_HALF_UP) > 0) {
                     if (!$comp_funds_finished) {
                         db_update('orders', $comp_order['id'], array('btc_price' => $comp_order['orig_btc_price'], 'btc' => $comp_order_outstanding, 'fiat' => $comp_order['orig_btc_price'] * $comp_order_outstanding));
                         if ($comp_order['is_market'] == 'Y') {
                             $hidden_executions[] = $comp_order;
                         }
                     } else {
                         self::cancelOrder($comp_order['id'], $comp_order_outstanding, $comp_order['site_user']);
                     }
                 } else {
                     self::setStatus($comp_order['id'], 'FILLED');
                     db_delete('orders', $comp_order['id']);
                 }
                 User::updateBalances($comp_order['site_user'], array('btc' => $comp_btc_balance[$comp_order['site_user']], $comp_order['currency_abbr'] => $comp_fiat_balance[$comp_order['site_user']]));
                 $i++;
             }
         }
         if ($trans_total > 0) {
             User::updateBalances($this_user_id, array('btc' => $this_btc_balance, $currency1 => $this_fiat_balance));
             if ($fiat_commision) {
                 Status::updateEscrows($fiat_commision);
             }
             //db_update('status',1,array('btc_escrow'=>($status['btc_escrow']+$btc_commision),strtolower($currency_info['currency']).'_escrow'=>($status[strtolower($currency_info['currency']).'_escrow']+$fiat_commision)));
         }
         if (round($amount, 8, PHP_ROUND_HALF_UP) > 0) {
             if ($edit_id > 0) {
                 if (!$this_funds_finished) {
                     if (!($no_compatible && $external_transaction)) {
                         db_update('orders', $edit_id, array('btc' => $amount, 'fiat' => $amount * $price, 'currency' => $currency_info['id'], 'btc_price' => $price != $stop_price ? $price : 0, 'market_price' => $market_price ? 'Y' : 'N', 'log_id' => $order_log_id, 'stop_price' => $stop_price));
                         $edit_order = 1;
                     }
                     $order_status = 'ACTIVE';
                 } else {
                     self::cancelOrder($edit_id, $amount, $this_user_id);
                     $order_status = 'OUT_OF_FUNDS';
                 }
             } else {
                 if (!$this_funds_finished) {
                     db_insert('orders', array('date' => date('Y-m-d H:i:s'), 'order_type' => $CFG->order_type_bid, 'site_user' => $this_user_id, 'btc' => $amount, 'fiat' => $amount * $price, 'currency' => $currency_info['id'], 'btc_price' => $price != $stop_price ? $market_price && $max_price > 0 ? $max_price : $price : 0, 'market_price' => $market_price ? 'Y' : 'N', 'log_id' => $order_log_id, 'stop_price' => $stop_price));
                     $new_order = $stop_price != $price && $stop_price > 0 ? 2 : 1;
                     $order_status = 'ACTIVE';
                 } else {
                     self::cancelOrder(false, $amount, $this_user_id);
                     $order_status = 'OUT_OF_FUNDS';
                 }
             }
         } elseif ($edit_id > 0) {
             self::setStatus($edit_id, 'FILLED');
             db_delete('orders', $edit_id);
             $order_status = 'FILLED';
         } else {
             self::setStatus(false, 'FILLED', $order_log_id);
             $order_status = 'FILLED';
         }
         db_insert('history', array('date' => date('Y-m-d H:i:s'), 'ip' => !empty($CFG->client_ip) ? $CFG->client_ip : '', 'history_action' => $CFG->history_buy_id, 'site_user' => $this_user_id, 'order_id' => $order_log_id));
     } else {
         if ($price != $stop_price) {
             $compatible = self::getCompatible($CFG->order_type_bid, $price, $currency1, $amount, 1, $market_price, false, $use_maker_fee, $this_user_id);
             $no_compatible = !$compatible;
             $compatible = is_array($compatible) ? new ArrayIterator($compatible) : false;
             $compatible[] = array('continue' => 1);
             //$btc_commision = 0;
             $fiat_commision = false;
             $c = count($compatible);
             $i = 1;
         }
         if ($compatible) {
             foreach ($compatible as $comp_order) {
                 if (!empty($comp_order['is_market']) && $comp_order['is_market'] == 'Y' && $price > $ask) {
                     $hidden_executions[] = $comp_order;
                     continue;
                 }
                 if (!empty($comp_order['real_market_price']) && round($comp_order['real_market_price'], 2, PHP_ROUND_HALF_UP) >= $price && round($comp_order['fiat_price'], 2, PHP_ROUND_HALF_UP) < $price && !$market_price) {
                     $hidden_executions[] = $comp_order;
                     continue;
                 }
                 if (!empty($comp_order['order_type']) && $comp_order['order_type'] == $CFG->order_type_ask) {
                     if ($comp_order['is_market'] == 'Y') {
                         $hidden_executions[] = $comp_order;
                     }
                     continue;
                 }
                 if (!($amount > 0) || !($this_btc_balance - $this_btc_on_hold > 0)) {
                     $triggered = self::triggerStops($max_price, $min_price, $currency1, false, $bid, $ask, $currency_max, $currency_min);
                     $triggered_rows = self::getMarketOrders();
                     if ($triggered_rows) {
                         $hidden_executions = array_merge($triggered_rows, $hidden_executions);
                     }
                     break;
                 } elseif ($i == $c && $min_price > 0) {
                     $triggered = self::triggerStops($max_price, $min_price, $currency1, false, $bid, $ask, $currency_max, $currency_min);
                     if ($triggered > 0) {
                         $triggered_rows = self::getCompatible($CFG->order_type_bid, $min_price, $currency1, $amount, 1, $market_price, $executed_orders, false, false, true);
                         if ($triggered_rows) {
                             foreach ($triggered_rows as $triggered_row) {
                                 $compatible->append($triggered_row);
                             }
                         }
                     }
                 }
                 if (!empty($comp_order['continue']) || $comp_order['site_user'] == $this_user_id) {
                     $i++;
                     continue;
                 }
                 $comp_user_info = self::lockOrder($comp_order['site_user'], $comp_order['id'], $comp_order['currency_id']);
                 if (!$comp_user_info) {
                     continue;
                 }
                 $comp_order = array_merge($comp_order, $comp_user_info);
                 $comp_order['btc_balance'] = array_key_exists($comp_order['site_user'], $comp_btc_balance) ? $comp_btc_balance[$comp_order['site_user']] : $comp_order['btc_balance'];
                 $comp_order['fiat_balance'] = array_key_exists($comp_order['site_user'], $comp_fiat_balance) ? $comp_fiat_balance[$comp_order['site_user']] : $comp_order['fiat_balance'];
                 $comp_fiat_on_hold[$comp_order['site_user']] = array_key_exists($comp_order['site_user'], $comp_fiat_on_hold) ? $comp_fiat_on_hold[$comp_order['site_user']] : round($comp_order['fiat_on_hold'], 2, PHP_ROUND_HALF_UP);
                 $comp_fiat_this_on_hold = $comp_fiat_on_hold[$comp_order['site_user']] - ($comp_order['btc_outstanding'] * $comp_order['orig_btc_price'] + $comp_order['fee1'] * 0.01 * ($comp_order['btc_outstanding'] * $comp_order['orig_btc_price']));
                 $max_amount = $this_btc_balance - $this_btc_on_hold > $amount ? $amount : $this_btc_balance - $this_btc_on_hold;
                 $max_comp_amount = ($comp_order['fiat_balance'] - $comp_fiat_this_on_hold) / $comp_order['orig_btc_price'] > $comp_order['btc_outstanding'] + $comp_order['fee1'] * 0.01 * $comp_order['btc_outstanding'] ? $comp_order['btc_outstanding'] : ($comp_order['fiat_balance'] - $comp_fiat_this_on_hold) / $comp_order['orig_btc_price'] - $comp_order['fee1'] * 0.01 * (($comp_order['fiat_balance'] - $comp_fiat_this_on_hold) / $comp_order['orig_btc_price']);
                 $this_funds_finished = $max_amount < $amount;
                 $comp_funds_finished = $max_comp_amount < $comp_order['btc_outstanding'];
                 if (!($max_amount > 0) || !($max_comp_amount > 0)) {
                     if ($comp_funds_finished) {
                         self::cancelOrder($comp_order['id'], 0, $comp_order['site_user']);
                     }
                     $i++;
                     continue;
                 }
                 if ($max_comp_amount >= $max_amount) {
                     $trans_amount = $max_amount;
                     $comp_order_outstanding = $comp_order['btc_outstanding'] - $amount;
                     $amount = $amount - $max_amount;
                 } else {
                     $trans_amount = $max_comp_amount;
                     $amount = $amount - $trans_amount;
                     $comp_order_outstanding = $comp_order['btc_outstanding'] - $max_comp_amount;
                 }
                 $this_fee = $fee * 0.01 * $trans_amount;
                 $comp_order_fee = $comp_order['fee1'] * 0.01 * $trans_amount;
                 $this_trans_amount_net = $trans_amount - $this_fee;
                 $this_conversion_fee = $currency_info['id'] != $comp_order['currency_id'] ? $comp_order['orig_btc_price'] * $comp_order['orig_conversion_factor'] * $trans_amount - $comp_order['fiat_price'] * $trans_amount : 0;
                 $comp_order_trans_amount_net = $trans_amount + $comp_order_fee;
                 $comp_btc_balance[$comp_order['site_user']] = $comp_order['btc_balance'] + $trans_amount;
                 $comp_fiat_balance[$comp_order['site_user']] = $comp_order['fiat_balance'] - round($comp_order['orig_btc_price'] * $comp_order_trans_amount_net, 2, PHP_ROUND_HALF_UP);
                 $comp_fiat_on_hold[$comp_order['site_user']] = $comp_fiat_on_hold[$comp_order['site_user']] - round($comp_order['orig_btc_price'] * $comp_order_trans_amount_net, 2, PHP_ROUND_HALF_UP);
                 //$btc_commision += $comp_order_fee;
                 if (!empty($fiat_commision[strtolower($currency_info['currency'])])) {
                     $fiat_commision[strtolower($currency_info['currency'])] += $this_fee * $comp_order['fiat_price'];
                 } else {
                     $fiat_commision[strtolower($currency_info['currency'])] = $this_fee * $comp_order['fiat_price'];
                 }
                 if (!empty($fiat_commision[strtolower($comp_order['currency_abbr'])])) {
                     $fiat_commision[strtolower($comp_order['currency_abbr'])] += $comp_order_fee * $comp_order['orig_btc_price'];
                 } else {
                     $fiat_commision[strtolower($comp_order['currency_abbr'])] = $comp_order_fee * $comp_order['orig_btc_price'];
                 }
                 $this_prev_btc = $this_btc_balance;
                 $this_prev_fiat = $this_fiat_balance;
                 $this_btc_balance -= $trans_amount;
                 $this_fiat_balance += round($this_trans_amount_net * $comp_order['fiat_price'], 2, PHP_ROUND_HALF_UP);
                 $trans_total += $trans_amount;
                 $max_price = $comp_order['fiat_price'] > $max_price ? $comp_order['fiat_price'] : $max_price;
                 $min_price = $comp_order['fiat_price'] < $min_price || !($min_price > 0) ? $comp_order['fiat_price'] : $min_price;
                 if ($currency_info['id'] != $comp_order['currency_id']) {
                     $currency_max[$comp_order['currency_id']] = $comp_order['orig_btc_price'] > $currency_max[$comp_order['currency_id']] ? $comp_order['orig_btc_price'] : $currency_max[$comp_order['currency_id']];
                     $currency_min[$comp_order['currency_id']] = $comp_order['orig_btc_price'] < $currency_min[$comp_order['currency_id']] || !($currency_min[$comp_order['currency_id']] > 0) ? $comp_order['orig_btc_price'] : $currency_min[$comp_order['currency_id']];
                 }
                 $trans_info = array('date' => date('Y-m-d H:i:s'), 'site_user' => $this_user_id, 'transaction_type' => $CFG->transactions_sell_id, 'site_user1' => $comp_order['site_user'], 'transaction_type1' => $CFG->transactions_buy_id, 'btc' => $trans_amount, 'btc_price' => $comp_order['fiat_price'], 'fiat' => $comp_order['fiat_price'] * $trans_amount, 'currency' => $currency_info['id'], 'currency1' => $comp_order['currency_id'], 'fee' => $this_fee, 'fee1' => $comp_order_fee, 'btc_net' => $this_trans_amount_net, 'btc_net1' => $comp_order_trans_amount_net, 'btc_before' => $this_prev_btc, 'btc_after' => $this_btc_balance, 'fiat_before' => $this_prev_fiat, 'fiat_after' => $this_fiat_balance, 'btc_before1' => $comp_order['btc_balance'], 'btc_after1' => $comp_btc_balance[$comp_order['site_user']], 'fiat_before1' => $comp_order['fiat_balance'], 'fiat_after1' => $comp_fiat_balance[$comp_order['site_user']], 'log_id' => $order_log_id, 'log_id1' => $comp_order['log_id'], 'fee_level' => $fee, 'fee_level1' => $comp_order['fee'], 'conversion_fee' => $this_conversion_fee, 'orig_btc_price' => $comp_order['orig_btc_price'], 'bid_at_transaction' => $bid, 'ask_at_transaction' => $ask);
                 if ($currency_info['id'] != $comp_order['currency_id']) {
                     $trans_info = array_merge($trans_info, array('conversion' => 'Y', 'convert_amount' => $comp_order['orig_btc_price'] * $trans_amount, 'convert_rate_given' => $comp_order['conversion_factor'], 'convert_system_rate' => $comp_order['orig_conversion_factor'], 'convert_from_currency' => $comp_order['currency_id'], 'convert_to_currency' => $currency_info['id']));
                 }
                 $transaction_id = db_insert('transactions', $trans_info);
                 $executed_orders[] = $comp_order['id'];
                 $executed_prices[] = array('price' => $comp_order['fiat_price'], 'amount' => $trans_amount);
                 $executed_orig_prices[$comp_order['id']] = array('price' => $comp_order['orig_btc_price'], 'amount' => $trans_amount);
                 ++$transactions;
                 if ($currency_info['id'] != $comp_order['currency_id']) {
                     db_update('transactions', $transaction_id, array('conversion' => 'Y', 'convert_amount' => $comp_order['orig_btc_price'] * $trans_amount, 'convert_rate_given' => $comp_order['conversion_factor'], 'convert_system_rate' => $comp_order['orig_conversion_factor'], 'convert_from_currency' => $comp_order['currency_id'], 'convert_to_currency' => $currency_info['id']));
                 }
                 if (round($comp_order_outstanding, 8, PHP_ROUND_HALF_UP) > 0) {
                     if (!$comp_funds_finished) {
                         db_update('orders', $comp_order['id'], array('btc_price' => $comp_order['orig_btc_price'], 'btc' => $comp_order_outstanding, 'fiat' => $comp_order['orig_btc_price'] * $comp_order_outstanding));
                         if ($comp_order['is_market'] == 'Y') {
                             $hidden_executions[] = $comp_order;
                         }
                     } else {
                         self::cancelOrder($comp_order['id'], $comp_order_outstanding, $comp_order['site_user']);
                     }
                 } else {
                     self::setStatus($comp_order['id'], 'FILLED');
                     db_delete('orders', $comp_order['id']);
                 }
                 User::updateBalances($comp_order['site_user'], array('btc' => $comp_btc_balance[$comp_order['site_user']], $comp_order['currency_abbr'] => $comp_fiat_balance[$comp_order['site_user']]));
                 $i++;
             }
         }
         if ($trans_total > 0) {
             User::updateBalances($this_user_id, array('btc' => $this_btc_balance, $currency1 => $this_fiat_balance));
             if ($fiat_commision) {
                 Status::updateEscrows($fiat_commision);
             }
         }
         if (round($amount, 8, PHP_ROUND_HALF_UP) > 0) {
             if ($edit_id > 0) {
                 if (!$this_funds_finished) {
                     if (!($no_compatible && $external_transaction)) {
                         db_update('orders', $edit_id, array('btc' => $amount, 'fiat' => $amount * $price, 'btc_price' => $price != $stop_price ? $price : 0, 'market_price' => $market_price ? 'Y' : 'N', 'log_id' => $order_log_id, 'stop_price' => $stop_price));
                         $edit_order = 1;
                     }
                     $order_status = 'ACTIVE';
                 } else {
                     self::cancelOrder($edit_id, $amount, $this_user_id);
                     $order_status = 'OUT_OF_FUNDS';
                 }
             } else {
                 if (!$this_funds_finished) {
                     $insert_id = db_insert('orders', array('date' => date('Y-m-d H:i:s'), 'order_type' => $CFG->order_type_ask, 'site_user' => $this_user_id, 'btc' => $amount, 'fiat' => $amount * $price, 'currency' => $currency_info['id'], 'btc_price' => $price != $stop_price ? $market_price && $min_price > 0 ? $min_price : $price : 0, 'market_price' => $market_price ? 'Y' : 'N', 'log_id' => $order_log_id, 'stop_price' => $stop_price));
                     $new_order = $stop_price != $price && $stop_price > 0 ? 2 : 1;
                     $order_status = 'ACTIVE';
                 } else {
                     self::cancelOrder(false, $amount, $this_user_id);
                     $order_status = 'OUT_OF_FUNDS';
                 }
             }
         } elseif ($edit_id > 0) {
             self::setStatus($edit_id, 'FILLED');
             db_delete('orders', $edit_id);
             $order_status = 'FILLED';
         } else {
             self::setStatus(false, 'FILLED', $order_log_id);
             $order_status = 'FILLED';
         }
         db_insert('history', array('date' => date('Y-m-d H:i:s'), 'ip' => !empty($CFG->client_ip) ? $CFG->client_ip : '', 'history_action' => $CFG->history_sell_id, 'site_user' => $this_user_id, 'order_id' => $order_log_id));
     }
     db_commit();
     if ($max_price > 0 && $currency1 == 'usd') {
         db_update('currencies', $CFG->btc_currency_id, array('usd_ask' => $max_price));
     }
     if ($min_price > 0 && $currency1 == 'usd') {
         db_update('currencies', $CFG->btc_currency_id, array('usd_bid' => $min_price));
     }
     if ($hidden_executions && !$external_transaction) {
         foreach ($hidden_executions as $comp_order) {
             if ($triggered_rows && $comp_order['is_market'] != 'Y') {
                 continue;
             }
             $return = self::executeOrder($comp_order['order_type'] == $CFG->order_type_bid, $comp_order['orig_btc_price'], $comp_order['btc_outstanding'], strtolower($comp_order['currency_abbr']), false, $comp_order['is_market'] == 'Y', $comp_order['id'], $comp_order['site_user'], true, $comp_order['stop_price'], true, true);
             if (!empty($return['order_info']['comp_orig_prices'][$edit_id ? $edit_id : $insert_id])) {
                 $executed_prices[] = $return['order_info']['comp_orig_prices'][$edit_id ? $edit_id : $insert_id];
                 ++$transactions;
             }
         }
         if ($verbose) {
             $reevaluated_order = DB::getRecord('orders', $edit_id ? $edit_id : $insert_id, 0, 1);
             if (!$reevaluated_order) {
                 $order_status = 'FILLED';
             } else {
                 $amount = $reevaluated_order['btc'];
             }
         }
     }
     $order_info = false;
     if ($verbose) {
         if ($executed_prices) {
             foreach ($executed_prices as $exec) {
                 $exec_amount[] = $exec['amount'];
             }
             $exec_amount_sum = array_sum($exec_amount);
             foreach ($executed_prices as $exec) {
                 $avg_exec[] = $exec['amount'] / $exec_amount_sum * $exec['price'];
             }
         }
         $order_info = array('id' => $order_log_id, 'side' => $buy ? 'buy' : 'sell', 'type' => $market_price ? 'market' : ($stop_price > 0 ? 'stop' : 'limit'), 'amount' => $orig_amount, 'amount_remaining' => $amount, 'price' => round($price, 8, PHP_ROUND_HALF_UP), 'avg_price_executed' => count($executed_prices) > 0 ? round(array_sum($avg_exec), 2, PHP_ROUND_HALF_UP) : 0, 'stop_price' => $stop_price, 'currency' => strtoupper($currency1), 'status' => $order_status, 'replaced' => $edit_id ? $orig_order['log_id'] : 0, 'comp_orig_prices' => $executed_orig_prices);
     }
     return array('transactions' => $transactions, 'new_order' => $new_order, 'edit_order' => $edit_order, 'executed' => $executed_orders, 'order_info' => $order_info);
 }