Merge pull request #219 from TheSerapher/next

Next
This commit is contained in:
Sebastian Grewe 2013-06-19 05:57:29 -07:00
commit f61bb5c11a
93 changed files with 3309 additions and 1352 deletions

View File

@ -29,6 +29,8 @@ Donors
These people have supported this project with a donation: These people have supported this project with a donation:
* [obigal](https://github.com/obigal) * [obigal](https://github.com/obigal)
* [vias](https://github.com/vias79)
* [WKNiGHT](https://github.com/WKNiGHT-)
Requirements Requirements
============ ============
@ -57,10 +59,11 @@ The following feature have been implemented so far:
* Reward Systems * Reward Systems
* Propotional * Propotional
* (Planned) PPS * PPS
* (Planned) PPLNS * (Planned) PPLNS
* Use of memcache for statistics instead of a cronjob * Use of memcache for statistics instead of a cronjob
* Web User accounts * Web User accounts
* Re-Captcha protected registration form
* Worker accounts * Worker accounts
* Worker activity (live, past 10 minutes) * Worker activity (live, past 10 minutes)
* Worker hashrates (live, past 10 minutes) * Worker hashrates (live, past 10 minutes)
@ -68,9 +71,23 @@ The following feature have been implemented so far:
* Minimal Block statistics * Minimal Block statistics
* Pool donations * Pool donations
* Pool fees * Pool fees
* Manual payout with 0.1 LTC fee * Manual payout
* Auto payout with 0.1 LTC fee * Auto payout
* Transaction list (confirmed and unconfirmed) * Transaction list (confirmed and unconfirmed)
* Admin Panel
* User Listing including statistics
* Wallet information
* (Planned) News Posts
* (Planned) Pool Donations
* Notification system
* IDLE Workers
* New blocks found in pool
* Auto Payout
* Manual Payout
* Support for various Scrypt based coins via config
* MNC
* LTC
* ...
Installation Installation
============ ============

View File

@ -27,6 +27,9 @@ if ($bitcoin->can_connect() !== true) {
exit(1); exit(1);
} }
// Mark this job as active
$setting->setValue('auto_payout_active', 1);
// Fetch all users with setup AP // Fetch all users with setup AP
$users = $user->getAllAutoPayout(); $users = $user->getAllAutoPayout();
@ -35,11 +38,12 @@ if (! empty($users)) {
verbose("UserID\tUsername\tBalance\tThreshold\tAddress\t\t\t\t\tStatus\n\n"); verbose("UserID\tUsername\tBalance\tThreshold\tAddress\t\t\t\t\tStatus\n\n");
foreach ($users as $aUserData) { foreach ($users as $aUserData) {
$dBalance = $transaction->getBalance($aUserData['id']); $aBalance = $transaction->getBalance($aUserData['id']);
$dBalance = $aBalance['confirmed'];
verbose($aUserData['id'] . "\t" . $aUserData['username'] . "\t" . $dBalance . "\t" . $aUserData['ap_threshold'] . "\t\t" . $aUserData['coin_address'] . "\t"); verbose($aUserData['id'] . "\t" . $aUserData['username'] . "\t" . $dBalance . "\t" . $aUserData['ap_threshold'] . "\t\t" . $aUserData['coin_address'] . "\t");
// Only run if balance meets threshold and can pay the transaction fee // Only run if balance meets threshold and can pay the potential transaction fee
if ($dBalance > $aUserData['ap_threshold'] && $dBalance > 0.1) { if ($dBalance > $aUserData['ap_threshold'] && $dBalance > $config['txfee']) {
// Validate address against RPC // Validate address against RPC
try { try {
$bitcoin->validateaddress($aUserData['coin_address']); $bitcoin->validateaddress($aUserData['coin_address']);
@ -48,20 +52,29 @@ if (! empty($users)) {
continue; continue;
} }
// Send balance - 0.1 Fee to address // Send balance, fees are reduced later by RPC Server
try { try {
$bitcoin->sendtoaddress($aUserData['coin_address'], $dBalance - 0.1); $bitcoin->sendtoaddress($aUserData['coin_address'], $dBalance);
} catch (BitcoinClientException $e) { } catch (BitcoinClientException $e) {
verbose("SEND FAILED\n"); verbose("SEND FAILED\n");
continue; continue;
} }
// Create transaction record // Create transaction record
if ($transaction->addTransaction($aUserData['id'], $dBalance, 'Debit_AP', NULL, $aUserData['coin_address'], 0.1)) { if ($transaction->addTransaction($aUserData['id'], $dBalance - $config['txfee'], 'Debit_AP', NULL, $aUserData['coin_address']) && $transaction->addTransaction($aUserData['id'], $config['txfee'], 'TXFee', NULL, $aUserData['coin_address'])) {
verbose("OK\n"); // Notify user via mail
$aMailData['email'] = $user->getUserEmail($user->getUserName($aUserData['id']));
$aMailData['subject'] = 'Auto Payout Completed';
$aMailData['amount'] = $dBalance;
if (!$notification->sendNotification($aUserData['id'], 'auto_payout', $aMailData)) {
verbose("NOTIFY FAILED\n");
} else {
verbose("OK\n");
}
} else { } else {
verbose("FAILED\n"); verbose("FAILED\n");
} }
} else { } else {
verbose("SKIPPED\n"); verbose("SKIPPED\n");
} }
@ -69,3 +82,8 @@ if (! empty($users)) {
} else { } else {
verbose("No user has configured their AP > 0\n"); verbose("No user has configured their AP > 0\n");
} }
// Mark this job as inactive
$setting->setValue('auto_payout_active', 0);
?>

View File

@ -39,9 +39,8 @@ if ( $bitcoin->can_connect() === true ){
// Nothing to do so bail out // Nothing to do so bail out
if (empty($aTransactions['transactions'])) { if (empty($aTransactions['transactions'])) {
verbose("No new transactions since last block\n"); verbose("No new RPC transactions since last block\n");
} else { } else {
// Table header // Table header
verbose("Blockhash\t\tHeight\tAmount\tConfirmations\tDiff\t\tTime\t\t\tStatus\n"); verbose("Blockhash\t\tHeight\tAmount\tConfirmations\tDiff\t\tTime\t\t\tStatus\n");
@ -66,36 +65,67 @@ if (empty($aTransactions['transactions'])) {
} }
} }
verbose("\n");
// Now with our blocks added we can scan for their upstream shares // Now with our blocks added we can scan for their upstream shares
$aAllBlocks = $block->getAllUnaccounted('ASC'); $aAllBlocks = $block->getAllUnaccounted('ASC');
if (empty($aAllBlocks)) {
verbose("No new unaccounted blocks found\n");
} else {
// Loop through our unaccounted blocks
verbose("\nBlock ID\tBlock Height\tShare ID\tShares\tFinder\t\t\tStatus\n");
foreach ($aAllBlocks as $iIndex => $aBlock) {
if (empty($aBlock['share_id'])) {
// Fetch this blocks upstream ID
if ($share->setUpstream($block->getLastUpstreamId())) {
$iCurrentUpstreamId = $share->getUpstreamId();
$iAccountId = $user->getUserId($share->getUpstreamFinder());
} else {
verbose("\nUnable to fetch blocks upstream share. Aborting!\n");
verbose($share->getError() . "\n");
exit;
}
// Fetch share information
if (!$iPreviousShareId = $block->getLastShareId()) {
$iPreviousShareId = 0;
verbose("\nUnable to find highest share ID found so far\n");
verbose("If this is your first block, this is normal\n\n");
}
$iRoundShares = $share->getRoundShares($iPreviousShareId, $iCurrentUpstreamId);
// Loop through our unaccounted blocks // Store new information
verbose("Block ID\tBlock Height\tShare ID\tFinder\t\t\tStatus\n"); $strStatus = "OK";
foreach ($aAllBlocks as $iIndex => $aBlock) { if (!$block->setShareId($aBlock['id'], $iCurrentUpstreamId))
if (empty($aBlock['share_id'])) { $strStatus = "Share ID Failed";
// Fetch this blocks upstream ID if (!$block->setFinder($aBlock['id'], $iAccountId))
if ($share->setUpstream($block->getLastUpstreamId())) { $strStatus = "Finder Failed";
$iCurrentUpstreamId = $share->getUpstreamId(); if (!$block->setShares($aBlock['id'], $iRoundShares))
$iAccountId = $user->getUserId($share->getUpstreamFinder()); $strStatus = "Shares Failed";
} else { if ($config['block_bonus'] > 0 && !$transaction->addTransaction($iAccountId, $config['block_bonus'], 'Bonus', $aBlock['id'])) {
verbose("Unable to fetch blocks upstream share\n"); $strStatus = "Bonus Failed";
verbose($share->getError() . "\n"); }
continue;
verbose(
$aBlock['id'] . "\t\t"
. $aBlock['height'] . "\t\t"
. $iCurrentUpstreamId . "\t\t"
. $iRoundShares . "\t"
. "[$iAccountId] " . $user->getUserName($iAccountId) . "\t\t"
. $strStatus
. "\n"
);
// Notify users
$aAccounts = $notification->getNotificationAccountIdByType('new_block');
if (is_array($aAccounts)) {
foreach ($aAccounts as $aData) {
$aMailData['height'] = $aBlock['height'];
$aMailData['subject'] = 'New Block';
$aMailData['email'] = $user->getUserEmail($user->getUserName($aData['account_id']));
$aMailData['shares'] = $iRoundShares;
$notification->sendNotification($aData['account_id'], 'new_block', $aMailData);
}
}
} }
// Store new information
$strStatus = "OK";
if (!$block->setShareId($aBlock['id'], $iCurrentUpstreamId))
$strStatus = "Share ID Failed";
if (!$block->setFinder($aBlock['id'], $iAccountId))
$strStatus = "Finder Failed";
verbose(
$aBlock['id'] . "\t\t"
. $aBlock['height'] . "\t\t"
. $iCurrentUpstreamId . "\t\t"
. "[$iAccountId] " . $user->getUserName($iAccountId) . "\t\t"
. $strStatus
. "\n"
);
} }
} }
?> ?>

56
cronjobs/notifications.php Executable file
View File

@ -0,0 +1,56 @@
#!/usr/bin/php
<?php
/*
Copyright:: 2013, Sebastian Grewe
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Include all settings and classes
require_once('shared.inc.php');
// Find all IDLE workers
$aWorkers = $worker->getAllIdleWorkers();
if (empty($aWorkers)) {
verbose("No idle workers found\n");
} else {
foreach ($aWorkers as $aWorker) {
$aData = $aWorker;
$aData['username'] = $user->getUserName($aWorker['account_id']);
$aData['subject'] = 'IDLE Worker : ' . $aWorker['username'];
$aData['worker'] = $aWorker['username'];
$aData['email'] = $user->getUserEmail($aData['username']);
if (!$notification->sendNotification($aWorker['account_id'], 'idle_worker', $aData))
verbose($notification->getError() . "\n");
}
}
// We notified, lets check which recovered
$aNotifications = $notification->getAllActive('idle_worker');
if (!empty($aNotifications)) {
foreach ($aNotifications as $aNotification) {
$aData = json_decode($aNotification['data'], true);
$aWorker = $worker->getWorker($aData['id']);
if ($aWorker['active'] == 1) {
if ($notification->setInactive($aNotification['id'])) {
verbose("Marked notification " . $aNotification['id'] . " as inactive\n");
} else {
verbose("Failed to set notification inactive for " . $aWorker['username'] . "\n");
}
}
}
}
?>

127
cronjobs/pps_payout.php Executable file
View File

@ -0,0 +1,127 @@
#!/usr/bin/php
<?php
/*
Copyright:: 2013, Sebastian Grewe
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Include all settings and classes
require_once('shared.inc.php');
// Check if we are set as the payout system
if ($config['payout_system'] != 'pps') {
verbose("Please activate this cron in configuration via payout_system = pps\n");
exit(0);
}
// Fetch all transactions since our last block
if ( $bitcoin->can_connect() === true ){
$dDifficulty = $bitcoin->getdifficulty();
} else {
verbose("Aborted: " . $bitcoin->can_connect() . "\n");
exit(1);
}
// Value per share calculation
$pps_value = number_format(round(50 / (pow(2,32) * $dDifficulty) * pow(2, $config['difficulty']), 12) ,12);
// Find our last share accounted and last inserted share for PPS calculations
$iPreviousShareId = $setting->getValue('pps_last_share_id');
$iLastShareId = $share->getLastInsertedShareId();
// Check for all new shares, we start one higher as our last accounted share to avoid duplicates
$aAccountShares = $share->getSharesForAccounts($iPreviousShareId + 1, $iLastShareId);
verbose("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\tPayout\t\tDonation\tFee\t\tStatus\n");
foreach ($aAccountShares as $aData) {
// Take our valid shares and multiply by per share value
$aData['payout'] = number_format(round($aData['valid'] * $pps_value, 8), 8);
// Defaults
$aData['fee' ] = 0;
$aData['donation'] = 0;
// Calculate block fees
if ($config['fees'] > 0)
$aData['fee'] = number_format(round($config['fees'] / 100 * $aData['payout'], 8), 8);
// Calculate donation amount
$aData['donation'] = number_format(round($user->getDonatePercent($user->getUserId($aData['username'])) / 100 * ( $aData['payout'] - $aData['fee']), 8), 8);
verbose($aData['id'] . "\t" .
$aData['username'] . "\t" .
$aData['invalid'] . "\t" .
$aData['valid'] . "\t*\t" .
$pps_value . "\t=\t" .
$aData['payout'] . "\t" .
$aData['donation'] . "\t" .
$aData['fee'] . "\t");
$strStatus = "OK";
// Add new credit transaction
if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit_PPS'))
$strStatus = "Transaction Failed";
// Add new fee debit for this block
if ($aData['fee'] > 0 && $config['fees'] > 0)
if (!$transaction->addTransaction($aData['id'], $aData['fee'], 'Fee_PPS'))
$strStatus = "Fee Failed";
// Add new donation debit
if ($aData['donation'] > 0)
if (!$transaction->addTransaction($aData['id'], $aData['donation'], 'Donation_PPS'))
$strStatus = "Donation Failed";
verbose($strStatus . "\n");
}
// Store our last inserted ID for the next run
$setting->setValue('pps_last_share_id', $iLastShareId);
verbose("\n\n------------------------------------------------------------------------------------\n\n");
// Fetch all unaccounted blocks
$aAllBlocks = $block->getAllUnaccounted('ASC');
if (empty($aAllBlocks)) {
verbose("No new unaccounted blocks found\n");
}
// Go through blocks and archive/delete shares that have been accounted for
foreach ($aAllBlocks as $iIndex => $aBlock) {
// If we are running through more than one block, check for previous share ID
$iLastBlockShare = @$aAllBlocks[$iIndex - 1]['share_id'] ? @$aAllBlocks[$iIndex - 1]['share_id'] : 0;
// Per account statistics
$aAccountShares = $share->getSharesForAccounts(@$iLastBlockShare, $aBlock['share_id']);
foreach ($aAccountShares as $key => $aData) {
if (!$statistics->updateShareStatistics($aData, $aBlock['id']))
verbose("Failed to update stats for this block on : " . $aData['username'] . "\n");
}
// Move shares to archive
if ($config['archive_shares'] && $aBlock['share_id'] < $iLastShareId) {
if (!$share->moveArchive($aBlock['share_id'], $aBlock['id'], @$iLastBlockShare))
verbose("Archving failed\n");
}
// Delete shares
if ($aBlock['share_id'] < $iLastShareId && !$share->deleteAccountedShares($aBlock['share_id'], $iLastBlockShare)) {
verbose("\nERROR : Failed to delete accounted shares from " . $aBlock['share_id'] . " to " . $iLastBlockShare . ", aborting!\n");
exit(1);
}
// Mark this block as accounted for
if (!$block->setAccounted($aBlock['id'])) {
verbose("\nERROR : Failed to mark block as accounted! Aborting!\n");
exit(1);
}
}
?>

View File

@ -22,6 +22,12 @@ limitations under the License.
// Include all settings and classes // Include all settings and classes
require_once('shared.inc.php'); require_once('shared.inc.php');
// Check if we are set as the payout system
if ($config['payout_system'] != 'prop') {
verbose("Please activate this cron in configuration via payout_system = prop\n");
exit(0);
}
// Fetch all unaccounted blocks // Fetch all unaccounted blocks
$aAllBlocks = $block->getAllUnaccounted('ASC'); $aAllBlocks = $block->getAllUnaccounted('ASC');
if (empty($aAllBlocks)) { if (empty($aAllBlocks)) {
@ -32,25 +38,16 @@ if (empty($aAllBlocks)) {
$count = 0; $count = 0;
foreach ($aAllBlocks as $iIndex => $aBlock) { foreach ($aAllBlocks as $iIndex => $aBlock) {
if (!$aBlock['accounted']) { if (!$aBlock['accounted']) {
$iPreviousShareId = $aAllBlocks[$iIndex - 1]['share_id'] ? $aAllBlocks[$iIndex - 1]['share_id'] : 0; $iPreviousShareId = @$aAllBlocks[$iIndex - 1]['share_id'] ? $aAllBlocks[$iIndex - 1]['share_id'] : 0;
$iCurrentUpstreamId = $aBlock['share_id']; $iCurrentUpstreamId = $aBlock['share_id'];
$aAccountShares = $share->getSharesForAccounts($iPreviousShareId, $aBlock['share_id']); $aAccountShares = $share->getSharesForAccounts($iPreviousShareId, $aBlock['share_id']);
$iRoundShares = $share->getRoundShares($iPreviousShareId, $aBlock['share_id']); $iRoundShares = $share->getRoundShares($iPreviousShareId, $aBlock['share_id']);
// Table header for block details
verbose("ID\tHeight\tTime\t\tShares\tFinder\t\tShare ID\tPrev Share\t\tStatus\n");
verbose($aBlock['id'] . "\t" . $aBlock['height'] . "\t" . $aBlock['time'] . "\t" . $iRoundShares . "\t" . $user->getUserName($aBlock['account_id']) . "\t" . $iCurrentUpstreamId . "\t\t" . $iPreviousShareId);
if (empty($aAccountShares)) { if (empty($aAccountShares)) {
verbose("\nNo shares found for this block\n\n"); verbose("\nNo shares found for this block\n\n");
sleep(2); sleep(2);
continue; continue;
} }
$strStatus = "OK";
// Store share information for this block
if (!$block->setShares($aBlock['id'], $iRoundShares))
$strStatus = "Shares Failed";
verbose("\t\t$strStatus\n\n");
// Table header for account shares // Table header for account shares
verbose("ID\tUsername\tValid\tInvalid\tPercentage\tPayout\t\tDonation\tFee\t\tStatus\n"); verbose("ID\tUsername\tValid\tInvalid\tPercentage\tPayout\t\tDonation\tFee\t\tStatus\n");

View File

@ -16,7 +16,7 @@ PIDFILE='/tmp/mmcfe-ng-cron.pid'
CRONHOME='.' CRONHOME='.'
# List of cruns to execute # List of cruns to execute
CRONS="findblock.php proportional_payout.php blockupdate.php auto_payout.php tickerupdate.php" CRONS="findblock.php proportional_payout.php pps_payout.php blockupdate.php auto_payout.php tickerupdate.php notifications.php statistics.php"
# Additional arguments to pass to cronjobs # Additional arguments to pass to cronjobs
CRONARGS="-v" CRONARGS="-v"

View File

@ -26,10 +26,10 @@ define("BASEPATH", "../public/");
define("SECURITY", 1); define("SECURITY", 1);
// Include our configuration (holding defines for the requires) // Include our configuration (holding defines for the requires)
require_once(BASEPATH . '/include/config/global.inc.php'); require_once(BASEPATH . 'include/config/global.inc.php');
// We include all needed files here, even though our templates could load them themself // We include all needed files here, even though our templates could load them themself
require_once(BASEPATH . INCLUDE_DIR . '/autoloader.inc.php'); require_once(INCLUDE_DIR . '/autoloader.inc.php');
// Parse command line // Parse command line
$options = getopt("v"); $options = getopt("v");

49
cronjobs/statistics.php Executable file
View File

@ -0,0 +1,49 @@
#!/usr/bin/php
<?php
/*
Copyright:: 2013, Sebastian Grewe
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Include all settings and classes
require_once('shared.inc.php');
// Fetch all cachable values but disable fetching from cache
$statistics->setGetCache(false);
// Since fetching from cache is disabled, overwrite our stats
if (!$statistics->getRoundShares())
verbose("Unable to fetch and store current round shares\n");
if (!$statistics->getTopContributors('shares'))
verbose("Unable to fetch and store top share contributors\n");
if (!$statistics->getTopContributors('hashes'))
verbose("Unable to fetch and store top hashrate contributors\n");
if (!$statistics->getCurrentHashrate())
verbose("Unable to fetch and store pool hashrate\n");
// Admin specific statistics, we cache the global query due to slowness
if (!$statistics->getAllUserStats('%'))
verbose("Unable to fetch and store admin panel full user list\n");
// Per user share statistics based on all shares submitted
$stmt = $mysqli->prepare("SELECT DISTINCT SUBSTRING_INDEX( `username` , '.', 1 ) AS username FROM " . $share->getTableName());
if ($stmt && $stmt->execute() && $result = $stmt->get_result()) {
while ($row = $result->fetch_assoc()) {
if (!$statistics->getUserShares($user->getUserId($row['username'])))
verbose("Failed to fetch and store user stats for " . $row['username'] . "\n");
}
}
?>

View File

@ -14,3 +14,5 @@ require_once(CLASS_DIR . '/worker.class.php');
require_once(CLASS_DIR . '/statistics.class.php'); require_once(CLASS_DIR . '/statistics.class.php');
require_once(CLASS_DIR . '/transaction.class.php'); require_once(CLASS_DIR . '/transaction.class.php');
require_once(CLASS_DIR . '/setting.class.php'); require_once(CLASS_DIR . '/setting.class.php');
require_once(CLASS_DIR . '/mail.class.php');
require_once(CLASS_DIR . '/notification.class.php');

View File

@ -246,8 +246,8 @@ class BitcoinClientException extends ErrorException {
} }
} }
require_once(BASEPATH . INCLUDE_DIR . "/xmlrpc.inc.php"); require_once(INCLUDE_DIR . "/xmlrpc.inc.php");
require_once(BASEPATH . INCLUDE_DIR . "/jsonrpc.inc.php"); require_once(INCLUDE_DIR . "/jsonrpc.inc.php");
/** /**
* Bitcoin client class for access to a Bitcoin server via JSON-RPC-HTTP[S] * Bitcoin client class for access to a Bitcoin server via JSON-RPC-HTTP[S]

View File

@ -43,6 +43,18 @@ class Block {
return false; return false;
} }
/**
* Get our last, highest share ID inserted for a block
* @param none
* @return int data Share ID
**/
public function getLastShareId() {
$stmt = $this->mysqli->prepare("SELECT MAX(share_id) AS share_id FROM $this->table LIMIT 1");
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_object()->share_id;
return false;
}
/** /**
* Fetch all unaccounted blocks * Fetch all unaccounted blocks
* @param order string Sort order, default ASC * @param order string Sort order, default ASC

View File

@ -0,0 +1,67 @@
<?php
// Make sure we are called from index.php
if (!defined('SECURITY'))
die('Hacking attempt');
class Mail {
private $sError = '';
public function setDebug($debug) {
$this->debug = $debug;
}
public function setMysql($mysqli) {
$this->mysqli = $mysqli;
}
public function setSmarty($smarty) {
$this->smarty = $smarty;
}
public function setUser($user) {
$this->user = $user;
}
public function setConfig($config) {
$this->config = $config;
}
public function setErrorMessage($msg) {
$this->sError = $msg;
}
public function getError() {
return $this->sError;
}
function checkStmt($bState) {
$this->debug->append("STA " . __METHOD__, 4);
if ($bState ===! true) {
$this->debug->append("Failed to prepare statement: " . $this->mysqli->error);
$this->setErrorMessage('Internal application Error');
return false;
}
return true;
}
public function sendMail($template, $aData) {
$this->smarty->assign('WEBSITENAME', $this->config['website']['name']);
$this->smarty->assign('SUBJECT', $aData['subject']);
$this->smarty->assign('DATA', $aData);
$headers = 'From: Website Administration <' . $this->config['website']['email'] . ">\n";
$headers .= "MIME-Version: 1.0\n";
$headers .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
if (mail($aData['email'],
$this->smarty->fetch(BASEPATH . 'templates/mail/subject.tpl'),
$this->smarty->fetch(BASEPATH . 'templates/mail/' . $template . '.tpl'),
$headers)) {
return true;
} else {
$this->setErrorMessage("Unable to send mail");
return false;
}
return false;
}
}
// Make our class available automatically
$mail = new Mail ();
$mail->setDebug($debug);
$mail->setMysql($mysqli);
$mail->setSmarty($smarty);
$mail->setConfig($config);
?>

View File

@ -0,0 +1,191 @@
<?php
// Make sure we are called from index.php
if (!defined('SECURITY'))
die('Hacking attempt');
class Notification extends Mail {
var $table = 'notifications';
var $tableSettings = 'notification_settings';
public function setInactive($id) {
$field = array(
'name' => 'active',
'type' => 'i',
'value' => 0
);
return $this->updateSingle($id, $field);
}
/**
* Update a single row in a table
* @param userID int Account ID
* @param field string Field to update
* @return bool
**/
private function updateSingle($id, $field, $table='') {
if (empty($table)) $table = $this->table;
$this->debug->append("STA " . __METHOD__, 4);
$stmt = $this->mysqli->prepare("UPDATE $table SET " . $field['name'] . " = ? WHERE id = ? LIMIT 1");
if ($this->checkStmt($stmt) && $stmt->bind_param($field['type'].'i', $field['value'], $id) && $stmt->execute())
return true;
$this->debug->append("Unable to update " . $field['name'] . " with " . $field['value'] . " for ID $id");
return false;
}
/**
* We check our notification table for existing data
* so we can avoid duplicate entries
**/
public function isNotified($aData) {
$this->debug->append("STA " . __METHOD__, 4);
$data = json_encode($aData);
$stmt = $this->mysqli->prepare("SELECT id FROM $this->table WHERE data = ? AND active = 1 LIMIT 1");
if ($stmt && $stmt->bind_param('s', $data) && $stmt->execute() && $stmt->store_result() && $stmt->num_rows == 1)
return true;
// Catchall
// Does not seem to have a notification set
return false;
}
/**
* Get all active notifications
**/
public function getAllActive($strType) {
$this->debug->append("STA " . __METHOD__, 4);
$stmt =$this->mysqli->prepare("SELECT id, data FROM $this->table WHERE active = 1 AND type = ?");
if ($stmt && $stmt->bind_param('s', $strType) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_all(MYSQLI_ASSOC);
// Catchall
return false;
}
/**
* Add a new notification to the table
* @param type string Type of the notification
* @return bool
**/
public function addNotification($account_id, $type, $data) {
$this->debug->append("STA " . __METHOD__, 4);
// Store notification data as json
$data = json_encode($data);
$stmt = $this->mysqli->prepare("INSERT INTO $this->table (account_id, type, data, active) VALUES (?, ?,?,1)");
if ($stmt && $stmt->bind_param('iss', $account_id, $type, $data) && $stmt->execute())
return true;
$this->debug->append("Failed to add notification for $type with $data: " . $this->mysqli->error);
$this->setErrorMessage("Unable to add new notification " . $this->mysqli->error);
return false;
}
/**
* Fetch notifications for a user account
* @param id int Account ID
* @return array Notification data
**/
public function getNofifications($account_id) {
$this->debug->append("STA " . __METHOD__, 4);
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE account_id = ? ORDER BY time DESC");
if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_all(MYSQLI_ASSOC);
// Catchall
return false;
}
/**
* Fetch notification settings for user account
* @param id int Account ID
* @return array Notification settings
**/
public function getNotificationSettings($account_id) {
$this->debug->append("STA " . __METHOD__, 4);
$stmt = $this->mysqli->prepare("SELECT * FROM $this->tableSettings WHERE account_id = ?");
if ($stmt && $stmt->bind_param('i', $account_id) && $stmt->execute() && $result = $stmt->get_result()) {
while ($row = $result->fetch_assoc()) {
$aData[$row['type']] = $row['active'];
}
return $aData;
}
// Catchall
return false;
}
/**
* Get all accounts that wish to receive a specific notification
* @param strType string Notification type
* @return data array User Accounts
**/
public function getNotificationAccountIdByType($strType) {
$this->debug->append("STA " . __METHOD__, 4);
$stmt = $this->mysqli->prepare("SELECT account_id FROM $this->tableSettings WHERE type = ? AND active = 1");
if ($stmt && $stmt->bind_param('s', $strType) && $stmt->execute() && $result = $stmt->get_result()) {
return $result->fetch_all(MYSQLI_ASSOC);
}
// Catchall
return false;
}
/**
* Update accounts notification settings
* @param account_id int Account ID
* @param data array Data array
* @return bool
**/
public function updateSettings($account_id, $data) {
$this->debug->append("STA " . __METHOD__, 4);
$failed = $ok = 0;
foreach ($data as $type => $active) {
// Does an entry exist already
$stmt = $this->mysqli->prepare("SELECT * FROM $this->tableSettings WHERE account_id = ? AND type = ?");
if ($stmt && $stmt->bind_param('is', $account_id, $type) && $stmt->execute() && $stmt->store_result() && $stmt->num_rows() > 0) {
// We found a matching row
$stmt = $this->mysqli->prepare("UPDATE $this->tableSettings SET active = ? WHERE type = ? AND account_id = ?");
if ($stmt && $stmt->bind_param('isi', $active, $type, $account_id) && $stmt->execute() && $stmt->close()) {
$ok++;
} else {
$failed++;
}
} else {
$stmt = $this->mysqli->prepare("INSERT INTO $this->tableSettings (active, type, account_id) VALUES (?,?,?)");
if ($stmt && $stmt->bind_param('isi', $active, $type, $account_id) && $stmt->execute()) {
$ok++;
} else {
$failed++;
}
}
}
if ($failed > 0) {
$this->setErrorMessage('Failed to update ' . $failed . ' settings');
return false;
}
return true;
}
/**
* Send a specific notification setup in notification_settings
* @param type string Notification type
* @return bool
**/
public function sendNotification($account_id, $strType, $aMailData) {
// Check if we notified for this event already
if ( $this->isNotified($aMailData) ) {
$this->setErrorMessage('A notification for this event has been sent already');
return false;
}
// Check if this user wants strType notifications
$stmt = $this->mysqli->prepare("SELECT account_id FROM $this->tableSettings WHERE type = ? AND active = 1 AND account_id = ?");
if ($stmt && $stmt->bind_param('si', $strType, $account_id) && $stmt->execute() && $stmt->bind_result($id) && $stmt->fetch()) {
if ($stmt->close() && $this->sendMail('notifications/' . $strType, $aMailData) && $this->addNotification($account_id, $strType, $aMailData))
return true;
} else {
$this->setErrorMessage('User disabled ' . $strType . ' notifications');
}
return false;
}
}
$notification = new Notification();
$notification->setDebug($debug);
$notification->setMysql($mysqli);
$notification->setSmarty($smarty);
$notification->setConfig($config);
?>

View File

@ -44,6 +44,21 @@ class Share {
return $this->table; return $this->table;
} }
/**
* Get last inserted Share ID from Database
* Used for PPS calculations without moving to archive
**/
public function getLastInsertedShareId() {
$stmt = $this->mysqli->prepare("
SELECT MAX(id) AS id FROM $this->table
");
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_object()->id;
// Catchall
$this->setErrorMessage('Failed to fetch last inserted share ID');
return false;
}
/** /**
* Get all valid shares for this round * Get all valid shares for this round
* @param previous_upstream int Previous found share accepted by upstream to limit results * @param previous_upstream int Previous found share accepted by upstream to limit results
@ -172,7 +187,8 @@ class Share {
ORDER BY id ASC LIMIT 1"); ORDER BY id ASC LIMIT 1");
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $last) && $stmt->execute() && $result = $stmt->get_result()) { if ($this->checkStmt($stmt) && $stmt->bind_param('i', $last) && $stmt->execute() && $result = $stmt->get_result()) {
$this->oUpstream = $result->fetch_object(); $this->oUpstream = $result->fetch_object();
return true; if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id))
return true;
} }
// Catchall // Catchall
return false; return false;

View File

@ -13,6 +13,7 @@ if (!defined('SECURITY'))
class Statistics { class Statistics {
private $sError = ''; private $sError = '';
private $table = 'statistics_shares'; private $table = 'statistics_shares';
private $getcache = true;
public function __construct($debug, $mysqli, $config, $share, $user, $block, $memcache) { public function __construct($debug, $mysqli, $config, $share, $user, $block, $memcache) {
$this->debug = $debug; $this->debug = $debug;
@ -34,6 +35,14 @@ class Statistics {
return $this->sError; return $this->sError;
} }
// Disable fetching values from cache
public function setGetCache($set=false) {
$this->getcache = $set;
}
public function getGetCache() {
return $this->getcache;
}
private function checkStmt($bState) { private function checkStmt($bState) {
if ($bState ===! true) { if ($bState ===! true) {
$this->debug->append("Failed to prepare statement: " . $this->mysqli->error); $this->debug->append("Failed to prepare statement: " . $this->mysqli->error);
@ -54,7 +63,7 @@ class Statistics {
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT b.*, a.username as finder SELECT b.*, a.username as finder
FROM " . $this->block->getTableName() . " AS b FROM " . $this->block->getTableName() . " AS b
LEFT JOIN accounts AS a LEFT JOIN " . $this->user->getTableName() . " AS a
ON b.account_id = a.id ON b.account_id = a.id
ORDER BY height DESC LIMIT ?"); ORDER BY height DESC LIMIT ?");
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result()) if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result())
@ -88,14 +97,10 @@ class Statistics {
**/ **/
public function getCurrentHashrate() { public function getCurrentHashrate() {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
if ($data = $this->memcache->get(__FUNCTION__)) return $data; if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__)) return $data;
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT SUM(hashrate) AS hashrate FROM SELECT ROUND(COUNT(id) * POW(2, " . $this->config['difficulty'] . ")/600/1000) AS hashrate FROM " . $this->share->getTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE)
( ");
SELECT ROUND(COUNT(id) * POW(2, " . $this->config['difficulty'] . ")/600/1000) AS hashrate FROM " . $this->share->getTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE)
UNION
SELECT ROUND(COUNT(id) * POW(2, " . $this->config['difficulty'] . ")/600/1000) AS hashrate FROM " . $this->share->getArchiveTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE)
) AS sum");
// Catchall // Catchall
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->hashrate); if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->hashrate);
$this->debug->append("Failed to get hashrate: " . $this->mysqli->error); $this->debug->append("Failed to get hashrate: " . $this->mysqli->error);
@ -111,12 +116,8 @@ class Statistics {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
if ($data = $this->memcache->get(__FUNCTION__)) return $data; if ($data = $this->memcache->get(__FUNCTION__)) return $data;
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT ROUND(SUM(sharerate) / 600, 2) AS sharerate FROM SELECT ROUND(COUNT(id) / 600, 2) AS sharerate FROM " . $this->share->getTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE)
( ");
SELECT COUNT(id) AS sharerate FROM " . $this->share->getTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE)
UNION ALL
SELECT COUNT(id) AS sharerate FROM " . $this->share->getArchiveTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE)
) AS sum");
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->sharerate); if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->sharerate);
// Catchall // Catchall
$this->debug->append("Failed to fetch share rate: " . $this->mysqli->error); $this->debug->append("Failed to fetch share rate: " . $this->mysqli->error);
@ -130,7 +131,7 @@ class Statistics {
**/ **/
public function getRoundShares() { public function getRoundShares() {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
if ($data = $this->memcache->get(__FUNCTION__)) return $data; if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__)) return $data;
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT SELECT
( SELECT IFNULL(count(id), 0) ( SELECT IFNULL(count(id), 0)
@ -155,7 +156,7 @@ class Statistics {
**/ **/
public function getUserShares($account_id) { public function getUserShares($account_id) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT SELECT
( (
@ -183,12 +184,42 @@ class Statistics {
return false; return false;
} }
/**
* Admin panel specific query
* @return data array invlid and valid shares for all accounts
**/
public function getAllUserStats($filter='%') {
$this->debug->append("STA " . __METHOD__, 4);
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $filter)) return $data;
$stmt = $this->mysqli->prepare("
SELECT
a.id AS id,
a.is_admin as is_admin,
a.is_locked as is_locked,
a.username AS username,
a.donate_percent AS donate_percent,
a.email AS email,
COUNT(s.id) AS shares
FROM " . $this->user->getTableName() . " AS a
LEFT JOIN " . $this->share->getTableName() . " AS s
ON a.username = SUBSTRING_INDEX( s.username, '.', 1 )
WHERE
a.username LIKE ?
GROUP BY username
ORDER BY username
");
if ($this->checkStmt($stmt) && $stmt->bind_param('s', $filter) && $stmt->execute() && $result = $stmt->get_result()) {
return $this->memcache->setCache(__FUNCTION__ . $filter, $result->fetch_all(MYSQLI_ASSOC));
}
}
/** /**
* Same as getUserShares for Hashrate * Same as getUserShares for Hashrate
* @param account_id integer User ID * @param account_id integer User ID
* @return data integer Current Hashrate in khash/s * @return data integer Current Hashrate in khash/s
**/ **/
public function getUserHashrate($account_id) { public function getUserHashrate($account_id) {
$this->debug->append("STA " . __METHOD__, 4);
if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT ROUND(COUNT(s.id) * POW(2, " . $this->config['difficulty'] . ")/600/1000) AS hashrate SELECT ROUND(COUNT(s.id) * POW(2, " . $this->config['difficulty'] . ")/600/1000) AS hashrate
@ -204,6 +235,28 @@ class Statistics {
return false; return false;
} }
/**
* Same as getUserHashrate for Sharerate
* @param account_id integer User ID
* @return data integer Current Sharerate in shares/s
**/
public function getUserSharerate($account_id) {
$this->debug->append("STA " . __METHOD__, 4);
if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
$stmt = $this->mysqli->prepare("
SELECT COUNT(s.id)/600 AS sharerate
FROM " . $this->share->getTableName() . " AS s,
" . $this->user->getTableName() . " AS u
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 )
AND s.time > DATE_SUB(now(), INTERVAL 10 MINUTE)
AND u.id = ?");
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $account_id) && $stmt->execute() && $result = $stmt->get_result() )
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->sharerate);
// Catchall
$this->debug->append("Failed to fetch sharerate: " . $this->mysqli->error);
return false;
}
/** /**
* Get hashrate for a specific worker * Get hashrate for a specific worker
* @param worker_id int Worker ID to fetch hashrate for * @param worker_id int Worker ID to fetch hashrate for
@ -234,7 +287,7 @@ class Statistics {
**/ **/
public function getTopContributors($type='shares', $limit=15) { public function getTopContributors($type='shares', $limit=15) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
if ($data = $this->memcache->get(__FUNCTION__ . $type . $limit)) return $data; if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $type . $limit)) return $data;
switch ($type) { switch ($type) {
case 'shares': case 'shares':
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
@ -242,6 +295,7 @@ class Statistics {
COUNT(id) AS shares, COUNT(id) AS shares,
SUBSTRING_INDEX( username, '.', 1 ) AS account SUBSTRING_INDEX( username, '.', 1 ) AS account
FROM " . $this->share->getTableName() . " FROM " . $this->share->getTableName() . "
WHERE our_result = 'Y'
GROUP BY account GROUP BY account
ORDER BY shares DESC ORDER BY shares DESC
LIMIT ?"); LIMIT ?");
@ -258,6 +312,7 @@ class Statistics {
SUBSTRING_INDEX( username, '.', 1 ) AS account SUBSTRING_INDEX( username, '.', 1 ) AS account
FROM " . $this->share->getTableName() . " FROM " . $this->share->getTableName() . "
WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE) WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE)
AND our_result = 'Y'
GROUP BY account GROUP BY account
ORDER BY hashrate DESC LIMIT ?"); ORDER BY hashrate DESC LIMIT ?");
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result()) if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result())
@ -270,7 +325,6 @@ class Statistics {
/** /**
* get Hourly hashrate for a user * get Hourly hashrate for a user
* Not working yet since I was not able to solve this via SQL queries
* @param account_id int User ID * @param account_id int User ID
* @return data array NOT FINISHED YET * @return data array NOT FINISHED YET
**/ **/
@ -279,24 +333,50 @@ class Statistics {
if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT SELECT
ROUND(COUNT(s.id) * POW(2, 12)/600/1000) AS hashrate, ROUND(COUNT(s.id) * POW(2, " . $this->config['difficulty'] . ") / 3600 / 1000) AS hashrate,
HOUR(s.time) AS hour HOUR(s.time) AS hour
FROM " . $this->share->getTableName() . " AS s, accounts AS a FROM " . $this->share->getTableName() . " AS s, accounts AS a
WHERE time < NOW() - INTERVAL 1 HOUR AND time > NOW() - INTERVAL 25 HOUR WHERE time < NOW() - INTERVAL 1 HOUR
AND time > NOW() - INTERVAL 25 HOUR
AND a.username = SUBSTRING_INDEX( s.username, '.', 1 ) AND a.username = SUBSTRING_INDEX( s.username, '.', 1 )
AND a.id = ? AND a.id = ?
GROUP BY HOUR(time) GROUP BY HOUR(time)
UNION ALL ");
SELECT if ($this->checkStmt($stmt) && $stmt->bind_param("i", $account_id) && $stmt->execute() && $result = $stmt->get_result()) {
ROUND(COUNT(s.id) * POW(2, 12)/600/1000) AS hashrate, $aData = array();
HOUR(s.time) AS hour while ($row = $result->fetch_assoc()) {
FROM " . $this->share->getArchiveTableName() . " AS s, accounts AS a $aData[$row['hour']] = $row['hashrate'];
WHERE time < NOW() - INTERVAL 1 HOUR AND time > NOW() - INTERVAL 25 HOUR }
AND a.username = SUBSTRING_INDEX( s.username, '.', 1 ) return $this->memcache->setCache(__FUNCTION__ . $account_id, $aData);
AND a.id = ? }
GROUP BY HOUR(time)"); // Catchall
if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $account_id, $account_id) && $stmt->execute() && $result = $stmt->get_result()) $this->debug->append("Failed to fetch hourly hashrate: " . $this->mysqli->error);
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_all(MYSQLI_ASSOC), 3600); return false;
}
/**
* get Hourly hashrate for the pool
* @param none
* @return data array NOT FINISHED YET
**/
public function getHourlyHashrateByPool() {
$this->debug->append("STA " . __METHOD__, 4);
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__)) return $data;
$stmt = $this->mysqli->prepare("
SELECT
ROUND(COUNT(s.id) * POW(2, " . $this->config['difficulty'] . ") / 3600 / 1000) AS hashrate,
HOUR(s.time) AS hour
FROM " . $this->share->getTableName() . " AS s
WHERE time < NOW() - INTERVAL 1 HOUR
AND time > NOW() - INTERVAL 25 HOUR
GROUP BY HOUR(time)
");
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result()) {
while ($row = $result->fetch_assoc()) {
$aData[$row['hour']] = $row['hashrate'];
}
return $this->memcache->setCache(__FUNCTION__, @$aData);
}
// Catchall // Catchall
$this->debug->append("Failed to fetch hourly hashrate: " . $this->mysqli->error); $this->debug->append("Failed to fetch hourly hashrate: " . $this->mysqli->error);
return false; return false;

View File

@ -55,35 +55,23 @@ class Transaction {
**/ **/
public function setOrphan($block_id) { public function setOrphan($block_id) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
$stmt = $this->mysqli->prepare(" $aOrphans = array(
UPDATE $this->table 'Credit' => 'Orphan_Credit',
SET type = 'Orphan_Credit' 'Fee' => 'Orphan_Fee',
WHERE type = 'Credit' 'Donation' => 'Orphan_Donation',
AND block_id = ? 'Bonus' => 'Orphan_Bonus'
"); );
if (!($this->checkStmt($stmt) && $stmt->bind_param('i', $block_id) && $stmt->execute())) { foreach ($aOrphans as $from => $to) {
$this->debug->append("Failed to set orphan credit transactions for $block_id"); $stmt = $this->mysqli->prepare("
return false; UPDATE $this->table
} SET type = '$to'
$stmt = $this->mysqli->prepare(" WHERE type = '$from'
UPDATE $this->table AND block_id = ?
SET type = 'Orphan_Fee' ");
WHERE type = 'Fee' if (!($this->checkStmt($stmt) && $stmt->bind_param('i', $block_id) && $stmt->execute())) {
AND block_id = ? $this->debug->append("Failed to set orphan $from => $to transactions for $block_id");
"); return false;
if (!($this->checkStmt($stmt) && $stmt->bind_param('i', $block_id) && $stmt->execute())) { }
$this->debug->append("Failed to set orphan fee transactions for $block_id");
return false;
}
$stmt = $this->mysqli->prepare("
UPDATE $this->table
SET type = 'Orphan_Donation'
WHERE type = 'Donation'
AND block_id = ?
");
if (!($this->checkStmt($stmt) && $stmt->bind_param('i', $block_id) && $stmt->execute())) {
$this->debug->append("Failed to set orphan donation transactions for $block_id");
return false;
} }
return true; return true;
} }
@ -130,6 +118,7 @@ class Transaction {
/** /**
* Get total balance for all users locked in wallet * Get total balance for all users locked in wallet
* This includes any outstanding unconfirmed transactions!
* @param none * @param none
* @return data double Amount locked for users * @return data double Amount locked for users
**/ **/
@ -142,8 +131,10 @@ class Transaction {
SELECT sum(t.amount) AS credit SELECT sum(t.amount) AS credit
FROM $this->table AS t FROM $this->table AS t
LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id
WHERE t.type = 'Credit' WHERE (
AND b.confirmations >= ? ( t.type IN ('Credit','Bonus') AND b.confirmations >= ? ) OR
( t.type = 'Credit_PPS' )
)
) AS t1, ) AS t1,
( (
SELECT sum(t.amount) AS debit SELECT sum(t.amount) AS debit
@ -152,10 +143,12 @@ class Transaction {
) AS t2, ) AS t2,
( (
SELECT sum(t.amount) AS other SELECT sum(t.amount) AS other
FROM transactions AS t FROM " . $this->table . " AS t
LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id
WHERE t.type IN ('Donation','Fee') WHERE (
AND b.confirmations >= ? ( t.type IN ('Donation','Fee') AND b.confirmations >= ? ) OR
t.type IN ('Donation_PPS','Fee_PPS','TXFee')
)
) AS t3"); ) AS t3");
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $this->config['confirmations'], $this->config['confirmations']) && $stmt->execute() && $stmt->bind_result($dBalance) && $stmt->fetch()) if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $this->config['confirmations'], $this->config['confirmations']) && $stmt->execute() && $stmt->bind_result($dBalance) && $stmt->fetch())
return $dBalance; return $dBalance;
@ -173,14 +166,19 @@ class Transaction {
public function getBalance($account_id) { public function getBalance($account_id) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT ROUND(IFNULL(t1.credit, 0) - IFNULL(t2.debit, 0) - IFNULL(t3.other, 0), 8) AS balance SELECT
ROUND(IFNULL(t1.credit, 0) - IFNULL(t2.debit, 0) - IFNULL(t3.other, 0), 8) AS confirmed,
ROUND(IFNULL(t4.credit, 0) - IFNULL(t5.other, 0), 8) AS unconfirmed
FROM FROM
( (
SELECT sum(t.amount) AS credit SELECT sum(t.amount) AS credit
FROM $this->table AS t FROM $this->table AS t
LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id
WHERE t.type = 'Credit' WHERE
AND b.confirmations >= ? (
( t.type IN ('Credit','Bonus') AND b.confirmations >= ? ) OR
( t.type = 'Credit_PPS' )
)
AND t.account_id = ? AND t.account_id = ?
) AS t1, ) AS t1,
( (
@ -193,20 +191,41 @@ class Transaction {
SELECT sum(t.amount) AS other SELECT sum(t.amount) AS other
FROM $this->table AS t FROM $this->table AS t
LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id
WHERE t.type IN ('Donation','Fee') WHERE
AND b.confirmations >= ? (
( t.type IN ('Donation','Fee') AND b.confirmations >= ? ) OR
( t.type IN ('Donation_PPS', 'Fee_PPS', 'TXFee') )
)
AND t.account_id = ? AND t.account_id = ?
) AS t3 ) AS t3,
(
SELECT sum(t.amount) AS credit
FROM $this->table AS t
LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id
WHERE
t.type IN ('Credit','Bonus') AND b.confirmations < ?
AND t.account_id = ?
) AS t4,
(
SELECT sum(t.amount) AS other
FROM $this->table AS t
LEFT JOIN " . $this->block->getTableName() . " AS b ON t.block_id = b.id
WHERE
(
t.type IN ('Donation','Fee') AND b.confirmations < ?
)
AND t.account_id = ?
) AS t5
"); ");
if ($this->checkStmt($stmt)) { if ($this->checkStmt($stmt)) {
$stmt->bind_param("iiiii", $this->config['confirmations'], $account_id, $account_id, $this->config['confirmations'], $account_id); $stmt->bind_param("iiiiiiiii", $this->config['confirmations'], $account_id, $account_id, $this->config['confirmations'], $account_id, $this->config['confirmations'], $account_id, $this->config['confirmations'], $account_id);
if (!$stmt->execute()) { if (!$stmt->execute()) {
$this->debug->append("Unable to execute statement: " . $stmt->error); $this->debug->append("Unable to execute statement: " . $stmt->error);
$this->setErrorMessage("Fetching balance failed"); $this->setErrorMessage("Fetching balance failed");
} }
$result = $stmt->get_result(); $result = $stmt->get_result();
$stmt->close(); $stmt->close();
return $result->fetch_object()->balance; return $result->fetch_assoc();
} }
return false; return false;
} }

View File

@ -26,35 +26,75 @@ class User {
public function getError() { public function getError() {
return $this->sError; return $this->sError;
} }
public function getUserName($id) { public function getUserName($id) {
return $this->getSingle($id, 'username', 'id'); return $this->getSingle($id, 'username', 'id');
} }
public function getUserId($username) { public function getUserId($username) {
return $this->getSingle($username, 'id', 'username', 's'); return $this->getSingle($username, 'id', 'username', 's');
} }
public function getUserEmail($username) { public function getUserEmail($username) {
return $this->getSingle($username, 'email', 'username', 's'); return $this->getSingle($username, 'email', 'username', 's');
} }
public function getUserAdmin($id) {
return $this->getSingle($id, 'is_admin', 'id');
}
public function getUserLocked($id) {
return $this->getSingle($id, 'is_locked', 'id');
}
public function getUserToken($id) { public function getUserToken($id) {
return $this->getSingle($id, 'token', 'id'); return $this->getSingle($id, 'token', 'id');
} }
public function getUserIp($id) {
return $this->getSingle($id, 'loggedIp', 'id');
}
public function getUserFailed($id) {
return $this->getSingle($id, 'failed_logins', 'id');
}
public function getIdFromToken($token) { public function getIdFromToken($token) {
return $this->getSingle($token, 'id', 'token', 's'); return $this->getSingle($token, 'id', 'token', 's');
} }
public function isLocked($id) {
public function setUserToken($id) { return $this->getUserLocked($id);
$field = array( }
'name' => 'token', public function isAdmin($id) {
'type' => 's', return $this->getUserAdmin($id);
'value' => hash('sha256', $id.time().$this->salt) }
); public function changeLocked($id) {
$field = array('name' => 'is_locked', 'type' => 'i', 'value' => !$this->isLocked($id));
return $this->updateSingle($id, $field); return $this->updateSingle($id, $field);
} }
public function changeAdmin($id) {
$field = array('name' => 'is_admin', 'type' => 'i', 'value' => !$this->isAdmin($id));
return $this->updateSingle($id, $field);
}
public function setUserToken($id) {
$field = array('name' => 'token', 'type' => 's', 'value' => hash('sha256', $id.time().$this->salt));
return $this->updateSingle($id, $field);
}
private function setUserFailed($id, $value) {
$field = array( 'name' => 'failed_logins', 'type' => 'i', 'value' => $value);
return $this->updateSingle($id, $field);
}
private function incUserFailed($id) {
$field = array( 'name' => 'failed_logins', 'type' => 'i', 'value' => $this->getUserFailed($id) + 1);
return $this->updateSingle($id, $field);
}
private function setUserIp($id, $ip) {
$field = array( 'name' => 'loggedIp', 'type' => 's', 'value' => $ip );
return $this->updateSingle($id, $field);
}
/**
* Fetch all users for administrative tasks
* @param none
* @return data array All users with db columns as array fields
**/
public function getUsers($filter='%') {
$stmt = $this->mysqli->prepare("SELECT * FROM " . $this->getTableName() . " WHERE username LIKE ?");
if ($this->checkStmt($stmt) && $stmt->bind_param('s', $filter) && $stmt->execute() && $result = $stmt->get_result()) {
return $result->fetch_all(MYSQLI_ASSOC);
}
}
/** /**
* Check user login * Check user login
@ -65,10 +105,20 @@ class User {
public function checkLogin($username, $password) { public function checkLogin($username, $password) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
$this->debug->append("Checking login for $username with password $password", 2); $this->debug->append("Checking login for $username with password $password", 2);
if ( $this->checkUserPassword($username, $password) ) { if ($this->isLocked($this->getUserId($username))) {
$this->setErrorMessage("Account is locked. Please contact site support.");
return false;
}
if ( $this->checkUserPassword($username, $password)) {
$this->createSession($username); $this->createSession($username);
$this->setUserFailed($this->getUserId($username), 0);
$this->setUserIp($this->getUserId($username), $_SERVER['REMOTE_ADDR']);
return true; return true;
} }
$this->setErrorMessage("Invalid username or password");
if ($id = $this->getUserId($username))
$this->incUserFailed($id);
return false; return false;
} }
@ -166,7 +216,7 @@ class User {
**/ **/
private function updateSingle($id, $field) { private function updateSingle($id, $field) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
$stmt = $this->mysqli->prepare("UPDATE $this->table SET " . $field['name'] . " = ? WHERE id = ? LIMIT 1"); $stmt = $this->mysqli->prepare("UPDATE $this->table SET `" . $field['name'] . "` = ? WHERE id = ? LIMIT 1");
if ($this->checkStmt($stmt) && $stmt->bind_param($field['type'].'i', $field['value'], $id) && $stmt->execute()) if ($this->checkStmt($stmt) && $stmt->bind_param($field['type'].'i', $field['value'], $id) && $stmt->execute())
return true; return true;
$this->debug->append("Unable to update " . $field['name'] . " with " . $field['value'] . " for ID $id"); $this->debug->append("Unable to update " . $field['name'] . " with " . $field['value'] . " for ID $id");
@ -224,20 +274,40 @@ class User {
* @param donat float donation % of income * @param donat float donation % of income
* @return bool * @return bool
**/ **/
public function updateAccount($userID, $address, $threshold, $donate) { public function updateAccount($userID, $address, $threshold, $donate, $email) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
$bUser = false; $bUser = false;
$threshold = min(250, max(0, floatval($threshold)));
if ($threshold < 1) $threshold = 0.0; // number validation checks
if ($threshold < $this->config['ap_threshold']['min'] && $threshold != 0) {
$this->setErrorMessage('Threshold below configured minimum of ' . $this->config['ap_threshold']['min']);
return false;
} else if ($threshold > $this->config['ap_threshold']['max']) {
$this->setErrorMessage('Threshold above configured maximum of ' . $this->config['ap_threshold']['max']);
return false;
}
if ($donate < 0) {
$this->setErrorMessage('Donation below allowed 0% limit');
return false;
} else if ($donate > 100) {
$this->setErrorMessage('Donation above allowed 100% limit');
return false;
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$this->setErrorMessage('Invalid email address');
return false;
}
// Number sanitizer, just in case we fall through above
$threshold = min($this->config['ap_threshold']['max'], max(0, floatval($threshold)));
$donate = min(100, max(0, floatval($donate))); $donate = min(100, max(0, floatval($donate)));
$stmt = $this->mysqli->prepare("UPDATE $this->table SET coin_address = ?, ap_threshold = ?, donate_percent = ? WHERE id = ?"); // We passed all validation checks so update the account
$stmt->bind_param('sddi', $address, $threshold, $donate, $userID); $stmt = $this->mysqli->prepare("UPDATE $this->table SET coin_address = ?, ap_threshold = ?, donate_percent = ?, email = ? WHERE id = ?");
$stmt->execute(); if ($this->checkStmt($stmt) && $stmt->bind_param('sddsi', $address, $threshold, $donate, $email, $userID) && $stmt->execute())
if ( $stmt->errno == 0 ) {
$stmt->close();
return true; return true;
} // Catchall
$this->setErrorMessage('Failed to update your account');
$this->debug->append('Account update failed: ' . $this->mysqli->error);
return false; return false;
} }
@ -266,15 +336,15 @@ class User {
private function checkUserPassword($username, $password) { private function checkUserPassword($username, $password) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
$user = array(); $user = array();
$stmt = $this->mysqli->prepare("SELECT username, id FROM $this->table WHERE username=? AND pass=? LIMIT 1"); $stmt = $this->mysqli->prepare("SELECT username, id, is_admin FROM $this->table WHERE username=? AND pass=? LIMIT 1");
if ($this->checkStmt($stmt)) { if ($this->checkStmt($stmt)) {
$stmt->bind_param('ss', $username, hash('sha256', $password.$this->salt)); $stmt->bind_param('ss', $username, hash('sha256', $password.$this->salt));
$stmt->execute(); $stmt->execute();
$stmt->bind_result($row_username, $row_id); $stmt->bind_result($row_username, $row_id, $row_admin);
$stmt->fetch(); $stmt->fetch();
$stmt->close(); $stmt->close();
// Store the basic login information // Store the basic login information
$this->user = array('username' => $row_username, 'id' => $row_id); $this->user = array('username' => $row_username, 'id' => $row_id, 'is_admin' => $row_admin);
return $username === $row_username; return $username === $row_username;
} }
return false; return false;
@ -303,7 +373,8 @@ class User {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
session_destroy(); session_destroy();
session_regenerate_id(true); session_regenerate_id(true);
return true; // Enforce a page reload
header("Location: index.php");
} }
/** /**
@ -325,7 +396,7 @@ class User {
$this->debug->append("Fetching user information for user id: $userID"); $this->debug->append("Fetching user information for user id: $userID");
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT SELECT
id, username, pin, api_key, admin, id, username, pin, api_key, is_admin, email,
IFNULL(donate_percent, '0') as donate_percent, coin_address, ap_threshold IFNULL(donate_percent, '0') as donate_percent, coin_address, ap_threshold
FROM $this->table FROM $this->table
WHERE id = ? LIMIT 0,1"); WHERE id = ? LIMIT 0,1");
@ -363,7 +434,7 @@ class User {
$this->setErrorMessage( 'Password do not match' ); $this->setErrorMessage( 'Password do not match' );
return false; return false;
} }
if (!empty($email1) && !filter_var($email1, FILTER_VALIDATE_EMAIL)) { if (empty($email1) || !filter_var($email1, FILTER_VALIDATE_EMAIL)) {
$this->setErrorMessage( 'Invalid e-mail address' ); $this->setErrorMessage( 'Invalid e-mail address' );
return false; return false;
} }
@ -383,7 +454,7 @@ class User {
"); ");
} else { } else {
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
INSERT INTO $this->table (username, pass, email, pin, api_key, admin) INSERT INTO $this->table (username, pass, email, pin, api_key, is_admin)
VALUES (?, ?, ?, ?, ?, 1) VALUES (?, ?, ?, ?, ?, 1)
"); ");
} }
@ -455,6 +526,7 @@ class User {
} }
$smarty->assign('TOKEN', $token); $smarty->assign('TOKEN', $token);
$smarty->assign('USERNAME', $username); $smarty->assign('USERNAME', $username);
$smarty->assign('SUBJECT', 'Password Reset Request');
$smarty->assign('WEBSITENAME', $this->config['website']['name']); $smarty->assign('WEBSITENAME', $this->config['website']['name']);
$headers = 'From: Website Administration <' . $this->config['website']['email'] . ">\n"; $headers = 'From: Website Administration <' . $this->config['website']['email'] . ">\n";
$headers .= "MIME-Version: 1.0\n"; $headers .= "MIME-Version: 1.0\n";
@ -470,6 +542,22 @@ class User {
} }
return false; return false;
} }
/**
* Check if a user is authenticated and allowed to login
* Checks the $_SESSION for existing data
* Destroys the session if account is now locked
* @param none
* @return bool
**/
public function isAuthenticated() {
$this->debug->append("STA " . __METHOD__, 4);
if (@$_SESSION['AUTHENTICATED'] == true && ! $this->isLocked($_SESSION['USERDATA']['id']) && $this->getUserIp($_SESSION['USERDATA']['id']) == $_SERVER['REMOTE_ADDR'])
return true;
// Catchall
$this->logoutUser();
return false;
}
} }
// Make our class available automatically // Make our class available automatically

View File

@ -43,17 +43,60 @@ class Worker {
public function updateWorkers($account_id, $data) { public function updateWorkers($account_id, $data) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
$username = $this->user->getUserName($account_id); $username = $this->user->getUserName($account_id);
$iFailed = 0;
foreach ($data as $key => $value) { foreach ($data as $key => $value) {
// Prefix the WebUser to Worker name // Prefix the WebUser to Worker name
$value['username'] = "$username." . $value['username']; $value['username'] = "$username." . $value['username'];
$stmt = $this->mysqli->prepare("UPDATE $this->table SET password = ?, username = ? WHERE account_id = ? AND id = ?"); $stmt = $this->mysqli->prepare("UPDATE $this->table SET password = ?, username = ?, monitor = ? WHERE account_id = ? AND id = ?");
if ($this->checkStmt($stmt)) { if ( ! ( $this->checkStmt($stmt) && $stmt->bind_param('ssiii', $value['password'], $value['username'], $value['monitor'], $account_id, $key) && $stmt->execute()) )
if (!$stmt->bind_param('ssii', $value['password'], $value['username'], $account_id, $key)) return false; $iFailed++;
if (!$stmt->execute()) return false;
$stmt->close();
}
} }
return true; if ($iFailed == 0)
return true;
// Catchall
$this->setErrorMessage('Failed to update ' . $iFailed . ' worker.');
return false;
}
/**
* Fetch all IDLE workers that have monitoring enabled
* @param none
* @return data array Workers in IDLE state and monitoring enabled
**/
public function getAllIdleWorkers() {
$this->debug->append("STA " . __METHOD__, 4);
$stmt = $this->mysqli->prepare("
SELECT account_id, id, username
FROM " . $this->table . "
WHERE monitor = 1 AND ( SELECT SIGN(COUNT(id)) FROM " . $this->share->getTableName() . " WHERE username = $this->table.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) = 0");
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_all(MYSQLI_ASSOC);
// Catchall
$this->setErrorMessage("Unable to fetch IDLE, monitored workers");
echo $this->mysqli->error;
return false;
}
/**
* Fetch a specific worker and its status
* @param id int Worker ID
* @return mixed array Worker details
**/
public function getWorker($id) {
$this->debug->append("STA " . __METHOD__, 4);
$stmt = $this->mysqli->prepare("
SELECT id, username, password, monitor,
( SELECT SIGN(COUNT(id)) FROM " . $this->share->getTableName() . " WHERE username = $this->table.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS active,
( SELECT ROUND(COUNT(id) * POW(2, " . $this->config['difficulty'] . ")/600/1000) FROM " . $this->share->getTableName() . " WHERE username = $this->table.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS hashrate
FROM $this->table
WHERE id = ?
");
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $id) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_assoc();
// Catchall
echo $this->mysqli->error;
return false;
} }
/** /**
@ -64,7 +107,7 @@ class Worker {
public function getWorkers($account_id) { public function getWorkers($account_id) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT id, username, password, SELECT id, username, password, monitor,
( SELECT SIGN(COUNT(id)) FROM " . $this->share->getTableName() . " WHERE username = $this->table.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS active, ( SELECT SIGN(COUNT(id)) FROM " . $this->share->getTableName() . " WHERE username = $this->table.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS active,
( SELECT ROUND(COUNT(id) * POW(2, " . $this->config['difficulty'] . ")/600/1000) FROM " . $this->share->getTableName() . " WHERE username = $this->table.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS hashrate ( SELECT ROUND(COUNT(id) * POW(2, " . $this->config['difficulty'] . ")/600/1000) FROM " . $this->share->getTableName() . " WHERE username = $this->table.username AND time > DATE_SUB(now(), INTERVAL 10 MINUTE)) AS hashrate
FROM $this->table FROM $this->table

View File

@ -23,13 +23,29 @@ define('SALT', 'PLEASEMAKEMESOMETHINGRANDOM');
$config = array( $config = array(
'price' => array( 'price' => array(
'url' => 'https://btc-e.com/api/2', 'url' => 'https://btc-e.com/api/2',
'target' => '/ltc_usd/ticker' 'target' => '/ltc_usd/ticker',
'currency' => 'USD' // Used in ministats template
),
'ap_threshold' => array(
'min' => 1,
'max' => 250
), ),
'website' => array( 'website' => array(
'registration' => true, // Allow new users to register
'name' => 'The Pool', 'name' => 'The Pool',
'slogan' => 'Resistance is futile', 'slogan' => 'Resistance is futile',
'email' => 'test@example.com', // Mail address used for notifications 'email' => 'test@example.com', // Mail address used for notifications
), ),
// See: http://www.google.com/recaptcha
'recaptcha' => array(
'enabled' => false, // Enable re-captcha during registraion
'public_key' => 'YOUR_PUBLIC_RECAPTCHA_KEY',
'private_key' => 'YOUR_PRIVATE_RECAPTCHA_KEY'
),
'currency' => 'LTC', // Currency name to be used on website
'txfee' => 0.1, // Default tx fee added by RPC server
'block_bonus' => 0,
'payout_system' => 'prop', // Set your payout here so template changes are activated
'archive_shares' => true, // Store accounted shares in archive table? 'archive_shares' => true, // Store accounted shares in archive table?
'blockexplorer' => 'http://explorer.litecoin.net/search?q=', // URL for block searches, prefixed to each block number 'blockexplorer' => 'http://explorer.litecoin.net/search?q=', // URL for block searches, prefixed to each block number
'chaininfo' => 'http://allchains.info', // Link to Allchains for Difficulty information 'chaininfo' => 'http://allchains.info', // Link to Allchains for Difficulty information

View File

@ -1,13 +1,10 @@
<?php <?php
// Make sure we are called from index.php // Make sure we are called from index.php
if (!defined('SECURITY')) if (!defined('SECURITY')) die('Hacking attempt');
die('Hacking attempt');
if (!$_SESSION['AUTHENTICATED']) { if ($user->isAuthenticated()) {
header('Location: index.php?page=home'); // Tempalte specifics
$smarty->assign("CONTENT", "default.tpl");
} }
// Tempalte specifics
$smarty->assign("CONTENT", "default.tpl");
?> ?>

View File

@ -4,61 +4,77 @@
if (!defined('SECURITY')) if (!defined('SECURITY'))
die('Hacking attempt'); die('Hacking attempt');
if (!$_SESSION['AUTHENTICATED']) { if ($user->isAuthenticated()) {
header('Location: index.php?page=home'); if ( ! $user->checkPin($_SESSION['USERDATA']['id'], @$_POST['authPin']) && @$_POST['do']) {
} $_SESSION['POPUP'][] = array('CONTENT' => 'Invalid PIN','TYPE' => 'errormsg');
} else {
if ( ! $user->checkPin($_SESSION['USERDATA']['id'], $_POST['authPin']) && $_POST['do']) { switch (@$_POST['do']) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Invalid PIN','TYPE' => 'errormsg'); case 'cashOut':
} else { if ($setting->getValue('manual_payout_active') == 1) {
switch ($_POST['do']) { $_SESSION['POPUP'][] = array('CONTENT' => 'A manual payout is in progress. Please try again later.', 'TYPE' => 'errormsg');
case 'cashOut':
$continue = true;
$dBalance = $transaction->getBalance($_SESSION['USERDATA']['id']);
$sCoinAddress = $user->getCoinAddress($_SESSION['USERDATA']['id']);
if ($dBalance > 0.1) {
if ($bitcoin->can_connect() === true) {
try {
$bitcoin->validateaddress($sCoinAddress);
} catch (BitcoinClientException $e) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Invalid payment address: ' . $sUserSendAddress, 'TYPE' => 'errormsg');
$continue = false;
}
if ($continue == true) {
// Remove the transfer fee and send to address
try {
$bitcoin->sendtoaddress($sCoinAddress, $dBalance - 0.1);
} catch (BitcoinClientException $e) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Failed to send LTC, please contact site support immidiately', 'TYPE' => 'errormsg');
$continue = false;
}
}
// Set balance to 0, add to paid out, insert to ledger
if ($continue == true && $transaction->addTransaction($_SESSION['USERDATA']['id'], $dBalance, 'Debit_MP', NULL, $sCoinAddress))
$_SESSION['POPUP'][] = array('CONTENT' => 'Transaction completed', 'TYPE' => 'success');
} else { } else {
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to litecoind RPC service', 'TYPE' => 'errormsg'); $setting->setValue('manual_payout_active', 1);
$continue = true;
$aBalance = $transaction->getBalance($_SESSION['USERDATA']['id']);
$dBalance = $aBalance['confirmed'];
$sCoinAddress = $user->getCoinAddress($_SESSION['USERDATA']['id']);
// Ensure we can cover the potential transaction fee
if ($dBalance > $config['txfee']) {
if ($bitcoin->can_connect() === true) {
try {
$bitcoin->validateaddress($sCoinAddress);
} catch (BitcoinClientException $e) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Invalid payment address: ' . $sUserSendAddress, 'TYPE' => 'errormsg');
$continue = false;
}
if ($continue == true) {
// Send balance to address, mind fee for transaction!
try {
if ($setting->getValue('auto_payout_active') == 0) {
$bitcoin->sendtoaddress($sCoinAddress, $dBalance);
} else {
$_SESSION['POPUP'][] = array('CONTENT' => 'Auto-payout active, please contact site support immidiately to revoke invalid transactions.', 'TYPE' => 'errormsg');
$continue = false;
}
} catch (BitcoinClientException $e) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Failed to send ' . $config['currency'] . ', please contact site support immidiately', 'TYPE' => 'errormsg');
$continue = false;
}
}
// Set balance to 0, add to paid out, insert to ledger
if ($continue == true && $transaction->addTransaction($_SESSION['USERDATA']['id'], $dBalance - $config['txfee'], 'Debit_MP', NULL, $sCoinAddress) && $transaction->addTransaction($_SESSION['USERDATA']['id'], $config['txfee'], 'TXFee', NULL, $sCoinAddress) ) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Transaction completed', 'TYPE' => 'success');
$aMailData['email'] = $user->getUserEmail($user->getUserName($_SESSION['USERDATA']['id']));
$aMailData['amount'] = $dBalance;
$aMailData['subject'] = 'Manual Payout Completed';
$notification->sendNotification($_SESSION['USERDATA']['id'], 'manual_payout', $aMailData);
}
} else {
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to litecoind RPC service', 'TYPE' => 'errormsg');
}
} else {
$_SESSION['POPUP'][] = array('CONTENT' => 'Insufficient funds, you need more than ' . $config['txfee'] . ' ' . $conifg['currency'] . ' to cover transaction fees', 'TYPE' => 'errormsg');
}
$setting->setValue('manual_payout_active', 0);
} }
} else { break;
$_SESSION['POPUP'][] = array('CONTENT' => 'Insufficient funds, you need more than 0.1 LTC to cover transaction fees', 'TYPE' => 'errormsg');
}
break;
case 'updateAccount': case 'updateAccount':
if ($user->updateAccount($_SESSION['USERDATA']['id'], $_POST['paymentAddress'], $_POST['payoutThreshold'], $_POST['donatePercent'])) { if ($user->updateAccount($_SESSION['USERDATA']['id'], $_POST['paymentAddress'], $_POST['payoutThreshold'], $_POST['donatePercent'], $_POST['email'])) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Account details updated', 'TYPE' => 'success'); $_SESSION['POPUP'][] = array('CONTENT' => 'Account details updated', 'TYPE' => 'success');
} else { } else {
$_SESSION['POPUP'][] = array('CONTENT' => 'Failed to update your account', 'TYPE' => 'errormsg'); $_SESSION['POPUP'][] = array('CONTENT' => 'Failed to update your account: ' . $user->getError(), 'TYPE' => 'errormsg');
} }
break; break;
case 'updatePassword': case 'updatePassword':
if ($user->updatePassword($_SESSION['USERDATA']['id'], $_POST['currentPassword'], $_POST['newPassword'], $_POST['newPassword2'])) { if ($user->updatePassword($_SESSION['USERDATA']['id'], $_POST['currentPassword'], $_POST['newPassword'], $_POST['newPassword2'])) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Password updated', 'TYPE' => 'success'); $_SESSION['POPUP'][] = array('CONTENT' => 'Password updated', 'TYPE' => 'success');
} else { } else {
$_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg'); $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg');
}
break;
} }
break;
} }
} }

View File

@ -0,0 +1,25 @@
<?php
// Make sure we are called from index.php
if (!defined('SECURITY')) die('Hacking attempt');
if ($user->isAuthenticated()) {
if (@$_REQUEST['do'] == 'save') {
if ($notification->updateSettings($_SESSION['USERDATA']['id'], $_REQUEST['data'])) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Updated notification settings');
} else {
$_SESSION['POPUP'][] = array('CONTENT' => 'Failed to update settings', 'TYPE' => 'errormsg');
}
}
// Fetch notifications
$aNotifications = $notification->getNofifications($_SESSION['USERDATA']['id']);
if (!$aNotifications) $_SESSION['POPUP'][] = array('CONTENT' => 'Could not find any notifications', 'TYPE' => 'errormsg');
// Fetch user notification settings
$aSettings = $notification->getNotificationSettings($_SESSION['USERDATA']['id']);
$smarty->assign('NOTIFICATIONS', $aNotifications);
$smarty->assign('SETTINGS', $aSettings);
$smarty->assign('CONTENT', 'default.tpl');
}
?>

View File

@ -2,11 +2,10 @@
// Make sure we are called from index.php // Make sure we are called from index.php
if (!defined('SECURITY')) die('Hacking attempt'); if (!defined('SECURITY')) die('Hacking attempt');
if (!$_SESSION['AUTHENTICATED']) header('Location: index.php?page=home'); if ($user->isAuthenticated()) {
$aTransactions = $transaction->getTransactions($_SESSION['USERDATA']['id']);
$aTransactions = $transaction->getTransactions($_SESSION['USERDATA']['id']); if (!$aTransactions) $_SESSION['POPUP'][] = array('CONTENT' => 'Could not find any transaction', 'TYPE' => 'errormsg');
if (!$aTransactions) $_SESSION['POPUP'][] = array('CONTENT' => 'Could not find any transaction', 'TYPE' => 'errormsg'); $smarty->assign('TRANSACTIONS', $aTransactions);
$smarty->assign('CONTENT', 'default.tpl');
$smarty->assign('TRANSACTIONS', $aTransactions); }
$smarty->assign('CONTENT', 'default.tpl');
?> ?>

View File

@ -2,35 +2,38 @@
// Make sure we are called from index.php // Make sure we are called from index.php
if (!defined('SECURITY')) die('Hacking attempt'); if (!defined('SECURITY')) die('Hacking attempt');
if (!$_SESSION['AUTHENTICATED']) header('Location: index.php?page=home');
switch ($_REQUEST['do']) { if ($user->isAuthenticated()) {
case 'delete': switch (@$_REQUEST['do']) {
if ($worker->deleteWorker($_SESSION['USERDATA']['id'], $_GET['id'])) { case 'delete':
$_SESSION['POPUP'][] = array('CONTENT' => 'Worker removed'); if ($worker->deleteWorker($_SESSION['USERDATA']['id'], $_GET['id'])) {
} else { $_SESSION['POPUP'][] = array('CONTENT' => 'Worker removed');
$_SESSION['POPUP'][] = array('CONTENT' => $worker->getError(), 'TYPE' => 'errormsg'); } else {
$_SESSION['POPUP'][] = array('CONTENT' => $worker->getError(), 'TYPE' => 'errormsg');
}
break;
case 'add':
if ($worker->addWorker($_SESSION['USERDATA']['id'], $_POST['username'], $_POST['password'])) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Worker added');
} else {
$_SESSION['POPUP'][] = array('CONTENT' => $worker->getError(), 'TYPE' => 'errormsg');
}
break;
case 'update':
if ($worker->updateWorkers($_SESSION['USERDATA']['id'], $_POST['data'])) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Worker updated');
} else {
$_SESSION['POPUP'][] = array('CONTENT' => $worker->getError(), 'TYPE' => 'errormsg');
}
break;
} }
break;
case 'add': $aWorkers = $worker->getWorkers($_SESSION['USERDATA']['id']);
if ($worker->addWorker($_SESSION['USERDATA']['id'], $_POST['username'], $_POST['password'])) { if (!$aWorkers) $_SESSION['POPUP'][] = array('CONTENT' => 'You have no workers configured', 'TYPE' => 'errormsg');
$_SESSION['POPUP'][] = array('CONTENT' => 'Worker added');
} else { $smarty->assign('WORKERS', $aWorkers);
$_SESSION['POPUP'][] = array('CONTENT' => $worker->getError(), 'TYPE' => 'errormsg');
}
break;
case 'update':
if ($worker->updateWorkers($_SESSION['USERDATA']['id'], $_POST['data'])) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Worker updated');
} else {
$_SESSION['POPUP'][] = array('CONTENT' => $worker->getError(), 'TYPE' => 'errormsg');
}
break;
} }
$aWorkers = $worker->getWorkers($_SESSION['USERDATA']['id']);
if (!$aWorkers) $_SESSION['POPUP'][] = array('CONTENT' => 'You have no workers configured', 'TYPE' => 'errormsg');
$smarty->assign('CONTENT', 'default.tpl'); $smarty->assign('CONTENT', 'default.tpl');
$smarty->assign('WORKERS', $aWorkers);
?> ?>

View File

@ -0,0 +1,14 @@
<?php
// Make sure we are called from index.php
if (!defined('SECURITY')) die('Hacking attempt');
// Check user to ensure they are admin
if (!$user->isAuthenticated() || !$user->isAdmin($_SESSION['USERDATA']['id'])) {
header("HTTP/1.1 404 Page not found");
die("404 Page not found");
}
// Tempalte specifics
$smarty->assign("CONTENT", "default.tpl");
?>

View File

@ -0,0 +1,50 @@
<?php
// Make sure we are called from index.php
if (!defined('SECURITY')) die('Hacking attempt');
// Check user to ensure they are admin
if (!$user->isAuthenticated() || !$user->isAdmin($_SESSION['USERDATA']['id'])) {
header("HTTP/1.1 404 Page not found");
die("404 Page not found");
}
$aRoundShares = $statistics->getRoundShares();
// Change account lock
if (@$_POST['do'] == 'lock') {
$supress_master = 1;
$user->changeLocked($_POST['account_id']);
}
// Change account admin
if (@$_POST['do'] == 'admin') {
$supress_master = 1;
$user->changeAdmin($_POST['account_id']);
}
if (@$_POST['query']) {
// Fetch requested users
$aUsers = $statistics->getAllUserStats($_POST['query']);
// Add additional stats to each user
// This is not optimized yet, best is a proper SQL
// Query against the stats table? Currently cached though.
foreach ($aUsers as $iKey => $aUser) {
$aBalance = $transaction->getBalance($aUser['id']);
$aUser['balance'] = $aBalance['confirmed'];
$aUser['hashrate'] = $statistics->getUserHashrate($aUser['id']);
$aUser['payout']['est_block'] = round(( (int)$aUser['shares'] / (int)$aRoundShares['valid'] ) * (int)$config['reward'], 3);
$aUser['payout']['est_fee'] = round(($config['fees'] / 100) * $aUser['payout']['est_block'], 3);
$aUser['payout']['est_donation'] = round((( $aUser['donate_percent'] / 100) * ($aUser['payout']['est_block'] - $aUser['payout']['est_fee'])), 3);
$aUser['payout']['est_payout'] = round($aUser['payout']['est_block'] - $aUser['payout']['est_donation'] - $aUser['payout']['est_fee'], 3);
$aUsers[$iKey] = $aUser;
}
// Assign our variables
$smarty->assign("USERS", $aUsers);
}
// Tempalte specifics
$smarty->assign("CONTENT", "default.tpl");
?>

View File

@ -0,0 +1,24 @@
<?php
// Make sure we are called from index.php
if (!defined('SECURITY')) die('Hacking attempt');
// Check user to ensure they are admin
if (!$user->isAuthenticated() || !$user->isAdmin($_SESSION['USERDATA']['id'])) {
header("HTTP/1.1 404 Page not found");
die("404 Page not found");
}
if ($bitcoin->can_connect() === true){
$dBalance = $bitcoin->query('getbalance');
} else {
$dBalance = 0;
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to litecoind RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg');
}
$smarty->assign("BALANCE", $dBalance);
$smarty->assign("LOCKED", $transaction->getLockedBalance());
// Tempalte specifics
$smarty->assign("CONTENT", "default.tpl");
?>

View File

@ -0,0 +1,29 @@
<?php
// Make sure we are called from index.php
if (!defined('SECURITY'))
die('Hacking attempt');
// Check user token
$id = $user->checkApiKey($_REQUEST['api_key']);
// We have to check if that user is admin too
if ( ! $user->isAdmin($id) ) {
header("HTTP/1.1 401 Unauthorized");
die("Access denied");
}
// Is it a username or a user ID
ctype_digit($_REQUEST['id']) ? $username = $user->getUserName($_REQUEST['id']) : $username = $_REQUEST['id'];
ctype_digit($_REQUEST['id']) ? $id = $_REQUEST['id'] : $id = $user->getUserId($_REQUEST['id']);
// Output JSON format
echo json_encode(array('getuserstatus' => array(
'username' => $username,
'shares' => $statistics->getUserShares($id),
'hashrate' => $statistics->getUserHashrate($id)
)));
// Supress master template
$supress_master = 1;
?>

View File

@ -0,0 +1,24 @@
<?php
// Make sure we are called from index.php
if (!defined('SECURITY'))
die('Hacking attempt');
// Check user token
$id = $user->checkApiKey($_REQUEST['api_key']);
// We have to check if that user is admin too
if ( ! $user->isAdmin($id) ) {
header("HTTP/1.1 401 Unauthorized");
die("Access denied");
}
// Is it a username or a user ID
ctype_digit($_REQUEST['id']) ? $id = $_REQUEST['id'] : $id = $user->getUserId($_REQUEST['id']);
// Output JSON format
echo json_encode(array('getuserworkers' => $worker->getWorkers($id)));
// Supress master template
$supress_master = 1;
?>

View File

@ -0,0 +1,26 @@
<?php
// Make sure we are called from index.php
if (!defined('SECURITY'))
die('Hacking attempt');
// {"pool_name":"Pool-X.eu","hashrate":"511128.99","workers":"2104","shares_this_round":92450,"last_block":"365294","network_hashrate":17327056.06}
// Fetch last block information
$aLastBlock = $block->getLast();
$aShares = $statistics->getRoundShares();
echo json_encode(
array(
'pool_name' => $config['website']['name'],
'hashrate' => $statistics->getCurrentHashrate(),
'workers' => $worker->getCountAllActiveWorkers(),
'shares_this_round' => $aShares['valid'],
'last_block' => $aLastBlock['height'],
'network_hashrate' => '0'
)
);
// Supress master template
$supress_master = 1;
?>

View File

@ -7,7 +7,7 @@ if (!defined('SECURITY'))
if ( $user->checkLogin($_POST['username'],$_POST['password']) ) { if ( $user->checkLogin($_POST['username'],$_POST['password']) ) {
header('Location: index.php?page=home'); header('Location: index.php?page=home');
} else { } else {
$_SESSION['POPUP'][] = array('CONTENT' => 'Invalid username or password', 'TYPE' => 'errormsg'); $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to login: '. $user->getError(), 'TYPE' => 'errormsg');
} }
$smarty->assign('CONTENT', 'default.tpl'); $smarty->assign('CONTENT', 'default.tpl');
?> ?>

View File

@ -1,9 +1,17 @@
<?php <?php
// Make sure we are called from index.php // Make sure we are called from index.php
if (!defined('SECURITY')) if (!defined('SECURITY')) die('Hacking attempt');
die('Hacking attempt');
// Tempalte specifics if (!$config['website']['registration']) {
$smarty->assign("CONTENT", "default.tpl"); $_SESSION['POPUP'][] = array('CONTENT' => 'Account registration is currently disabled. Please try again later.', 'TYPE' => 'errormsg');
$smarty->assign("CONTENT", "disabled.tpl");
} else {
if ($config['recaptcha']['enabled']) {
require_once(INCLUDE_DIR . '/recaptchalib.php');
$smarty->assign("RECAPTCHA", recaptcha_get_html($config['recaptcha']['public_key']));
}
// Tempalte specifics
$smarty->assign("CONTENT", "default.tpl");
}
?> ?>

View File

@ -1,14 +1,46 @@
<?php <?php
// Make sure we are called from index.php // Make sure we are called from index.php
if (!defined('SECURITY')) if (!defined('SECURITY')) die('Hacking attempt');
die('Hacking attempt');
if ($config['recaptcha']['enabled']) {
// Load re-captcha specific data
require_once(INCLUDE_DIR . '/recaptchalib.php');
$rsp = recaptcha_check_answer (
$config['recaptcha']['private_key'],
$_SERVER["REMOTE_ADDR"],
$_POST["recaptcha_challenge_field"],
$_POST["recaptcha_response_field"]
);
}
if ($user->register($_POST['username'], $_POST['password1'], $_POST['password2'], $_POST['pin'], $_POST['email1'], $_POST['email2'])) { // Check if recaptcha is enabled, process form data if valid
$_SESSION['POPUP'][] = array('CONTENT' => 'Account created, please login'); if($config['recaptcha']['enabled'] && $_POST["recaptcha_response_field"] && $_POST["recaptcha_response_field"]!=''){
if ($rsp->is_valid) {
$smarty->assign("RECAPTCHA", recaptcha_get_html($config['recaptcha']['public_key']));
if (!$config['website']['registration']) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Account registration is currently disabled. Please try again later.', 'TYPE' => 'errormsg');
} else if ($user->register($_POST['username'], $_POST['password1'], $_POST['password2'], $_POST['pin'], $_POST['email1'], $_POST['email2']) && $config['website']['registration']) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Account created, please login');
} else {
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to create account: ' . $user->getError(), 'TYPE' => 'errormsg');
}
} else {
$smarty->assign("RECAPTCHA", recaptcha_get_html($config['recaptcha']['public_key'], $rsp->error));
$_SESSION['POPUP'][] = array('CONTENT' => 'Invalid Captcha, please try again. (' . $rsp->error . ')', 'TYPE' => 'errormsg');
}
// Empty captcha
} else if ($config['recaptcha']['enabled']) {
$smarty->assign("RECAPTCHA", recaptcha_get_html($config['recaptcha']['public_key'], $rsp->error));
$_SESSION['POPUP'][] = array('CONTENT' => 'Empty Captcha, please try again.', 'TYPE' => 'errormsg');
// Captcha disabled
} else { } else {
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to create account: ' . $user->getError(), 'TYPE' => 'errormsg'); if (!$config['website']['registration']) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Account registration is currently disabled. Please try again later.', 'TYPE' => 'errormsg');
} else if ($user->register($_POST['username'], $_POST['password1'], $_POST['password2'], $_POST['pin'], $_POST['email1'], $_POST['email2']) && $config['website']['registration']) {
$_SESSION['POPUP'][] = array('CONTENT' => 'Account created, please login');
} else {
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to create account: ' . $user->getError(), 'TYPE' => 'errormsg');
}
} }
// We load the default registration template instead of an action specific one // We load the default registration template instead of an action specific one

View File

@ -5,14 +5,14 @@ if (!defined('SECURITY'))
die('Hacking attempt'); die('Hacking attempt');
if ($bitcoin->can_connect() === true){ if ($bitcoin->can_connect() === true){
$iDifficulty = $bitcoin->query('getdifficulty'); $dDifficulty = $bitcoin->query('getdifficulty');
$iBlock = $bitcoin->query('getblockcount'); $iBlock = $bitcoin->query('getblockcount');
} else { } else {
$iDifficulty = 1; $dDifficulty = 1;
$iBlock = 0; $iBlock = 0;
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to litecoind RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg'); $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to litecoind RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg');
} }
$smarty->assign("CURRENTBLOCK", $iBlock); $smarty->assign("CURRENTBLOCK", $iBlock);
$smarty->assign("CURRENTDIFFICULTY", $iDifficulty); $smarty->assign("DIFFICULTY", $dDifficulty);
$smarty->assign("CONTENT", "pool/default.tpl"); $smarty->assign("CONTENT", "default.tpl");

View File

@ -1,9 +1,8 @@
<?php <?php
// Make sure we are called from index.php // Make sure we are called from index.php
if (!defined('SECURITY')) if (!defined('SECURITY')) die('Hacking attempt');
die('Hacking attempt'); if (!$user->isAuthenticated()) header("Location: index.php?page=home");
// Grab the last blocks found // Grab the last blocks found
$iLimit = 30; $iLimit = 30;
@ -14,9 +13,5 @@ $aBlockData = $aBlocksFoundData[0];
$smarty->assign("BLOCKSFOUND", $aBlocksFoundData); $smarty->assign("BLOCKSFOUND", $aBlocksFoundData);
$smarty->assign("BLOCKLIMIT", $iLimit); $smarty->assign("BLOCKLIMIT", $iLimit);
if ($_SESSION['AUTHENTICATED']) { $smarty->assign("CONTENT", "default.tpl");
$smarty->assign("CONTENT", "blocks_found.tpl");
} else {
$smarty->assign("CONTENT", "default.tpl");
}
?> ?>

View File

@ -0,0 +1,16 @@
<?php
// Make sure we are called from index.php
if (!defined('SECURITY'))
die('Hacking attempt');
if ($user->isAuthenticated()) {
$aHourlyHashRates = $statistics->getHourlyHashrateByAccount($_SESSION['USERDATA']['id']);
$aPoolHourlyHashRates = $statistics->getHourlyHashrateByPool();
}
// Propagate content our template
$smarty->assign("YOURHASHRATES", @$aHourlyHashRates);
$smarty->assign("POOLHASHRATES", @$aPoolHourlyHashRates);
$smarty->assign("CONTENT", "default.tpl");
?>

View File

@ -21,12 +21,14 @@ $aContributorsShares = $statistics->getTopContributors('shares', 15);
$aContributorsHashes = $statistics->getTopContributors('hashes', 15); $aContributorsHashes = $statistics->getTopContributors('hashes', 15);
// Grab the last 10 blocks found // Grab the last 10 blocks found
$iLimit = 10; $iLimit = 5;
$aBlocksFoundData = $statistics->getBlocksFound($iLimit); $aBlocksFoundData = $statistics->getBlocksFound($iLimit);
$aBlockData = $aBlocksFoundData[0]; $aBlockData = $aBlocksFoundData[0];
// Estimated time to find the next block // Estimated time to find the next block
$iCurrentPoolHashrate = $statistics->getCurrentHashrate(); $iCurrentPoolHashrate = $statistics->getCurrentHashrate();
$iCurrentPoolHashrate == 0 ? $iCurrentPoolHashrate = 1 : true;
// Time in seconds, not hours, using modifier in smarty to translate // Time in seconds, not hours, using modifier in smarty to translate
$iEstTime = $dDifficulty * pow(2,32) / ($iCurrentPoolHashrate * 1000); $iEstTime = $dDifficulty * pow(2,32) / ($iCurrentPoolHashrate * 1000);
@ -50,9 +52,9 @@ $smarty->assign("LASTBLOCK", $aBlockData['height']);
$smarty->assign("DIFFICULTY", $dDifficulty); $smarty->assign("DIFFICULTY", $dDifficulty);
$smarty->assign("REWARD", $config['reward']); $smarty->assign("REWARD", $config['reward']);
if ($_SESSION['AUTHENTICATED']) { if ($user->isAuthenticated()) {
$smarty->assign("CONTENT", "authenticated.tpl"); $smarty->assign("CONTENT", "authenticated.tpl");
} else { } else {
$smarty->assign("CONTENT", "default.tpl"); $smarty->assign("CONTENT", "../default.tpl");
} }
?> ?>

View File

@ -1,26 +0,0 @@
<?php
// Make sure we are called from index.php
if (!defined('SECURITY'))
die('Hacking attempt');
// Fetch data from litecoind
if ($bitcoin->can_connect() === true){
$dDifficulty = $bitcoin->getdifficulty();
$iBlock = $bitcoin->getblockcount();
} else {
$iDifficulty = 1;
$iBlock = 0;
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to litecoind RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg');
}
$aHourlyHashRates = $statistics->getHourlyHashrateByAccount($_SESSION['USERDATA']['id']);
// Propagate content our template
$smarty->assign("YOURHASHRATES", $aHourlyHashRates);
$smarty->assign("DIFFICULTY", $dDifficulty);
if ($_SESSION['AUTHENTICATED']) {
$smarty->assign("CONTENT", "default.tpl");
}
?>

View File

@ -0,0 +1,277 @@
<?php
/*
* This is a PHP library that handles calling reCAPTCHA.
* - Documentation and latest version
* http://recaptcha.net/plugins/php/
* - Get a reCAPTCHA API Key
* https://www.google.com/recaptcha/admin/create
* - Discussion group
* http://groups.google.com/group/recaptcha
*
* Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
* AUTHORS:
* Mike Crawford
* Ben Maurer
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* The reCAPTCHA server URL's
*/
define("RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api");
define("RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api");
define("RECAPTCHA_VERIFY_SERVER", "www.google.com");
/**
* Encodes the given data into a query string format
* @param $data - array of string elements to be encoded
* @return string - encoded request
*/
function _recaptcha_qsencode ($data) {
$req = "";
foreach ( $data as $key => $value )
$req .= $key . '=' . urlencode( stripslashes($value) ) . '&';
// Cut the last '&'
$req=substr($req,0,strlen($req)-1);
return $req;
}
/**
* Submits an HTTP POST to a reCAPTCHA server
* @param string $host
* @param string $path
* @param array $data
* @param int port
* @return array response
*/
function _recaptcha_http_post($host, $path, $data, $port = 80) {
$req = _recaptcha_qsencode ($data);
$http_request = "POST $path HTTP/1.0\r\n";
$http_request .= "Host: $host\r\n";
$http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
$http_request .= "Content-Length: " . strlen($req) . "\r\n";
$http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
$http_request .= "\r\n";
$http_request .= $req;
$response = '';
if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
die ('Could not open socket');
}
fwrite($fs, $http_request);
while ( !feof($fs) )
$response .= fgets($fs, 1160); // One TCP-IP packet
fclose($fs);
$response = explode("\r\n\r\n", $response, 2);
return $response;
}
/**
* Gets the challenge HTML (javascript and non-javascript version).
* This is called from the browser, and the resulting reCAPTCHA HTML widget
* is embedded within the HTML form it was called from.
* @param string $pubkey A public key for reCAPTCHA
* @param string $error The error given by reCAPTCHA (optional, default is null)
* @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
* @return string - The HTML to be embedded in the user's form.
*/
function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false)
{
if ($pubkey == null || $pubkey == '') {
die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
}
if ($use_ssl) {
$server = RECAPTCHA_API_SECURE_SERVER;
} else {
$server = RECAPTCHA_API_SERVER;
}
$errorpart = "";
if ($error) {
$errorpart = "&amp;error=" . $error;
}
return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script>
<noscript>
<iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/>
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
</noscript>';
}
/**
* A ReCaptchaResponse is returned from recaptcha_check_answer()
*/
class ReCaptchaResponse {
var $is_valid;
var $error;
}
/**
* Calls an HTTP POST function to verify if the user's guess was correct
* @param string $privkey
* @param string $remoteip
* @param string $challenge
* @param string $response
* @param array $extra_params an array of extra variables to post to the server
* @return ReCaptchaResponse
*/
function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array())
{
if ($privkey == null || $privkey == '') {
die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
}
if ($remoteip == null || $remoteip == '') {
die ("For security reasons, you must pass the remote ip to reCAPTCHA");
}
//discard spam submissions
if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
$recaptcha_response = new ReCaptchaResponse();
$recaptcha_response->is_valid = false;
$recaptcha_response->error = 'incorrect-captcha-sol';
return $recaptcha_response;
}
$response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify",
array (
'privatekey' => $privkey,
'remoteip' => $remoteip,
'challenge' => $challenge,
'response' => $response
) + $extra_params
);
$answers = explode ("\n", $response [1]);
$recaptcha_response = new ReCaptchaResponse();
if (trim ($answers [0]) == 'true') {
$recaptcha_response->is_valid = true;
}
else {
$recaptcha_response->is_valid = false;
$recaptcha_response->error = $answers [1];
}
return $recaptcha_response;
}
/**
* gets a URL where the user can sign up for reCAPTCHA. If your application
* has a configuration page where you enter a key, you should provide a link
* using this function.
* @param string $domain The domain where the page is hosted
* @param string $appname The name of your application
*/
function recaptcha_get_signup_url ($domain = null, $appname = null) {
return "https://www.google.com/recaptcha/admin/create?" . _recaptcha_qsencode (array ('domains' => $domain, 'app' => $appname));
}
function _recaptcha_aes_pad($val) {
$block_size = 16;
$numpad = $block_size - (strlen ($val) % $block_size);
return str_pad($val, strlen ($val) + $numpad, chr($numpad));
}
/* Mailhide related code */
function _recaptcha_aes_encrypt($val,$ky) {
if (! function_exists ("mcrypt_encrypt")) {
die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
}
$mode=MCRYPT_MODE_CBC;
$enc=MCRYPT_RIJNDAEL_128;
$val=_recaptcha_aes_pad($val);
return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
}
function _recaptcha_mailhide_urlbase64 ($x) {
return strtr(base64_encode ($x), '+/', '-_');
}
/* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
function recaptcha_mailhide_url($pubkey, $privkey, $email) {
if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) {
die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
"you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>");
}
$ky = pack('H*', $privkey);
$cryptmail = _recaptcha_aes_encrypt ($email, $ky);
return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail);
}
/**
* gets the parts of the email to expose to the user.
* eg, given johndoe@example,com return ["john", "example.com"].
* the email is then displayed as john...@example.com
*/
function _recaptcha_mailhide_email_parts ($email) {
$arr = preg_split("/@/", $email );
if (strlen ($arr[0]) <= 4) {
$arr[0] = substr ($arr[0], 0, 1);
} else if (strlen ($arr[0]) <= 6) {
$arr[0] = substr ($arr[0], 0, 3);
} else {
$arr[0] = substr ($arr[0], 0, 4);
}
return $arr;
}
/**
* Gets html to display an email address given a public an private key.
* to get a key, go to:
*
* http://www.google.com/recaptcha/mailhide/apikey
*/
function recaptcha_mailhide_html($pubkey, $privkey, $email) {
$emailparts = _recaptcha_mailhide_email_parts ($email);
$url = recaptcha_mailhide_url ($pubkey, $privkey, $email);
return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
"' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
}
?>

View File

@ -5,7 +5,7 @@ if (!defined('SECURITY'))
die('Hacking attempt'); die('Hacking attempt');
$debug->append('Loading Smarty libraries', 2); $debug->append('Loading Smarty libraries', 2);
define('SMARTY_DIR', BASEPATH . INCLUDE_DIR . '/smarty/libs/'); define('SMARTY_DIR', INCLUDE_DIR . '/smarty/libs/');
// Include the actual smarty class file // Include the actual smarty class file
include(SMARTY_DIR . 'Smarty.class.php'); include(SMARTY_DIR . 'Smarty.class.php');
@ -16,10 +16,10 @@ $smarty = new Smarty;
// Assign our local paths // Assign our local paths
$debug->append('Define Smarty Paths', 3); $debug->append('Define Smarty Paths', 3);
$smarty->template_dir = 'templates/' . THEME . '/'; $smarty->template_dir = BASEPATH . 'templates/' . THEME . '/';
$smarty->compile_dir = 'templates/compile/'; $smarty->compile_dir = BASEPATH . 'templates/compile/';
// Optional smarty caching, check Smarty documentation for details // Optional smarty caching, check Smarty documentation for details
$smarty->caching = $config['cache']; $smarty->caching = $config['cache'];
$smarty->cache_dir = "templates/cache"; $smarty->cache_dir = BASEPATH . "templates/cache";
?> ?>

View File

@ -7,17 +7,29 @@ if (!defined('SECURITY'))
// Globally available variables // Globally available variables
$debug->append('Global smarty variables', 3); $debug->append('Global smarty variables', 3);
// Defaults to get rid of PHP Notice warnings
$dDifficulty = 1;
$aRoundShares = 1;
// Only run these if the user is logged in
if (@$_SESSION['AUTHENTICATED']) {
$aRoundShares = $statistics->getRoundShares();
if ($bitcoin->can_connect() === true)
$dDifficulty = $bitcoin->query('getdifficulty');
}
// Fetch some data // Fetch some data
$aRoundShares = $statistics->getRoundShares();
$iCurrentActiveWorkers = $worker->getCountAllActiveWorkers(); $iCurrentActiveWorkers = $worker->getCountAllActiveWorkers();
$iCurrentPoolHashrate = $statistics->getCurrentHashrate(); $iCurrentPoolHashrate = $statistics->getCurrentHashrate();
$iCurrentPoolShareRate = $statistics->getCurrentShareRate(); $iCurrentPoolShareRate = $statistics->getCurrentShareRate();
// Global data for Smarty
$aGlobal = array( $aGlobal = array(
'slogan' => $config['website']['slogan'], 'slogan' => $config['website']['slogan'],
'websitename' => $config['website']['name'], 'websitename' => $config['website']['name'],
'hashrate' => $iCurrentPoolHashrate, 'hashrate' => $iCurrentPoolHashrate,
'sharerate' => $iCurrentPoolShareRate, 'sharerate' => $iCurrentPoolShareRate,
'ppsvalue' => number_format(round(50 / (pow(2,32) * $dDifficulty) * pow(2, $config['difficulty']), 12) ,12),
'workers' => $iCurrentActiveWorkers, 'workers' => $iCurrentActiveWorkers,
'roundshares' => $aRoundShares, 'roundshares' => $aRoundShares,
'fees' => $config['fees'], 'fees' => $config['fees'],
@ -25,7 +37,18 @@ $aGlobal = array(
'reward' => $config['reward'], 'reward' => $config['reward'],
'price' => $setting->getValue('price'), 'price' => $setting->getValue('price'),
'blockexplorer' => $config['blockexplorer'], 'blockexplorer' => $config['blockexplorer'],
'chaininfo' => $config['chaininfo'] 'chaininfo' => $config['chaininfo'],
'config' => array(
'price' => array( 'currency' => $config['price']['currency'] ),
'targetdiff' => $config['difficulty'],
'currency' => $config['currency'],
'txfee' => $config['txfee'],
'payout_system' => $config['payout_system'],
'ap_threshold' => array(
'min' => $config['ap_threshold']['min'],
'max' => $config['ap_threshold']['max']
)
)
); );
// We don't want these session infos cached // We don't want these session infos cached
@ -36,12 +59,19 @@ if (@$_SESSION['USERDATA']['id']) {
// Other userdata that we can cache savely // Other userdata that we can cache savely
$aGlobal['userdata']['shares'] = $statistics->getUserShares($_SESSION['USERDATA']['id']); $aGlobal['userdata']['shares'] = $statistics->getUserShares($_SESSION['USERDATA']['id']);
$aGlobal['userdata']['hashrate'] = $statistics->getUserHashrate($_SESSION['USERDATA']['id']); $aGlobal['userdata']['hashrate'] = $statistics->getUserHashrate($_SESSION['USERDATA']['id']);
$aGlobal['userdata']['sharerate'] = $statistics->getUserSharerate($_SESSION['USERDATA']['id']);
// Some estimations switch ($config['payout_system']) {
$aGlobal['userdata']['est_block'] = round(( (int)$aGlobal['userdata']['shares']['valid'] / (int)$aRoundShares['valid'] ) * (int)$config['reward'], 3); case 'pps':
$aGlobal['userdata']['est_fee'] = round(($config['fees'] / 100) * $aGlobal['userdata']['est_block'], 3); break;
$aGlobal['userdata']['est_donation'] = round((( $aGlobal['userdata']['donate_percent'] / 100) * ($aGlobal['userdata']['est_block'] - $aGlobal['userdata']['est_fee'])), 3); default:
$aGlobal['userdata']['est_payout'] = round($aGlobal['userdata']['est_block'] - $aGlobal['userdata']['est_donation'] - $aGlobal['userdata']['est_fee'], 3); // Some estimations
$aGlobal['userdata']['est_block'] = round(( (int)$aGlobal['userdata']['shares']['valid'] / (int)$aRoundShares['valid'] ) * (int)$config['reward'], 3);
$aGlobal['userdata']['est_fee'] = round(($config['fees'] / 100) * $aGlobal['userdata']['est_block'], 3);
$aGlobal['userdata']['est_donation'] = round((( $aGlobal['userdata']['donate_percent'] / 100) * ($aGlobal['userdata']['est_block'] - $aGlobal['userdata']['est_fee'])), 3);
$aGlobal['userdata']['est_payout'] = round($aGlobal['userdata']['est_block'] - $aGlobal['userdata']['est_donation'] - $aGlobal['userdata']['est_fee'], 3);
break;
}
} }
// Make it available in Smarty // Make it available in Smarty

View File

@ -465,6 +465,12 @@ a:hover {
.block table tr th.right{ .block table tr th.right{
text-align: right; text-align: right;
} }
.block table tr td.center{
text-align: center;
}
.block table tr th.center{
text-align: center;
}
.block table tr td.delete a { color: #666; } .block table tr td.delete a { color: #666; }
@ -1032,3 +1038,25 @@ a:hover {
padding-left:5px; padding-left:5px;
} }
/* Custom checkboxes */
input[type=checkbox] {
display:none;
}
input[type=checkbox] + label
{
background: url('../images/error.gif');
height: 16px;
width: 16px;
display:inline-block;
padding: 0 0 0 0px;
}
input[type=checkbox]:checked + label
{
background: url('../images/success.gif');
height: 16px;
width: 16px;
display:inline-block;
padding: 0 0 0 0px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 B

View File

@ -16,19 +16,12 @@ $(function () {
var statsType = 'area'; var statsType = 'area';
} }
// calculate width of graph so it doesnt overflow its parent div
//var chart_width = ($(this).parent('div').width()) - 60;
// hack to statically set width as something is broken with div width calculation - anni
var chart_width = $(document).width() - 340;
if (statsType == 'line' || statsType == 'pie') { if (statsType == 'line' || statsType == 'pie') {
$(this).hide().visualize({ $(this).hide().visualize({
type: statsType, type: statsType,
// 'bar', 'area', 'pie', 'line' // 'bar', 'area', 'pie', 'line'
width: chart_width,
height: '240px', height: '240px',
colors: ['#6fb9e8', '#ec8526', '#9dc453', '#ddd74c'], colors: ['#6fb9e8', '#ec8526', '#9dc453', '#ddd74c'],
lineDots: 'double', lineDots: 'double',
interaction: true, interaction: true,
multiHover: 5, multiHover: 5,
@ -43,9 +36,8 @@ $(function () {
}); });
} else { } else {
$(this).hide().visualize({ $(this).hide().visualize({
type: statsType,
// 'bar', 'area', 'pie', 'line' // 'bar', 'area', 'pie', 'line'
width: chart_width, type: statsType,
height: '240px', height: '240px',
colors: ['#6fb9e8', '#ec8526', '#9dc453', '#ddd74c'] colors: ['#6fb9e8', '#ec8526', '#9dc453', '#ddd74c']
}); });
@ -66,6 +58,16 @@ $(function () {
widgets: ['zebra'] widgets: ['zebra']
}); });
$("table.pagesort")
.tablesorter({ widgets: ['zebra'] })
.tablesorterPager({ positionFixed: false, container: $("#pager") });
$("table.pagesort2")
.tablesorter({ widgets: ['zebra'] })
.tablesorterPager({ positionFixed: false, container: $("#pager2") });
$("table.pagesort4")
.tablesorter({ widgets: ['zebra'] })
.tablesorterPager({ positionFixed: false, container: $("#pager3") });
$('.block table tr th.header').css('cursor', 'pointer'); $('.block table tr th.header').css('cursor', 'pointer');
// Check / uncheck all checkboxes // Check / uncheck all checkboxes

View File

@ -0,0 +1,106 @@
/**
* --------------------------------------------------------------------
* Tooltip plugin for the jQuery-Plugin "Visualize"
* Tolltip by Iraê Carvalho, irae@irae.pro.br, http://irae.pro.br/en/
* Copyright (c) 2010 Iraê Carvalho
* Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
*
* Visualize plugin by Scott Jehl, scott@filamentgroup.com
* Copyright (c) 2009 Filament Group, http://www.filamentgroup.com
*
* --------------------------------------------------------------------
*/
(function($){
$.visualizePlugins.push(function visualizeTooltip(options,tableData) {
//configuration
var o = $.extend({
tooltip: false,
tooltipalign: 'auto', // also available 'left' and 'right'
tooltipvalign: 'top',
tooltipclass: 'visualize-tooltip',
tooltiphtml: function(data){
if(options.multiHover) {
var html='';
for(var i=0;i<data.point.length;i++){
html += '<p>'+data.point[i].value+' - '+data.point[i].yLabels[0]+'</p>';
}
return html;
} else {
return '<p>'+data.point.value+' - '+data.point.yLabels[0]+'</p>';
}
},
delay:false
},options);
// don't go any further if we are not to show anything
if(!o.tooltip) {return;}
var self = $(this),
canvasContain = self.next(),
scroller = canvasContain.find('.visualize-scroller'),
scrollerW = scroller.width(),
tracker = canvasContain.find('.visualize-interaction-tracker');
// IE needs background color and opacity white or the tracker stays behind the tooltip
tracker.css({
backgroundColor:'white',
opacity:0,
zIndex:100
});
var tooltip = $('<div class="'+o.tooltipclass+'"/>').css({
position:'absolute',
display:'none',
zIndex:90
})
.insertAfter(scroller.find('canvas'));
var usescroll = true;
if( typeof(G_vmlCanvasManager) != 'undefined' ){
scroller.css({'position':'absolute'});
tracker.css({marginTop:'-'+(o.height)+'px'});
}
self.bind('vizualizeOver',function visualizeTooltipOver(e,data){
if(data.canvasContain.get(0) != canvasContain.get(0)) {return;} // for multiple graphs originated from same table
if(o.multiHover) {
var p = data.point[0].canvasCords;
} else {
var p = data.point.canvasCords;
}
var left,right,top,clasRem,clasAd,bottom,x=Math.round(p[0]+data.tableData.zeroLocX),y=Math.round(p[1]+data.tableData.zeroLocY);
if(o.tooltipalign == 'left' || ( o.tooltipalign=='auto' && x-scroller.scrollLeft()<=scrollerW/2 ) ) {
if($.browser.msie && ($.browser.version == 7 || $.browser.version == 6) ) {usescroll=false;} else {usescroll=true;}
left = (x-(usescroll?scroller.scrollLeft():0))+'px';
right = '';
clasAdd="tooltipleft";
clasRem="tooltipright";
} else {
if($.browser.msie && $.browser.version == 7) {usescroll=false;} else {usescroll=true;}
left = '';
right = (Math.abs(x-o.width)- (o.width-(usescroll?scroller.scrollLeft():0)-scrollerW) )+'px';
clasAdd="tooltipright";
clasRem="tooltipleft";
}
tooltip
.addClass(clasAdd)
.removeClass(clasRem)
.html(o.tooltiphtml(data))
.css({
display:'block',
top: y+'px',
left: left,
right: right
});
});
self.bind('vizualizeOut',function visualizeTooltipOut(e,data){
tooltip.css({display:'none'});
});
});
})(jQuery);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
<html>
<body>
<p>An automated payout completed.</p>
<p>Amount: {$DATA.amount}</p>
<br/>
<br/>
</body>
</html>

View File

@ -0,0 +1,11 @@
<html>
<body>
<p>One of your workers is currently IDLE: {$DATA.worker}</p>
<p>We have not received any shares for this worker in the past 10 minutes.</p>
<p>Since monitoring is enabled for this worker, this notification was sent.</p>
<br />
<p>Please check your workers!</p>
<br/>
<br/>
</body>
</html>

View File

@ -0,0 +1,8 @@
<html>
<body>
<p>An manual payout request completed.</p>
<p>Amount: {$DATA.amount}</p>
<br/>
<br/>
</body>
</html>

View File

@ -0,0 +1,7 @@
<html>
<body>
<p>A new block has been discovered!</p>
<br/>
<br/>
</body>
</html>

View File

@ -1 +1 @@
[ {$WEBSITENAME} ] Password Reset Request [ {$WEBSITENAME} ] {$SUBJECT}

View File

@ -7,22 +7,23 @@
<tbody><tr><td>Username: </td><td>{$GLOBAL.userdata.username}</td></tr> <tbody><tr><td>Username: </td><td>{$GLOBAL.userdata.username}</td></tr>
<tr><td>User Id: </td><td>{$GLOBAL.userdata.id}</td></tr> <tr><td>User Id: </td><td>{$GLOBAL.userdata.id}</td></tr>
<tr><td>API Key: </td><td>{$GLOBAL.userdata.api_key}</td></tr> <tr><td>API Key: </td><td>{$GLOBAL.userdata.api_key}</td></tr>
<tr><td>E-Mail: </td><td><input type="text" name="email" value="{$GLOBAL.userdata.email|escape}" size="20"></td></tr>
<tr><td>Payment Address: </td><td><input type="text" name="paymentAddress" value="{$smarty.request.paymentAddress|default:$GLOBAL.userdata.coin_address|escape}" size="40"></td></tr> <tr><td>Payment Address: </td><td><input type="text" name="paymentAddress" value="{$smarty.request.paymentAddress|default:$GLOBAL.userdata.coin_address|escape}" size="40"></td></tr>
<tr><td>Donation %: </td><td><input type="text" name="donatePercent" value="{$smarty.request.donatePercent|default:$GLOBAL.userdata.donate_percent|escape}" size="4"><font size="1"> [donation amount in percent (example: 0.5)]</font></td></tr> <tr><td>Donation %: </td><td><input type="text" name="donatePercent" value="{$smarty.request.donatePercent|default:$GLOBAL.userdata.donate_percent|escape}" size="4"><font size="1"> [donation amount in percent (example: 0.5)]</font></td></tr>
<tr><td>Automatic Payout Threshold: </td><td valign="top"><input type="text" name="payoutThreshold" value="{$smarty.request.payoutThreshold|default:$GLOBAL.userdata.ap_threshold|escape}" size="5" maxlength="5"> <font size="1">[1-250 LTC. Set to '0' for no auto payout]</font></td></tr> <tr><td>Automatic Payout Threshold: </td><td valign="top"><input type="text" name="payoutThreshold" value="{$smarty.request.payoutThreshold|default:$GLOBAL.userdata.ap_threshold|escape}" size="5" maxlength="5"> <font size="1">[{$GLOBAL.config.ap_threshold.min}-{$GLOBAL.config.ap_threshold.max} {$GLOBAL.config.currency}. Set to '0' for no auto payout]</font></td></tr>
<tr><td>4 digit PIN: </td><td><input type="password" name="authPin" size="4" maxlength="4"><font size="1"> [The 4 digit PIN you chose when registering]</font></td></tr> <tr><td>4 digit PIN: </td><td><input type="password" name="authPin" size="4" maxlength="4"><font size="1"> [The 4 digit PIN you chose when registering]</font></td></tr>
</tbody></table> </tbody></table>
<input type="submit" class="submit long" value="Update Settings"></form> <input type="submit" class="submit long" value="Update Settings"></form>
{include file="global/block_footer.tpl"} {include file="global/block_footer.tpl"}
{include file="global/block_header.tpl" BLOCK_HEADER="Cash Out"} {include file="global/block_header.tpl" BLOCK_HEADER="Cash Out"}
<ul><li><font color="">Please note: a 0.1 ltc transaction will apply when processing "On-Demand" manual payments</font></li></ul> <ul><li><font color="">Please note: a {$GLOBAL.config.txfee} {$GLOBAL.config.currency} transaction will apply when processing "On-Demand" manual payments</font></li></ul>
<form action="{$smarty.server.PHP_SELF}" method="post"> <form action="{$smarty.server.PHP_SELF}" method="post">
<input type="hidden" name="page" value="{$smarty.request.page|escape}"> <input type="hidden" name="page" value="{$smarty.request.page|escape}">
<input type="hidden" name="action" value="{$smarty.request.action|escape}"> <input type="hidden" name="action" value="{$smarty.request.action|escape}">
<input type="hidden" name="do" value="cashOut"> <input type="hidden" name="do" value="cashOut">
<table> <table>
<tbody><tr><td>Account Balance: &nbsp;&nbsp;&nbsp;</td><td>{$GLOBAL.userdata.balance|escape} LTC</td></tr> <tbody><tr><td>Account Balance: &nbsp;&nbsp;&nbsp;</td><td>{$GLOBAL.userdata.balance.confirmed|escape} {$GLOBAL.config.currency}</td></tr>
<tr><td>Payout to: </td><td><h6>{$GLOBAL.userdata.coin_address|escape}</h6></td></tr> <tr><td>Payout to: </td><td><h6>{$GLOBAL.userdata.coin_address|escape}</h6></td></tr>
<tr><td>4 digit PIN: </td><td><input type="password" name="authPin" size="4" maxlength="4"></td></tr> <tr><td>4 digit PIN: </td><td><input type="password" name="authPin" size="4" maxlength="4"></td></tr>
</tbody></table> </tbody></table>

View File

@ -0,0 +1,84 @@
{include file="global/block_header.tpl" ALIGN="left" BLOCK_HEADER="Notification Settings"}
<form action="{$smarty.server.PHP_SELF}" method="POST">
<input type="hidden" name="page" value="{$smarty.request.page}">
<input type="hidden" name="action" value="{$smarty.request.action}">
<input type="hidden" name="do" value="save">
<table width="100%">
<tr>
<th class="left">Type</th>
<th class="center">Active</th>
</tr>
<tr>
<td class="left">IDLE Worker</td>
<td class="center">
<input type="hidden" name="data[idle_worker]" value="0" />
<input type="checkbox" name="data[idle_worker]" id="data[idle_worker]" value="1"{if $SETTINGS['idle_worker']}checked{/if} />
<label for="data[idle_worker]"></label>
</td>
</tr>
<tr>
<td class="left">New Blocks</td>
<td class="center">
<input type="hidden" name="data[new_block]" value="0" />
<input type="checkbox" name="data[new_block]" id="data[new_block]" value="1"{if $SETTINGS['new_block']}checked{/if} />
<label for="data[new_block]"></label>
</td>
</tr>
<tr>
<td class="left">Auto Payout</td>
<td class="center">
<input type="hidden" name="data[auto_payout]" value="0" />
<input type="checkbox" name="data[auto_payout]" id="data[auto_payout]" value="1"{if $SETTINGS['auto_payout']}checked{/if} />
<label for="data[auto_payout]"></label>
</td>
</tr>
<tr>
<td class="left">Manual Payout</td>
<td class="center">
<input type="hidden" name="data[manual_payout]" value="0" />
<input type="checkbox" name="data[manual_payout]" id="data[manual_payout]" value="1"{if $SETTINGS['manual_payout']}checked{/if} />
<label for="data[manual_payout]"></label>
</td>
</tr>
<tr>
<td colspan="2" class="center">
<input type="submit" class="submit small" value="Update">
</td>
</tr>
</table>
</form>
{include file="global/block_footer.tpl"}
{include file="global/block_header.tpl" ALIGN="right" BLOCK_HEADER="Notification History"}
<center>
{include file="global/pagination.tpl"}
<table width="100%" class="pagesort">
<thead style="font-size:13px;">
<tr>
<th class="center" style="cursor: pointer;">ID</th>
<th class="center" style="cursor: pointer;">Time</th>
<th class="center" style="cursor: pointer;">Type</th>
<th class="center" style="cursor: pointer;">Active</th>
</tr>
</thead>
<tbody style="font-size:12px;">
{section notification $NOTIFICATIONS}
<tr class="{cycle values="odd,even"}">
<td class="center">{$NOTIFICATIONS[notification].id}</td>
<td class="center">{$NOTIFICATIONS[notification].time}</td>
<td class="center">
{if $NOTIFICATIONS[notification].type == new_block}New Block
{else if $NOTIFICATIONS[notification].type == auto_payout}Auto Payout
{else if $NOTIFICATIONS[notification].type == idle_worker}IDLE Worker
{else if $NOTIFICATIONS[notification].type == manual_payout}Manual Payout
{/if}
</td>
<td class="center">
<img src="{$PATH}/images/{if $NOTIFICATIONS[notification].active}success{else}error{/if}.gif" />
</td>
</tr>
{/section}
</tbody>
</table>
</center>
{include file="global/block_footer.tpl"}

View File

@ -1,7 +1,8 @@
{include file="global/block_header.tpl" BLOCK_HEADER="Transaction Log" BUTTONS=array(Confirmed,Unconfirmed,Orphan)} {include file="global/block_header.tpl" BLOCK_HEADER="Transaction Log" BUTTONS=array(Confirmed,Unconfirmed,Orphan)}
<div class="block_content tab_content" id="Confirmed" style="clear:;"> <div class="block_content tab_content" id="Confirmed" style="clear:;">
<center> <center>
<table cellpadding="1" cellspacing="1" width="98%" class="sortable"> {include file="global/pagination.tpl"}
<table cellpadding="1" cellspacing="1" width="98%" class="pagesort">
<thead style="font-size:13px;"> <thead style="font-size:13px;">
<tr> <tr>
<th class="header" style="cursor: pointer;">TX #</th> <th class="header" style="cursor: pointer;">TX #</th>
@ -15,11 +16,15 @@
<tbody style="font-size:12px;"> <tbody style="font-size:12px;">
{section transaction $TRANSACTIONS} {section transaction $TRANSACTIONS}
{if ( {if (
($TRANSACTIONS[transaction].type == 'Credit' and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations) (($TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus')and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations)
or ($TRANSACTIONS[transaction].type == 'Donation' and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations) or ($TRANSACTIONS[transaction].type == 'Donation' and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations)
or ($TRANSACTIONS[transaction].type == 'Fee' and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations) or ($TRANSACTIONS[transaction].type == 'Fee' and $TRANSACTIONS[transaction].confirmations >= $GLOBAL.confirmations)
or $TRANSACTIONS[transaction].type == 'Credit_PPS'
or $TRANSACTIONS[transaction].type == 'Fee_PPS'
or $TRANSACTIONS[transaction].type == 'Donation_PPS'
or $TRANSACTIONS[transaction].type == 'Debit_AP' or $TRANSACTIONS[transaction].type == 'Debit_AP'
or $TRANSACTIONS[transaction].type == 'Debit_MP' or $TRANSACTIONS[transaction].type == 'Debit_MP'
or $TRANSACTIONS[transaction].type == 'TXFee'
)} )}
<tr class="{cycle values="odd,even"}"> <tr class="{cycle values="odd,even"}">
<td>{$TRANSACTIONS[transaction].id}</td> <td>{$TRANSACTIONS[transaction].id}</td>
@ -27,7 +32,7 @@
<td>{$TRANSACTIONS[transaction].type}</td> <td>{$TRANSACTIONS[transaction].type}</td>
<td>{$TRANSACTIONS[transaction].coin_address}</td> <td>{$TRANSACTIONS[transaction].coin_address}</td>
<td>{if $TRANSACTIONS[transaction].height == 0}n/a{else}{$TRANSACTIONS[transaction].height}{/if}</td> <td>{if $TRANSACTIONS[transaction].height == 0}n/a{else}{$TRANSACTIONS[transaction].height}{/if}</td>
<td><font color="{if $TRANSACTIONS[transaction].type == Credit}green{else}red{/if}">{$TRANSACTIONS[transaction].amount}</td> <td><font color="{if $TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Credit_PPS' or $TRANSACTIONS[transaction].type == 'Bonus'}green{else}red{/if}">{$TRANSACTIONS[transaction].amount}</td>
</tr> </tr>
{/if} {/if}
{/section} {/section}
@ -42,7 +47,8 @@
</div> </div>
<div class="block_content tab_content" id="Unconfirmed" style=""> <div class="block_content tab_content" id="Unconfirmed" style="">
<center> <center>
<table cellpadding="1" cellspacing="1" width="98%" class="sortable"> {include file="global/pagination.tpl" ID=2}
<table cellpadding="1" cellspacing="1" width="98%" class="pagesort2">
<thead style="font-size:13px;"> <thead style="font-size:13px;">
<tr> <tr>
<th class="header" style="cursor: pointer;">TX #</th> <th class="header" style="cursor: pointer;">TX #</th>
@ -56,7 +62,7 @@
<tbody style="font-size:12px;"> <tbody style="font-size:12px;">
{section transaction $TRANSACTIONS} {section transaction $TRANSACTIONS}
{if ( {if (
$TRANSACTIONS[transaction].type == 'Credit' && $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations ($TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus') and $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations
or ($TRANSACTIONS[transaction].type == 'Donation' and $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations) or ($TRANSACTIONS[transaction].type == 'Donation' and $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations)
or ($TRANSACTIONS[transaction].type == 'Fee' and $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations) or ($TRANSACTIONS[transaction].type == 'Fee' and $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations)
)} )}
@ -66,9 +72,9 @@
<td>{$TRANSACTIONS[transaction].type}</td> <td>{$TRANSACTIONS[transaction].type}</td>
<td>{$TRANSACTIONS[transaction].coin_address}</td> <td>{$TRANSACTIONS[transaction].coin_address}</td>
<td>{if $TRANSACTIONS[transaction].height == 0}n/a{else}{$TRANSACTIONS[transaction].height}{/if}</td> <td>{if $TRANSACTIONS[transaction].height == 0}n/a{else}{$TRANSACTIONS[transaction].height}{/if}</td>
<td><font color="{if $TRANSACTIONS[transaction].type == Credit}green{else}red{/if}">{$TRANSACTIONS[transaction].amount}</td> <td><font color="{if $TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus'}green{else}red{/if}">{$TRANSACTIONS[transaction].amount}</td>
</tr> </tr>
{if $TRANSACTIONS[transaction].type == Credit} {if $TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus'}
{assign var="credits" value="`$credits+$TRANSACTIONS[transaction].amount`"} {assign var="credits" value="`$credits+$TRANSACTIONS[transaction].amount`"}
{else} {else}
{assign var="debits" value="`$debits+$TRANSACTIONS[transaction].amount`"} {assign var="debits" value="`$debits+$TRANSACTIONS[transaction].amount`"}
@ -86,7 +92,8 @@
</div> </div>
<div class="block_content tab_content" id="Orphan" style=""> <div class="block_content tab_content" id="Orphan" style="">
<center> <center>
<table cellpadding="1" cellspacing="1" width="98%" class="sortable"> {include file="global/pagination.tpl"}
<table cellpadding="1" cellspacing="1" width="98%" class="pagesort3">
<thead style="font-size:13px;"> <thead style="font-size:13px;">
<tr> <tr>
<th class="header" style="cursor: pointer;">TX #</th> <th class="header" style="cursor: pointer;">TX #</th>
@ -103,6 +110,7 @@
$TRANSACTIONS[transaction].type == 'Orphan_Credit' $TRANSACTIONS[transaction].type == 'Orphan_Credit'
or $TRANSACTIONS[transaction].type == 'Orphan_Donation' or $TRANSACTIONS[transaction].type == 'Orphan_Donation'
or $TRANSACTIONS[transaction].type == 'Orphan_Fee' or $TRANSACTIONS[transaction].type == 'Orphan_Fee'
or $TRANSACTIONS[transaction].type == 'Orphan_Bonus'
)} )}
<tr class="{cycle values="odd,even"}"> <tr class="{cycle values="odd,even"}">
<td>{$TRANSACTIONS[transaction].id}</td> <td>{$TRANSACTIONS[transaction].id}</td>
@ -110,9 +118,9 @@
<td>{$TRANSACTIONS[transaction].type}</td> <td>{$TRANSACTIONS[transaction].type}</td>
<td>{$TRANSACTIONS[transaction].coin_address}</td> <td>{$TRANSACTIONS[transaction].coin_address}</td>
<td>{if $TRANSACTIONS[transaction].height == 0}n/a{else}{$TRANSACTIONS[transaction].height}{/if}</td> <td>{if $TRANSACTIONS[transaction].height == 0}n/a{else}{$TRANSACTIONS[transaction].height}{/if}</td>
<td><font color="{if $TRANSACTIONS[transaction].type == Orphan_Credit}green{else}red{/if}">{$TRANSACTIONS[transaction].amount}</td> <td><font color="{if $TRANSACTIONS[transaction].type == 'Orphan_Credit' or $TRANSACTIONS[transaction].type == 'Orphan_Bonus'}green{else}red{/if}">{$TRANSACTIONS[transaction].amount}</td>
</tr> </tr>
{if $TRANSACTIONS[transaction].type == Orphan_Credit} {if $TRANSACTIONS[transaction].type == 'Orphan_Credit' or $TRANSACTIONS[transaction].type == 'Orphan_Bonus'}
{assign var="orphan_credits" value="`$orphan_credits+$TRANSACTIONS[transaction].amount`"} {assign var="orphan_credits" value="`$orphan_credits+$TRANSACTIONS[transaction].amount`"}
{else} {else}
{assign var="orphan_debits" value="`$orphan_debits+$TRANSACTIONS[transaction].amount`"} {assign var="orphan_debits" value="`$orphan_debits+$TRANSACTIONS[transaction].amount`"}

View File

@ -1,9 +1,4 @@
{include file="global/block_header.tpl" BLOCK_HEADER="My Workers"} {include file="global/block_header.tpl" BLOCK_HEADER="My Workers"}
<ul><li><font color="red">
CAUTION! </font>Deletion of a worker could cause all associated shares for that worker to be lost.
Do not delete Workers unless you are certain all of their shares have been counted or that you have never used that worker account.
</li></ul>
<center> <center>
<form action="{$smarty.server.PHP_SELF}" method="post"> <form action="{$smarty.server.PHP_SELF}" method="post">
<input type="hidden" name="page" value="{$smarty.request.page}"> <input type="hidden" name="page" value="{$smarty.request.page}">
@ -14,18 +9,23 @@
<tr> <tr>
<td>Worker Name</td> <td>Worker Name</td>
<td>Password</td> <td>Password</td>
<td>Active</td> <td class="center">Active</td>
<td>Khash/s</td> <td class="center">Monitor</td>
<td class="right">Khash/s</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&nbsp;</td> <td>&nbsp;</td>
</tr> </tr>
{section worker $WORKERS} {section worker $WORKERS}
{assign var="username" value="."|escape|explode:$WORKERS[worker].username:2} {assign var="username" value="."|escape|explode:$WORKERS[worker].username:2}
<tr> <tr>
<td{if $WORKERS[worker].active == 1} style="color: orange"{/if}>{$username.0|escape}.<input name="data[{$WORKERS[worker].id}][username]" value="{$username.1|escape}" size="10" /></td> <td{if $WORKERS[worker].active} style="color: orange"{/if}>{$username.0|escape}.<input name="data[{$WORKERS[worker].id}][username]" value="{$username.1|escape}" size="10" /></td>
<td><input type="text" name="data[{$WORKERS[worker].id}][password]" value="{$WORKERS[worker].password|escape}" size="10"></td> <td><input type="text" name="data[{$WORKERS[worker].id}][password]" value="{$WORKERS[worker].password|escape}" size="10"></td>
<td>{if $WORKERS[worker].active == 1}Y{else}N{/if}</td> <td class="center"><img src="{$PATH}/images/{if $WORKERS[worker].active}success{else}error{/if}.gif" /></td>
<td>{$WORKERS[worker].hashrate}</td> <td class="center">
<input type="checkbox" name="data[{$WORKERS[worker].id}][monitor]" value="1" id="data[{$WORKERS[worker].id}][monitor]" {if $WORKERS[worker].monitor}checked{/if} />
<label for="data[{$WORKERS[worker].id}][monitor]"></label>
</td>
<td class="right">{$WORKERS[worker].hashrate|number_format}</td>
<td align="right"><a href="{$smarty.server.PHP_SELF}?page={$smarty.request.page|escape}&action={$smarty.request.action|escape}&do=delete&id={$WORKERS[worker].id|escape}"><button style="padding:5px" type="button">Delete</button></a></td> <td align="right"><a href="{$smarty.server.PHP_SELF}?page={$smarty.request.page|escape}&action={$smarty.request.action|escape}&do=delete&id={$WORKERS[worker].id|escape}"><button style="padding:5px" type="button">Delete</button></a></td>
</tr> </tr>
{/section} {/section}

View File

@ -0,0 +1,3 @@
{include file="global/block_header.tpl" BLOCK_HEADER="Admin Panel"}
<p>Welcome to the admin panel. Please select an option from the drop-down menu.</p>
{include file="global/block_footer.tpl"}

View File

@ -0,0 +1,89 @@
<script language="javascript">
function storeLock(id) {
$.ajax({
type: "POST",
url: "{$smarty.server.PHP_SELF}",
data: "page={$smarty.request.page}&action={$smarty.request.action}&do=lock&account_id=" + id,
});
}
function storeAdmin(id) {
$.ajax({
type: "POST",
url: "{$smarty.server.PHP_SELF}",
data: "page={$smarty.request.page}&action={$smarty.request.action}&do=admin&account_id=" + id,
});
}
</script>
{include file="global/block_header.tpl" BLOCK_HEADER="Query User Database"}
<form action="{$smarty.server.PHP_SELF}" method="POST" id='query'>
<input type="hidden" name="page" value="{$smarty.request.page}">
<input type="hidden" name="action" value="{$smarty.request.action}">
<input type="text" class="pin" name="query" value="{$smarty.request.query|default:"%"}">
<input type="submit" class="submit small" value="Query">
</form>
{include file="global/block_footer.tpl"}
{include file="global/block_header.tpl" BLOCK_HEADER="User Information"}
<center>
{include file="global/pagination.tpl"}
</center>
<table width="100%" class="pagesort">
<thead>
<tr>
<th class="center">ID</th>
<th>Username</th>
<th>E-Mail</th>
<th class="right">Shares&nbsp;&nbsp;</th>
<th class="right">Hashrate&nbsp;&nbsp;</th>
<th class="right">Est. Donation&nbsp;&nbsp;</th>
<th class="right">Est. Payout&nbsp;&nbsp;&nbsp;</th>
<th class="right">Balance&nbsp;&nbsp;&nbsp;</th>
<th class="center">Admin</th>
<th class="center">Locked</th>
</tr>
</thead>
<tbody>
{section name=user loop=$USERS|default}
<tr>
<td class="center">{$USERS[user].id}</td>
<td>{$USERS[user].username}</td>
<td>{$USERS[user].email}</td>
<td class="right">{$USERS[user].shares}</td>
<td class="right">{$USERS[user].hashrate}</td>
<td class="right">{$USERS[user].payout.est_donation|number_format:"8"}</td>
<td class="right">{$USERS[user].payout.est_payout|number_format:"8"}</td>
<td class="right">{$USERS[user].balance|number_format:"8"}</td>
<td class="center">
<input type="hidden" name="admin[{$USERS[user].id}]" value="0"/>
<input type="checkbox" onclick="storeAdmin({$USERS[user].id})" name="admin[{$USERS[user].id}]" value="1" id="admin[{$USERS[user].id}]" {if $USERS[user].is_admin}checked{/if} />
<label for="admin[{$USERS[user].id}]"></label>
</td>
<td class="center">
<input type="hidden" name="locked[{$USERS[user].id}]" value="0"/>
<input type="checkbox" onclick="storeLock({$USERS[user].id})" name="locked[{$USERS[user].id}]" value="1" id="locked[{$USERS[user].id}]" {if $USERS[user].is_locked}checked{/if} />
<label for="locked[{$USERS[user].id}]"></label>
</td>
</tr>
{sectionelse}
<tr>
<td colspan="10"></td>
</tr>
{/section}
</tbody>
<tfoot>
<tr>
<th class="center">ID</th>
<th>Username</th>
<th>E-Mail</th>
<th class="right">Shares&nbsp;&nbsp;</th>
<th class="right">Hashrate&nbsp;&nbsp;</th>
<th class="right">Est. Donation&nbsp;&nbsp;</th>
<th class="right">Est. Payout&nbsp;&nbsp;&nbsp;</th>
<th class="right">Balance&nbsp;&nbsp;&nbsp;</th>
<th class="center">Admin</th>
<th class="center">Locked</th>
</tr>
</tfoot>
</table>
{include file="global/block_footer.tpl"}

View File

@ -0,0 +1,16 @@
{include file="global/block_header.tpl" BLOCK_HEADER="Wallet Information"}
<table width="350px">
<tr>
<th>Wallet Balance</th>
<td class="right">{$BALANCE|number_format:"8"}</td>
</tr>
<tr>
<th>Locked for users</th>
<td class="right">{$LOCKED|number_format:"8"}</td>
</tr>
<tr>
<th>Liquid Assets</th>
<td class="right">{($BALANCE - $LOCKED)|number_format:"8"}</td>
</tr>
</table>
{include file="global/block_footer.tpl"}

View File

@ -1,5 +1,5 @@
<center> <center>
Litecoin Pool using <a href="https://github.com/litecoin-project/litecoin">litecoind</a>, <a href="https://github.com/ArtForz/pushpool/tree/tenebrix">pushpoold</a><br/> Litecoin Pool using <a href="https://github.com/litecoin-project/litecoin">litecoind</a>, <a href="https://github.com/ArtForz/pushpool/tree/tenebrix">pushpoold</a>, <a href="https://github.com/viperaus/stratum-mining">stratum-mining</a></br>
<a href="https://github.com/TheSerapher/php-mmcfe-ng">mmcfe-ng</a> Website based on <a href="https://github.com/Greedi/mmcFE">mmcfe</a>, overhauled by TheSerapher, available on <a href="https://github.com/TheSerapher/php-mmcfe-ng">GitHub</a><br/> <a href="https://github.com/TheSerapher/php-mmcfe-ng">mmcfe-ng</a> Website based on mmcfe by <a href="https://bitcointalk.org/index.php?action=profile;u=19135">AnnihilaT</a> overhauled by TheSerapher, available on <a href="https://github.com/TheSerapher/php-mmcfe-ng">GitHub</a><br/>
<i style="color: grey">LTC: Lge95QR2frp9y1wJufjUPCycVsg5gLJPW8<br/></i><br/><br/> <i style="color: grey">LTC: Lge95QR2frp9y1wJufjUPCycVsg5gLJPW8<br/></i><br/><br/>
</center> </center>

View File

@ -4,9 +4,9 @@
<div id="ministats"> <div id="ministats">
<table border="0"> <table border="0">
<tr> <tr>
<td><li>LTC/usd: {$GLOBAL.price|default:"n/a"}&nbsp;&nbsp;&nbsp;&nbsp;</li></td> <td><li>{$GLOBAL.config.currency}/{$GLOBAL.config.price.currency}: {$GLOBAL.price|default:"n/a"|number_format:"4"}&nbsp;&nbsp;&nbsp;&nbsp;</li></td>
<td><li>Pool Hashrate: {$GLOBAL.hashrate / 1000} MH/s&nbsp;&nbsp;&nbsp;&nbsp;</li></td> <td><li>Pool Hashrate: {($GLOBAL.hashrate / 1000)|number_format:"3"} MH/s&nbsp;&nbsp;&nbsp;&nbsp;</li></td>
<td><li>Pool Sharerate: {$GLOBAL.sharerate} Shares/s&nbsp;&nbsp;&nbsp;&nbsp;</li></td> <td><li>Pool Sharerate: {$GLOBAL.sharerate|number_format:"2"} Shares/s&nbsp;&nbsp;&nbsp;&nbsp;</li></td>
<td><li>Pool Workers: {$GLOBAL.workers}&nbsp;&nbsp;&nbsp;&nbsp;</li></td> <td><li>Pool Workers: {$GLOBAL.workers}&nbsp;&nbsp;&nbsp;&nbsp;</li></td>
</tr> </tr>
</table> </table>

View File

@ -5,16 +5,24 @@
<ul> <ul>
<li><a href="{$smarty.server.PHP_SELF}?page=account&action=edit">Edit Account</a></li> <li><a href="{$smarty.server.PHP_SELF}?page=account&action=edit">Edit Account</a></li>
<li><a href="{$smarty.server.PHP_SELF}?page=account&action=workers">My Workers</a></li> <li><a href="{$smarty.server.PHP_SELF}?page=account&action=workers">My Workers</a></li>
<li><a href="{$smarty.server.PHP_SELF}?page=statistics&action=user">My Graphs</a></li>
<li><a href="{$smarty.server.PHP_SELF}?page=account&action=transactions">Transactions</a></li> <li><a href="{$smarty.server.PHP_SELF}?page=account&action=transactions">Transactions</a></li>
<li><a href="{$smarty.server.PHP_SELF}?page=account&action=notifications">Notifications</a></li>
</ul> </ul>
</li> </li>
{/if} {/if}
{if $smarty.session.AUTHENTICATED|default:"0" == 1 && $GLOBAL.userdata.admin == 1}<li><a href="#">Admin Panel</a></li>{/if} {if $smarty.session.AUTHENTICATED|default:"0" == 1 && $GLOBAL.userdata.is_admin == 1}
<li><a href="{$smarty.server.PHP_SELF}?page=statistics">Statistics</a> <li><a href="{$smarty.server.PHP_SELF}?page=admin">Admin Panel</a>
<ul>
<li><a href="{$smarty.server.PHP_SELF}?page=admin&action=user">User Info</a></li>
<li><a href="{$smarty.server.PHP_SELF}?page=admin&action=wallet">Wallet Info</a></li>
</ul>
</li>
{/if}
<li><a href="{$smarty.server.PHP_SELF}?page=statistics&action=pool">Statistics</a>
<ul> <ul>
<li><a href="{$smarty.server.PHP_SELF}?page=statistics&action=pool">Pool Stats</a></li> <li><a href="{$smarty.server.PHP_SELF}?page=statistics&action=pool">Pool Stats</a></li>
{if $smarty.session.AUTHENTICATED|default}<li><a href="{$smarty.server.PHP_SELF}?page=statistics&action=blocks">Block Stats</a></li>{/if} {if $smarty.session.AUTHENTICATED|default}<li><a href="{$smarty.server.PHP_SELF}?page=statistics&action=blocks">Block Stats</a></li>{/if}
{if $smarty.session.AUTHENTICATED|default}<li><a href="{$smarty.server.PHP_SELF}?page=statistics&action=graphs">Hashrate Graphs</a></li>{/if}
</ul> </ul>
</li> </li>
<li><a href="{$smarty.server.PHP_SELF}?page=gettingstarted">Getting Started</a></li> <li><a href="{$smarty.server.PHP_SELF}?page=gettingstarted">Getting Started</a></li>

View File

@ -0,0 +1,15 @@
<div id="pager{$ID|default:""}">
<form>
<img src="{$PATH}/images/first.png" class="first"/>
<img src="{$PATH}/images/prev.png" class="prev"/>
<input type="text" class="pagedisplay"/>
<img src="{$PATH}/images/next.png" class="next"/>
<img src="{$PATH}/images/last.png" class="last"/>
<select class="pagesize">
<option selected="selected" value="10">10</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="40">40</option>
</select>
</form>
</div>

View File

@ -6,8 +6,13 @@
</div> </div>
<div class="block_content" style="padding-top:10px;"> <div class="block_content" style="padding-top:10px;">
<table class="sidebar" style="width: 196px"> <table class="sidebar" style="width: 196px">
<tr><td colspan="2"><b>Your Hashrate</b></td></tr> <tr>
<tr><td colspan="2" class="right">{$GLOBAL.userdata.hashrate|number_format} KH/s</td></tr> <td colspan="2"><b><u>Your Stats</u></b></td>
</tr>
<tr>
<td><b>Hashrate</b></td>
<td class="right">{$GLOBAL.userdata.hashrate|number_format} KH/s</td>
</tr>
<tr> <tr>
<td colspan="2"><b><u>Unpaid Shares</u></b> <span id='tt'><img src='{$PATH}/images/questionmark.png' height='15px' width='15px' title='Submitted shares between the last 120 confirms block until now.'></span></td> <td colspan="2"><b><u>Unpaid Shares</u></b> <span id='tt'><img src='{$PATH}/images/questionmark.png' height='15px' width='15px' title='Submitted shares between the last 120 confirms block until now.'></span></td>
</tr> </tr>
@ -35,7 +40,7 @@
<td class="right"><i>{$GLOBAL.userdata.shares.invalid|number_format}</i><font size='1px'></font></td> <td class="right"><i>{$GLOBAL.userdata.shares.invalid|number_format}</i><font size='1px'></font></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><b><u>LTC Round Estimate</u></b></td> <td colspan="2"><b><u>{$GLOBAL.config.currency} Round Estimate</u></b></td>
</tr> </tr>
<tr> <tr>
<td><b>Block</b></td> <td><b>Block</b></td>
@ -54,8 +59,9 @@
<td class="right">{$GLOBAL.userdata.est_payout|number_format:"3"}</td> <td class="right">{$GLOBAL.userdata.est_payout|number_format:"3"}</td>
</tr> </tr>
<tr><td colspan="2">&nbsp;</td></tr> <tr><td colspan="2">&nbsp;</td></tr>
<tr><td colspan="2"><b><u>Account Balance</u></b></td></tr> <tr><td colspan="2"><b><u>{$GLOBAL.config.currency} Account Balance</u></b></td></tr>
<tr><td colspan="2" class="right"><b>{$GLOBAL.userdata.balance|default:"0"} LTC</td></tr> <tr><td>Confirmed</td><td class="right"><b>{$GLOBAL.userdata.balance.confirmed|default:"0"}</td></tr>
<tr><td>Unconfirmed</td><td class="right"><b>{$GLOBAL.userdata.balance.unconfirmed|default:"0"}</td></tr>
</table> </table>
</div> </div>
<div class="bendl"></div> <div class="bendl"></div>

View File

@ -0,0 +1,61 @@
<div class="block" style="clear:none; margin-top:15px; margin-left:13px;">
<div class="block_head">
<div class="bheadl"></div>
<div class="bheadr"></div>
<h1>Dashboard</h1>
</div>
<div class="block_content" style="padding-top:10px;">
<table class="sidebar" style="width: 196px">
<tr>
<td colspan="2"><b><u>Your Stats</u></b></td>
</tr>
<tr>
<td><b>Hashrate</b></td>
<td class="right">{$GLOBAL.userdata.hashrate|number_format} KH/s</td>
</tr>
<tr>
<td><b>Share Rate</b></td>
<td class="right">{$GLOBAL.userdata.sharerate|number_format:"2"} S/s</td>
</tr>
<tr>
<td><b>PPS Value</b></td>
<td class="right">{$GLOBAL.ppsvalue}</td>
</tr>
<tr>
<td colspan="2"><b><u>Round Shares</u></b> <span id='tt'><img src='{$PATH}/images/questionmark.png' height='15px' width='15px' title='Submitted shares since last found block (ie. round shares)'></span></td>
</tr>
<tr>
<td><b>Pool Valid</b></td>
<td class="right"><i>{$GLOBAL.roundshares.valid|number_format}</i></td>
</tr>
<tr>
<td><b>Pool Invalid</b></td>
<td class="right"><i>{$GLOBAL.roundshares.invalid|number_format}</i></td>
</tr>
<tr>
<td><b>Your Invalid</b></td>
<td class="right"><i>{$GLOBAL.userdata.shares.invalid|number_format}</i><font size='1px'></font></td>
</tr>
<tr><td colspan="2">&nbsp;</td></tr>
<tr><td colspan="2"><b><u>{$GLOBAL.config.currency} Estimates</u></b></td></tr>
<tr>
<td><b>in 24 hours</b></td>
<td class="right">{($GLOBAL.userdata.sharerate * 24 * 60 * 60 * $GLOBAL.ppsvalue)|number_format:"8"}</td>
</tr>
<tr>
<td><b>in 7 days</b></td>
<td class="right">{($GLOBAL.userdata.sharerate * 7 * 24 * 60 * 60 * $GLOBAL.ppsvalue)|number_format:"8"}</td>
</tr>
<tr>
<td><b>in 14 days</b></td>
<td class="right">{($GLOBAL.userdata.sharerate * 14 * 24 * 60 * 60 * $GLOBAL.ppsvalue)|number_format:"8"}</td>
</tr>
<tr><td colspan="2">&nbsp;</td></tr>
<tr><td colspan="2"><b><u>{$GLOBAL.config.currency} Account Balance</u></b></td></tr>
<tr><td>Confirmed</td><td class="right"><b>{$GLOBAL.userdata.balance.confirmed|default:"0"}</td></tr>
<tr><td>Unconfirmed</td><td class="right"><b>{$GLOBAL.userdata.balance.unconfirmed|default:"0"}</td></tr>
</table>
</div>
<div class="bendl"></div>
<div class="bendr"></div>
</div>

View File

@ -11,6 +11,7 @@
<script src="{$PATH}/js/jquery.tablesorter.min.js"></script> <script src="{$PATH}/js/jquery.tablesorter.min.js"></script>
<script src="{$PATH}/js/jquery.tablesorter.pager.js"></script> <script src="{$PATH}/js/jquery.tablesorter.pager.js"></script>
<script src="{$PATH}/js/jquery.visualize.js"></script> <script src="{$PATH}/js/jquery.visualize.js"></script>
<script src="{$PATH}/js/jquery.tooltip.visualize.js"></script>
<script src="{$PATH}/js/custom.js"></script> <script src="{$PATH}/js/custom.js"></script>
<script src="{$PATH}/js/tools.js"></script> <script src="{$PATH}/js/tools.js"></script>
<!--[if IE]><script type="text/javascript" src="{$PATH}/js/excanvas.js"></script><![endif]--> <!--[if IE]><script type="text/javascript" src="{$PATH}/js/excanvas.js"></script><![endif]-->
@ -46,7 +47,11 @@
<div class="block_content"> <div class="block_content">
<div class="sidebar"> <div class="sidebar">
{if $smarty.session.AUTHENTICATED|default} {if $smarty.session.AUTHENTICATED|default}
{include file="global/sidebar.tpl"} {if $GLOBAL.config.payout_system == 'pps'}
{include file="global/sidebar_pps.tpl"}
{else}
{include file="global/sidebar.tpl"}
{/if}
{else} {else}
{include file="global/login.tpl"} {include file="global/login.tpl"}
{/if} {/if}

View File

@ -3,13 +3,16 @@
<input type="hidden" name="page" value="{$smarty.request.page|escape}"> <input type="hidden" name="page" value="{$smarty.request.page|escape}">
<input type="hidden" name="action" value="register"> <input type="hidden" name="action" value="register">
<table width="90%" border="0"> <table width="90%" border="0">
<tbody><tr><td>Username:</td><td><input type="text" class="text tiny" name="username" value="{$smarty.post.username|escape}" size="15" maxlength="20"></td></tr> <tbody>
<tr><td>Password:</td><td><input type="password" class="text tiny" name="password1" value="" size="15" maxlength="20"></td></tr> <tr><td>Username:</td><td><input type="text" class="text tiny" name="username" value="{$smarty.post.username|escape}" size="15" maxlength="20"></td></tr>
<tr><td>Repeat Password:</td><td><input type="password" class="text tiny" name="password2" value="" size="15" maxlength="20"></td></tr> <tr><td>Password:</td><td><input type="password" class="text tiny" name="password1" value="" size="15" maxlength="20"></td></tr>
<tr><td>Email:</td><td><input type="text" name="email1" class="text small" value="{$smarty.post.email1|escape}" size="15"><font size="1"> (Optional) </font></td></tr> <tr><td>Repeat Password:</td><td><input type="password" class="text tiny" name="password2" value="" size="15" maxlength="20"></td></tr>
<tr><td>Email Repeat:</td><td><input type="text" class="text small" name="email2" value="{$smarty.post.email2|escape}" size="15"><font size="1"> (Optional) </font></td></tr> <tr><td>Email:</td><td><input type="text" name="email1" class="text small" value="{$smarty.post.email1|escape}" size="15"></td></tr>
<tr><td>PIN:</td><td><input type="password" class="text pin" name="pin" value="" size="4" maxlength="4"><font size="1"> (4 digit number. <b>Remember this pin!</b>)</font></td></tr> <tr><td>Email Repeat:</td><td><input type="text" class="text small" name="email2" value="{$smarty.post.email2|escape}" size="15"></td></tr>
</tbody></table> <tr><td>PIN:</td><td><input type="password" class="text pin" name="pin" value="" size="4" maxlength="4"><font size="1"> (4 digit number. <b>Remember this pin!</b>)</font></td></tr>
<input type="submit" class="submit small" value="Register"> <tr><td colspan="2">{nocache}{$RECAPTCHA}{/nocache}</td></tr>
<tr><td class="center"><input type="submit" class="submit small" value="Register"></td><td></td></tr>
</tbody>
</table>
</form> </form>
{include file="global/block_footer.tpl"} {include file="global/block_footer.tpl"}

View File

@ -0,0 +1,3 @@
{include file="global/block_header.tpl" BLOCK_HEADER="Registration disabled" BLOCK_STYLE="clear:none;"}
<br /><center><p><font size="5px">We are currently not accepting new user registrations.</font></p></center>
{include file="global/block_footer.tpl"}

View File

@ -1,37 +0,0 @@
{include file="global/block_header.tpl" BLOCK_HEADER="Last $BLOCKLIMIT Blocks Found" BLOCK_STYLE="clear:none;"}
<center>
<table class="stats_lastblocks" width="100%" style="font-size:13px;">
<thead>
<tr style="background-color:#B6DAFF;">
<th scope="col" align="left">Block</th>
<th scope="col" align="left">Validity</th>
<th scope="col" align="left">Finder</th>
<th scope="col" align="left">Date / Time</th>
<th class="right" scope="col">Difficulty</th>
<th class="right" scope="col">Shares</th>
</tr>
</thead>
<tbody>
{assign var=rank value=1}
{section block $BLOCKSFOUND}
<tr class="{cycle values="odd,even"}">
<td><a href="{$GLOBAL.blockexplorer}{$BLOCKSFOUND[block].height}" target="_blank">{$BLOCKSFOUND[block].height}</a></td>
<td>
{if $BLOCKSFOUND[block].confirmations >= $GLOBAL.confirmations}
<font color="green">Confirmed</font>
{else if $BLOCKSFOUND[block].confirmations == -1}
<font color="red">Orphan</font>
{else}{$GLOBAL.confirmations - $BLOCKSFOUND[block].confirmations} left{/if}</td>
<td>{$BLOCKSFOUND[block].finder|default:"unknown"}</td>
<td>{$BLOCKSFOUND[block].time|date_format:"%d/%m/%Y %H:%M:%S"}</td>
<td class="right">{$BLOCKSFOUND[block].difficulty|number_format:"8"}</td>
<td class="right">{$BLOCKSFOUND[block].shares|number_format}</td>
</tr>
{/section}
</tbody>
</table>
</center>
<ul>
<li>Note: <font color="orange">Round Earnings are not credited until {$GLOBAL.confirmations} confirms.</font></li>
</ul>
{include file="global/block_footer.tpl"}

View File

@ -0,0 +1,73 @@
{include file="global/block_header.tpl" BLOCK_HEADER="Block Shares" BLOCK_STYLE="clear:none;"}
<table width="70%" class="stats" rel="line">
<caption>Block Shares</caption>
<thead>
<tr>
{section block $BLOCKSFOUND step=-1 max=20}
<th scope="col">{$BLOCKSFOUND[block].height}</th>
{/section}
</th>
</thead>
<tbody>
<tr>
<th scope="row">Expected</th>
{section block $BLOCKSFOUND step=-1 max=20}
<td>{round(pow(2,32 - $GLOBAL.config.targetdiff) * $BLOCKSFOUND[block].difficulty)}</td>
{/section}
</tr>
<tr>
<th scope="row">Actual</th>
{section block $BLOCKSFOUND step=-1 max=20}
<td>{$BLOCKSFOUND[block].shares}</td>
{/section}
</tr>
</tbody>
</table>
<center><br>
<p style="padding-left:30px; padding-redight:30px; font-size:10px;">
The graph above illustrates N shares to find a block vs. E Shares expected to find a block based on
target and network difficulty and assuming a zero variance scenario.
</p></center>
{include file="global/block_footer.tpl"}
{include file="global/block_header.tpl" BLOCK_HEADER="Last $BLOCKLIMIT Blocks Found" BLOCK_STYLE="clear:none;"}
<center>
<table width="100%" style="font-size:13px;">
<thead>
<tr style="background-color:#B6DAFF;">
<th class="center">Block</th>
<th class="center">Validity</th>
<th>Finder</th>
<th class="center">Time</th>
<th class="right">Difficulty</th>
<th class="right">Expected Shares</th>
<th class="right">Actual Shares</th>
<th class="right">Percentage</th>
</tr>
</thead>
<tbody>
{assign var=rank value=1}
{section block $BLOCKSFOUND}
<tr class="{cycle values="odd,even"}">
<td class="center"><a href="{$GLOBAL.blockexplorer}{$BLOCKSFOUND[block].height}" target="_blank">{$BLOCKSFOUND[block].height}</a></td>
<td class="center">
{if $BLOCKSFOUND[block].confirmations >= $GLOBAL.confirmations}
<font color="green">Confirmed</font>
{else if $BLOCKSFOUND[block].confirmations == -1}
<font color="red">Orphan</font>
{else}{$GLOBAL.confirmations - $BLOCKSFOUND[block].confirmations} left{/if}</td>
<td>{$BLOCKSFOUND[block].finder|default:"unknown"}</td>
<td class="center">{$BLOCKSFOUND[block].time|date_format:"%d/%m %H:%M:%S"}</td>
<td class="right">{$BLOCKSFOUND[block].difficulty|number_format:"2"}</td>
<td class="right">{(pow(2,32 - $GLOBAL.config.targetdiff) * $BLOCKSFOUND[block].difficulty)|number_format}</td>
<td class="right">{$BLOCKSFOUND[block].shares|number_format}</td>
<td class="right">{($BLOCKSFOUND[block].shares / (pow(2,32 - $GLOBAL.config.targetdiff) * $BLOCKSFOUND[block].difficulty) * 100)|number_format:"2"}</td>
</tr>
{/section}
</tbody>
</table>
</center>
<ul>
<li>Note: <font color="orange">Round Earnings are not credited until {$GLOBAL.confirmations} confirms.</font></li>
</ul>
{include file="global/block_footer.tpl"}

View File

@ -0,0 +1,28 @@
{include file="global/block_header.tpl" BLOCK_HEADER="Last $BLOCKLIMIT Blocks Found" BLOCK_STYLE="clear:none;"}
<center>
<table width="100%" style="font-size:13px;">
<thead>
<tr style="background-color:#B6DAFF;">
<th class="center">Block</th>
<th>Finder</th>
<th class="center">Time</th>
<th class="right">Actual Shares</th>
</tr>
</thead>
<tbody>
{assign var=rank value=1}
{section block $BLOCKSFOUND}
<tr class="{cycle values="odd,even"}">
<td class="center"><a href="{$GLOBAL.blockexplorer}{$BLOCKSFOUND[block].height}" target="_blank">{$BLOCKSFOUND[block].height}</a></td>
<td>{$BLOCKSFOUND[block].finder|default:"unknown"}</td>
<td class="center">{$BLOCKSFOUND[block].time|date_format:"%d/%m %H:%M:%S"}</td>
<td class="right">{$BLOCKSFOUND[block].shares|number_format}</td>
</tr>
{/section}
</tbody>
</table>
</center>
<ul>
<li>Note: <font color="orange">Round Earnings are not credited until {$GLOBAL.confirmations} confirms.</font></li>
</ul>
{include file="global/block_footer.tpl"}

View File

@ -19,4 +19,5 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<li>These stats are also available in JSON format <a href="{$smarty.server.PHP_SELF}?page=api&action=public" target="_api">HERE</a></li>
{include file="global/block_footer.tpl"} {include file="global/block_footer.tpl"}

View File

@ -0,0 +1,43 @@
{if is_array($YOURHASHRATES) && is_array($POOLHASHRATES)}
<div class="block_content tab_content" id="both" style="padding-left:30px;">
{foreach from=array('area','pie') item=chartType}
<table width="60%" class="stats" rel="{$chartType}">
<caption>Your vs Pool Hashrate</caption>
<thead>
<tr>
<td></td>
{for $i=date('G') to 23}
<th scope="col">{$i}:00</th>
{/for}
{for $i=0 to date('G', time () - 60 * 60)}
<th scope="col">{$i}:00</th>
{/for}
</tr>
</thead>
<tbody>
<tr>
<th scope="row">{$smarty.session.USERDATA.username}</th>
{for $i=date('G') to 23}
<td>{$YOURHASHRATES.$i|default:"0"}</td>
{/for}
{for $i=0 to date('G', time() - 60 * 60)}
<td>{$YOURHASHRATES.$i|default:"0"}</td>
{/for}
</tr>
<tr>
<th scope="row">Pool</th>
{for $i=date('G') to 23}
<td>{$POOLHASHRATES.$i|default:"0"}</td>
{/for}
{for $i=0 to date('G', time() - 60 * 60)}
<td>{$POOLHASHRATES.$i|default:"0"}</td>
{/for}
</tr>
</tbody>
</table>
<br />
{/foreach}
</div>
{else}
<p><li>No shares available to start calculations</li></p>
{/if}

View File

@ -0,0 +1,5 @@
{include file="global/block_header.tpl" BLOCK_HEADER="24h Hashrate Statistics" BUTTONS=array(mine,pool,both)}
{include file="{$smarty.request.page}/{$smarty.request.action}/mine.tpl"}
{include file="{$smarty.request.page}/{$smarty.request.action}/pool.tpl"}
{include file="{$smarty.request.page}/{$smarty.request.action}/both.tpl"}
{include file="global/block_footer.tpl"}

View File

@ -0,0 +1,31 @@
{if is_array($YOURHASHRATES)}
<div class="block_content tab_content" id="mine" style="padding-left:30px;">
<table width="60%" class="stats" rel="area">
<caption>Your Hashrate</caption>
<thead>
<tr>
<td></td>
{for $i=date('G') to 23}
<th scope="col">{$i}:00</th>
{/for}
{for $i=0 to date('G', time () - 60 * 60)}
<th scope="col">{$i}:00</th>
{/for}
</tr>
</thead>
<tbody>
<tr>
<th scope="row">{$smarty.session.USERDATA.username}</th>
{for $i=date('G') to 23}
<td>{$YOURHASHRATES.$i|default:"0"}</td>
{/for}
{for $i=0 to date('G', time() - 60 * 60)}
<td>{$YOURHASHRATES.$i|default:"0"}</td>
{/for}
</tr>
</tbody>
</table>
</div>
{else}
<p><li>No shares available to start calculations</li></p>
{/if}

View File

@ -0,0 +1,31 @@
{if is_array($POOLHASHRATES)}
<div class="block_content tab_content" id="pool" style="padding-left:30px;">
<table width="60%" class="stats" rel="area">
<caption>Pool Hashrate</caption>
<thead>
<tr>
<td></td>
{for $i=date('G') to 23}
<th scope="col">{$i}:00</th>
{/for}
{for $i=0 to date('G', time () - 60 * 60)}
<th scope="col">{$i}:00</th>
{/for}
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Pool</th>
{for $i=date('G') to 23}
<td>{$POOLHASHRATES.$i|default:"0"}</td>
{/for}
{for $i=0 to date('G', time() - 60 * 60)}
<td>{$POOLHASHRATES.$i|default:"0"}</td>
{/for}
</tr>
</tbody>
</table>
</div>
{else}
<p><li>No shares available to start calculations</li></p>
{/if}

View File

@ -4,15 +4,19 @@
{include file="statistics/pool/contributors_hashrate.tpl"} {include file="statistics/pool/contributors_hashrate.tpl"}
{include file="global/block_header.tpl" BLOCK_HEADER="Server Stats" BLOCK_STYLE="clear:all;" STYLE="padding-left:5px;padding-right:5px;"} {include file="global/block_header.tpl" ALIGN="left" BLOCK_HEADER="Server Stats" BLOCK_STYLE="clear:all;" STYLE="padding-left:5px;padding-right:5px;"}
<table class="" width="100%" style="font-size:13px;"> <table class="" width="100%" style="font-size:13px;">
<tbody> <tbody>
<tr> <tr>
<td class="leftheader">Pool Hash Rate</td> <td class="leftheader">Pool Hash Rate</td>
<td>{$GLOBAL.hashrate / 1000} Mhash/s</td> <td>{($GLOBAL.hashrate / 1000)|number_format:"3"} Mhash/s</td>
</tr> </tr>
<tr> <tr>
<td class="leftheader">Current Workers Mining</td> <td class="leftheader">Pool Efficiency</td>
<td>{(100 - (100 / $GLOBAL.roundshares.valid * $GLOBAL.roundshares.invalid))|number_format:"2"} %</td>
</tr>
<tr>
<td class="leftheader">Current Active Workers</td>
<td>{$GLOBAL.workers}</td> <td>{$GLOBAL.workers}</td>
</tr> </tr>
<tr> <tr>
@ -32,8 +36,8 @@
<td>{$ESTTIME|seconds_to_words}</td> <td>{$ESTTIME|seconds_to_words}</td>
</tr> </tr>
<tr> <tr>
<td class="leftheader">Est. Avg. Shares per Round</td> <td class="leftheader">Est. Shares this Round</td>
<td>{($ESTTIME * $GLOBAL.sharerate)|number_format:"0"}</td> <td>{(pow(2, 32 - $GLOBAL.config.targetdiff) * $DIFFICULTY)|number_format:"0"} <font size="1">(done: {(100 / (pow(2, 32 - $GLOBAL.config.targetdiff) * $DIFFICULTY) * $GLOBAL.roundshares.valid)|number_format:"2"} %)</td>
</tr> </tr>
<tr> <tr>
<td class="leftheader">Time Since Last Block</td> <td class="leftheader">Time Since Last Block</td>
@ -44,6 +48,6 @@
{include file="global/block_footer.tpl"} {include file="global/block_footer.tpl"}
{include file="statistics/blocks/blocks_found.tpl"} {include file="statistics/blocks/small_table.tpl" ALIGN="right" SHORT=true}
{include file="global/block_footer.tpl"} {include file="global/block_footer.tpl"}

View File

@ -6,18 +6,21 @@
<th align="left">Rank</th> <th align="left">Rank</th>
<th align="left" scope="col">User Name</th> <th align="left" scope="col">User Name</th>
<th class="right" scope="col">KH/s</th> <th class="right" scope="col">KH/s</th>
<th class="right">Ł/Day<font size="1"> (est)</font></th> <th class="right">{$GLOBAL.config.currency}/Day</th>
<th class="right">{$GLOBAL.config.price.currency}/Day</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{assign var=rank value=1} {assign var=rank value=1}
{assign var=listed value=0} {assign var=listed value=0}
{section contrib $CONTRIBHASHES} {section contrib $CONTRIBHASHES}
{math assign="estday" equation="round(reward / ( diff * pow(2,32) / ( hashrate * 1000 ) / 3600 / 24), 3)" diff=$DIFFICULTY reward=$REWARD hashrate=$CONTRIBHASHES[contrib].hashrate}
<tr{if $GLOBAL.userdata.username == $CONTRIBHASHES[contrib].account}{assign var=listed value=1} style="background-color:#99EB99;"{else} class="{cycle values="odd,even"}"{/if}> <tr{if $GLOBAL.userdata.username == $CONTRIBHASHES[contrib].account}{assign var=listed value=1} style="background-color:#99EB99;"{else} class="{cycle values="odd,even"}"{/if}>
<td>{$rank++}</td> <td>{$rank++}</td>
<td>{$CONTRIBHASHES[contrib].account}</td> <td>{$CONTRIBHASHES[contrib].account}</td>
<td class="right">{$CONTRIBHASHES[contrib].hashrate|number_format}</td> <td class="right">{$CONTRIBHASHES[contrib].hashrate|number_format}</td>
<td class="right">{math equation="round(reward / ( diff * pow(2,32) / ( hashrate * 1000 ) / 3600 / 24), 3)" diff=$DIFFICULTY reward=$REWARD hashrate=$CONTRIBHASHES[contrib].hashrate}</td> <td class="right">{$estday|number_format:"3"}</td>
<td class="right">{($estday * $GLOBAL.price)|default:"n/a"|number_format:"2"}</td>
</tr> </tr>
{/section} {/section}
{if $listed != 1} {if $listed != 1}
@ -25,7 +28,8 @@
<td>n/a</td> <td>n/a</td>
<td>{$GLOBAL.userdata.username}</td> <td>{$GLOBAL.userdata.username}</td>
<td class="right">{$GLOBAL.userdata.hashrate}</td> <td class="right">{$GLOBAL.userdata.hashrate}</td>
<td class="right">{math equation="round(reward / ( diff * pow(2,32) / ( hashrate * 1000 ) / 3600 / 24), 3)" diff=$DIFFICULTY reward=$REWARD hashrate=$GLOBAL.userdata.hashrate}</td> <td class="right">{$estday|number_format:"3"|default:"n/a"}</td>
<td class="right">{($estday * $GLOBAL.price)|default:"n/a"|number_format:"2"}</td>
</tr> </tr>
{/if} {/if}
</tbody> </tbody>

View File

@ -22,7 +22,7 @@
<tr style="background-color:#99EB99;"> <tr style="background-color:#99EB99;">
<td>n/a</td> <td>n/a</td>
<td>{$GLOBAL.userdata.username}</td> <td>{$GLOBAL.userdata.username}</td>
<td class="right">{$GLOBAL.userdata.shares.valid}</td> <td class="right">{$GLOBAL.userdata.shares.valid|number_format}</td>
</tr> </tr>
{/if} {/if}
</tbody> </tbody>

View File

@ -1,22 +0,0 @@
{include file="global/block_header.tpl" BLOCK_HEADER="Pool Statistics"}
<table class="" width="50%" style="font-size:14px;">
<tbody>
<tr>
<td class="leftheader">Pool Hash Rate</td>
<td>{$GLOBAL.hashrate / 1000} Mhash/s</td>
</tr>
<tr>
<td class="leftheader">Current Total Miners</td>
<td>{$GLOBAL.workers}</td>
</tr>
<tr>
<td class="leftheader">Current Block</td>
<td><a href="http://explorer.litecoin.net/search?q={$CURRENTBLOCK}" target="_new">{$CURRENTBLOCK}</a></td>
</tr>
<tr>
<td class="leftheader">Current Difficulty</td>
<td><a href="http://allchains.info/" target="_new">{$DIFFICULTY}</a></td>
</tr>
</tbody>
</table>
{include file="global/block_footer.tpl"}

View File

@ -1,23 +0,0 @@
{include file="global/block_header.tpl" BLOCK_HEADER="Your Average Hourly Hash Rate" BUTTONS=array(mine,pool,both)}
<div class="block_content tab_content" id="mine" style="padding-left:30px;">
<table class="stats" rel="area" cellpadding="0">
<caption>Your Hashrate&nbsp;</caption>
<thead>
<tr>
<td></td>
{section hashrate $YOURHASHRATES}
<th scope="col">{$YOURHASHRATES[hashrate].hour}</th>
{/section}
</tr>
</thead>
<tbody>
<tr>
<th scope="row">{$GLOBAL.USERDATA.username}</th>
{section hashrate $YOURHASHRATES}
<td>{$YOURHASHRATES[hashrate].hashrate|number_format}</td>
{/section}
</tr>
</tbody>
</table>
</div>
{include file="global/block_footer.tpl"}

View File

@ -0,0 +1,17 @@
CREATE TABLE IF NOT EXISTS `notifications` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(25) NOT NULL,
`data` varchar(255) NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT '1',
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`account_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `active` (`active`),
KEY `data` (`data`),
KEY `account_id` (`account_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `notification_settings` (
`type` varchar(15) NOT NULL,
`account_id` int(11) NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View File

@ -0,0 +1,2 @@
ALTER TABLE `accounts` ADD `is_locked` BOOLEAN NOT NULL DEFAULT FALSE AFTER `email` ;
ALTER TABLE `accounts` CHANGE `admin` `is_admin` BOOLEAN NOT NULL DEFAULT FALSE ;

View File

@ -0,0 +1 @@
ALTER TABLE `transactions` CHANGE `type` `type` ENUM( 'Credit', 'Debit_MP', 'Debit_AP', 'Donation', 'Fee', 'Orphan_Credit', 'Orphan_Fee', 'Orphan_Donation', 'Bonus', 'Orphan_Bonus' ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;

View File

@ -0,0 +1 @@
ALTER TABLE `settings` CHANGE `setting` `name` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ;

View File

@ -0,0 +1 @@
ALTER TABLE `accounts` ADD `failed_logins` INT( 5 ) UNSIGNED NULL DEFAULT '0' AFTER `is_locked` ;

View File

@ -0,0 +1 @@
ALTER TABLE `transactions` CHANGE `type` `type` ENUM( 'Credit', 'Debit_MP', 'Debit_AP', 'Donation', 'Fee', 'Orphan_Credit', 'Orphan_Fee', 'Orphan_Donation', 'Credit_PPS', 'Fee_PPS', 'Donation_PPS', 'TXFee' ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ;

View File

@ -0,0 +1 @@
ALTER TABLE `notification_settings` ADD `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST ;

View File

@ -0,0 +1 @@
ALTER TABLE `transactions` CHANGE `type` `type` ENUM( 'Credit', 'Debit_MP', 'Debit_AP', 'Donation', 'Fee', 'Orphan_Credit', 'Orphan_Fee', 'Orphan_Donation', 'Bonus', 'Orphan_Bonus', 'Credit_PPS', 'Debit_PPS', 'Donation_PPS' ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;

View File

@ -1,37 +1,22 @@
-- phpMyAdmin SQL Dump SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
-- version 3.5.8.1deb1
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: May 31, 2013 at 02:31 PM
-- Server version: 5.5.31-0ubuntu0.13.04.1
-- PHP Version: 5.4.9-4ubuntu2
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00"; SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */; /*!40101 SET NAMES utf8 */;
-- CREATE DATABASE IF NOT EXISTS `mmcfe_ng` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
-- Database: `mmcfe_ng` USE `mmcfe_ng`;
--
-- --------------------------------------------------------
--
-- Table structure for table `accounts`
--
CREATE TABLE IF NOT EXISTS `accounts` ( CREATE TABLE IF NOT EXISTS `accounts` (
`id` int(255) NOT NULL AUTO_INCREMENT, `id` int(255) NOT NULL AUTO_INCREMENT,
`admin` int(1) NOT NULL DEFAULT '0', `is_admin` tinyint(1) NOT NULL DEFAULT '0',
`username` varchar(40) NOT NULL, `username` varchar(40) NOT NULL,
`pass` varchar(255) NOT NULL, `pass` varchar(255) NOT NULL,
`email` varchar(255) DEFAULT NULL COMMENT 'Assocaited email: used for validating users, and re-setting passwords', `email` varchar(255) DEFAULT NULL COMMENT 'Assocaited email: used for validating users, and re-setting passwords',
`is_locked` tinyint(1) NOT NULL DEFAULT '0',
`failed_logins` int(5) unsigned DEFAULT '0',
`loggedIp` varchar(255) DEFAULT NULL, `loggedIp` varchar(255) DEFAULT NULL,
`sessionTimeoutStamp` int(255) DEFAULT NULL, `sessionTimeoutStamp` int(255) DEFAULT NULL,
`pin` varchar(255) NOT NULL COMMENT 'four digit pin to allow account changes', `pin` varchar(255) NOT NULL COMMENT 'four digit pin to allow account changes',
@ -44,12 +29,6 @@ CREATE TABLE IF NOT EXISTS `accounts` (
UNIQUE KEY `username` (`username`) UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `blocks`
--
CREATE TABLE IF NOT EXISTS `blocks` ( CREATE TABLE IF NOT EXISTS `blocks` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`height` int(10) unsigned NOT NULL, `height` int(10) unsigned NOT NULL,
@ -65,13 +44,39 @@ CREATE TABLE IF NOT EXISTS `blocks` (
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `height` (`height`,`blockhash`), UNIQUE KEY `height` (`height`,`blockhash`),
KEY `time` (`time`) KEY `time` (`time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Discovered blocks persisted from Litecoin Service'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Discovered blocks persisted from Litecoin Service';
-- -------------------------------------------------------- CREATE TABLE IF NOT EXISTS `notifications` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`type` varchar(25) NOT NULL,
`data` varchar(255) NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT '1',
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`account_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `active` (`active`),
KEY `data` (`data`),
KEY `account_id` (`account_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- CREATE TABLE IF NOT EXISTS `notification_settings` (
-- Table structure for table `settings` `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
-- `type` varchar(15) NOT NULL,
`account_id` int(11) NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `pool_worker` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`account_id` int(255) NOT NULL,
`username` char(50) DEFAULT NULL,
`password` char(255) DEFAULT NULL,
`monitor` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
KEY `account_id` (`account_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `settings` ( CREATE TABLE IF NOT EXISTS `settings` (
`name` varchar(255) NOT NULL, `name` varchar(255) NOT NULL,
@ -80,12 +85,6 @@ CREATE TABLE IF NOT EXISTS `settings` (
UNIQUE KEY `setting` (`name`) UNIQUE KEY `setting` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `shares`
--
CREATE TABLE IF NOT EXISTS `shares` ( CREATE TABLE IF NOT EXISTS `shares` (
`id` bigint(30) NOT NULL AUTO_INCREMENT, `id` bigint(30) NOT NULL AUTO_INCREMENT,
`rem_host` varchar(255) NOT NULL, `rem_host` varchar(255) NOT NULL,
@ -100,13 +99,7 @@ CREATE TABLE IF NOT EXISTS `shares` (
KEY `upstream_result` (`upstream_result`), KEY `upstream_result` (`upstream_result`),
KEY `our_result` (`our_result`), KEY `our_result` (`our_result`),
KEY `username` (`username`) KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `shares_archive`
--
CREATE TABLE IF NOT EXISTS `shares_archive` ( CREATE TABLE IF NOT EXISTS `shares_archive` (
`id` int(255) unsigned NOT NULL AUTO_INCREMENT, `id` int(255) unsigned NOT NULL AUTO_INCREMENT,
@ -119,13 +112,7 @@ CREATE TABLE IF NOT EXISTS `shares_archive` (
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `share_id` (`share_id`), UNIQUE KEY `share_id` (`share_id`),
KEY `time` (`time`) KEY `time` (`time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Archive shares for potential later debugging purposes'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Archive shares for potential later debugging purposes';
-- --------------------------------------------------------
--
-- Table structure for table `statistics_shares`
--
CREATE TABLE IF NOT EXISTS `statistics_shares` ( CREATE TABLE IF NOT EXISTS `statistics_shares` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
@ -136,18 +123,12 @@ CREATE TABLE IF NOT EXISTS `statistics_shares` (
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `account_id` (`account_id`), KEY `account_id` (`account_id`),
KEY `block_id` (`block_id`) KEY `block_id` (`block_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `transactions`
--
CREATE TABLE IF NOT EXISTS `transactions` ( CREATE TABLE IF NOT EXISTS `transactions` (
`id` int(255) NOT NULL AUTO_INCREMENT, `id` int(255) NOT NULL AUTO_INCREMENT,
`account_id` int(255) unsigned NOT NULL, `account_id` int(255) unsigned NOT NULL,
`type` enum('Credit','Debit_MP','Debit_AP','Donation','Fee','Orphan_Credit','Orphan_Fee','Orphan_Donation') DEFAULT NULL, `type` enum('Credit','Debit_MP','Debit_AP','Donation','Fee','Orphan_Credit','Orphan_Fee','Orphan_Donation','Credit_PPS','Fee_PPS','Donation_PPS','TXFee') DEFAULT NULL,
`coin_address` varchar(255) DEFAULT NULL, `coin_address` varchar(255) DEFAULT NULL,
`amount` double DEFAULT '0', `amount` double DEFAULT '0',
`block_id` int(255) DEFAULT NULL, `block_id` int(255) DEFAULT NULL,
@ -156,24 +137,7 @@ CREATE TABLE IF NOT EXISTS `transactions` (
KEY `block_id` (`block_id`), KEY `block_id` (`block_id`),
KEY `account_id` (`account_id`), KEY `account_id` (`account_id`),
KEY `type` (`type`) KEY `type` (`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `pool_worker`
--
CREATE TABLE IF NOT EXISTS `pool_worker` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`account_id` int(255) NOT NULL,
`username` char(50) DEFAULT NULL,
`password` char(255) DEFAULT NULL,
`hashrate` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
KEY `account_id` (`account_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;