<file_sep>#!/usr/bin/php
<?php
include 'common.php';
echo date('Y-m-d H:i:s').' Beginning Crypto Deposits processing...'.PHP_EOL;
ini_set('display_errors',1);

$CFG->session_active = true;
$transactions_dir = $CFG->dirroot.'transactions/';

$transactions = scandir($transactions_dir);
$transactions = (!$transactions) ? array() : $transactions;

$wallets = Wallets::get();
if (!$wallets) {
	echo 'Error: no wallets to process.'.PHP_EOL;
	exit;
}

$sql = "SELECT id, transaction_id FROM bitcoind_log WHERE date >= '".date('Y-m-d H:i:s',strtotime('-2 day'))."' ORDER BY id DESC ";
$result = db_query_array($sql);
if ($result) {
	foreach ($result as $row) {
		$transaction_log[$row['transaction_id']] = $row['id'];
	}
}

foreach ($wallets as $wallet) {
	$c_currency_info = $CFG->currencies[$wallet['c_currency']];
	$is_bitcoin = ($c_currency_info['currency'] != 'ETH');
	$is_ether = ($c_currency_info['currency'] == 'ETH');
	
	$total_received = 0;
	$block_num = false;
	
	if ($is_bitcoin) {
		$bitcoin = new Bitcoin($wallet['bitcoin_username'],$wallet['bitcoin_passphrase'],'localhost',$wallet['bitcoin_port'],$wallet['bitcoin_protocol']);
		if ($c_currency_info['currency'] == 'DASH')
			$bitcoin->settxfee((float)$wallet['bitcoin_sending_fee']);
		else
			$bitcoin->settxfee(($wallet['bitcoin_sending_fee'] / 226) * 1000);
	}
	else if ($is_ether) {
		$ethereum = new Ethereum($wallet['bitcoin_username'],$wallet['bitcoin_passphrase'],'localhost',$wallet['bitcoin_port'],$wallet['etherscan_api_key']);
		$block_num = $ethereum->getBlockNum();
		$address_list = $ethereum->getAddressesWithBalance();
		$transactions = array();
		
		foreach ($address_list as $address) {
			$trans_received = $ethereum->getTransactionsFromEtherscan($block_num,$address);
			if ($trans_received)
				$transactions = array_merge($transactions,$trans_received);
		}
	}
	
	$email = SiteEmail::getRecord('new-deposit');
	$sql = "SELECT transaction_id, id FROM requests WHERE request_status != {$CFG->request_completed_id} AND currency = {$wallet['c_currency']} AND request_type = {$CFG->request_deposit_id} ";
	$result = db_query_array($sql);
	if ($result) {
		foreach ($result as $row) {
			$requests[$row['transaction_id']] = $row['id'];
		}
	}
	
	$addresses = array();
	$addresses_received = array();
	$hot_wallet_addresses = array();
	$user_balances = array();
	
	foreach ($transactions as $t_id) {
		if (!$t_id || $t_id == '.' || $t_id == '..' || $t_id == '.gitignore')
			continue;
		
		if ($is_bitcoin) {
			$transaction = $bitcoin->gettransaction($t_id);
			
			if (!empty($transaction_log[$t_id])) {
				unlink($transactions_dir.$t_id);
				continue;
			}
			if (empty($transaction['details']))
				continue;
		}
		else if ($is_ether) {
			$transaction = $t_id;
			$transaction['details'] = array($t_id);
			
			if (!empty($transaction_log[$t_id['txid']]))
				continue;
		}
		
		$send = false;
		$pending = false;
		$hot_wallet_in = 0;
		
		foreach ($transaction['details'] as $detail) {
			if ($is_bitcoin) {
				if ($detail['category'] == 'send') {
					$send = true;
					continue;
				}
			}
			
			$addr_in = ($is_bitcoin) ? $detail['address'] : $detail['to'];
			if (empty($addresses[$addr_in])) {
				$addr_info = BitcoinAddresses::getAddress($addr_in,$wallet['c_currency']);
				if (!$addr_info)
					continue;
				
				$addresses[$addr_in] = $addr_info;
				$addresses_received[$addr_in] = 0;
			}
			
			$user_id = $addresses[$addr_in]['site_user'];
			$request_id = (!empty($requests[$transaction['txid']])) ? $requests[$transaction['txid']] : false;
			$fee = ($detail['amount'] * $CFG->crypto_deposit_fee * 0.01) + $CFG->crypto_deposit_fee_unit;
			$net_amount = max($detail['amount'] - $fee,0);
			
			/*
			$limits = User::checkLimits(true,$net_amount,$c_currency_info['id']);
			
			if (!$limits || $limits['d_remaining'] < 0)
				Errors::add(str_replace('[limit]',$limits['d_limit'],Lang::string('daily-dp-limit')));
			else if ($limits['m_remaining'] < 0)
				Errors::add(str_replace('[limit]',$limits['m_limit'],Lang::string('monthly-dp-limit'))); 
			 */
			 
			// check for hot wallet recharge
			if ($addresses[$addr_in]['hot_wallet'] == 'Y') {
				if ($transaction['confirmations'] > 0) {
					$hot_wallet_in = $detail['amount'];
					
					if (empty($hot_wallet_addresses[$addr_in]))
						$hot_wallet_addresses[$addr_in] = 0;
					
					$hot_wallet_addresses[$addr_in] += $detail['amount'];
					unset($addresses_received[$addr_in]);
				}
				
				continue;
			}
			elseif ($addresses[$addr_in]['system_address'] == 'Y') {
				if ($is_bitcoin)
					unlink($transactions_dir.$t_id);
				else if ($is_ether) {
					BitcoinAddresses::updateAddressBalance($addresses[$addr_in]['id'],$detail['amount'],true);
					db_insert('bitcoind_log',array('transaction_id'=>$transaction['txid'],'amount'=>$detail['amount'],'date'=>date('Y-m-d H:i:s')));	
				}
				
				unset($addresses_received[$addr_in]);
				continue;
			}
			
			// get user balance... no need to lock
			if (empty($user_balances[$user_id])) {
				$bal_info = User::getBalance($user_id,$wallet['c_currency']);
				$user_balances[$user_id] = $bal_info['balance'];
			}
			
			// if not confirmed enough
			if (($addresses[$addr_in]['trusted'] == 'Y' && $transaction['confirmations'] < 1) || ($addresses[$addr_in]['trusted'] != 'Y' && $transaction['confirmations'] < $wallet['confirmations'])) {
				if (!($request_id > 0)) {
					$rid = db_insert('requests',array('date'=>date('Y-m-d H:i:s'),'site_user'=>$user_id,'currency'=>$wallet['c_currency'],'amount'=>$detail['amount'],'net_amount'=>$net_amount,'fee'=>$fee,'description'=>$CFG->deposit_bitcoin_desc,'request_status'=>$CFG->request_pending_id,'request_type'=>$CFG->request_deposit_id,'transaction_id'=>$transaction['txid'],'send_address'=>$addr_in));
					db_insert('history',array('date'=>date('Y-m-d H:i:s'),'history_action'=>$CFG->history_deposit_id,'site_user'=>$user_id,'request_id'=>$rid,'balance_before'=>$user_balances[$user_id],'balance_after'=>($user_balances[$user_id] + $net_amount),'bitcoin_address'=>$addr_in));
				}
				
				echo $CFG->currencies[$wallet['c_currency']]['currency'].' transaction pending.'.PHP_EOL;
				$pending = true;
			}
			else {
				// if confirmation sufficient
				if (!($request_id > 0)) {
					$updated = db_insert('requests',array('date'=>date('Y-m-d H:i:s'),'site_user'=>$user_id,'currency'=>$wallet['c_currency'],'amount'=>$detail['amount'],'net_amount'=>$net_amount,'fee'=>$fee,'description'=>$CFG->deposit_bitcoin_desc,'request_status'=>$CFG->request_completed_id,'request_type'=>$CFG->request_deposit_id,'transaction_id'=>$transaction['txid'],'send_address'=>$addr_in));
					db_insert('history',array('date'=>date('Y-m-d H:i:s'),'history_action'=>$CFG->history_deposit_id,'site_user'=>$user_id,'request_id'=>$updated,'balance_before'=>$user_balances[$user_id],'balance_after'=>($user_balances[$user_id] + $net_amount),'bitcoin_address'=>$addr_in));
				}
				else
					$updated = db_update('requests',$request_id,array('request_status'=>$CFG->request_completed_id));
				
				if ($updated > 0) {
					User::updateBalances($user_id,array($wallet['c_currency']=>$net_amount),true);
					Status::updateEscrows(array($wallet['c_currency']=>$fee));
					db_insert('bitcoind_log',array('transaction_id'=>$transaction['txid'],'amount'=>$detail['amount'],'date'=>date('Y-m-d H:i:s')));
					
					$total_received += $detail['amount'];
					$addresses_received[$addr_in] += $detail['amount'];
					$user_balances[$user_id] = $user_balances[$user_id] + $net_amount;
					$info = $addresses[$addr_in];
					
					if ($is_bitcoin) {
						$unlink = unlink($transactions_dir.$t_id);
						if (!$unlink && file_exists($unlink)) {
							$unlink = unlink($transactions_dir.$t_id);
						}
					}
					else if ($is_ether)
						$unlink = true;
					
					if ($info['notify_deposit_btc'] == 'Y') {
					    $info['amount'] = $detail['amount'];
					    $info['currency'] = $CFG->currencies[$wallet['c_currency']]['currency'];
					    $info['id'] = (!empty($request_id)) ? $request_id : $updated;
					    $CFG->language = ($info['last_lang']) ? $info['last_lang'] : 'en';
					    Email::send($CFG->form_email,$info['email'],str_replace('[amount]',$detail['amount'],str_replace('[currency]',$info['currency'],$email['title'])),$CFG->form_email_from,false,$email['content'],$info);
					}
					
					if (!$unlink)
						echo 'Error: Could not delete transaction file.'.PHP_EOL;
					else
						echo $CFG->currencies[$wallet['c_currency']]['currency'].' transaction credited successfully.'.PHP_EOL;
				}
			}
		}
		
		if ($send && !$pending && !($hot_wallet_in > 0) && $is_bitcoin)
			unlink($transactions_dir.$t_id);
		elseif (!$send && ($hot_wallet_in > 0)) {
			$updated = Wallets::sumFields($wallet['id'],array('hot_wallet_btc'=>$hot_wallet_in,'warm_wallet_btc'=>(-1 * ($hot_wallet_in + $wallet['bitcoin_sending_fee'])),'total_btc'=>(-1 * $wallet['bitcoin_sending_fee'])));
			echo 'Hot wallet received '.$hot_wallet_in.' '.$CFG->currencies[$wallet['c_currency']]['currency'].PHP_EOL;
			if ($updated) {
				if ($is_bitcoin) {
					$unlink = unlink($transactions_dir.$t_id);
					if (!$unlink && file_exists($unlink)) {
						$unlink = unlink($transactions_dir.$t_id);
					}
				}
				
				db_insert('bitcoind_log',array('transaction_id'=>$transaction['txid'],'amount'=>$hot_wallet_in,'date'=>date('Y-m-d H:i:s')));
				db_update('wallets',$wallet['id'],array('hot_wallet_notified'=>'N'));
			}
		}
	}
	
	$warm_wallet = $wallet['bitcoin_warm_wallet_address'];
	$reserve = Wallets::getReserveSurplus($wallet['id']);
	$reserve_surplus = round($reserve['surplus'],8,PHP_ROUND_HALF_UP) + $total_received;
	echo 'Reserve surplus: '.sprintf("%.8f", $reserve_surplus).' '.$CFG->currencies[$wallet['c_currency']]['currency'].PHP_EOL;
	
	if ($total_received > 0) {
		echo 'Total '.$CFG->currencies[$wallet['c_currency']]['currency'].' received: '.$total_received.PHP_EOL;
		$update = Wallets::sumFields($wallet['id'],array('hot_wallet_btc'=>$total_received,'total_btc'=>$total_received));
	}
	
	if ($is_bitcoin) {
		if ($warm_wallet && $reserve_surplus > $CFG->bitcoin_reserve_min) {
			$bitcoin->walletpassphrase($wallet['bitcoin_passphrase'],3);
			$response = $bitcoin->sendtoaddress($warm_wallet,floatval($reserve_surplus));
			$transferred = 0;
			echo $bitcoin->error;
			
			if ($response && !$bitcoin->error) {
				$transferred = $reserve_surplus;
				$transfer_fees = 0;
				$transaction = $bitcoin->gettransaction($response);
				
				foreach ($transaction['details'] as $detail) {
					if ($detail['category'] == 'send') {
						$detail['fee'] = round(abs($detail['fee']),8,PHP_ROUND_HALF_UP);
						if ($detail['fee'] > 0) {
							$transfer_fees += $detail['fee'];
							db_insert('fees',array('fee'=>$detail['fee'],'date'=>date('Y-m-d H:i:s'),'c_currency'=>$wallet['c_currency']));
						}
					}
				}
				
				Wallets::sumFields($wallet['id'],array('hot_wallet_btc'=>(0 - $transferred - $transfer_fees),'warm_wallet_btc'=>$transferred - $transfer_fees,'total_btc'=>(0 - $transfer_fees)));
				echo 'Transferred '.$reserve_surplus.' '.$CFG->currencies[$wallet['c_currency']]['currency'].' to warm wallet.'.PHP_EOL;
			}
		}
	}
	else if ($is_ether) {
		$hot_wallets = BitcoinAddresses::getHotWallets($wallet['c_currency']);
		$system_addresses = BitcoinAddresses::getSystemAddresses($wallet['c_currency']);
		$system_wallet = ($system_addresses) ? $system_addresses[0] : false;
		$gas_price = $wallet['bitcoin_sending_fee'];
		$send_to_hot = array();
		$send_to_warm = array();
		
		if (count($addresses_received) > 0) foreach ($addresses_received as $addr_in => $amount) {
			if ($reserve_surplus > 0 && $warm_wallet) {
				$send_to_warm[] = array('amount'=>min($amount,$reserve_surplus),'from'=>$addr_in,'to'=>$warm_wallet,'fee'=>$gas_price);
				$orig_amount = $amount;
				$amount -= $reserve_surplus;
				$reserve_surplus -= $orig_amount;
			}
			
			if ($amount > 0 && $system_wallet) {
				$send_to_hot[] = array('amount'=>$amount,'from'=>$addr_in,'to'=>$system_wallet['address'],'fee'=>$gas_price);
			}
		}
		
		if (count($hot_wallet_addresses) > 0 && $reserve_surplus > 0 && $warm_wallet) foreach ($hot_wallet_addresses as $addr_in => $amount) {
			if ($reserve_surplus <= 0)
				break;
			
			$send_to_warm[] = array('amount'=>min($amount,$reserve_surplus),'from'=>$addr_in,'to'=>$warm_wallet,'fee'=>$gas_price);
			$reserve_surplus -= $amount;
		}
		
		if (count($hot_wallets) > 0 && $reserve_surplus > 0 && $warm_wallet) foreach ($hot_wallets as $address) {
			if ($reserve_surplus <= 0 || $address['balance'] <= 0)
				break;
			
			$send_to_warm[] = array('amount'=>min($address['balance'],$reserve_surplus),'from'=>$address['address'],'to'=>$warm_wallet,'fee'=>$gas_price);
			$reserve_surplus -= $address['balance'];
		}

		if (count($send_to_hot) > 0 || count($send_to_warm)) {
			$sent_to_hot = $ethereum->sendTransactions($send_to_hot,$wallet['gas_limit']);
			$sent_to_warm = $ethereum->sendTransactions($send_to_warm,$wallet['gas_limit']);
			
			if ($sent_to_hot['transactions']) foreach ($sent_to_hot['transactions'] as $detail) {
				if (empty($detail['txid']))
					continue;
				
				$transfer_fees += $detail['fee'];
				db_insert('fees',array('fee'=>$detail['fee'],'date'=>date('Y-m-d H:i:s'),'c_currency'=>$wallet['c_currency']));
			}
			
			if ($sent_to_warm['transactions']) foreach ($sent_to_warm['transactions'] as $detail) {
				if (empty($detail['txid']))
					continue;
				
				$transfer_fees += $detail['fee'];
				db_insert('fees',array('fee'=>$detail['fee'],'date'=>date('Y-m-d H:i:s'),'c_currency'=>$wallet['c_currency']));
			}
			
			foreach ($hot_wallets as $address) {
				$balance = $ethereum->getBalance($address['address']);
				if ($balance)
					BitcoinAddresses::updateAddressBalance($address['id'],$balance);
			}
			
			if (!empty($sent_to_warm['sent']) && $sent_to_warm['sent'] > 0) {
				Wallets::sumFields($wallet['id'],array('hot_wallet_btc'=>(0 - $sent_to_warm['sent'] - $transfer_fees),'warm_wallet_btc'=>$sent_to_warm['sent'] - $transfer_fees,'total_btc'=>(0 - $transfer_fees)));
				echo 'Transferred '.$sent_to_warm['sent'].' '.$CFG->currencies[$wallet['c_currency']]['currency'].' to warm wallet.'.PHP_EOL;
			}
		}
	}
}

db_update('status',1,array('cron_receive_bitcoin'=>date('Y-m-d H:i:s')));

echo 'done'.PHP_EOL;
<file_sep>#!/usr/bin/php
<?php
include 'common.php';
echo date('Y-m-d H:i:s').' Beginning Maintenance processing...'.PHP_EOL;

$CFG->session_active = 1;
$CFG->in_cron = 1;

$main = Currencies::getMain();
$cryptos = Currencies::getCryptos();
$wallets = Wallets::get();
$btc_24h_main = 0;
$reserve_ratio = ($CFG->bitcoin_reserve_ratio) ? $CFG->bitcoin_reserve_ratio : '0';

// get 24 hour BTC volume
$now = 'DATE_ADD(NOW(), INTERVAL '.((($CFG->timezone_offset)/60)/60).' HOUR)';
$sql = "SELECT transactions.c_currency, IFNULL(SUM(btc),0) AS btc_24h, IFNULL(SUM(IF(transaction_type != {$CFG->transactions_buy_id},btc,0)),0) AS btc_24h_s, IFNULL(SUM(IF(transaction_type = {$CFG->transactions_buy_id},btc,0)),0) AS btc_24h_b, IFNULL(SUM(IF(`date` >= DATE_SUB($now, INTERVAL 1 HOUR),btc,0)),0) AS btc_1h, IFNULL(SUM(IF(transaction_type != {$CFG->transactions_buy_id} AND `date` >= DATE_SUB($now, INTERVAL 1 HOUR),btc,0)),0) AS btc_1h_s, IFNULL(SUM(IF(transaction_type = {$CFG->transactions_buy_id} AND `date` >= DATE_SUB($now, INTERVAL 1 HOUR),btc,0)),0) AS btc_1h_b FROM transactions WHERE `date` >= DATE_SUB($now, INTERVAL 1 DAY) GROUP BY transactions.c_currency ORDER BY NULL";
$result = db_query_array($sql);
$processed = array();
if ($result) {
	foreach ($result as $currency) {
		$processed[] = $currency['c_currency'];
		
		$btc_24h[$currency['c_currency']] = $currency['btc_24h'];
		$btc_24h_s[$currency['c_currency']] = $currency['btc_24h_s'];
		$btc_24h_b[$currency['c_currency']] = $currency['btc_24h_b'];
		$btc_1h[$currency['c_currency']] = $currency['btc_1h'];
		$btc_1h_s[$currency['c_currency']] = $currency['btc_1h_s'];
		$btc_1h_b[$currency['c_currency']] = $currency['btc_1h_b'];
		$btc_24h_main += ($currency['c_currency'] != $main['crypto']) ? round(($CFG->currencies[$currency['c_currency']]['usd_ask'] / $CFG->currencies[$main['crypto']]['usd_ask']) * $currency['btc_24h'],8,PHP_ROUND_HALF_UP) : $currency['btc_24h'];
		
		db_update('wallets',$wallets[$CFG->currencies[$currency['c_currency']]['currency']]['id'],array('btc_24h'=>$currency['btc_24h'],'btc_24h_s'=>$currency['btc_24h_s'],'btc_24h_b'=>$currency['btc_24h_b'],'btc_1h'=>$currency['btc_1h'],'btc_1h_s'=>$currency['btc_1h_s'],'btc_1h_b'=>$currency['btc_1h_b']));
	}
}

foreach ($CFG->currencies as $currency_id => $currency) {
	if (!is_numeric($currency_id) || $currency['is_crypto'] != 'Y' || in_array($currency_id,$processed))
		continue;
	
	$btc_24h[$currency_id] = '0';
	$btc_24h_s[$currency_id] = '0';
	$btc_24h_b[$currency_id] = '0';
	$btc_1h[$currency_id] = '0';
	$btc_1h_s[$currency_id] = '0';
	$btc_1h_b[$currency_id] = '0';
	
	db_update('wallets',$wallets[$CFG->currencies[$currency_id]['currency']]['id'],array('btc_24h'=>0,'btc_24h_s'=>0,'btc_24h_b'=>0,'btc_1h'=>0,'btc_1h_s'=>0,'btc_1h_b'=>0));
}


// determine users' monthly volume
/*
$sql = 'SELECT id, global_btc, from_usd, to_usd FROM fee_schedule ORDER BY global_btc ASC, from_usd ASC';
$result = db_query_array($sql);
if ($result && count($result) > 1) {
	$sql = 'SELECT ROUND(SUM(IF(transactions.id IS NOT NULL,transactions.btc * transactions.btc_price * currencies.usd_ask,transactions1.btc * transactions1.btc_price * currencies1.usd_ask)),2) AS volume, site_users.id AS user_id
			FROM site_users
			LEFT JOIN transactions ON (transactions.site_user = site_users.id AND transactions.date >= DATE_SUB(CURDATE(),INTERVAL 1 MONTH))
			LEFT JOIN transactions transactions1 ON (transactions1.site_user1 = site_users.id AND transactions1.date >= DATE_SUB(CURDATE(),INTERVAL 1 MONTH))
			LEFT JOIN currencies ON (currencies.id = transactions.currency)
			LEFT JOIN currencies currencies1 ON (currencies1.id = transactions1.currency)
			WHERE transactions.id IS NOT NULL OR transactions1.id IS NOT NULL
			GROUP BY site_users.id';
	$volumes = db_query_array($sql);
	
	$global_fc_id = false;
	$fee_schedule = false;
	if ($volumes) {
		foreach ($volumes as $volume) {
			foreach ($result as $row) {
				$global_fc_id = ($row['global_btc'] <= $btc_24h_main && $row['global_btc'] > 0) ? $row['id'] : $global_fc_id;
				$fee_schedule = ($row['from_usd'] <= ($volume['volume'] / $CFG->currencies[$main['fiat']]['usd_ask'])) ? $row['id'] : $fee_schedule;
			}
			
			$fee_schedule = ($fee_schedule >= $global_fc_id) ? $fee_schedule : $global_fc_id;
			$sql = 'UPDATE site_users SET site_users.fee_schedule = '.$fee_schedule.' WHERE site_users.id = '.$volume['user_id'];
			db_query($sql);
		}
	}
}
*/
// expire settings change request
$sql = 'DELETE FROM change_settings WHERE `date` <= ("'.date('Y-m-d H:i:s').'" - INTERVAL 1 DAY)';
$result = db_query($sql);

// expire unautharized requests
$sql = 'UPDATE requests SET request_status = '.$CFG->request_cancelled_id.' WHERE request_status = '.$CFG->request_awaiting_id.' AND `date` <= (NOW() - INTERVAL 1 DAY)';
$result = db_query($sql);

// 30 day token don't ask
//$sql = 'UPDATE site_users SET dont_ask_30_days = "N" WHERE dont_ask_date <= (NOW() - INTERVAL 1 MONTH) AND dont_ask_30_days = "Y" ';
//$result = db_query($sql);

// delete old sessions
$sql = "DELETE FROM sessions WHERE session_time < ('".date('Y-m-d H:i:s')."' - INTERVAL 15 MINUTE) ";
db_query($sql);

// delete old chats
$sql = 'SELECT COUNT(id) AS total FROM chat';
$result = db_query_array($sql);
if ($result && $result[0]['total'] > 0) {
	$c = $result[0]['total'] - 30;
	if ($c > 0)
		db_query('DELETE FROM chat ORDER BY id ASC LIMIT '.$c);
}

// delete ip access log
$timeframe = (!empty($CFG->cloudflare_blacklist_timeframe)) ? $CFG->cloudflare_blacklist_timeframe : 15;
$sql = "DELETE FROM ip_access_log WHERE `timestamp` < ('".date('Y-m-d H:i:s')."' - INTERVAL $timeframe MINUTE) ";
db_query($sql);

// set market price orders at market price
$sql = "SELECT id,btc,currency,c_currency,order_type,site_user FROM orders WHERE orders.market_price = 'Y' ORDER BY orders.id ASC";
$result = db_query_array($sql);
if ($result) {
	foreach ($result as $row) {
		$buy = ($row['order_type'] == $CFG->order_type_bid);
		$operations = Orders::executeOrder($buy,false,$row['btc'],$row['c_currency'],$row['currency'],false,1,$row['id'],$row['site_user'],true);
	}
}

// notify pending withdrawals
if ($CFG->email_notify_fiat_withdrawals == 'Y') {
	$sql = 'SELECT 1 FROM requests WHERE notified = 0 AND request_type = '.$CFG->request_widthdrawal_id.' AND request_status = '.$CFG->request_pending_id.' AND `date` < DATE_SUB(DATE_ADD(NOW(), INTERVAL '.((($CFG->timezone_offset)/60)/60).' HOUR), INTERVAL 5 MINUTE) AND done != \'Y\' LIMIT 0,1';
	$result = db_query_array($sql);
	
	$sql = 'SELECT c_currency, (hot_wallet_btc - ((total_btc * '.$reserve_ratio.') + pending_withdrawals) - bitcoin_sending_fee) AS deficit FROM wallets WHERE hot_wallet_notified = "N" AND (hot_wallet_btc - ((total_btc * '.$reserve_ratio.') + pending_withdrawals) - bitcoin_sending_fee) LIMIT 0,1';
	$result1 = db_query_array($sql);
	
	if ($result || $result1) {
		$info = array();
		
		$sql = 'SELECT ROUND(SUM(requests.amount),2) AS amount, LOWER(currencies.currency) AS currency FROM requests LEFT JOIN currencies ON (currencies.id = requests.currency) WHERE requests.request_type = '.$CFG->request_widthdrawal_id.' AND requests.request_status = '.$CFG->request_pending_id.' AND requests.done != \'Y\' GROUP BY requests.currency';
		$result = db_query_array($sql);
		
		if ($result) {
			foreach ($result as $row) {
				if (empty($info['pending_withdrawals']))
					$info['pending_withdrawals'] = '';
				
				$info['pending_withdrawals'] .= strtoupper($row['currency']).': '.$row['amount'].'<br/>';
			}
		}
		
		if ($result1) {
			foreach ($result1 as $row) {
				if (empty($info['pending_withdrawals']))
					$info['pending_withdrawals'] = '';
				
				$info['pending_withdrawals'] .= 'Hot Wallet Deficit ('.$CFG->currencies[$row['c_currency']]['currency'].'): '.abs($row['deficit']).'<br/>';
			}
		}
		
		if (count($info) > 0) {
			$CFG->language = 'en';
			$email = SiteEmail::getRecord('pending-withdrawals');
			Email::send($CFG->form_email,$CFG->contact_email,$email['title'],$CFG->form_email_from,false,$email['content'],$info);
				
			$sql = 'UPDATE requests SET notified = 1 WHERE notified = 0';
			db_query($sql);
				
			$sql = 'UPDATE wallets SET hot_wallet_notified = "Y"';
			db_query($sql);
		}
	}
}

// subtract withdrawals
$sql = 'SELECT site_users_balances.balance AS balance, site_users_balances.id AS balance_id, requests.id AS request_id, requests.site_user AS site_user, requests.currency AS currency, ROUND(requests.amount,2) AS amount FROM requests LEFT JOIN site_users_balances ON (site_users_balances.site_user = requests.site_user AND site_users_balances.currency = requests.currency) WHERE requests.request_type = '.$CFG->request_widthdrawal_id.' AND requests.currency NOT IN ('.implode(',',$cryptos).') AND requests.request_status = '.$CFG->request_pending_id.' AND requests.done = \'Y\'';
$result = db_query_array($sql);
if ($result) {
	foreach ($result as $row) {
		if (empty($old_balance[$row['site_user']][$row['currency']]))
			$old_balance[$row['site_user']][$row['currency']] = $row['balance'];
		
		$sql = 'UPDATE site_users_balances SET balance = balance - '.number_format($row['amount'],8,'.','').' WHERE id = '.$row['balance_id'];
		db_query($sql);
		
		$sql = 'UPDATE history SET balance_before = '.number_format($old_balance[$row['site_user']][$row['currency']],8,'.','').', balance_after = '.number_format(($old_balance[$row['site_user']][$row['currency']] - $row['amount']),8,'.','').' WHERE request_id = '.$row['request_id'];
		db_query($sql);
		
		$old_balance[$row['site_user']][$row['currency']] = $old_balance[$row['site_user']][$row['currency']] - $row['amount'];
	}
	$sql = 'UPDATE requests SET requests.request_status = '.$CFG->request_completed_id.' WHERE requests.request_type = '.$CFG->request_widthdrawal_id.' AND requests.currency NOT IN ('.implode(',',$cryptos).') AND requests.request_status = '.$CFG->request_pending_id.' AND requests.done = "Y" ';
	db_query($sql);
}

// currency ledger
if ((date('H') == 7 || date('H') == 16) && (date('i') >= 0 && date('i') < 5)) {
	// check total currency needed for withdrawals
	$sql = "SELECT currency, SUM(amount) AS amount FROM requests WHERE requests.request_status = {$CFG->request_pending_id} AND currency NOT IN ('.implode(',',$cryptos).') AND request_type = {$CFG->request_withdrawal_id} GROUP BY currency";
	$result = db_query_array($sql);
	if ($result) {
		foreach ($result as $row) {
			$withdrawals[$row['currency']] = $row['amount'];
		}
	}
	
	// get fiat escrow balances from Bank
	//////////////////////////////////////////
	
	// get crypto escrow balances
	//$wallets = Wallets::get();
	
	// get current currency ledger
	$ledger = array();
	$sql = 'SELECT * FROM conversions WHERE is_active != "Y"';
	$result = db_query_array($sql);
	if ($result) {
		foreach ($result as $row) {
			$ledger[$row['currency']] = $row['amount'];
		}
	}
	
	// factor new imbalances into ledger balances
	$sql = 'SELECT 
			IF(transactions.transaction_type = '.$CFG->transactions_buy_id.', currency, currency1) AS currency, 
			IF(transactions.transaction_type = '.$CFG->transactions_buy_id.', currency1, currency) AS currency1, 
			SUM(IF(transactions.transaction_type = '.$CFG->transactions_buy_id.', transactions.btc_price * transactions.btc, transactions.orig_btc_price * transactions.btc )) AS amount, 
			SUM(IF(transactions.transaction_type = '.$CFG->transactions_buy_id.', transactions.orig_btc_price * transactions.btc, transactions.btc_price * transactions.btc)) AS amount_needed 
			FROM transactions WHERE factored != "Y" AND conversion = "Y" 
			GROUP BY CONCAT(IF(transactions.transaction_type = '.$CFG->transactions_buy_id.', currency1, currency) , "-", IF(transactions.transaction_type = '.$CFG->transactions_buy_id.', currency, currency1))';
	$result = db_query_array($sql);
	if ($result) {
		foreach ($result as $row) {
			$ledger[$row['currency']] = (!empty($ledger[$row['currency']])) ? $ledger[$row['currency']] + $row['amount'] : $row['amount'];
			$ledger[$row['currency1']] = (!empty($ledger[$row['currency1']])) ? $ledger[$row['currency1']] - $row['amount_needed'] : ($row['amount_needed'] * -1);
		}
	}
	
	if ($ledger) {
		foreach ($ledger as $currency => $amount) {
			/*
			 if ($withdrawals[$currency] > $amount) {
			// consolidate that particular currency to satisfy withdrawals
			/////////////////////////////////////////////
			}
			*/
	
			$sql = 'SELECT id FROM conversions WHERE currency = '.$currency.' AND is_active != "Y" LIMIT 0,1';
			$result = db_query_array($sql);
			if ($result)
				db_update('conversions',$result[0]['id'],array('amount'=>$amount,'total_withdrawals'=>((!empty($withdrawals[$currency])) ? $withdrawals[$currency] : 0),'date1'=>date('Y-m-d H:i:s')));
			else
				db_insert('conversions',array('amount'=>$amount,'total_withdrawals'=>((!empty($withdrawals[$currency])) ? $withdrawals[$currency] : 0),'date'=>date('Y-m-d H:i:s'),'date1'=>date('Y-m-d H:i:s'),'currency'=>$currency,'is_active'=>'N','factored'=>'N'));
		}
	}
	
	$sql = 'UPDATE transactions SET factored = "Y" WHERE factored != "Y"';
	db_query($sql);
}

db_update('status',1,array('cron_maintenance'=>date('Y-m-d H:i:s')));

echo 'done'.PHP_EOL;
<file_sep>#!/usr/bin/php
<?php
include 'common.php';

// WARNING
// This file is only to be run to pull price data from other exchanges before the exchange has it's own operations!
// Once the exchange is operating, it will generate it's own price data

echo date('Y-m-d H:i:s').' Beginning Historical Data processing...'.PHP_EOL;

$wallets = Wallets::get();
if (!$wallets) {
	echo 'Error: no wallets to process.'.PHP_EOL;
	exit;
}

if (!array_key_exists('BTC',$wallets)) {
	echo 'Error: Must have BTC data series to execute this function.'.PHP_EOL;
	exit;
}

$btc_data = array();
$btc_wallet = $wallets['BTC'];
unset($wallets['BTC']);
$wallets = array('BTC'=>$btc_wallet) + $wallets;

// QUANDL HISTORICAL DATA
foreach ($wallets as $wallet) {
	if ($CFG->currencies[$wallet['c_currency']]['currency'] == 'BTC')
		$url = 'https://www.quandl.com/api/v3/datasets/BTCE/USDBTC.csv';
	else
		$url = 'https://www.quandl.com/api/v3/datasets/CRYPTOCHART/'.$CFG->currencies[$wallet['c_currency']]['currency'].'.csv';
	
	$ch = curl_init();
	curl_setopt($ch,CURLOPT_URL,$url);
	curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
	curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10);
	curl_setopt($ch,CURLOPT_TIMEOUT,10);
	curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
	$data = curl_exec($ch);
	curl_close($ch);
	$data1 = explode("\n",$data);
	
	if ($data1) {
		$i = 1;
		$c = count($data1);
		$rows = array();
		
		foreach ($data1 as $row) {
			$row1 = explode(',',$row);
			if ($i == 1 || ($i > 2 && (empty($row1[0]) || empty($row1[1])))) {
				$i++;
				continue;
			}
			
			if ($CFG->currencies[$wallet['c_currency']]['currency'] == 'BTC') {
				$btc_data[$row1[0]] = $row1[1];
				$exchange_rate = $row1[1];
			}
			else if (!empty($btc_data[$row1[0]]))
				$exchange_rate = $row1[1] * $btc_data[$row1[0]];
			else
				continue;
			
			if ($i == 2) {
				db_update('currencies',$wallet['c_currency'],array('usd_ask'=>$exchange_rate,'usd_bid'=>$exchange_rate));
			}
			
			$rows[] = array('c_currency'=>$wallet['c_currency'],'date'=>'"'.$row1[0].'"','usd'=>$exchange_rate);
			$i++;
		}
		
		foreach ($rows as $row) {
			$rows1[] = '('.implode(',',$row).')';
		}
		
		$sql = 'INSERT INTO historical_data ('.implode(',',array_keys($rows[0])).') VALUES '.implode(',',$rows1).' ON DUPLICATE KEY UPDATE c_currency = VALUES(c_currency), date = VALUES(date), usd = VALUES(usd)';
		db_query($sql);
	}
}

echo 'done';
?>
<file_sep>#!/usr/bin/php
<?php
include 'common.php';
echo date('Y-m-d H:i:s').' Beginning Daily Report processing...'.PHP_EOL;

/* should run at the very start of every day */

$main = Currencies::getMain();
$cryptos = Currencies::getCryptos();
$wallets = Wallets::get();

// compile historical data
if ($wallets) {
	foreach ($wallets as $wallet) {
		$sql = "INSERT IGNORE INTO historical_data (`date`,usd,c_currency) (SELECT '".(date('Y-m-d',strtotime('-1 day')))."',(transactions.btc_price * currencies.usd_ask) AS btc_price, transactions.c_currency FROM transactions LEFT JOIN currencies ON (transactions.currency = currencies.id) WHERE transactions.c_currency = ".$wallet['c_currency']." AND transactions.date <= (CURDATE()) ORDER BY transactions.date DESC LIMIT 0,1) ";
		$result = db_query($sql);
	}
}

// get total of each currency
$sql = 'SELECT COUNT(DISTINCT site_users.id) AS total_users, SUM(IF(site_users_balances.currency IN ('.implode(',',$cryptos).'),site_users_balances.balance * currencies.usd_ask,0)) AS btc, SUM(IF(site_users_balances.currency NOT IN ('.implode(',',$cryptos).'),site_users_balances.balance * currencies.usd_ask,0)) AS usd FROM site_users LEFT JOIN site_users_balances ON (site_users.id = site_users_balances.site_user) LEFT JOIN currencies ON (currencies.id = site_users_balances.currency)';
$result = db_query_array($sql);
if ($result) {
	$total_users = $result[0]['total_users'];
	$total_btc = number_format(round($result[0]['btc'] / $CFG->currencies[$main['crypto']]['usd_ask'],8,PHP_ROUND_HALF_UP),8,'.','');
	$total_usd = round($result[0]['usd'] / $CFG->currencies[$main['fiat']]['usd_ask'],2,PHP_ROUND_HALF_UP);
	$btc_per_user = number_format(round($total_btc / $total_users,8,PHP_ROUND_HALF_UP),8,'.','');
	$usd_per_user = round($total_usd / $total_users,2,PHP_ROUND_HALF_UP);
}

// get open orders BTC
$sql = 'SELECT SUM(orders.btc * currencies.usd_ask) AS btc FROM orders LEFT JOIN currencies ON (orders.c_currency = currencies.id)';
$result = db_query_array($sql);
$open_orders_btc = number_format(round($result[0]['btc'] / $CFG->currencies[$main['crypto']]['usd_ask'],8,PHP_ROUND_HALF_UP),8,'.','');

// get total transactions for the day
$sql = 'SELECT SUM(transactions.btc * c_currencies.usd_ask) AS total_btc, AVG(transactions.btc * c_currencies.usd_ask) AS avg_btc, SUM((transactions.fee + transactions.fee1)  * transactions.btc_price * currencies.usd_ask) AS total_fees FROM transactions LEFT JOIN currencies ON (transactions.currency = currencies.id) LEFT JOIN currencies c_currencies ON (transactions.c_currency = c_currencies.id) WHERE DATE(transactions.date) = (CURDATE() - INTERVAL 1 DAY)';
$result = db_query_array($sql);
$transactions_btc = round($result[0]['total_btc'] / $CFG->currencies[$main['crypto']]['usd_ask'],2,PHP_ROUND_HALF_UP);
$avg_transaction = round($result[0]['avg_btc'] / $CFG->currencies[$main['crypto']]['usd_ask'],2,PHP_ROUND_HALF_UP);
$trans_per_user = number_format(round($transactions_btc / $total_users,8,PHP_ROUND_HALF_UP),8,'.','');
$total_fees = round($result[0]['total_fees'] / $CFG->currencies[$main['fiat']]['usd_ask'],2,PHP_ROUND_HALF_UP);
$fees_per_user = number_format(round($total_fees / $total_users,8,PHP_ROUND_HALF_UP),8,'.','');

// get fees incurred from crypto networks for internal movements
$sql = 'SELECT SUM(fees.fee*currencies.usd_ask) AS fees_incurred FROM fees LEFT JOIN currencies ON (currencies.id = fees.c_currency) WHERE DATE(fees.date) = (CURDATE() - INTERVAL 1 DAY)';
$result = db_query_array($sql);
$gross_profit = $total_fees - round($result[0]['fees_incurred'] / $CFG->currencies[$main['fiat']]['usd_ask'],2,PHP_ROUND_HALF_UP);

db_insert('daily_reports',array('date'=>date('Y-m-d',strtotime('-1 day')),'total_btc'=>$total_btc,'total_fiat_usd'=>$total_usd,'btc_per_user'=>$btc_per_user,'usd_per_user'=>$usd_per_user,'open_orders_btc'=>$open_orders_btc,'transactions_btc'=>$transactions_btc,'avg_transaction_size_btc'=>$avg_transaction,'transaction_volume_per_user'=>$trans_per_user,'total_fees_btc'=>$total_fees,'fees_per_user_btc'=>$fees_per_user,'gross_profit_btc'=>$gross_profit));

db_update('status',1,array('cron_daily_stats'=>date('Y-m-d H:i:s')));
echo 'done'.PHP_EOL;
<file_sep><?php
class Ethereum {
	public $user,$pass,$host,$port;
	
	public function __construct($user,$pass,$host,$port,$etherscan_api_key=false) {
		$this->user = $user;
		$this->pass = $pass;
		$this->host = $host;
		$this->port = $port;
		$this->etherscan_api_key = $etherscan_api_key;
		$this->from_wei = 1000000000000000000;
	}
	
	public function newAccount() {
		$params = array(
			'jsonrpc'=>'2.0x',
			'method'=>'personal_newAccount',
			'params'=>array($this->pass),
			'id'=>time()
		);
		
		$result = $this->call($params);
		if ($result && $result['result'])
			return $result['result'];
		else if ($result && $result['error'])
			echo $result['error']['message'].PHP_EOL;

		return false;	
	}
	
	public function getGasPrice() {
		$params = array(
			'jsonrpc'=>'2.0x',
			'method'=>'eth_gasPrice',
			'params'=>array(),
			'id'=>time()
		);
		
		$result = $this->call($params);
		if ($result && $result['result'])
			return hexdec($result['result']);
		else if ($result && $result['error'])
			echo $result['error']['message'].PHP_EOL;
		
		return false;
	}
	
	public function unlock($address,$password) {
		$params = array(
			'jsonrpc'=>'2.0x',
			'method'=>'personal_unlockAccount',
			'params'=>array($address,$password,60),
			'id'=>time()
		);
		
		$result = $this->call($params);
		if ($result && $result['result'])
			return $result['result'];
		else if ($result && $result['error'])
			echo $result['error']['message'].PHP_EOL;
		
		return false;
	}
	
	public function sendTransactions($transactions,$gas_limit) {
		if (!is_array($transactions) || count($transactions) == 0)
			return false;
		
		$sent = 0;
		$errors = false;
		
		foreach ($transactions as $i => $transaction) {
			$this->unlock($transaction['from'],$this->pass);
			$gas_price = (bcmul($transaction['fee'],$this->from_wei) / $gas_limit);
			
			$params = array(
				'jsonrpc'=>'2.0x',
				'method'=>'eth_sendTransaction',
				'params'=>array(array(
					'from'=>$transaction['from'],
					'to'=>$transaction['to'],
					'gas'=>$this->encodeHex($gas_limit),
					'gasPrice'=>$this->encodeHex($gas_price),
					'value'=>$this->encodeHex(bcmul($transaction['amount'],$this->from_wei) - ($gas_price * $gas_limit))
				)),
				'id'=>time()
			);
			
			$result = $this->call($params);
			if ($result && $result['result']) {
				$transactions[$i]['txid'] = $result['result'];
				$transactions[$i]['fee'] = number_format(($gas_price * $gas_limit) / $this->from_wei,8,'.','');
				$sent += $transaction['amount'];
			}
			else if ($result && $result['error']) {
				echo $result['error']['message'].PHP_EOL;
				$errors[] = $result['error']['message'];
			}
		}
		
		return array('sent'=>$sent,'transactions'=>$transactions,'errors'=>$errors);
	}
	
	public function getTransactions($current_block,$addresses) {
		if (!$addresses)
			return false;
		
		$params = array(
			'jsonrpc'=>'2.0x',
			'method'=>'eth_getLogs',
			'params'=>array(
				array(
					'topics'=>array(),
					'fromBlock'=>$this->encodeHex($current_block - 14000),
					'toBlock'=>$this->encodeHex($current_block),
					'address'=>$addresses,
				)
			),
			'id'=>time()
		);
		
		$result = $this->call($params);
		if ($result && is_array($result['result'])) {
			$result['result']['amount'] = number_format($this->decodeHex($result['result']['value']) / $this->from_wei,8,'.','');
			return $result['result'];
		}
		else if ($result && $result['error'])
			echo $result['error']['message'].PHP_EOL;
			
		return false;
	}
	
	public function getTransactionsFromEtherscan($current_block,$address) {
		if (!$this->etherscan_api_key || !$address)
			return false;
		
		$params = array(
			'module'=>'account',
			'action'=>'txlist',
			'address'=>$address,
			'startBlock'=>$current_block - 14000,
			'sort'=>'asc',
			'api_key'=>$this->etherscan_api_key
		);
		
		$return = array();
		$result = $this->callEtherscan($params);
		if (!empty($result['result'])) {
			foreach ($result['result'] as $t) {
				$t['amount'] = number_format($t['value'] / $this->from_wei,8,'.','');
				$t['txid'] = $t['hash'];
				$return[] = $t;
			}
		}
		
		return $return;
	}
	
	public function getTransaction($hash,$current_block) {
		$params = array(
			'jsonrpc'=>'2.0x',
			'method'=>'eth_getTransactionByHash',
			'params'=>array($hash),
			'id'=>time()
		);
		
		$result = $this->call($params);
		if ($result && $result['result']) {
			if ($current_block > 0) {
				$b = hexdec($result['result']['blockNumber']);
				$result['result']['confirmations'] = $b - $current_block;
			}
			return $result['result'];
		}
		else if ($result && $result['error'])
			echo $result['error']['message'].PHP_EOL;
			
		return false;	
	}
	
	public function getBlockNum() {
		$params = array(
			'jsonrpc'=>'2.0x',
			'method'=>'eth_blockNumber',
			'params'=>array(),
			'id'=>time()
		);
		
		$result = $this->call($params);
		if ($result && $result['result'])
			return hexdec($result['result']);
		else if ($result && $result['error'])
			echo $result['error']['message'].PHP_EOL;
			
		return false;
	}
	
	public function getBalance($address) {
		if (!$address)
			return false;
		
		$params = array(
			'jsonrpc'=>'2.0x',
			'method'=>'eth_getBalance',
			'params'=>array($address,'latest'),
			'id'=>time()
		);
		
		$result = $this->call($params);
		if ($result && $result['result'])
			return number_format(hexdec($result['result']) / $this->from_wei,8,'.','');
		else if ($result && $result['error'])
			echo $result['error']['message'].PHP_EOL;
			
		return false;
	}
	
	public function getAddressesWithBalance() {
		$input = 'function getBalances() { var wb = []; for (i in web3.eth.accounts) { var b = web3.fromWei(web3.eth.getBalance(web3.eth.accounts[i])); if (b > 0) wb.push(web3.eth.accounts[i]); } return wb; } getBalances();';
		return $this->callGeth($input);
	}
	
	public function call($params) {
		$ch = curl_init();
			
		curl_setopt($ch,CURLOPT_URL,$this->host.':'.$this->port);
		curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
		curl_setopt($ch,CURLOPT_POSTFIELDS,str_replace('2.0x','2.0',json_encode($params)));
		curl_setopt($ch,CURLOPT_POST,1);
		
		$headers = array();
		$headers[] = "Content-Type: application/json";
		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
		
		if (!empty($params['simulate'])) {
			print_r(str_replace('2.0x','2.0',json_encode($params)));
			return false;
		}
		
		$result = json_decode(curl_exec($ch),true);
		curl_close($ch);
		
		return $result;
	}
	
	public function callGeth($input) {
		$exec = 'geth --exec "'.$input.'" attach http://'.$this->host.':'.$this->port;
		return json_decode(exec($exec),true);
	}
	
	public function callEtherscan($params) {
		$ch = curl_init();
			
		curl_setopt($ch,CURLOPT_URL,'http://api.etherscan.io/api?'.http_build_query($params));
		curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
		
		$result = json_decode(curl_exec($ch),true);
		curl_close($ch);
		
		return $result;
	}
	
	private function decodeHex($input) {
		if(substr($input,0,2) == '0x')
			$input = substr($input,2);
		
		if(preg_match('/[a-f0-9]+/', $input))
			return hexdec($input);
			
		return $input;
	}

	private function encodeHex($input) {
		$number = (string) dechex($input);
		return '0x'.$number;
	}
}
<file_sep><?php
class Currencies {
	public static function get() {
		$sql = "SELECT * FROM currencies WHERE is_active = 'Y' ORDER BY currency ASC";
		$result = db_query_array($sql);
		
		if ($result) {
			foreach ($result as $row) {
				$currencies[$row['currency']] = $row;
				$currencies[$row['id']] = $row;
			}
		}
		return $currencies;
	}
	
	public static function getRecord($currency_abbr=false,$currency_id=false) {
		if (!$currency_abbr && !$currency_id)
			return false;

		if ($currency_abbr)
			return DB::getRecord('currencies',false,$currency_abbr,0,'currency');
		elseif ($currency_id > 0)
			return DB::getRecord('currencies',$currency_id,false,1);
	}
	
	public static function getMain() {
		global $CFG;
		
		$main_crypto = 0;
		$main_fiat = 0;
		
		foreach ($CFG->currencies as $currency_id => $currency) {
			if (!is_numeric($currency_id) || $currency['is_main'] != 'Y')
				continue;
			
			if ($currency['is_crypto'] == 'Y')
				$main_crypto = $currency_id;
			else 
				$main_fiat = $currency_id;
		}
		
		if (!$main_crypto)
			$main_crypto = $CFG->currencies['BTC']['id'];
		if (!$main_fiat)
			$main_fiat = $CFG->currencies['USD']['id'];
		
		return array('crypto'=>$main_crypto,'fiat'=>$main_fiat);
	}
	
	public static function getCryptos() {
		global $CFG;
	
		$cryptos = array();
		foreach ($CFG->currencies as $currency_id => $currency) {
			if (!is_numeric($currency_id) || $currency['is_crypto'] != 'Y')
				continue;
				
			$cryptos[] = $currency_id;
		}
		return $cryptos;
	}
}<file_sep>#!/usr/bin/php
<?php
include 'common.php';
echo date('Y-m-d H:i:s').' Beginning Fiat Withdrawal processing...'.PHP_EOL;
ini_set('display_errors',1);

// GET SYSTEM BANK ACCOUNTS
$sys = array();

foreach ($CFG->currencies as $c) {
	if (!$c['account_number'] || strlen($c['account_number']) < 6)
		continue;
		
	$sys[$c['account_number']] = $c;
};


$cc = new CryptoCap($CFG->crypto_capital_pk,$CFG->crypto_capital_secret);

// FETCH INCOMING DEPOSITS
foreach ($sys as $ac) {
	$result = $cc->statement(array('limit'=>'100', 'accountNumber'=>$ac['account_number']));

	if ($result) foreach ($result as $r) {
		if ($r['receiveAccount'] != $ac['account_number'])
			continue;
		
		// check internal conversion
		if (!empty($sys[$r['sendAccount']])) {
			db_query('UPDATE requests  
					SET requests.crypto_id = "" 
					WHERE requests.request_status = '.$CFG->request_pending_id.' 
					AND requests.request_type = '.$CFG->request_withdrawal_id.' 
					AND crypto_id = 1 
					AND requests.currency = "'.$CFG->currencies[strtoupper($r['receiveCurrency'])].'"');
			continue;
		}
		
		$e = db_query_array('SELECT id FROM requests WHERE crypto_id = '.$r['id'].' LIMIT 0,1');
		if ($e)
			continue;
		
		$sql = 'SELECT 
				bank_accounts.site_user AS user_id, 
				bank_accounts.currency AS currency_id, 
				currencies1.id AS currency_id1, 
				bank_accounts1.account_number AS account_number1, 
				currencies.currency AS currency, 
				site_users.notify_deposit_bank AS notify_deposit_bank, 
				site_users.first_name AS first_name, 
				site_users.last_name AS last_name, 
				site_users.email AS email, 
				site_users.last_lang AS last_lang, 
				site_users.notify_deposit_bank AS notify_deposit_bank, 
				IFNULL(site_users_balances.balance,0) AS cur_balance, 
				site_users_balances.id AS balance_id 
				FROM bank_accounts 
				LEFT JOIN currencies ON (currencies.id = bank_accounts.currency) 
				LEFT JOIN site_users ON (bank_accounts.site_user = site_users.id) 
				LEFT JOIN currencies currencies1 ON (currencies1.currency = "'.$r['receiveCurrency'].'") 
				LEFT JOIN bank_accounts bank_accounts1 ON (site_users.id = bank_accounts1.site_user AND bank_accounts1.currency = currencies1.id) 
				LEFT JOIN site_users_balances ON (site_users.id = site_users_balances.site_user AND site_users_balances.currency = currencies1.id) 
				WHERE bank_accounts.account_number = '.$r['sendAccount'].' LIMIT 0,1';
				
		$result1 = db_query_array($sql);
		if (!$result1)
			continue;
		
		$i = $result1[0];
		if ($i['currency'] != $r['receiveCurrency'])
			$i['currency_id'] = $i['currency_id1'];
								
		$fee = $r['sendAmount'] - $r['receiveAmount'];
		$id = db_query('INSERT INTO requests (`date`,site_user,currency,amount,net_amount,fee,description,request_type,request_status,account,crypto_id) VALUES ("'.date('Y-m-d H:i:s').'",'.$i['user_id'].','.$i['currency_id'].','.$r['receiveAmount'].','.$r['receiveAmount'].','.$fee.','.$CFG->deposit_fiat_desc.','.$CFG->request_deposit_id.','.$CFG->request_completed_id.','.$r['sendAccount'].','.$r['id'].')');
	
		if ($i['balance_id'])
			db_query('UPDATE site_users_balances SET balance = balance + '.$r['receiveAmount'].' WHERE id = '.$i['balance_id']);
		else
			db_query('INSERT INTO site_users_balances (balance,site_user,currency) VALUES ('.$r['receiveAmount'].','.$i['user_id'].','.$i['currency_id1'].')');
	
		db_query('INSERT INTO history (`date`,history_action,site_user,request_id,balance_before,balance_after) VALUES ("'.date('Y-m-d H:i:s').'",'.$CFG->history_deposit_id.','.$i['user_id'].','.$id.','.$i['cur_balance'].','.($i['cur_balance'] + $r['receiveAmount']).')');
	}
}

// CHECK PENDING WITHDRAWALS
$sql = 'SELECT r.*, 
		b.id AS user_acc_id,
		c.account_number AS sys_acc_num, 
		c.currency AS currency_abbr 
		FROM requests r 
		LEFT JOIN bank_accounts b ON (b.account_number = r.account AND b.site_user = r.site_user AND b.currency = r.currency) 
		LEFT JOIN currencies c ON (r.currency = c.id) 
		WHERE r.request_status = '.$CFG->request_pending_id.' 
		AND r.request_type = '.$CFG->request_withdrawal_id.' 
		AND c.is_crypto != "Y" 
		AND crypto_id != 1 
		AND r.done != "Y"';
if ($CFG->withdrawals_fiat_manual_approval == 'Y')
	$sql .= ' AND requests.approved = "Y"';

$result = db_query_array($sql);

// SEND WITHDRAWALS FOR PROCESSING
if ($result) foreach ($result as $r) {
	if (!$r['user_acc_id'] || !$r['sys_acc_num']) {
		db_query('UPDATE requests SET request_status = '.$CFG->request_cancelled_id+' WHERE requests.id = '.$r['id']);
		continue;
	}
	
	$res = $cc->transfer(array(
		'fromAccount' => $r['sys_acc_num'],
		'toAccount' => $r['account'],
		'currency' => $r['currency_abbr'],
		'amount' => $r['amount'],
		'narrative' => $CFG->exchange_name.' #'.$r['id']
	));

	// SUBTRACT SUCCESSFUL WITHDRAWAL FROM BALANCE
	if ($res) {
		$b = db_query_array('
			SELECT r.id AS request_id, 
			r.site_user AS user_id, 
			sub.balance AS balance, 
			sub.id AS balance_id 
			FROM requests r 
			LEFT JOIN site_users_balances sub ON (r.site_user = sub.site_user AND r.currency = sub.currency) 
			WHERE r.id = '.$r['id'].' 
			AND r.request_status != '.$CFG->request_completed_id.' 
			LIMIT 0,1');
			
		db_query('UPDATE site_users_balances SET balance = balance - '.$r['amount'].' WHERE id = '.$b[0]['balance_id']);
		db_query('UPDATE requests SET request_status = '.$CFG->request_completed_id.', done = "Y" WHERE id = '.$r['id']);
		db_query('UPDATE history SET balance_before = '.$b[0]['balance'].', balance_after = '.($b[0]['balance'] - $r['amount']).' WHERE request_id = '.$r['id']);
	}
}

echo 'done'.PHP_EOL;
<file_sep><?php 
class Wallets {
	public static function get() {
		global $CFG;
	
		$sql = 'SELECT wallets.* FROM wallets ';
		$result = db_query_array($sql);
		if (!$result)
			return false;
	
		$sorted = array();
		foreach ($result as $row) {
			$sorted[$CFG->currencies[$row['c_currency']]['currency']] = $row;
		}
		return $sorted;
	}
	
	public static function sumFields($wallet_id,$fields) {
		global $CFG;
	
		if (!is_array($fields) || empty($fields) || !$wallet_id)
			return false;
	
		$set = array();
		foreach ($fields as $field => $sum_amount) {
			if (!is_numeric($sum_amount))
				continue;
				
			$set[] = $field.' = '.$field.' + ('.$sum_amount.')';
		}
	
		$sql = 'UPDATE wallets SET '.implode(',',$set).' WHERE id = '.$wallet_id;
		return db_query($sql);
	}
	
	public static function getReserveSurplus($wallet_id) {
		global $CFG;
		
		if (!$wallet_id)
			return false;
	
		$reserve_ratio = ($CFG->bitcoin_reserve_ratio) ? $CFG->bitcoin_reserve_ratio : '0';
		$reserve_min = ($CFG->bitcoin_reserve_min) ? $CFG->bitcoin_reserve_min : '0';
		$sql = 'SELECT (hot_wallet_btc - ((total_btc * '.$reserve_ratio.') + pending_withdrawals + '.$reserve_min.') - bitcoin_sending_fee) AS surplus, hot_wallet_btc FROM wallets WHERE id = '.$wallet_id;
		$result = db_query_array($sql);
		if (!$result)
			return 0;
	
		return $result[0];
	}
}
?><file_sep><?php
class API{
	public static function getJson($url) {
		$ch = curl_init();
		curl_setopt($ch,CURLOPT_URL,$url);
		curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
		curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10);
		curl_setopt($ch,CURLOPT_TIMEOUT,10);
		curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
		$data1 = curl_exec($ch);
		
		if (curl_exec($ch) === false)
			trigger_error(curl_error($ch));
		
		curl_close($ch);
		$data = json_decode($data1,true);
		
		return $data;
	}
}
	<file_sep><?php
Class CryptoCap {
	public $api_key,$api_secret,$message,$signature,$nonce;
	
	public function __construct($api_key,$api_secret) {
		$this->api_key = $api_key;
		$this->api_secret = $api_secret;
	}
	
	private function nonce() {
		$this->nonce = round(microtime(true) * 1000);
		return $this->nonce;
	}
	
	private function signature() {
		$this->signature = sha1($this->message.$this->api_key.$this->api_secret);
		return $this->signature;
	}
	
	private function request($url,$params=false,$use_get=false) {
		$headers = array(
			'Content-Type: application/json',
			'key: '.$this->api_key,
			'message: '.$this->message,
			'signature: '.$this->signature,
			'nonce: '.$this->nonce
		);
		
		$json = false;
		$query = false;
		
		if (!$use_get)
			$json = is_array($params) ? json_encode($params) : false;
		else
			$query = '?'.http_build_query($params);
		
		$ch = curl_init('https://api.cryptocapital.co/v4/'.$url.($query));
		curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
		curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); 

		if (!$use_get)
			curl_setopt($ch,CURLOPT_POSTFIELDS,$json);
		
		$r = curl_exec($ch);
		$data = json_decode($r,true);
		
		if (!is_array($data)) {
			print_r(curl_error($ch));
			curl_close($ch);
			return false;
		}
		else if (is_array($data) && !empty($data['statusCode'])) {
			print_r('Error @/'.$url.': '.$data['message']);
			curl_close($ch);
			return false;
		}
		
		curl_close($ch);
		
		return $data;
	}
	
	public function ping() {
		$this->message = 'PING'.$this->nonce();
		$this->signature();
		
		return $this->request('ping');
	}
	
	public function transfer($params) {
		$this->message = 'TRANSFER'.$this->nonce().$params['fromAccount'].$params['toAccount'].$params['currency'].$params['amount'];
		$this->signature();
		
		$res = $this->request('transfer',$params);
		if (is_array($res) && $res['statusCode'] != 0) {
			print_r($res['data']);
			return false;
		}
		
		return $res;
	}
	
	public function statement($params) {
		$this->message = 'STATEMENT'.$this->nonce().$params['accountNumber'];
		$this->signature();
		
		$res = $this->request('statement/'.$params['accountNumber'],$params,true);
		if (is_array($res) && !empty($res['statusCode']) && $res['statusCode'] != 0) {
			print_r($res['data']);
			return false;
		}
		
		return $res;
	}
}
<file_sep><?php 
class Gateways {
	public static $gateways;
	
	public static function get() {
		if (is_array(self::$gateways))
			return self::$gateways;
			
		$sql = 'SELECT * FROM gateways';
		$result = db_query_array($sql);
		if (!$result)
			return false;

		$return = array();
		foreach ($result as $gateway) {
			$return[$gateway['key']] = $gateway;
		}
		self::$gateways = $return;
		return $return;
	}
	
	public static function getEscrows() {
		$sql = 'SELECT * FROM gateway_escrows';
		return db_query_array($sql);
	}
	
	public static function updateEscrows($currencies_balances,$sum=false) {
		global $CFG;
	
		if (empty($currencies_balances) || !is_array($currencies_balances))
			return false;
	
		$currencies_str = '(CASE currency ';
		$currency_ids = array();
		foreach ($currencies_balances as $curr_abbr => $balance) {
			$curr_info = $CFG->currencies[strtoupper($curr_abbr)];
			$currencies_str .= ' WHEN '.$curr_info['id'].' THEN '.(($sum) ? 'balance + ' : '').' ('.$balance.') ';
			$currency_ids[] = $curr_info['id'];
		}
		$currencies_str .= ' END)';
	
		$sql = 'UPDATE gateway_escrows SET balance = '.$currencies_str.', last_update = "'.date('Y-m-d H:i:s').'" WHERE currency IN ('.implode(',',$currency_ids).')';
		$result = db_query($sql);
	
		if (!$result || $result < count($currencies_balances)) {
			$sql = 'SELECT currency FROM gateway_escrows WHERE currency IN ('.implode(',',$currency_ids).')';
			$result = db_query_array($sql);
			$existing = array();
			if ($result) {
				foreach ($result as $row) {
					$existing[] = $row['currency'];
				}
			}
				
			foreach ($currencies_balances as $curr_abbr => $balance) {
				$curr_info = $CFG->currencies[strtoupper($curr_abbr)];
				if (in_array($curr_info['id'],$existing))
					continue;
	
				$sql = 'INSERT INTO gateway_escrows (balance,currency,last_update) VALUES ('.$balance.','.$curr_info['id'].',"'.date('Y-m-d H:i:s').'") ';
				$result = db_query($sql);
			}
		}
		return $result;
	}
	
	public static function processDeposits() {
		global $CFG;
		
		$ignore = array('crypto-capital');
		
		$gateways = self::get();
		if (!$gateways)
			return false;
		
		foreach ($gateways as $key => $gateway) {
			if (in_array($key,$ignore) || $gateway['is_active'] != 'Y')
				continue;
			
			if ($key == 'astropay') {
				
			}
		}
	}
	
	public static function processWithdrawals() {
	
	}
	
	public static function findEscrows() {
	
	}
}
?><file_sep><?php
class BitcoinAddresses{
	static $bitcoin;
	
	public static function get($count=false,$c_currency=false,$page=false,$per_page=false,$user=false,$unassigned=false,$system=false) {
		global $CFG;
		
		$page = ($page > 0) ? $page - 1 : 0;
		$r1 = $page * $per_page;
		$user = User::$info['id'];
		
		if (!$count)
			$sql = "SELECT * FROM bitcoin_addresses WHERE 1 ";
		else
			$sql = "SELECT COUNT(id) AS total FROM bitcoin_addresses WHERE 1  ";
		
		if ($user > 0)
			$sql .= " AND site_user = $user ";
		
		if ($unassigned)
			$sql .= " AND site_user = 0 ";
		
		if ($system)
			$sql .= " AND system_address = 'Y' ";
		else
			$sql .= " AND system_address != 'Y' ";
		
		if ($c_currency)
			$sql .= ' AND c_currency = '.$c_currency.' ';
		
		if ($per_page > 0 && !$count)
			$sql .= " ORDER BY bitcoin_addresses.date DESC LIMIT $r1,$per_page ";
		
		$result = db_query_array($sql);
		if (!$count)
			return $result;
		else
			return $result[0]['total'];
	}
	
	public static function getNew($c_currency=false,$return_address=false,$hot_wallet=false) {
		global $CFG;
		
		$c_currency = preg_replace("/[^0-9]/", "",$c_currency);
		if (!array_key_exists($c_currency,$CFG->currencies))
			return false;
		
		$c_currency_info = $CFG->currencies[$c_currency];
		$wallet = Wallets::getWallet($c_currency);
		
		if (!$c_currency_info['coin_type'] || $c_currency_info['coin_type'] == 'BTC') {
			require_once('../lib/easybitcoin.php');
			$bitcoin = new Bitcoin($wallet['bitcoin_username'],$wallet['bitcoin_passphrase'],$wallet['bitcoin_host'],$wallet['bitcoin_port'],$wallet['bitcoin_protocol']);
			$new_address = $bitcoin->getnewaddress($wallet['bitcoin_accountname']);
		}
		else if ($c_currency_info['coin_type'] == 'ETH') {
			$ethereum = new Ethereum($wallet['bitcoin_username'],$wallet['bitcoin_passphrase'],$wallet['bitcoin_host'],$wallet['bitcoin_port']);
			$new_address = $ethereum->newAccount();
		}
		
		if (!$hot_wallet)
			$new_id = db_insert('bitcoin_addresses',array('c_currency'=>$c_currency,'address'=>$new_address,'site_user'=>User::$info['id'],'date'=>date('Y-m-d H:i:s')));
		else
			$new_id = db_insert('bitcoin_addresses',array('c_currency'=>$c_currency,'address'=>$new_address,'date'=>date('Y-m-d H:i:s'),'hot_wallet'=>'Y','system_address'=>'Y'));
		
		return ($return_address) ? $new_address : $new_id;
	}
	
	public static function getAddress($address,$c_currency=false) {
		global $CFG;
		
		$sql = "SELECT bitcoin_addresses.id, bitcoin_addresses.site_user,bitcoin_addresses.date,bitcoin_addresses.system_address, bitcoin_addresses.hot_wallet, site_users.trusted, site_users.first_name, site_users.last_name, site_users.notify_deposit_btc,site_users.email FROM bitcoin_addresses LEFT JOIN site_users ON (site_users.id = bitcoin_addresses.site_user) WHERE ".($c_currency ? 'bitcoin_addresses.c_currency = '.$c_currency.' AND ' : '')." bitcoin_addresses.address = '$address' LIMIT 0,1";
		$result = db_query_array($sql);
		
		if ($result) {
			return $result[0];
		}
		
		return false;
	}
	
	public static function updateAddressBalance($address_id,$amount,$sum=false) {
		global $CFG;

		if (!$address_id || !$amount)
			return false;
		
		$sign = ($amount >= 0) ? 'balance + ' : 'balance - ';
		$sign = (!$sum) ? '' : $sign;
		
		$sql = 'UPDATE bitcoin_addresses SET balance = '.$sign.$amount.' WHERE id = '.$address_id;
		return db_query($sql);
	}
	
	public static function getBitcoindBalance() {
		global $CFG;
		
		if (!$CFG->session_active)
			return false;
		
		if (!self::$bitcoin) {
			require_once('easybitcoin.php');
			$bitcoin = new Bitcoin($CFG->bitcoin_username,$CFG->bitcoin_passphrase,$CFG->bitcoin_host,$CFG->bitcoin_port,$CFG->bitcoin_protocol);
		}
		else
			$bitcoin = self::$bitcoin;
		
		$accounts = $bitcoin->listaccounts(3);
		$total = 0;
		if (is_array($accounts)) {
			foreach ($accounts as $account) {
				$total += $account;
			}
		}
		return $total;
	}
	
	public static function cheapsweep($destination) {
		global $CFG;
		
		if (!$CFG->session_active)
			return false;
		
		$destination = preg_replace("/[^0-9a-zA-Z]/",'',$destination);
		if (!$destination)
			return false;
		
		if (!self::$bitcoin) {
			require_once('easybitcoin.php');
			$bitcoin = new Bitcoin($CFG->bitcoin_username,$CFG->bitcoin_passphrase,$CFG->bitcoin_host,$CFG->bitcoin_port,$CFG->bitcoin_protocol);
		}
		else
			$bitcoin = self::$bitcoin;
		
		$bitcoin->walletpassphrase($CFG->bitcoin_passphrase,3);
		$addresses1 = $bitcoin->listaddressgroupings();
		if ($addresses1) {
			foreach ($addresses1 as $address1) {
				if (is_array($address1)) {
					foreach ($address1 as $address2) {
						if (!($address2[1] > 0) || $address2[0] == $destination)
							continue;
							
						$addresses[] = $address2[0];
					}
				}
			}
		}
		
		if ($addresses) {
			$address_str = implode(' ', $addresses);
			$response = shell_exec('cd '.$CFG->dirroot.'lib/ && ./cheapsweap -d '.$destination.' '.$address_str);
			return $response;
		}
	}
	
	public static function getHotWallets($c_currency) {
		global $CFG;
		
		if (!$c_currency)
			return false;
		
		$sql = "SELECT * FROM bitcoin_addresses WHERE (hot_wallet = 'Y' || system_address = 'Y') AND c_currency = $c_currency ORDER BY balance DESC LIMIT 0,1";
		return db_query_array($sql);	
	}
	
	public static function getSystemAddresses($c_currency) {
		global $CFG;
		
		if (!$c_currency)
			return false;
		
		$sql = "SELECT * FROM bitcoin_addresses WHERE system_address = 'Y' AND c_currency = $c_currency ORDER BY balance DESC LIMIT 0,1";
		return db_query_array($sql);	
	}
	
	public static function getWarmWallet() {
		global $CFG;
		
		if (!$CFG->session_active)
			return false;
		
		$sql = "SELECT * FROM bitcoin_addresses WHERE AND warm_wallet = 'Y' LIMIT 0,1";
		$result = db_query_array($sql);
		return $result[0];
	}
	
	public static function validateAddress($btc_address) {
		global $CFG;
		
		$btc_address = preg_replace("/[^0-9a-zA-Z]/",'',$btc_address);
		
		if (!$btc_address)
			return false;
	
		if (!self::$bitcoin) {
			require_once('easybitcoin.php');
			$bitcoin = new Bitcoin($CFG->bitcoin_username,$CFG->bitcoin_passphrase,$CFG->bitcoin_host,$CFG->bitcoin_port,$CFG->bitcoin_protocol);
		}
		else
			$bitcoin = self::$bitcoin;
		
		$response = $bitcoin->validateaddress($btc_address);
	
		if (!$response['isvalid'] || !is_array($response))
			return false;
		else
			return true;
	}
}<file_sep>#!/usr/bin/php
<?php
echo "Beginning Get Global Market Stats processing...".PHP_EOL;

include 'common.php';

$main = Currencies::getMain();
$wallets = Wallets::get();
if (!$wallets)
	exit;

// GET FEE LEVELS
$ch = curl_init();
foreach ($wallets as $wallet) {
	$c_currency_info = $CFG->currencies[$wallet['c_currency']];
	$is_bitcoin = ($c_currency_info['currency'] != 'ETH');
	$is_ether = ($c_currency_info['currency'] == 'ETH');
	$wait = 10;
	$wait1 = 30;
	$wait2 = 60;
	
	if ($is_bitcoin) {
		$bitcoin = new Bitcoin($wallet['bitcoin_username'],$wallet['bitcoin_passphrase'],'localhost',$wallet['bitcoin_port'],$wallet['bitcoin_protocol']);
		$latest_id = $bitcoin->getblockcount();
		$latest_hash = $bitcoin->getblockhash($latest_id);
		$latest_t = $bitcoin->getblock($latest_hash);
		$first_hash = $bitcoin->getblockhash($latest_id - 20);
		$first_t = $bitcoin->getblock($first_hash);
		$time_per_block = ceil(($latest_t['time'] - $first_t['time']) / 20);
		$half_hour = $bitcoin->estimatefee(floor(1800/$time_per_block));
		
		if ($half_hour == -1 && $c_currency_info['currency'] == 'BTC') {
			$data = API::getJson('https://bitcoinfees.21.co/api/v1/fees/recommended');
			$half_hour = $data['halfHourFee'] * 0.00000001 * 226;
		}
	}
	else if ($is_ether){
		$data = API::getJson('http://ethgasstation.info/json/ethgasAPI.json');
		$from_wei = 1000000000;
		$half_hour = number_format(($data['average'] * $wallet['gas_limit']) / $from_wei,8,'.','');
	}	
	
	db_update('wallets',$wallet['id'],array('bitcoin_sending_fee'=>$half_hour));
}

// GET CRYPTO GLOBAL STATS
$data = API::getJson('https://api.coinmarketcap.com/v1/ticker/');

foreach ($wallets as $wallet) {
	$market_data = array();
	foreach ($data as $market) {
		if ($market['symbol'] == $CFG->currencies[$wallet['c_currency']]['currency']) {
			$market_data = $market;
			break;
		}
	}
	
	if (count($market_data) == 0)
		continue;

	$update_data = array(
		'global_btc' => $market_data['available_supply'],
		'market_cap' => ($market_data['market_cap_usd'] / $CFG->currencies[$main['fiat']]['usd_ask']),
		'trade_volume' => ($market_data['24h_volume_usd'] / $CFG->currencies[$main['fiat']]['usd_ask'])
	);
	
	db_update('wallets',$wallet['id'],$update_data);
}

// GET FIAT EXCHANGE RATES
if ($CFG->currencies) {
	foreach ($CFG->currencies as $currency) {
		if ($currency['is_crypto'] == 'Y' || $currency == 'USD')
			continue;
		
		$currencies[] = $currency['currency'].'USD';
	}
	
	$currency_string = urlencode(implode(',',$currencies));
	$data = API::getJson('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%3D%22'.$currency_string.'%22&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys');
	
	if ($data['query']['results']['rate']) {
		$bid_str = '(CASE currency ';
		$ask_str = '(CASE currency ';
		$currency_ids = array();
		$last = false;
		
		foreach ($data['query']['results']['rate'] as $row) {
			$key = str_replace('USD','',$row['id']);
			if ($key == $last)
				continue;
			
			$ask = $row['Ask'];
			$bid = $row['Bid'];
			
			if (strlen($key) < 3 || strstr($key,'='))
				continue;
			
			if ($bid == $CFG->currencies[$key]['usd_bid'] || $ask == $CFG->currencies[$key]['usd_ask'])
				continue;
			
			$bid_str .= ' WHEN "'.$key.'" THEN '.$bid.' ';
			$ask_str .= ' WHEN "'.$key.'" THEN '.$ask.' ';
			$currency_ids[] = $CFG->currencies[$key]['id'];
			$last = $key;
		}
		
		$bid_str .= ' END)';
		$ask_str .= ' END)';
		
		if (count($currency_ids) > 0) {
			$sql = 'UPDATE currencies SET usd_bid = '.$bid_str.', usd_ask = '.$ask_str.' WHERE id IN ('.implode(',',$currency_ids).')';
			$result = db_query($sql);
		}
	}
}
db_update('status',1,array('cron_get_stats'=>date('Y-m-d H:i:s')));
echo 'done'.PHP_EOL;

<file_sep>#!/usr/bin/php
<?php
include 'common.php';
echo date('Y-m-d H:i:s').' Beginning Crypto Withdrawals processing...'.PHP_EOL;
ini_set('display_errors',1);

$cryptos = Currencies::getCryptos();
$sql = "SELECT 
		r.currency, 
		r.site_user, 
		r.amount, 
		r.send_address, 
		r.fee, 
		r.net_amount, 
		r.id, 
		sub.balance, 
		sub.id AS balance_id 
		FROM requests r
		LEFT JOIN site_users su ON (r.site_user = su.id) 
		LEFT JOIN site_users_balances sub ON (sub.site_user = r.site_user AND sub.currency = r.currency) 
		WHERE r.request_status = {$CFG->request_pending_id} 
		AND r.currency IN (".implode(',',$cryptos).") 
		AND r.request_type = {$CFG->request_withdrawal_id}".(($CFG->withdrawals_btc_manual_approval == 'Y') ? " 
		AND (r.done = 'Y' OR su.trusted = 'Y')" : '')."
		ORDER BY r.id ASC";
$result = db_query_array($sql);

if (!$result) {
	echo 'done'.PHP_EOL;
	exit;
}

$wallets = Wallets::get();
if (!$wallets) {
	echo 'Error: no wallets to process.'.PHP_EOL;
	exit;
}

foreach ($wallets as $wallet) {
	$c_currency_info = $CFG->currencies[$wallet['c_currency']];
	$is_bitcoin = ($c_currency_info['currency'] != 'ETH');
	$is_ether = ($c_currency_info['currency'] == 'ETH');
	
	if ($is_bitcoin) {
		$bitcoin = new Bitcoin($wallet['bitcoin_username'],$wallet['bitcoin_passphrase'],'localhost',$wallet['bitcoin_port'],$wallet['bitcoin_protocol']);
	}
	else if ($is_ether){
		$ethereum = new Ethereum($wallet['bitcoin_username'],$wallet['bitcoin_passphrase'],'localhost',$wallet['bitcoin_port']);
	}
	
	$available = $wallet['hot_wallet_btc'];
	$deficit = $wallet['deficit_btc'];
	$users = array();
	$transactions = array();
	$user_balances = array();
	$addresses = array();
	$fees_collected = 0;
	
	if ($result) {
		$pending = 0;
		
		foreach ($result as $row) {
			if ($row['currency'] != $wallet['c_currency'])
				continue;
			
			$fee = $row['fee'];
			$operator_fee = 0;
			
			// check if user sending to himself
			$addr_info = BitcoinAddresses::getAddress($row['send_address'],$wallet['c_currency']);
			if (!empty($addr_info['site_user']) && $addr_info['site_user'] == $row['site_user']) {
				db_update('requests',$row['id'],array('request_status'=>$CFG->request_completed_id));
				continue;
			}
			
			// check if sending to another wlox user
			if (!empty($addr_info['site_user'])) {
				if (empty($user_balances[$addr_info['site_user']])) {
					$bal_info = User::getBalance($addr_info['site_user'],$wallet['c_currency'],true);
					$user_balances[$addr_info['site_user']] = $bal_info['balance'];
				}
				
				$deposit_fee = ($CFG->crypto_deposit_fee * 0.01 * $row['amount']) + $CFG->fiat_deposit_fee_unit;	
				
				User::updateBalances($row['site_user'],array($wallet['c_currency']=>(-1 * ($row['amount'] + $fee + $operator_fee))),true);
				User::updateBalances($addr_info['site_user'],array($wallet['c_currency']=>($row['amount'] - $deposit_fee)),true);
				Status::updateEscrows(array($wallet['c_currency']=>($fee + $deposit_fee)));
				db_update('requests',$row['id'],array('request_status'=>$CFG->request_completed_id));
				
				$rid = db_insert('requests',array('date'=>date('Y-m-d H:i:s'),'site_user'=>$addr_info['site_user'],'currency'=>$wallet['c_currency'],'amount'=>$row['amount'],'net_amount'=>($row['amount'] - $deposit_fee),'fee'=>$fee,'description'=>$CFG->deposit_bitcoin_desc,'request_status'=>$CFG->request_completed_id,'request_type'=>$CFG->request_deposit_id));
				if ($rid)
					db_insert('history',array('date'=>date('Y-m-d H:i:s'),'history_action'=>$CFG->history_deposit_id,'site_user'=>$addr_info['site_user'],'request_id'=>$rid,'balance_before'=>$user_balances[$addr_info['site_user']],'balance_after'=>($user_balances[$addr_info['site_user']] + $row['amount'] - $deposit_fee),'bitcoin_address'=>$row['send_address']));
				
				$user_balances[$addr_info['site_user']] = $user_balances[$addr_info['site_user']] + $row['amount'];
				continue;
			}

			if (!($row['net_amount'] > 0) || $row['net_amount'] > $available)
				continue;
			
			// check if hot wallet has enough to send
			$pending += $row['amount'];
			$transactions[$row['send_address']] = array(
				'amount' => ((!empty($transactions[$row['send_address']])) ? bcadd($row['net_amount'],(float)$transactions[$row['send_address']]['amount'],8) : $row['net_amount']),
				'blockchain_fee' => $wallet['bitcoin_sending_fee']
			);
			
			$users[$row['site_user']] = (!empty($users[$row['site_user']])) ? bcadd($row['amount'],$users[$row['site_user']],8) : $row['amount'];
			$users_net[$row['site_user']] = (!empty($users_net[$row['site_user']])) ? bcadd($row['net_amount'],$users_net[$row['site_user']],8) : $row['net_amount'];
			$users_fees[$row['site_user']] = (!empty($users_fees[$row['site_user']])) ? bcadd($fee + $operator_fee,$users_fees[$row['site_user']],8) : $fee + $operator_fee;
			$users_addresses[$row['send_address']] = $row['site_user'];
			$requests[$row['id']] = $row['send_address'];
			$available = bcsub($available,$row['net_amount'],8);
		}
	
		if ($pending > $available) {
			db_update('wallets',$wallet['id'],array('deficit_btc'=>($pending - $available),'pending_withdrawals'=>$pending));
			echo $CFG->currencies[$wallet['c_currency']]['currency'].' Deficit: '.($pending - $available).PHP_EOL;
		}
	}
	
	$errors = false;

	if (!empty($transactions)) {
		if ($is_bitcoin) {
			$bitcoin->walletpassphrase($wallet['bitcoin_passphrase'],3);
			
			foreach ($transactions as $address => $info) {
				if ($c_currency_info['currency'] == 'DASH')
					$bitcoin->settxfee((float)$info['blockchain_fee']);
				else
					$bitcoin->settxfee(round(($info['blockchain_fee'] / 226) * 1000,8));
				
				$response = $bitcoin->sendtoaddress($address,(float)$info['amount']);
				
				if (!empty($bitcoin->error)) {
					$errors[] = $bitcoin->error;
					$response = false;
					echo $bitcoin->error.PHP_EOL;
				}
			}
		}
		else if ($is_ether) {
			$hot_wallets = BitcoinAddresses::getHotWallets($wallet['c_currency']);
			$to_send = array();
			
			foreach ($transactions as $address => $info) {
				foreach ($hot_wallets as $hot_wallet) {
					if ($info['amount'] > 0 && $hot_wallet['balance'] > 0) {
						$send_amount = min($info['amount'],$hot_wallet['balance']);
						$info['amount'] -= $send_amount;
						
						$to_send[] = array('to'=>$address,'from'=>$hot_wallet['address'],'amount'=>$send_amount,'fee'=>$info['blockchain_fee']);
					}
				}
			}
			
			$sent = $ethereum->sendTransactions($to_send,$wallet['gas_limit']);
			$response = ($sent['sent'] > 0);
			
			if ($sent['errors'])
				$errors = $sent['errors'];
		}
	}

	if ($errors) {
		echo 'Errors ocurred while sending:'.PHP_EOL;
		echo print_r($errors,1).PHP_EOL;
	}
	
	if (!empty($response) && $users) {
		echo $CFG->currencies[$wallet['c_currency']]['currency'].' Transactions sent. '.PHP_EOL;
		
		$total = 0;
		
		if ($is_bitcoin) {
			$transaction = $bitcoin->gettransaction($response);
			//$actual_fee_difference = $fees_charged - abs($transaction['fee']);
			
			foreach ($users as $site_user => $amount) {
				$total += $users[$site_user];
				$fees_collected += $users_fees[$site_user];
				
				User::updateBalances($site_user,array($wallet['c_currency']=>(-1 * $amount)),true);
			}
			
			foreach ($requests as $request_id => $address) {
				db_update('requests',$request_id,array('request_status'=>$CFG->request_completed_id));
			}
		}
		else if ($is_ether) {
			//$actual_fee_difference = 0;
			$sent_addresses = array();
			
			foreach ($sent['transactions'] as $detail) {
				if (empty($detail['txid']) || empty($users_addresses[$detail['to']]))
					continue;
				
				$site_user = $users_addresses[$detail['to']];
				$gross_amount = $users[$site_user];
				$fees_collected += $users_fees[$site_user];
				$total += $detail['amount'];
				$sent_addresses[] = $detail['to'];
				
				User::updateBalances($users_addresses[$detail['to']],array($wallet['c_currency']=>(-1 * $gross_amount)),true);
			}
			
			foreach ($requests as $request_id => $address) {
				if (!in_array($address,$sent_addresses))
					continue;
				
				db_update('requests',$request_id,array('request_status'=>$CFG->request_completed_id));
			}
		}
		
		if ($total > 0) {
			Wallets::sumFields($wallet['id'],array('hot_wallet_btc'=>(0 - $total),'total_btc'=>(0 - $total)));
			//Status::updateEscrows(array($wallet['c_currency']=>($fees_collected + $actual_fee_difference)));
			db_update('wallets',$wallet['id'],array('pending_withdrawals'=>($pending - $total)));
		}
	}
	
	if (empty($pending)) db_update('wallets',$wallet['id'],array('deficit_btc'=>'0'));
	
	// FALLBACK FOR STUCK BITCOIN TRANSACTIONS
	if ($c_currency_info['currency'] == 'BTC') {
		$stuck = $bitcoin->listtransactions('*',300);
		if (is_array($stuck) && count($stuck) > 0) foreach ($stuck as $t) {
			if ($t['trusted'] || $t['category'] != 'send')
				continue;
			
			$tt = $bitcoin->gettransaction($t['txid']);
			$bitcoin->sendrawtransaction($tt['hex']);
		} 
	}
}

db_update('status',1,array('cron_send_bitcoin'=>date('Y-m-d H:i:s')));

echo 'done'.PHP_EOL;
