Upgrade Electrum base to 3.3.8
36
contrib/build-osx/README.md
Normal file
|
@ -0,0 +1,36 @@
|
|||
Building Mac OS binaries
|
||||
========================
|
||||
|
||||
This guide explains how to build Electrum binaries for macOS systems.
|
||||
|
||||
The build process consists of two steps:
|
||||
|
||||
## 1. Building the binary
|
||||
|
||||
This needs to be done on a system running macOS or OS X. We use El Capitan (10.11.6) as building it on High Sierra
|
||||
makes the binaries incompatible with older versions.
|
||||
|
||||
Before starting, make sure that the Xcode command line tools are installed (e.g. you have `git`).
|
||||
|
||||
|
||||
cd electrum
|
||||
./contrib/build-osx/make_osx
|
||||
|
||||
This creates a folder named Electrum.app.
|
||||
|
||||
## 2. Building the image
|
||||
The usual way to distribute macOS applications is to use image files containing the
|
||||
application. Although these images can be created on a Mac with the built-in `hdiutil`,
|
||||
they are not deterministic.
|
||||
|
||||
Instead, we use the toolchain that Bitcoin uses: genisoimage and libdmg-hfsplus.
|
||||
These tools do not work on macOS, so you need a separate Linux machine (or VM).
|
||||
|
||||
Copy the Electrum.app directory over and install the dependencies, e.g.:
|
||||
|
||||
apt install libcap-dev cmake make gcc faketime
|
||||
|
||||
Then you can just invoke `package.sh` with the path to the app:
|
||||
|
||||
cd electrum
|
||||
./contrib/build-osx/package.sh ~/Electrum.app/
|
12
contrib/build-osx/base.sh
Normal file
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
RED='\033[0;31m'
|
||||
BLUE='\033[0,34m'
|
||||
NC='\033[0m' # No Color
|
||||
function info {
|
||||
printf "\r💬 ${BLUE}INFO:${NC} ${1}\n"
|
||||
}
|
||||
function fail {
|
||||
printf "\r🗯 ${RED}ERROR:${NC} ${1}\n"
|
||||
exit 1
|
||||
}
|
86
contrib/build-osx/cdrkit-deterministic.patch
Normal file
|
@ -0,0 +1,86 @@
|
|||
--- cdrkit-1.1.11.old/genisoimage/tree.c 2008-10-21 19:57:47.000000000 -0400
|
||||
+++ cdrkit-1.1.11/genisoimage/tree.c 2013-12-06 00:23:18.489622668 -0500
|
||||
@@ -1139,8 +1139,9 @@
|
||||
scan_directory_tree(struct directory *this_dir, char *path,
|
||||
struct directory_entry *de)
|
||||
{
|
||||
- DIR *current_dir;
|
||||
+ int current_file;
|
||||
char whole_path[PATH_MAX];
|
||||
+ struct dirent **d_list;
|
||||
struct dirent *d_entry;
|
||||
struct directory *parent;
|
||||
int dflag;
|
||||
@@ -1164,7 +1165,8 @@
|
||||
this_dir->dir_flags |= DIR_WAS_SCANNED;
|
||||
|
||||
errno = 0; /* Paranoia */
|
||||
- current_dir = opendir(path);
|
||||
+ //current_dir = opendir(path);
|
||||
+ current_file = scandir(path, &d_list, NULL, alphasort);
|
||||
d_entry = NULL;
|
||||
|
||||
/*
|
||||
@@ -1173,12 +1175,12 @@
|
||||
*/
|
||||
old_path = path;
|
||||
|
||||
- if (current_dir) {
|
||||
+ if (current_file >= 0) {
|
||||
errno = 0;
|
||||
- d_entry = readdir(current_dir);
|
||||
+ d_entry = d_list[0];
|
||||
}
|
||||
|
||||
- if (!current_dir || !d_entry) {
|
||||
+ if (current_file < 0 || !d_entry) {
|
||||
int ret = 1;
|
||||
|
||||
#ifdef USE_LIBSCHILY
|
||||
@@ -1191,8 +1193,8 @@
|
||||
de->isorec.flags[0] &= ~ISO_DIRECTORY;
|
||||
ret = 0;
|
||||
}
|
||||
- if (current_dir)
|
||||
- closedir(current_dir);
|
||||
+ if(d_list)
|
||||
+ free(d_list);
|
||||
return (ret);
|
||||
}
|
||||
#ifdef ABORT_DEEP_ISO_ONLY
|
||||
@@ -1208,7 +1210,7 @@
|
||||
errmsgno(EX_BAD, "use Rock Ridge extensions via -R or -r,\n");
|
||||
errmsgno(EX_BAD, "or allow deep ISO9660 directory nesting via -D.\n");
|
||||
}
|
||||
- closedir(current_dir);
|
||||
+ free(d_list);
|
||||
return (1);
|
||||
}
|
||||
#endif
|
||||
@@ -1250,13 +1252,13 @@
|
||||
* The first time through, skip this, since we already asked
|
||||
* for the first entry when we opened the directory.
|
||||
*/
|
||||
- if (dflag)
|
||||
- d_entry = readdir(current_dir);
|
||||
+ if (dflag && current_file >= 0)
|
||||
+ d_entry = d_list[current_file];
|
||||
dflag++;
|
||||
|
||||
- if (!d_entry)
|
||||
+ if (current_file < 0)
|
||||
break;
|
||||
-
|
||||
+ current_file--;
|
||||
/* OK, got a valid entry */
|
||||
|
||||
/* If we do not want all files, then pitch the backups. */
|
||||
@@ -1348,7 +1350,7 @@
|
||||
insert_file_entry(this_dir, whole_path, d_entry->d_name);
|
||||
#endif /* APPLE_HYB */
|
||||
}
|
||||
- closedir(current_dir);
|
||||
+ free(d_list);
|
||||
|
||||
#ifdef APPLE_HYB
|
||||
/*
|
100
contrib/build-osx/make_osx
Normal file
|
@ -0,0 +1,100 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Parameterize
|
||||
PYTHON_VERSION=3.6.4
|
||||
BUILDDIR=/tmp/electrum-build
|
||||
PACKAGE=Electrum
|
||||
GIT_REPO=https://github.com/spesmilo/electrum
|
||||
LIBSECP_VERSION=452d8e4d2a2f9f1b5be6b02e18f1ba102e5ca0b4
|
||||
|
||||
. $(dirname "$0")/base.sh
|
||||
|
||||
src_dir=$(dirname "$0")
|
||||
cd $src_dir/../..
|
||||
|
||||
export PYTHONHASHSEED=22
|
||||
VERSION=`git describe --tags --dirty --always`
|
||||
|
||||
which brew > /dev/null 2>&1 || fail "Please install brew from https://brew.sh/ to continue"
|
||||
|
||||
info "Installing Python $PYTHON_VERSION"
|
||||
export PATH="~/.pyenv/bin:~/.pyenv/shims:~/Library/Python/3.6/bin:$PATH"
|
||||
if [ -d "~/.pyenv" ]; then
|
||||
pyenv update
|
||||
else
|
||||
curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash > /dev/null 2>&1
|
||||
fi
|
||||
PYTHON_CONFIGURE_OPTS="--enable-framework" pyenv install -s $PYTHON_VERSION && \
|
||||
pyenv global $PYTHON_VERSION || \
|
||||
fail "Unable to use Python $PYTHON_VERSION"
|
||||
|
||||
|
||||
info "Installing pyinstaller"
|
||||
python3 -m pip install -I --user pyinstaller==3.4 || fail "Could not install pyinstaller"
|
||||
|
||||
info "Using these versions for building $PACKAGE:"
|
||||
sw_vers
|
||||
python3 --version
|
||||
echo -n "Pyinstaller "
|
||||
pyinstaller --version
|
||||
|
||||
rm -rf ./dist
|
||||
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
rm -rf $BUILDDIR > /dev/null 2>&1
|
||||
mkdir $BUILDDIR
|
||||
|
||||
cp -R ./contrib/deterministic-build/electrum-locale/locale/ ./electrum/locale/
|
||||
cp ./contrib/deterministic-build/electrum-icons/icons_rc.py ./electrum/gui/qt/
|
||||
|
||||
|
||||
info "Downloading libusb..."
|
||||
curl https://homebrew.bintray.com/bottles/libusb-1.0.22.el_capitan.bottle.tar.gz | \
|
||||
tar xz --directory $BUILDDIR
|
||||
cp $BUILDDIR/libusb/1.0.22/lib/libusb-1.0.dylib contrib/build-osx
|
||||
|
||||
info "Building libsecp256k1"
|
||||
brew install autoconf automake libtool
|
||||
git clone https://github.com/bitcoin-core/secp256k1 $BUILDDIR/secp256k1
|
||||
pushd $BUILDDIR/secp256k1
|
||||
git reset --hard $LIBSECP_VERSION
|
||||
git clean -f -x -q
|
||||
./autogen.sh
|
||||
./configure --enable-module-recovery --enable-experimental --enable-module-ecdh --disable-jni
|
||||
make
|
||||
popd
|
||||
cp $BUILDDIR/secp256k1/.libs/libsecp256k1.0.dylib contrib/build-osx
|
||||
|
||||
|
||||
info "Installing requirements..."
|
||||
python3 -m pip install -Ir ./contrib/deterministic-build/requirements.txt --user && \
|
||||
python3 -m pip install -Ir ./contrib/deterministic-build/requirements-binaries.txt --user || \
|
||||
fail "Could not install requirements"
|
||||
|
||||
info "Installing hardware wallet requirements..."
|
||||
python3 -m pip install -Ir ./contrib/deterministic-build/requirements-hw.txt --user || \
|
||||
fail "Could not install hardware wallet requirements"
|
||||
|
||||
info "Building $PACKAGE..."
|
||||
python3 setup.py install --user > /dev/null || fail "Could not build $PACKAGE"
|
||||
|
||||
info "Faking timestamps..."
|
||||
for d in ~/Library/Python/ ~/.pyenv .; do
|
||||
pushd $d
|
||||
find . -exec touch -t '200101220000' {} +
|
||||
popd
|
||||
done
|
||||
|
||||
info "Building binary"
|
||||
pyinstaller --noconfirm --ascii --clean --name $VERSION contrib/build-osx/osx.spec || fail "Could not build binary"
|
||||
|
||||
info "Adding bitcoin URI types to Info.plist"
|
||||
plutil -insert 'CFBundleURLTypes' \
|
||||
-xml '<array><dict> <key>CFBundleURLName</key> <string>bitcoin</string> <key>CFBundleURLSchemes</key> <array><string>bitcoin</string></array> </dict></array>' \
|
||||
-- dist/$PACKAGE.app/Contents/Info.plist \
|
||||
|| fail "Could not add keys to Info.plist. Make sure the program 'plutil' exists and is installed."
|
||||
|
||||
info "Creating .DMG"
|
||||
hdiutil create -fs HFS+ -volname $PACKAGE -srcfolder dist/$PACKAGE.app dist/electrum-$VERSION.dmg || fail "Could not create .DMG"
|
104
contrib/build-osx/osx.spec
Normal file
|
@ -0,0 +1,104 @@
|
|||
# -*- mode: python -*-
|
||||
|
||||
from PyInstaller.utils.hooks import collect_data_files, collect_submodules, collect_dynamic_libs
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
PACKAGE='Electrum'
|
||||
PYPKG='electrum'
|
||||
MAIN_SCRIPT='run_electrum'
|
||||
ICONS_FILE='electrum.icns'
|
||||
|
||||
for i, x in enumerate(sys.argv):
|
||||
if x == '--name':
|
||||
VERSION = sys.argv[i+1]
|
||||
break
|
||||
else:
|
||||
raise Exception('no version')
|
||||
|
||||
electrum = os.path.abspath(".") + "/"
|
||||
block_cipher = None
|
||||
|
||||
# see https://github.com/pyinstaller/pyinstaller/issues/2005
|
||||
hiddenimports = []
|
||||
hiddenimports += collect_submodules('trezorlib')
|
||||
hiddenimports += collect_submodules('safetlib')
|
||||
hiddenimports += collect_submodules('btchip')
|
||||
hiddenimports += collect_submodules('keepkeylib')
|
||||
hiddenimports += collect_submodules('websocket')
|
||||
hiddenimports += collect_submodules('ckcc')
|
||||
|
||||
datas = [
|
||||
(electrum + PYPKG + '/*.json', PYPKG),
|
||||
(electrum + PYPKG + '/wordlist/english.txt', PYPKG + '/wordlist'),
|
||||
(electrum + PYPKG + '/locale', PYPKG + '/locale'),
|
||||
(electrum + PYPKG + '/plugins', PYPKG + '/plugins'),
|
||||
]
|
||||
datas += collect_data_files('trezorlib')
|
||||
datas += collect_data_files('safetlib')
|
||||
datas += collect_data_files('btchip')
|
||||
datas += collect_data_files('keepkeylib')
|
||||
datas += collect_data_files('ckcc')
|
||||
|
||||
# Add libusb so Trezor and Safe-T mini will work
|
||||
binaries = [(electrum + "contrib/build-osx/libusb-1.0.dylib", ".")]
|
||||
binaries += [(electrum + "contrib/build-osx/libsecp256k1.0.dylib", ".")]
|
||||
|
||||
# Workaround for "Retro Look":
|
||||
binaries += [b for b in collect_dynamic_libs('PyQt5') if 'macstyle' in b[0]]
|
||||
|
||||
# We don't put these files in to actually include them in the script but to make the Analysis method scan them for imports
|
||||
a = Analysis([electrum+ MAIN_SCRIPT,
|
||||
electrum+'electrum/gui/qt/main_window.py',
|
||||
electrum+'electrum/gui/text.py',
|
||||
electrum+'electrum/util.py',
|
||||
electrum+'electrum/wallet.py',
|
||||
electrum+'electrum/simple_config.py',
|
||||
electrum+'electrum/bitcoin.py',
|
||||
electrum+'electrum/dnssec.py',
|
||||
electrum+'electrum/commands.py',
|
||||
electrum+'electrum/plugins/cosigner_pool/qt.py',
|
||||
electrum+'electrum/plugins/email_requests/qt.py',
|
||||
electrum+'electrum/plugins/trezor/client.py',
|
||||
electrum+'electrum/plugins/trezor/qt.py',
|
||||
electrum+'electrum/plugins/safe_t/client.py',
|
||||
electrum+'electrum/plugins/safe_t/qt.py',
|
||||
electrum+'electrum/plugins/keepkey/qt.py',
|
||||
electrum+'electrum/plugins/ledger/qt.py',
|
||||
electrum+'electrum/plugins/coldcard/qt.py',
|
||||
],
|
||||
binaries=binaries,
|
||||
datas=datas,
|
||||
hiddenimports=hiddenimports,
|
||||
hookspath=[])
|
||||
|
||||
# http://stackoverflow.com/questions/19055089/pyinstaller-onefile-warning-pyconfig-h-when-importing-scipy-or-scipy-signal
|
||||
for d in a.datas:
|
||||
if 'pyconfig' in d[0]:
|
||||
a.datas.remove(d)
|
||||
break
|
||||
|
||||
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
||||
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.datas,
|
||||
name=PACKAGE,
|
||||
debug=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
icon=electrum+ICONS_FILE,
|
||||
console=False)
|
||||
|
||||
app = BUNDLE(exe,
|
||||
version = VERSION,
|
||||
name=PACKAGE + '.app',
|
||||
icon=electrum+ICONS_FILE,
|
||||
bundle_identifier=None,
|
||||
info_plist={
|
||||
'NSHighResolutionCapable': 'True',
|
||||
'NSSupportsAutomaticGraphicsSwitching': 'True'
|
||||
}
|
||||
)
|
88
contrib/build-osx/package.sh
Normal file
|
@ -0,0 +1,88 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
cdrkit_version=1.1.11
|
||||
cdrkit_download_path=http://distro.ibiblio.org/fatdog/source/600/c
|
||||
cdrkit_file_name=cdrkit-${cdrkit_version}.tar.bz2
|
||||
cdrkit_sha256_hash=b50d64c214a65b1a79afe3a964c691931a4233e2ba605d793eb85d0ac3652564
|
||||
cdrkit_patches=cdrkit-deterministic.patch
|
||||
genisoimage=genisoimage-$cdrkit_version
|
||||
|
||||
libdmg_url=https://github.com/theuni/libdmg-hfsplus
|
||||
|
||||
|
||||
export LD_PRELOAD=$(locate libfaketime.so.1)
|
||||
export FAKETIME="2000-01-22 00:00:00"
|
||||
export PATH=$PATH:~/bin
|
||||
|
||||
. $(dirname "$0")/base.sh
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "Usage: $0 Electrum.app"
|
||||
exit -127
|
||||
fi
|
||||
|
||||
mkdir -p ~/bin
|
||||
|
||||
if ! which ${genisoimage} > /dev/null 2>&1; then
|
||||
mkdir -p /tmp/electrum-macos
|
||||
cd /tmp/electrum-macos
|
||||
info "Downloading cdrkit $cdrkit_version"
|
||||
wget -nc ${cdrkit_download_path}/${cdrkit_file_name}
|
||||
tar xvf ${cdrkit_file_name}
|
||||
|
||||
info "Patching genisoimage"
|
||||
cd cdrkit-${cdrkit_version}
|
||||
patch -p1 < ../cdrkit-deterministic.patch
|
||||
|
||||
info "Building genisoimage"
|
||||
cmake . -Wno-dev
|
||||
make genisoimage
|
||||
cp genisoimage/genisoimage ~/bin/${genisoimage}
|
||||
fi
|
||||
|
||||
if ! which dmg > /dev/null 2>&1; then
|
||||
mkdir -p /tmp/electrum-macos
|
||||
cd /tmp/electrum-macos
|
||||
info "Downloading libdmg"
|
||||
LD_PRELOAD= git clone ${libdmg_url}
|
||||
cd libdmg-hfsplus
|
||||
info "Building libdmg"
|
||||
cmake .
|
||||
make
|
||||
cp dmg/dmg ~/bin
|
||||
fi
|
||||
|
||||
${genisoimage} -version || fail "Unable to install genisoimage"
|
||||
dmg -|| fail "Unable to install libdmg"
|
||||
|
||||
plist=$1/Contents/Info.plist
|
||||
test -f "$plist" || fail "Info.plist not found"
|
||||
VERSION=$(grep -1 ShortVersionString $plist |tail -1|gawk 'match($0, /<string>(.*)<\/string>/, a) {print a[1]}')
|
||||
echo $VERSION
|
||||
|
||||
rm -rf /tmp/electrum-macos/image > /dev/null 2>&1
|
||||
mkdir /tmp/electrum-macos/image/
|
||||
cp -r $1 /tmp/electrum-macos/image/
|
||||
|
||||
build_dir=$(dirname "$1")
|
||||
test -n "$build_dir" -a -d "$build_dir" || exit
|
||||
cd $build_dir
|
||||
|
||||
${genisoimage} \
|
||||
-no-cache-inodes \
|
||||
-D \
|
||||
-l \
|
||||
-probe \
|
||||
-V "Electrum" \
|
||||
-no-pad \
|
||||
-r \
|
||||
-dir-mode 0755 \
|
||||
-apple \
|
||||
-o Electrum_uncompressed.dmg \
|
||||
/tmp/electrum-macos/image || fail "Unable to create uncompressed dmg"
|
||||
|
||||
dmg dmg Electrum_uncompressed.dmg electrum-$VERSION.dmg || fail "Unable to create compressed dmg"
|
||||
rm Electrum_uncompressed.dmg
|
||||
|
||||
echo "Done."
|
||||
md5sum electrum-$VERSION.dmg
|
40
contrib/build-wine/build-secp256k1.sh
Normal file
|
@ -0,0 +1,40 @@
|
|||
#!/bin/bash
|
||||
# heavily based on https://github.com/ofek/coincurve/blob/417e726f553460f88d7edfa5dc67bfda397c4e4a/.travis/build_windows_wheels.sh
|
||||
|
||||
set -e
|
||||
|
||||
build_dll() {
|
||||
#sudo apt-get install -y mingw-w64
|
||||
export SOURCE_DATE_EPOCH=1530212462
|
||||
./autogen.sh
|
||||
echo "LDFLAGS = -no-undefined" >> Makefile.am
|
||||
LDFLAGS="-Wl,--no-insert-timestamp" ./configure \
|
||||
--host=$1 \
|
||||
--enable-module-recovery \
|
||||
--enable-experimental \
|
||||
--enable-module-ecdh \
|
||||
--disable-jni
|
||||
make
|
||||
${1}-strip .libs/libsecp256k1-0.dll
|
||||
}
|
||||
|
||||
|
||||
cd /tmp/electrum-build
|
||||
|
||||
if [ ! -d secp256k1 ]; then
|
||||
git clone https://github.com/bitcoin-core/secp256k1.git
|
||||
cd secp256k1;
|
||||
else
|
||||
cd secp256k1
|
||||
git pull
|
||||
fi
|
||||
|
||||
git reset --hard 452d8e4d2a2f9f1b5be6b02e18f1ba102e5ca0b4
|
||||
git clean -f -x -q
|
||||
|
||||
build_dll i686-w64-mingw32 # 64-bit would be: x86_64-w64-mingw32
|
||||
mv .libs/libsecp256k1-0.dll libsecp256k1.dll
|
||||
|
||||
find -exec touch -d '2000-11-11T11:11:11+00:00' {} +
|
||||
|
||||
echo "building libsecp256k1 finished"
|
|
@ -118,7 +118,7 @@ exe_standalone = EXE(
|
|||
a.scripts,
|
||||
a.binaries,
|
||||
a.datas,
|
||||
name=os.path.join('build\\pyi.win32\\electrum', cmdline_name + ".exe"),
|
||||
name=os.path.join('build\\pyi.win32\\electrum-lbry', cmdline_name + ".exe"),
|
||||
debug=False,
|
||||
strip=None,
|
||||
upx=False,
|
||||
|
@ -131,7 +131,7 @@ exe_portable = EXE(
|
|||
a.scripts,
|
||||
a.binaries,
|
||||
a.datas + [ ('is_portable', 'README.md', 'DATA' ) ],
|
||||
name=os.path.join('build\\pyi.win32\\electrum', cmdline_name + "-portable.exe"),
|
||||
name=os.path.join('build\\pyi.win32\\electrum-lbry', cmdline_name + "-portable.exe"),
|
||||
debug=False,
|
||||
strip=None,
|
||||
upx=False,
|
||||
|
@ -145,7 +145,7 @@ exe_dependent = EXE(
|
|||
pyz,
|
||||
a.scripts,
|
||||
exclude_binaries=True,
|
||||
name=os.path.join('build\\pyi.win32\\electrum', cmdline_name),
|
||||
name=os.path.join('build\\pyi.win32\\electrum-lbry', cmdline_name),
|
||||
debug=False,
|
||||
strip=None,
|
||||
upx=False,
|
||||
|
|
34
contrib/build-wine/docker/Dockerfile
Normal file
|
@ -0,0 +1,34 @@
|
|||
FROM ubuntu:18.04@sha256:5f4bdc3467537cbbe563e80db2c3ec95d548a9145d64453b06939c4592d67b6d
|
||||
|
||||
ENV LC_ALL=C.UTF-8 LANG=C.UTF-8
|
||||
|
||||
RUN dpkg --add-architecture i386 && \
|
||||
apt-get update -q && \
|
||||
apt-get install -qy \
|
||||
wget=1.19.4-1ubuntu2.1 \
|
||||
gnupg2=2.2.4-1ubuntu1.1 \
|
||||
dirmngr=2.2.4-1ubuntu1.1 \
|
||||
python3-software-properties=0.96.24.32.1 \
|
||||
software-properties-common=0.96.24.32.1 \
|
||||
&& \
|
||||
wget -nc https://dl.winehq.org/wine-builds/Release.key && \
|
||||
apt-key add Release.key && \
|
||||
apt-add-repository https://dl.winehq.org/wine-builds/ubuntu/ && \
|
||||
apt-get update -q && \
|
||||
apt-get install -qy \
|
||||
wine-stable-amd64:amd64=3.0.1~bionic \
|
||||
wine-stable-i386:i386=3.0.1~bionic \
|
||||
wine-stable:amd64=3.0.1~bionic \
|
||||
winehq-stable:amd64=3.0.1~bionic \
|
||||
git \
|
||||
p7zip-full=16.02+dfsg-6 \
|
||||
make=4.1-9.1ubuntu1 \
|
||||
mingw-w64=5.0.3-1 \
|
||||
autotools-dev=20180224.1 \
|
||||
autoconf=2.69-11 \
|
||||
libtool=2.4.6-2 \
|
||||
gettext=0.19.8.1-6 \
|
||||
&& \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
apt-get autoremove -y && \
|
||||
apt-get clean
|
103
contrib/build-wine/docker/README.md
Normal file
|
@ -0,0 +1,103 @@
|
|||
Deterministic Windows binaries with Docker
|
||||
==========================================
|
||||
|
||||
Produced binaries are deterministic, so you should be able to generate
|
||||
binaries that match the official releases.
|
||||
|
||||
This assumes an Ubuntu host, but it should not be too hard to adapt to another
|
||||
similar system. The docker commands should be executed in the project's root
|
||||
folder.
|
||||
|
||||
1. Install Docker
|
||||
|
||||
```
|
||||
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
|
||||
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get install -y docker-ce
|
||||
```
|
||||
|
||||
2. Build image
|
||||
|
||||
```
|
||||
$ sudo docker build --no-cache -t electrum-wine-builder-img contrib/build-wine/docker
|
||||
```
|
||||
|
||||
Note: see [this](https://stackoverflow.com/a/40516974/7499128) if having dns problems
|
||||
|
||||
3. Build Windows binaries
|
||||
|
||||
It's recommended to build from a fresh clone
|
||||
(but you can skip this if reproducibility is not necessary).
|
||||
|
||||
```
|
||||
$ FRESH_CLONE=contrib/build-wine/fresh_clone && \
|
||||
rm -rf $FRESH_CLONE && \
|
||||
mkdir -p $FRESH_CLONE && \
|
||||
cd $FRESH_CLONE && \
|
||||
git clone https://github.com/spesmilo/electrum.git && \
|
||||
cd electrum
|
||||
```
|
||||
|
||||
And then build from this directory:
|
||||
```
|
||||
$ git checkout $REV
|
||||
$ sudo docker run \
|
||||
--name electrum-wine-builder-cont \
|
||||
-v $PWD:/opt/wine64/drive_c/electrum \
|
||||
--rm \
|
||||
--workdir /opt/wine64/drive_c/electrum/contrib/build-wine \
|
||||
electrum-wine-builder-img \
|
||||
./build.sh
|
||||
```
|
||||
4. The generated binaries are in `./contrib/build-wine/dist`.
|
||||
|
||||
|
||||
|
||||
Note: the `setup` binary (NSIS installer) is not deterministic yet.
|
||||
|
||||
|
||||
Code Signing
|
||||
============
|
||||
|
||||
Electrum Windows builds are signed with a Microsoft Authenticode™ code signing
|
||||
certificate in addition to the GPG-based signatures.
|
||||
|
||||
The advantage of using Authenticode is that Electrum users won't receive a
|
||||
Windows SmartScreen warning when starting it.
|
||||
|
||||
The release signing procedure involves a signer (the holder of the
|
||||
certificate/key) and one or multiple trusted verifiers:
|
||||
|
||||
|
||||
| Signer | Verifier |
|
||||
|-----------------------------------------------------------|-----------------------------------|
|
||||
| Build .exe files using `build.sh` | |
|
||||
| Sign .exe with `./sign.sh` | |
|
||||
| Upload signed files to download server | |
|
||||
| | Build .exe files using `build.sh` |
|
||||
| | Compare files using `unsign.sh` |
|
||||
| | Sign .exe file using `gpg -b` |
|
||||
|
||||
| Signer and verifiers: |
|
||||
|-----------------------------------------------------------------------------------------------|
|
||||
| Upload signatures to 'electrum-signatures' repo, as `$version/$filename.$builder.asc` |
|
||||
|
||||
|
||||
|
||||
Verify Integrity of signed binary
|
||||
=================================
|
||||
|
||||
Every user can verify that the official binary was created from the source code in this
|
||||
repository. To do so, the Authenticode signature needs to be stripped since the signature
|
||||
is not reproducible.
|
||||
|
||||
This procedure removes the differences between the signed and unsigned binary:
|
||||
|
||||
1. Remove the signature from the signed binary using osslsigncode or signtool.
|
||||
2. Set the COFF image checksum for the signed binary to 0x0. This is necessary
|
||||
because pyinstaller doesn't generate a checksum.
|
||||
3. Append null bytes to the _unsigned_ binary until the byte count is a multiple
|
||||
of 8.
|
||||
|
||||
The script `unsign.sh` performs these steps.
|
|
@ -6,7 +6,7 @@
|
|||
;--------------------------------
|
||||
;Variables
|
||||
|
||||
!define PRODUCT_NAME "Electrum"
|
||||
!define PRODUCT_NAME "LBRY_Wallet"
|
||||
!define PRODUCT_WEB_SITE "https://github.com/spesmilo/electrum"
|
||||
!define PRODUCT_PUBLISHER "Electrum Technologies GmbH"
|
||||
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
|
||||
|
@ -16,7 +16,7 @@
|
|||
|
||||
;Name and file
|
||||
Name "${PRODUCT_NAME}"
|
||||
OutFile "dist/electrum-setup.exe"
|
||||
OutFile "dist/electrum-lbry-setup.exe"
|
||||
|
||||
;Default installation folder
|
||||
InstallDir "$PROGRAMFILES\${PRODUCT_NAME}"
|
||||
|
@ -122,21 +122,23 @@ Section
|
|||
|
||||
;Create desktop shortcut
|
||||
DetailPrint "Creating desktop shortcut..."
|
||||
CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\electrum-${PRODUCT_VERSION}.exe" ""
|
||||
CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\electrum-lbry-${PRODUCT_VERSION}.exe" ""
|
||||
|
||||
;Create start-menu items
|
||||
DetailPrint "Creating start-menu items..."
|
||||
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
|
||||
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe" "" "$INSTDIR\Uninstall.exe" 0
|
||||
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\electrum-${PRODUCT_VERSION}.exe" "" "$INSTDIR\electrum-${PRODUCT_VERSION}.exe" 0
|
||||
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME} Testnet.lnk" "$INSTDIR\electrum-${PRODUCT_VERSION}.exe" "--testnet" "$INSTDIR\electrum-${PRODUCT_VERSION}.exe" 0
|
||||
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\electrum-${PRODUCT_VERSION}.exe" "" "$INSTDIR\electrum-lbry-${PRODUCT_VERSION}.exe" 0
|
||||
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME} Testnet.lnk" "$INSTDIR\electrum-${PRODUCT_VERSION}.exe" "--testnet" "$INSTDIR\electrum-lbry-${PRODUCT_VERSION}.exe" 0
|
||||
|
||||
|
||||
|
||||
|
||||
;Links bitcoin: URI's to Electrum
|
||||
WriteRegStr HKCU "Software\Classes\bitcoin" "" "URL:bitcoin Protocol"
|
||||
WriteRegStr HKCU "Software\Classes\bitcoin" "URL Protocol" ""
|
||||
WriteRegStr HKCU "Software\Classes\bitcoin" "DefaultIcon" "$\"$INSTDIR\electrum.ico, 0$\""
|
||||
WriteRegStr HKCU "Software\Classes\bitcoin\shell\open\command" "" "$\"$INSTDIR\electrum-${PRODUCT_VERSION}.exe$\" $\"%1$\""
|
||||
WriteRegStr HKCU "Software\Classes\bitcoin\shell\open\command" "" "$\"$INSTDIR\electrum-lbry-${PRODUCT_VERSION}.exe$\" $\"%1$\""
|
||||
|
||||
;Adds an uninstaller possibility to Windows Uninstall or change a program section
|
||||
WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
|
||||
|
@ -167,7 +169,7 @@ Section "Uninstall"
|
|||
Delete "$SMPROGRAMS\${PRODUCT_NAME}\*.*"
|
||||
RMDir "$SMPROGRAMS\${PRODUCT_NAME}"
|
||||
|
||||
DeleteRegKey HKCU "Software\Classes\bitcoin"
|
||||
DeleteRegKey HKCU "Software\Classes\lbc"
|
||||
DeleteRegKey HKCU "Software\${PRODUCT_NAME}"
|
||||
DeleteRegKey HKCU "${PRODUCT_UNINST_KEY}"
|
||||
SectionEnd
|
||||
|
|
82
contrib/make_locale
Normal file
|
@ -0,0 +1,82 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
import subprocess
|
||||
import io
|
||||
import zipfile
|
||||
import requests
|
||||
|
||||
os.chdir(os.path.dirname(os.path.realpath(__file__)))
|
||||
os.chdir('..')
|
||||
|
||||
cmd = "find electrum -type f -name '*.py' -o -name '*.kv'"
|
||||
|
||||
files = subprocess.check_output(cmd, shell=True)
|
||||
|
||||
with open("app.fil", "wb") as f:
|
||||
f.write(files)
|
||||
|
||||
print("Found {} files to translate".format(len(files.splitlines())))
|
||||
|
||||
# Generate fresh translation template
|
||||
if not os.path.exists('electrum/locale'):
|
||||
os.mkdir('electrum/locale')
|
||||
cmd = 'xgettext -s --from-code UTF-8 --language Python --no-wrap -f app.fil --output=electrum/locale/messages.pot'
|
||||
print('Generate template')
|
||||
os.system(cmd)
|
||||
|
||||
os.chdir('electrum')
|
||||
|
||||
crowdin_identifier = 'electrum'
|
||||
crowdin_file_name = 'files[electrum-client/messages.pot]'
|
||||
locale_file_name = 'locale/messages.pot'
|
||||
crowdin_api_key = None
|
||||
|
||||
filename = os.path.expanduser('~/.crowdin_api_key')
|
||||
if os.path.exists(filename):
|
||||
with open(filename) as f:
|
||||
crowdin_api_key = f.read().strip()
|
||||
|
||||
if "crowdin_api_key" in os.environ:
|
||||
crowdin_api_key = os.environ["crowdin_api_key"]
|
||||
|
||||
if crowdin_api_key:
|
||||
# Push to Crowdin
|
||||
print('Push to Crowdin')
|
||||
url = ('https://api.crowdin.com/api/project/' + crowdin_identifier + '/update-file?key=' + crowdin_api_key)
|
||||
with open(locale_file_name, 'rb') as f:
|
||||
files = {crowdin_file_name: f}
|
||||
response = requests.request('POST', url, files=files)
|
||||
print("", "update-file:", "-"*20, response.text, "-"*20, sep="\n")
|
||||
# Build translations
|
||||
print('Build translations')
|
||||
response = requests.request('GET', 'https://api.crowdin.com/api/project/' + crowdin_identifier + '/export?key=' + crowdin_api_key)
|
||||
print("", "export:", "-" * 20, response.text, "-" * 20, sep="\n")
|
||||
|
||||
# Download & unzip
|
||||
print('Download translations')
|
||||
s = requests.request('GET', 'https://crowdin.com/backend/download/project/' + crowdin_identifier + '.zip').content
|
||||
zfobj = zipfile.ZipFile(io.BytesIO(s))
|
||||
|
||||
print('Unzip translations')
|
||||
for name in zfobj.namelist():
|
||||
if not name.startswith('electrum-client/locale'):
|
||||
continue
|
||||
if name.endswith('/'):
|
||||
if not os.path.exists(name[16:]):
|
||||
os.mkdir(name[16:])
|
||||
else:
|
||||
with open(name[16:], 'wb') as output:
|
||||
output.write(zfobj.read(name))
|
||||
|
||||
# Convert .po to .mo
|
||||
print('Installing')
|
||||
for lang in os.listdir('locale'):
|
||||
if lang.startswith('messages'):
|
||||
continue
|
||||
# Check LC_MESSAGES folder
|
||||
mo_dir = 'locale/%s/LC_MESSAGES' % lang
|
||||
if not os.path.exists(mo_dir):
|
||||
os.mkdir(mo_dir)
|
||||
cmd = 'msgfmt --output-file="%s/electrum.mo" "locale/%s/electrum.po"' % (mo_dir,lang)
|
||||
print('Installing', lang)
|
||||
os.system(cmd)
|
BIN
electrum.icns
Normal file
|
@ -139,7 +139,7 @@ class BaseWizard(Logger):
|
|||
('standard', _("Standard wallet")),
|
||||
('2fa', _("Wallet with two-factor authentication")),
|
||||
('multisig', _("Multi-signature wallet")),
|
||||
('imported', _("Import Bitcoin addresses or private keys")),
|
||||
('imported', _("Import LBRY Credits addresses or private keys")),
|
||||
]
|
||||
choices = [pair for pair in wallet_kinds if pair[0] in wallet_types]
|
||||
self.choice_dialog(title=title, message=message, choices=choices, run_next=self.on_wallet_type)
|
||||
|
@ -211,8 +211,8 @@ class BaseWizard(Logger):
|
|||
|
||||
def import_addresses_or_keys(self):
|
||||
v = lambda x: keystore.is_address_list(x) or keystore.is_private_key_list(x, raise_on_error=True)
|
||||
title = _("Import Bitcoin Addresses")
|
||||
message = _("Enter a list of Bitcoin addresses (this will create a watching-only wallet), or a list of private keys.")
|
||||
title = _("Import LBRY Credits Addresses")
|
||||
message = _("Enter a list of LBRY Credits addresses (this will create a watching-only wallet), or a list of private keys.")
|
||||
self.add_xpub_dialog(title=title, message=message, run_next=self.on_import,
|
||||
is_valid=v, allow_multi=True, show_wif_help=True)
|
||||
|
||||
|
@ -393,14 +393,13 @@ class BaseWizard(Logger):
|
|||
# There is no general standard for HD multisig.
|
||||
# For legacy, this is partially compatible with BIP45; assumes index=0
|
||||
# For segwit, a custom path is used, as there is no standard at all.
|
||||
default_choice_idx = 2
|
||||
default_choice_idx = 0
|
||||
choices = [
|
||||
('standard', 'legacy multisig (p2sh)', normalize_bip32_derivation("m/45'/0")),
|
||||
('p2wsh-p2sh', 'p2sh-segwit multisig (p2wsh-p2sh)', purpose48_derivation(0, xtype='p2wsh-p2sh')),
|
||||
('p2wsh', 'native segwit multisig (p2wsh)', purpose48_derivation(0, xtype='p2wsh')),
|
||||
|
||||
]
|
||||
else:
|
||||
default_choice_idx = 2
|
||||
default_choice_idx = 0
|
||||
choices = [
|
||||
('standard', 'legacy (p2pkh)', bip44_derivation(0, bip43_purpose=44)),
|
||||
('p2wpkh-p2sh', 'p2sh-segwit (p2wpkh-p2sh)', bip44_derivation(0, bip43_purpose=49)),
|
||||
|
@ -625,11 +624,11 @@ class BaseWizard(Logger):
|
|||
_("The type of addresses used by your wallet will depend on your seed."),
|
||||
_("Segwit wallets use bech32 addresses, defined in BIP173."),
|
||||
_("Please note that websites and other wallets may not support these addresses yet."),
|
||||
_("Thus, you might want to keep using a non-segwit wallet in order to be able to receive bitcoins during the transition period.")
|
||||
_("Thus, you might want to keep using a non-segwit wallet in order to be able to receive LBRY Credits during the transition period.")
|
||||
])
|
||||
if choices is None:
|
||||
choices = [
|
||||
('create_segwit_seed', _('Segwit')),
|
||||
|
||||
('create_standard_seed', _('Legacy')),
|
||||
]
|
||||
self.choice_dialog(title=title, message=message, choices=choices, run_next=self.run)
|
||||
|
|
|
@ -24,6 +24,9 @@ import os
|
|||
import threading
|
||||
from typing import Optional, Dict, Mapping, Sequence
|
||||
|
||||
import hashlib
|
||||
import hmac
|
||||
|
||||
from . import util
|
||||
from .bitcoin import hash_encode, int_to_hex, rev_hex
|
||||
from .crypto import sha256d
|
||||
|
@ -35,9 +38,10 @@ from .logging import get_logger, Logger
|
|||
|
||||
_logger = get_logger(__name__)
|
||||
|
||||
HEADER_SIZE = 80 # bytes
|
||||
MAX_TARGET = 0x00000000FFFF0000000000000000000000000000000000000000000000000000
|
||||
|
||||
HEADER_SIZE = 112 # bytes
|
||||
MAX_TARGET = 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
||||
GENESIS_BITS = 0x1f00ffff
|
||||
N_TARGET_TIMESPAN = 150
|
||||
|
||||
class MissingHeader(Exception):
|
||||
pass
|
||||
|
@ -49,6 +53,7 @@ def serialize_header(header_dict: dict) -> str:
|
|||
s = int_to_hex(header_dict['version'], 4) \
|
||||
+ rev_hex(header_dict['prev_block_hash']) \
|
||||
+ rev_hex(header_dict['merkle_root']) \
|
||||
+ rev_hex(header_dict['claim_trie_root']) \
|
||||
+ int_to_hex(int(header_dict['timestamp']), 4) \
|
||||
+ int_to_hex(int(header_dict['bits']), 4) \
|
||||
+ int_to_hex(int(header_dict['nonce']), 4)
|
||||
|
@ -64,9 +69,10 @@ def deserialize_header(s: bytes, height: int) -> dict:
|
|||
h['version'] = hex_to_int(s[0:4])
|
||||
h['prev_block_hash'] = hash_encode(s[4:36])
|
||||
h['merkle_root'] = hash_encode(s[36:68])
|
||||
h['timestamp'] = hex_to_int(s[68:72])
|
||||
h['bits'] = hex_to_int(s[72:76])
|
||||
h['nonce'] = hex_to_int(s[76:80])
|
||||
h['claim_trie_root'] = hash_encode(s[68:100])
|
||||
h['timestamp'] = hex_to_int(s[100:104])
|
||||
h['bits'] = hex_to_int(s[104:108])
|
||||
h['nonce'] = hex_to_int(s[108:112])
|
||||
h['block_height'] = height
|
||||
return h
|
||||
|
||||
|
@ -77,10 +83,35 @@ def hash_header(header: dict) -> str:
|
|||
header['prev_block_hash'] = '00'*32
|
||||
return hash_raw_header(serialize_header(header))
|
||||
|
||||
def pow_hash_header(header: dict) -> str:
|
||||
if header is None:
|
||||
return '0' * 64
|
||||
return hash_encode(PoWHash(bfh(serialize_header(header))))
|
||||
|
||||
def sha256(x):
|
||||
return hashlib.sha256(x).digest()
|
||||
|
||||
def sha512(x):
|
||||
return hashlib.sha512(x).digest()
|
||||
|
||||
def ripemd160(x):
|
||||
h = hashlib.new('ripemd160')
|
||||
h.update(x)
|
||||
return h.digest()
|
||||
|
||||
def Hash(x):
|
||||
return sha256(sha256(x))
|
||||
|
||||
def hash_raw_header(header: str) -> str:
|
||||
return hash_encode(sha256d(bfh(header)))
|
||||
|
||||
def PoWHash(x):
|
||||
|
||||
r = sha512(Hash(x))
|
||||
r1 = ripemd160(r[:len(r) // 2])
|
||||
r2 = ripemd160(r[len(r) // 2:])
|
||||
r3 = Hash(r1 + r2)
|
||||
return r3
|
||||
|
||||
# key: blockhash hex at forkpoint
|
||||
# the chain at some key is the best chain that includes the given hash
|
||||
|
@ -282,35 +313,37 @@ class Blockchain(Logger):
|
|||
self._size = os.path.getsize(p)//HEADER_SIZE if os.path.exists(p) else 0
|
||||
|
||||
@classmethod
|
||||
def verify_header(cls, header: dict, prev_hash: str, target: int, expected_header_hash: str=None) -> None:
|
||||
_hash = hash_header(header)
|
||||
if expected_header_hash and expected_header_hash != _hash:
|
||||
raise Exception("hash mismatches with expected: {} vs {}".format(expected_header_hash, _hash))
|
||||
def verify_header(self, header: dict, prev_hash: str, target: int, bits: int, expected_header_hash: str=None) -> None:
|
||||
_hash = pow_hash_header(header)
|
||||
if expected_header_hash:
|
||||
_hash2 = hash_header(header)
|
||||
if expected_header_hash != _hash2:
|
||||
raise Exception("hash mismatches with expected: {} vs {}".format(expected_header_hash, _hash2))
|
||||
if prev_hash != header.get('prev_block_hash'):
|
||||
raise Exception("prev hash mismatch: %s vs %s" % (prev_hash, header.get('prev_block_hash')))
|
||||
if constants.net.TESTNET:
|
||||
return
|
||||
bits = cls.target_to_bits(target)
|
||||
if bits != header.get('bits'):
|
||||
raise Exception("bits mismatch: %s vs %s" % (bits, header.get('bits')))
|
||||
block_hash_as_num = int.from_bytes(bfh(_hash), byteorder='big')
|
||||
if block_hash_as_num > target:
|
||||
raise Exception(f"insufficient proof of work: {block_hash_as_num} vs target {target}")
|
||||
|
||||
#if bits != header.get('bits'):
|
||||
# raise Exception("bits mismatch: %s vs %s" % (bits, header.get('bits')))
|
||||
#if int('0x' + _hash, 16) > target:
|
||||
# raise Exception("insufficient proof of work: %s vs target %s" % (int('0x' + _hash, 16), target))
|
||||
|
||||
def verify_chunk(self, index: int, data: bytes) -> None:
|
||||
num = len(data) // HEADER_SIZE
|
||||
start_height = index * 2016
|
||||
prev_hash = self.get_hash(start_height - 1)
|
||||
target = self.get_target(index-1)
|
||||
for i in range(num):
|
||||
height = start_height + i
|
||||
header = self.read_header(height - 1)
|
||||
#bits, target = self.get_target2(height - 1, header)
|
||||
try:
|
||||
expected_header_hash = self.get_hash(height)
|
||||
except MissingHeader:
|
||||
expected_header_hash = None
|
||||
raw_header = data[i*HEADER_SIZE : (i+1)*HEADER_SIZE]
|
||||
header = deserialize_header(raw_header, index*2016 + i)
|
||||
self.verify_header(header, prev_hash, target, expected_header_hash)
|
||||
self.verify_header(header, prev_hash, 0, 0, expected_header_hash)
|
||||
prev_hash = hash_header(header)
|
||||
|
||||
@with_lock
|
||||
|
@ -507,18 +540,73 @@ class Blockchain(Logger):
|
|||
bits = last.get('bits')
|
||||
target = self.bits_to_target(bits)
|
||||
nActualTimespan = last.get('timestamp') - first.get('timestamp')
|
||||
nTargetTimespan = 14 * 24 * 60 * 60
|
||||
nActualTimespan = max(nActualTimespan, nTargetTimespan // 4)
|
||||
nActualTimespan = min(nActualTimespan, nTargetTimespan * 4)
|
||||
new_target = min(MAX_TARGET, (target * nActualTimespan) // nTargetTimespan)
|
||||
# not any target can be represented in 32 bits:
|
||||
new_target = self.bits_to_target(self.target_to_bits(new_target))
|
||||
return new_target
|
||||
nTargetTimespan = 150
|
||||
nModulatedTimespan = nTargetTimespan - (nActualTimespan - nTargetTimespan) / 8
|
||||
nMinTimespan = nTargetTimespan - (nTargetTimespan / 8)
|
||||
nMaxTimespan = nTargetTimespan + (nTargetTimespan / 2)
|
||||
if nModulatedTimespan < nMinTimespan:
|
||||
nModulatedTimespan = nMinTimespan
|
||||
elif nModulatedTimespan > nMaxTimespan:
|
||||
nModulatedTimespan = nMaxTimespan
|
||||
|
||||
bnOld = ArithUint256.SetCompact(bits)
|
||||
bnNew = bnOld * nModulatedTimespan
|
||||
# this doesn't work if it is nTargetTimespan even though that
|
||||
# is what it looks like it should be based on reading the code
|
||||
# in lbry.cpp
|
||||
bnNew /= nModulatedTimespan
|
||||
if bnNew > MAX_TARGET:
|
||||
bnNew = ArithUint256(MAX_TARGET)
|
||||
return bnNew.compact(), bnNew._value
|
||||
|
||||
def get_target2(self, index, last, chain='main'):
|
||||
|
||||
if index == -1:
|
||||
return GENESIS_BITS, MAX_TARGET
|
||||
if index == 0:
|
||||
return GENESIS_BITS, MAX_TARGET
|
||||
first = self.read_header(index-1)
|
||||
assert last is not None, "Last shouldn't be none"
|
||||
# bits to target
|
||||
bits = last.get('bits')
|
||||
# print_error("Last bits: ", bits)
|
||||
self.check_bits(bits)
|
||||
|
||||
# new target
|
||||
nActualTimespan = last.get('timestamp') - first.get('timestamp')
|
||||
nTargetTimespan = N_TARGET_TIMESPAN
|
||||
nModulatedTimespan = nTargetTimespan - (nActualTimespan - nTargetTimespan) / 8
|
||||
nMinTimespan = nTargetTimespan - (nTargetTimespan / 8)
|
||||
nMaxTimespan = nTargetTimespan + (nTargetTimespan / 2)
|
||||
if nModulatedTimespan < nMinTimespan:
|
||||
nModulatedTimespan = nMinTimespan
|
||||
elif nModulatedTimespan > nMaxTimespan:
|
||||
nModulatedTimespan = nMaxTimespan
|
||||
|
||||
bnOld = ArithUint256.SetCompact(bits)
|
||||
bnNew = bnOld * nModulatedTimespan
|
||||
# this doesn't work if it is nTargetTimespan even though that
|
||||
# is what it looks like it should be based on reading the code
|
||||
# in lbry.cpp
|
||||
bnNew /= nModulatedTimespan
|
||||
if bnNew > MAX_TARGET:
|
||||
bnNew = ArithUint256(MAX_TARGET)
|
||||
return bnNew.compact, bnNew._value
|
||||
|
||||
def check_bits(self, bits):
|
||||
bitsN = (bits >> 24) & 0xff
|
||||
assert 0x03 <= bitsN <= 0x1f, \
|
||||
"First part of bits should be in [0x03, 0x1d], but it was {}".format(hex(bitsN))
|
||||
bitsBase = bits & 0xffffff
|
||||
assert 0x8000 <= bitsBase <= 0x7fffff, \
|
||||
"Second part of bits should be in [0x8000, 0x7fffff] but it was {}".format(bitsBase)
|
||||
|
||||
|
||||
|
||||
@classmethod
|
||||
def bits_to_target(cls, bits: int) -> int:
|
||||
bitsN = (bits >> 24) & 0xff
|
||||
if not (0x03 <= bitsN <= 0x1d):
|
||||
if not (0x03 <= bitsN <= 0x1f):
|
||||
raise Exception("First part of bits should be in [0x03, 0x1d]")
|
||||
bitsBase = bits & 0xffffff
|
||||
if not (0x8000 <= bitsBase <= 0x7fffff):
|
||||
|
@ -573,25 +661,33 @@ class Blockchain(Logger):
|
|||
def can_connect(self, header: dict, check_height: bool=True) -> bool:
|
||||
if header is None:
|
||||
return False
|
||||
|
||||
height = header['block_height']
|
||||
if check_height and self.height() != height - 1:
|
||||
print("cannot connect at height", height)
|
||||
return False
|
||||
if height == 0:
|
||||
return hash_header(header) == constants.net.GENESIS
|
||||
|
||||
try:
|
||||
prev_hash = self.get_hash(height - 1)
|
||||
except:
|
||||
return False
|
||||
|
||||
if prev_hash != header.get('prev_block_hash'):
|
||||
return False
|
||||
|
||||
try:
|
||||
target = self.get_target(height // 2016 - 1)
|
||||
bits, target = self.get_target2(height, header)
|
||||
except MissingHeader:
|
||||
return False
|
||||
|
||||
try:
|
||||
self.verify_header(header, prev_hash, target)
|
||||
self.verify_header(header, prev_hash, target, bits)
|
||||
except BaseException as e:
|
||||
print(e)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def connect_chunk(self, idx: int, hexdata: str) -> bool:
|
||||
|
@ -632,3 +728,83 @@ def can_connect(header: dict) -> Optional[Blockchain]:
|
|||
if b.can_connect(header):
|
||||
return b
|
||||
return None
|
||||
|
||||
class ArithUint256:
|
||||
# https://github.com/bitcoin/bitcoin/blob/master/src/arith_uint256.cpp
|
||||
|
||||
__slots__ = '_value', '_compact'
|
||||
|
||||
def __init__(self, value: int) -> None:
|
||||
self._value = value
|
||||
self._compact: Optional[int] = None
|
||||
|
||||
@classmethod
|
||||
def SetCompact(cls, nCompact):
|
||||
return (ArithUint256.from_compact(nCompact))
|
||||
|
||||
@classmethod
|
||||
def from_compact(cls, compact) -> 'ArithUint256':
|
||||
size = compact >> 24
|
||||
word = compact & 0x007fffff
|
||||
if size <= 3:
|
||||
return cls(word >> 8 * (3 - size))
|
||||
else:
|
||||
return cls(word << 8 * (size - 3))
|
||||
|
||||
@property
|
||||
def value(self) -> int:
|
||||
return self._value
|
||||
|
||||
@property
|
||||
def compact(self) -> int:
|
||||
if self._compact is None:
|
||||
self._compact = self._calculate_compact()
|
||||
return self._compact
|
||||
|
||||
@property
|
||||
def negative(self) -> int:
|
||||
return self._calculate_compact(negative=True)
|
||||
|
||||
@property
|
||||
def bits(self) -> int:
|
||||
""" Returns the position of the highest bit set plus one. """
|
||||
bits = bin(self._value)[2:]
|
||||
for i, d in enumerate(bits):
|
||||
if d:
|
||||
return (len(bits) - i) + 1
|
||||
return 0
|
||||
|
||||
@property
|
||||
def low64(self) -> int:
|
||||
return self._value & 0xffffffffffffffff
|
||||
|
||||
def _calculate_compact(self, negative=False) -> int:
|
||||
size = (self.bits + 7) // 8
|
||||
if size <= 3:
|
||||
compact = self.low64 << 8 * (3 - size)
|
||||
else:
|
||||
compact = ArithUint256(self._value >> 8 * (size - 3)).low64
|
||||
# The 0x00800000 bit denotes the sign.
|
||||
# Thus, if it is already set, divide the mantissa by 256 and increase the exponent.
|
||||
if compact & 0x00800000:
|
||||
compact >>= 8
|
||||
size += 1
|
||||
assert (compact & ~0x007fffff) == 0
|
||||
assert size < 256
|
||||
compact |= size << 24
|
||||
if negative and compact & 0x007fffff:
|
||||
compact |= 0x00800000
|
||||
return compact
|
||||
|
||||
def __mul__(self, x):
|
||||
# Take the mod because we are limited to an unsigned 256 bit number
|
||||
return ArithUint256((self._value * x) % 2 ** 256)
|
||||
|
||||
def __truediv__(self, x):
|
||||
return ArithUint256(int(self._value / x))
|
||||
|
||||
def __gt__(self, other):
|
||||
return self._value > other
|
||||
|
||||
def __lt__(self, other):
|
||||
return self._value < other
|
||||
|
|
|
@ -239,7 +239,7 @@ class Commands:
|
|||
@command('')
|
||||
async def restore(self, text, passphrase=None, password=None, encrypt_file=True, wallet_path=None):
|
||||
"""Restore a wallet from text. Text can be a seed phrase, a master
|
||||
public key, a master private key, a list of bitcoin addresses
|
||||
public key, a master private key, a list of LBRY Credits addresses
|
||||
or bitcoin private keys.
|
||||
If you want to be prompted for an argument, type '?' or ':' (concealed)
|
||||
"""
|
||||
|
@ -667,7 +667,7 @@ class Commands:
|
|||
|
||||
@command('w')
|
||||
async def setlabel(self, key, label, wallet: Abstract_Wallet = None):
|
||||
"""Assign a label to an item. Item may be a bitcoin address or a
|
||||
"""Assign a label to an item. Item may be a LBRY Credits address or a
|
||||
transaction ID"""
|
||||
wallet.set_label(key, label)
|
||||
|
||||
|
@ -1012,8 +1012,8 @@ def eval_bool(x: str) -> bool:
|
|||
|
||||
param_descriptions = {
|
||||
'privkey': 'Private key. Type \'?\' to get a prompt.',
|
||||
'destination': 'Bitcoin address, contact or alias',
|
||||
'address': 'Bitcoin address',
|
||||
'destination': 'LBRY Credits address, contact or alias',
|
||||
'address': 'LBRY Credits address',
|
||||
'seed': 'Seed phrase',
|
||||
'txid': 'Transaction ID',
|
||||
'pos': 'Position',
|
||||
|
@ -1023,8 +1023,8 @@ param_descriptions = {
|
|||
'pubkey': 'Public key',
|
||||
'message': 'Clear text message. Use quotes if it contains spaces.',
|
||||
'encrypted': 'Encrypted message',
|
||||
'amount': 'Amount to be sent (in BTC). Type \'!\' to send the maximum available.',
|
||||
'requested_amount': 'Requested amount (in BTC).',
|
||||
'amount': 'Amount to be sent (in LBC). Type \'!\' to send the maximum available.',
|
||||
'requested_amount': 'Requested amount (in LBC).',
|
||||
'outputs': 'list of ["address", amount]',
|
||||
'redeem_script': 'redeem script (hexadecimal)',
|
||||
}
|
||||
|
@ -1042,7 +1042,7 @@ command_options = {
|
|||
'labels': ("-l", "Show the labels of listed addresses"),
|
||||
'nocheck': (None, "Do not verify aliases"),
|
||||
'imax': (None, "Maximum number of inputs"),
|
||||
'fee': ("-f", "Transaction fee (absolute, in BTC)"),
|
||||
'fee': ("-f", "Transaction fee (absolute, in LBC)"),
|
||||
'feerate': (None, "Transaction fee rate (in sat/byte)"),
|
||||
'from_addr': ("-F", "Source address (must be a wallet address; use sweep to spend from non-wallet address)."),
|
||||
'from_coins': (None, "Source coins (must be in wallet; use sweep to spend from non-wallet address)."),
|
||||
|
@ -1062,7 +1062,7 @@ command_options = {
|
|||
'timeout': (None, "Timeout in seconds"),
|
||||
'force': (None, "Create new address beyond gap limit, if no more addresses are available."),
|
||||
'pending': (None, "Show only pending requests."),
|
||||
'push_amount': (None, 'Push initial amount (in BTC)'),
|
||||
'push_amount': (None, 'Push initial amount (in LBC)'),
|
||||
'expired': (None, "Show only expired requests."),
|
||||
'paid': (None, "Show only paid requests."),
|
||||
'show_addresses': (None, "Show input and output addresses"),
|
||||
|
@ -1106,10 +1106,10 @@ config_variables = {
|
|||
'addrequest': {
|
||||
'ssl_privkey': 'Path to your SSL private key, needed to sign the request.',
|
||||
'ssl_chain': 'Chain of SSL certificates, needed for signed requests. Put your certificate at the top and the root CA at the end',
|
||||
'url_rewrite': 'Parameters passed to str.replace(), in order to create the r= part of bitcoin: URIs. Example: \"(\'file:///var/www/\',\'https://electrum.org/\')\"',
|
||||
'url_rewrite': 'Parameters passed to str.replace(), in order to create the r= part of lbry credits: URIs. Example: \"(\'file:///var/www/\',\'https://electrum.org/\')\"',
|
||||
},
|
||||
'listrequests':{
|
||||
'url_rewrite': 'Parameters passed to str.replace(), in order to create the r= part of bitcoin: URIs. Example: \"(\'file:///var/www/\',\'https://electrum.org/\')\"',
|
||||
'url_rewrite': 'Parameters passed to str.replace(), in order to create the r= part of lbry credits: URIs. Example: \"(\'file:///var/www/\',\'https://electrum.org/\')\"',
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1194,7 +1194,7 @@ def get_parser():
|
|||
subparsers = parser.add_subparsers(dest='cmd', metavar='<command>')
|
||||
# gui
|
||||
parser_gui = subparsers.add_parser('gui', description="Run Electrum's Graphical User Interface.", help="Run GUI (default)")
|
||||
parser_gui.add_argument("url", nargs='?', default=None, help="bitcoin URI (or bip70 file)")
|
||||
parser_gui.add_argument("url", nargs='?', default=None, help="lbry credits URI (or bip70 file)")
|
||||
parser_gui.add_argument("-g", "--gui", dest="gui", help="select graphical user interface", choices=['qt', 'kivy', 'text', 'stdio'])
|
||||
parser_gui.add_argument("-m", action="store_true", dest="hide_gui", default=False, help="hide GUI on startup")
|
||||
parser_gui.add_argument("-L", "--lang", dest="language", default=None, help="default language used in GUI")
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
import os
|
||||
import json
|
||||
|
||||
BLOCKS_PER_CHUNK = 96
|
||||
from .util import inv_dict
|
||||
from . import bitcoin
|
||||
|
||||
|
@ -60,14 +61,14 @@ class AbstractNet:
|
|||
class BitcoinMainnet(AbstractNet):
|
||||
|
||||
TESTNET = False
|
||||
WIF_PREFIX = 0x80
|
||||
ADDRTYPE_P2PKH = 0
|
||||
ADDRTYPE_P2SH = 5
|
||||
SEGWIT_HRP = "bc"
|
||||
GENESIS = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
|
||||
WIF_PREFIX = 0x1c
|
||||
ADDRTYPE_P2PKH = 0x55
|
||||
ADDRTYPE_P2SH = 0x7A
|
||||
SEGWIT_HRP = "lbc"
|
||||
GENESIS = "9c89283ba0f3227f6c03b70216b9f665f0118d5e0fa729cedf4fb34d6a34f463"
|
||||
DEFAULT_PORTS = {'t': '50001', 's': '50002'}
|
||||
DEFAULT_SERVERS = read_json('servers.json', {})
|
||||
CHECKPOINTS = read_json('checkpoints.json', [])
|
||||
CHECKPOINTS = read_json('bullshit.json', [])
|
||||
BLOCK_HEIGHT_FIRST_LIGHTNING_CHANNELS = 497000
|
||||
|
||||
XPRV_HEADERS = {
|
||||
|
@ -86,7 +87,7 @@ class BitcoinMainnet(AbstractNet):
|
|||
'p2wsh': 0x02aa7ed3, # Zpub
|
||||
}
|
||||
XPUB_HEADERS_INV = inv_dict(XPUB_HEADERS)
|
||||
BIP44_COIN_TYPE = 0
|
||||
BIP44_COIN_TYPE = 140
|
||||
LN_REALM_BYTE = 0
|
||||
LN_DNS_SEEDS = [
|
||||
'nodes.lightning.directory.',
|
||||
|
@ -100,7 +101,7 @@ class BitcoinTestnet(AbstractNet):
|
|||
WIF_PREFIX = 0xef
|
||||
ADDRTYPE_P2PKH = 111
|
||||
ADDRTYPE_P2SH = 196
|
||||
SEGWIT_HRP = "tb"
|
||||
SEGWIT_HRP = "tlbc"
|
||||
GENESIS = "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"
|
||||
DEFAULT_PORTS = {'t': '51001', 's': '51002'}
|
||||
DEFAULT_SERVERS = read_json('servers_testnet.json', {})
|
||||
|
@ -132,7 +133,7 @@ class BitcoinTestnet(AbstractNet):
|
|||
|
||||
class BitcoinRegtest(BitcoinTestnet):
|
||||
|
||||
SEGWIT_HRP = "bcrt"
|
||||
SEGWIT_HRP = "blbc"
|
||||
GENESIS = "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"
|
||||
DEFAULT_SERVERS = read_json('servers_regtest.json', {})
|
||||
CHECKPOINTS = []
|
||||
|
@ -144,7 +145,7 @@ class BitcoinSimnet(BitcoinTestnet):
|
|||
WIF_PREFIX = 0x64
|
||||
ADDRTYPE_P2PKH = 0x3f
|
||||
ADDRTYPE_P2SH = 0x7b
|
||||
SEGWIT_HRP = "sb"
|
||||
SEGWIT_HRP = "slbc"
|
||||
GENESIS = "683e86bd5c6d110d91b94b97137ba6bfe02dbbdb8e3dff722a669b5d69d77af6"
|
||||
DEFAULT_SERVERS = read_json('servers_regtest.json', {})
|
||||
CHECKPOINTS = []
|
||||
|
|
|
@ -93,7 +93,7 @@ class Contacts(dict, Logger):
|
|||
'type': 'openalias',
|
||||
'validated': validated
|
||||
}
|
||||
raise Exception("Invalid Bitcoin address or alias", k)
|
||||
raise Exception("Invalid LBRY Credits address or alias", k)
|
||||
|
||||
def resolve_openalias(self, url):
|
||||
# support email-style addresses, per the OA standard
|
||||
|
@ -103,7 +103,7 @@ class Contacts(dict, Logger):
|
|||
except DNSException as e:
|
||||
self.logger.info(f'Error resolving openalias: {repr(e)}')
|
||||
return None
|
||||
prefix = 'btc'
|
||||
prefix = 'lbc'
|
||||
for record in records:
|
||||
string = to_string(record.strings[0], 'utf8')
|
||||
if string.startswith('oa1:' + prefix):
|
||||
|
@ -133,4 +133,3 @@ class Contacts(dict, Logger):
|
|||
if _type != 'address':
|
||||
data.pop(k)
|
||||
return data
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
"BTC",
|
||||
"BTN",
|
||||
"BWP",
|
||||
"BYN",
|
||||
"BZD",
|
||||
"CAD",
|
||||
"CDF",
|
||||
|
@ -46,6 +47,7 @@
|
|||
"DZD",
|
||||
"EGP",
|
||||
"ETB",
|
||||
"ETH",
|
||||
"EUR",
|
||||
"FJD",
|
||||
"FKP",
|
||||
|
@ -160,6 +162,7 @@
|
|||
"XCD",
|
||||
"XOF",
|
||||
"XPF",
|
||||
"XRP",
|
||||
"YER",
|
||||
"ZAR",
|
||||
"ZMW",
|
||||
|
@ -172,175 +175,6 @@
|
|||
"Bitbank": [
|
||||
"JPY"
|
||||
],
|
||||
"BitcoinAverage": [
|
||||
"AED",
|
||||
"AFN",
|
||||
"ALL",
|
||||
"AMD",
|
||||
"ANG",
|
||||
"AOA",
|
||||
"ARS",
|
||||
"AUD",
|
||||
"AWG",
|
||||
"AZN",
|
||||
"BAM",
|
||||
"BBD",
|
||||
"BDT",
|
||||
"BGN",
|
||||
"BHD",
|
||||
"BIF",
|
||||
"BMD",
|
||||
"BND",
|
||||
"BOB",
|
||||
"BRL",
|
||||
"BSD",
|
||||
"BTN",
|
||||
"BWP",
|
||||
"BYN",
|
||||
"BZD",
|
||||
"CAD",
|
||||
"CDF",
|
||||
"CHF",
|
||||
"CLF",
|
||||
"CLP",
|
||||
"CNH",
|
||||
"CNY",
|
||||
"COP",
|
||||
"CRC",
|
||||
"CUC",
|
||||
"CUP",
|
||||
"CVE",
|
||||
"CZK",
|
||||
"DJF",
|
||||
"DKK",
|
||||
"DOP",
|
||||
"DZD",
|
||||
"EGP",
|
||||
"ERN",
|
||||
"ETB",
|
||||
"EUR",
|
||||
"FJD",
|
||||
"FKP",
|
||||
"GBP",
|
||||
"GEL",
|
||||
"GGP",
|
||||
"GHS",
|
||||
"GIP",
|
||||
"GMD",
|
||||
"GNF",
|
||||
"GTQ",
|
||||
"GYD",
|
||||
"HKD",
|
||||
"HNL",
|
||||
"HRK",
|
||||
"HTG",
|
||||
"HUF",
|
||||
"IDR",
|
||||
"ILS",
|
||||
"IMP",
|
||||
"INR",
|
||||
"IQD",
|
||||
"IRR",
|
||||
"ISK",
|
||||
"JEP",
|
||||
"JMD",
|
||||
"JOD",
|
||||
"JPY",
|
||||
"KES",
|
||||
"KGS",
|
||||
"KHR",
|
||||
"KMF",
|
||||
"KPW",
|
||||
"KRW",
|
||||
"KWD",
|
||||
"KYD",
|
||||
"KZT",
|
||||
"LAK",
|
||||
"LBP",
|
||||
"LKR",
|
||||
"LRD",
|
||||
"LSL",
|
||||
"LYD",
|
||||
"MAD",
|
||||
"MDL",
|
||||
"MGA",
|
||||
"MKD",
|
||||
"MMK",
|
||||
"MNT",
|
||||
"MOP",
|
||||
"MRO",
|
||||
"MUR",
|
||||
"MVR",
|
||||
"MWK",
|
||||
"MXN",
|
||||
"MYR",
|
||||
"MZN",
|
||||
"NAD",
|
||||
"NGN",
|
||||
"NIO",
|
||||
"NOK",
|
||||
"NPR",
|
||||
"NZD",
|
||||
"OMR",
|
||||
"PAB",
|
||||
"PEN",
|
||||
"PGK",
|
||||
"PHP",
|
||||
"PKR",
|
||||
"PLN",
|
||||
"PYG",
|
||||
"QAR",
|
||||
"RON",
|
||||
"RSD",
|
||||
"RUB",
|
||||
"RWF",
|
||||
"SAR",
|
||||
"SBD",
|
||||
"SCR",
|
||||
"SDG",
|
||||
"SEK",
|
||||
"SGD",
|
||||
"SHP",
|
||||
"SLL",
|
||||
"SOS",
|
||||
"SRD",
|
||||
"SSP",
|
||||
"STD",
|
||||
"SVC",
|
||||
"SYP",
|
||||
"SZL",
|
||||
"THB",
|
||||
"TJS",
|
||||
"TMT",
|
||||
"TND",
|
||||
"TOP",
|
||||
"TRY",
|
||||
"TTD",
|
||||
"TWD",
|
||||
"TZS",
|
||||
"UAH",
|
||||
"UGX",
|
||||
"USD",
|
||||
"UYU",
|
||||
"UZS",
|
||||
"VES",
|
||||
"VND",
|
||||
"VUV",
|
||||
"WST",
|
||||
"XAF",
|
||||
"XAG",
|
||||
"XAU",
|
||||
"XCD",
|
||||
"XDR",
|
||||
"XOF",
|
||||
"XPD",
|
||||
"XPF",
|
||||
"XPT",
|
||||
"YER",
|
||||
"ZAR",
|
||||
"ZMW",
|
||||
"ZWL"
|
||||
],
|
||||
"BitcoinVenezuela": [
|
||||
"ARS",
|
||||
"ETH",
|
||||
|
@ -350,9 +184,6 @@
|
|||
"VEF",
|
||||
"XMR"
|
||||
],
|
||||
"Bitcointoyou": [
|
||||
"BRL"
|
||||
],
|
||||
"Bitso": [
|
||||
"MXN"
|
||||
],
|
||||
|
@ -604,6 +435,7 @@
|
|||
"THB",
|
||||
"TRY",
|
||||
"TWD",
|
||||
"UAH",
|
||||
"USD",
|
||||
"VEF",
|
||||
"VND",
|
||||
|
@ -657,12 +489,14 @@
|
|||
"CUC",
|
||||
"CVE",
|
||||
"CZK",
|
||||
"DAI",
|
||||
"DJF",
|
||||
"DKK",
|
||||
"DOP",
|
||||
"DZD",
|
||||
"EEK",
|
||||
"EGP",
|
||||
"EOS",
|
||||
"ERN",
|
||||
"ETB",
|
||||
"ETC",
|
||||
|
@ -733,6 +567,7 @@
|
|||
"NPR",
|
||||
"NZD",
|
||||
"OMR",
|
||||
"OXT",
|
||||
"PAB",
|
||||
"PEN",
|
||||
"PGK",
|
||||
|
@ -741,10 +576,12 @@
|
|||
"PLN",
|
||||
"PYG",
|
||||
"QAR",
|
||||
"REP",
|
||||
"RON",
|
||||
"RSD",
|
||||
"RUB",
|
||||
"RWF",
|
||||
"SAI",
|
||||
"SAR",
|
||||
"SBD",
|
||||
"SCR",
|
||||
|
@ -773,6 +610,7 @@
|
|||
"UYU",
|
||||
"UZS",
|
||||
"VEF",
|
||||
"VES",
|
||||
"VND",
|
||||
"VUV",
|
||||
"WST",
|
||||
|
@ -781,10 +619,13 @@
|
|||
"XAU",
|
||||
"XCD",
|
||||
"XDR",
|
||||
"XLM",
|
||||
"XOF",
|
||||
"XPD",
|
||||
"XPF",
|
||||
"XPT",
|
||||
"XRP",
|
||||
"XTZ",
|
||||
"YER",
|
||||
"ZAR",
|
||||
"ZEC",
|
||||
|
@ -802,14 +643,14 @@
|
|||
],
|
||||
"LocalBitcoins": [
|
||||
"AED",
|
||||
"AMD",
|
||||
"AOA",
|
||||
"ARS",
|
||||
"AUD",
|
||||
"BAM",
|
||||
"BDT",
|
||||
"BGN",
|
||||
"BOB",
|
||||
"BRL",
|
||||
"BWP",
|
||||
"BYN",
|
||||
"CAD",
|
||||
"CHF",
|
||||
|
@ -828,7 +669,6 @@
|
|||
"GHS",
|
||||
"GTQ",
|
||||
"HKD",
|
||||
"HNL",
|
||||
"HRK",
|
||||
"HUF",
|
||||
"IDR",
|
||||
|
@ -836,25 +676,26 @@
|
|||
"INR",
|
||||
"IRR",
|
||||
"JOD",
|
||||
"JPY",
|
||||
"KES",
|
||||
"KRW",
|
||||
"KWD",
|
||||
"KZT",
|
||||
"LKR",
|
||||
"LTC",
|
||||
"MAD",
|
||||
"MDL",
|
||||
"MUR",
|
||||
"MXN",
|
||||
"MYR",
|
||||
"NGN",
|
||||
"NIO",
|
||||
"NOK",
|
||||
"NZD",
|
||||
"OMR",
|
||||
"PAB",
|
||||
"PEN",
|
||||
"PHP",
|
||||
"PKR",
|
||||
"PLN",
|
||||
"QAR",
|
||||
"PYG",
|
||||
"RON",
|
||||
"RSD",
|
||||
"RUB",
|
||||
|
@ -865,7 +706,6 @@
|
|||
"SZL",
|
||||
"THB",
|
||||
"TRY",
|
||||
"TTD",
|
||||
"TWD",
|
||||
"TZS",
|
||||
"UAH",
|
||||
|
@ -875,21 +715,15 @@
|
|||
"VES",
|
||||
"VND",
|
||||
"XAF",
|
||||
"XMR",
|
||||
"XOF",
|
||||
"XRP",
|
||||
"ZAR"
|
||||
],
|
||||
"MercadoBitcoin": [
|
||||
"BRL"
|
||||
],
|
||||
"NegocieCoins": [
|
||||
"BRL"
|
||||
"ZAR",
|
||||
"ZMW"
|
||||
],
|
||||
"TheRockTrading": [
|
||||
"EUR"
|
||||
],
|
||||
"Zaif": [
|
||||
"JPY"
|
||||
],
|
||||
"itBit": []
|
||||
]
|
||||
}
|
|
@ -352,7 +352,7 @@ POINT_AT_INFINITY = ECPubkey(None)
|
|||
def msg_magic(message: bytes) -> bytes:
|
||||
from .bitcoin import var_int
|
||||
length = bfh(var_int(len(message)))
|
||||
return b"\x18Bitcoin Signed Message:\n" + length + message
|
||||
return b"\x18LBRYcrd Signed Message:\n" + length + message
|
||||
|
||||
|
||||
def verify_signature(pubkey: bytes, sig: bytes, h: bytes) -> bool:
|
||||
|
|
|
@ -184,7 +184,7 @@ class ElectrumWindow(App):
|
|||
|
||||
def on_new_intent(self, intent):
|
||||
data = intent.getDataString()
|
||||
if intent.getScheme() == 'bitcoin':
|
||||
if intent.getScheme() == 'lbrycredits':
|
||||
self.set_URI(data)
|
||||
elif intent.getScheme() == 'lightning':
|
||||
self.set_ln_invoice(data)
|
||||
|
|
56
electrum/gui/kivy/uix/context_menu.py
Normal file
|
@ -0,0 +1,56 @@
|
|||
#!python
|
||||
#!/usr/bin/env python
|
||||
from kivy.app import App
|
||||
from kivy.uix.bubble import Bubble
|
||||
from kivy.animation import Animation
|
||||
from kivy.uix.floatlayout import FloatLayout
|
||||
from kivy.lang import Builder
|
||||
from kivy.factory import Factory
|
||||
from kivy.clock import Clock
|
||||
|
||||
from electrum.gui.kivy.i18n import _
|
||||
|
||||
Builder.load_string('''
|
||||
<MenuItem@Button>
|
||||
background_normal: ''
|
||||
background_color: (0.192, .498, 0.745, 1)
|
||||
height: '48dp'
|
||||
size_hint: 1, None
|
||||
|
||||
<ContextMenu>
|
||||
size_hint: 1, None
|
||||
height: '48dp'
|
||||
pos: (0, 0)
|
||||
show_arrow: False
|
||||
arrow_pos: 'top_mid'
|
||||
padding: 0
|
||||
orientation: 'horizontal'
|
||||
BoxLayout:
|
||||
size_hint: 1, 1
|
||||
height: '48dp'
|
||||
padding: '12dp', '0dp'
|
||||
spacing: '3dp'
|
||||
orientation: 'horizontal'
|
||||
id: buttons
|
||||
''')
|
||||
|
||||
|
||||
class MenuItem(Factory.Button):
|
||||
pass
|
||||
|
||||
class ContextMenu(Bubble):
|
||||
|
||||
def __init__(self, obj, action_list):
|
||||
Bubble.__init__(self)
|
||||
self.obj = obj
|
||||
for k, v in action_list:
|
||||
l = MenuItem()
|
||||
l.text = _(k)
|
||||
def func(f=v):
|
||||
Clock.schedule_once(lambda dt: f(obj), 0.15)
|
||||
l.on_release = func
|
||||
self.ids.buttons.add_widget(l)
|
||||
|
||||
def hide(self):
|
||||
if self.parent:
|
||||
self.parent.hide_menu()
|
169
electrum/gui/kivy/uix/dialogs/invoices.py
Normal file
|
@ -0,0 +1,169 @@
|
|||
from kivy.app import App
|
||||
from kivy.factory import Factory
|
||||
from kivy.properties import ObjectProperty
|
||||
from kivy.lang import Builder
|
||||
from decimal import Decimal
|
||||
|
||||
Builder.load_string('''
|
||||
<InvoicesLabel@Label>
|
||||
#color: .305, .309, .309, 1
|
||||
text_size: self.width, None
|
||||
halign: 'left'
|
||||
valign: 'top'
|
||||
|
||||
<InvoiceItem@CardItem>
|
||||
requestor: ''
|
||||
memo: ''
|
||||
amount: ''
|
||||
status: ''
|
||||
date: ''
|
||||
icon: 'atlas://electrum/gui/kivy/theming/light/important'
|
||||
Image:
|
||||
id: icon
|
||||
source: root.icon
|
||||
size_hint: None, 1
|
||||
width: self.height *.54
|
||||
mipmap: True
|
||||
BoxLayout:
|
||||
spacing: '8dp'
|
||||
height: '32dp'
|
||||
orientation: 'vertical'
|
||||
Widget
|
||||
InvoicesLabel:
|
||||
text: root.requestor
|
||||
shorten: True
|
||||
Widget
|
||||
InvoicesLabel:
|
||||
text: root.memo
|
||||
color: .699, .699, .699, 1
|
||||
font_size: '13sp'
|
||||
shorten: True
|
||||
Widget
|
||||
BoxLayout:
|
||||
spacing: '8dp'
|
||||
height: '32dp'
|
||||
orientation: 'vertical'
|
||||
Widget
|
||||
InvoicesLabel:
|
||||
text: root.amount
|
||||
font_size: '15sp'
|
||||
halign: 'right'
|
||||
width: '110sp'
|
||||
Widget
|
||||
InvoicesLabel:
|
||||
text: root.status
|
||||
font_size: '13sp'
|
||||
halign: 'right'
|
||||
color: .699, .699, .699, 1
|
||||
Widget
|
||||
|
||||
|
||||
<InvoicesDialog@Popup>
|
||||
id: popup
|
||||
title: _('Invoices')
|
||||
BoxLayout:
|
||||
id: box
|
||||
orientation: 'vertical'
|
||||
spacing: '1dp'
|
||||
ScrollView:
|
||||
GridLayout:
|
||||
cols: 1
|
||||
id: invoices_container
|
||||
size_hint: 1, None
|
||||
height: self.minimum_height
|
||||
spacing: '2dp'
|
||||
padding: '12dp'
|
||||
''')
|
||||
|
||||
from kivy.properties import BooleanProperty
|
||||
from electrum.gui.kivy.i18n import _
|
||||
from electrum.util import format_time
|
||||
from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED
|
||||
from electrum.gui.kivy.uix.context_menu import ContextMenu
|
||||
|
||||
invoice_text = {
|
||||
PR_UNPAID:_('Pending'),
|
||||
PR_UNKNOWN:_('Unknown'),
|
||||
PR_PAID:_('Paid'),
|
||||
PR_EXPIRED:_('Expired')
|
||||
}
|
||||
pr_icon = {
|
||||
PR_UNPAID: 'atlas://electrum/gui/kivy/theming/light/important',
|
||||
PR_UNKNOWN: 'atlas://electrum/gui/kivy/theming/light/important',
|
||||
PR_PAID: 'atlas://electrum/gui/kivy/theming/light/confirmed',
|
||||
PR_EXPIRED: 'atlas://electrum/gui/kivy/theming/light/close'
|
||||
}
|
||||
|
||||
|
||||
class InvoicesDialog(Factory.Popup):
|
||||
|
||||
def __init__(self, app, screen, callback):
|
||||
Factory.Popup.__init__(self)
|
||||
self.app = app
|
||||
self.screen = screen
|
||||
self.callback = callback
|
||||
self.cards = {}
|
||||
self.context_menu = None
|
||||
|
||||
def get_card(self, pr):
|
||||
key = pr.get_id()
|
||||
ci = self.cards.get(key)
|
||||
if ci is None:
|
||||
ci = Factory.InvoiceItem()
|
||||
ci.key = key
|
||||
ci.screen = self
|
||||
self.cards[key] = ci
|
||||
ci.requestor = pr.get_requestor()
|
||||
ci.memo = pr.get_memo()
|
||||
amount = pr.get_amount()
|
||||
if amount:
|
||||
ci.amount = self.app.format_amount_and_units(amount)
|
||||
status = self.app.wallet.invoices.get_status(ci.key)
|
||||
ci.status = invoice_text[status]
|
||||
ci.icon = pr_icon[status]
|
||||
else:
|
||||
ci.amount = _('No Amount')
|
||||
ci.status = ''
|
||||
exp = pr.get_expiration_date()
|
||||
ci.date = format_time(exp) if exp else _('Never')
|
||||
return ci
|
||||
|
||||
def update(self):
|
||||
self.menu_actions = [('Pay', self.do_pay), ('Details', self.do_view), ('Delete', self.do_delete)]
|
||||
invoices_list = self.ids.invoices_container
|
||||
invoices_list.clear_widgets()
|
||||
_list = self.app.wallet.invoices.sorted_list()
|
||||
for pr in _list:
|
||||
ci = self.get_card(pr)
|
||||
invoices_list.add_widget(ci)
|
||||
|
||||
def do_pay(self, obj):
|
||||
self.hide_menu()
|
||||
self.dismiss()
|
||||
pr = self.app.wallet.invoices.get(obj.key)
|
||||
self.app.on_pr(pr)
|
||||
|
||||
def do_view(self, obj):
|
||||
pr = self.app.wallet.invoices.get(obj.key)
|
||||
pr.verify(self.app.wallet.contacts)
|
||||
self.app.show_pr_details(pr.get_dict(), obj.status, True)
|
||||
|
||||
def do_delete(self, obj):
|
||||
from .question import Question
|
||||
def cb(result):
|
||||
if result:
|
||||
self.app.wallet.invoices.remove(obj.key)
|
||||
self.hide_menu()
|
||||
self.update()
|
||||
d = Question(_('Delete invoice?'), cb)
|
||||
d.open()
|
||||
|
||||
def show_menu(self, obj):
|
||||
self.hide_menu()
|
||||
self.context_menu = ContextMenu(obj, self.menu_actions)
|
||||
self.ids.box.add_widget(self.context_menu)
|
||||
|
||||
def hide_menu(self):
|
||||
if self.context_menu is not None:
|
||||
self.ids.box.remove_widget(self.context_menu)
|
||||
self.context_menu = None
|
157
electrum/gui/kivy/uix/dialogs/requests.py
Normal file
|
@ -0,0 +1,157 @@
|
|||
from kivy.app import App
|
||||
from kivy.factory import Factory
|
||||
from kivy.properties import ObjectProperty
|
||||
from kivy.lang import Builder
|
||||
from decimal import Decimal
|
||||
|
||||
Builder.load_string('''
|
||||
<RequestLabel@Label>
|
||||
#color: .305, .309, .309, 1
|
||||
text_size: self.width, None
|
||||
halign: 'left'
|
||||
valign: 'top'
|
||||
|
||||
<RequestItem@CardItem>
|
||||
address: ''
|
||||
memo: ''
|
||||
amount: ''
|
||||
status: ''
|
||||
date: ''
|
||||
icon: 'atlas://electrum/gui/kivy/theming/light/important'
|
||||
Image:
|
||||
id: icon
|
||||
source: root.icon
|
||||
size_hint: None, 1
|
||||
width: self.height *.54
|
||||
mipmap: True
|
||||
BoxLayout:
|
||||
spacing: '8dp'
|
||||
height: '32dp'
|
||||
orientation: 'vertical'
|
||||
Widget
|
||||
RequestLabel:
|
||||
text: root.address
|
||||
shorten: True
|
||||
Widget
|
||||
RequestLabel:
|
||||
text: root.memo
|
||||
color: .699, .699, .699, 1
|
||||
font_size: '13sp'
|
||||
shorten: True
|
||||
Widget
|
||||
BoxLayout:
|
||||
spacing: '8dp'
|
||||
height: '32dp'
|
||||
orientation: 'vertical'
|
||||
Widget
|
||||
RequestLabel:
|
||||
text: root.amount
|
||||
halign: 'right'
|
||||
font_size: '15sp'
|
||||
Widget
|
||||
RequestLabel:
|
||||
text: root.status
|
||||
halign: 'right'
|
||||
font_size: '13sp'
|
||||
color: .699, .699, .699, 1
|
||||
Widget
|
||||
|
||||
<RequestsDialog@Popup>
|
||||
id: popup
|
||||
title: _('Requests')
|
||||
BoxLayout:
|
||||
id:box
|
||||
orientation: 'vertical'
|
||||
spacing: '1dp'
|
||||
ScrollView:
|
||||
GridLayout:
|
||||
cols: 1
|
||||
id: requests_container
|
||||
size_hint: 1, None
|
||||
height: self.minimum_height
|
||||
spacing: '2dp'
|
||||
padding: '12dp'
|
||||
''')
|
||||
|
||||
from kivy.properties import BooleanProperty
|
||||
from electrum.gui.kivy.i18n import _
|
||||
from electrum.util import format_time
|
||||
from electrum.paymentrequest import PR_UNPAID, PR_PAID, PR_UNKNOWN, PR_EXPIRED
|
||||
from electrum.gui.kivy.uix.context_menu import ContextMenu
|
||||
|
||||
pr_icon = {
|
||||
PR_UNPAID: 'atlas://electrum/gui/kivy/theming/light/important',
|
||||
PR_UNKNOWN: 'atlas://electrum/gui/kivy/theming/light/important',
|
||||
PR_PAID: 'atlas://electrum/gui/kivy/theming/light/confirmed',
|
||||
PR_EXPIRED: 'atlas://electrum/gui/kivy/theming/light/close'
|
||||
}
|
||||
request_text = {
|
||||
PR_UNPAID: _('Pending'),
|
||||
PR_UNKNOWN: _('Unknown'),
|
||||
PR_PAID: _('Received'),
|
||||
PR_EXPIRED: _('Expired')
|
||||
}
|
||||
|
||||
|
||||
class RequestsDialog(Factory.Popup):
|
||||
|
||||
def __init__(self, app, screen, callback):
|
||||
Factory.Popup.__init__(self)
|
||||
self.app = app
|
||||
self.screen = screen
|
||||
self.callback = callback
|
||||
self.cards = {}
|
||||
self.context_menu = None
|
||||
|
||||
def get_card(self, req):
|
||||
address = req['address']
|
||||
ci = self.cards.get(address)
|
||||
if ci is None:
|
||||
ci = Factory.RequestItem()
|
||||
ci.address = address
|
||||
ci.screen = self
|
||||
self.cards[address] = ci
|
||||
|
||||
amount = req.get('amount')
|
||||
ci.amount = self.app.format_amount_and_units(amount) if amount else ''
|
||||
ci.memo = req.get('memo', '')
|
||||
status, conf = self.app.wallet.get_request_status(address)
|
||||
ci.status = request_text[status]
|
||||
ci.icon = pr_icon[status]
|
||||
#exp = pr.get_expiration_date()
|
||||
#ci.date = format_time(exp) if exp else _('Never')
|
||||
return ci
|
||||
|
||||
def update(self):
|
||||
self.menu_actions = [(_('Show'), self.do_show), (_('Delete'), self.do_delete)]
|
||||
requests_list = self.ids.requests_container
|
||||
requests_list.clear_widgets()
|
||||
_list = self.app.wallet.get_sorted_requests(self.app.electrum_config)
|
||||
for pr in _list:
|
||||
ci = self.get_card(pr)
|
||||
requests_list.add_widget(ci)
|
||||
|
||||
def do_show(self, obj):
|
||||
self.hide_menu()
|
||||
self.dismiss()
|
||||
self.app.show_request(obj.address)
|
||||
|
||||
def do_delete(self, req):
|
||||
from .question import Question
|
||||
def cb(result):
|
||||
if result:
|
||||
self.app.wallet.remove_payment_request(req.address, self.app.electrum_config)
|
||||
self.hide_menu()
|
||||
self.update()
|
||||
d = Question(_('Delete request'), cb)
|
||||
d.open()
|
||||
|
||||
def show_menu(self, obj):
|
||||
self.hide_menu()
|
||||
self.context_menu = ContextMenu(obj, self.menu_actions)
|
||||
self.ids.box.add_widget(self.context_menu)
|
||||
|
||||
def hide_menu(self):
|
||||
if self.context_menu is not None:
|
||||
self.ids.box.remove_widget(self.context_menu)
|
||||
self.context_menu = None
|
89
electrum/gui/kivy/uix/ui_screens/invoice.kv
Normal file
|
@ -0,0 +1,89 @@
|
|||
#:import Decimal decimal.Decimal
|
||||
|
||||
|
||||
|
||||
Popup:
|
||||
id: popup
|
||||
is_invoice: True
|
||||
amount: 0
|
||||
requestor: ''
|
||||
exp: ''
|
||||
description: ''
|
||||
status: ''
|
||||
signature: ''
|
||||
isaddr: ''
|
||||
fund: 0
|
||||
pk: ''
|
||||
title: _('Invoice') if popup.is_invoice else _('Request')
|
||||
tx_hash: ''
|
||||
BoxLayout:
|
||||
orientation: 'vertical'
|
||||
ScrollView:
|
||||
GridLayout:
|
||||
cols: 1
|
||||
height: self.minimum_height
|
||||
size_hint_y: None
|
||||
padding: '10dp'
|
||||
spacing: '10dp'
|
||||
GridLayout:
|
||||
cols: 1
|
||||
size_hint_y: None
|
||||
height: self.minimum_height
|
||||
spacing: '10dp'
|
||||
BoxLabel:
|
||||
text: (_('Status') if popup.amount or popup.is_invoice or popup.isaddr == 'y' else _('Amount received')) if root.status else ''
|
||||
value: root.status
|
||||
BoxLabel:
|
||||
text: _('Request amount') if root.amount else ''
|
||||
value: app.format_amount_and_units(root.amount) if root.amount else ''
|
||||
BoxLabel:
|
||||
text: _('Requestor') if popup.is_invoice else _('Address')
|
||||
value: root.requestor
|
||||
BoxLabel:
|
||||
text: _('Signature') if root.signature else ''
|
||||
value: root.signature
|
||||
BoxLabel:
|
||||
text: _('Expiration') if root.exp else ''
|
||||
value: root.exp
|
||||
BoxLabel:
|
||||
text: _('Description') if root.description else ''
|
||||
value: root.description
|
||||
BoxLabel:
|
||||
text: _('Balance') if popup.fund else ''
|
||||
value: app.format_amount_and_units(root.fund) if root.fund else ''
|
||||
TopLabel:
|
||||
text: _('Private Key')
|
||||
RefLabel:
|
||||
id: pk_label
|
||||
touched: True if not self.touched else True
|
||||
data: root.pk
|
||||
|
||||
TopLabel:
|
||||
text: _('Outputs') if popup.is_invoice else ''
|
||||
OutputList:
|
||||
id: output_list
|
||||
TopLabel:
|
||||
text: _('Transaction ID') if popup.tx_hash else ''
|
||||
TxHashLabel:
|
||||
data: popup.tx_hash
|
||||
name: _('Transaction ID')
|
||||
Widget:
|
||||
size_hint: 1, 0.1
|
||||
|
||||
BoxLayout:
|
||||
size_hint: 1, None
|
||||
height: '48dp'
|
||||
Widget:
|
||||
size_hint: 0.5, None
|
||||
height: '48dp'
|
||||
Button:
|
||||
size_hint: 2, None
|
||||
height: '48dp'
|
||||
text: _('Close')
|
||||
on_release: popup.dismiss()
|
||||
Button:
|
||||
size_hint: 2, None
|
||||
height: '48dp'
|
||||
text: _('Hide private key') if pk_label.data else _('Export private key')
|
||||
on_release:
|
||||
setattr(pk_label, 'data', '') if pk_label.data else popup.export(pk_label, popup.requestor)
|
|
@ -82,7 +82,7 @@ from .amountedit import AmountEdit, BTCAmountEdit, FreezableLineEdit, FeerateEdi
|
|||
from .qrcodewidget import QRCodeWidget, QRDialog
|
||||
from .qrtextedit import ShowQRTextEdit, ScanQRTextEdit
|
||||
from .transaction_dialog import show_transaction
|
||||
from .fee_slider import FeeSlider
|
||||
#from .fee_slider import FeeSlider
|
||||
from .util import (read_QIcon, ColorScheme, text_dialog, icon_path, WaitingDialog,
|
||||
WindowModalDialog, ChoicesLayout, HelpLabel, Buttons,
|
||||
OkButton, InfoButton, WWLabel, TaskThread, CancelButton,
|
||||
|
@ -991,8 +991,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
|
|||
msg = ' '.join([
|
||||
_('Expiration date of your request.'),
|
||||
_('This information is seen by the recipient if you send them a signed payment request.'),
|
||||
_('Expired requests have to be deleted manually from your list, in order to free the corresponding Bitcoin addresses.'),
|
||||
_('The bitcoin address never expires and will always be part of this electrum wallet.'),
|
||||
_('Expired requests have to be deleted manually from your list, in order to free the corresponding LBRY Credits addresses.'),
|
||||
_('The LBRY Credits address never expires and will always be part of this electrum wallet.'),
|
||||
])
|
||||
grid.addWidget(HelpLabel(_('Request expires'), msg), 2, 0)
|
||||
grid.addWidget(self.expires_combo, 2, 1)
|
||||
|
@ -1033,7 +1033,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
|
|||
addr = str(self.receive_address_e.text())
|
||||
self.receive_address_widgets.setVisible(bool(addr))
|
||||
|
||||
msg = _('Bitcoin address where the payment should be received. Note that each payment request uses a different Bitcoin address.')
|
||||
msg = _('LBRY Credits address where the payment should be received. Note that each payment request uses a different LBRY Credits address.')
|
||||
receive_address_label = HelpLabel(_('Receiving address'), msg)
|
||||
|
||||
self.receive_address_e = ButtonsTextEdit()
|
||||
|
@ -1246,7 +1246,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
|
|||
self.amount_e = BTCAmountEdit(self.get_decimal_point)
|
||||
self.payto_e = PayToEdit(self)
|
||||
msg = _('Recipient of the funds.') + '\n\n'\
|
||||
+ _('You may enter a Bitcoin address, a label from your list of contacts (a list of completions will be proposed), or an alias (email-like address that forwards to a Bitcoin address)')
|
||||
+ _('You may enter a LBRY Credits address, a label from your list of contacts (a list of completions will be proposed), or an alias (email-like address that forwards to a LBRY Credits address)')
|
||||
payto_label = HelpLabel(_('Pay to'), msg)
|
||||
grid.addWidget(payto_label, 1, 0)
|
||||
grid.addWidget(self.payto_e, 1, 1, 1, -1)
|
||||
|
|
|
@ -445,8 +445,8 @@ class Interface(Logger):
|
|||
self.logger.info(f'requesting block header {height} in mode {assert_mode}')
|
||||
# use lower timeout as we usually have network.bhi_lock here
|
||||
timeout = self.network.get_network_timeout_seconds(NetworkTimeout.Urgent)
|
||||
res = await self.session.send_request('blockchain.block.header', [height], timeout=timeout)
|
||||
return blockchain.deserialize_header(bytes.fromhex(res), height)
|
||||
res = await self.session.send_request('blockchain.block.headers', [height,1], timeout=timeout)
|
||||
return blockchain.deserialize_header(bytes.fromhex(res['hex']), height)
|
||||
|
||||
async def request_chunk(self, height: int, tip=None, *, can_return_early=False):
|
||||
index = height // 2016
|
||||
|
@ -518,10 +518,12 @@ class Interface(Logger):
|
|||
|
||||
async def run_fetch_blocks(self):
|
||||
header_queue = asyncio.Queue()
|
||||
await self.session.subscribe('blockchain.headers.subscribe', [], header_queue)
|
||||
await self.session.subscribe('blockchain.headers.subscribe', [True], header_queue)
|
||||
while True:
|
||||
item = await header_queue.get()
|
||||
raw_header = item[0]
|
||||
print(item)
|
||||
raw_header = item[1]
|
||||
print(raw_header)
|
||||
height = raw_header['height']
|
||||
header = blockchain.deserialize_header(bfh(raw_header['hex']), height)
|
||||
self.tip_header = header
|
||||
|
|
99
electrum/jsonrpc.py
Normal file
|
@ -0,0 +1,99 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Electrum - lightweight Bitcoin client
|
||||
# Copyright (C) 2018 Thomas Voegtlin
|
||||
#
|
||||
# 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.
|
||||
|
||||
from base64 import b64decode
|
||||
import time
|
||||
|
||||
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer, SimpleJSONRPCRequestHandler
|
||||
|
||||
from . import util
|
||||
|
||||
|
||||
class RPCAuthCredentialsInvalid(Exception):
|
||||
def __str__(self):
|
||||
return 'Authentication failed (bad credentials)'
|
||||
|
||||
|
||||
class RPCAuthCredentialsMissing(Exception):
|
||||
def __str__(self):
|
||||
return 'Authentication failed (missing credentials)'
|
||||
|
||||
|
||||
class RPCAuthUnsupportedType(Exception):
|
||||
def __str__(self):
|
||||
return 'Authentication failed (only basic auth is supported)'
|
||||
|
||||
|
||||
# based on http://acooke.org/cute/BasicHTTPA0.html by andrew cooke
|
||||
class VerifyingJSONRPCServer(SimpleJSONRPCServer):
|
||||
|
||||
def __init__(self, *args, rpc_user, rpc_password, **kargs):
|
||||
|
||||
self.rpc_user = rpc_user
|
||||
self.rpc_password = rpc_password
|
||||
|
||||
class VerifyingRequestHandler(SimpleJSONRPCRequestHandler):
|
||||
def parse_request(myself):
|
||||
# first, call the original implementation which returns
|
||||
# True if all OK so far
|
||||
if SimpleJSONRPCRequestHandler.parse_request(myself):
|
||||
# Do not authenticate OPTIONS-requests
|
||||
if myself.command.strip() == 'OPTIONS':
|
||||
return True
|
||||
try:
|
||||
self.authenticate(myself.headers)
|
||||
return True
|
||||
except (RPCAuthCredentialsInvalid, RPCAuthCredentialsMissing,
|
||||
RPCAuthUnsupportedType) as e:
|
||||
myself.send_error(401, str(e))
|
||||
except BaseException as e:
|
||||
import traceback, sys
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
myself.send_error(500, str(e))
|
||||
return False
|
||||
|
||||
SimpleJSONRPCServer.__init__(
|
||||
self, requestHandler=VerifyingRequestHandler, *args, **kargs)
|
||||
|
||||
def authenticate(self, headers):
|
||||
if self.rpc_password == '':
|
||||
# RPC authentication is disabled
|
||||
return
|
||||
|
||||
auth_string = headers.get('Authorization', None)
|
||||
if auth_string is None:
|
||||
raise RPCAuthCredentialsMissing()
|
||||
|
||||
(basic, _, encoded) = auth_string.partition(' ')
|
||||
if basic != 'Basic':
|
||||
raise RPCAuthUnsupportedType()
|
||||
|
||||
encoded = util.to_bytes(encoded, 'utf8')
|
||||
credentials = util.to_string(b64decode(encoded), 'utf8')
|
||||
(username, _, password) = credentials.partition(':')
|
||||
if not (util.constant_time_compare(username, self.rpc_user)
|
||||
and util.constant_time_compare(password, self.rpc_password)):
|
||||
time.sleep(0.050)
|
||||
raise RPCAuthCredentialsInvalid()
|
|
@ -140,7 +140,7 @@ class Mnemonic(Logger):
|
|||
mnemonic = normalize_text(mnemonic)
|
||||
passphrase = passphrase or ''
|
||||
passphrase = normalize_text(passphrase)
|
||||
return hashlib.pbkdf2_hmac('sha512', mnemonic.encode('utf-8'), b'electrum' + passphrase.encode('utf-8'), iterations = PBKDF2_ROUNDS)
|
||||
return hashlib.pbkdf2_hmac('sha512', mnemonic.encode('utf-8'), b'lbryum' + passphrase.encode('utf-8'), iterations = PBKDF2_ROUNDS)
|
||||
|
||||
def mnemonic_encode(self, i):
|
||||
n = len(self.wordlist)
|
||||
|
|
94
electrum/msqr.py
Normal file
|
@ -0,0 +1,94 @@
|
|||
# from http://eli.thegreenplace.net/2009/03/07/computing-modular-square-roots-in-python/
|
||||
|
||||
def modular_sqrt(a, p):
|
||||
""" Find a quadratic residue (mod p) of 'a'. p
|
||||
must be an odd prime.
|
||||
|
||||
Solve the congruence of the form:
|
||||
x^2 = a (mod p)
|
||||
And returns x. Note that p - x is also a root.
|
||||
|
||||
0 is returned is no square root exists for
|
||||
these a and p.
|
||||
|
||||
The Tonelli-Shanks algorithm is used (except
|
||||
for some simple cases in which the solution
|
||||
is known from an identity). This algorithm
|
||||
runs in polynomial time (unless the
|
||||
generalized Riemann hypothesis is false).
|
||||
"""
|
||||
# Simple cases
|
||||
#
|
||||
if legendre_symbol(a, p) != 1:
|
||||
return 0
|
||||
elif a == 0:
|
||||
return 0
|
||||
elif p == 2:
|
||||
return p
|
||||
elif p % 4 == 3:
|
||||
return pow(a, (p + 1) // 4, p)
|
||||
|
||||
# Partition p-1 to s * 2^e for an odd s (i.e.
|
||||
# reduce all the powers of 2 from p-1)
|
||||
#
|
||||
s = p - 1
|
||||
e = 0
|
||||
while s % 2 == 0:
|
||||
s //= 2
|
||||
e += 1
|
||||
|
||||
# Find some 'n' with a legendre symbol n|p = -1.
|
||||
# Shouldn't take long.
|
||||
#
|
||||
n = 2
|
||||
while legendre_symbol(n, p) != -1:
|
||||
n += 1
|
||||
|
||||
# Here be dragons!
|
||||
# Read the paper "Square roots from 1; 24, 51,
|
||||
# 10 to Dan Shanks" by Ezra Brown for more
|
||||
# information
|
||||
#
|
||||
|
||||
# x is a guess of the square root that gets better
|
||||
# with each iteration.
|
||||
# b is the "fudge factor" - by how much we're off
|
||||
# with the guess. The invariant x^2 = ab (mod p)
|
||||
# is maintained throughout the loop.
|
||||
# g is used for successive powers of n to update
|
||||
# both a and b
|
||||
# r is the exponent - decreases with each update
|
||||
#
|
||||
x = pow(a, (s + 1) // 2, p)
|
||||
b = pow(a, s, p)
|
||||
g = pow(n, s, p)
|
||||
r = e
|
||||
|
||||
while True:
|
||||
t = b
|
||||
m = 0
|
||||
for m in range(r):
|
||||
if t == 1:
|
||||
break
|
||||
t = pow(t, 2, p)
|
||||
|
||||
if m == 0:
|
||||
return x
|
||||
|
||||
gs = pow(g, 2 ** (r - m - 1), p)
|
||||
g = (gs * gs) % p
|
||||
x = (x * gs) % p
|
||||
b = (b * g) % p
|
||||
r = m
|
||||
|
||||
def legendre_symbol(a, p):
|
||||
""" Compute the Legendre symbol a|p using
|
||||
Euler's criterion. p is a prime, a is
|
||||
relatively prime to p (if p divides
|
||||
a, then a|p = 0)
|
||||
|
||||
Returns 1 if a has a square root modulo
|
||||
p, -1 otherwise.
|
||||
"""
|
||||
ls = pow(a, (p - 1) // 2, p)
|
||||
return -1 if ls == p - 1 else ls
|
|
@ -117,7 +117,7 @@ def filter_noonion(servers):
|
|||
return {k: v for k, v in servers.items() if not k.endswith('.onion')}
|
||||
|
||||
|
||||
def filter_protocol(hostmap, protocol='s'):
|
||||
def filter_protocol(hostmap, protocol='t'):
|
||||
'''Filters the hostmap for those implementing protocol.
|
||||
The result is a list in serialized form.'''
|
||||
eligible = []
|
||||
|
@ -128,7 +128,7 @@ def filter_protocol(hostmap, protocol='s'):
|
|||
return eligible
|
||||
|
||||
|
||||
def pick_random_server(hostmap=None, protocol='s', exclude_set=None):
|
||||
def pick_random_server(hostmap=None, protocol='t', exclude_set=None):
|
||||
if hostmap is None:
|
||||
hostmap = constants.net.DEFAULT_SERVERS
|
||||
if exclude_set is None:
|
||||
|
|
5
electrum/plugins/greenaddress_instant/__init__.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
from electrum.i18n import _
|
||||
|
||||
fullname = 'GreenAddress instant'
|
||||
description = _("Allows validating if your transactions have instant confirmations by GreenAddress")
|
||||
available_for = ['qt']
|
106
electrum/plugins/greenaddress_instant/qt.py
Normal file
|
@ -0,0 +1,106 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Electrum - lightweight Bitcoin client
|
||||
# Copyright (C) 2014 Thomas Voegtlin
|
||||
#
|
||||
# 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.
|
||||
|
||||
import base64
|
||||
import urllib.parse
|
||||
import sys
|
||||
import requests
|
||||
|
||||
from PyQt5.QtWidgets import QApplication, QPushButton
|
||||
|
||||
from electrum.plugin import BasePlugin, hook
|
||||
from electrum.i18n import _
|
||||
|
||||
|
||||
class Plugin(BasePlugin):
|
||||
|
||||
button_label = _("Verify GA instant")
|
||||
|
||||
@hook
|
||||
def transaction_dialog(self, d):
|
||||
d.verify_button = QPushButton(self.button_label)
|
||||
d.verify_button.clicked.connect(lambda: self.do_verify(d))
|
||||
d.buttons.insert(0, d.verify_button)
|
||||
self.transaction_dialog_update(d)
|
||||
|
||||
def get_my_addr(self, d):
|
||||
"""Returns the address for given tx which can be used to request
|
||||
instant confirmation verification from GreenAddress"""
|
||||
for o in d.tx.outputs():
|
||||
if d.wallet.is_mine(o.address):
|
||||
return o.address
|
||||
return None
|
||||
|
||||
@hook
|
||||
def transaction_dialog_update(self, d):
|
||||
if d.tx.is_complete() and self.get_my_addr(d):
|
||||
d.verify_button.show()
|
||||
else:
|
||||
d.verify_button.hide()
|
||||
|
||||
def do_verify(self, d):
|
||||
tx = d.tx
|
||||
wallet = d.wallet
|
||||
window = d.main_window
|
||||
|
||||
if wallet.is_watching_only():
|
||||
d.show_critical(_('This feature is not available for watch-only wallets.'))
|
||||
return
|
||||
|
||||
# 1. get the password and sign the verification request
|
||||
password = None
|
||||
if wallet.has_keystore_encryption():
|
||||
msg = _('GreenAddress requires your signature \n'
|
||||
'to verify that transaction is instant.\n'
|
||||
'Please enter your password to sign a\n'
|
||||
'verification request.')
|
||||
password = window.password_dialog(msg, parent=d)
|
||||
if not password:
|
||||
return
|
||||
try:
|
||||
d.verify_button.setText(_('Verifying...'))
|
||||
QApplication.processEvents() # update the button label
|
||||
|
||||
addr = self.get_my_addr(d)
|
||||
message = "Please verify if %s is GreenAddress instant confirmed" % tx.txid()
|
||||
sig = wallet.sign_message(addr, message, password)
|
||||
sig = base64.b64encode(sig).decode('ascii')
|
||||
|
||||
# 2. send the request
|
||||
response = requests.request("GET", ("https://greenaddress.it/verify/?signature=%s&txhash=%s" % (urllib.parse.quote(sig), tx.txid())),
|
||||
headers = {'User-Agent': 'Electrum'})
|
||||
response = response.json()
|
||||
|
||||
# 3. display the result
|
||||
if response.get('verified'):
|
||||
d.show_message(_('{} is covered by GreenAddress instant confirmation').format(tx.txid()), title=_('Verification successful!'))
|
||||
else:
|
||||
d.show_critical(_('{} is not covered by GreenAddress instant confirmation').format(tx.txid()), title=_('Verification failed!'))
|
||||
except BaseException as e:
|
||||
import traceback
|
||||
traceback.print_exc(file=sys.stdout)
|
||||
d.show_error(str(e))
|
||||
finally:
|
||||
d.verify_button.setText(self.button_label)
|
11
electrum/plugins/trezor/client.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
from trezorlib.client import proto, BaseClient, ProtocolMixin
|
||||
from .clientbase import TrezorClientBase
|
||||
|
||||
class TrezorClient(TrezorClientBase, ProtocolMixin, BaseClient):
|
||||
def __init__(self, transport, handler, plugin):
|
||||
BaseClient.__init__(self, transport=transport)
|
||||
ProtocolMixin.__init__(self, transport=transport)
|
||||
TrezorClientBase.__init__(self, handler, plugin, proto)
|
||||
|
||||
|
||||
TrezorClientBase.wrap_methods(TrezorClient)
|
95
electrum/plugins/trezor/transport.py
Normal file
|
@ -0,0 +1,95 @@
|
|||
from electrum.util import PrintError
|
||||
|
||||
|
||||
class TrezorTransport(PrintError):
|
||||
|
||||
@staticmethod
|
||||
def all_transports():
|
||||
"""Reimplemented trezorlib.transport.all_transports so that we can
|
||||
enable/disable specific transports.
|
||||
"""
|
||||
try:
|
||||
# only to detect trezorlib version
|
||||
from trezorlib.transport import all_transports
|
||||
except ImportError:
|
||||
# old trezorlib. compat for trezorlib < 0.9.2
|
||||
transports = []
|
||||
try:
|
||||
from trezorlib.transport_bridge import BridgeTransport
|
||||
transports.append(BridgeTransport)
|
||||
except BaseException:
|
||||
pass
|
||||
try:
|
||||
from trezorlib.transport_hid import HidTransport
|
||||
transports.append(HidTransport)
|
||||
except BaseException:
|
||||
pass
|
||||
try:
|
||||
from trezorlib.transport_udp import UdpTransport
|
||||
transports.append(UdpTransport)
|
||||
except BaseException:
|
||||
pass
|
||||
try:
|
||||
from trezorlib.transport_webusb import WebUsbTransport
|
||||
transports.append(WebUsbTransport)
|
||||
except BaseException:
|
||||
pass
|
||||
else:
|
||||
# new trezorlib.
|
||||
transports = []
|
||||
try:
|
||||
from trezorlib.transport.bridge import BridgeTransport
|
||||
transports.append(BridgeTransport)
|
||||
except BaseException:
|
||||
pass
|
||||
try:
|
||||
from trezorlib.transport.hid import HidTransport
|
||||
transports.append(HidTransport)
|
||||
except BaseException:
|
||||
pass
|
||||
try:
|
||||
from trezorlib.transport.udp import UdpTransport
|
||||
transports.append(UdpTransport)
|
||||
except BaseException:
|
||||
pass
|
||||
try:
|
||||
from trezorlib.transport.webusb import WebUsbTransport
|
||||
transports.append(WebUsbTransport)
|
||||
except BaseException:
|
||||
pass
|
||||
return transports
|
||||
return transports
|
||||
|
||||
def enumerate_devices(self):
|
||||
"""Just like trezorlib.transport.enumerate_devices,
|
||||
but with exception catching, so that transports can fail separately.
|
||||
"""
|
||||
devices = []
|
||||
for transport in self.all_transports():
|
||||
try:
|
||||
new_devices = transport.enumerate()
|
||||
except BaseException as e:
|
||||
self.print_error('enumerate failed for {}. error {}'
|
||||
.format(transport.__name__, str(e)))
|
||||
else:
|
||||
devices.extend(new_devices)
|
||||
return devices
|
||||
|
||||
def get_transport(self, path=None):
|
||||
"""Reimplemented trezorlib.transport.get_transport,
|
||||
(1) for old trezorlib
|
||||
(2) to be able to disable specific transports
|
||||
(3) to call our own enumerate_devices that catches exceptions
|
||||
"""
|
||||
if path is None:
|
||||
try:
|
||||
return self.enumerate_devices()[0]
|
||||
except IndexError:
|
||||
raise Exception("No TREZOR device found") from None
|
||||
|
||||
def match_prefix(a, b):
|
||||
return a.startswith(b) or b.startswith(a)
|
||||
transports = [t for t in self.all_transports() if match_prefix(path, t.PATH_PREFIX)]
|
||||
if transports:
|
||||
return transports[0].find_by_path(path)
|
||||
raise Exception("Unknown path prefix '%s'" % path)
|
47
electrum/scripts/util.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
import asyncio
|
||||
from typing import List, Sequence
|
||||
|
||||
from aiorpcx import TaskGroup
|
||||
|
||||
from electrum.network import parse_servers, Network
|
||||
from electrum.interface import Interface
|
||||
|
||||
|
||||
#electrum.util.set_verbosity(True)
|
||||
|
||||
async def get_peers(network: Network):
|
||||
while not network.is_connected():
|
||||
await asyncio.sleep(1)
|
||||
print("waiting for network to get connected...")
|
||||
interface = network.interface
|
||||
session = interface.session
|
||||
print(f"asking server {interface.server} for its peers")
|
||||
peers = parse_servers(await session.send_request('server.peers.subscribe'))
|
||||
print(f"got {len(peers)} servers")
|
||||
return peers
|
||||
|
||||
|
||||
async def send_request(network: Network, servers: List[str], method: str, params: Sequence):
|
||||
print(f"contacting {len(servers)} servers")
|
||||
num_connecting = len(network.connecting)
|
||||
for server in servers:
|
||||
network._start_interface(server)
|
||||
# sleep a bit
|
||||
for _ in range(10):
|
||||
if len(network.connecting) < num_connecting:
|
||||
break
|
||||
await asyncio.sleep(1)
|
||||
print(f"connected to {len(network.interfaces)} servers. sending request to all.")
|
||||
responses = dict()
|
||||
async def get_response(iface: Interface):
|
||||
try:
|
||||
res = await iface.session.send_request(method, params, timeout=10)
|
||||
except Exception as e:
|
||||
print(f"server {iface.server} errored or timed out: ({repr(e)})")
|
||||
res = e
|
||||
responses[iface.server] = res
|
||||
async with TaskGroup() as group:
|
||||
for interface in network.interfaces.values():
|
||||
await group.spawn(get_response(interface))
|
||||
print("%d answers" % len(responses))
|
||||
return responses
|
|
@ -1,405 +1,14 @@
|
|||
{
|
||||
"3smoooajg7qqac2y.onion": {
|
||||
"spv1.lbry.com": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
"version": "1.2"
|
||||
},
|
||||
"81-7-10-251.blue.kundencontroller.de": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"version": "1.4"
|
||||
},
|
||||
"E-X.not.fyi": {
|
||||
"lbryumx2.lbry.io": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"VPS.hsmiths.com": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"b.ooze.cc": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"bauerjda5hnedjam.onion": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"bauerjhejlv6di7s.onion": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"bitcoin.corgi.party": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"bitcoin3nqy3db7c.onion": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"bitcoins.sk": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"btc.cihar.com": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"btc.xskyx.net": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"currentlane.lovebitco.in": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"daedalus.bauerj.eu": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum.jochen-hoenicke.de": {
|
||||
"pruning": "-",
|
||||
"s": "50005",
|
||||
"t": "50003",
|
||||
"version": "1.4"
|
||||
},
|
||||
"dragon085.startdedicated.de": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"version": "1.4"
|
||||
},
|
||||
"e-1.claudioboxx.com": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"e.keff.org": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum-server.ninja": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum-unlimited.criptolayer.net": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum.eff.ro": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum.festivaldelhumor.org": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum.hsmiths.com": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum.leblancnet.us": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum.mindspot.org": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum.qtornado.com": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum.taborsky.cz": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum.villocq.com": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum2.eff.ro": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum2.villocq.com": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrumx.bot.nu": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrumx.ddns.net": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrumx.ftp.sh": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrumx.soon.it": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrumxhqdsmlu.onion": {
|
||||
"pruning": "-",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"elx01.knas.systems": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"enode.duckdns.org": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"fedaykin.goip.de": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"fn.48.org": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50003",
|
||||
"version": "1.4"
|
||||
},
|
||||
"helicarrier.bauerj.eu": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"hsmiths4fyqlw5xw.onion": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"hsmiths5mjk6uijs.onion": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum.emzy.de": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"ndnd.selfhost.eu": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"ndndword5lpb7eex.onion": {
|
||||
"pruning": "-",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"orannis.com": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"ozahtqwp25chjdjd.onion": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"qtornadoklbgdyww.onion": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"rbx.curalle.ovh": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"version": "1.4"
|
||||
},
|
||||
"s7clinmo4cazmhul.onion": {
|
||||
"pruning": "-",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"tardis.bauerj.eu": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"technetium.network": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"version": "1.4"
|
||||
},
|
||||
"tomscryptos.com": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"ulrichard.ch": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"vmd27610.contaboserver.net": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"vmd30612.contaboserver.net": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"wsw6tua3xl24gsmi264zaep6seppjyrkyucpsmuxnjzyt3f3j6swshad.onion": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"xray587.startdedicated.de": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"version": "1.4"
|
||||
},
|
||||
"yuio.top": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"bitcoin.dragon.zone": {
|
||||
"pruning": "-",
|
||||
"s": "50004",
|
||||
"t": "50003",
|
||||
"version": "1.4"
|
||||
},
|
||||
"ecdsa.net" : {
|
||||
"pruning": "-",
|
||||
"s": "110",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"btc.usebsv.com": {
|
||||
"pruning": "-",
|
||||
"s": "50006",
|
||||
"version": "1.4"
|
||||
},
|
||||
"e2.keff.org": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum.hodlister.co": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum3.hodlister.co": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrum5.hodlister.co": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrumx.electricnewyear.net": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"version": "1.4"
|
||||
},
|
||||
"fortress.qtornado.com": {
|
||||
"pruning": "-",
|
||||
"s": "443",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"green-gold.westeurope.cloudapp.azure.com": {
|
||||
"pruning": "-",
|
||||
"s": "56002",
|
||||
"t": "56001",
|
||||
"version": "1.4"
|
||||
},
|
||||
"electrumx.erbium.eu": {
|
||||
"pruning": "-",
|
||||
"s": "50002",
|
||||
"t": "50001",
|
||||
"version": "1.4"
|
||||
"version": "1.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,13 +23,12 @@ FEE_DEPTH_TARGETS = [10000000, 5000000, 2000000, 1000000, 500000, 200000, 100000
|
|||
FEE_LN_ETA_TARGET = 2 # note: make sure the network is asking for estimates for this target
|
||||
|
||||
# satoshi per kbyte
|
||||
FEERATE_MAX_DYNAMIC = 1500000
|
||||
FEERATE_MAX_DYNAMIC = 50000
|
||||
FEERATE_WARNING_HIGH_FEE = 600000
|
||||
FEERATE_FALLBACK_STATIC_FEE = 150000
|
||||
FEERATE_DEFAULT_RELAY = 1000
|
||||
FEERATE_MAX_RELAY = 50000
|
||||
FEERATE_STATIC_VALUES = [1000, 2000, 5000, 10000, 20000, 30000,
|
||||
50000, 70000, 100000, 150000, 200000, 300000]
|
||||
FEERATE_FALLBACK_STATIC_FEE = 50000
|
||||
FEERATE_DEFAULT_RELAY = 50000
|
||||
FEERATE_STATIC_VALUES = [50000,100000]
|
||||
|
||||
FEERATE_REGTEST_HARDCODED = 180000 # for eclair compat
|
||||
|
||||
|
||||
|
@ -197,7 +196,7 @@ class SimpleConfig(Logger):
|
|||
base_unit = self.user_config.get('base_unit')
|
||||
if isinstance(base_unit, str):
|
||||
self._set_key_in_user_config('base_unit', None)
|
||||
map_ = {'btc':8, 'mbtc':5, 'ubtc':2, 'bits':2, 'sat':0}
|
||||
map_ = {'lbc':8, 'mlbc':5, 'ulbc':2, 'lbcs':2, 'dewey':0}
|
||||
decimal_point = map_.get(base_unit.lower())
|
||||
self._set_key_in_user_config('decimal_point', decimal_point)
|
||||
|
||||
|
|
|
@ -68,11 +68,11 @@ def inv_dict(d):
|
|||
ca_path = certifi.where()
|
||||
|
||||
|
||||
base_units = {'BTC':8, 'mBTC':5, 'bits':2, 'sat':0}
|
||||
base_units = {'LBC':8, 'mLBC':5, 'deweys':2, 'dewey':0}
|
||||
base_units_inverse = inv_dict(base_units)
|
||||
base_units_list = ['BTC', 'mBTC', 'bits', 'sat'] # list(dict) does not guarantee order
|
||||
base_units_list = ['LBC', 'mLBC', 'deweys', 'dewey'] # list(dict) does not guarantee order
|
||||
|
||||
DECIMAL_POINT_DEFAULT = 5 # mBTC
|
||||
DECIMAL_POINT_DEFAULT = 8 # mBTC
|
||||
|
||||
# types of payment requests
|
||||
PR_TYPE_ONCHAIN = 0
|
||||
|
@ -554,9 +554,9 @@ def user_dir():
|
|||
elif os.name == 'posix':
|
||||
return os.path.join(os.environ["HOME"], ".electrum")
|
||||
elif "APPDATA" in os.environ:
|
||||
return os.path.join(os.environ["APPDATA"], "Electrum")
|
||||
return os.path.join(os.environ["APPDATA"], "Electrum-lbry")
|
||||
elif "LOCALAPPDATA" in os.environ:
|
||||
return os.path.join(os.environ["LOCALAPPDATA"], "Electrum")
|
||||
return os.path.join(os.environ["LOCALAPPDATA"], "Electrum-lbry")
|
||||
else:
|
||||
#raise Exception("No home directory found in environment variables.")
|
||||
return
|
||||
|
@ -721,39 +721,7 @@ def time_difference(distance_in_time, include_seconds):
|
|||
return "over %d years" % (round(distance_in_minutes / 525600))
|
||||
|
||||
mainnet_block_explorers = {
|
||||
'Bitupper Explorer': ('https://bitupper.com/en/explorer/bitcoin/',
|
||||
{'tx': 'transactions/', 'addr': 'addresses/'}),
|
||||
'Bitflyer.jp': ('https://chainflyer.bitflyer.jp/',
|
||||
{'tx': 'Transaction/', 'addr': 'Address/'}),
|
||||
'Blockchain.info': ('https://blockchain.com/btc/',
|
||||
{'tx': 'tx/', 'addr': 'address/'}),
|
||||
'blockchainbdgpzk.onion': ('https://blockchainbdgpzk.onion/',
|
||||
{'tx': 'tx/', 'addr': 'address/'}),
|
||||
'Blockstream.info': ('https://blockstream.info/',
|
||||
{'tx': 'tx/', 'addr': 'address/'}),
|
||||
'Bitaps.com': ('https://btc.bitaps.com/',
|
||||
{'tx': '', 'addr': ''}),
|
||||
'BTC.com': ('https://btc.com/',
|
||||
{'tx': '', 'addr': ''}),
|
||||
'Chain.so': ('https://www.chain.so/',
|
||||
{'tx': 'tx/BTC/', 'addr': 'address/BTC/'}),
|
||||
'Insight.is': ('https://insight.bitpay.com/',
|
||||
{'tx': 'tx/', 'addr': 'address/'}),
|
||||
'TradeBlock.com': ('https://tradeblock.com/blockchain/',
|
||||
{'tx': 'tx/', 'addr': 'address/'}),
|
||||
'BlockCypher.com': ('https://live.blockcypher.com/btc/',
|
||||
{'tx': 'tx/', 'addr': 'address/'}),
|
||||
'Blockchair.com': ('https://blockchair.com/bitcoin/',
|
||||
{'tx': 'transaction/', 'addr': 'address/'}),
|
||||
'blockonomics.co': ('https://www.blockonomics.co/',
|
||||
{'tx': 'api/tx?txid=', 'addr': '#/search?q='}),
|
||||
'OXT.me': ('https://oxt.me/',
|
||||
{'tx': 'transaction/', 'addr': 'address/'}),
|
||||
'smartbit.com.au': ('https://www.smartbit.com.au/',
|
||||
{'tx': 'tx/', 'addr': 'address/'}),
|
||||
'mynode.local': ('http://mynode.local:3002/',
|
||||
{'tx': 'tx/', 'addr': 'address/'}),
|
||||
'system default': ('blockchain:/',
|
||||
'LBRY Explorer': ('https://explorer.lbry.io/',
|
||||
{'tx': 'tx/', 'addr': 'address/'}),
|
||||
}
|
||||
|
||||
|
@ -778,7 +746,7 @@ def block_explorer_info():
|
|||
|
||||
def block_explorer(config: 'SimpleConfig') -> str:
|
||||
from . import constants
|
||||
default_ = 'Blockstream.info'
|
||||
default_ = 'LBRY Explorer'
|
||||
be_key = config.get('block_explorer', default_)
|
||||
be = block_explorer_info().get(be_key)
|
||||
return be_key if be is not None else default_
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
ELECTRUM_VERSION = '4.0.0a0' # version of the client package
|
||||
APK_VERSION = '4.0.0.0' # read by buildozer.spec
|
||||
|
||||
PROTOCOL_VERSION = '1.4' # protocol version requested
|
||||
PROTOCOL_VERSION = '1.2' # protocol version requested
|
||||
|
||||
# The hash of the mnemonic seed must begin with this
|
||||
SEED_PREFIX = '01' # Standard wallet
|
||||
|
|
128
electrum/websockets.py
Normal file
|
@ -0,0 +1,128 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Electrum - lightweight Bitcoin client
|
||||
# Copyright (C) 2015 Thomas Voegtlin
|
||||
#
|
||||
# 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.
|
||||
import threading
|
||||
import os
|
||||
import json
|
||||
from collections import defaultdict
|
||||
import asyncio
|
||||
from typing import Dict, List, Tuple, TYPE_CHECKING
|
||||
import traceback
|
||||
import sys
|
||||
|
||||
try:
|
||||
from SimpleWebSocketServer import WebSocket, SimpleSSLWebSocketServer
|
||||
except ImportError:
|
||||
sys.exit("install SimpleWebSocketServer")
|
||||
|
||||
from .util import PrintError
|
||||
from . import bitcoin
|
||||
from .synchronizer import SynchronizerBase
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .network import Network
|
||||
from .simple_config import SimpleConfig
|
||||
|
||||
|
||||
request_queue = asyncio.Queue()
|
||||
|
||||
|
||||
class ElectrumWebSocket(WebSocket, PrintError):
|
||||
|
||||
def handleMessage(self):
|
||||
assert self.data[0:3] == 'id:'
|
||||
self.print_error("message received", self.data)
|
||||
request_id = self.data[3:]
|
||||
asyncio.run_coroutine_threadsafe(
|
||||
request_queue.put((self, request_id)), asyncio.get_event_loop())
|
||||
|
||||
def handleConnected(self):
|
||||
self.print_error("connected", self.address)
|
||||
|
||||
def handleClose(self):
|
||||
self.print_error("closed", self.address)
|
||||
|
||||
|
||||
class BalanceMonitor(SynchronizerBase):
|
||||
|
||||
def __init__(self, config: 'SimpleConfig', network: 'Network'):
|
||||
SynchronizerBase.__init__(self, network)
|
||||
self.config = config
|
||||
self.expected_payments = defaultdict(list) # type: Dict[str, List[Tuple[WebSocket, int]]]
|
||||
|
||||
def make_request(self, request_id):
|
||||
# read json file
|
||||
rdir = self.config.get('requests_dir')
|
||||
n = os.path.join(rdir, 'req', request_id[0], request_id[1], request_id, request_id + '.json')
|
||||
with open(n, encoding='utf-8') as f:
|
||||
s = f.read()
|
||||
d = json.loads(s)
|
||||
addr = d.get('address')
|
||||
amount = d.get('amount')
|
||||
return addr, amount
|
||||
|
||||
async def main(self):
|
||||
# resend existing subscriptions if we were restarted
|
||||
for addr in self.expected_payments:
|
||||
await self._add_address(addr)
|
||||
# main loop
|
||||
while True:
|
||||
ws, request_id = await request_queue.get()
|
||||
try:
|
||||
addr, amount = self.make_request(request_id)
|
||||
except Exception:
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
continue
|
||||
self.expected_payments[addr].append((ws, amount))
|
||||
await self._add_address(addr)
|
||||
|
||||
async def _on_address_status(self, addr, status):
|
||||
self.print_error('new status for addr {}'.format(addr))
|
||||
sh = bitcoin.address_to_scripthash(addr)
|
||||
balance = await self.network.get_balance_for_scripthash(sh)
|
||||
for ws, amount in self.expected_payments[addr]:
|
||||
if not ws.closed:
|
||||
if sum(balance.values()) >= amount:
|
||||
ws.sendMessage('paid')
|
||||
|
||||
|
||||
class WebSocketServer(threading.Thread):
|
||||
|
||||
def __init__(self, config: 'SimpleConfig', network: 'Network'):
|
||||
threading.Thread.__init__(self)
|
||||
self.config = config
|
||||
self.network = network
|
||||
asyncio.set_event_loop(network.asyncio_loop)
|
||||
self.daemon = True
|
||||
self.balance_monitor = BalanceMonitor(self.config, self.network)
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
asyncio.set_event_loop(self.network.asyncio_loop)
|
||||
host = self.config.get('websocket_server')
|
||||
port = self.config.get('websocket_port', 9999)
|
||||
certfile = self.config.get('ssl_chain')
|
||||
keyfile = self.config.get('ssl_privkey')
|
||||
self.server = SimpleSSLWebSocketServer(host, port, ElectrumWebSocket, certfile, keyfile)
|
||||
self.server.serveforever()
|
67
icons.qrc
Normal file
|
@ -0,0 +1,67 @@
|
|||
<RCC>
|
||||
<qresource prefix="/" >
|
||||
<file>icons/electrum.png</file>
|
||||
<file>icons/clock1.png</file>
|
||||
<file>icons/clock2.png</file>
|
||||
<file>icons/clock3.png</file>
|
||||
<file>icons/clock4.png</file>
|
||||
<file>icons/clock5.png</file>
|
||||
<file>icons/confirmed.png</file>
|
||||
<file>icons/copy.png</file>
|
||||
<file>icons/digitalbitbox.png</file>
|
||||
<file>icons/digitalbitbox_unpaired.png</file>
|
||||
<file>icons/expired.png</file>
|
||||
<file>icons/electrum_light_icon.png</file>
|
||||
<file>icons/electrum_dark_icon.png</file>
|
||||
<file>icons/electrumb.png</file>
|
||||
<file>icons/eye1.png</file>
|
||||
<file>icons/file.png</file>
|
||||
<file>icons/info.png</file>
|
||||
<file>icons/keepkey.png</file>
|
||||
<file>icons/keepkey_unpaired.png</file>
|
||||
<file>icons/key.png</file>
|
||||
<file>icons/ledger.png</file>
|
||||
<file>icons/ledger_unpaired.png</file>
|
||||
<file>icons/lock.png</file>
|
||||
<file>icons/microphone.png</file>
|
||||
<file>icons/network.png</file>
|
||||
<file>icons/offline_tx.png</file>
|
||||
<file>icons/revealer.png</file>
|
||||
<file>icons/revealer_c.png</file>
|
||||
<file>icons/qrcode.png</file>
|
||||
<file>icons/qrcode_white.png</file>
|
||||
<file>icons/preferences.png</file>
|
||||
<file>icons/safe-t_unpaired.png</file>
|
||||
<file>icons/safe-t.png</file>
|
||||
<file>icons/seed.png</file>
|
||||
<file>icons/status_connected.png</file>
|
||||
<file>icons/status_connected_fork.png</file>
|
||||
<file>icons/status_connected_proxy.png</file>
|
||||
<file>icons/status_connected_proxy_fork.png</file>
|
||||
<file>icons/status_disconnected.png</file>
|
||||
<file>icons/status_waiting.png</file>
|
||||
<file>icons/status_lagging.png</file>
|
||||
<file>icons/status_lagging_fork.png</file>
|
||||
<file>icons/seal.png</file>
|
||||
<file>icons/tab_addresses.png</file>
|
||||
<file>icons/tab_coins.png</file>
|
||||
<file>icons/tab_console.png</file>
|
||||
<file>icons/tab_contacts.png</file>
|
||||
<file>icons/tab_history.png</file>
|
||||
<file>icons/tab_receive.png</file>
|
||||
<file>icons/tab_send.png</file>
|
||||
<file>icons/tor_logo.png</file>
|
||||
<file>icons/speaker.png</file>
|
||||
<file>icons/trezor_unpaired.png</file>
|
||||
<file>icons/trezor.png</file>
|
||||
<file>icons/coldcard.png</file>
|
||||
<file>icons/coldcard_unpaired.png</file>
|
||||
<file>icons/trustedcoin-status.png</file>
|
||||
<file>icons/trustedcoin-wizard.png</file>
|
||||
<file>icons/unconfirmed.png</file>
|
||||
<file>icons/unpaid.png</file>
|
||||
<file>icons/unlock.png</file>
|
||||
<file>icons/warning.png</file>
|
||||
<file>icons/zoom.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
BIN
icons/clock1.png
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
icons/clock2.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
icons/clock3.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
icons/clock4.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
icons/clock5.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
icons/coldcard.png
Normal file
After Width: | Height: | Size: 528 B |
BIN
icons/coldcard_unpaired.png
Normal file
After Width: | Height: | Size: 788 B |
BIN
icons/confirmed.png
Normal file
After Width: | Height: | Size: 53 KiB |
44
icons/confirmed.svg
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- https://commons.wikimedia.org/wiki/File:CrystalClearActionApply.svg -->
|
||||
<svg width="512" height="512" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<linearGradient id="linearGradient3930">
|
||||
<stop style="stop-color:#ffffff;stop-opacity:1" offset="0"/>
|
||||
<stop style="stop-color:#b3d187;stop-opacity:1" offset="0.53316939"/>
|
||||
<stop style="stop-color:#28f400;stop-opacity:1" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3904">
|
||||
<stop style="stop-color:#4df60b;stop-opacity:1" offset="0"/>
|
||||
<stop style="stop-color:#008000;stop-opacity:1" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3878">
|
||||
<stop style="stop-color:#79ef39;stop-opacity:1" offset="0"/>
|
||||
<stop style="stop-color:#e9ffe3;stop-opacity:1" offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3044">
|
||||
<stop style="stop-color:#f9ffd1;stop-opacity:1" offset="0"/>
|
||||
<stop style="stop-color:#84e246;stop-opacity:1" offset="0.25998953"/>
|
||||
<stop style="stop-color:#008000;stop-opacity:1" offset="1"/>
|
||||
</linearGradient>
|
||||
<radialGradient cx="60.764378" cy="104.22466" r="63.17857" fx="60.764378" fy="104.22466" id="radialGradient3838" xlink:href="#linearGradient3044" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.85744972,-0.78795737,0.89944031,0.97876469,-84.596269,34.939755)"/>
|
||||
<radialGradient cx="145" cy="29" r="230" id="radialGradient3838-0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.66070117,-0.56004574,0.69392651,0.81864398,-39.045089,37.984063)">
|
||||
<stop style="stop-color:#FFFFFF;stop-opacity:1" offset="0"/>
|
||||
<stop style="stop-color:#FFFFFF;stop-opacity:1" offset="0.20"/>
|
||||
<stop style="stop-color:#8BE456;stop-opacity:1" offset="0.51"/>
|
||||
<stop style="stop-color:#8BE456;stop-opacity:1" offset="0.74"/>
|
||||
<stop style="stop-color:#8BE456;stop-opacity:1" offset="1"/>
|
||||
</radialGradient>
|
||||
<radialGradient cx="48.356026" cy="122.04626" r="63.17857" fx="48.356026" fy="122.04626" id="radialGradient3838-4" xlink:href="#linearGradient3904" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.97494521,-0.22244513,0.1978519,0.86715661,-18.612993,12.209071)"/>
|
||||
<radialGradient cx="57.965954" cy="109.5996" r="63.17857" fx="57.965954" fy="109.5996" id="radialGradient3838-5" xlink:href="#linearGradient3930" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.77328328,-0.70601122,0.71173774,0.77955545,-64.080277,49.199946)"/>
|
||||
</defs>
|
||||
<g>
|
||||
<path d="M 24.642857,32.642859 1.4285714,54.07143 51.071429,97.285716 126.78571,31.57143 l -22.5,-20 -52.142853,47.142858 z" id="path2997-1" style="fill:url(#radialGradient3838);fill-opacity:1;stroke:none"/>
|
||||
<path d="M 1.4285714,54.428573 51.071429,97.64286 126.78571,31.928573 126.86922,40.559647 51.78571,108.71429 1.77525,63.026751 z" id="path2997-7" style="color:#000000;fill:url(#radialGradient3838-4);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"/>
|
||||
<path d="m 24.285714,39.785715 27.5,25.000001 52.142856,-46.428569 15.71429,14.64285 c 0,0 -14.28571,12.857149 -28.928573,25.714289 -14.642854,12.85714 -54.642859,15 -80.7142871,-5.71429 C 20.357143,43.714286 24.285714,39.785715 24.285714,39.785715 z" id="path3042" style="color:#000000;fill:url(#radialGradient3838-0);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"/>
|
||||
<path d="M 1.4285714,54.07143 51.071429,97.285716 126.78571,31.57143 51.071424,101.21429 z" id="path2997" style="color:#000000;fill:url(#radialGradient3838-5);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.1 KiB |
BIN
icons/copy.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
icons/digitalbitbox.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
icons/digitalbitbox_unpaired.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
icons/electrum.ico
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
icons/electrum.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
icons/electrum_dark_icon.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
icons/electrum_launcher.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
icons/electrum_light_icon.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
icons/electrum_presplash.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
icons/electrumb.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
icons/expired.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
icons/eye1.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
icons/file.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
icons/info.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
icons/keepkey.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
icons/keepkey_unpaired.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
icons/key.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
icons/ledger.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
icons/ledger_unpaired.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
icons/lock.png
Normal file
After Width: | Height: | Size: 39 KiB |
277
icons/lock.svg
Normal file
|
@ -0,0 +1,277 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.0"
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 22 22"
|
||||
id="svg2">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="linearGradient2411">
|
||||
<stop
|
||||
id="stop2413"
|
||||
style="stop-color:#fee7b1;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop2419"
|
||||
style="stop-color:#ebd4b4;stop-opacity:1"
|
||||
offset="0.25796592" />
|
||||
<stop
|
||||
id="stop2421"
|
||||
style="stop-color:#c8a775;stop-opacity:1"
|
||||
offset="0.50796592" />
|
||||
<stop
|
||||
id="stop2423"
|
||||
style="stop-color:#b0935b;stop-opacity:1"
|
||||
offset="0.74009573" />
|
||||
<stop
|
||||
id="stop2415"
|
||||
style="stop-color:#fcebbf;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="6.72682"
|
||||
y1="32.161697"
|
||||
x2="40.938126"
|
||||
y2="32.161697"
|
||||
id="linearGradient2576"
|
||||
xlink:href="#linearGradient2411"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.4857987,0,0,0.5667573,-0.657656,-4.7557638)" />
|
||||
<linearGradient
|
||||
id="linearGradient9845">
|
||||
<stop
|
||||
id="stop9847"
|
||||
style="stop-color:white;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop9849"
|
||||
style="stop-color:white;stop-opacity:0.49484536"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="10.907269"
|
||||
y1="25.002281"
|
||||
x2="30.875446"
|
||||
y2="36.127281"
|
||||
id="linearGradient2573"
|
||||
xlink:href="#linearGradient9845"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.4541292,0,0,0.5078849,0.107594,-1.9931168)" />
|
||||
<linearGradient
|
||||
id="linearGradient5881">
|
||||
<stop
|
||||
id="stop5883"
|
||||
style="stop-color:#d6c8a7;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop5885"
|
||||
style="stop-color:#d0bd99;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="24.875"
|
||||
y1="21"
|
||||
x2="24.75"
|
||||
y2="17"
|
||||
id="linearGradient2570"
|
||||
xlink:href="#linearGradient5881"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.4705882,0,0,0.807484,-0.294082,-6.1887078)" />
|
||||
<linearGradient
|
||||
id="linearGradient12071">
|
||||
<stop
|
||||
id="stop12073"
|
||||
style="stop-color:white;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop12075"
|
||||
style="stop-color:white;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="21.941509"
|
||||
y1="21.550869"
|
||||
x2="21.941509"
|
||||
y2="18.037588"
|
||||
id="linearGradient2567"
|
||||
xlink:href="#linearGradient12071"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.4545455,0,0,0.2515938,0.090945,5.0971072)" />
|
||||
<filter
|
||||
x="-0.49411765"
|
||||
y="-0.082352944"
|
||||
width="1.9882354"
|
||||
height="1.1647059"
|
||||
color-interpolation-filters="sRGB"
|
||||
id="filter5957">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur5959"
|
||||
stdDeviation="0.69878785" />
|
||||
</filter>
|
||||
<radialGradient
|
||||
cx="15.9375"
|
||||
cy="20.3125"
|
||||
r="3.3125"
|
||||
fx="15.9375"
|
||||
fy="20.3125"
|
||||
id="radialGradient2563"
|
||||
xlink:href="#linearGradient6075"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.7547171,0,0,0.3566673,-5.528266,1.0326108)" />
|
||||
<linearGradient
|
||||
id="linearGradient6075">
|
||||
<stop
|
||||
id="stop6077"
|
||||
style="stop-color:black;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop6079"
|
||||
style="stop-color:black;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
cx="15.9375"
|
||||
cy="20.3125"
|
||||
r="3.3125"
|
||||
fx="15.9375"
|
||||
fy="20.3125"
|
||||
id="radialGradient2560"
|
||||
xlink:href="#linearGradient6075"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.7547175,0,0,0.3566673,3.471729,1.0326108)" />
|
||||
<linearGradient
|
||||
id="linearGradient10591">
|
||||
<stop
|
||||
id="stop10593"
|
||||
style="stop-color:#cad0c6;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop10599"
|
||||
style="stop-color:#eaece9;stop-opacity:1"
|
||||
offset="0.5" />
|
||||
<stop
|
||||
id="stop10595"
|
||||
style="stop-color:#c5cbc0;stop-opacity:1"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="10.650842"
|
||||
y1="2.9136841"
|
||||
x2="27.192274"
|
||||
y2="17.470011"
|
||||
id="linearGradient2557"
|
||||
xlink:href="#linearGradient10591"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.4093677,0,0,0.4456702,1.146515,-1.679622)" />
|
||||
<linearGradient
|
||||
x1="35.004684"
|
||||
y1="14.849737"
|
||||
x2="33.004314"
|
||||
y2="14.849737"
|
||||
id="linearGradient2580"
|
||||
xlink:href="#linearGradient6227"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(1.6824037,1.125)" />
|
||||
<filter
|
||||
x="-0.24242526"
|
||||
y="-0.047579072"
|
||||
width="1.4848505"
|
||||
height="1.0951581"
|
||||
color-interpolation-filters="sRGB"
|
||||
id="filter6251">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur6253"
|
||||
stdDeviation="0.24444548" />
|
||||
</filter>
|
||||
<linearGradient
|
||||
id="linearGradient6227">
|
||||
<stop
|
||||
id="stop6229"
|
||||
style="stop-color:black;stop-opacity:1"
|
||||
offset="0" />
|
||||
<stop
|
||||
id="stop6231"
|
||||
style="stop-color:black;stop-opacity:0"
|
||||
offset="1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
x1="32.128025"
|
||||
y1="13.789077"
|
||||
x2="35.020981"
|
||||
y2="13.789077"
|
||||
id="linearGradient2578"
|
||||
xlink:href="#linearGradient6227"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-19.532826,1.7437184)" />
|
||||
<filter
|
||||
color-interpolation-filters="sRGB"
|
||||
id="filter5745">
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur5747"
|
||||
stdDeviation="0.8362597" />
|
||||
</filter>
|
||||
</defs>
|
||||
<g
|
||||
id="layer1">
|
||||
<path
|
||||
d="m 3.585783,7.0017592 c 4.897701,-0.724037 9.847515,-0.611633 14.828433,0 0.601506,0 1.085748,0.523475 1.085748,1.173711 l 0,11.6979168 c 0,0.650237 -0.515495,1.079658 -1.085748,1.173711 -5.164043,0.60626 -9.5918631,0.601474 -14.828433,0 C 2.890521,20.827641 2.500036,20.523624 2.500036,19.873387 l 0,-11.6979168 c 0,-0.650236 0.484243,-1.173711 1.085747,-1.173711 z"
|
||||
id="rect1314"
|
||||
style="fill:url(#linearGradient2576);fill-opacity:1;fill-rule:evenodd;stroke:#a2824e;stroke-width:0.99999946;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0" />
|
||||
<path
|
||||
d="m 4.085707,8.5000012 13.828656,0 c 0.324462,0 0.585672,0.266352 0.585672,0.597203 l 0,10.3958448 c 0,0.33085 -0.231917,0.483593 -0.585672,0.597203 -4.521671,0.546964 -8.9847586,0.545698 -13.828656,0 -0.324462,-0.11361 -0.585671,-0.266353 -0.585671,-0.597203 l 0,-10.3958448 c 0,-0.330851 0.261209,-0.597203 0.585671,-0.597203 z"
|
||||
id="rect6903"
|
||||
style="opacity:0.37999998;fill:none;stroke:url(#linearGradient2573);stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.60109289;stroke-dashoffset:0" />
|
||||
<path
|
||||
d="m 3.779465,7.5385202 c 4.8137134,-0.786353 9.627427,-0.646293 14.441141,0 0.431803,0 0.77943,0.386003 0.77943,0.865475 l 0,1.498987 c 0,0.4794728 -0.347627,0.8654758 -0.77943,0.8654758 -5.023394,0.371496 -9.6453579,0.238912 -14.441141,0 -0.431804,0 -0.779429,-0.386003 -0.779429,-0.8654758 l 0,-1.498987 c 0,-0.479472 0.347625,-0.865475 0.779429,-0.865475 z"
|
||||
id="rect1460"
|
||||
style="fill:url(#linearGradient2570);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible" />
|
||||
<path
|
||||
d="m 4.045579,9.4999992 13.908915,0 c 0.30223,0 0.545542,0.129295 0.545542,0.289899 l 0,0.174986 c 0,0.1606028 -0.243312,0.2898978 -0.545542,0.2898978 -4.593039,0.317179 -9.2379615,0.33659 -13.908915,0 -0.302231,0 -0.545543,-0.129295 -0.545543,-0.2898978 l 0,-0.174986 c 0,-0.160604 0.243312,-0.289899 0.545543,-0.289899 z"
|
||||
id="rect1593"
|
||||
style="opacity:0.6;fill:none;stroke:url(#linearGradient2567);stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
|
||||
<rect
|
||||
width="2.8284271"
|
||||
height="16.970562"
|
||||
rx="1.6077254"
|
||||
ry="1.6077254"
|
||||
x="14.594036"
|
||||
y="23.226137"
|
||||
transform="matrix(0.923405,0,0,0.5777374,-8.226979,-3.3564678)"
|
||||
id="rect5887"
|
||||
style="opacity:0.2;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter5957);enable-background:accumulate" />
|
||||
<path
|
||||
d="m 9.0000359,8.2774169 c 0,0.6525027 -1.1192909,1.1814597 -2.4999999,1.1814597 -1.380712,0 -2.5,-0.528957 -2.5,-1.1814597 0,-0.6525037 1.119288,-1.1814615 2.5,-1.1814615 1.380709,0 2.4999999,0.5289578 2.4999999,1.1814615 z"
|
||||
id="path6073"
|
||||
style="opacity:0.3;fill:url(#radialGradient2563);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 18.000036,8.2774169 c 0,0.6525027 -1.119288,1.1814597 -2.500001,1.1814597 -1.380712,0 -2.499999,-0.528957 -2.499999,-1.1814597 0,-0.6525037 1.119287,-1.1814615 2.499999,-1.1814615 1.380713,0 2.500001,0.5289578 2.500001,1.1814615 z"
|
||||
id="path6083"
|
||||
style="opacity:0.3;fill:url(#radialGradient2560);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
|
||||
<path
|
||||
d="m 5.502269,8.1969323 0,-2.55585 c 0,-3.5074844 2.152214,-5.17378339 5.477269,-5.1299805 3.343147,0.0438029 5.518265,1.5812319 5.518265,5.1299805 l 0,2.6672674 c 0,0.8709416 -2.247715,0.98179 -2.247715,0 l 0,-1.7759272 c 0,-0.8913402 0.232705,-3.7756533 -3.247128,-3.7756533 -3.45114,0 -3.19968,2.9020879 -3.186298,3.7720995 l 0,1.6830728 c 0,1.0493847 -2.314393,1.0449226 -2.314393,-0.015009 z"
|
||||
id="path2086"
|
||||
style="fill:url(#linearGradient2557);fill-opacity:1;fill-rule:evenodd;stroke:#888a85;stroke-width:0.99999946;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<path
|
||||
d="m 34.687087,10.837069 1.263948,0.125 c 0.927239,2.822733 0.736052,9.510413 0.736052,9.510413 -0.0625,1.125 -2.03125,0.53125 -2,0 l 0,-9.635413 z"
|
||||
transform="matrix(0.4093677,0,0,0.4456703,1.146515,-0.8211368)"
|
||||
id="rect1345"
|
||||
style="opacity:0.18235294;fill:url(#linearGradient2580);fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter6251)" />
|
||||
<path
|
||||
d="m 12.926606,11.544175 0.371719,0.169195 c 1.720331,1.054966 2.173532,9.37783 2.173532,9.37783 -0.0625,1.125 -2.03125,0.53125 -2,0 0,0 0.37822,-6.87064 -0.545251,-9.547025 z"
|
||||
transform="matrix(-0.4093677,0,0,0.4456703,13.04224,-1.0968812)"
|
||||
id="path6332"
|
||||
style="opacity:0.14117647;fill:url(#linearGradient2578);fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter6251)" />
|
||||
<path
|
||||
d="m 13.876557,17.722122 0.124999,-7.5 c 0,-9.8763728 18.6875,-10.6764 18.6875,0.875 l 0,6.875"
|
||||
transform="matrix(0.459148,0,0,0.4456703,-0.021657,0.2462079)"
|
||||
id="path5675"
|
||||
style="opacity:0.62352941;fill:none;stroke:white;stroke-width:4.42126894;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter5745);enable-background:accumulate" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 12 KiB |
BIN
icons/microphone.png
Normal file
After Width: | Height: | Size: 199 B |
BIN
icons/network.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
icons/offline_tx.png
Normal file
After Width: | Height: | Size: 463 B |
BIN
icons/preferences.png
Normal file
After Width: | Height: | Size: 57 KiB |
686
icons/preferences.svg
Normal file
|
@ -0,0 +1,686 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:ns="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="512px"
|
||||
height="512px"
|
||||
id="svg4289"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.45"
|
||||
sodipodi:docbase="https://commons.wikimedia.org/wiki/File:Gnome-preferences-system.svg"
|
||||
sodipodi:docname="preferences-system.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
viewBox="0 0 48 48">
|
||||
<defs
|
||||
id="defs4291">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6998">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop7000" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop7002" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5443">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5445" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5447" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5437">
|
||||
<stop
|
||||
style="stop-color:#2e3436;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop5439" />
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop5441" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient6791">
|
||||
<stop
|
||||
id="stop6793"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop6795"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient6707">
|
||||
<stop
|
||||
id="stop6709"
|
||||
offset="0"
|
||||
style="stop-color:#888a85;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop6711"
|
||||
offset="1"
|
||||
style="stop-color:#555753;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6696">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6698" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6700" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6576">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6578" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6580" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient6545">
|
||||
<stop
|
||||
style="stop-color:#d3d7cf;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop6547" />
|
||||
<stop
|
||||
style="stop-color:#eeeeec;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop6549" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient6525">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6527" />
|
||||
<stop
|
||||
style="stop-color:#babdb6;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop6529" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6424">
|
||||
<stop
|
||||
style="stop-color:#eeeeec;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop6426" />
|
||||
<stop
|
||||
style="stop-color:#eeeeec;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6428" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5440">
|
||||
<stop
|
||||
id="stop5442"
|
||||
offset="0"
|
||||
style="stop-color:#eeeeec;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop5444"
|
||||
offset="1"
|
||||
style="stop-color:#a2a298;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5402">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5404" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5406" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2808">
|
||||
<stop
|
||||
id="stop2810"
|
||||
offset="0"
|
||||
style="stop-color:white;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop2812"
|
||||
offset="1"
|
||||
style="stop-color:white;stop-opacity:0.2937853" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient6221">
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop6223" />
|
||||
<stop
|
||||
style="stop-color:black;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop6225" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5220">
|
||||
<stop
|
||||
style="stop-color:#0c1d35;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop5222" />
|
||||
<stop
|
||||
style="stop-color:white;stop-opacity:0.2937853"
|
||||
offset="1"
|
||||
id="stop5224" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5210">
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop5212" />
|
||||
<stop
|
||||
style="stop-color:#295ead;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop5214" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6221"
|
||||
id="radialGradient6819"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.982963,0,0,0.508943,0.37414,16.84139)"
|
||||
cx="21.96048"
|
||||
cy="34.498356"
|
||||
fx="21.96048"
|
||||
fy="34.498356"
|
||||
r="12.727922" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6221"
|
||||
id="radialGradient6821"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.982963,0,0,0.508943,0.37414,16.84139)"
|
||||
cx="21.96048"
|
||||
cy="34.498356"
|
||||
fx="21.96048"
|
||||
fy="34.498356"
|
||||
r="12.727922" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6545"
|
||||
id="linearGradient6823"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="101.75"
|
||||
y1="16.75"
|
||||
x2="84.875"
|
||||
y2="23.5" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6707"
|
||||
id="linearGradient6825"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="101.76143"
|
||||
y1="23.366385"
|
||||
x2="84.3106"
|
||||
y2="40.943737" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6791"
|
||||
id="linearGradient6827"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="99.686363"
|
||||
y1="7.6145449"
|
||||
x2="75.039978"
|
||||
y2="16.260931" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6525"
|
||||
id="linearGradient6829"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="94"
|
||||
y1="43.240894"
|
||||
x2="94"
|
||||
y2="40.766018" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5437"
|
||||
id="linearGradient6831"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.9982232,0,0,1.1271997,101.97505,-16.992011)"
|
||||
x1="-5.7610831"
|
||||
y1="40.212852"
|
||||
x2="-12.691682"
|
||||
y2="44.514675" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6576"
|
||||
id="linearGradient6833"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,-58.460697,73.506628)"
|
||||
x1="93.686363"
|
||||
y1="11.614545"
|
||||
x2="96.311363"
|
||||
y2="3.2395456" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6696"
|
||||
id="linearGradient6835"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="19.5"
|
||||
y1="17.750786"
|
||||
x2="19.5"
|
||||
y2="7.8089299"
|
||||
gradientTransform="translate(-1,-1)" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6221"
|
||||
id="radialGradient6837"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.982963,0,0,0.508943,0.37414,16.84139)"
|
||||
cx="21.96048"
|
||||
cy="34.498356"
|
||||
fx="21.96048"
|
||||
fy="34.498356"
|
||||
r="12.727922" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6221"
|
||||
id="radialGradient6839"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.982963,0,0,0.508943,0.37414,16.84139)"
|
||||
cx="21.96048"
|
||||
cy="34.498356"
|
||||
fx="21.96048"
|
||||
fy="34.498356"
|
||||
r="12.727922" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6998"
|
||||
id="radialGradient7004"
|
||||
cx="24.32572"
|
||||
cy="24.577896"
|
||||
fx="24.32572"
|
||||
fy="24.577896"
|
||||
r="5.140625"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.7495432,-0.7495432,1.8567518,1.8567518,-40.477603,-2.5737503)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5210"
|
||||
id="linearGradient7047"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.8213511,0,0,1.0094537,61.676283,-5.2539543)"
|
||||
x1="-10.69499"
|
||||
y1="41.105709"
|
||||
x2="-1.0492263"
|
||||
y2="41.137775" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5443"
|
||||
id="linearGradient7049"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="53.58926"
|
||||
y1="32.856834"
|
||||
x2="69.976395"
|
||||
y2="44.960426" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5440"
|
||||
id="linearGradient7051"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.7118239,-0.7118239,0.7071068,0.7071068,20.979979,22.298119)"
|
||||
x1="24.518135"
|
||||
y1="22.429499"
|
||||
x2="25.910631"
|
||||
y2="23.831284" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2808"
|
||||
id="linearGradient7053"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.581783,0,0,0.6787466,57.543659,10.506054)"
|
||||
x1="-6.9787297"
|
||||
y1="37.126617"
|
||||
x2="-9.9043236"
|
||||
y2="36.848248" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5220"
|
||||
id="linearGradient7055"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.4887947,0,0,0.6787448,59.055567,10.472634)"
|
||||
x1="-8.9375"
|
||||
y1="40.375"
|
||||
x2="-7"
|
||||
y2="40.375" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5402"
|
||||
id="linearGradient7057"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="57.349243"
|
||||
y1="37.496914"
|
||||
x2="59.350101"
|
||||
y2="37.505516" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient6424"
|
||||
id="linearGradient7059"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="54.5"
|
||||
y1="1.7340142"
|
||||
x2="54.5"
|
||||
y2="7.1931787" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666"
|
||||
borderopacity="0.31372549"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="4"
|
||||
inkscape:cx="40.725752"
|
||||
inkscape:cy="9.5969463"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:grid-bbox="false"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="897"
|
||||
inkscape:window-height="925"
|
||||
inkscape:window-x="88"
|
||||
inkscape:window-y="25"
|
||||
inkscape:showpageshadow="false"
|
||||
gridspacingx="0.5px"
|
||||
gridspacingy="0.5px"
|
||||
gridempspacing="2"
|
||||
inkscape:grid-points="false"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
showborder="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid5999" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata4294">
|
||||
<rdf:RDF>
|
||||
<ns:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>System Preferences</dc:title>
|
||||
<dc:creator>
|
||||
<ns:Agent>
|
||||
<dc:title>Andreas Nilsson</dc:title>
|
||||
</ns:Agent>
|
||||
</dc:creator>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>category</rdf:li>
|
||||
<rdf:li>system</rdf:li>
|
||||
<rdf:li>preferences</rdf:li>
|
||||
<rdf:li>settings</rdf:li>
|
||||
<rdf:li>control center</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<dc:contributor>
|
||||
<ns:Agent>
|
||||
<dc:title>Jakub Steiner
|
||||
Ulisse Perusin</dc:title>
|
||||
</ns:Agent>
|
||||
</dc:contributor>
|
||||
<ns:license
|
||||
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
|
||||
</ns:Work>
|
||||
<ns:License
|
||||
rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
|
||||
<ns:permits
|
||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<ns:permits
|
||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<ns:requires
|
||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<ns:permits
|
||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
<ns:requires
|
||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
<ns:requires
|
||||
rdf:resource="http://web.resource.org/cc/SourceCode" />
|
||||
</ns:License>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>Preferences</dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Andreas Nilsson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>Lapo Calamandrei, Ulisse Perusin, Jakub Steiner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>category</rdf:li>
|
||||
<rdf:li>system</rdf:li>
|
||||
<rdf:li>preferences</rdf:li>
|
||||
<rdf:li>settings</rdf:li>
|
||||
<rdf:li>control center</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/SourceCode" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:0.15;fill:url(#radialGradient6839);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path5331"
|
||||
sodipodi:cx="21.743534"
|
||||
sodipodi:cy="34.299805"
|
||||
sodipodi:rx="12.727922"
|
||||
sodipodi:ry="6.3639612"
|
||||
d="M 34.471457 34.299805 A 12.727922 6.3639612 0 1 1 9.0156116,34.299805 A 12.727922 6.3639612 0 1 1 34.471457 34.299805 z"
|
||||
transform="matrix(0.9035244,0,0,0.6241817,-8.1457785,20.562958)" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:0.2;fill:url(#radialGradient6837);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path6769"
|
||||
sodipodi:cx="21.743534"
|
||||
sodipodi:cy="34.299805"
|
||||
sodipodi:rx="12.727922"
|
||||
sodipodi:ry="6.3639612"
|
||||
d="M 34.471457 34.299805 A 12.727922 6.3639612 0 1 1 9.0156116,34.299805 A 12.727922 6.3639612 0 1 1 34.471457 34.299805 z"
|
||||
transform="matrix(0.3535525,0,0,0.2357023,2.8125306,34.415459)" />
|
||||
<g
|
||||
id="g6432"
|
||||
transform="matrix(0.7071068,0.7071068,-0.7071068,0.7071068,0.4039197,-30.117395)">
|
||||
<rect
|
||||
transform="matrix(0.9999917,-4.085772e-3,-2.7048962e-3,0.9999963,0,0)"
|
||||
ry="3.6587055"
|
||||
rx="4.0743828"
|
||||
y="27.726946"
|
||||
x="50.588039"
|
||||
height="17.996519"
|
||||
width="8.9973431"
|
||||
id="rect5288"
|
||||
style="fill:url(#linearGradient7047);fill-opacity:1;stroke:#204a87;stroke-width:1.0000124;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
transform="matrix(0.9999873,-5.0480452e-3,-2.8992949e-3,0.9999958,0,0)"
|
||||
ry="2.5968282"
|
||||
rx="3.0795631"
|
||||
y="28.815769"
|
||||
x="51.574001"
|
||||
height="15.960262"
|
||||
width="7.0178103"
|
||||
id="rect5292"
|
||||
style="opacity:0.5;fill:none;fill-opacity:1;stroke:url(#linearGradient7049);stroke-width:1.00001645;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
id="path5286"
|
||||
d="M 52.246834,0.49999993 L 52.604531,5.4548034 L 53.59322,7.162543 L 53.585977,28.755101 C 53.674365,30.257703 56.419206,30.336084 56.595983,28.745094 L 56.621068,7.1748733 L 57.628707,5.8770552 L 57.95997,0.51454306 C 57.95997,0.51454306 52.246834,0.49999993 52.246834,0.49999993 z "
|
||||
style="fill:url(#linearGradient7051);fill-opacity:1;stroke:#888a85;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
style="opacity:0.3;fill:url(#linearGradient7053);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect2804"
|
||||
width="1.4200811"
|
||||
height="10.612979"
|
||||
x="51.725819"
|
||||
y="32.225933"
|
||||
rx="0.6661315"
|
||||
ry="1.6036282"
|
||||
transform="matrix(0.9999908,-4.299452e-3,-4.299452e-3,0.9999908,0,0)" />
|
||||
<rect
|
||||
transform="matrix(0.9999869,-5.11738e-3,-3.6122511e-3,0.9999935,0,0)"
|
||||
ry="1.6036212"
|
||||
rx="1.3473127"
|
||||
y="32.192463"
|
||||
x="54.167618"
|
||||
height="10.859921"
|
||||
width="1.9551785"
|
||||
id="rect5290"
|
||||
style="opacity:0.3;fill:url(#linearGradient7055);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
style="opacity:0.25;fill:url(#linearGradient7057);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect5398"
|
||||
width="1.420082"
|
||||
height="10.612979"
|
||||
x="57.132236"
|
||||
y="32.24918"
|
||||
rx="0.6661315"
|
||||
ry="1.603629"
|
||||
transform="matrix(0.9999908,-4.2994573e-3,-4.2994573e-3,0.9999908,0,0)" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
id="path5450"
|
||||
d="M 52.78125,1 L 53.09375,5.3125 L 54.03125,6.90625 C 54.073567,6.982692 54.095116,7.0688875 54.09375,7.15625 L 56.125,7.1875 C 56.120433,7.0757816 56.153441,6.9657558 56.21875,6.875 L 57.125,5.65625 L 57.4375,1 C 56.652768,1 53.565982,1 52.78125,1 z "
|
||||
style="fill:url(#linearGradient7059);fill-opacity:1;stroke:none;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" />
|
||||
</g>
|
||||
<path
|
||||
style="opacity:0.5;fill:url(#radialGradient7004);fill-opacity:1;stroke:none;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 25.96875,19.46875 L 18.46875,26.96875 L 21.25,29.75 L 28.75,22.25 L 25.96875,19.46875 z "
|
||||
id="path6010" />
|
||||
<g
|
||||
id="g6807"
|
||||
transform="translate(-1,0)">
|
||||
<path
|
||||
transform="matrix(0.8642397,0,0,0.6241817,18.208399,20.562958)"
|
||||
d="M 34.471457 34.299805 A 12.727922 6.3639612 0 1 1 9.0156116,34.299805 A 12.727922 6.3639612 0 1 1 34.471457 34.299805 z"
|
||||
sodipodi:ry="6.3639612"
|
||||
sodipodi:rx="12.727922"
|
||||
sodipodi:cy="34.299805"
|
||||
sodipodi:cx="21.743534"
|
||||
id="path6765"
|
||||
style="opacity:0.15;fill:url(#radialGradient6819);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="matrix(0.3535525,0,0,0.2357023,29.812531,34.415459)"
|
||||
d="M 34.471457 34.299805 A 12.727922 6.3639612 0 1 1 9.0156116,34.299805 A 12.727922 6.3639612 0 1 1 34.471457 34.299805 z"
|
||||
sodipodi:ry="6.3639612"
|
||||
sodipodi:rx="12.727922"
|
||||
sodipodi:cy="34.299805"
|
||||
sodipodi:cx="21.743534"
|
||||
id="path6773"
|
||||
style="opacity:0.2;fill:url(#radialGradient6821);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
sodipodi:type="arc" />
|
||||
<g
|
||||
transform="translate(-1.697983,0.2707704)"
|
||||
id="g6739">
|
||||
<g
|
||||
id="g6553"
|
||||
transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,-57.460697,74.506628)">
|
||||
<path
|
||||
sodipodi:nodetypes="csccsccscccccc"
|
||||
id="path6491"
|
||||
d="M 91,1.1482865 C 88.356663,2.3083638 86.5,4.9532014 86.5,8.0232865 C 86.5,10.894407 88.12854,13.387995 90.5,14.648286 L 90.5,43.414214 C 90.5,45.353214 92.061,46.914213 94,46.914214 C 95.939,46.914214 97.5,45.353213 97.5,43.414214 L 97.5,14.648286 C 99.87146,13.387995 101.5,10.894407 101.5,8.0232865 C 101.5,4.9532011 99.643337,2.3083637 97,1.1482865 L 97,7.0857865 L 95.28125,9.0857865 L 92.71875,9.0857865 L 91,7.0857865 L 91,1.1482865 z "
|
||||
style="opacity:1;fill:url(#linearGradient6823);fill-opacity:1;stroke:url(#linearGradient6825);stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.7;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cscccscccscccccccccc"
|
||||
id="path6505"
|
||||
d="M 89.96875,2.9920365 C 88.491165,4.1803215 87.53125,5.9777353 87.53125,8.0232865 C 87.53125,10.510038 88.917637,12.651991 90.96875,13.742036 C 91.312399,13.913596 91.530012,14.264195 91.53125,14.648286 L 91.53125,43.414214 C 91.53125,44.807674 92.606539,45.882963 94,45.882964 C 95.39346,45.882964 96.46875,44.807673 96.46875,43.414214 L 96.46875,14.648286 C 96.469988,14.264195 96.687601,13.913596 97.03125,13.742036 C 99.082363,12.651991 100.46875,10.510038 100.46875,8.0232865 C 100.46875,5.977735 99.508835,4.1803214 98.03125,2.9920365 L 98.03125,7.0857865 C 98.028519,7.3272888 97.939894,7.5599296 97.78125,7.7420365 L 96.0625,9.7420365 C 95.871073,9.9773335 95.584572,10.114853 95.28125,10.117036 L 92.71875,10.117036 C 92.415428,10.114853 92.128927,9.9773335 91.9375,9.7420365 L 90.21875,7.7420365 C 90.060106,7.5599296 89.971481,7.3272888 89.96875,7.0857865 L 89.96875,2.9920365 z "
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:url(#linearGradient6827);stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0.7;stroke-opacity:1" />
|
||||
<path
|
||||
transform="translate(-3.7626907e-8,0.9142136)"
|
||||
d="M 95.5 42.5 A 1.5 1.5 0 1 1 92.5,42.5 A 1.5 1.5 0 1 1 95.5 42.5 z"
|
||||
sodipodi:ry="1.5"
|
||||
sodipodi:rx="1.5"
|
||||
sodipodi:cy="42.5"
|
||||
sodipodi:cx="94"
|
||||
id="path6507"
|
||||
style="opacity:1;fill:#888a85;fill-opacity:1;stroke:url(#linearGradient6829);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.7;stroke-opacity:1"
|
||||
sodipodi:type="arc" />
|
||||
<rect
|
||||
style="opacity:0.23106061;fill:url(#linearGradient6831);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
|
||||
id="rect6533"
|
||||
width="3.9928944"
|
||||
height="21.999802"
|
||||
x="91.992836"
|
||||
y="16.963778"
|
||||
rx="1.7379364"
|
||||
ry="1.7444341"
|
||||
transform="matrix(0.9999999,3.8645919e-4,3.8358553e-4,0.9999999,0,0)" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:url(#linearGradient6833);stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0.7;stroke-opacity:1"
|
||||
d="M 13.973556,7.3037539 L 16.868274,10.198472 C 17.037111,10.371171 17.138946,10.598341 17.155536,10.839288 L 17.35441,13.468841 C 17.385431,13.770581 17.280086,14.070409 17.067148,14.286434 L 15.255187,16.098395 C 15.039162,16.311332 14.739334,16.416678 14.437595,16.385657 L 11.808041,16.186783 C 11.567094,16.170192 11.339925,16.068358 11.167226,15.899521 L 8.2725073,13.004802"
|
||||
id="path6573"
|
||||
sodipodi:nodetypes="cccccccccc" />
|
||||
<path
|
||||
style="opacity:0.59051723;fill:url(#linearGradient6835);fill-opacity:1;stroke:none;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0.7;stroke-opacity:1"
|
||||
d="M 14.71875,6.8125 C 14.129935,6.8140249 13.543329,6.8880281 12.96875,7.03125 L 16.5,10.5625 C 16.589624,10.650873 16.646088,10.749545 16.65625,10.875 L 16.875,13.5 C 16.888638,13.656013 16.830347,13.827626 16.71875,13.9375 L 15.125,15.5625 C 17.279079,16.073694 19.038866,17.020591 21.34375,15.78125 C 22.074648,13.392376 21.483569,10.671069 19.59375,8.78125 C 18.245921,7.4334204 16.485196,6.8079254 14.71875,6.8125 z M 8,12 C 7.6061401,13.580092 7.7314214,15.26324 8.4375,16.75 C 9.564272,16.068398 10.560695,15.675078 11.46875,15.46875 L 8,12 z "
|
||||
id="path6651"
|
||||
sodipodi:nodetypes="ccccccccsccccc" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 26 KiB |
BIN
icons/qrcode.png
Normal file
After Width: | Height: | Size: 314 B |
BIN
icons/qrcode_white.png
Normal file
After Width: | Height: | Size: 380 B |
BIN
icons/revealer.png
Normal file
After Width: | Height: | Size: 272 B |
BIN
icons/revealer_c.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
icons/safe-t.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
icons/safe-t_unpaired.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
icons/seal.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
icons/seed.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
icons/speaker.png
Normal file
After Width: | Height: | Size: 392 B |
BIN
icons/status_connected.png
Normal file
After Width: | Height: | Size: 69 KiB |
173
icons/status_connected.svg
Normal file
|
@ -0,0 +1,173 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.0"
|
||||
id="svg7854"
|
||||
height="512"
|
||||
width="512"
|
||||
viewBox="9 9 30 30">
|
||||
<defs
|
||||
id="defs7856">
|
||||
<linearGradient
|
||||
id="linearGradient860">
|
||||
<stop
|
||||
id="stop856"
|
||||
offset="0"
|
||||
style="stop-color:#90bb65;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop858"
|
||||
offset="1"
|
||||
style="stop-color:#6ac017;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient7577">
|
||||
<stop
|
||||
id="stop7579"
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:0.3137255;" />
|
||||
<stop
|
||||
id="stop7581"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5167">
|
||||
<stop
|
||||
style="stop-color:#76d717;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop5169" />
|
||||
<stop
|
||||
style="stop-color:#509e07;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop5171" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5184">
|
||||
<stop
|
||||
style="stop-color:white;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5186" />
|
||||
<stop
|
||||
style="stop-color:white;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5188" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="matrix(2.1074616,0,0,2.1078593,-9.43551,-10.006786)"
|
||||
y2="17.024479"
|
||||
x2="16.657505"
|
||||
y1="10.883683"
|
||||
x1="15.011773"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient8317"
|
||||
xlink:href="#linearGradient7577" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(1.897257,0,0,1.897615,-6.10046,-6.6146433)"
|
||||
r="7.5896134"
|
||||
fy="20.410854"
|
||||
fx="15.865708"
|
||||
cy="20.410854"
|
||||
cx="15.865708"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient8319"
|
||||
xlink:href="#linearGradient5167" />
|
||||
<radialGradient
|
||||
r="5.96875"
|
||||
fy="11.308558"
|
||||
fx="14.05685"
|
||||
cy="11.308558"
|
||||
cx="14.05685"
|
||||
gradientTransform="matrix(-4.2002315,0.5953403,0.2958442,2.0989386,75.31118,-18.732928)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient8321"
|
||||
xlink:href="#linearGradient5184" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1.7591324,0,0,1.7580929,-3.90899,-4.3562887)"
|
||||
y2="26.431587"
|
||||
x2="13.458839"
|
||||
y1="2.0178134"
|
||||
x1="8.9317284"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient8323"
|
||||
xlink:href="#linearGradient860" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7859">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Lapo Calamandrei</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:source />
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
|
||||
<dc:title></dc:title>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>record</rdf:li>
|
||||
<rdf:li>media</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Steiner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/SourceCode" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1">
|
||||
<ellipse
|
||||
ry="14.997972"
|
||||
rx="14.995141"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.4;fill:url(#linearGradient8317);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.11079514;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
|
||||
id="path7691"
|
||||
cx="24.00086"
|
||||
cy="24.002029" />
|
||||
<ellipse
|
||||
ry="13.502028"
|
||||
rx="13.49948"
|
||||
cy="24.002029"
|
||||
cx="24.000866"
|
||||
id="path7968"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient8319);fill-opacity:1;fill-rule:nonzero;stroke:#336402;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none" />
|
||||
<path
|
||||
id="path7970"
|
||||
d="M 25.3861,13.485003 C 20.31979,12.724926 15.45183,15.857848 14,20.764516 c 1.18871,3.18039 3.90811,5.70993 7.46677,6.47724 5.29459,1.141602 10.50115,-2.027543 12.01505,-7.143895 -1.18869,-3.180413 -3.90812,-5.709952 -7.46675,-6.477239 -0.217,-0.04678 -0.41248,-0.103152 -0.62897,-0.135619 z"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.404;fill:url(#radialGradient8321);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.09465754;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none" />
|
||||
<ellipse
|
||||
ry="12.509292"
|
||||
rx="12.516688"
|
||||
cy="24.009293"
|
||||
cx="24.000891"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.54494413;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient8323);stroke-width:1.00000215;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
|
||||
id="path7972" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.4 KiB |
BIN
icons/status_connected_fork.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
icons/status_connected_proxy.png
Normal file
After Width: | Height: | Size: 68 KiB |
173
icons/status_connected_proxy.svg
Normal file
|
@ -0,0 +1,173 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.0"
|
||||
id="svg7854"
|
||||
height="512"
|
||||
width="512"
|
||||
viewBox="9 9 30 30">
|
||||
<defs
|
||||
id="defs7856">
|
||||
<linearGradient
|
||||
id="linearGradient860">
|
||||
<stop
|
||||
id="stop856"
|
||||
offset="0"
|
||||
style="stop-color:#479fc6;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop858"
|
||||
offset="1"
|
||||
style="stop-color:#0c89c1;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient7577">
|
||||
<stop
|
||||
id="stop7579"
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:0.3137255;" />
|
||||
<stop
|
||||
id="stop7581"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5167">
|
||||
<stop
|
||||
style="stop-color:#0090ef;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop5169" />
|
||||
<stop
|
||||
style="stop-color:#0062b2;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop5171" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5184">
|
||||
<stop
|
||||
style="stop-color:white;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5186" />
|
||||
<stop
|
||||
style="stop-color:white;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5188" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="matrix(2.1074616,0,0,2.1078593,-9.43551,-10.006786)"
|
||||
y2="17.024479"
|
||||
x2="16.657505"
|
||||
y1="10.883683"
|
||||
x1="15.011773"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient8317"
|
||||
xlink:href="#linearGradient7577" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(1.897257,0,0,1.897615,-6.10046,-6.6146433)"
|
||||
r="7.5896134"
|
||||
fy="20.410854"
|
||||
fx="15.865708"
|
||||
cy="20.410854"
|
||||
cx="15.865708"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient8319"
|
||||
xlink:href="#linearGradient5167" />
|
||||
<radialGradient
|
||||
r="5.96875"
|
||||
fy="11.308558"
|
||||
fx="14.05685"
|
||||
cy="11.308558"
|
||||
cx="14.05685"
|
||||
gradientTransform="matrix(-4.2002315,0.5953403,0.2958442,2.0989386,75.31118,-18.732928)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient8321"
|
||||
xlink:href="#linearGradient5184" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1.7591324,0,0,1.7580929,-3.90899,-4.3562887)"
|
||||
y2="26.431587"
|
||||
x2="13.458839"
|
||||
y1="2.0178134"
|
||||
x1="8.9317284"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient8323"
|
||||
xlink:href="#linearGradient860" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7859">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Lapo Calamandrei</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:source />
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
|
||||
<dc:title></dc:title>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>record</rdf:li>
|
||||
<rdf:li>media</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Steiner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/SourceCode" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1">
|
||||
<ellipse
|
||||
ry="14.997972"
|
||||
rx="14.995141"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.4;fill:url(#linearGradient8317);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.11079514;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
|
||||
id="path7691"
|
||||
cx="24.00086"
|
||||
cy="24.002029" />
|
||||
<ellipse
|
||||
ry="13.502028"
|
||||
rx="13.49948"
|
||||
cy="24.002029"
|
||||
cx="24.000866"
|
||||
id="path7968"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient8319);fill-opacity:1;fill-rule:nonzero;stroke:#003f70;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none" />
|
||||
<path
|
||||
id="path7970"
|
||||
d="M 25.3861,13.485003 C 20.31979,12.724926 15.45183,15.857848 14,20.764516 c 1.18871,3.18039 3.90811,5.70993 7.46677,6.47724 5.29459,1.141602 10.50115,-2.027543 12.01505,-7.143895 -1.18869,-3.180413 -3.90812,-5.709952 -7.46675,-6.477239 -0.217,-0.04678 -0.41248,-0.103152 -0.62897,-0.135619 z"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.404;fill:url(#radialGradient8321);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.09465754;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none" />
|
||||
<ellipse
|
||||
ry="12.509292"
|
||||
rx="12.516688"
|
||||
cy="24.009293"
|
||||
cx="24.000891"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.54494413;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient8323);stroke-width:1.00000215;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
|
||||
id="path7972" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.4 KiB |
BIN
icons/status_connected_proxy_fork.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
icons/status_disconnected.png
Normal file
After Width: | Height: | Size: 65 KiB |
293
icons/status_disconnected.svg
Normal file
|
@ -0,0 +1,293 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="9 9 30 30"
|
||||
id="svg7854"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.45"
|
||||
version="1.0"
|
||||
sodipodi:docbase="/home/dobey/Projects/gnome-icon-theme/scalable/actions"
|
||||
sodipodi:docname="media-record.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape"
|
||||
inkscape:export-filename="/home/lapo/Desktop/media-icons.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs7856">
|
||||
<linearGradient
|
||||
id="linearGradient7577">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0.3137255;"
|
||||
offset="0"
|
||||
id="stop7579" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop7581" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5167">
|
||||
<stop
|
||||
id="stop5169"
|
||||
offset="0"
|
||||
style="stop-color:#ef2929;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop5171"
|
||||
offset="1"
|
||||
style="stop-color:#c60e0e;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5184"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop5186"
|
||||
offset="0"
|
||||
style="stop-color:white;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop5188"
|
||||
offset="1"
|
||||
style="stop-color:white;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5172"
|
||||
inkscape:collect="always">
|
||||
<stop
|
||||
id="stop5174"
|
||||
offset="0"
|
||||
style="stop-color:white;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop5176"
|
||||
offset="1"
|
||||
style="stop-color:white;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient7577"
|
||||
id="linearGradient8317"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="15.011773"
|
||||
y1="10.883683"
|
||||
x2="16.657505"
|
||||
y2="17.024479" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5167"
|
||||
id="radialGradient8319"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="15.865708"
|
||||
cy="20.410854"
|
||||
fx="15.865708"
|
||||
fy="20.410854"
|
||||
r="7.5896134" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5184"
|
||||
id="radialGradient8321"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-4.2002315,0.5953403,0.2958442,2.0989386,-274.68882,-18.732928)"
|
||||
cx="14.05685"
|
||||
cy="11.308558"
|
||||
fx="14.05685"
|
||||
fy="11.308558"
|
||||
r="5.96875" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5172"
|
||||
id="linearGradient8323"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="8.9317284"
|
||||
y1="2.0178134"
|
||||
x2="13.458839"
|
||||
y2="26.431587" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#afafaf"
|
||||
borderopacity="1"
|
||||
gridtolerance="10000"
|
||||
guidetolerance="10"
|
||||
objecttolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="-137.53856"
|
||||
inkscape:cy="10.827794"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
width="48px"
|
||||
height="48px"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:window-width="872"
|
||||
inkscape:window-height="971"
|
||||
inkscape:window-x="117"
|
||||
inkscape:window-y="27"
|
||||
showgrid="false"
|
||||
gridspacingx="0.5px"
|
||||
gridspacingy="0.5px"
|
||||
gridempspacing="2"
|
||||
inkscape:grid-points="true"
|
||||
showborder="true"
|
||||
showguides="false"
|
||||
inkscape:guide-bbox="true"
|
||||
borderlayer="true">
|
||||
<sodipodi:guide
|
||||
orientation="horizontal"
|
||||
position="13.125"
|
||||
id="guide7377" />
|
||||
<sodipodi:guide
|
||||
orientation="horizontal"
|
||||
position="5.4800776"
|
||||
id="guide7379" />
|
||||
<sodipodi:guide
|
||||
orientation="horizontal"
|
||||
position="35"
|
||||
id="guide7492" />
|
||||
<sodipodi:guide
|
||||
orientation="horizontal"
|
||||
position="48"
|
||||
id="guide7046" />
|
||||
<sodipodi:guide
|
||||
orientation="horizontal"
|
||||
position="-17.5"
|
||||
id="guide7233" />
|
||||
<sodipodi:guide
|
||||
orientation="horizontal"
|
||||
position="-29"
|
||||
id="guide7235" />
|
||||
<sodipodi:guide
|
||||
orientation="horizontal"
|
||||
position="22.097087"
|
||||
id="guide7556" />
|
||||
<sodipodi:guide
|
||||
orientation="vertical"
|
||||
position="-76.125"
|
||||
id="guide7644" />
|
||||
<sodipodi:guide
|
||||
orientation="vertical"
|
||||
position="-26.125"
|
||||
id="guide7646" />
|
||||
<sodipodi:guide
|
||||
orientation="vertical"
|
||||
position="24"
|
||||
id="guide7648" />
|
||||
<sodipodi:guide
|
||||
orientation="vertical"
|
||||
position="-125.28125"
|
||||
id="guide7665" />
|
||||
<sodipodi:guide
|
||||
orientation="vertical"
|
||||
position="-175.125"
|
||||
id="guide7667" />
|
||||
<sodipodi:guide
|
||||
orientation="vertical"
|
||||
position="-225.83223"
|
||||
id="guide7685" />
|
||||
<sodipodi:guide
|
||||
orientation="vertical"
|
||||
position="-326.06462"
|
||||
id="guide7695" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7859">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Lapo Calamandrei</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:source />
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
|
||||
<dc:title>Record</dc:title>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>record</rdf:li>
|
||||
<rdf:li>media</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Steiner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/SourceCode" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g7170"
|
||||
transform="translate(350,0)">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:0.4;color:#000000;fill:url(#linearGradient8317);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52702755;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
id="path7691"
|
||||
sodipodi:cx="15.865708"
|
||||
sodipodi:cy="16.134291"
|
||||
sodipodi:rx="7.115262"
|
||||
sodipodi:ry="7.115262"
|
||||
d="M 22.98097 16.134291 A 7.115262 7.115262 0 1 1 8.7504463,16.134291 A 7.115262 7.115262 0 1 1 22.98097 16.134291 z"
|
||||
transform="matrix(2.1074616,0,0,2.1078593,-359.43551,-10.006786)" />
|
||||
<g
|
||||
id="g7564">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="color:#000000;fill:url(#radialGradient8319);fill-opacity:1;fill-rule:nonzero;stroke:#a40000;stroke-width:0.52702755;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
id="path7968"
|
||||
sodipodi:cx="15.865708"
|
||||
sodipodi:cy="16.134291"
|
||||
sodipodi:rx="7.115262"
|
||||
sodipodi:ry="7.115262"
|
||||
d="M 22.98097 16.134291 A 7.115262 7.115262 0 1 1 8.7504463,16.134291 A 7.115262 7.115262 0 1 1 22.98097 16.134291 z"
|
||||
transform="matrix(1.897257,0,0,1.897615,-356.10046,-6.6146433)" />
|
||||
<path
|
||||
style="opacity:0.64044949;color:#000000;fill:url(#radialGradient8321);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.09465754;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
d="M -324.6139,13.485003 C -329.68021,12.724926 -334.54817,15.857848 -336,20.764516 C -334.81129,23.944906 -332.09189,26.474446 -328.53323,27.241756 C -323.23864,28.383358 -318.03208,25.214213 -316.51818,20.097861 C -317.70687,16.917448 -320.4263,14.387909 -323.98493,13.620622 C -324.20193,13.573837 -324.39741,13.51747 -324.6139,13.485003 z "
|
||||
id="path7970" />
|
||||
<path
|
||||
transform="matrix(1.7591324,0,0,1.7580929,-353.90899,-4.3562887)"
|
||||
d="M 22.98097 16.134291 A 7.115262 7.115262 0 1 1 8.7504463,16.134291 A 7.115262 7.115262 0 1 1 22.98097 16.134291 z"
|
||||
sodipodi:ry="7.115262"
|
||||
sodipodi:rx="7.115262"
|
||||
sodipodi:cy="16.134291"
|
||||
sodipodi:cx="15.865708"
|
||||
id="path7972"
|
||||
style="opacity:0.54494413;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient8323);stroke-width:0.56863129;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 10 KiB |
BIN
icons/status_lagging.png
Normal file
After Width: | Height: | Size: 73 KiB |
173
icons/status_lagging.svg
Normal file
|
@ -0,0 +1,173 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.0"
|
||||
id="svg7854"
|
||||
height="512"
|
||||
width="512"
|
||||
viewBox="9 9 30 30">
|
||||
<defs
|
||||
id="defs7856">
|
||||
<linearGradient
|
||||
id="linearGradient860">
|
||||
<stop
|
||||
id="stop856"
|
||||
offset="0"
|
||||
style="stop-color:#ef9d29;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop858"
|
||||
offset="1"
|
||||
style="stop-color:#c67f0e;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient7577">
|
||||
<stop
|
||||
id="stop7579"
|
||||
offset="0"
|
||||
style="stop-color:#000000;stop-opacity:0.3137255;" />
|
||||
<stop
|
||||
id="stop7581"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5167">
|
||||
<stop
|
||||
style="stop-color:#ef9a29;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop5169" />
|
||||
<stop
|
||||
style="stop-color:#a6600c;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop5171" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5184">
|
||||
<stop
|
||||
style="stop-color:white;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5186" />
|
||||
<stop
|
||||
style="stop-color:white;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5188" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="matrix(2.1074616,0,0,2.1078593,-9.43551,-10.006786)"
|
||||
y2="17.024479"
|
||||
x2="16.657505"
|
||||
y1="10.883683"
|
||||
x1="15.011773"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient8317"
|
||||
xlink:href="#linearGradient7577" />
|
||||
<radialGradient
|
||||
gradientTransform="matrix(1.897257,0,0,1.897615,-6.10046,-6.6146433)"
|
||||
r="7.5896134"
|
||||
fy="20.410854"
|
||||
fx="15.865708"
|
||||
cy="20.410854"
|
||||
cx="15.865708"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient8319"
|
||||
xlink:href="#linearGradient5167" />
|
||||
<radialGradient
|
||||
r="5.96875"
|
||||
fy="11.308558"
|
||||
fx="14.05685"
|
||||
cy="11.308558"
|
||||
cx="14.05685"
|
||||
gradientTransform="matrix(-4.2002315,0.5953403,0.2958442,2.0989386,75.31118,-18.732928)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="radialGradient8321"
|
||||
xlink:href="#linearGradient5184" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1.7591324,0,0,1.7580929,-3.90899,-4.3562887)"
|
||||
y2="26.431587"
|
||||
x2="13.458839"
|
||||
y1="2.0178134"
|
||||
x1="8.9317284"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient8323"
|
||||
xlink:href="#linearGradient860" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7859">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Lapo Calamandrei</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:source />
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
|
||||
<dc:title></dc:title>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>record</rdf:li>
|
||||
<rdf:li>media</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Steiner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/SourceCode" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1">
|
||||
<ellipse
|
||||
ry="14.997972"
|
||||
rx="14.995141"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.4;fill:url(#linearGradient8317);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.11079514;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
|
||||
id="path7691"
|
||||
cx="24.00086"
|
||||
cy="24.002029" />
|
||||
<ellipse
|
||||
ry="13.502028"
|
||||
rx="13.49948"
|
||||
cy="24.002029"
|
||||
cx="24.000866"
|
||||
id="path7968"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:url(#radialGradient8319);fill-opacity:1.0;fill-rule:nonzero;stroke:#8e5700;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none" />
|
||||
<path
|
||||
id="path7970"
|
||||
d="M 25.3861,13.485003 C 20.31979,12.724926 15.45183,15.857848 14,20.764516 c 1.18871,3.18039 3.90811,5.70993 7.46677,6.47724 5.29459,1.141602 10.50115,-2.027543 12.01505,-7.143895 -1.18869,-3.180413 -3.90812,-5.709952 -7.46675,-6.477239 -0.217,-0.04678 -0.41248,-0.103152 -0.62897,-0.135619 z"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.404;fill:url(#radialGradient8321);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.09465754;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none" />
|
||||
<ellipse
|
||||
ry="12.509292"
|
||||
rx="12.516688"
|
||||
cy="24.009293"
|
||||
cx="24.000891"
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.54494413;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient8323);stroke-width:1.00000215;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none"
|
||||
id="path7972" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.4 KiB |
BIN
icons/status_lagging_fork.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
icons/status_waiting.png
Normal file
After Width: | Height: | Size: 79 KiB |
398
icons/status_waiting.svg
Normal file
|
@ -0,0 +1,398 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
inkscape:export-ydpi="90.000000"
|
||||
inkscape:export-xdpi="90.000000"
|
||||
inkscape:export-filename="c:\Tango\git\view-refresh.png"
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 48 48"
|
||||
id="svg11300"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.45"
|
||||
sodipodi:docbase="/home/dobey/Projects/gnome-icon-theme/scalable/actions"
|
||||
sodipodi:docname="view-refresh.svg"
|
||||
version="1.0"
|
||||
inkscape:r_cx="true"
|
||||
inkscape:r_cy="true"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs3">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient5335">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop5337" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop5339" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient5313">
|
||||
<stop
|
||||
id="stop5315"
|
||||
offset="0"
|
||||
style="stop-color:#99b8df;stop-opacity:1" />
|
||||
<stop
|
||||
style="stop-color:#3969a8;stop-opacity:1;"
|
||||
offset="0.23705086"
|
||||
id="stop5333" />
|
||||
<stop
|
||||
style="stop-color:#4f7eba;stop-opacity:1;"
|
||||
offset="0.54706067"
|
||||
id="stop5317" />
|
||||
<stop
|
||||
id="stop5321"
|
||||
offset="0.74557692"
|
||||
style="stop-color:#96b6d7;stop-opacity:1" />
|
||||
<stop
|
||||
style="stop-color:#a0bddc;stop-opacity:1"
|
||||
offset="0.87321436"
|
||||
id="stop5331" />
|
||||
<stop
|
||||
id="stop5319"
|
||||
offset="1"
|
||||
style="stop-color:#729fcf;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient8152">
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop8154" />
|
||||
<stop
|
||||
id="stop3174"
|
||||
offset="0.5"
|
||||
style="stop-color:#4f7eba;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#729fcf;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop8156" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3207">
|
||||
<stop
|
||||
style="stop-color:#eeeeec;stop-opacity:0.47058824;"
|
||||
offset="0"
|
||||
id="stop3209" />
|
||||
<stop
|
||||
style="stop-color:#eeeeec;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3211" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient2847">
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2849" />
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2851" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2831">
|
||||
<stop
|
||||
style="stop-color:#3465a4;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop2833" />
|
||||
<stop
|
||||
id="stop2855"
|
||||
offset="0.33333334"
|
||||
style="stop-color:#5b86be;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#83a8d8;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop2835" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient8662">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop8664" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop8666" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2831"
|
||||
id="linearGradient1486"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.0818662,0,0,1.1166851,-0.8207482,-1.8622434)"
|
||||
x1="13.478554"
|
||||
y1="10.612206"
|
||||
x2="15.419417"
|
||||
y2="19.115122" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2847"
|
||||
id="linearGradient1488"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-1.0818662,0,0,-1.1166851,50.09459,49.644854)"
|
||||
x1="37.128052"
|
||||
y1="29.729605"
|
||||
x2="37.40255"
|
||||
y2="26.800913" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient8662"
|
||||
id="radialGradient1503"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,0.536723,0,16.87306)"
|
||||
cx="24.837126"
|
||||
cy="36.421127"
|
||||
fx="24.837126"
|
||||
fy="36.421127"
|
||||
r="15.644737" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient8152"
|
||||
id="linearGradient8158"
|
||||
x1="49.412277"
|
||||
y1="37.904068"
|
||||
x2="11.881318"
|
||||
y2="19.776045"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2831"
|
||||
id="linearGradient8170"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-1.0818662,0,0,-1.1166851,48.639854,47.862243)"
|
||||
x1="13.478554"
|
||||
y1="10.612206"
|
||||
x2="15.419417"
|
||||
y2="19.115122" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient2847"
|
||||
id="linearGradient8172"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.0818662,0,0,1.1166851,-2.2754847,-3.644854)"
|
||||
x1="37.128052"
|
||||
y1="29.729605"
|
||||
x2="37.40255"
|
||||
y2="26.800913" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient8152"
|
||||
id="linearGradient8174"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="49.412277"
|
||||
y1="37.904068"
|
||||
x2="11.881318"
|
||||
y2="19.776045" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3207"
|
||||
id="linearGradient8178"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="5.8925977"
|
||||
y1="20.540676"
|
||||
x2="45.198921"
|
||||
y2="27.721035" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5313"
|
||||
id="linearGradient8180"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="61.572533"
|
||||
y1="28.049652"
|
||||
x2="10.969182"
|
||||
y2="20.333939" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient5335"
|
||||
id="linearGradient5341"
|
||||
x1="8.6878577"
|
||||
y1="25.265626"
|
||||
x2="52.122673"
|
||||
y2="25.265626"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
stroke="#3465a4"
|
||||
fill="#729fcf"
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#e8e8e8"
|
||||
borderopacity="0.86666667"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="48.628749"
|
||||
inkscape:cy="21.704614"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:showpageshadow="false"
|
||||
inkscape:window-width="892"
|
||||
inkscape:window-height="938"
|
||||
inkscape:window-x="374"
|
||||
inkscape:window-y="37"
|
||||
width="48px"
|
||||
height="48px"
|
||||
borderlayer="true" />
|
||||
<metadata
|
||||
id="metadata4">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Jakub Steiner</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:source>http://jimmac.musichall.cz</dc:source>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
|
||||
<dc:title>View Refresh</dc:title>
|
||||
<dc:subject>
|
||||
<rdf:Bag>
|
||||
<rdf:li>reload</rdf:li>
|
||||
<rdf:li>refresh</rdf:li>
|
||||
<rdf:li>view</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:subject>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>Ricardo 'Rick' González</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/Notice" />
|
||||
<cc:permits
|
||||
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/ShareAlike" />
|
||||
<cc:requires
|
||||
rdf:resource="http://web.resource.org/cc/SourceCode" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:r_cx="true"
|
||||
inkscape:r_cy="true">
|
||||
<path
|
||||
transform="matrix(-1.5146484,0,0,-0.7917058,60.923237,69.528413)"
|
||||
d="M 40.481863 36.421127 A 15.644737 8.3968935 0 1 1 9.1923885,36.421127 A 15.644737 8.3968935 0 1 1 40.481863 36.421127 z"
|
||||
sodipodi:ry="8.3968935"
|
||||
sodipodi:rx="15.644737"
|
||||
sodipodi:cy="36.421127"
|
||||
sodipodi:cx="24.837126"
|
||||
id="path8660"
|
||||
style="opacity:0.36111109;color:#000000;fill:url(#radialGradient1503);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
|
||||
sodipodi:type="arc"
|
||||
inkscape:r_cx="true"
|
||||
inkscape:r_cy="true" />
|
||||
<path
|
||||
style="color:#000000;fill:url(#linearGradient1486);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient1488);stroke-width:1.04300582000000008;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible;opacity:0.51807229"
|
||||
d="M 20.478497,9.7711467 C 20.478497,9.7711467 12.632988,7.9438002 14.368023,21.024298 L 5.1028658,21.024298 C 5.1028658,21.024298 6.0085332,7.5377773 20.478497,9.7711467 z "
|
||||
id="path2865"
|
||||
inkscape:r_cx="true"
|
||||
inkscape:r_cy="true"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<g
|
||||
id="g1878"
|
||||
transform="matrix(-0.6129282,-0.5154381,-0.5178496,0.610074,58.686164,13.911361)"
|
||||
inkscape:r_cx="true"
|
||||
inkscape:r_cy="true"
|
||||
style="fill:url(#linearGradient8158);fill-opacity:1;stroke:#204a87;stroke-width:1.24932528;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
id="path1880"
|
||||
d="M 45.862102,50.273522 C 62.924432,34.96305 47.150241,15.929711 22.760624,12.513943 L 22.113577,3.1522143 L 7.613534,20.510135 L 22.703188,33.23244 C 22.703188,33.23244 22.454828,23.347105 22.454828,23.347105 C 41.289895,24.339584 54.775794,35.675041 45.862102,50.273522 z "
|
||||
style="opacity:1;color:#000000;fill:url(#linearGradient8180);fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:1.24977946000000006;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
|
||||
inkscape:r_cx="true"
|
||||
inkscape:r_cy="true" />
|
||||
</g>
|
||||
<g
|
||||
style="fill:none;fill-opacity:1;stroke:url(#linearGradient5341);stroke-width:1.24928653000000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;opacity:0.54819277"
|
||||
inkscape:r_cy="true"
|
||||
inkscape:r_cx="true"
|
||||
transform="matrix(-0.612811,-0.5154406,-0.5177506,0.6100769,58.675633,13.911365)"
|
||||
id="g3185">
|
||||
<path
|
||||
sodipodi:type="inkscape:offset"
|
||||
inkscape:radius="-1.197237"
|
||||
inkscape:original="M 22.125 3.15625 L 7.625 20.5 L 22.71875 33.21875 C 22.718749 33.21875 22.46875 23.34375 22.46875 23.34375 C 41.298509 24.342727 54.468144 35.661007 45.5625 50.25 C 62.614067 34.952315 46.852277 15.923275 22.46875 12.5 L 22.125 3.15625 z "
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient5341);stroke-width:1.24928653000000001;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
|
||||
id="path3189"
|
||||
d="M 21.0625,6.3125 L 9.3125,20.34375 L 21.46875,30.59375 C 21.39688,27.754893 21.28125,23.375 21.28125,23.375 C 21.27502,23.044409 21.405774,22.725958 21.642519,22.495132 C 21.879264,22.264306 22.200923,22.141654 22.53125,22.15625 C 32.170255,22.667629 40.441027,25.773015 45.28125,30.875 C 48.676469,34.453835 50.102049,39.131532 49.125,44.21875 C 50.368339,42.205641 51.107893,40.194594 51.375,38.21875 C 51.870422,34.55401 50.856988,30.946652 48.5625,27.59375 C 43.973525,20.887947 34.236978,15.361613 22.3125,13.6875 C 21.732114,13.606381 21.295727,13.117098 21.28125,12.53125 L 21.0625,6.3125 z "
|
||||
transform="translate(1.0080026e-6,8.5223784e-7)" />
|
||||
</g>
|
||||
<g
|
||||
id="g2424"
|
||||
transform="matrix(0.190868,0.16126,0.16126,-0.190868,-0.719083,15.30613)"
|
||||
inkscape:r_cx="true"
|
||||
inkscape:r_cy="true"
|
||||
style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:r_cy="true"
|
||||
inkscape:r_cx="true"
|
||||
id="path8160"
|
||||
d="M 27.340608,36.228853 C 27.340608,36.228853 35.186117,38.0562 33.451082,24.975702 L 42.71624,24.975702 C 42.71624,24.975702 41.810572,38.462223 27.340608,36.228853 z "
|
||||
style="color:#000000;fill:url(#linearGradient8170);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient8172);stroke-width:1.04300582000000008;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible;opacity:0.51807229" />
|
||||
<g
|
||||
style="fill:url(#linearGradient8174);fill-opacity:1;stroke:#204a87;stroke-width:1.24932528;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
inkscape:r_cy="true"
|
||||
inkscape:r_cx="true"
|
||||
transform="matrix(0.6101332,0.5154999,0.5154881,-0.6101471,-10.618024,32.088556)"
|
||||
id="g8162">
|
||||
<path
|
||||
inkscape:r_cy="true"
|
||||
inkscape:r_cx="true"
|
||||
style="opacity:1;color:#000000;fill:url(#linearGradient8180);fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:1.25256376;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible;enable-background:accumulate"
|
||||
d="M 45.862102,50.273522 C 62.924432,34.96305 47.150241,15.929711 22.760624,12.513943 L 22.113577,3.1522141 L 7.6135337,20.510135 L 22.703188,33.23244 C 22.703188,33.23244 22.454828,23.347105 22.454828,23.347105 C 41.289895,24.339584 54.775794,35.675041 45.862102,50.273522 z "
|
||||
id="path8164"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
</g>
|
||||
<g
|
||||
id="g8166"
|
||||
transform="matrix(0.6128107,0.5154406,0.5177504,-0.6100769,-10.856505,32.088635)"
|
||||
inkscape:r_cx="true"
|
||||
inkscape:r_cy="true"
|
||||
style="fill:none;fill-opacity:1;stroke:#204a87;stroke-width:1.24928653;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
|
||||
<path
|
||||
transform="matrix(0.9972307,-2.4605589e-3,-2.4605593e-3,0.9980642,0.2457029,0.2077351)"
|
||||
d="M 21.0625,6.3125 L 9.3125,20.34375 L 21.46875,30.59375 C 21.39688,27.754893 21.28125,23.375 21.28125,23.375 C 21.27502,23.044409 21.405774,22.725958 21.642519,22.495132 C 21.879264,22.264306 22.200923,22.141654 22.53125,22.15625 C 32.170255,22.667629 40.441027,25.773015 45.28125,30.875 C 48.676469,34.453835 50.102049,39.131532 49.125,44.21875 C 50.368339,42.205641 51.107893,40.194594 51.375,38.21875 C 51.870422,34.55401 50.856988,30.946652 48.5625,27.59375 C 43.973525,20.887947 34.236978,15.361613 22.3125,13.6875 C 21.732114,13.606381 21.295727,13.117098 21.28125,12.53125 L 21.0625,6.3125 z "
|
||||
id="path8168"
|
||||
style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient8178);stroke-width:1.24973191;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.70588235;visibility:visible;display:block;overflow:visible"
|
||||
inkscape:original="M 22.125 3.15625 L 7.625 20.5 L 22.71875 33.21875 C 22.718749 33.21875 22.46875 23.34375 22.46875 23.34375 C 41.298509 24.342727 54.468144 35.661007 45.5625 50.25 C 62.614067 34.952315 46.852277 15.923275 22.46875 12.5 L 22.125 3.15625 z "
|
||||
inkscape:radius="-1.197237"
|
||||
sodipodi:type="inkscape:offset" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 17 KiB |
BIN
icons/tab_addresses.png
Normal file
After Width: | Height: | Size: 886 B |