Initial commit

master
dsc 2 years ago
commit 10328c7470

4
.gitignore vendored

@ -0,0 +1,4 @@
__pycache__
.idea/
output/
venv/

3
.gitmodules vendored

@ -0,0 +1,3 @@
[submodule "plugins"]
path = plugins
url = https://github.com/getpelican/pelican-plugins.git

@ -0,0 +1,75 @@
PY?=python3
PELICAN?=pelican
PELICANOPTS=
BASEDIR=$(CURDIR)
INPUTDIR=$(BASEDIR)/content
OUTPUTDIR=$(BASEDIR)/output
CONFFILE=$(BASEDIR)/pelicanconf.py
PUBLISHCONF=$(BASEDIR)/publishconf.py
DEBUG ?= 0
ifeq ($(DEBUG), 1)
PELICANOPTS += -D
endif
RELATIVE ?= 0
ifeq ($(RELATIVE), 1)
PELICANOPTS += --relative-urls
endif
help:
@echo 'Makefile for a pelican Web site '
@echo ' '
@echo 'Usage: '
@echo ' make html (re)generate the web site '
@echo ' make clean remove the generated files '
@echo ' make regenerate regenerate files upon modification '
@echo ' make publish generate using production settings '
@echo ' make serve [PORT=8000] serve site at http://localhost:8000'
@echo ' make serve-global [SERVER=0.0.0.0] serve (as root) to $(SERVER):80 '
@echo ' make devserver [PORT=8000] serve and regenerate together '
@echo ' make ssh_upload upload the web site via SSH '
@echo ' make rsync_upload upload the web site via rsync+ssh '
@echo ' '
@echo 'Set the DEBUG variable to 1 to enable debugging, e.g. make DEBUG=1 html '
@echo 'Set the RELATIVE variable to 1 to enable relative urls '
@echo ' '
html:
$(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
clean:
[ ! -d $(OUTPUTDIR) ] || rm -rf $(OUTPUTDIR)
regenerate:
$(PELICAN) -r $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
serve:
ifdef PORT
$(PELICAN) -l $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) -p $(PORT)
else
$(PELICAN) -l $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
endif
serve-global:
ifdef SERVER
$(PELICAN) -l $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) -p $(PORT) -b $(SERVER)
else
$(PELICAN) -l $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) -p $(PORT) -b 0.0.0.0
endif
devserver:
ifdef PORT
$(PELICAN) -lr $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) -p $(PORT)
else
$(PELICAN) -lr $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
endif
publish:
$(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(PUBLISHCONF) $(PELICANOPTS)
.PHONY: html help clean regenerate serve serve-global devserver publish

@ -0,0 +1,157 @@
Title: Introduction
Date: 2020-06-27 10:20
Category: faq
### What is WOWlet?
The goal of WOWlet is to provide a simple/easy-to-use Wownero wallet for every day use. It is beginner friendly, but should also cater to the needs of experienced users.
- Free and open source
- The source code is available [here](http://git.wownero.com/wowlet/wowlet). WOWlet is licensed under BSD-3.
- Familiar
- The UI was heavily inspired by Electrum (the Bitcoin wallet).
- Easy to use
- You download and run it. No complicated setup required. It should work straight out of the box.
- Fast
- WOWlet is designed with lower-specced hardware in mind. No fancy graphics or animations.
- Feature-rich
- We support a number of features that are not available in other graphical wallets.
### What kind of software is WOWlet made with?
- C++
- Qt 5.15
- OpenSSL 1.1.1g, CMake, libqrencode.
- Wownero, as a library to hook into the `wallet2` interface.
- Tevador's 14 word seed library.
- Tor.
### Where does WOWlet store data?
Application-wide configuration is stored inside `~/.config/wowlet/settings.json` as a JSON blob. WOWlet does not have an uninstaller, manual removal is required.
- `~/.config/wowlet` - configuration/settings, tor
- `~/Wownero/wallets` - wallet directory
Note that paths are listed in WOWlet itself (`File->Settings->Paths`).
### What are Wownero wallet files?
When you create a wallet called `foo`, WOWlet writes 2 files to a user specified directory:
1. `foo.keys` - The wallet file. It is important. Do not remove it unless you have a backup and/or mnemonic seed. It contains your private key.
2. `foo` - The wallet cache. You can safely remove this, however, you will lose address
book contacts, and various other metadata/state.
3. `foo.address.txt` - (optionally) This file is only written in testnet/stagenet mode and contains your primary Wownero address.
### Does WOWlet run on my operating system?
WOWlet has releases for Linux, macOS, and Windows. WOWlet should also work fine on Tails and Whonix.
WOWlet runs on Qt 5.15 - some old(er) operating systems will be incompatible.
If WOWlet does not work on your OS or distro you may create an
issue [on our git](https://git.wownero.com/wowlet/wowlet/issues). Please beware WOWlet
has a small development team so the fastest way to fix problems is to fix them
yourself (and submitting a pull request in the process).
### Does WOWlet work without a Tor connection?
Yes, but you'll be missing some features.
### Why does WOWlet communicate with a websocket server?
The websocket server is used to fetch miscellaneous data:
- A list of community hosted remote nodes
- Price information (fiat/crypto)
- Reddit and forum feed
- Most recent blockheight (used as fallback)
- Latest WOWlet version
- More exiciting stuff™
WOWlet's intent was always to be a Wownero wallet "with extras" - such as realtime fiat/cryptocurrency market price updates and community forum updates within the wallet application itself.
Please note the websocket server can only be contacted through Tor, which WOWlet will do for us - we have no interests capturing IP addresses and/or other information.
### Does WOWlet support...
Reminder: WOWlet is made by a small team of developers.
#### My low-specced machine
Most likely.
#### 32-bit machines?
No, we see no reason to support legacy architectures.
#### Apple M1?
We unfortunately don't have the hardware available for testing and/or releasing those kind of executables.
#### Hardware wallets
We will **not** support Ledger or Trezor because:
- The feature takes too much time to develop and maintain.
- It is error-prone - users will flock to our support forum(s) for help and assistance, which sucks up valuable developer time.
Just keep your `.keys` safe, it is not hard :-)
#### language localization?
No, keeping the translation strings up-to-date is currently too time consuming.
### How does WOWlet automatically find remote nodes?
Known and working remote nodes are distributed via the websocket server. [Want yours included? Submit new nodes here](https://git.wownero.com/wowlet/wowlet-backend/src/branch/master/data/nodes.json).
### Why is the second word of the seed always the same?
In addition to the private spend key, the 14 word seed scheme also encodes the restore date, cryptocurrency type, and reserves a few bits for future use. The second word is static because the reserved bits remain the same for each seed generation.
### Why does WOWlet automatically connect to a remote node?
Speed and ease-of-use. WOWlet is tailored towards an audience that don't want to run their own node and don't mind
the benign privacy implications of automatically connecting to one. Funnily enough, this setup
is *still* more secure than using Bitcoin, as Wownero is
a private blockchain - regardless of how we interface with it.
### How can I connect to my (local) node?
In `File -> Settings -> Node` choose "From custom list" and add the IP address and port of your node. If your
node runs locally under default configuration, you can enter `127.0.0.1:18081`.
### How can I open a wallet straight from the commandline?
Use `--wallet-file` and `--password` to immediately open a wallet, skipping the startup wizard.
`./wowlet --wallet-file /home/user/Wownero/wallets/mywallet.keys --password "my_wallet_password"`
### How do I restore my wallet from seed?
You need a 14 word or 25 word mnemonic seed to restore a wallet. Without a mnemonic seed you have no way of restoring your wallet.
If you have a 14 word seed, the wallet can be restored without any further complications.
If you have a 25 word seed, specifying a "restore height" is necessary. This tells WOWlet at what point to start scanning the blockchain
from - in search of incoming and outgoing transactions associated with your wallet. If you fill in an invalid restore height,
you will not be able to detect any transactions you have done previously and consequently your balance might turn out
incorrect. When you don't know the restore height, simply leave it on `0`. Alternatively you can guess your wallet's
creation date. WOWlet will derive the restore height from it.
By default, WOWlet gives out 14 word mnemonic seeds because of the (perceived) complexities (for beginners) regarding
restore heights.
### How can I support the development of WOWlet?
By submitting pull requests!
### The application is very small on my high DPI 4K monitor
The Qt GUI framework should theoretically adept to on any type of monitor, but if for some reason it doesn't you can use an environment variable to scale the application manually:
`QT_SCALE_FACTOR=2 ./wowlet`
On Mac OS this hack *might* crash the application.

@ -0,0 +1,15 @@
Title: Future development
Date: 2022-03-02
Category: news
The WOWlet project has been running great the past 2 years and we have not had
anything catastrophic happen - a testament to the greatness of our
development community (lie). There are currently about 12k WOWlet users
running the latest version on all 3 major platforms (Windows/Linux/MacOS).
Which brings us to future developments. WOWlet is a place to
store Wownero funds in a decentralized and privacy respecting manner. We
are exploring options to add more service(s)/features to WOWlet itself. What those
service(s) should be - we don't know yet.
For now, we have a new website. You are looking at it. See you around!

@ -0,0 +1,7 @@
Title: Builds are now available.
Date: 2020-12-12
Category: news
The alpha was a great success. We would like to thank everyone who helped test the wallet during this phase.
As a result of your feedback we've ironed out many kinks and implemented new features.
The wallet can now be considered stable.

@ -0,0 +1,2 @@
Title: WOWlet Downloads
Slug: download

@ -0,0 +1,3 @@
Title: Feather Features
Slug: features

@ -0,0 +1,16 @@
Title: WOWlet Support
Slug: support
## General help
If you need help with WOWlet it is best to open a new thread [on the forums](https://forum.wownero.com).
Alternatively you could join IRC: `#wownero` on OFTC - you'll definitely find community members
that are willing to help.
## Bugs
Please report any bugs on our [issue tracker](https://git.wownero.com/wowlet/wowlet/issues).
Try to explain not only what the bug is, but how it occurs.
If you're able to open the wallet, please copy the output of the debug information dialog (`Help -> Show debug info`) to your clipboard and include it in your issue.

@ -0,0 +1,64 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals
import re
import os
from glob import glob
from pathlib import Path
import sys
sys.path.append('.')
AUTHOR = 'wowlet'
SITENAME = 'WOWlet'
SITEURL = 'http://localhost:8000/'
SHORT_SITENAME = "WOWlet"
LONG_SITENAME = "WOWlet: a free Wownero desktop wallet"
PATH = 'content'
TIMEZONE = 'Europe/Amsterdam'
STATIC_PATHS = ['downloads', 'images']
DEFAULT_LANG = 'en'
# Feed generation is usually not desired when developing
FEED_ALL_ATOM = None
CATEGORY_FEED_ATOM = None
TRANSLATION_FEED_ATOM = None
AUTHOR_FEED_ATOM = None
AUTHOR_FEED_RSS = None
DEFAULT_PAGINATION = False
THEME = 'themes/wowlet'
DISABLE_SEARCH = True
DISPLAY_PAGES_ON_MENU = False
USE_FOLDER_AS_CATEGORY = True
JINJA_ENVIRONMENT = {'trim_blocks': True, 'lstrip_blocks': True}
MARKDOWN = {
'extension_configs': {
'markdown.extensions.codehilite': {'css_class': 'highlight'},
'markdown.extensions.extra': {},
'markdown.extensions.meta': {},
'markdown.extensions.toc': {},
},
'output_format': 'html5',
}
ARTICLE_URL = 'posts/{date:%Y}/{date:%b}/{date:%d}/{slug}/'
ARTICLE_SAVE_AS = 'posts/{date:%Y}/{date:%b}/{date:%d}/{slug}/index.html'
PAGE_URL = '{slug}/'
PAGE_SAVE_AS = '{slug}/index.html'
CATEGORY_URL = '{slug}/'
CATEGORY_SAVE_AS = '{slug}/index.html'
def ARTICLE_FIND_ENDSWITH(articles, path):
for a in articles:
if a.source_path.endswith(path):
return a
# Uncomment following line if you want document-relative URLs when developing
# RELATIVE_URLS = True

@ -0,0 +1,25 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals
# This file is only used if you use `make publish` or
# explicitly specify it as your config file.
import os
import sys
sys.path.append(os.curdir)
from pelicanconf import *
# If your site is available via HTTPS, make sure SITEURL begins with https://
SITEURL = 'https://wowlet.app'
RELATIVE_URLS = False
FEED_ALL_ATOM = 'feeds/all.atom.xml'
CATEGORY_FEED_ATOM = 'feeds/{slug}.atom.xml'
DELETE_OUTPUT_DIRECTORY = True
# Following items are often useful when publishing
#DISQUS_SITENAME = ""
#GOOGLE_ANALYTICS = ""

@ -0,0 +1,5 @@
pelican[Markdown]
requests
requests[socks]
beautifulsoup4
python-dateutil

@ -0,0 +1,16 @@
#!/usr/bin/env bash
# Workaround for kicking off two subprocesses, allows you to quit both at once via Ctrl-C.
# See: https://spin.atomicobject.com/2017/08/24/start-stop-bash-background-process/
trap "kill 0" EXIT
# These need to be run separately to work around:
# https://github.com/getpelican/pelican/issues/2674
pelican --autoreload &
pelican --listen &
# Launch Firefox to load the page.
# open http://localhost:8000
# Wait for all background processes to finish.
wait

@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
import os
import shutil
import sys
import datetime
from invoke import task
from invoke.util import cd
from pelican.server import ComplexHTTPRequestHandler, RootedHTTPServer
from pelican.settings import DEFAULT_CONFIG, get_settings_from_file
SETTINGS_FILE_BASE = 'pelicanconf.py'
SETTINGS = {}
SETTINGS.update(DEFAULT_CONFIG)
LOCAL_SETTINGS = get_settings_from_file(SETTINGS_FILE_BASE)
SETTINGS.update(LOCAL_SETTINGS)
CONFIG = {
'settings_base': SETTINGS_FILE_BASE,
'settings_publish': 'publishconf.py',
# Output path. Can be absolute or relative to tasks.py. Default: 'output'
'deploy_path': SETTINGS['OUTPUT_PATH'],
# Port for `serve`
'port': 8000,
}
@task
def clean(c):
"""Remove generated files"""
if os.path.isdir(CONFIG['deploy_path']):
shutil.rmtree(CONFIG['deploy_path'])
os.makedirs(CONFIG['deploy_path'])
@task
def build(c):
"""Build local version of site"""
c.run('pelican -s {settings_base}'.format(**CONFIG))
@task
def rebuild(c):
"""`build` with the delete switch"""
c.run('pelican -d -s {settings_base}'.format(**CONFIG))
@task
def regenerate(c):
"""Automatically regenerate site upon file modification"""
c.run('pelican -r -s {settings_base}'.format(**CONFIG))
@task
def serve(c):
"""Serve site at http://localhost:$PORT/ (default port is 8000)"""
class AddressReuseTCPServer(RootedHTTPServer):
allow_reuse_address = True
server = AddressReuseTCPServer(
CONFIG['deploy_path'],
('', CONFIG['port']),
ComplexHTTPRequestHandler)
sys.stderr.write('Serving on port {port} ...\n'.format(**CONFIG))
server.serve_forever()
@task
def reserve(c):
"""`build`, then `serve`"""
build(c)
serve(c)
@task
def preview(c):
"""Build production version of site"""
c.run('pelican -s {settings_publish}'.format(**CONFIG))
@task
def livereload(c):
"""Automatically reload browser tab upon file modification."""
from livereload import Server
build(c)
server = Server()
# Watch the base settings file
server.watch(CONFIG['settings_base'], lambda: build(c))
# Watch content source files
content_file_extensions = ['.md', '.rst']
for extension in content_file_extensions:
content_blob = '{0}/**/*{1}'.format(SETTINGS['PATH'], extension)
server.watch(content_blob, lambda: build(c))
# Watch the theme's templates and static assets
theme_path = SETTINGS['THEME']
server.watch('{}/templates/*.html'.format(theme_path), lambda: build(c))
static_file_extensions = ['.css', '.js']
for extension in static_file_extensions:
static_file = '{0}/static/**/*{1}'.format(theme_path, extension)
server.watch(static_file, lambda: build(c))
# Serve output path on configured port
server.serve(port=CONFIG['port'], root=CONFIG['deploy_path'])
@task
def publish(c):
"""Publish to production via rsync"""
c.run('pelican -s {settings_publish}'.format(**CONFIG))
c.run(
'rsync --delete --exclude ".DS_Store" -pthrvz -c '
'-e "ssh -p {ssh_port}" '
'{} {ssh_user}@{ssh_host}:{ssh_path}'.format(
CONFIG['deploy_path'].rstrip('/') + '/',
**CONFIG))

@ -0,0 +1,64 @@
.highlight .hll { background-color: #49483e }
.highlight { background: #222222; color: #f8f8f2 }
.highlight .c { color: #75715e } /* Comment */
.highlight .err { color: #960050; background-color: #1e0010 } /* Error */
.highlight .k { color: #66d9ef } /* Keyword */
.highlight .l { color: #ae81ff } /* Literal */
.highlight .n { color: #f8f8f2 } /* Name */
.highlight .o { color: #f92672 } /* Operator */
.highlight .p { color: #f8f8f2 } /* Punctuation */
.highlight .cm { color: #75715e } /* Comment.Multiline */
.highlight .cp { color: #75715e } /* Comment.Preproc */
.highlight .c1 { color: #75715e } /* Comment.Single */
.highlight .cs { color: #75715e } /* Comment.Special */
.highlight .gd { color: #f92672 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gi { color: #a6e22e } /* Generic.Inserted */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #75715e } /* Generic.Subheading */
.highlight .kc { color: #66d9ef } /* Keyword.Constant */
.highlight .kd { color: #66d9ef } /* Keyword.Declaration */
.highlight .kn { color: #f92672 } /* Keyword.Namespace */
.highlight .kp { color: #66d9ef } /* Keyword.Pseudo */
.highlight .kr { color: #66d9ef } /* Keyword.Reserved */
.highlight .kt { color: #66d9ef } /* Keyword.Type */
.highlight .ld { color: #e6db74 } /* Literal.Date */
.highlight .m { color: #ae81ff } /* Literal.Number */
.highlight .s { color: #e6db74 } /* Literal.String */
.highlight .na { color: #a6e22e } /* Name.Attribute */
.highlight .nb { color: #f8f8f2 } /* Name.Builtin */
.highlight .nc { color: #a6e22e } /* Name.Class */
.highlight .no { color: #66d9ef } /* Name.Constant */
.highlight .nd { color: #a6e22e } /* Name.Decorator */
.highlight .ni { color: #f8f8f2 } /* Name.Entity */
.highlight .ne { color: #a6e22e } /* Name.Exception */
.highlight .nf { color: #a6e22e } /* Name.Function */
.highlight .nl { color: #f8f8f2 } /* Name.Label */
.highlight .nn { color: #f8f8f2 } /* Name.Namespace */
.highlight .nx { color: #a6e22e } /* Name.Other */
.highlight .py { color: #f8f8f2 } /* Name.Property */
.highlight .nt { color: #f92672 } /* Name.Tag */
.highlight .nv { color: #f8f8f2 } /* Name.Variable */
.highlight .ow { color: #f92672 } /* Operator.Word */
.highlight .w { color: #f8f8f2 } /* Text.Whitespace */
.highlight .mb { color: #ae81ff } /* Literal.Number.Bin */
.highlight .mf { color: #ae81ff } /* Literal.Number.Float */
.highlight .mh { color: #ae81ff } /* Literal.Number.Hex */
.highlight .mi { color: #ae81ff } /* Literal.Number.Integer */
.highlight .mo { color: #ae81ff } /* Literal.Number.Oct */
.highlight .sb { color: #e6db74 } /* Literal.String.Backtick */
.highlight .sc { color: #e6db74 } /* Literal.String.Char */
.highlight .sd { color: #e6db74 } /* Literal.String.Doc */
.highlight .s2 { color: #e6db74 } /* Literal.String.Double */
.highlight .se { color: #ae81ff } /* Literal.String.Escape */
.highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */
.highlight .si { color: #e6db74 } /* Literal.String.Interpol */
.highlight .sx { color: #e6db74 } /* Literal.String.Other */
.highlight .sr { color: #e6db74 } /* Literal.String.Regex */
.highlight .s1 { color: #e6db74 } /* Literal.String.Single */
.highlight .ss { color: #e6db74 } /* Literal.String.Symbol */
.highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */
.highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */
.highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */
.highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */

@ -0,0 +1,168 @@
html {
height: 100%;
}
body {
margin:0;
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;
background-repeat-y: no-repeat;
background: radial-gradient(ellipse at top left, rgba(255, 255, 255, 1) 40%, rgb(255, 224, 0) 200%) fixed;
background-image: url("../image/background.png");
}
.page {
max-width: 120ch;
margin: 1em auto;
margin-bottom: 300px;
}
.container {
margin-top:40px;
}
.grass {
background-image: url("../image/grass.png");
width: 100%;
height: 46px;
position: fixed;
bottom: 32px;
}
.dog {
background-image: url("../image/dog.gif");
background-repeat: no-repeat;
background-size: contain;
width: 150px;
height: 100px;
position: fixed;
bottom: 30px;
left: 30px;
}
.grass_extended {
background: #83cb53;
width: 100%;
height: 32px;
position: fixed;
bottom: 0;
}
.perl_forbidden {
background-image: url("../image/perl_forbidden.png");
width: 99px;
height: 127px;
position: fixed;
bottom: 20px;
right: 128px;
}
code {
border: 1px solid #d9d9d9;
background: #ededed;
padding-left: 4px;
padding-right: 4px;
}
table {
border-collapse: collapse;
border: 1px solid black;
background-color: #f0f0f0;
}
td {
padding-top: 0.3em;
padding-bottom: 0.4em;
padding-right: 2em;
padding-left:0.3em;
}
.buildtype { display: block; font-weight: bold; margin-top: 1em;}
.downloadheading { font-weight: bold; margin-top: 0.8em; }
.downloadrow { margin-top: 0.2em; margin-bottom: 0.2em; }
.downloadname { display: -moz-inline-box; display: inline-block;
max-width: 18vw; width: 8em; vertical-align: middle; }
.downloadfile { display: -moz-inline-box; display: inline-block;
max-width: 36vw; width: 16em; vertical-align: middle; }
.downloadftp { display: -moz-inline-box; display: inline-block;
max-width: 18vw; width: 8em; vertical-align: middle; }
.downloadsig { display: -moz-inline-box; display: inline-block;
max-width: 18vw; width: 8em; vertical-align: middle; }
.downloadgitlink { display: -moz-inline-box; display: inline-block;
vertical-align: middle; }
.downloadtop { margin: 24px; padding: 24px;
border: 2px solid black;
margin-bottom: 0;
-moz-border-radius-topleft: 1em;
-moz-border-radius-topright: 1em;
-webkit-border-top-left-radius: 1em;
-webkit-border-top-right-radius: 1em; }
.downloadbottom { margin: 24px; padding: 24px;
border: 2px solid black;
border-top: 0;
margin-top: 0;
-moz-border-radius-bottomleft: 1em;
-moz-border-radius-bottomright: 1em;
-webkit-border-bottom-left-radius: 1em;
-webkit-border-bottom-right-radius: 1em; }
.downloadbottom p:first-child { margin-top: 0; }
.downloadbottom h3:first-child { margin-top: 0; }
.downloadbottom div.downloadheading:first-child { margin-top: 0; }
.downloadinsecuretopcolour { background-color: rgba(200,40,0,0.1); }
.downloadinsecurebotcolour { background-color: rgba(200,40,0,0.04); }
.downloadoldertopcolour { background-color: rgba(200,200,0,0.1); }
.downloadolderbotcolour { background-color: rgba(200,200,0,0.04); }
.downloadlatesttopcolour { background-color: rgba(0,255,0,0.1); }
.downloadlatestbotcolour { background-color: rgba(0,255,0,0.04); }
.downloadprereltopcolour { background-color: rgba(0,192,255,0.1); }
.downloadprerelbotcolour { background-color: rgba(0,192,255,0.04); }
.downloadsnapshottopcolour { background-color: rgba(0,0,255,0.1); }
.downloadsnapshotbotcolour { background-color: rgba(0,0,255,0.04); }
.featureimg {
display: block;
margin-right: auto;
border: 1px solid black;
max-width: 50%;
box-shadow: 4px 4px 6px #00000020;
}
.icon {
width: 32px;
padding-right: 8px;
padding-left: 5px;
}
td {
vertical-align: sub;
}
pre.description {
font-size: 16px;
background: white;
}
a.title {
text-decoration: none;
color: black;
font-size:18px;
font-weight:bold;
}
@media only screen and (max-width: 1400px) {
img.wowlet {
width: 800px;
height: 420px;
}
}
@media only screen and (max-height: 900px) {
img.wowlet {
width: 800px;
height: 420px;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

@ -0,0 +1,49 @@
let gitea_api_wowlet = 'https://git.wownero.com/api/v1/repos/wowlet/wowlet/releases?draft=false&pre-release=false&limit=1';
let dog_running = false;
function bytesForHuman(bytes, decimals = 2) {
let units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
let i = 0
for (i; bytes > 1024; i++) {
bytes /= 1024;
}
return parseFloat(bytes.toFixed(decimals)) + ' ' + units[i]
}
function getVersion(cb) {
let _data = {
"linux": {},
"macos": {},
"windows": {}
}
$.get(gitea_api_wowlet, function(data) {
let item = data[0];
_data['name'] = item.tag_name;
_data['published_at'] = item.published_at.substring(0, item.published_at.indexOf('T'));
_data['gitea_api_wowlet'] = item.url;
_data['body'] = item.body;
item.assets.forEach(element => {
let _item = {
'name': element.name,
'download': element.browser_download_url,
'size': bytesForHuman(element.size)
}
if (_item.name.indexOf('linux') >= 0) {
_data['linux'] = _item
} else if (_item.name.indexOf('windows') >= 0) {
_data['windows'] = _item
} else {
_data['macos'] = _item;
}
});
cb(_data);
});
}

@ -0,0 +1,25 @@
{% macro render_menu(current_page) %}
{% set menu = ["home", "download", "faq", "support"] %}
<p align=center>
{% for m in menu %}
{% if current_page | lower == m %}
{% if m == "faq" %}
<b data-href="/faq">FAQ</b>
{% else %}
<b data-href="/{{ m }}">{{ m | capitalize }}</b>
{% endif %}
{% else %}
{% if m == "home" %}
<a href="/">Home</a>
{% elif m == "faq" %}
<a href="/faq">FAQ</a>
{% else %}
<a href="/{{ m }}">{{ m | capitalize }}</a>
{% endif %}
{% endif %}
{% if not loop.last %}
|
{% endif %}
{% endfor %}
{% endmacro %}

@ -0,0 +1,11 @@
{% extends "base.html" %}
{% block content %}
<header>{{ SHORT_SITENAME }} - Archives</header>
{% for article in dates %}
<article class="index">
include "article-header.html"
</article>
{% endfor %}
{% endblock %}

@ -0,0 +1,6 @@
<a href="{{ SITEURL }}/{{ article.url }}">
<p data-url="{{ SITEURL }}/{{ article.url }}">
<b>{{article.date.strftime("%Y-%m-%d")}} {{article.title}}</b>
</p>
</a>
{{article.content}}

@ -0,0 +1,18 @@
{% extends "base.html" %}
{% block menuheader %}
{% import "_macros/menu.html" as macros %}
{{ macros.render_menu(article.slug) }}
{% endblock menuheader %}
{% block title %}{{ SHORT_SITENAME }} - {{ article.title|striptags }}{% endblock %}
{% block head %}
{{ super() }}
{% endblock %}
{% block content %}
<h2 style="margin-bottom:4px;">{{ article.title }}</h2>
<b>2020-06-04</b>
<br>
{{ article.content }}
{% endblock %}

@ -0,0 +1,40 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
{% block head %}
<title>WOWlet: a free Wownero wallet</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="description" content="Feather Monero Wallet"/>
<meta name="twitter:site" content="@FeatherWallet" />
<link rel="icon" href="theme/image/favicon.ico" type="image/png" />
<link rel="canonical" href="https://wowlet.org">
<link rel="stylesheet" type="text/css" href="{{ SITEURL }}/theme/css/style.css" title="feather Home Page Style">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="theme/js/main.js"></script>
<link rel="shortcut icon" href="theme/image/favicon.ico">
{% endblock head %}
</head>
<body>
<div class="container">
<div class="page">
<h1 align="center">{% block header %}WOWlet: a free Wownero desktop wallet{% endblock %}</h1>
{% block menuheader %}
{% import "_macros/menu.html" as macros %}
{{ macros.render_menu("home") }}
{% endblock menuheader %}
<div class="content">
{% block content %}
{% endblock %}
</div>
</div>
</div>
<div class="grass"></div>
<div class="grass_extended"></div>
<div class="perl_forbidden"></div>
<div class="dog"></div>
</body>
</html>

@ -0,0 +1,10 @@
{% extends "base.html" %}
{% block title %}{{ SHORT_SITENAME }} - Categories{% endblock %}
{% block content %}
<header>Categories on {{ SITENAME }}</header>
<ul>
{% for cat, articles in categories|sort %}
<li><a href="{{ SITEURL }}/{{ cat.url }}">{{ cat }}</a> ({{ articles|count }})</li>
{% endfor %}
</ul>
{% endblock %}

@ -0,0 +1,35 @@
{% extends "base.html" %}
{% block title %}{{ SHORT_SITENAME }} - {{ category|striptags }}{% endblock %}
{% block header %}
{{ LONG_SITENAME }}
{%endblock%}
{% block menuheader %}
{% import "_macros/menu.html" as macros %}
{{ macros.render_menu(category.slug) }}
{% endblock menuheader %}
{% block content %}
{% if category == "faq" %}
{% for article in articles|sort(attribute='published_at')|reverse %}
{% if article.category == "faq" %}
<article>
{{ article.content }}
</article>
{% endif %}
{% endfor %}
<script>
$(document).ready(function(){
$('.content').find('h3').each(function() {
let item = $(this);
let uid = item.attr('id');
let title = item.html();
item.replaceWith(`<a class="title" id="${uid}" href="#${uid}">${title}</a>`);
});
});
</script>
{% endif %}
{% endblock %}

@ -0,0 +1,52 @@
{% extends "base.html" %}
{% block content %}
<p>
WOWlet is a free, open-source Wownero wallet for Linux, macOS, and Windows. Created by the same authors of <a target="_blank" href="https://featherwallet.org">Feather wallet</a>.
</p>
<a href="/features" title="View more screenshots">
<img class="front" src="/theme/image/wowlet2.png">
</a>
<p>
The latest version is <code class="latest_version"></code>.
<a href="download"><b>Download it here</b></a>.
</p>
<h2>Features</h2>
<ul>
<li><b>Safe</b> - Your private keys are encrypted and never leave your computer.</li>
<li><b>Private</b> - Tor is embedded and used to protect your IP.</li>
<li><b>Easy</b> - automatically uses community servers - no need to download the blockchain.</li>
<li><b>Fast</b> - written in C++ with performance and speed in mind.</li>
<li><b>No Lock-In</b> - You can export your private keys and use them in other client(s).</li>
<li><b>Cross-Platform</b> - Supports all 3 major operating systems.</li>
</ul>
<h2>Latest news</h2>
{% for article in articles_page.object_list %}
{% if article.category == "news" %}
<article class="index">
{% include "article-header.html" %}
</article>
{% endif %}
{% endfor %}
{% for article in articles_page.object_list %}
{% if article.category == "changelogs" %}
<article class="index">
{% include "changelog-header.html" %}
</article>
{% endif %}
{% endfor %}
<script>
getVersion((data) => {
$('code.latest_version').html(data['name']);
});
</script>
{% include 'pagination.html' %}
{% endblock content %}

@ -0,0 +1,93 @@
{% extends "base.html" %}
{% block title %}{{ SHORT_SITENAME }} - {{ page.title|striptags }}{%endblock%}
{% block header %}{{ LONG_SITENAME }}{%endblock%}
{% block menuheader %}
{% import "_macros/menu.html" as macros %}
{{ macros.render_menu(page.slug) }}
{% endblock menuheader %}
{% block content %}
{% if page.slug == "download" %}
<h1>Latest release: <code class="latest_version"></code>
<span style="font-size:16px;" class="latest_date"></span></h1>
<p>You may also grab the executable(s) straight from our <a href="https://git.wownero.com/wowlet/wowlet/releases">git releases page.</a></p>
<table>
<tbody>
<tr class="windows">
<td><img src="/theme/img/Windows-icon.png" class="icon">Windows <span style="font-size:80%">(8 and higher)</span></td>
<td><a class="download" href="#">Standalone executable</a></td>
<td class="size">-</td>
<td></td>
</tr>
<tr class="linux">
<td rowspan="2"><img src="/theme/img/Linux-icon.png" class="icon">Linux</td>
<td><a class="download" href="#">Standalone executable</a></td>
<td class="size">-</td>
<td></td>
</tr>
<tr></tr>
<tr class="macos">
<td><img src="/theme/img/macOS-icon.png" class="icon">macOS <span style="font-size:80%">(10.0 and higher)</span></td>
<td><a class="download" href="#">Executable</a></td>
<td class="size">-</td>
<td></td>
</tr>
<tr>
<td><img src="/theme/img/Feather-icon.png" class="icon">Source code</td>
<td><a href="https://git.wownero.com/wowlet/wowlet">Git repository</a></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<br>
<h3>Release note(s):</h3>
<pre class="description">-
</pre>
<h3>PGP verification How-To:</h3>
The release above is signed with a PGP key that can be found
<a href="https://git.wownero.com/wowlet/wowlet/src/branch/master/utils/pubkeys">inside the git repository</a>.
The signed message usually contains checksum(s) for the individual files.
So, in short:
<ol>
<li>Import the public key from the git repository</li>
<li>Verify that the above PGP signed message is signed with this key</li>
<li>Verify the checksum(s)</li>
</ol>
The steps above are not outlined in detail because they usually involve issuing different
terminal commands which depend on the operating system that you are currently using.
<script>
getVersion((data) => {
$('code.latest_version').html(data['name']);
$('.latest_date').html(`(${data['published_at']})`);
$('pre.description').html(data['body']);
let linux = $('tr.linux');
let windows = $('tr.windows');
let macos = $('tr.macos');
linux.find('a.download').attr('href', data['linux']['download']);
linux.find('td.size').html(data['linux']['size']);
windows.find('a.download').attr('href', data['windows']['download']);
windows.find('td.size').html(data['windows']['size']);
macos.find('a.download').attr('href', data['macos']['download']);
macos.find('td.size').html(data['macos']['size']);
});
</script>
{% else %}
{{ page.content }}
{% endif %}
{% endblock %}

@ -0,0 +1,11 @@
{% if DEFAULT_PAGINATION %}
<p class="paginator">
{% if articles_page.has_previous() %}
<a href="{{ SITEURL }}/{{ articles_previous_page.url }}">&laquo;</a>
{% endif %}
Page {{ articles_page.number }} / {{ articles_paginator.num_pages }}
{% if articles_page.has_next() %}
<a href="{{ SITEURL }}/{{ articles_next_page.url }}">&raquo;</a>
{% endif %}
</p>
{% endif %}

@ -0,0 +1,9 @@
{% macro translations_for(article) %}
{% if article.translations %}
Translations:
{% for translation in article.translations %}
<a href="{{ SITEURL }}/{{ translation.url }}">{{ translation.lang }}</a>
{% endfor %}
{% endif %}
{% endmacro %}
Loading…
Cancel
Save