commit
f61bb5c11a
23
README.md
23
README.md
@ -29,6 +29,8 @@ Donors
|
||||
These people have supported this project with a donation:
|
||||
|
||||
* [obigal](https://github.com/obigal)
|
||||
* [vias](https://github.com/vias79)
|
||||
* [WKNiGHT](https://github.com/WKNiGHT-)
|
||||
|
||||
Requirements
|
||||
============
|
||||
@ -57,10 +59,11 @@ The following feature have been implemented so far:
|
||||
|
||||
* Reward Systems
|
||||
* Propotional
|
||||
* (Planned) PPS
|
||||
* PPS
|
||||
* (Planned) PPLNS
|
||||
* Use of memcache for statistics instead of a cronjob
|
||||
* Web User accounts
|
||||
* Re-Captcha protected registration form
|
||||
* Worker accounts
|
||||
* Worker activity (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
|
||||
* Pool donations
|
||||
* Pool fees
|
||||
* Manual payout with 0.1 LTC fee
|
||||
* Auto payout with 0.1 LTC fee
|
||||
* Manual payout
|
||||
* Auto payout
|
||||
* 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
|
||||
============
|
||||
|
||||
@ -27,6 +27,9 @@ if ($bitcoin->can_connect() !== true) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Mark this job as active
|
||||
$setting->setValue('auto_payout_active', 1);
|
||||
|
||||
// Fetch all users with setup AP
|
||||
$users = $user->getAllAutoPayout();
|
||||
|
||||
@ -35,11 +38,12 @@ if (! empty($users)) {
|
||||
verbose("UserID\tUsername\tBalance\tThreshold\tAddress\t\t\t\t\tStatus\n\n");
|
||||
|
||||
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");
|
||||
|
||||
// Only run if balance meets threshold and can pay the transaction fee
|
||||
if ($dBalance > $aUserData['ap_threshold'] && $dBalance > 0.1) {
|
||||
// Only run if balance meets threshold and can pay the potential transaction fee
|
||||
if ($dBalance > $aUserData['ap_threshold'] && $dBalance > $config['txfee']) {
|
||||
// Validate address against RPC
|
||||
try {
|
||||
$bitcoin->validateaddress($aUserData['coin_address']);
|
||||
@ -48,20 +52,29 @@ if (! empty($users)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Send balance - 0.1 Fee to address
|
||||
// Send balance, fees are reduced later by RPC Server
|
||||
try {
|
||||
$bitcoin->sendtoaddress($aUserData['coin_address'], $dBalance - 0.1);
|
||||
$bitcoin->sendtoaddress($aUserData['coin_address'], $dBalance);
|
||||
} catch (BitcoinClientException $e) {
|
||||
verbose("SEND FAILED\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create transaction record
|
||||
if ($transaction->addTransaction($aUserData['id'], $dBalance, 'Debit_AP', NULL, $aUserData['coin_address'], 0.1)) {
|
||||
verbose("OK\n");
|
||||
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'])) {
|
||||
// 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 {
|
||||
verbose("FAILED\n");
|
||||
}
|
||||
|
||||
} else {
|
||||
verbose("SKIPPED\n");
|
||||
}
|
||||
@ -69,3 +82,8 @@ if (! empty($users)) {
|
||||
} else {
|
||||
verbose("No user has configured their AP > 0\n");
|
||||
}
|
||||
|
||||
// Mark this job as inactive
|
||||
$setting->setValue('auto_payout_active', 0);
|
||||
|
||||
?>
|
||||
|
||||
@ -39,9 +39,8 @@ if ( $bitcoin->can_connect() === true ){
|
||||
|
||||
// Nothing to do so bail out
|
||||
if (empty($aTransactions['transactions'])) {
|
||||
verbose("No new transactions since last block\n");
|
||||
verbose("No new RPC transactions since last block\n");
|
||||
} else {
|
||||
|
||||
// Table header
|
||||
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
|
||||
$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
|
||||
verbose("Block ID\tBlock Height\tShare ID\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("Unable to fetch blocks upstream share\n");
|
||||
verbose($share->getError() . "\n");
|
||||
continue;
|
||||
// Store new information
|
||||
$strStatus = "OK";
|
||||
if (!$block->setShareId($aBlock['id'], $iCurrentUpstreamId))
|
||||
$strStatus = "Share ID Failed";
|
||||
if (!$block->setFinder($aBlock['id'], $iAccountId))
|
||||
$strStatus = "Finder Failed";
|
||||
if (!$block->setShares($aBlock['id'], $iRoundShares))
|
||||
$strStatus = "Shares Failed";
|
||||
if ($config['block_bonus'] > 0 && !$transaction->addTransaction($iAccountId, $config['block_bonus'], 'Bonus', $aBlock['id'])) {
|
||||
$strStatus = "Bonus Failed";
|
||||
}
|
||||
|
||||
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
56
cronjobs/notifications.php
Executable 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
127
cronjobs/pps_payout.php
Executable 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);
|
||||
}
|
||||
}
|
||||
?>
|
||||
@ -22,6 +22,12 @@ 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'] != 'prop') {
|
||||
verbose("Please activate this cron in configuration via payout_system = prop\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Fetch all unaccounted blocks
|
||||
$aAllBlocks = $block->getAllUnaccounted('ASC');
|
||||
if (empty($aAllBlocks)) {
|
||||
@ -32,25 +38,16 @@ if (empty($aAllBlocks)) {
|
||||
$count = 0;
|
||||
foreach ($aAllBlocks as $iIndex => $aBlock) {
|
||||
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'];
|
||||
$aAccountShares = $share->getSharesForAccounts($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)) {
|
||||
verbose("\nNo shares found for this block\n\n");
|
||||
sleep(2);
|
||||
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
|
||||
verbose("ID\tUsername\tValid\tInvalid\tPercentage\tPayout\t\tDonation\tFee\t\tStatus\n");
|
||||
|
||||
@ -16,7 +16,7 @@ PIDFILE='/tmp/mmcfe-ng-cron.pid'
|
||||
CRONHOME='.'
|
||||
|
||||
# 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
|
||||
CRONARGS="-v"
|
||||
|
||||
@ -26,10 +26,10 @@ define("BASEPATH", "../public/");
|
||||
define("SECURITY", 1);
|
||||
|
||||
// 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
|
||||
require_once(BASEPATH . INCLUDE_DIR . '/autoloader.inc.php');
|
||||
require_once(INCLUDE_DIR . '/autoloader.inc.php');
|
||||
|
||||
// Parse command line
|
||||
$options = getopt("v");
|
||||
|
||||
49
cronjobs/statistics.php
Executable file
49
cronjobs/statistics.php
Executable 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");
|
||||
}
|
||||
}
|
||||
?>
|
||||
@ -14,3 +14,5 @@ require_once(CLASS_DIR . '/worker.class.php');
|
||||
require_once(CLASS_DIR . '/statistics.class.php');
|
||||
require_once(CLASS_DIR . '/transaction.class.php');
|
||||
require_once(CLASS_DIR . '/setting.class.php');
|
||||
require_once(CLASS_DIR . '/mail.class.php');
|
||||
require_once(CLASS_DIR . '/notification.class.php');
|
||||
|
||||
@ -246,8 +246,8 @@ class BitcoinClientException extends ErrorException {
|
||||
}
|
||||
}
|
||||
|
||||
require_once(BASEPATH . INCLUDE_DIR . "/xmlrpc.inc.php");
|
||||
require_once(BASEPATH . INCLUDE_DIR . "/jsonrpc.inc.php");
|
||||
require_once(INCLUDE_DIR . "/xmlrpc.inc.php");
|
||||
require_once(INCLUDE_DIR . "/jsonrpc.inc.php");
|
||||
|
||||
/**
|
||||
* Bitcoin client class for access to a Bitcoin server via JSON-RPC-HTTP[S]
|
||||
|
||||
@ -43,6 +43,18 @@ class Block {
|
||||
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
|
||||
* @param order string Sort order, default ASC
|
||||
|
||||
67
public/include/classes/mail.class.php
Normal file
67
public/include/classes/mail.class.php
Normal 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);
|
||||
?>
|
||||
191
public/include/classes/notification.class.php
Normal file
191
public/include/classes/notification.class.php
Normal 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);
|
||||
|
||||
?>
|
||||
@ -44,6 +44,21 @@ class Share {
|
||||
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
|
||||
* @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");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $last) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||
$this->oUpstream = $result->fetch_object();
|
||||
return true;
|
||||
if (!empty($this->oUpstream->account) && is_int($this->oUpstream->id))
|
||||
return true;
|
||||
}
|
||||
// Catchall
|
||||
return false;
|
||||
|
||||
@ -13,6 +13,7 @@ if (!defined('SECURITY'))
|
||||
class Statistics {
|
||||
private $sError = '';
|
||||
private $table = 'statistics_shares';
|
||||
private $getcache = true;
|
||||
|
||||
public function __construct($debug, $mysqli, $config, $share, $user, $block, $memcache) {
|
||||
$this->debug = $debug;
|
||||
@ -34,6 +35,14 @@ class Statistics {
|
||||
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) {
|
||||
if ($bState ===! true) {
|
||||
$this->debug->append("Failed to prepare statement: " . $this->mysqli->error);
|
||||
@ -54,7 +63,7 @@ class Statistics {
|
||||
$stmt = $this->mysqli->prepare("
|
||||
SELECT b.*, a.username as finder
|
||||
FROM " . $this->block->getTableName() . " AS b
|
||||
LEFT JOIN accounts AS a
|
||||
LEFT JOIN " . $this->user->getTableName() . " AS a
|
||||
ON b.account_id = a.id
|
||||
ORDER BY height DESC LIMIT ?");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $limit) && $stmt->execute() && $result = $stmt->get_result())
|
||||
@ -88,14 +97,10 @@ class Statistics {
|
||||
**/
|
||||
public function getCurrentHashrate() {
|
||||
$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("
|
||||
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)
|
||||
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");
|
||||
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)
|
||||
");
|
||||
// Catchall
|
||||
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);
|
||||
@ -111,12 +116,8 @@ class Statistics {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
if ($data = $this->memcache->get(__FUNCTION__)) return $data;
|
||||
$stmt = $this->mysqli->prepare("
|
||||
SELECT ROUND(SUM(sharerate) / 600, 2) AS sharerate FROM
|
||||
(
|
||||
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");
|
||||
SELECT ROUND(COUNT(id) / 600, 2) AS sharerate FROM " . $this->share->getTableName() . " WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE)
|
||||
");
|
||||
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setCache(__FUNCTION__, $result->fetch_object()->sharerate);
|
||||
// Catchall
|
||||
$this->debug->append("Failed to fetch share rate: " . $this->mysqli->error);
|
||||
@ -130,7 +131,7 @@ class Statistics {
|
||||
**/
|
||||
public function getRoundShares() {
|
||||
$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("
|
||||
SELECT
|
||||
( SELECT IFNULL(count(id), 0)
|
||||
@ -155,7 +156,7 @@ class Statistics {
|
||||
**/
|
||||
public function getUserShares($account_id) {
|
||||
$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("
|
||||
SELECT
|
||||
(
|
||||
@ -183,12 +184,42 @@ class Statistics {
|
||||
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
|
||||
* @param account_id integer User ID
|
||||
* @return data integer Current Hashrate in khash/s
|
||||
**/
|
||||
public function getUserHashrate($account_id) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
|
||||
$stmt = $this->mysqli->prepare("
|
||||
SELECT ROUND(COUNT(s.id) * POW(2, " . $this->config['difficulty'] . ")/600/1000) AS hashrate
|
||||
@ -204,6 +235,28 @@ class Statistics {
|
||||
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
|
||||
* @param worker_id int Worker ID to fetch hashrate for
|
||||
@ -234,7 +287,7 @@ class Statistics {
|
||||
**/
|
||||
public function getTopContributors($type='shares', $limit=15) {
|
||||
$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) {
|
||||
case 'shares':
|
||||
$stmt = $this->mysqli->prepare("
|
||||
@ -242,6 +295,7 @@ class Statistics {
|
||||
COUNT(id) AS shares,
|
||||
SUBSTRING_INDEX( username, '.', 1 ) AS account
|
||||
FROM " . $this->share->getTableName() . "
|
||||
WHERE our_result = 'Y'
|
||||
GROUP BY account
|
||||
ORDER BY shares DESC
|
||||
LIMIT ?");
|
||||
@ -258,6 +312,7 @@ class Statistics {
|
||||
SUBSTRING_INDEX( username, '.', 1 ) AS account
|
||||
FROM " . $this->share->getTableName() . "
|
||||
WHERE time > DATE_SUB(now(), INTERVAL 10 MINUTE)
|
||||
AND our_result = 'Y'
|
||||
GROUP BY account
|
||||
ORDER BY hashrate DESC LIMIT ?");
|
||||
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
|
||||
* Not working yet since I was not able to solve this via SQL queries
|
||||
* @param account_id int User ID
|
||||
* @return data array NOT FINISHED YET
|
||||
**/
|
||||
@ -279,24 +333,50 @@ class Statistics {
|
||||
if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
|
||||
$stmt = $this->mysqli->prepare("
|
||||
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
|
||||
FROM " . $this->share->getTableName() . " AS s, accounts AS a
|
||||
WHERE time < NOW() - INTERVAL 1 HOUR AND time > NOW() - INTERVAL 25 HOUR
|
||||
FROM " . $this->share->getTableName() . " AS s, accounts AS a
|
||||
WHERE time < NOW() - INTERVAL 1 HOUR
|
||||
AND time > NOW() - INTERVAL 25 HOUR
|
||||
AND a.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
||||
AND a.id = ?
|
||||
GROUP BY HOUR(time)
|
||||
UNION ALL
|
||||
SELECT
|
||||
ROUND(COUNT(s.id) * POW(2, 12)/600/1000) AS hashrate,
|
||||
HOUR(s.time) AS hour
|
||||
FROM " . $this->share->getArchiveTableName() . " AS s, accounts AS a
|
||||
WHERE time < NOW() - INTERVAL 1 HOUR AND time > NOW() - INTERVAL 25 HOUR
|
||||
AND a.username = SUBSTRING_INDEX( s.username, '.', 1 )
|
||||
AND a.id = ?
|
||||
GROUP BY HOUR(time)");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $account_id, $account_id) && $stmt->execute() && $result = $stmt->get_result())
|
||||
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_all(MYSQLI_ASSOC), 3600);
|
||||
GROUP BY HOUR(time)
|
||||
");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $account_id) && $stmt->execute() && $result = $stmt->get_result()) {
|
||||
$aData = array();
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$aData[$row['hour']] = $row['hashrate'];
|
||||
}
|
||||
return $this->memcache->setCache(__FUNCTION__ . $account_id, $aData);
|
||||
}
|
||||
// Catchall
|
||||
$this->debug->append("Failed to fetch hourly hashrate: " . $this->mysqli->error);
|
||||
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
|
||||
$this->debug->append("Failed to fetch hourly hashrate: " . $this->mysqli->error);
|
||||
return false;
|
||||
|
||||
@ -55,35 +55,23 @@ class Transaction {
|
||||
**/
|
||||
public function setOrphan($block_id) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
$stmt = $this->mysqli->prepare("
|
||||
UPDATE $this->table
|
||||
SET type = 'Orphan_Credit'
|
||||
WHERE type = 'Credit'
|
||||
AND block_id = ?
|
||||
");
|
||||
if (!($this->checkStmt($stmt) && $stmt->bind_param('i', $block_id) && $stmt->execute())) {
|
||||
$this->debug->append("Failed to set orphan credit transactions for $block_id");
|
||||
return false;
|
||||
}
|
||||
$stmt = $this->mysqli->prepare("
|
||||
UPDATE $this->table
|
||||
SET type = 'Orphan_Fee'
|
||||
WHERE type = 'Fee'
|
||||
AND block_id = ?
|
||||
");
|
||||
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;
|
||||
$aOrphans = array(
|
||||
'Credit' => 'Orphan_Credit',
|
||||
'Fee' => 'Orphan_Fee',
|
||||
'Donation' => 'Orphan_Donation',
|
||||
'Bonus' => 'Orphan_Bonus'
|
||||
);
|
||||
foreach ($aOrphans as $from => $to) {
|
||||
$stmt = $this->mysqli->prepare("
|
||||
UPDATE $this->table
|
||||
SET type = '$to'
|
||||
WHERE type = '$from'
|
||||
AND block_id = ?
|
||||
");
|
||||
if (!($this->checkStmt($stmt) && $stmt->bind_param('i', $block_id) && $stmt->execute())) {
|
||||
$this->debug->append("Failed to set orphan $from => $to transactions for $block_id");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -130,6 +118,7 @@ class Transaction {
|
||||
|
||||
/**
|
||||
* Get total balance for all users locked in wallet
|
||||
* This includes any outstanding unconfirmed transactions!
|
||||
* @param none
|
||||
* @return data double Amount locked for users
|
||||
**/
|
||||
@ -142,8 +131,10 @@ class Transaction {
|
||||
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 = 'Credit'
|
||||
AND b.confirmations >= ?
|
||||
WHERE (
|
||||
( t.type IN ('Credit','Bonus') AND b.confirmations >= ? ) OR
|
||||
( t.type = 'Credit_PPS' )
|
||||
)
|
||||
) AS t1,
|
||||
(
|
||||
SELECT sum(t.amount) AS debit
|
||||
@ -152,10 +143,12 @@ class Transaction {
|
||||
) AS t2,
|
||||
(
|
||||
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
|
||||
WHERE t.type IN ('Donation','Fee')
|
||||
AND b.confirmations >= ?
|
||||
WHERE (
|
||||
( t.type IN ('Donation','Fee') AND b.confirmations >= ? ) OR
|
||||
t.type IN ('Donation_PPS','Fee_PPS','TXFee')
|
||||
)
|
||||
) AS t3");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $this->config['confirmations'], $this->config['confirmations']) && $stmt->execute() && $stmt->bind_result($dBalance) && $stmt->fetch())
|
||||
return $dBalance;
|
||||
@ -173,14 +166,19 @@ class Transaction {
|
||||
public function getBalance($account_id) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
$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
|
||||
(
|
||||
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 = 'Credit'
|
||||
AND b.confirmations >= ?
|
||||
WHERE
|
||||
(
|
||||
( t.type IN ('Credit','Bonus') AND b.confirmations >= ? ) OR
|
||||
( t.type = 'Credit_PPS' )
|
||||
)
|
||||
AND t.account_id = ?
|
||||
) AS t1,
|
||||
(
|
||||
@ -193,20 +191,41 @@ class Transaction {
|
||||
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 >= ?
|
||||
WHERE
|
||||
(
|
||||
( t.type IN ('Donation','Fee') AND b.confirmations >= ? ) OR
|
||||
( t.type IN ('Donation_PPS', 'Fee_PPS', 'TXFee') )
|
||||
)
|
||||
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)) {
|
||||
$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()) {
|
||||
$this->debug->append("Unable to execute statement: " . $stmt->error);
|
||||
$this->setErrorMessage("Fetching balance failed");
|
||||
}
|
||||
$result = $stmt->get_result();
|
||||
$stmt->close();
|
||||
return $result->fetch_object()->balance;
|
||||
return $result->fetch_assoc();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -26,35 +26,75 @@ class User {
|
||||
public function getError() {
|
||||
return $this->sError;
|
||||
}
|
||||
|
||||
public function getUserName($id) {
|
||||
return $this->getSingle($id, 'username', 'id');
|
||||
}
|
||||
|
||||
public function getUserId($username) {
|
||||
return $this->getSingle($username, 'id', 'username', 's');
|
||||
}
|
||||
|
||||
public function getUserEmail($username) {
|
||||
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) {
|
||||
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) {
|
||||
return $this->getSingle($token, 'id', 'token', 's');
|
||||
}
|
||||
|
||||
public function setUserToken($id) {
|
||||
$field = array(
|
||||
'name' => 'token',
|
||||
'type' => 's',
|
||||
'value' => hash('sha256', $id.time().$this->salt)
|
||||
);
|
||||
public function isLocked($id) {
|
||||
return $this->getUserLocked($id);
|
||||
}
|
||||
public function isAdmin($id) {
|
||||
return $this->getUserAdmin($id);
|
||||
}
|
||||
public function changeLocked($id) {
|
||||
$field = array('name' => 'is_locked', 'type' => 'i', 'value' => !$this->isLocked($id));
|
||||
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
|
||||
@ -65,10 +105,20 @@ class User {
|
||||
public function checkLogin($username, $password) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
$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->setUserFailed($this->getUserId($username), 0);
|
||||
$this->setUserIp($this->getUserId($username), $_SERVER['REMOTE_ADDR']);
|
||||
return true;
|
||||
}
|
||||
$this->setErrorMessage("Invalid username or password");
|
||||
if ($id = $this->getUserId($username))
|
||||
$this->incUserFailed($id);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -166,7 +216,7 @@ class User {
|
||||
**/
|
||||
private function updateSingle($id, $field) {
|
||||
$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())
|
||||
return true;
|
||||
$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
|
||||
* @return bool
|
||||
**/
|
||||
public function updateAccount($userID, $address, $threshold, $donate) {
|
||||
public function updateAccount($userID, $address, $threshold, $donate, $email) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
$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)));
|
||||
|
||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET coin_address = ?, ap_threshold = ?, donate_percent = ? WHERE id = ?");
|
||||
$stmt->bind_param('sddi', $address, $threshold, $donate, $userID);
|
||||
$stmt->execute();
|
||||
if ( $stmt->errno == 0 ) {
|
||||
$stmt->close();
|
||||
// We passed all validation checks so update the account
|
||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET coin_address = ?, ap_threshold = ?, donate_percent = ?, email = ? WHERE id = ?");
|
||||
if ($this->checkStmt($stmt) && $stmt->bind_param('sddsi', $address, $threshold, $donate, $email, $userID) && $stmt->execute())
|
||||
return true;
|
||||
}
|
||||
// Catchall
|
||||
$this->setErrorMessage('Failed to update your account');
|
||||
$this->debug->append('Account update failed: ' . $this->mysqli->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -266,15 +336,15 @@ class User {
|
||||
private function checkUserPassword($username, $password) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
$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)) {
|
||||
$stmt->bind_param('ss', $username, hash('sha256', $password.$this->salt));
|
||||
$stmt->execute();
|
||||
$stmt->bind_result($row_username, $row_id);
|
||||
$stmt->bind_result($row_username, $row_id, $row_admin);
|
||||
$stmt->fetch();
|
||||
$stmt->close();
|
||||
// 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 false;
|
||||
@ -303,7 +373,8 @@ class User {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
session_destroy();
|
||||
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");
|
||||
$stmt = $this->mysqli->prepare("
|
||||
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
|
||||
FROM $this->table
|
||||
WHERE id = ? LIMIT 0,1");
|
||||
@ -363,7 +434,7 @@ class User {
|
||||
$this->setErrorMessage( 'Password do not match' );
|
||||
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' );
|
||||
return false;
|
||||
}
|
||||
@ -383,7 +454,7 @@ class User {
|
||||
");
|
||||
} else {
|
||||
$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)
|
||||
");
|
||||
}
|
||||
@ -455,6 +526,7 @@ class User {
|
||||
}
|
||||
$smarty->assign('TOKEN', $token);
|
||||
$smarty->assign('USERNAME', $username);
|
||||
$smarty->assign('SUBJECT', 'Password Reset Request');
|
||||
$smarty->assign('WEBSITENAME', $this->config['website']['name']);
|
||||
$headers = 'From: Website Administration <' . $this->config['website']['email'] . ">\n";
|
||||
$headers .= "MIME-Version: 1.0\n";
|
||||
@ -470,6 +542,22 @@ class User {
|
||||
}
|
||||
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
|
||||
|
||||
@ -43,17 +43,60 @@ class Worker {
|
||||
public function updateWorkers($account_id, $data) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
$username = $this->user->getUserName($account_id);
|
||||
$iFailed = 0;
|
||||
foreach ($data as $key => $value) {
|
||||
// Prefix the WebUser to Worker name
|
||||
$value['username'] = "$username." . $value['username'];
|
||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET password = ?, username = ? WHERE account_id = ? AND id = ?");
|
||||
if ($this->checkStmt($stmt)) {
|
||||
if (!$stmt->bind_param('ssii', $value['password'], $value['username'], $account_id, $key)) return false;
|
||||
if (!$stmt->execute()) return false;
|
||||
$stmt->close();
|
||||
}
|
||||
$stmt = $this->mysqli->prepare("UPDATE $this->table SET password = ?, username = ?, monitor = ? WHERE account_id = ? AND id = ?");
|
||||
if ( ! ( $this->checkStmt($stmt) && $stmt->bind_param('ssiii', $value['password'], $value['username'], $value['monitor'], $account_id, $key) && $stmt->execute()) )
|
||||
$iFailed++;
|
||||
}
|
||||
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) {
|
||||
$this->debug->append("STA " . __METHOD__, 4);
|
||||
$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 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
|
||||
|
||||
@ -23,13 +23,29 @@ define('SALT', 'PLEASEMAKEMESOMETHINGRANDOM');
|
||||
$config = array(
|
||||
'price' => array(
|
||||
'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(
|
||||
'registration' => true, // Allow new users to register
|
||||
'name' => 'The Pool',
|
||||
'slogan' => 'Resistance is futile',
|
||||
'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?
|
||||
'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
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
<?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()) {
|
||||
// Tempalte specifics
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
}
|
||||
|
||||
// Tempalte specifics
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
?>
|
||||
|
||||
@ -4,61 +4,77 @@
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
|
||||
if (!$_SESSION['AUTHENTICATED']) {
|
||||
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 {
|
||||
switch ($_POST['do']) {
|
||||
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');
|
||||
if ($user->isAuthenticated()) {
|
||||
if ( ! $user->checkPin($_SESSION['USERDATA']['id'], @$_POST['authPin']) && @$_POST['do']) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Invalid PIN','TYPE' => 'errormsg');
|
||||
} else {
|
||||
switch (@$_POST['do']) {
|
||||
case 'cashOut':
|
||||
if ($setting->getValue('manual_payout_active') == 1) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'A manual payout is in progress. Please try again later.', 'TYPE' => 'errormsg');
|
||||
} 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 {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Insufficient funds, you need more than 0.1 LTC to cover transaction fees', 'TYPE' => 'errormsg');
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'updateAccount':
|
||||
if ($user->updateAccount($_SESSION['USERDATA']['id'], $_POST['paymentAddress'], $_POST['payoutThreshold'], $_POST['donatePercent'])) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Account details updated', 'TYPE' => 'success');
|
||||
} else {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Failed to update your account', 'TYPE' => 'errormsg');
|
||||
}
|
||||
break;
|
||||
case 'updateAccount':
|
||||
if ($user->updateAccount($_SESSION['USERDATA']['id'], $_POST['paymentAddress'], $_POST['payoutThreshold'], $_POST['donatePercent'], $_POST['email'])) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Account details updated', 'TYPE' => 'success');
|
||||
} else {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Failed to update your account: ' . $user->getError(), 'TYPE' => 'errormsg');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'updatePassword':
|
||||
if ($user->updatePassword($_SESSION['USERDATA']['id'], $_POST['currentPassword'], $_POST['newPassword'], $_POST['newPassword2'])) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Password updated', 'TYPE' => 'success');
|
||||
} else {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg');
|
||||
case 'updatePassword':
|
||||
if ($user->updatePassword($_SESSION['USERDATA']['id'], $_POST['currentPassword'], $_POST['newPassword'], $_POST['newPassword2'])) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Password updated', 'TYPE' => 'success');
|
||||
} else {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg');
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
25
public/include/pages/account/notifications.inc.php
Normal file
25
public/include/pages/account/notifications.inc.php
Normal 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');
|
||||
}
|
||||
?>
|
||||
@ -2,11 +2,10 @@
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
if (!$_SESSION['AUTHENTICATED']) header('Location: index.php?page=home');
|
||||
|
||||
$aTransactions = $transaction->getTransactions($_SESSION['USERDATA']['id']);
|
||||
if (!$aTransactions) $_SESSION['POPUP'][] = array('CONTENT' => 'Could not find any transaction', 'TYPE' => 'errormsg');
|
||||
|
||||
$smarty->assign('TRANSACTIONS', $aTransactions);
|
||||
$smarty->assign('CONTENT', 'default.tpl');
|
||||
if ($user->isAuthenticated()) {
|
||||
$aTransactions = $transaction->getTransactions($_SESSION['USERDATA']['id']);
|
||||
if (!$aTransactions) $_SESSION['POPUP'][] = array('CONTENT' => 'Could not find any transaction', 'TYPE' => 'errormsg');
|
||||
$smarty->assign('TRANSACTIONS', $aTransactions);
|
||||
$smarty->assign('CONTENT', 'default.tpl');
|
||||
}
|
||||
?>
|
||||
|
||||
@ -2,35 +2,38 @@
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
if (!$_SESSION['AUTHENTICATED']) header('Location: index.php?page=home');
|
||||
|
||||
switch ($_REQUEST['do']) {
|
||||
case 'delete':
|
||||
if ($worker->deleteWorker($_SESSION['USERDATA']['id'], $_GET['id'])) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Worker removed');
|
||||
} else {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => $worker->getError(), 'TYPE' => 'errormsg');
|
||||
if ($user->isAuthenticated()) {
|
||||
switch (@$_REQUEST['do']) {
|
||||
case 'delete':
|
||||
if ($worker->deleteWorker($_SESSION['USERDATA']['id'], $_GET['id'])) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Worker removed');
|
||||
} 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':
|
||||
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;
|
||||
|
||||
$aWorkers = $worker->getWorkers($_SESSION['USERDATA']['id']);
|
||||
if (!$aWorkers) $_SESSION['POPUP'][] = array('CONTENT' => 'You have no workers configured', 'TYPE' => 'errormsg');
|
||||
|
||||
$smarty->assign('WORKERS', $aWorkers);
|
||||
}
|
||||
|
||||
$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('WORKERS', $aWorkers);
|
||||
|
||||
?>
|
||||
|
||||
14
public/include/pages/admin.inc.php
Normal file
14
public/include/pages/admin.inc.php
Normal 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");
|
||||
?>
|
||||
50
public/include/pages/admin/user.inc.php
Normal file
50
public/include/pages/admin/user.inc.php
Normal 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");
|
||||
?>
|
||||
24
public/include/pages/admin/wallet.inc.php
Normal file
24
public/include/pages/admin/wallet.inc.php
Normal 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");
|
||||
?>
|
||||
29
public/include/pages/api/getuserstatus.inc.php
Normal file
29
public/include/pages/api/getuserstatus.inc.php
Normal 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;
|
||||
?>
|
||||
24
public/include/pages/api/getuserworkers.inc.php
Normal file
24
public/include/pages/api/getuserworkers.inc.php
Normal 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;
|
||||
?>
|
||||
26
public/include/pages/api/public.inc.php
Normal file
26
public/include/pages/api/public.inc.php
Normal 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;
|
||||
?>
|
||||
@ -7,7 +7,7 @@ if (!defined('SECURITY'))
|
||||
if ( $user->checkLogin($_POST['username'],$_POST['password']) ) {
|
||||
header('Location: index.php?page=home');
|
||||
} 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');
|
||||
?>
|
||||
|
||||
@ -1,9 +1,17 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
|
||||
// Tempalte specifics
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
if (!$config['website']['registration']) {
|
||||
$_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");
|
||||
}
|
||||
?>
|
||||
|
||||
@ -1,14 +1,46 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
if (!defined('SECURITY')) 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'])) {
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Account created, please login');
|
||||
// Check if recaptcha is enabled, process form data if valid
|
||||
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 {
|
||||
$_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
|
||||
|
||||
@ -5,14 +5,14 @@ if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
|
||||
if ($bitcoin->can_connect() === true){
|
||||
$iDifficulty = $bitcoin->query('getdifficulty');
|
||||
$dDifficulty = $bitcoin->query('getdifficulty');
|
||||
$iBlock = $bitcoin->query('getblockcount');
|
||||
} else {
|
||||
$iDifficulty = 1;
|
||||
$dDifficulty = 1;
|
||||
$iBlock = 0;
|
||||
$_SESSION['POPUP'][] = array('CONTENT' => 'Unable to connect to litecoind RPC service: ' . $bitcoin->can_connect(), 'TYPE' => 'errormsg');
|
||||
}
|
||||
|
||||
$smarty->assign("CURRENTBLOCK", $iBlock);
|
||||
$smarty->assign("CURRENTDIFFICULTY", $iDifficulty);
|
||||
$smarty->assign("CONTENT", "pool/default.tpl");
|
||||
$smarty->assign("DIFFICULTY", $dDifficulty);
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
<?php
|
||||
|
||||
// Make sure we are called from index.php
|
||||
if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
|
||||
if (!defined('SECURITY')) die('Hacking attempt');
|
||||
if (!$user->isAuthenticated()) header("Location: index.php?page=home");
|
||||
|
||||
// Grab the last blocks found
|
||||
$iLimit = 30;
|
||||
@ -14,9 +13,5 @@ $aBlockData = $aBlocksFoundData[0];
|
||||
$smarty->assign("BLOCKSFOUND", $aBlocksFoundData);
|
||||
$smarty->assign("BLOCKLIMIT", $iLimit);
|
||||
|
||||
if ($_SESSION['AUTHENTICATED']) {
|
||||
$smarty->assign("CONTENT", "blocks_found.tpl");
|
||||
} else {
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
}
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
?>
|
||||
|
||||
16
public/include/pages/statistics/graphs.inc.php
Normal file
16
public/include/pages/statistics/graphs.inc.php
Normal 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");
|
||||
?>
|
||||
@ -21,12 +21,14 @@ $aContributorsShares = $statistics->getTopContributors('shares', 15);
|
||||
$aContributorsHashes = $statistics->getTopContributors('hashes', 15);
|
||||
|
||||
// Grab the last 10 blocks found
|
||||
$iLimit = 10;
|
||||
$iLimit = 5;
|
||||
$aBlocksFoundData = $statistics->getBlocksFound($iLimit);
|
||||
$aBlockData = $aBlocksFoundData[0];
|
||||
|
||||
// Estimated time to find the next block
|
||||
$iCurrentPoolHashrate = $statistics->getCurrentHashrate();
|
||||
$iCurrentPoolHashrate == 0 ? $iCurrentPoolHashrate = 1 : true;
|
||||
|
||||
// Time in seconds, not hours, using modifier in smarty to translate
|
||||
$iEstTime = $dDifficulty * pow(2,32) / ($iCurrentPoolHashrate * 1000);
|
||||
|
||||
@ -50,9 +52,9 @@ $smarty->assign("LASTBLOCK", $aBlockData['height']);
|
||||
$smarty->assign("DIFFICULTY", $dDifficulty);
|
||||
$smarty->assign("REWARD", $config['reward']);
|
||||
|
||||
if ($_SESSION['AUTHENTICATED']) {
|
||||
if ($user->isAuthenticated()) {
|
||||
$smarty->assign("CONTENT", "authenticated.tpl");
|
||||
} else {
|
||||
$smarty->assign("CONTENT", "default.tpl");
|
||||
$smarty->assign("CONTENT", "../default.tpl");
|
||||
}
|
||||
?>
|
||||
|
||||
@ -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");
|
||||
}
|
||||
?>
|
||||
277
public/include/recaptchalib.php
Normal file
277
public/include/recaptchalib.php
Normal 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 = "&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]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
@ -5,7 +5,7 @@ if (!defined('SECURITY'))
|
||||
die('Hacking attempt');
|
||||
|
||||
$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(SMARTY_DIR . 'Smarty.class.php');
|
||||
@ -16,10 +16,10 @@ $smarty = new Smarty;
|
||||
|
||||
// Assign our local paths
|
||||
$debug->append('Define Smarty Paths', 3);
|
||||
$smarty->template_dir = 'templates/' . THEME . '/';
|
||||
$smarty->compile_dir = 'templates/compile/';
|
||||
$smarty->template_dir = BASEPATH . 'templates/' . THEME . '/';
|
||||
$smarty->compile_dir = BASEPATH . 'templates/compile/';
|
||||
|
||||
// Optional smarty caching, check Smarty documentation for details
|
||||
$smarty->caching = $config['cache'];
|
||||
$smarty->cache_dir = "templates/cache";
|
||||
$smarty->cache_dir = BASEPATH . "templates/cache";
|
||||
?>
|
||||
|
||||
@ -7,17 +7,29 @@ if (!defined('SECURITY'))
|
||||
// Globally available variables
|
||||
$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
|
||||
$aRoundShares = $statistics->getRoundShares();
|
||||
$iCurrentActiveWorkers = $worker->getCountAllActiveWorkers();
|
||||
$iCurrentPoolHashrate = $statistics->getCurrentHashrate();
|
||||
$iCurrentPoolShareRate = $statistics->getCurrentShareRate();
|
||||
|
||||
// Global data for Smarty
|
||||
$aGlobal = array(
|
||||
'slogan' => $config['website']['slogan'],
|
||||
'websitename' => $config['website']['name'],
|
||||
'hashrate' => $iCurrentPoolHashrate,
|
||||
'sharerate' => $iCurrentPoolShareRate,
|
||||
'ppsvalue' => number_format(round(50 / (pow(2,32) * $dDifficulty) * pow(2, $config['difficulty']), 12) ,12),
|
||||
'workers' => $iCurrentActiveWorkers,
|
||||
'roundshares' => $aRoundShares,
|
||||
'fees' => $config['fees'],
|
||||
@ -25,7 +37,18 @@ $aGlobal = array(
|
||||
'reward' => $config['reward'],
|
||||
'price' => $setting->getValue('price'),
|
||||
'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
|
||||
@ -36,12 +59,19 @@ if (@$_SESSION['USERDATA']['id']) {
|
||||
// Other userdata that we can cache savely
|
||||
$aGlobal['userdata']['shares'] = $statistics->getUserShares($_SESSION['USERDATA']['id']);
|
||||
$aGlobal['userdata']['hashrate'] = $statistics->getUserHashrate($_SESSION['USERDATA']['id']);
|
||||
$aGlobal['userdata']['sharerate'] = $statistics->getUserSharerate($_SESSION['USERDATA']['id']);
|
||||
|
||||
// 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);
|
||||
switch ($config['payout_system']) {
|
||||
case 'pps':
|
||||
break;
|
||||
default:
|
||||
// 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
|
||||
|
||||
@ -465,6 +465,12 @@ a:hover {
|
||||
.block table tr th.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; }
|
||||
@ -1032,3 +1038,25 @@ a:hover {
|
||||
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;
|
||||
}
|
||||
|
||||
BIN
public/site_assets/mmcFE/images/first.png
Normal file
BIN
public/site_assets/mmcFE/images/first.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 720 B |
BIN
public/site_assets/mmcFE/images/last.png
Normal file
BIN
public/site_assets/mmcFE/images/last.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 737 B |
BIN
public/site_assets/mmcFE/images/next.png
Normal file
BIN
public/site_assets/mmcFE/images/next.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 736 B |
BIN
public/site_assets/mmcFE/images/prev.png
Normal file
BIN
public/site_assets/mmcFE/images/prev.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 745 B |
@ -16,19 +16,12 @@ $(function () {
|
||||
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') {
|
||||
$(this).hide().visualize({
|
||||
type: statsType,
|
||||
// 'bar', 'area', 'pie', 'line'
|
||||
width: chart_width,
|
||||
height: '240px',
|
||||
colors: ['#6fb9e8', '#ec8526', '#9dc453', '#ddd74c'],
|
||||
|
||||
lineDots: 'double',
|
||||
interaction: true,
|
||||
multiHover: 5,
|
||||
@ -43,9 +36,8 @@ $(function () {
|
||||
});
|
||||
} else {
|
||||
$(this).hide().visualize({
|
||||
type: statsType,
|
||||
// 'bar', 'area', 'pie', 'line'
|
||||
width: chart_width,
|
||||
type: statsType,
|
||||
height: '240px',
|
||||
colors: ['#6fb9e8', '#ec8526', '#9dc453', '#ddd74c']
|
||||
});
|
||||
@ -66,6 +58,16 @@ $(function () {
|
||||
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');
|
||||
|
||||
// Check / uncheck all checkboxes
|
||||
|
||||
106
public/site_assets/mmcFE/js/jquery.tooltip.visualize.js
Normal file
106
public/site_assets/mmcFE/js/jquery.tooltip.visualize.js
Normal 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
8
public/templates/mail/notifications/auto_payout.tpl
Normal file
8
public/templates/mail/notifications/auto_payout.tpl
Normal file
@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>An automated payout completed.</p>
|
||||
<p>Amount: {$DATA.amount}</p>
|
||||
<br/>
|
||||
<br/>
|
||||
</body>
|
||||
</html>
|
||||
11
public/templates/mail/notifications/idle_worker.tpl
Normal file
11
public/templates/mail/notifications/idle_worker.tpl
Normal 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>
|
||||
8
public/templates/mail/notifications/manual_payout.tpl
Normal file
8
public/templates/mail/notifications/manual_payout.tpl
Normal file
@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>An manual payout request completed.</p>
|
||||
<p>Amount: {$DATA.amount}</p>
|
||||
<br/>
|
||||
<br/>
|
||||
</body>
|
||||
</html>
|
||||
7
public/templates/mail/notifications/new_block.tpl
Normal file
7
public/templates/mail/notifications/new_block.tpl
Normal file
@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>A new block has been discovered!</p>
|
||||
<br/>
|
||||
<br/>
|
||||
</body>
|
||||
</html>
|
||||
@ -1 +1 @@
|
||||
[ {$WEBSITENAME} ] Password Reset Request
|
||||
[ {$WEBSITENAME} ] {$SUBJECT}
|
||||
|
||||
@ -7,22 +7,23 @@
|
||||
<tbody><tr><td>Username: </td><td>{$GLOBAL.userdata.username}</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>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>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>
|
||||
</tbody></table>
|
||||
<input type="submit" class="submit long" value="Update Settings"></form>
|
||||
{include file="global/block_footer.tpl"}
|
||||
|
||||
{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">
|
||||
<input type="hidden" name="page" value="{$smarty.request.page|escape}">
|
||||
<input type="hidden" name="action" value="{$smarty.request.action|escape}">
|
||||
<input type="hidden" name="do" value="cashOut">
|
||||
<table>
|
||||
<tbody><tr><td>Account Balance: </td><td>{$GLOBAL.userdata.balance|escape} LTC</td></tr>
|
||||
<tbody><tr><td>Account Balance: </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>4 digit PIN: </td><td><input type="password" name="authPin" size="4" maxlength="4"></td></tr>
|
||||
</tbody></table>
|
||||
|
||||
84
public/templates/mmcFE/account/notifications/default.tpl
Normal file
84
public/templates/mmcFE/account/notifications/default.tpl
Normal 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"}
|
||||
@ -1,7 +1,8 @@
|
||||
{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:;">
|
||||
<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;">
|
||||
<tr>
|
||||
<th class="header" style="cursor: pointer;">TX #</th>
|
||||
@ -15,11 +16,15 @@
|
||||
<tbody style="font-size:12px;">
|
||||
{section transaction $TRANSACTIONS}
|
||||
{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 == '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_MP'
|
||||
or $TRANSACTIONS[transaction].type == 'TXFee'
|
||||
)}
|
||||
<tr class="{cycle values="odd,even"}">
|
||||
<td>{$TRANSACTIONS[transaction].id}</td>
|
||||
@ -27,7 +32,7 @@
|
||||
<td>{$TRANSACTIONS[transaction].type}</td>
|
||||
<td>{$TRANSACTIONS[transaction].coin_address}</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>
|
||||
{/if}
|
||||
{/section}
|
||||
@ -42,7 +47,8 @@
|
||||
</div>
|
||||
<div class="block_content tab_content" id="Unconfirmed" style="">
|
||||
<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;">
|
||||
<tr>
|
||||
<th class="header" style="cursor: pointer;">TX #</th>
|
||||
@ -56,7 +62,7 @@
|
||||
<tbody style="font-size:12px;">
|
||||
{section transaction $TRANSACTIONS}
|
||||
{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 == 'Fee' and $TRANSACTIONS[transaction].confirmations < $GLOBAL.confirmations)
|
||||
)}
|
||||
@ -66,9 +72,9 @@
|
||||
<td>{$TRANSACTIONS[transaction].type}</td>
|
||||
<td>{$TRANSACTIONS[transaction].coin_address}</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>
|
||||
{if $TRANSACTIONS[transaction].type == Credit}
|
||||
{if $TRANSACTIONS[transaction].type == 'Credit' or $TRANSACTIONS[transaction].type == 'Bonus'}
|
||||
{assign var="credits" value="`$credits+$TRANSACTIONS[transaction].amount`"}
|
||||
{else}
|
||||
{assign var="debits" value="`$debits+$TRANSACTIONS[transaction].amount`"}
|
||||
@ -86,7 +92,8 @@
|
||||
</div>
|
||||
<div class="block_content tab_content" id="Orphan" style="">
|
||||
<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;">
|
||||
<tr>
|
||||
<th class="header" style="cursor: pointer;">TX #</th>
|
||||
@ -103,6 +110,7 @@
|
||||
$TRANSACTIONS[transaction].type == 'Orphan_Credit'
|
||||
or $TRANSACTIONS[transaction].type == 'Orphan_Donation'
|
||||
or $TRANSACTIONS[transaction].type == 'Orphan_Fee'
|
||||
or $TRANSACTIONS[transaction].type == 'Orphan_Bonus'
|
||||
)}
|
||||
<tr class="{cycle values="odd,even"}">
|
||||
<td>{$TRANSACTIONS[transaction].id}</td>
|
||||
@ -110,9 +118,9 @@
|
||||
<td>{$TRANSACTIONS[transaction].type}</td>
|
||||
<td>{$TRANSACTIONS[transaction].coin_address}</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>
|
||||
{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`"}
|
||||
{else}
|
||||
{assign var="orphan_debits" value="`$orphan_debits+$TRANSACTIONS[transaction].amount`"}
|
||||
|
||||
@ -1,9 +1,4 @@
|
||||
{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>
|
||||
<form action="{$smarty.server.PHP_SELF}" method="post">
|
||||
<input type="hidden" name="page" value="{$smarty.request.page}">
|
||||
@ -14,18 +9,23 @@
|
||||
<tr>
|
||||
<td>Worker Name</td>
|
||||
<td>Password</td>
|
||||
<td>Active</td>
|
||||
<td>Khash/s</td>
|
||||
<td class="center">Active</td>
|
||||
<td class="center">Monitor</td>
|
||||
<td class="right">Khash/s</td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
{section worker $WORKERS}
|
||||
{assign var="username" value="."|escape|explode:$WORKERS[worker].username:2}
|
||||
<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>{if $WORKERS[worker].active == 1}Y{else}N{/if}</td>
|
||||
<td>{$WORKERS[worker].hashrate}</td>
|
||||
<td class="center"><img src="{$PATH}/images/{if $WORKERS[worker].active}success{else}error{/if}.gif" /></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>
|
||||
</tr>
|
||||
{/section}
|
||||
|
||||
3
public/templates/mmcFE/admin/default.tpl
Normal file
3
public/templates/mmcFE/admin/default.tpl
Normal 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"}
|
||||
89
public/templates/mmcFE/admin/user/default.tpl
Normal file
89
public/templates/mmcFE/admin/user/default.tpl
Normal 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 </th>
|
||||
<th class="right">Hashrate </th>
|
||||
<th class="right">Est. Donation </th>
|
||||
<th class="right">Est. Payout </th>
|
||||
<th class="right">Balance </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 </th>
|
||||
<th class="right">Hashrate </th>
|
||||
<th class="right">Est. Donation </th>
|
||||
<th class="right">Est. Payout </th>
|
||||
<th class="right">Balance </th>
|
||||
<th class="center">Admin</th>
|
||||
<th class="center">Locked</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
{include file="global/block_footer.tpl"}
|
||||
16
public/templates/mmcFE/admin/wallet/default.tpl
Normal file
16
public/templates/mmcFE/admin/wallet/default.tpl
Normal 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"}
|
||||
@ -1,5 +1,5 @@
|
||||
<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/>
|
||||
<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/>
|
||||
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 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/>
|
||||
</center>
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
<div id="ministats">
|
||||
<table border="0">
|
||||
<tr>
|
||||
<td><li>LTC/usd: {$GLOBAL.price|default:"n/a"} </li></td>
|
||||
<td><li>Pool Hashrate: {$GLOBAL.hashrate / 1000} MH/s </li></td>
|
||||
<td><li>Pool Sharerate: {$GLOBAL.sharerate} Shares/s </li></td>
|
||||
<td><li>{$GLOBAL.config.currency}/{$GLOBAL.config.price.currency}: {$GLOBAL.price|default:"n/a"|number_format:"4"} </li></td>
|
||||
<td><li>Pool Hashrate: {($GLOBAL.hashrate / 1000)|number_format:"3"} MH/s </li></td>
|
||||
<td><li>Pool Sharerate: {$GLOBAL.sharerate|number_format:"2"} Shares/s </li></td>
|
||||
<td><li>Pool Workers: {$GLOBAL.workers} </li></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@ -5,16 +5,24 @@
|
||||
<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=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=notifications">Notifications</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
{/if}
|
||||
{if $smarty.session.AUTHENTICATED|default:"0" == 1 && $GLOBAL.userdata.admin == 1}<li><a href="#">Admin Panel</a></li>{/if}
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=statistics">Statistics</a>
|
||||
{if $smarty.session.AUTHENTICATED|default:"0" == 1 && $GLOBAL.userdata.is_admin == 1}
|
||||
<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>
|
||||
<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=graphs">Hashrate Graphs</a></li>{/if}
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="{$smarty.server.PHP_SELF}?page=gettingstarted">Getting Started</a></li>
|
||||
|
||||
15
public/templates/mmcFE/global/pagination.tpl
Normal file
15
public/templates/mmcFE/global/pagination.tpl
Normal 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>
|
||||
@ -6,8 +6,13 @@
|
||||
</div>
|
||||
<div class="block_content" style="padding-top:10px;">
|
||||
<table class="sidebar" style="width: 196px">
|
||||
<tr><td colspan="2"><b>Your Hashrate</b></td></tr>
|
||||
<tr><td colspan="2" class="right">{$GLOBAL.userdata.hashrate|number_format} KH/s</td></tr>
|
||||
<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 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>
|
||||
@ -35,7 +40,7 @@
|
||||
<td class="right"><i>{$GLOBAL.userdata.shares.invalid|number_format}</i><font size='1px'></font></td>
|
||||
</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>
|
||||
<td><b>Block</b></td>
|
||||
@ -54,8 +59,9 @@
|
||||
<td class="right">{$GLOBAL.userdata.est_payout|number_format:"3"}</td>
|
||||
</tr>
|
||||
<tr><td colspan="2"> </td></tr>
|
||||
<tr><td colspan="2"><b><u>Account Balance</u></b></td></tr>
|
||||
<tr><td colspan="2" class="right"><b>{$GLOBAL.userdata.balance|default:"0"} LTC</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>
|
||||
|
||||
61
public/templates/mmcFE/global/sidebar_pps.tpl
Normal file
61
public/templates/mmcFE/global/sidebar_pps.tpl
Normal 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"> </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"> </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>
|
||||
@ -11,6 +11,7 @@
|
||||
<script src="{$PATH}/js/jquery.tablesorter.min.js"></script>
|
||||
<script src="{$PATH}/js/jquery.tablesorter.pager.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/tools.js"></script>
|
||||
<!--[if IE]><script type="text/javascript" src="{$PATH}/js/excanvas.js"></script><![endif]-->
|
||||
@ -46,7 +47,11 @@
|
||||
<div class="block_content">
|
||||
<div class="sidebar">
|
||||
{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}
|
||||
{include file="global/login.tpl"}
|
||||
{/if}
|
||||
|
||||
@ -3,13 +3,16 @@
|
||||
<input type="hidden" name="page" value="{$smarty.request.page|escape}">
|
||||
<input type="hidden" name="action" value="register">
|
||||
<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>
|
||||
<tr><td>Password:</td><td><input type="password" class="text tiny" name="password1" value="" 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>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>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>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>
|
||||
</tbody></table>
|
||||
<input type="submit" class="submit small" value="Register">
|
||||
<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>
|
||||
<tr><td>Password:</td><td><input type="password" class="text tiny" name="password1" value="" 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>Email:</td><td><input type="text" name="email1" class="text small" value="{$smarty.post.email1|escape}" size="15"></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>
|
||||
<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 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>
|
||||
{include file="global/block_footer.tpl"}
|
||||
|
||||
3
public/templates/mmcFE/register/disabled.tpl
Normal file
3
public/templates/mmcFE/register/disabled.tpl
Normal 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"}
|
||||
@ -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"}
|
||||
73
public/templates/mmcFE/statistics/blocks/default.tpl
Normal file
73
public/templates/mmcFE/statistics/blocks/default.tpl
Normal 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"}
|
||||
28
public/templates/mmcFE/statistics/blocks/small_table.tpl
Normal file
28
public/templates/mmcFE/statistics/blocks/small_table.tpl
Normal 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"}
|
||||
@ -19,4 +19,5 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</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"}
|
||||
|
||||
43
public/templates/mmcFE/statistics/graphs/both.tpl
Normal file
43
public/templates/mmcFE/statistics/graphs/both.tpl
Normal 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}
|
||||
5
public/templates/mmcFE/statistics/graphs/default.tpl
Normal file
5
public/templates/mmcFE/statistics/graphs/default.tpl
Normal 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"}
|
||||
31
public/templates/mmcFE/statistics/graphs/mine.tpl
Normal file
31
public/templates/mmcFE/statistics/graphs/mine.tpl
Normal 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}
|
||||
31
public/templates/mmcFE/statistics/graphs/pool.tpl
Normal file
31
public/templates/mmcFE/statistics/graphs/pool.tpl
Normal 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}
|
||||
@ -4,15 +4,19 @@
|
||||
|
||||
{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;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<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>
|
||||
<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>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -32,8 +36,8 @@
|
||||
<td>{$ESTTIME|seconds_to_words}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="leftheader">Est. Avg. Shares per Round</td>
|
||||
<td>{($ESTTIME * $GLOBAL.sharerate)|number_format:"0"}</td>
|
||||
<td class="leftheader">Est. Shares this Round</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>
|
||||
<td class="leftheader">Time Since Last Block</td>
|
||||
@ -44,6 +48,6 @@
|
||||
{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"}
|
||||
|
||||
@ -6,18 +6,21 @@
|
||||
<th align="left">Rank</th>
|
||||
<th align="left" scope="col">User Name</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>
|
||||
</thead>
|
||||
<tbody>
|
||||
{assign var=rank value=1}
|
||||
{assign var=listed value=0}
|
||||
{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}>
|
||||
<td>{$rank++}</td>
|
||||
<td>{$CONTRIBHASHES[contrib].account}</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>
|
||||
{/section}
|
||||
{if $listed != 1}
|
||||
@ -25,7 +28,8 @@
|
||||
<td>n/a</td>
|
||||
<td>{$GLOBAL.userdata.username}</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>
|
||||
{/if}
|
||||
</tbody>
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
<tr style="background-color:#99EB99;">
|
||||
<td>n/a</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>
|
||||
{/if}
|
||||
</tbody>
|
||||
|
||||
@ -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"}
|
||||
@ -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 </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"}
|
||||
17
sql/issue_144_notification_upgrade.sql
Normal file
17
sql/issue_144_notification_upgrade.sql
Normal 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;
|
||||
2
sql/issue_147_accounts_upgrade.sql
Normal file
2
sql/issue_147_accounts_upgrade.sql
Normal 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 ;
|
||||
1
sql/issue_148_transactions_upgrade.sql
Normal file
1
sql/issue_148_transactions_upgrade.sql
Normal 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;
|
||||
1
sql/issue_167_settings_upgrade.sql
Normal file
1
sql/issue_167_settings_upgrade.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE `settings` CHANGE `setting` `name` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ;
|
||||
1
sql/issue_182_accounts_upgrade.sql
Normal file
1
sql/issue_182_accounts_upgrade.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE `accounts` ADD `failed_logins` INT( 5 ) UNSIGNED NULL DEFAULT '0' AFTER `is_locked` ;
|
||||
1
sql/issue_203_transactions_upgrade.sql
Normal file
1
sql/issue_203_transactions_upgrade.sql
Normal 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 ;
|
||||
1
sql/issue_212_notification_settings_upgrade.sql
Normal file
1
sql/issue_212_notification_settings_upgrade.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE `notification_settings` ADD `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST ;
|
||||
1
sql/issue_70_transactions_upgrade.sql
Normal file
1
sql/issue_70_transactions_upgrade.sql
Normal 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;
|
||||
@ -1,37 +1,22 @@
|
||||
-- phpMyAdmin SQL Dump
|
||||
-- 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 SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||
SET time_zone = "+00:00";
|
||||
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
|
||||
--
|
||||
-- Database: `mmcfe_ng`
|
||||
--
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `accounts`
|
||||
--
|
||||
CREATE DATABASE IF NOT EXISTS `mmcfe_ng` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
|
||||
USE `mmcfe_ng`;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `accounts` (
|
||||
`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,
|
||||
`pass` varchar(255) NOT NULL,
|
||||
`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,
|
||||
`sessionTimeoutStamp` int(255) DEFAULT NULL,
|
||||
`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`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `blocks`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `blocks` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`height` int(10) unsigned NOT NULL,
|
||||
@ -65,13 +44,39 @@ CREATE TABLE IF NOT EXISTS `blocks` (
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `height` (`height`,`blockhash`),
|
||||
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;
|
||||
|
||||
--
|
||||
-- Table structure for table `settings`
|
||||
--
|
||||
CREATE TABLE IF NOT EXISTS `notification_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` (
|
||||
`name` varchar(255) NOT NULL,
|
||||
@ -80,12 +85,6 @@ CREATE TABLE IF NOT EXISTS `settings` (
|
||||
UNIQUE KEY `setting` (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `shares`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `shares` (
|
||||
`id` bigint(30) NOT NULL AUTO_INCREMENT,
|
||||
`rem_host` varchar(255) NOT NULL,
|
||||
@ -100,13 +99,7 @@ CREATE TABLE IF NOT EXISTS `shares` (
|
||||
KEY `upstream_result` (`upstream_result`),
|
||||
KEY `our_result` (`our_result`),
|
||||
KEY `username` (`username`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `shares_archive`
|
||||
--
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `shares_archive` (
|
||||
`id` int(255) unsigned NOT NULL AUTO_INCREMENT,
|
||||
@ -119,13 +112,7 @@ CREATE TABLE IF NOT EXISTS `shares_archive` (
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `share_id` (`share_id`),
|
||||
KEY `time` (`time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Archive shares for potential later debugging purposes';
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `statistics_shares`
|
||||
--
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Archive shares for potential later debugging purposes';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `statistics_shares` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
@ -136,18 +123,12 @@ CREATE TABLE IF NOT EXISTS `statistics_shares` (
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `account_id` (`account_id`),
|
||||
KEY `block_id` (`block_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `transactions`
|
||||
--
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `transactions` (
|
||||
`id` int(255) NOT NULL AUTO_INCREMENT,
|
||||
`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,
|
||||
`amount` double DEFAULT '0',
|
||||
`block_id` int(255) DEFAULT NULL,
|
||||
@ -156,24 +137,7 @@ CREATE TABLE IF NOT EXISTS `transactions` (
|
||||
KEY `block_id` (`block_id`),
|
||||
KEY `account_id` (`account_id`),
|
||||
KEY `type` (`type`)
|
||||
) 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;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user