├── .dockerignore
├── hsdexplorer
├── explorer
│ ├── __init__.py
│ ├── history
│ │ ├── __init__.py
│ │ └── write.py
│ ├── migrations
│ │ ├── __init__.py
│ │ └── 0001_initial.py
│ ├── templatetags
│ │ ├── __init__.py
│ │ └── hsd_math.py
│ ├── tests.py
│ ├── apps.py
│ ├── static
│ │ ├── img
│ │ │ ├── right_red_arrow.png
│ │ │ ├── right_black_arrow.png
│ │ │ └── right_green_arrow.png
│ │ ├── scss
│ │ │ ├── modules
│ │ │ │ └── _colors.scss
│ │ │ ├── main.scss
│ │ │ └── partials
│ │ │ │ ├── _card.scss
│ │ │ │ ├── _tables.scss
│ │ │ │ ├── _header.scss
│ │ │ │ ├── _layout.scss
│ │ │ │ └── _box.scss
│ │ └── js
│ │ │ └── popper.min.js
│ ├── admin.py
│ ├── templates
│ │ └── explorer
│ │ │ ├── _tx-input-list.html
│ │ │ ├── events.html
│ │ │ ├── blocks.html
│ │ │ ├── _block-table.html
│ │ │ ├── _pagination.html
│ │ │ ├── _events-table.html
│ │ │ ├── index.html
│ │ │ ├── about.html
│ │ │ ├── _events-single-table.html
│ │ │ ├── names.html
│ │ │ ├── _transaction.html
│ │ │ ├── _tx-output-list.html
│ │ │ ├── address.html
│ │ │ ├── name.html
│ │ │ ├── block.html
│ │ │ ├── transaction.html
│ │ │ └── base.html
│ ├── math.py
│ ├── urls.py
│ ├── utils.py
│ ├── models.py
│ ├── tasks.py
│ ├── views.py
│ └── hsd.py
├── .dockerignore
├── hsdexplorer
│ ├── middleware
│ │ ├── __init__.py
│ │ └── health.py
│ ├── __init__.py
│ ├── wsgi.py
│ ├── celery.py
│ ├── urls.py
│ └── settings.py
├── hsdbin
│ ├── decode.js
│ ├── package.json
│ ├── key.js
│ ├── package-lock.json
│ ├── compress.js
│ └── records.js
└── manage.py
├── .gitignore
├── docs
├── constants.md
└── transactions.md
├── skaffold.yaml
├── Pipfile
├── Dockerfile
├── kube
├── redis.yaml
├── handshake-node.yaml
├── postgres.yaml
└── handshake-explorer.yaml
├── README.md
├── .circleci
└── config.yml
├── Pipfile.lock
└── LICENSE
/.dockerignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.swp
3 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/hsdexplorer/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/history/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/templatetags/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/hsdexplorer/hsdexplorer/middleware/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class ExplorerConfig(AppConfig):
5 | name = 'explorer'
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.swp
3 | GeoIP.dat
4 | node_modules/
5 | celerybeat-schedule
6 | **/static/**/scss/**/*.css
7 | **/static/**/scss/**/*.css.map
8 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/static/img/right_red_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tdickman/handshake-explorer/HEAD/hsdexplorer/explorer/static/img/right_red_arrow.png
--------------------------------------------------------------------------------
/hsdexplorer/explorer/static/img/right_black_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tdickman/handshake-explorer/HEAD/hsdexplorer/explorer/static/img/right_black_arrow.png
--------------------------------------------------------------------------------
/hsdexplorer/explorer/static/img/right_green_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tdickman/handshake-explorer/HEAD/hsdexplorer/explorer/static/img/right_green_arrow.png
--------------------------------------------------------------------------------
/hsdexplorer/explorer/static/scss/modules/_colors.scss:
--------------------------------------------------------------------------------
1 | $background: #EBE9E9;
2 | $boxBackground: #FFF;
3 | $boxHeaderBackground: #F7F2F2;
4 | $lightGrey: grey;
5 | $black: #3E3F3A;
6 |
--------------------------------------------------------------------------------
/hsdexplorer/hsdbin/decode.js:
--------------------------------------------------------------------------------
1 | const Resource = require('./resource');
2 |
3 | data = process.argv[2];
4 | b = new Buffer.from(data, 'hex');
5 | console.log(JSON.stringify(Resource.decode(b)));
6 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/static/scss/main.scss:
--------------------------------------------------------------------------------
1 | @import 'vendor/bootstrap';
2 | @import 'partials/box';
3 | @import 'partials/card';
4 | @import 'partials/layout';
5 | @import 'partials/header';
6 | @import 'partials/tables';
7 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from . import models
3 |
4 | # Register your models here.
5 | admin.site.register(models.Name)
6 | admin.site.register(models.Block)
7 | admin.site.register(models.Event)
8 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/templatetags/hsd_math.py:
--------------------------------------------------------------------------------
1 | from django import template
2 |
3 | register = template.Library()
4 |
5 |
6 | @register.filter(name='to_hns')
7 | def to_hns(value):
8 | if value is None or value == '':
9 | return ''
10 | return value / 1000000
11 |
--------------------------------------------------------------------------------
/hsdexplorer/hsdexplorer/__init__.py:
--------------------------------------------------------------------------------
1 | from __future__ import absolute_import, unicode_literals
2 |
3 | # This will make sure the app is always imported when
4 | # Django starts so that shared_task will use this app.
5 | from .celery import app as celery_app
6 |
7 | __all__ = ('celery_app',)
8 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/static/scss/partials/_card.scss:
--------------------------------------------------------------------------------
1 | @import '../modules/colors';
2 |
3 | .border-secondary {
4 | border-color: #fff !important;
5 | }
6 |
7 | .card-header {
8 | background-color: $boxHeaderBackground;
9 | }
10 |
11 | .row .tx-card {
12 | margin-top: 1rem;
13 | }
14 |
15 | .tx-arrow {
16 | width: 16px;
17 | }
18 |
--------------------------------------------------------------------------------
/docs/constants.md:
--------------------------------------------------------------------------------
1 | # Network Constants
2 |
3 | Values for Testnet:
4 |
5 | * Open period - 72 blocks (~6 hours) == treeInterval
6 |
7 | Values:
8 |
9 | * Mainnet - https://github.com/handshake-org/hsd/blob/master/lib/protocol/networks.js#L230
10 | * Testnet - https://github.com/handshake-org/hsd/blob/master/lib/protocol/networks.js#L683
11 |
--------------------------------------------------------------------------------
/skaffold.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: skaffold/v1alpha5
2 | kind: Config
3 | build:
4 | artifacts:
5 | - image: gcr.io/hello-world-392/handshake-explorer
6 | context: .
7 | deploy:
8 | kubectl:
9 | manifests:
10 | - ./kube/*.yaml
11 | profiles:
12 | - name: gcb
13 | build:
14 | googleCloudBuild:
15 | projectId: hello-world-392
16 |
--------------------------------------------------------------------------------
/hsdexplorer/hsdbin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hsd",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "decode.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "bns": "^0.3.0",
13 | "bstring": "^0.2.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/static/scss/partials/_tables.scss:
--------------------------------------------------------------------------------
1 | @import '../modules/colors';
2 |
3 | .table {
4 | margin-bottom: 0;
5 | }
6 |
7 | .table th, .table td {
8 | border-top: 0;
9 | padding: 0.5rem;
10 | }
11 |
12 | .table thead th {
13 | border-bottom: 0;
14 | color: $lightGrey;
15 | font-weight: 200;
16 | }
17 |
18 | td.label {
19 | color: $lightGrey;
20 | }
21 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/static/scss/partials/_header.scss:
--------------------------------------------------------------------------------
1 | .bg-primary {
2 | background-color: #3581B8 !important;
3 | }
4 |
5 | .search-icon {
6 | margin-left: -33px;
7 | font-weight: 500;
8 | font-size: 18px;
9 | -webkit-transform: rotate(45deg);
10 | -moz-transform: rotate(45deg);
11 | -o-transform: rotate(45deg);
12 | transform: rotate(45deg);
13 | cursor: pointer;
14 | }
15 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/templates/explorer/_tx-input-list.html:
--------------------------------------------------------------------------------
1 | {% load hsd_math %}
2 |
11 |
--------------------------------------------------------------------------------
/hsdexplorer/hsdexplorer/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for hsdexplorer project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hsdexplorer.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/templates/explorer/events.html:
--------------------------------------------------------------------------------
1 | {% extends "explorer/base.html" %}
2 | {% block title %}Handshake Explorer: Events{% endblock %}
3 | {% block content %}
4 |
5 |
8 |
9 | {% include "explorer/_events-table.html" %}
10 | {% include "explorer/_pagination.html" with url_prefix="/events" %}
11 |
12 |
13 | {% endblock %}
14 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/math.py:
--------------------------------------------------------------------------------
1 | def total_received(txs, address):
2 | received = 0
3 | for tx in txs:
4 | for it in tx['outputs']:
5 | if it.get('address') == address:
6 | received += it.get('value', 0)
7 | return received
8 |
9 |
10 | def total_sent(txs, address):
11 | sent = 0
12 | for tx in txs:
13 | for ot in tx['inputs']:
14 | if ot.get('address') == address:
15 | sent += ot.get('value', 0)
16 | return sent
17 |
--------------------------------------------------------------------------------
/Pipfile:
--------------------------------------------------------------------------------
1 | [[source]]
2 | url = "https://pypi.org/simple"
3 | verify_ssl = true
4 | name = "pypi"
5 |
6 | [dev-packages]
7 |
8 | [packages]
9 | gunicorn = "*"
10 | django = ">=2.1.2"
11 | whitenoise = "*"
12 | requests = "*"
13 | "pysha3" = "*"
14 | django-tz-detect = "*"
15 | redis = "*"
16 | "psycopg2-binary" = "*"
17 | django-debug-toolbar = "*"
18 | libsass = "*"
19 | django-compressor = "*"
20 | django-sass-processor = "*"
21 | django-redis = "*"
22 | celery = "*"
23 | django-extensions = "*"
24 | django-memoize = "*"
25 |
26 | [requires]
27 | python_version = "3.6"
28 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/static/scss/partials/_layout.scss:
--------------------------------------------------------------------------------
1 | @import '../modules/colors';
2 |
3 | body {
4 | padding-top: 100px;
5 | }
6 |
7 | h1 {
8 | padding: 2rem 0;
9 | }
10 |
11 | h2 {
12 | padding: 2rem 0 1.3rem;
13 | }
14 |
15 | .right {
16 | float: right;
17 | text-align: right;
18 | }
19 |
20 | .full {
21 | width: 100%;
22 | }
23 |
24 | .row {
25 | margin-right: 0px;
26 | margin-left: 0px;
27 | }
28 |
29 | /* Layout */
30 | body {
31 | background-color: $background;
32 | }
33 |
34 | /* Links */
35 | a, a:hover {
36 | color: $black;
37 | }
38 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/templates/explorer/blocks.html:
--------------------------------------------------------------------------------
1 | {% extends "explorer/base.html" %}
2 | {% block title %}Handshake Explorer: Blocks{% endblock %}
3 | {% block content %}
4 |
15 | {% endblock %}
16 |
--------------------------------------------------------------------------------
/hsdexplorer/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == '__main__':
6 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hsdexplorer.settings')
7 | try:
8 | from django.core.management import execute_from_command_line
9 | except ImportError as exc:
10 | raise ImportError(
11 | "Couldn't import Django. Are you sure it's installed and "
12 | "available on your PYTHONPATH environment variable? Did you "
13 | "forget to activate a virtual environment?"
14 | ) from exc
15 | execute_from_command_line(sys.argv)
16 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/static/scss/partials/_box.scss:
--------------------------------------------------------------------------------
1 | @import '../modules/colors';
2 |
3 | .box {
4 | margin-bottom: 21px;
5 | width: 100%;
6 | background-color: $boxBackground;
7 | border-radius: 5px;
8 | box-shadow: 0 2px 2px rgba(0, 0, 0, 0.1);
9 | overflow: hidden;
10 | }
11 |
12 | .box-header {
13 | background-color: $boxHeaderBackground;
14 | line-height: 21px;
15 | padding: 10px 20px;
16 | }
17 |
18 | .box-header-right {
19 | float: right;
20 | }
21 |
22 | .box-header-title {
23 | color: $black;
24 | font-size: 16px;
25 | }
26 |
27 | .box-body {
28 | padding: 8px 15px 8px 15px;
29 | overflow-x: auto;
30 | }
31 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/templates/explorer/_block-table.html:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.6
2 |
3 | RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
4 | RUN apt update && apt install -y nodejs libunbound-dev && rm -rf /var/lib/apt/lists/*
5 |
6 | WORKDIR /app
7 | RUN pip install pipenv
8 | ADD Pipfile* /tmp/
9 | RUN cd /tmp && pipenv install --system --deploy
10 |
11 | ADD hsdexplorer/hsdbin/package.json /app/hsdbin/
12 | RUN cd hsdbin && npm install
13 |
14 | ADD ./hsdexplorer/ /app/
15 | RUN COLLECTSTATIC=1 echo 'yes' | python manage.py collectstatic; python manage.py compilescss; unset COLLECTSTATIC
16 |
17 | ENTRYPOINT ["gunicorn", "--bind", "0.0.0.0:8000", "--log-level", "debug", "hsdexplorer.wsgi"]
18 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/templates/explorer/_pagination.html:
--------------------------------------------------------------------------------
1 | {# Required variables: current_page, pages, max_page, url_prefix #}
2 |
19 |
--------------------------------------------------------------------------------
/kube/redis.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: redis
5 | spec:
6 | ports:
7 | - port: 6379
8 | name: redis
9 | clusterIP: None
10 | selector:
11 | app: redis
12 | ---
13 | apiVersion: apps/v1
14 | kind: StatefulSet
15 | metadata:
16 | name: redis
17 | spec:
18 | selector:
19 | matchLabels:
20 | app: redis # has to match .spec.template.metadata.labels
21 | serviceName: redis
22 | replicas: 1
23 | template:
24 | metadata:
25 | labels:
26 | app: redis # has to match .spec.selector.matchLabels
27 | spec:
28 | containers:
29 | - name: redis
30 | image: redis:3.2-alpine
31 | ports:
32 | - containerPort: 6379
33 | name: redis
34 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/templates/explorer/_events-table.html:
--------------------------------------------------------------------------------
1 | {# Required variables: events #}
2 | {% load hsd_math %}
3 |
4 |
5 |
6 | | Block |
7 | Action |
8 | Name |
9 | Value |
10 | TX |
11 |
12 |
13 |
14 | {% for event in events %}
15 |
16 | | {{ event.block_id }} |
17 | {{ event.action | lower }} |
18 | {{ event.name.name }} |
19 | {{ event.value | to_hns }}{% if event.value is not None %} HNS{% endif %} |
20 | TX |
21 |
22 | {% endfor %}
23 |
24 |
25 |
--------------------------------------------------------------------------------
/hsdexplorer/explorer/templates/explorer/index.html:
--------------------------------------------------------------------------------
1 | {% extends "explorer/base.html" %}
2 | {% block title %}Handshake Explorer: Home{% endblock %}
3 | {% block content %}
4 |