Browse Source

bringing the hush puppy in

pull/1/head
jahway603 3 years ago
parent
commit
0a02d54d85
  1. 7
      .gitignore
  2. 20
      .vscode/launch.json
  3. 19
      Dockerfile
  4. 11
      Old/CHANGELOG.md
  5. 7
      Old/LICENSE
  6. 164
      Old/README.md
  7. 23
      README.md
  8. 14
      docker-compose.yml
  9. 36
      pool_configs/hushsolo.json
  10. 6
      website/default/index.html
  11. 8
      website/default/pages/home.html
  12. BIN
      website/default/static/hush-logo-horizontal-01.png
  13. BIN
      website/default/static/hushfavicon.ico
  14. 86
      website/minerpond/index.html
  15. 2798
      website/minerpond/key.html
  16. 50
      website/minerpond/pages/admin.html
  17. 11
      website/minerpond/pages/api.html
  18. 325
      website/minerpond/pages/getting_started.html
  19. 134
      website/minerpond/pages/home.html
  20. 105
      website/minerpond/pages/miner_stats.html
  21. 25
      website/minerpond/pages/mining_key.html
  22. 94
      website/minerpond/pages/payments.html
  23. 234
      website/minerpond/pages/stats.html
  24. 64
      website/minerpond/pages/tbs.html
  25. 96
      website/minerpond/pages/workers.html
  26. 100
      website/minerpond/static/admin.js
  27. BIN
      website/minerpond/static/favicon.png
  28. 13
      website/minerpond/static/kmdfavicon.svg
  29. BIN
      website/minerpond/static/komodo-logo-horizontal-01.png
  30. 13
      website/minerpond/static/logo.svg
  31. 30
      website/minerpond/static/main.js
  32. 246
      website/minerpond/static/miner_stats.js
  33. 1
      website/minerpond/static/nvd3.css
  34. 6
      website/minerpond/static/nvd3.js
  35. 143
      website/minerpond/static/stats.js
  36. 68
      website/minerpond/static/style.css

7
.gitignore

@ -1,8 +1,9 @@
node_modules/
.idea/
config.json
pool_configs/
!pool_configs/komodo.json
!pool_configs/
pool_configs/*
!pool_configs/hushsolo.json
!pool_configs/solo-wsb.json
website/piratepool.io/static/*.txt
redis-data/
.vscode/

20
.vscode/launch.json

@ -1,20 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch via NPM",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run-script",
"debug"
],
"port": 9229,
"useWSL": true
}
]
}

19
Dockerfile

@ -1,5 +1,8 @@
FROM ubuntu:18.04
LABEL maintainer="webworker01"
LABEL maintainer="jahway603"
# added this to fix strange error about /tmp
RUN chmod 1777 /tmp
RUN apt-get update -y && \
apt-get install -y gcc g++ make libboost-dev libboost-system-dev libsodium-dev sudo curl git iputils-ping
@ -7,17 +10,17 @@ RUN apt-get update -y && \
RUN curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - && \
apt-get install -y nodejs
RUN useradd knomp
COPY . /home/knomp/knomp
RUN useradd hnomp
COPY . /home/hnomp/hnomp
RUN echo "knomp ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/user && \
RUN echo "hnomp ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/user && \
chmod 0440 /etc/sudoers.d/user && \
chown -R knomp:knomp /home/knomp
chown -R hnomp:hnomp /home/hnomp
RUN cd /home/knomp/knomp && npm install
RUN cd /home/hnomp/hnomp && npm install
USER knomp
WORKDIR /home/knomp/knomp
USER hnomp
WORKDIR /home/hnomp/hnomp
EXPOSE 8080

11
Old/CHANGELOG.md

@ -1,11 +0,0 @@
# Changelog
### 20161127
* Fixed payment processor crashes
* Fixed varDiff and set default to 0.125
* Fixed merkleRoot issue with multiple transactions in each block
* Fixed incorrect hashrates
* Begin compatibility testing with Node 7+
* Added t_address -> z_address -> t_address coin transfer function

7
Old/LICENSE

@ -1,7 +0,0 @@
Copyright (c) <year> <copyright holders>
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.

164
Old/README.md

@ -1,164 +0,0 @@
# Zcash® and Zclassic - Node Open Mining Portal
**[Click here for the official - Zcash® and Zclassic Stratum Mining Pool Installation Guide](https://zdeveloper.org/wiki:z-nomp_install)**
This is a Equihash mining pool based off of Node Open Mining Portal.
Donations for development are greatly appreciated!
* BTC: 18vHMxVzotQ9EPyESrf7Z1hNM9AwJeVHgD
* ZCL: zcXDWbgReztLLXSTUMT2nEumiDM6zTzUXFb7vUnx9JNfJDVqbodyxwEQwgDkFw7Dp128tBU8n8rmVxT43DshmeTEM4LHcdz
#### Production Usage Notice
This is beta software. All of the following are things that can change and break an existing Z-NOMP setup: functionality of any feature, structure of configuration files and structure of redis data. If you use this software in production then *DO NOT* pull new code straight into production usage because it can and often will break your setup and require you to tweak things like config files or redis data. *Only tagged releases are considered stable.*
#### Paid Solution
Usage of this software requires abilities with sysadmin, database admin, coin daemons, and sometimes a bit of programming. Running a production pool can literally be more work than a full-time job.
### Community / Support
IRC
* Support / general discussion join: https://gitter.im/zclassicorg/z-nomp
If your pool uses Z-NOMP let us know and we will list your website here.
### Some pools using Z-NOMP or node-stratum-module:
http://mineflowpool.pl Z-nomp based pool. Custom frontend and API.
http://luckpool.org Zcash Pool with Custom Frontend w/Miner's Jackpot
http://zclassic.miningspeed.com Custom frontend and 0% fee
http://miningpool.io/
https://lucky-mining.com.ua/ Running MPOS and no fee, [vot][zcl][zen][hush][btg].lucky-mining.com.ua <-- Ukraine
Usage
=====
#### Requirements
* Coin daemon(s) (find the coin's repo and build latest version from source)
* [Node.js](http://nodejs.org/) v7+ ([follow these installation instructions](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager))
* [Redis](http://redis.io/) key-value store v2.6+ ([follow these instructions](http://redis.io/topics/quickstart))
##### Seriously
Those are legitimate requirements. If you use old versions of Node.js or Redis that may come with your system package manager then you will have problems. Follow the linked instructions to get the last stable versions.
[**Redis security warning**](http://redis.io/topics/security): be sure firewall access to redis - an easy way is to
include `bind 127.0.0.1` in your `redis.conf` file. Also it's a good idea to learn about and understand software that
you are using - a good place to start with redis is [data persistence](http://redis.io/topics/persistence).
#### 0) Setting up coin daemon
Follow the build/install instructions for your coin daemon. Your coin.conf file should end up looking something like this:
```
daemon=1
rpcuser=zclassicrpc
rpcpassword=securepassword
rpcport=8232
```
For redundancy, its recommended to have at least two daemon instances running in case one drops out-of-sync or offline,
all instances will be polled for block/transaction updates and be used for submitting blocks. Creating a backup daemon
involves spawning a daemon using the `-datadir=/backup` command-line argument which creates a new daemon instance with
it's own config directory and coin.conf file. Learn about the daemon, how to use it and how it works if you want to be
a good pool operator. For starters be sure to read:
* https://en.bitcoin.it/wiki/Running_bitcoind
* https://en.bitcoin.it/wiki/Data_directory
* https://en.bitcoin.it/wiki/Original_Bitcoin_client/API_Calls_list
* https://en.bitcoin.it/wiki/Difficulty
#### 1) Downloading & Installing
Clone the repository and run `npm update` for all the dependencies to be installed:
```bash
sudo apt-get install build-essential libsodium-dev npm
sudo npm install n -g
sudo n stable
git clone https://github.com/joshuayabut/node-open-mining-portal.git z-nomp
cd z-nomp
npm update
npm install
```
##### Pool config
Take a look at the example json file inside the `pool_configs` directory. Rename it to `zclassic.json` and change the
example fields to fit your setup.
```
Please Note that: 1 Difficulty is actually 8192, 0.125 Difficulty is actually 1024.
Whenever a miner submits a share, the pool counts the difficulty and keeps adding them as the shares.
ie: Miner 1 mines at 0.1 difficulty and finds 10 shares, the pool sees it as 1 share. Miner 2 mines at 0.5 difficulty and finds 5 shares, the pool sees it as 2.5 shares.
```
##### [Optional, recommended] Setting up blocknotify
1. In `config.json` set the port and password for `blockNotifyListener`
2. In your daemon conf file set the `blocknotify` command to use:
```
node [path to cli.js] [coin name in config] [block hash symbol]
```
Example: inside `zclassic.conf` add the line
```
blocknotify=node /home/user/z-nomp/scripts/cli.js blocknotify zclassic %s
```
Alternatively, you can use a more efficient block notify script written in pure C. Build and usage instructions
are commented in [scripts/blocknotify.c](scripts/blocknotify.c).
#### 3) Start the portal
```bash
npm start
```
###### Optional enhancements for your awesome new mining pool server setup:
* Use something like [forever](https://github.com/nodejitsu/forever) to keep the node script running
in case the master process crashes.
* Use something like [redis-commander](https://github.com/joeferner/redis-commander) to have a nice GUI
for exploring your redis database.
* Use something like [logrotator](http://www.thegeekstuff.com/2010/07/logrotate-examples/) to rotate log
output from Z-NOMP.
* Use [New Relic](http://newrelic.com/) to monitor your Z-NOMP instance and server performance.
#### Upgrading Z-NOMP
When updating Z-NOMP to the latest code its important to not only `git pull` the latest from this repo, but to also update
the `node-stratum-pool` and `node-multi-hashing` modules, and any config files that may have been changed.
* Inside your Z-NOMP directory (where the init.js script is) do `git pull` to get the latest Z-NOMP code.
* Remove the dependenices by deleting the `node_modules` directory with `rm -r node_modules`.
* Run `npm update` to force updating/reinstalling of the dependencies.
* Compare your `config.json` and `pool_configs/coin.json` configurations to the latest example ones in this repo or the ones in the setup instructions where each config field is explained. <b>You may need to modify or add any new changes.</b>
Credits
-------
### Z-NOMP
* [Joshua Yabut / movrcx](https://github.com/joshuayabut)
* [Aayan L / anarch3](https://github.com/aayanl)
* [hellcatz](https://github.com/hellcatz)
### NOMP
* [Matthew Little / zone117x](https://github.com/zone117x) - developer of NOMP
* [Jerry Brady / mintyfresh68](https://github.com/bluecircle) - got coin-switching fully working and developed proxy-per-algo feature
* [Tony Dobbs](http://anthonydobbs.com) - designs for front-end and created the NOMP logo
* [LucasJones](//github.com/LucasJones) - got p2p block notify working and implemented additional hashing algos
* [vekexasia](//github.com/vekexasia) - co-developer & great tester
* [TheSeven](//github.com/TheSeven) - answering an absurd amount of my questions and being a very helpful gentleman
* [UdjinM6](//github.com/UdjinM6) - helped implement fee withdrawal in payment processing
* [Alex Petrov / sysmanalex](https://github.com/sysmanalex) - contributed the pure C block notify script
* [svirusxxx](//github.com/svirusxxx) - sponsored development of MPOS mode
* [icecube45](//github.com/icecube45) - helping out with the repo wiki
* [Fcases](//github.com/Fcases) - ordered me a pizza <3
* Those that contributed to [node-stratum-pool](//github.com/zone117x/node-stratum-pool#credits)
License
-------
Released under the MIT License. See LICENSE file.

23
README.md

@ -5,10 +5,11 @@
* [Using Docker (easy)](#using-docker-easy)
* [Bare metal installation](#bare-metal-installation)
* [More Config Information](#more-config-information)
* [More Resources](#more-resources)
* [License](#license)
## Differences between this and Z-NOMP
* This is meant for Hush mining
* This is meant for Hush and Hush smartchain mining
* ZEC/ZEN specific stuff is removed
## Using Docker (easy)
@ -28,8 +29,9 @@ cd ./hnomp
cp config_example.json config.json
```
Setup your [config.json](./config_example.json), `./coins/` and `./pool_configs/` in here, then:
Setup your [config.json](./config_example.json), `./coins/` and `./pool_configs/` here. Can reference [hushsolo](pool_configs/hushsolo.json) to help you.
Then run the following command.
```
docker-compose up &
```
@ -72,12 +74,7 @@ Some initial setup
sudo apt-get update
sudo apt-get install build-essential pkg-config libc6-dev m4 g++-multilib autoconf libtool ncurses-dev unzip git python python-zmq zlib1g-dev wget libcurl4-openssl-dev bsdmainutils automake curl libboost-dev libboost-system-dev libsodium-dev jq redis-server nano -y
```
Now, let's build Hush
```shell
git clone https://git.hush.is/hush/hush3
cd hush3
./build.sh -j$(nproc)
```
Now, let's build the Hush daemon. In order to not duplicate documentation, please follow the instructions in the [hush3 repository here](https://git.hush.is/hush/hush3/src/branch/master/INSTALL.md) before proceeding.
Now, let's run the assets. This will start ALL of the assets might take a day or so to sync, depending on system speed/network connection.
@ -122,7 +119,7 @@ If all went well the program should start without error and you should be able t
## More Config Information
### Disable Coinbase Mode
This mode uses -pubkey to tell the daemon where the coinbase should be sent, and uses the daemons coinbase transaction rather then having the pool create the coinabse transaction. This enables special coinbase transactions, such as ac_founders and ac_script or new modes with CC vouts in the coinbase not yet created, it will work with all coins, except Full Z support described below.
This mode uses -pubkey to tell the daemon where the coinbase should be sent, and uses the daemons coinbase transaction rather then having the pool create the coinbase transaction. This enables special coinbase transactions, such as ac_founders and ac_script or new modes with CC vouts in the coinbase not yet created, it will work with all coins, except Full Z support described below.
To enable it, change the value in the `./coins/*.json` to `"disablecb" : true`
@ -174,8 +171,12 @@ In pool_config:
"maxBlocksPerPayment": 20,
```
### More Resources
[Further info on config](https://github.com/zone117x/node-open-mining-portal#2-configuration) and some [sample configs](https://github.com/z-classic/z-nomp)
## More Resources
1. [This resource has further info on configs](https://github.com/zone117x/node-open-mining-portal) and was a great help.
1. [This repository has sample configs](https://github.com/z-classic/z-nomp/tree/master/pool_configs) is an old Z-NOMP with pool configurations, so these were helpful to see other options.
1. Reference [the hush.json here](coins/hush.json) to configure your coin file, but [refer to this repo](https://github.com/zone117x/node-stratum-pool#module-usage) to help learn more about coin files in general.
## License

14
docker-compose.yml

@ -1,18 +1,18 @@
version: '3'
services:
knomp:
container_name: knomp
hnomp:
container_name: hnomp
network_mode: host
build:
context: .
dockerfile: Dockerfile
volumes:
- ./config.json:/home/knomp/knomp/config.json
- ./coins:/home/knomp/knomp/coins
- ./libs:/home/knomp/knomp/libs
- ./pool_configs:/home/knomp/knomp/pool_configs
- ./website:/home/knomp/knomp/website
- ./config.json:/home/hnomp/hnomp/config.json
- ./coins:/home/hnomp/hnomp/coins
- ./libs:/home/hnomp/hnomp/libs
- ./pool_configs:/home/hnomp/hnomp/pool_configs
- ./website:/home/hnomp/hnomp/website
# ports:
# - 8080:8080
# - 3333:3333

36
pool_configs/hushsolo.json

@ -0,0 +1,36 @@
{
"enabled":true,
"coin": "hush.json",
"address": "t-address-#1",
"zAddress": "your-pool-z-address",
"tAddress": "t-address-#2",
"invalidAddress":"t-address-#3",
"walletInterval": 5,
"rewardRecipients": {
"pool-operators-t-address-with-1.5-percent": 1.5,
"2nd-pool-operators-t-address-with-0.5-percent": 0.5,
"can-remove-these-if-only-solo-mining": 0.1
},
"tlsOptions": { "enabled": false },
"paymentProcessing": { "enabled": false, "daemon": false },
"trackShares": { "disable": true },
"ports": {
"3333": {
"diff": 262144
}
},
"daemons": [{
"host": "127.0.0.1",
"port": 18031,
"user": "username-set-in-HUSH3.conf",
"password": "password-set-in-HUSH3.conf"
}],
"p2p": {
"enabled": true,
"host": "127.0.0.1",
"port": 18030,
"disableTransactions": true
},
"mposMode": { "enabled": false }
}

6
website/default/index.html

@ -4,7 +4,7 @@
<head>
<meta charset="utf-8">
<link rel="shortcut icon" type="image/png" href="/static/kmdfavicon.svg"/>
<link rel="shortcut icon" type="image/png" href="/static/hushfavicon.ico"/>
<link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
@ -21,7 +21,7 @@
<script src="/static/main.js"></script>
<link rel="stylesheet" href="/static/style.css">
<title>knomp</title>
<title>hnomp</title>
</head>
@ -79,7 +79,7 @@
<footer>
&lt;3 🐸 &middot; <a href="https://github.com/webworker01/knomp" target="_blank">knomp on Github</a>
&lt;3 🐸 &middot; <a href="https://git.hush.is/hush/hnomp" target="_blank">hnomp on our own Gitea</a>
</footer>
</body>

8
website/default/pages/home.html

@ -74,11 +74,11 @@
</style>
<div class="pure-g-r" id="boxWelcome">
<img src="/static/komodo-logo-horizontal-01.png" style="margin: 0 auto; height:150px;">
<img src="/static/hush-logo-horizontal-01.png" style="margin: 0 auto; height:150px;">
<div class="pure-u-1">
<div style="font-size: 2em; text-align:center; margin-bottom:10px;">KNOMP</div>
<div style="text-align:center; margin-bottom:10px;"">Low 0.5% fee! Min payouts of 1!</div>
<div style="font-size: 2em; text-align:center; margin-bottom:10px;">HNOMP</div>
<div style="text-align:center; margin-bottom:10px;"">Low 1.5% fee! Min payouts of 1!</div>
</div>
</div>
@ -129,4 +129,4 @@
}
});
});
</script>
</script>

BIN
website/default/static/hush-logo-horizontal-01.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
website/default/static/hushfavicon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

86
website/minerpond/index.html

@ -1,86 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="shortcut icon" type="image/png" href="/static/kmdfavicon.svg"/>
<link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.0.3/css/font-awesome.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/3.0.1/normalize.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.4.2/pure-min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.5/d3.min.js"></script>
<script src="/static/nvd3.js"></script>
<link rel="stylesheet" href="/static/nvd3.css">
<script src="/static/main.js"></script>
<link rel="stylesheet" href="/static/style.css">
<title>minerpond - komodo assetchains mining pool</title>
</head>
<body>
<header>
<div class="home-menu pure-menu pure-menu-open pure-menu-horizontal">
<a class="pure-menu-heading hot-swapper" href="/"><i class="fa fa-home"></i>&nbsp;Home</a>
<ul>
<li class="{{? it.selected === 'getting_started' }}pure-menu-selected{{?}}">
<a class="hot-swapper" href="/getting_started">
<i class="fa fa-rocket"></i>&nbsp;
Getting Started
</a>
</li>
<li class="{{? it.selected === 'stats' }}pure-menu-selected{{?}}">
<a class="hot-swapper" href="/stats">
<i class="fa fa-bar-chart-o"></i>&nbsp;
Graph Stats
</a>
</li>
<li class="{{? it.selected === 'tbs' }}pure-menu-selected{{?}}">
<a class="hot-swapper" href="/tbs">
<i class="fa fa-table"></i>&nbsp;
Tab Stats
</a>
</li>
<li class="{{? it.selected === 'workers' }}pure-menu-selected{{?}}">
<a class="hot-swapper" href="/workers">
<i class="fa fa-cogs"></i>&nbsp;
Workers Stats
</a>
</li>
<li class="{{? it.selected === 'payments' }}pure-menu-selected{{?}}">
<a class="hot-swapper" href="/payments">
<i class="fa fa-bitcoin"></i>&nbsp;
Payments
</a>
</li>
<li class="{{? it.selected === 'api' }}pure-menu-selected{{?}}">
<a class="hot-swapper" href="/api">
<i class="fa fa-code"></i>&nbsp;
API
</a>
</li>
</ul>
</div>
</header>
<main>
{{=it.page}}
</main>
<footer>
&lt;3 <a href="https://webworker.sh" target="_blank">🐸</a> &middot; <a href="https://github.com/webworker01/knomp" target="_blank">knomp on Github</a> &middot; <a href="https://discord.gg/QaPwxKB" target="_blank" rel="nofollow noreferrer noopener">Discord Chat</a>
</footer>
</body>
</html>

2798
website/minerpond/key.html

File diff suppressed because it is too large

50
website/minerpond/pages/admin.html

@ -1,50 +0,0 @@
<div>
<style>
#passwordForm, #adminCenter{
display: none;
}
#adminCenter{
display: flex;
flex-flow: row;
}
#leftMenu{
flex: 0 0 200px;
}
#editForm{
flex: 1 1 auto;
}
</style>
<form class="pure-form pure-form-stacked" id="passwordForm">
<fieldset>
<legend>Password</legend>
<input id="password" type="password" placeholder="Password">
<label for="remember" class="pure-checkbox">
<input id="remember" type="checkbox"> Stay Logged In
</label>
<button type="submit" class="pure-button pure-button-primary">Log In</button>
</fieldset>
</form>
<div id="adminCenter">
<div class="pure-menu pure-menu-open" id="leftMenu">
<a class="pure-menu-heading">Administration</a>
<ul>
<li id="addPool"><a href="#">Add Pool</a></li>
<li class="pure-menu-heading" id="poolList">Current Pools</li>
</ul>
</div>
<div id="editForm"></div>
</div>
<script src="/static/admin.js"></script>
</div>

11
website/minerpond/pages/api.html

@ -1,11 +0,0 @@
<div style="margin: 18px;">
API - The API is work in progress and is subject to change during development.
<ul>
<li><a href="/api/stats">/api/stats</a> global pool stats</li>
<li><a href="/api/blocks">/api/blocks</a> global block stats</li>
<li><a href="/api/pool_stats">/api/pool_stats</a> - historical stats</li>
<li><a href="/api/payments">/api/payments</a> - payment history</li>
<li><a href="/api/worker_stats?taddr">/api/worker_stats?taddr</a> - historical time per pool json </li>
<li><a href="/api/live_stats">/api/live_stats</a> - live stats (websocket)</li>
</ul>
</div>

325
website/minerpond/pages/getting_started.html

@ -1,325 +0,0 @@
<style>
#holder{
display: flex;
flex-direction: row;
}
.glow{
box-shadow: inset 0 0 12px 4px #ff6c00;
}
.hidden{
display: none !important;
}
#menu{
background-color: #3d3d3d;
min-width: 170px;
}
#menu > .menuHeader{
color: #e3f7ff;
border-bottom: 1px solid #7f878b;
font-size: 1.2em;
padding: 16px 16px 4px 15px;
}
.menuList{
transition-duration: 200ms;
}
.menuList > a:first-child{
margin-top: 10px;
}
.menuList > a{
display: inline-block;
color: #e3f7ff;
text-decoration: none;
padding: 7px;
padding-left: 25px;
width:40px;
}
.menuList > a:hover{
color: #f69b3a;
}
#main{
flex: 1 1 auto;
display: flex;
flex-direction: column;
margin: 18px;
}
.miningOption{
color: white;
/* display: flex;
flex: 1 1 auto;
flex-direction: row;
flex-wrap: wrap; */
min-height: 215px;
justify-content: center;
align-items: center;
text-decoration: none;
}
a.miningOption:hover{
color: #f69b3a;
}
.miningOption:first-child{
background-color: #0eafc7;
}
.miningOption:last-child{
background-color: #b064e1;
}
.miningOptionNum{
font-size: 6em;
padding-right: 20px;
width: 140px;
text-align: center;
}
.miningOptionInstructions{
flex: 1 1 auto;
padding:10px;
}
.miningOptionInstructions > div:first-child{
font-size: 2.4em;
}
.miningOptionInstructions > div:last-child{
margin-top: 20px;
font-size: 1.3em;
}
#orHolder{
height: 37px;
text-align: center;
}
#orLine{
border-bottom: 1px solid #c2cacf;
height: 19px;
margin-bottom: -13px;
}
#orText{
background-color: #ebf4fa;
color: #5c5c5c;
display: inline-block;
width: 35px;
font-style: italic;
}
#coinInfoBackground{
transition-duration: 400ms;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: black;
opacity: 0.0;
}
#coinInfo{
display: flex;
flex-direction: column;
color: white;
width: 750px;
min-height: 400px;
top: 50px;
left: 50%;
margin-left: -375px;
position: absolute;
background-color: #f06350;
}
#coinInfo .coinInfoName{
text-transform: capitalize;
}
#coinInfo > div:first-of-type{
font-size: 1.8em;
text-align: center;
margin-top: 40px;
margin-bottom: 35px;
}
#coinInfoRows{
display: flex;
flex-direction: row;
justify-content: center;
flex: 1 1 auto;
margin-bottom: 70px;
}
#coinInfoRows > div{
display: flex;
flex-direction: column;
justify-content: center;
}
#coinInfoRows > div > div{
padding: 3px;
}
#coinInfoRowKeys{
font-weight: bold;
padding-right: 30px;
}
#coinInfoRowKeys .coinInfoSubtle{
font-weight: normal;
}
#coinInfoRowValues{
}
#coinInfoClose{
position: absolute;
font-size: 3em;
top: 0;
right: 0;
width: 60px;
height: 60px;
text-align: center;
color: white;
text-decoration: none;
}
#coinInfoClose:hover{
color: #50f0e3;
}
</style>
<div id="holder">
<a href="#" class="miningOption" id="coinGlowTrigger">
<div class="miningOptionInstructions">
<div>Select a coin for connection details</div>
<div>Configurations for each coin are available for advanced miners</div>
</div>
</a>
<div id="menu">
{{? (function(){
if (!it.portalConfig.switching) return false;
for (var p in it.portalConfig.switching){
if (it.portalConfig.switching[p].enabled)
return true;
}
return false;
})()
}}
<div class="menuHeader">Coin-Switching Ports</div>
{{?}}
<div class="menuList">
{{ for (var p in it.portalConfig.switching){
if (!it.portalConfig.switching[p].enabled) continue;
var info = {
algo: p,
ports: {},
host: it.portalConfig.website.stratumHost
};
info.ports[it.portalConfig.switching[p].port] = {diff: it.portalConfig.switching[p].diff};
info = JSON.stringify(info).replace(/"/g, '&quot;');
}}
<a href="#" class="poolOption" data-info="{{=info}}">{{=p}}</a>
{{ } }}
</div>
<div class="menuHeader">Coins</div>
<div class="menuList" id="coinList">
{{ for(var pool in it.poolsConfigs) {
var info = JSON.stringify({
coin: it.poolsConfigs[pool].coin,
algo: it.poolsConfigs[pool].coin.algorithm,
ports: it.poolsConfigs[pool].ports,
host: it.portalConfig.website.stratumHost
}).replace(/"/g, '&quot;');
}}
<a href="#" class="poolOption" data-info="{{=info}}">{{=pool}} {{=Object.keys(it.poolsConfigs[pool].ports)[0]}}</a>
{{ } }}
</div>
</div>
<!-- <div id="main">
<a href="#" class="miningOption" id="nompAppDownload">
<div class="miningOptionNum">1.</div>
<div class="miningOptionInstructions">
<div>Download NOMP App</div>
<div>Our preconfigured app makes mining that easy</div>
</div>
</a>
<div id="orHolder">
<div id="orLine"></div>
<div id="orText">or</div>
</div>
<a href="#" class="miningOption" id="coinGlowTrigger">
<div class="miningOptionNum">2.</div>
<div class="miningOptionInstructions">
<div>Select a coin for connection details</div>
<div>Configurations for each coin are available for advanced miners</div>
</div>
</a>
</div> -->
</div>
<a href="#" id="coinInfoBackground" class="hidden"></a>
<div id="coinInfo" class="hidden">
<a href="#" id="coinInfoClose">×</a>
<div><span class="coinInfoName"></span> Configuration:</div>
<div id="coinInfoRows">
<div id="coinInfoRowKeys">
<div>Username:</div>
<div>Password:</div>
</div>
<div id="coinInfoRowValues">
<div id="coinInfoUsername"></div>
<div>anything</div>
</div>
</div>
</div>
<script>
function showCoinConfig(info){
var htmlKeys = '<div class="coinInfoData">Algorithm:</div>';
var htmlValues = '<div class="coinInfoData">' + info.algo + '</div>';
for (var port in info.ports){
htmlKeys += '<div class="coinInfoData">URL <span class="coinInfoSubtle">(difficulty ' + info.ports[port].diff + ')</span>:</div>';
htmlValues += '<div class="coinInfoData">stratum+tcp://' + info.host + ':' + port + '</div>';
}
if (info.coin)
$('#coinInfoUsername').text('your ' + info.coin.name + ' wallet address');
else
$('#coinInfoUsername').text('your public key');
$('.coinInfoData').remove();
$('#coinInfoRowKeys').append(htmlKeys);
$('#coinInfoRowValues').append(htmlValues);
}
$('#coinGlowTrigger').click(function(event){
event.preventDefault();
$('.menuList').addClass('glow');
setTimeout(function(){
$('.menuList').removeClass('glow');
}, 200);
return false;
});
$('.poolOption').click(function(event){
event.preventDefault();
showCoinConfig($(this).data('info'));
$('#coinInfoBackground,#coinInfo').removeClass('hidden');
$('#coinInfoBackground').css('opacity', 0.7);
return false;
});
$('#coinInfoBackground,#coinInfoClose').click(function(event){
event.preventDefault();
$('#coinInfoBackground,#coinInfo').addClass('hidden');
$('#coinInfoBackground').css('opacity', 0.0);
return false;
});
$('#nompAppDownload').click(function(event){
event.preventDefault();
alert('NOMP App development still in progress...');
return false;
});
</script>

134
website/minerpond/pages/home.html

@ -1,134 +0,0 @@
<style>
#boxWelcome{
background-color: #0eafc7;
color: white;
margin: 18px;
}
#logoImg{
height: 285px;
margin: 55px;
}
#welcomeText{
font-size: 2.7em;
margin: 50px 18px 10px 18px;
}
#welcomeItems{
list-style-type: none;
font-size: 1.3em;
padding: 0 !important;
margin: 0 0 0 18px !important;
}
#welcomeItems > li{
margin: 30px !important;
}
#boxesLower {
margin: 0 9px;
}
#boxesLower > div {
display: flex;
}
#boxesLower > div > div {
flex: 1 1 auto;
margin: 0 9px 18px 9px;
padding: 10px;
display: flex;
flex-direction: column;
}
.boxLowerHeader{
font-size: 1.3em;
margin: 0 0 5px 10px;
}
#boxStatsLeft{
background-color: #b064e1;
}
#boxStatsRight{
background-color: #10bb9c;
}
.boxStats{
color: white;
}
.boxStatsList{
display: flex;
flex-flow: row wrap;
justify-content: space-around;
opacity: 0.77;
margin-bottom: 5px;
flex: 1 1 auto;
/* align-content: center; */
}
.boxStatsList i.fa{
height: 15px;
width: 33px;
text-align: center;
}
.boxStatsList > div{
padding: 5px 20px;
}
.boxStatsList > div > div{
padding: 3px;
}
</style>
<div class="pure-g-r" id="boxWelcome">
<!-- <img src="/static/komodo-logo-horizontal-01.png" style="margin: 0 auto; height:150px;"> -->
<div class="pure-u-1">
<div style="font-size: 2em; text-align:center; margin-bottom:10px;">MinerPond 🐸</div>
<div style="text-align:center; margin-bottom:10px;">Low 0.5% fee! Min payouts of 1!</div>
<div style="text-align:center; margin-bottom:10px;">KMDICE: Use a KMD compatible R address! Currently 15 minute payouts.</div>
<div style="text-align:center; margin-bottom:10px;">HUSH3Z: Use a zs1 sapling address! Currently 1 hour payouts.</div>
</div>
</div>
<div class="pure-g-r" id="boxesLower">
<div class="pure-u-1">
<div class="boxStats" id="boxStatsLeft">
<div class="boxLowerHeader">Global Stats</div>
<div class="boxStatsList">
{{ for(var algo in it.stats.algos) { }}
<div>
<div><i class="fa fa-flask"></i>{{=algo}}</div>
<div><i class="fa fa-users"></i><span id="statsMiners{{=algo}}">{{=it.stats.algos[algo].workers}}</span> Miners</div>
<div><i class="fa fa-tachometer"></i><span id="statsHashrate{{=algo}}">{{=it.stats.algos[algo].hashrateString}}</span></div>
</div>
{{ } }}
</div>
</div>
</div>
<div class="pure-u-1">
<div class="boxStats" id="boxStatsRight">
<div class="boxLowerHeader">Pools / Coins</div>
<div class="boxStatsList">
{{ for(var pool in it.stats.pools) { }}
<div>
<div><i class="fa fa-dot-circle-o"></i>{{=pool}}</div>
<div><i class="fa fa-users"></i><span id="statsMiners{{=pool}}">{{=it.stats.pools[pool].workerCount}}</span> Miners</div>
<div><i class="fa fa-tachometer"></i><span id="statsHashrate{{=pool}}">{{=it.stats.pools[pool].hashrateString}}</span></div>
</div>
{{ } }}
</div>
</div>
</div>
</div>
<script>
$(function() {
statsSource.addEventListener('message', function (e) {
var stats = JSON.parse(e.data);
for (algo in stats.algos) {
$('#statsMiners' + algo).text(stats.algos[algo].workers);
$('#statsHashrate' + algo).text(stats.algos[algo].hashrateString);
}
for (var pool in stats.pools) {
$('#statsMiners' + pool).text(stats.pools[pool].workerCount);
$('#statsHashrate' + pool).text(stats.pools[pool].hashrateString);
}
});
});
</script>

105
website/minerpond/pages/miner_stats.html

@ -1,105 +0,0 @@
<style>
#topCharts{
padding-left: 18px;
padding-right: 18px;
padding-top: 18px;
padding-bottom: 0px;
}
#topCharts > div > div > svg{
display: block;
height: 280px;
}
.chartWrapper{
border: solid 1px #c7c7c7;
border-radius: 5px;
padding: 5px;
margin-bottom: 18px;
}
.chartLabel{
font-size: 1.2em;
text-align: center;
padding: 4px;
}
.chartHolder{
}
#boxesWorkers {
margin: 0 9px;
}
#boxesWorkers > div {
display: flex;
}
#boxesWorkers > div > div {
flex: 1 1 auto;
margin: 0 9px 18px 9px;
padding: 10px;
display: flex;
flex-direction: column;
}
.boxLowerHeader{
font-size: 1.3em;
margin: 0 0 5px 10px;
}
#boxStatsLeft{
color: black;
background-color: #cccccc;
}
#boxStatsRight{
color: black;
background-color: #cccccc;
}
.boxStats{
color: white;
}
.boxStatsList{
display: flex;
flex-flow: row wrap;
justify-content: space-around;
opacity: 0.77;
margin-bottom: 5px;
flex: 1 1 auto;
align-content: center;
}
.boxStatsList i.fa{
height: 15px;
width: 33px;
text-align: center;
}
.boxStatsList > div{
padding: 5px 20px;
}
.boxStatsList > div > div{
padding: 3px;
}
</style>
<div id="topCharts">
<div class="chartWrapper">
<div class="chartLabel">
<!--<div style="float:left; padding-right: 18px;"><i class="fa fa-users"></i><span id="statsWorkers">...</span></div>-->
<div style="float:left; margin-right: 9px;">{{=String(it.stats.address).split(".")[0]}}</div>
<div style="float:right; padding-left: 18px;"><small><i class="fa fa-tachometer"></i> <span id="statsHashrateAvg">...</span> (Avg)</small></div>
<div style="float:right; padding-left: 18px;"><small><i class="fa fa-tachometer"></i> <span id="statsHashrate">...</span> (Now)</small></div>
<div style="float:right; padding-left: 18px;"><small><i class="fa fa-gavel"></i> Luck <span id="statsLuckDays">...</span> Days</small></div>
</div>
<div class="chartHolder"><svg id="workerHashrate" /></div>
<div>
<div style="float:right; padding-top: 9px; padding-right: 18px;"><i class="fa fa-cog"></i> Shares: <span id="statsTotalShares">...</span></div>
<div style="float:left; padding-top: 9px; padding-left: 18px; padding-right: 18px;"><i class="fa fa-money"></i> Immature: <span id="statsTotalImmature">...</span> </div>
<div style="float:left; padding-top: 9px; padding-left: 18px; padding-right: 18px;"><i class="fa fa-money"></i> Bal: <span id="statsTotalBal">...</span> </div>
<div style="padding-top: 9px; padding-left: 18px;"><i class="fa fa-money"></i> Paid: <span id="statsTotalPaid">...</span> </div>
</div>
</div>
</div>
<div id="boxesWorkers"> </div>
<script>
var _miner = "{{=String(it.stats.address).split(".")[0]}}";
var _workerCount = 0;
window.statsSource = new EventSource("/api/live_stats");
document.querySelector('main').appendChild(document.createElement('script')).src = '/static/miner_stats.js';
</script>

25
website/minerpond/pages/mining_key.html

@ -1,25 +0,0 @@
<style>
#miningKeyPage{
margin: 15px;
}
#keyFrame{
padding: 0;
border: 0;
width: 100%;
height: 750px;
display: block;
}
</style>
<div id="miningKeyPage">
<p>
This script run client-side (in your browser). For maximum security <a href="/key.html" download="key.html">download</a> the script and run it locally and
offline in a modern web browser.
</p>
<iframe id="keyFrame" src="/key.html">
</iframe>
</div>

94
website/minerpond/pages/payments.html

@ -1,94 +0,0 @@
<style>
#bottomNotes {
display: block;
padding-left: 18px;
padding-right: 18px;
padding-bottom: 18px;
}
#topPool {
padding-top: 18px;
padding-left: 18px;
padding-right: 18px;
}
#topPool > div > div > svg {
display: block;
height: 280px;
}
.poolWrapper {
border: solid 1px #c7c7c7;
border-radius: 5px;
padding: 5px;
margin-bottom: 18px;
}
.poolLabel {
font-size: 1.2em;
text-align: center;
padding: 4px;
}
.poolMinerTable {
}
table {
width: 100%;
}
table td {
padding: 6px 12px;
}
</style>
<script type="text/javascript">
$(function () {
$(document).tooltip({
content: function () {
return $(this).prop('title');
},
show: null,
close: function (event, ui) {
ui.tooltip.hover(
function () {
$(this).stop(true).fadeTo(400, 1);
},
function () {
$(this).fadeOut("400", function () {
$(this).remove();
})
});
}
});
});
</script>
{{ function readableDate(a){ return new Date(parseInt(a)).toISOString().substring(0, 16).replace('T', ' ') + ' UTC'; } }}
{{ for(var pool in it.stats.pools) { }}
<table class="puretable">
<thead>
<tr>
<th>Blocks</th>
<th>Time</th>
<th>Miners</th>
<th>Shares</th>
<th>Amount</th>
</tr>
</thead>
{{ for(var p in it.stats.pools[pool].payments) { }}
<tr>
<td style="max-width: 475px; word-wrap: break-word;">
{{if (String(it.stats.pools[pool].name) == 'kmd') { }}
<a href="https://kmdexplorer.io/tx/{{=it.stats.pools[pool].payments[p].txid}}" title="View transaction" target="_blank" rel="noopener noreferrer">{{=it.stats.pools[pool].payments[p].blocks}}</a>
{{ } else if (String(it.stats.pools[pool].name) == 'hush3z') { }}
<a href="https://hush.explorer.dexstats.info/tx/{{=it.stats.pools[pool].payments[p].txid}}" target="_blank" rel="noopener noreferrer">{{=it.stats.pools[pool].payments[p].blocks}}</a>
{{ } else if (String(it.stats.pools[pool].name) == 'kmdice') { }}
<a href="http://kmdice.explorer.dexstats.info/tx/{{=it.stats.pools[pool].payments[p].txid}}" target="_blank" rel="noopener noreferrer">{{=it.stats.pools[pool].payments[p].blocks}}</a>
{{ } else { }}
{{=it.stats.pools[pool].payments[p].blocks}}
{{ } }}
</td>
<td>{{=readableDate(it.stats.pools[pool].payments[p].time)}}</td>
<td>{{=it.stats.pools[pool].payments[p].miners}}</td>
<td>{{=Math.round(it.stats.pools[pool].payments[p].shares)}}</td>
<td>{{=it.stats.pools[pool].payments[p].paid}} {{=it.stats.pools[pool].symbol}}</td>
</tr>
{{ } }}
</table>
</div>
{{ } }}

234
website/minerpond/pages/stats.html

@ -1,234 +0,0 @@
<style>
#topCharts{
padding: 18px;
}
#topCharts > div > div > svg{
display: block;
height: 280px;
}
.chartWrapper{
border: solid 1px #c7c7c7;
border-radius: 5px;
padding: 5px;
margin-bottom: 18px;
}
.chartLabel{
font-size: 1.2em;
text-align: center;
padding: 4px;
}
#boxesLower {
margin: 0 9px;
}
#boxesLower > div {
display: flex;
}
#boxesLower > div > div {
flex: 1 1 auto;
margin: 0 9px 18px 9px;
padding: 10px;
display: flex;
flex-direction: column;
}
.boxLowerHeader{
font-size: 1.3em;
margin: 0 0 5px 10px;
}
#boxStatsLeft{
color: black;
background-color: #cccccc;
}
#boxStatsRight{
color: black;
background-color: #cccccc;
}
.boxStats{
color: white;
}
.boxStatsList{
display: flex;
flex-flow: row wrap;
justify-content: space-around;
opacity: 0.77;
margin-bottom: 5px;
flex: 1 1 auto;
align-content: center;
}
.boxStatsList i.fa{
height: 15px;
width: 33px;
text-align: center;
}
.boxStatsList > div{
padding: 5px 20px;
}
.boxStatsList > div > div{
padding: 3px;
}
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 28px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
#tooltip.hidden {
opacity: 0;
}
</style>
<div id="topCharts">
<div class="chartWrapper">
<div class="chartLabel">Pool Historical Hashrate</div>
<div class="chartHolder"><svg id="poolHashrate"/></div>
</div>
</div>
{{ function capitalizeFirstLetter(t){return t.charAt(0).toUpperCase()+t.slice(1)} }}
{{ function readableDate(a){ return new Date(parseInt(a)).toISOString().substring(0, 16).replace('T', ' ') + ' UTC'; } }}
<div class="pure-g-r" id="boxesLower">
{{ for(var pool in it.stats.pools) { }}
<div class="pure-u-1-2">
<div class="boxStats" id="boxStatsLeft">
<div class="boxLowerHeader">{{=it.stats.pools[pool].name}} Pool Stats</div>
<div class="boxStatsList">
<div>
<div><i class="fa fa-users"></i><span id="statsMiners{{=pool}}">{{=it.stats.pools[pool].minerCount}}</span> Miners</div>
<div><i class="fa fa-rocket"></i><span id="statsWorkers{{=pool}}">{{=it.stats.pools[pool].workerCount}}</span> Workers</div>
<div><i class="fa fa-tachometer"></i><span id="statsHashrate{{=pool}}">{{=it.stats.pools[pool].hashrateString}}</span> (Now)</div>
<div><i class="fa fa-tachometer"></i><span id="statsHashrateAvg{{=pool}}">...</span> (Avg)</div>
<div><i class="fa fa-gavel"></i>Luck <span id="statsLuckDays{{=pool}}">{{=it.stats.pools[pool].luckDays}}</span> Days</div>
</div>
</div>
</div>
</div>
<div class="pure-u-1-2">
<div class="boxStats" id="boxStatsRight">
<div class="boxLowerHeader">{{=it.stats.pools[pool].name}} Network Stats</div>
<div class="boxStatsList">
<div>
<div><i class="fa fa-bars" aria-hidden="true"></i><small>Block Height:</small> <span id="statsNetworkBlocks{{=pool}}">{{=it.stats.pools[pool].poolStats.networkBlocks}}</span></div>
<div><i class="fa fa-tachometer"></i><small>Network Hash/s:</small> <span id="statsNetworkSols{{=pool}}">{{=it.stats.pools[pool].poolStats.networkSolsString}}</span></div>
<div><i class="fa fa-unlock-alt" aria-hidden="true"></i><small>Difficulty:</small> <span id="statsNetworkDiff{{=pool}}">{{=it.stats.pools[pool].poolStats.networkDiff}}</span></div>
<div><i class="fa fa-users"></i><small>Node Connections:</small> <span id="statsNetworkConnections{{=pool}}">{{=it.stats.pools[pool].poolStats.networkConnections}}</span></div>
</div>
</div>
</div>
</div>
{{ } }}
</div>
{{ for(var pool in it.stats.pools) { }}
<div class="pure-g-r" id="boxesLower">
<div class="pure-u-1-1">
<div class="boxStats" id="boxStatsRight">
<div class="boxLowerHeader">{{=it.stats.pools[pool].name}} Blocks Found &nbsp;&nbsp;
<span style="float:right;"><small>
<i class="fa fa-bars"></i> <span id="statsValidBlocks{{=pool}}">{{=it.stats.pools[pool].poolStats.validBlocks}}</span> Blocks &nbsp;&nbsp;
<i class="fa fa-money"></i> Paid: <span id="statsTotalPaid{{=pool}}">{{=(parseFloat(it.stats.pools[pool].poolStats.totalPaid)).toFixed(8)}}</span> {{=it.stats.pools[pool].symbol}}</small>&nbsp;&nbsp;</span>
</div>
<div class="boxStatsList" style="margin-top: 9px;">
<!--<div id="{{=it.stats.pools[pool].name}}NewBlocks"></div>-->
{{ for(var b in it.stats.pools[pool].pending.blocks) { }}
{{ var block = it.stats.pools[pool].pending.blocks[b].split(":"); }}
<div style="margin-bottom: 9px; background-color: #eeeeee; min-width:600px;" title="{{if (it.stats.pools[pool].pending.confirms && it.stats.pools[pool].pending.confirms[block[0]]) { }}{{if (it.stats.pools[pool].pending.confirms[block[0]] == 1) { }}Waiting for dPoW notarization{{} else if (it.stats.pools[pool].pending.confirms[block[0]] < it.poolsConfigs[pool].paymentProcessing.minConf*2) { }}Waiting for min confirmations{{ } else { }}Queued for payment{{ } }}{{ } else { }}Waiting for payment processor to review{{ } }}">
<i class="fa fa-bars"></i>
<small>Block:</small>
{{if (String(it.stats.pools[pool].name) == "kmd") { }}
<a href="https://kmdexplorer.io/blocks/{{=block[0]}}" target="_blank">{{=block[2]}}</a>
{{ } else if (String(it.stats.pools[pool].name) == "rkt") { }}
<a href="http://rkt.explorer.dexstats.info/block/{{=block[0]}}" target="_blank">{{=block[2]}}</a>
{{ } else if (String(it.stats.pools[pool].name) == "kmdice") { }}
<a href="https://kmdice.explorer.dexstats.info/block/{{=block[0]}}" target="_blank">{{=block[2]}}</a>
{{ } else if (String(it.stats.pools[pool].name) == "hush3z") { }}
<a href="https://hush.explorer.dexstats.info/block/{{=block[0]}}" target="_blank">{{=block[2]}}</a>
{{ } else { }}
{{=block[2]}}
{{ } }}
{{if (block[4] != null) { }}
<span style="padding-left: 18px;"><small>{{=readableDate(block[4])}}</small></span>
{{ } }}
{{if (it.stats.pools[pool].pending.confirms && it.stats.pools[pool].pending.confirms[block[0]]) { }}
{{if (it.stats.pools[pool].pending.confirms[block[0]] == 1) { }}
<span style="float:right; color: red;"><small>Waiting for Notarization</small></span>
{{ } else { }}
<span style="float:right; color: red;"><small>{{=it.stats.pools[pool].pending.confirms[block[0]]}} of {{=it.poolsConfigs[pool].paymentProcessing.minConf*2}} Confirmations</small></span>
{{ } }}
{{ } else { }}
<span style="float:right; color: red;"><small>*PENDING*</small></span>
{{ } }}
</div>
{{ } }}
{{ var i=0; for(var b in it.stats.pools[pool].confirmed.blocks) { }}
{{ if (i < 8) { i++; }}
{{ var block = it.stats.pools[pool].confirmed.blocks[b].split(":"); }}
<div style="margin-bottom: 9px; background-color: #eeeeee; min-width:600px;"><i class="fa fa-bars"></i>
<small>Block:</small>
{{if (String(it.stats.pools[pool].name) == "kmd") { }}
<a href="https://kmdexplorer.io/blocks/{{=block[0]}}" target="_blank">{{=block[2]}}</a>
{{ } else if (String(it.stats.pools[pool].name).startsWith("rkt")) { }}
<a href="http://rkt.explorer.dexstats.info/block/{{=block[0]}}" target="_blank">{{=block[2]}}</a>
{{ } else if (String(it.stats.pools[pool].name).startsWith("kmdice")) { }}
<a href="http://kmdice.explorer.dexstats.info/block/{{=block[0]}}" target="_blank">{{=block[2]}}</a>
{{ } else if (String(it.stats.pools[pool].name) == "hush3z") { }}
<a href="https://hush.explorer.dexstats.info/block/{{=block[0]}}" target="_blank">{{=block[2]}}</a>
{{ } else { }}
{{=block[2]}}
{{ } }}
{{if (block[4] != null) { }}
<span style="padding-left: 18px;"><small>{{=readableDate(block[4])}}</small></span>
{{ } }}
<span style="float:right; padding-left: 18px; color: green;"><small>*PAID*</small></span>
</div>
{{ } }}
{{ } }}
</div>
</div>
</div>
</div>
{{ } }}
<script>
document.querySelector('main').appendChild(document.createElement('script')).src = '/static/stats.js';
$(function() {
window.statsSource = new EventSource("/api/live_stats");
statsSource.addEventListener('message', function (e) {
var stats = JSON.parse(e.data);
for (var pool in stats.pools) {
$('#statsMiners' + pool).text(stats.pools[pool].minerCount);
$('#statsWorkers' + pool).text(stats.pools[pool].workerCount);
$('#statsHashrate' + pool).text(stats.pools[pool].hashrateString);
$('#statsHashrateAvg' + pool).text(getReadableHashRateString(calculateAverageHashrate(pool)));
$('#statsLuckDays' + pool).text(stats.pools[pool].luckDays);
$('#statsValidBlocks' + pool).text(stats.pools[pool].poolStats.validBlocks);
$('#statsTotalPaid' + pool).text((parseFloat(stats.pools[pool].poolStats.totalPaid)).toFixed(8));
$('#statsNetworkBlocks' + pool).text(stats.pools[pool].poolStats.networkBlocks);
$('#statsNetworkDiff' + pool).text(stats.pools[pool].poolStats.networkDiff);
$('#statsNetworkSols' + pool).text(getReadableNetworkHashRateString(stats.pools[pool].poolStats.networkSols));
$('#statsNetworkConnections' + pool).text(stats.pools[pool].poolStats.networkConnections);
}
});
});
function getReadableNetworkHashRateString(hashrate){
hashrate = (hashrate * 1000000);
if (hashrate < 1000000)
return '0 Sol';
var byteUnits = [ ' Sol/s', ' KSol/s', ' MSol/s', ' GSol/s', ' TSol/s', ' PSol/s' ];
var i = Math.floor((Math.log(hashrate/1000) / Math.log(1000)) - 1);
hashrate = (hashrate/1000) / Math.pow(1000, i + 1);
return hashrate.toFixed(2) + byteUnits[i];
}
</script>

64
website/minerpond/pages/tbs.html

@ -1,64 +0,0 @@
<style>
#topCharts {
padding: 18px;
}
#topCharts > div > div > svg {
display: block;
height: 280px;
}
.chartWrapper {
border: solid 1px #c7c7c7;
border-radius: 5px;
padding: 5px;
margin-bottom: 18px;
}
.chartLabel {
font-size: 1.2em;
text-align: center;
padding: 4px;
}
.chartHolder {
}
table {
width: 100%;
}
</style>
<table class="pure-table">
<thead>
<tr>
<th>Pool</th>
<th>Algo</th>
<th>Workers</th>
<th>Valid Shares</th>
<th>Invalid Shares</th>
<th>Total Blocks</th>
<th>Pending</th>
<th>Confirmed</th>
<th>Orphaned</th>
<th>Hashrate</th>
</tr>
</thead>
{{ for(var pool in it.stats.pools) { }}
<tr class="pure-table-odd">
<td>{{=it.stats.pools[pool].name}}</td>
<td>{{=it.stats.pools[pool].algorithm}}</td>
<td>{{=Object.keys(it.stats.pools[pool].workers).length}}</td>
<td>{{=it.stats.pools[pool].poolStats.validShares}}</td>
<td>{{=it.stats.pools[pool].poolStats.invalidShares}}</td>
<td>{{=it.stats.pools[pool].poolStats.validBlocks}}</td>
<td>{{=it.stats.pools[pool].blocks.pending}}</td>
<td>{{=it.stats.pools[pool].blocks.confirmed}}</td>
<td>{{=it.stats.pools[pool].blocks.orphaned}}</td>
<td>{{=it.stats.pools[pool].hashrateString}}</td>
</tr>
{{ } }}
</table>

96
website/minerpond/pages/workers.html

@ -1,96 +0,0 @@
<style>
#bottomNotes {
display: block;
padding-left: 18px;
padding-right: 18px;
padding-bottom: 18px;
}
#topPool {
padding-top: 18px;
padding-left: 18px;
padding-right: 18px;
}
#topPool > div > div > svg {
display: block;
height: 280px;
}
.poolWrapper {
border: solid 1px #c7c7c7;
border-radius: 5px;
padding: 5px;
margin-bottom: 18px;
}
.poolLabel {
font-size: 1.2em;
text-align: center;
padding: 4px;
}
.poolMinerTable {
}
table {
width: 100%;
}
</style>
<script type="text/javascript">
function searchKeyPress(e)
{
// look for window.event in case event isn't passed in
e = e || window.event;
if (e.keyCode == 13) {
document.getElementById('btnSearch').click();
return false;
}
return true;
}
$(document).ready(function(){
$('.btn-lg').click(function(){
window.location = "workers/" + $('.input-lg').val();
});
});
</script>
{{ function capitalizeFirstLetter(t){return t.charAt(0).toUpperCase()+t.slice(1)} }}
{{ var i=0; for(var pool in it.stats.pools) { }}
<div id="topPool">
<div class="poolWrapper">
<div class="poolLabel">
<span style="float:right; margin-bottom: 8px;">
<small>
Miner Lookup:
<input type="text" class="form-control input-lg" onkeypress="return searchKeyPress(event);">
<span class="input-group-btn">
<button class="btn btn-default btn-lg" type="button">Lookup</button>
</span>
</small>
</span>
{{=capitalizeFirstLetter(it.stats.pools[pool].name)}} Top Miners &nbsp;&nbsp;
<small><i class="fa fa-users"></i> <span id="statsMiners{{=pool}}">{{=it.stats.pools[pool].minerCount}}</span> Miners &nbsp;&nbsp;
<i class="fa fa-rocket"></i> <span id="statsWorkers{{=pool}}">{{=it.stats.pools[pool].workerCount}}</span> Workers &nbsp;&nbsp;
<i class="fa fa-cog"></i> <span id="statsWorkers{{=pool}}">{{=it.stats.pools[pool].shareCount}}</span> Shares </small>
</div>
<div class="poolMinerTable">
<table class="pure-table">
<thead>
<tr>
<th>Address</th>
<th>Shares</th>
<th>Efficiency</th>
<th>Hashrate</th>
</tr>
</thead>
{{ var minerindex = 0; }}
{{ for(var worker in it.stats.pools[pool].miners) { }}
{{var workerstat = it.stats.pools[pool].miners[worker];}}
{{ minerindex++; }}
<tr class="pure-table-odd" id="miner-{{=minerindex}}">
<td>Miner #{{=minerindex}}</td>
<td>{{=Math.round(workerstat.currRoundShares * 100) / 100}}</td>
<td>{{? workerstat.shares > 0}} {{=Math.floor(10000 * workerstat.shares / (workerstat.shares + workerstat.invalidshares)) / 100}}% {{??}} 0% {{?}}</td>
<td>{{=workerstat.hashrateString}}</td>
</tr>
{{ } }}
</table>
</div>
</div>
</div>
{{ } }}

100
website/minerpond/static/admin.js

@ -1,100 +0,0 @@
var docCookies = {
getItem: function (sKey) {
return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
},
setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
var sExpires = "";
if (vEnd) {
switch (vEnd.constructor) {
case Number:
sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
break;
case String:
sExpires = "; expires=" + vEnd;
break;
case Date:
sExpires = "; expires=" + vEnd.toUTCString();
break;
}
}
document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
return true;
},
removeItem: function (sKey, sPath, sDomain) {
if (!sKey || !this.hasItem(sKey)) { return false; }
document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + ( sDomain ? "; domain=" + sDomain : "") + ( sPath ? "; path=" + sPath : "");
return true;
},
hasItem: function (sKey) {
return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
}
};
var password = docCookies.getItem('password');
function showLogin(){
$('#adminCenter').hide();
$('#passwordForm').show();
}
function showAdminCenter(){
$('#passwordForm').hide();
$('#adminCenter').show();
}
function tryLogin(){
apiRequest('pools', {}, function(response){
showAdminCenter();
displayMenu(response.result)
});
}
function displayMenu(pools){
$('#poolList').after(Object.keys(pools).map(function(poolName){
return '<li class="poolMenuItem"><a href="#">' + poolName + '</a></li>';
}).join(''));
}
function apiRequest(func, data, callback){
var httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function(){
if (httpRequest.readyState === 4 && httpRequest.responseText){
if (httpRequest.status === 401){
docCookies.removeItem('password');
$('#password').val('');
showLogin();
alert('Incorrect Password');
}
else{
var response = JSON.parse(httpRequest.responseText);
callback(response);
}
}
};
httpRequest.open('POST', '/api/admin/' + func);
data.password = password;
httpRequest.setRequestHeader('Content-Type', 'application/json');
httpRequest.send(JSON.stringify(data));
}
if (password){
tryLogin();
}
else{
showLogin();
}
$('#passwordForm').submit(function(event){
event.preventDefault();
password = $('#password').val();
if (password){
if ($('#remember').is(':checked'))
docCookies.setItem('password', password, Infinity);
else
docCookies.setItem('password', password);
tryLogin();
}
return false;
});

BIN
website/minerpond/static/favicon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 413 B

13
website/minerpond/static/kmdfavicon.svg

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 72 72" style="enable-background:new 0 0 72 72;" xml:space="preserve">
<style type="text/css">
.st0{fill:#316565;}
.st1{fill:#FFFFFF;}
</style>
<rect x="0" y="0" class="st0" width="72" height="72"/>
<path class="st1" d="M35.9,65.4l20.8-8.5l8.7-20.8l-8.5-21L36.1,6.6l-20.8,8.5v0.2L6.6,36.1l8.5,20.8L35.9,65.4z M23,22.9L23,22.9
l13.1-5.5l13.1,5.5l5.5,13.1l-5.5,13.1l-13.1,5.5L23,49.2l-5.5-13.1L23,22.9z"/>
<polygon class="st1" points="36,46.9 43.7,43.7 46.9,35.9 43.7,28.3 36,25.1 28.4,28.3 25.2,35.9 28.2,43.7 "/>
</svg>

Before

Width:  |  Height:  |  Size: 797 B

BIN
website/minerpond/static/komodo-logo-horizontal-01.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

13
website/minerpond/static/logo.svg

@ -1,13 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" width="350px" height="350px" viewBox="0 0 350 350" enable-background="new 0 0 350 350" xml:space="preserve" xmlns:xml="http://www.w3.org/XML/1998/namespace">
<g>
<path fill="#F48438" d="M138,346H93c0,0-9,0-9-9s0-18,0-18h63c0,0,0,9,0,18S138,346,138,346z"/>
<path fill="#F48438" d="M255,346h-45c0,0-9,0-9-9s0-18,0-18h63c0,0,0,9,0,18S255,346,255,346z"/>
<path fill="#F48438" d="M30,139c0-63,105.099-79.872,143.186-80C210.458,58.875,318,76,318,139c0,0,0,84.71,0,153c0,27-27,27-27,27 H57c0,0-27,0-27-27V139z"/>
<path fill="#FFFFFF" d="M246,264.056c0,4.643-3.428,8.944-9.12,8.944H112.805c-5.691,0-10.805-4.301-10.805-8.944v-65.15 c0-4.643,5.114-7.906,10.805-7.906H236.88c5.691,0,9.12,3.264,9.12,7.906V264.056z"/>
<circle fill="#FFFFFF" cx="94.667" cy="141.667" r="20.333"/>
<circle fill="#FFFFFF" cx="252.667" cy="141.667" r="20.333"/>
<path fill="#F48438" d="M174.24,45.664c24.69-30.635,70.778-25.601,70.778-25.601l6.603,13.863c0,0-48.596-0.658-62.896,24.075 S149.551,76.3,174.24,45.664z"/>
<circle fill="#F48438" cx="259.083" cy="24.083" r="21.083"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

30
website/minerpond/static/main.js

@ -1,30 +0,0 @@
$(function(){
var hotSwap = function(page, pushSate){
if (pushSate) history.pushState(null, null, '/' + page);
$('.pure-menu-selected').removeClass('pure-menu-selected');
$('a[href="/' + page + '"]').parent().addClass('pure-menu-selected');
$.get("/get_page", {id: page}, function(data){
$('main').html(data);
}, 'html')
};
$('.hot-swapper').click(function(event){
if (event.which !== 1) return;
var pageId = $(this).attr('href').slice(1);
hotSwap(pageId, true);
event.preventDefault();
return false;
});
window.addEventListener('load', function() {
setTimeout(function() {
window.addEventListener("popstate", function(e) {
hotSwap(location.pathname.slice(1));
});
}, 0);
});
window.statsSource = new EventSource("/api/live_stats");
});

246
website/minerpond/static/miner_stats.js

@ -1,246 +0,0 @@
var workerHashrateData;
var workerHashrateChart;
var workerHistoryMax = 160;
var statData;
var totalHash;
var totalImmature;
var totalBal;
var totalPaid;
var totalShares;
function getReadableHashRateString(hashrate){
hashrate = (hashrate * 2);
if (hashrate < 1000000) {
return (Math.round(hashrate / 1000) / 1000 ).toFixed(2)+' Sol/s';
}
var byteUnits = [ ' Sol/s', ' KSol/s', ' MSol/s', ' GSol/s', ' TSol/s', ' PSol/s' ];
var i = Math.floor((Math.log(hashrate/1000) / Math.log(1000)) - 1);
hashrate = (hashrate/1000) / Math.pow(1000, i + 1);
return hashrate.toFixed(2) + byteUnits[i];
}
function timeOfDayFormat(timestamp){
var dStr = d3.time.format('%I:%M %p')(new Date(timestamp));
if (dStr.indexOf('0') === 0) dStr = dStr.slice(1);
return dStr;
}
function getWorkerNameFromAddress(w) {
var worker = w;
if (w.split(".").length > 1) {
worker = w.split(".")[1];
if (worker == null || worker.length < 1) {
worker = "noname";
}
} else {
worker = "noname";
}
return worker;
}
function buildChartData(){
var workers = {};
for (var w in statData.history) {
var worker = getWorkerNameFromAddress(w);
var a = workers[worker] = (workers[worker] || {
hashrate: []
});
for (var wh in statData.history[w]) {
a.hashrate.push([statData.history[w][wh].time * 1000, statData.history[w][wh].hashrate]);
}
if (a.hashrate.length > workerHistoryMax) {
workerHistoryMax = a.hashrate.length;
}
}
var i=0;
workerHashrateData = [];
for (var worker in workers){
workerHashrateData.push({
key: worker,
disabled: (i > Math.min((_workerCount-1), 3)),
values: workers[worker].hashrate
});
i++;
}
}
function updateChartData(){
var workers = {};
for (var w in statData.history) {
var worker = getWorkerNameFromAddress(w);
// get a reference to lastest workerhistory
for (var wh in statData.history[w]) { }
//var wh = statData.history[w][statData.history[w].length - 1];
var foundWorker = false;
for (var i = 0; i < workerHashrateData.length; i++) {
if (workerHashrateData[i].key === worker) {
foundWorker = true;
if (workerHashrateData[i].values.length >= workerHistoryMax) {
workerHashrateData[i].values.shift();
}
workerHashrateData[i].values.push([statData.history[w][wh].time * 1000, statData.history[w][wh].hashrate]);
break;
}
}
if (!foundWorker) {
var hashrate = [];
hashrate.push([statData.history[w][wh].time * 1000, statData.history[w][wh].hashrate]);
workerHashrateData.push({
key: worker,
values: hashrate
});
rebuildWorkerDisplay();
return true;
}
}
triggerChartUpdates();
return false;
}
function calculateAverageHashrate(worker) {
var count = 0;
var total = 1;
var avg = 0;
for (var i = 0; i < workerHashrateData.length; i++) {
count = 0;
for (var ii = 0; ii < workerHashrateData[i].values.length; ii++) {
if (worker == null || workerHashrateData[i].key === worker) {
count++;
avg += parseFloat(workerHashrateData[i].values[ii][1]);
}
}
if (count > total)
total = count;
}
avg = avg / total;
return avg;
}
function triggerChartUpdates(){
workerHashrateChart.update();
}
function displayCharts() {
nv.addGraph(function() {
workerHashrateChart = nv.models.lineChart()
.margin({left: 80, right: 30})
.x(function(d){ return d[0] })
.y(function(d){ return d[1] })
.useInteractiveGuideline(true);
workerHashrateChart.xAxis.tickFormat(timeOfDayFormat);
workerHashrateChart.yAxis.tickFormat(function(d){
return getReadableHashRateString(d);
});
d3.select('#workerHashrate').datum(workerHashrateData).call(workerHashrateChart);
return workerHashrateChart;
});
}
function updateStats() {
totalHash = statData.totalHash;
totalPaid = statData.paid;
totalBal = statData.balance;
totalImmature = statData.immature;
totalShares = statData.totalShares;
// do some calculations
var _blocktime = 250;
var _networkHashRate = parseFloat(statData.networkSols) * 1.2;
var _myHashRate = (totalHash / 1000000) * 2;
var luckDays = ((_networkHashRate / _myHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3);
// update miner stats
$("#statsHashrate").text(getReadableHashRateString(totalHash));
$("#statsHashrateAvg").text(getReadableHashRateString(calculateAverageHashrate(null)));
$("#statsLuckDays").text(luckDays);
$("#statsTotalImmature").text(totalImmature);
$("#statsTotalBal").text(totalBal);
$("#statsTotalPaid").text(totalPaid);
$("#statsTotalShares").text(totalShares.toFixed(2));
}
function updateWorkerStats() {
// update worker stats
var i=0;
for (var w in statData.workers) { i++;
var htmlSafeWorkerName = w.split('.').join('_').replace(/[^\w\s]/gi, '');
var saneWorkerName = getWorkerNameFromAddress(w);
$("#statsHashrate"+htmlSafeWorkerName).text(getReadableHashRateString(statData.workers[w].hashrate));
$("#statsHashrateAvg"+htmlSafeWorkerName).text(getReadableHashRateString(calculateAverageHashrate(saneWorkerName)));
$("#statsLuckDays"+htmlSafeWorkerName).text(statData.workers[w].luckDays);
$("#statsPaid"+htmlSafeWorkerName).text(statData.workers[w].paid);
$("#statsBalance"+htmlSafeWorkerName).text(statData.workers[w].balance);
$("#statsShares"+htmlSafeWorkerName).text(Math.round(statData.workers[w].currRoundShares * 100) / 100);
$("#statsDiff"+htmlSafeWorkerName).text(statData.workers[w].diff);
}
}
function addWorkerToDisplay(name, htmlSafeName, workerObj) {
var htmlToAdd = "";
htmlToAdd = '<div class="boxStats" id="boxStatsLeft" style="float:left; margin: 9px; min-width: 260px;"><div class="boxStatsList">';
if (htmlSafeName.indexOf("_") >= 0) {
htmlToAdd+= '<div class="boxLowerHeader">'+htmlSafeName.substr(htmlSafeName.indexOf("_")+1,htmlSafeName.length)+'</div>';
} else {
htmlToAdd+= '<div class="boxLowerHeader">noname</div>';
}
htmlToAdd+='<div><i class="fa fa-tachometer"></i> <span id="statsHashrate'+htmlSafeName+'">'+getReadableHashRateString(workerObj.hashrate)+'</span> (Now)</div>';
htmlToAdd+='<div><i class="fa fa-tachometer"></i> <span id="statsHashrateAvg'+htmlSafeName+'">'+getReadableHashRateString(calculateAverageHashrate(name))+'</span> (Avg)</div>';
htmlToAdd+='<div><i class="fa fa-shield"></i> <small>Diff:</small> <span id="statsDiff'+htmlSafeName+'">'+workerObj.diff+'</span></div>';
htmlToAdd+='<div><i class="fa fa-cog"></i> <small>Shares:</small> <span id="statsShares'+htmlSafeName+'">'+(Math.round(workerObj.currRoundShares * 100) / 100)+'</span></div>';
htmlToAdd+='<div><i class="fa fa-gavel"></i> <small>Luck <span id="statsLuckDays'+htmlSafeName+'">'+workerObj.luckDays+'</span> Days</small></div>';
htmlToAdd+='<div><i class="fa fa-money"></i> <small>Bal: <span id="statsBalance'+htmlSafeName+'">'+workerObj.balance+'</span></small></div>';
htmlToAdd+='<div><i class="fa fa-money"></i> <small>Paid: <span id="statsPaid'+htmlSafeName+'">'+workerObj.paid+'</span></small></div>';
htmlToAdd+='</div></div></div>';
$("#boxesWorkers").html($("#boxesWorkers").html()+htmlToAdd);
}
function rebuildWorkerDisplay() {
$("#boxesWorkers").html("");
var i=0;
for (var w in statData.workers) { i++;
var htmlSafeWorkerName = w.split('.').join('_').replace(/[^\w\s]/gi, '');
var saneWorkerName = getWorkerNameFromAddress(w);
addWorkerToDisplay(saneWorkerName, htmlSafeWorkerName, statData.workers[w]);
}
}
// resize chart on window resize
nv.utils.windowResize(triggerChartUpdates);
// grab initial stats
$.getJSON('/api/worker_stats?'+_miner, function(data){
statData = data;
for (var w in statData.workers) { _workerCount++; }
buildChartData();
displayCharts();
rebuildWorkerDisplay();
updateStats();
});
// live stat updates
statsSource.addEventListener('message', function(e){
// TODO, create miner_live_stats...
// miner_live_stats will return the same josn except without the worker history
// FOR NOW, use this to grab updated stats
$.getJSON('/api/worker_stats?'+_miner, function(data){
statData = data;
// check for missing workers
var wc = 0;
var rebuilt = false;
// update worker stats
for (var w in statData.workers) { wc++; }
// TODO, this isn't 100% fool proof!
if (_workerCount != wc) {
if (_workerCount > wc) {
rebuildWorkerDisplay();
rebuilt = true;
}
_workerCount = wc;
}
rebuilt = (rebuilt || updateChartData());
updateStats();
if (!rebuilt) {
updateWorkerStats();
}
});
});

1
website/minerpond/static/nvd3.css

File diff suppressed because one or more lines are too long

6
website/minerpond/static/nvd3.js

File diff suppressed because one or more lines are too long

143
website/minerpond/static/stats.js

@ -1,143 +0,0 @@
var poolHashrateData;
var poolHashrateChart;
var statData;
var poolKeys;
function buildChartData(){
var pools = {};
poolKeys = [];
for (var i = 0; i < statData.length; i++){
for (var pool in statData[i].pools){
if (poolKeys.indexOf(pool) === -1)
poolKeys.push(pool);
}
}
for (var i = 0; i < statData.length; i++) {
var time = statData[i].time * 1000;
for (var f = 0; f < poolKeys.length; f++){
var pName = poolKeys[f];
var a = pools[pName] = (pools[pName] || {
hashrate: []
});
if (pName in statData[i].pools){
a.hashrate.push([time, statData[i].pools[pName].hashrate]);
}
else{
a.hashrate.push([time, 0]);
}
}
}
poolHashrateData = [];
for (var pool in pools){
poolHashrateData.push({
key: pool,
values: pools[pool].hashrate
});
$('#statsHashrateAvg' + pool).text(getReadableHashRateString(calculateAverageHashrate(pool)));
}
}
function calculateAverageHashrate(pool) {
var count = 0;
var total = 1;
var avg = 0;
for (var i = 0; i < poolHashrateData.length; i++) {
count = 0;
for (var ii = 0; ii < poolHashrateData[i].values.length; ii++) {
if (pool == null || poolHashrateData[i].key === pool) {
count++;
avg += parseFloat(poolHashrateData[i].values[ii][1]);
}
}
if (count > total)
total = count;
}
avg = avg / total;
return avg;
}
function getReadableHashRateString(hashrate){
hashrate = (hashrate * 2);
if (hashrate < 1000000) {
return (Math.round(hashrate / 1000) / 1000 ).toFixed(2)+' Sol/s';
}
var byteUnits = [ ' Sol/s', ' KSol/s', ' MSol/s', ' GSol/s', ' TSol/s', ' PSol/s' ];
var i = Math.floor((Math.log(hashrate/1000) / Math.log(1000)) - 1);
hashrate = (hashrate/1000) / Math.pow(1000, i + 1);
return hashrate.toFixed(2) + byteUnits[i];
}
function timeOfDayFormat(timestamp){
var dStr = d3.time.format('%I:%M %p')(new Date(timestamp));
if (dStr.indexOf('0') === 0) dStr = dStr.slice(1);
return dStr;
}
function displayCharts(){
nv.addGraph(function() {
poolHashrateChart = nv.models.lineChart()
.margin({left: 80, right: 30})
.x(function(d){ return d[0] })
.y(function(d){ return d[1] })
.useInteractiveGuideline(true);
poolHashrateChart.xAxis.tickFormat(timeOfDayFormat);
poolHashrateChart.yAxis.tickFormat(function(d){
return getReadableHashRateString(d);
});
d3.select('#poolHashrate').datum(poolHashrateData).call(poolHashrateChart);
return poolHashrateChart;
});
}
function triggerChartUpdates(){
poolHashrateChart.update();
}
nv.utils.windowResize(triggerChartUpdates);
$.getJSON('/api/pool_stats', function(data){
statData = data;
buildChartData();
displayCharts();
});
statsSource.addEventListener('message', function(e){
var stats = JSON.parse(e.data);
statData.push(stats);
var newPoolAdded = (function(){
for (var p in stats.pools){
if (poolKeys.indexOf(p) === -1)
return true;
}
return false;
})();
if (newPoolAdded || Object.keys(stats.pools).length > poolKeys.length){
buildChartData();
displayCharts();
}
else {
var time = stats.time * 1000;
for (var f = 0; f < poolKeys.length; f++) {
var pool = poolKeys[f];
for (var i = 0; i < poolHashrateData.length; i++) {
if (poolHashrateData[i].key === pool) {
poolHashrateData[i].values.shift();
poolHashrateData[i].values.push([time, pool in stats.pools ? stats.pools[pool].hashrate : 0]);
$('#statsHashrateAvg' + pool).text(getReadableHashRateString(calculateAverageHashrate(pool)));
break;
}
}
}
triggerChartUpdates();
}
});

68
website/minerpond/static/style.css

@ -1,68 +0,0 @@
html, button, input, select, textarea, .pure-g [class *= "pure-u"], .pure-g-r [class *= "pure-u"]{
font-family: 'Open Sans', sans-serif;
}
html{
background: #2d2d2d;
overflow-y: scroll;
}
body{
display: flex;
flex-direction: column;
max-width: 1160px;
margin: 0 auto;
}
header > .home-menu{
background: inherit !important;
height: 54px;
display: flex;
}
header > .home-menu > a.pure-menu-heading, header > .home-menu > ul, header > .home-menu > ul > li{
display: flex !important;
align-items: center;
justify-content: center;
line-height: normal !important;
}
header > .home-menu > a.pure-menu-heading{
color: white;
font-size: 1.5em;
}
header > .home-menu > ul > li > a{
color: #ced4d9;
}
header > .home-menu > ul > li > a:hover, header > .home-menu > ul > li > a:focus{
background: inherit !important;
}
header > .home-menu > ul > li > a:hover, header > .home-menu > ul > li.pure-menu-selected > a{
color: white;
}
main{
background-color: #ebf4fa;
position: relative;
}
footer{
text-align: center;
color: #b3b3b3;
text-decoration: none;
font-size: 0.8em;
padding: 15px;
line-height: 24px;
}
footer a{
color: #fff;
text-decoration: none;
}
footer iframe{
vertical-align: middle;
}
Loading…
Cancel
Save